diff --git a/classes/local/execution/engine.php b/classes/local/execution/engine.php index 6873c4de..ae845cbd 100644 --- a/classes/local/execution/engine.php +++ b/classes/local/execution/engine.php @@ -535,7 +535,14 @@ public function abort(?\Throwable $reason = null) { } $this->set_current_step(null); - $this->log('Engine: aborting steps', $message ? ['reason' => $message] : [], Logger::NOTICE); + $context = []; + if (!empty($reason->debuginfo)) { + $context = (array) json_decode($reason->debuginfo); + if (json_last_error() !== JSON_ERROR_NONE) { + $context = []; + } + } + $this->log('Engine: aborting steps', $message ? array_merge(['reason' => $message], $context) : [], Logger::NOTICE); $this->exception = $reason; foreach ($this->enginesteps as $enginestep) { $status = $enginestep->status; diff --git a/classes/local/step/reader_csv.php b/classes/local/step/reader_csv.php index bc643d40..c5f8e7aa 100644 --- a/classes/local/step/reader_csv.php +++ b/classes/local/step/reader_csv.php @@ -91,7 +91,18 @@ public function csv_contents_generator() { // Convert header string to an actual headers array. $headers = str_getcsv($strheaders, $delimiter); + $numheaders = count($headers); while (($data = fgetcsv($handle, $maxlinelength, $delimiter)) !== false) { + $numfields = count($data); + if ($numfields !== $numheaders) { + throw new \moodle_exception('reader_csv:header_field_count_mismatch', 'tool_dataflows', '', (object) [ + 'numfields' => $numfields, + 'numheaders' => $numheaders, + ], json_encode([ + 'fields' => $data, + 'headers' => $headers, + ])); + } $record = array_combine($headers, $data); yield (object) $record; } diff --git a/lang/en/tool_dataflows.php b/lang/en/tool_dataflows.php index a7aecb4e..97ec6645 100644 --- a/lang/en/tool_dataflows.php +++ b/lang/en/tool_dataflows.php @@ -370,6 +370,7 @@ $string['reader_csv:headers_help'] = 'If populated, then this will act as the header to map field to keys. If left blank, it will be populated automatically using the first read row.'; $string['reader_csv:overwriteheaders'] = 'Overwrite existing headers'; $string['reader_csv:overwriteheaders_help'] = 'If checked, the headers supplied above will be used instead of the ones in the file, effectively ignoring the first row.'; +$string['reader_csv:header_field_count_mismatch'] = 'Number of headers ({$a->numheaders}) should match number of fields ({$a->numfields})'; // Reader JSON. $string['reader_json:arrayexpression_help'] = 'Nested array to extract from JSON. For example, {$a->expression} will return the users array from the following JSON (If empty it is assumed the starting point of the JSON file is an array):{$a->jsonexample}'; diff --git a/version.php b/version.php index 975b927d..be472ff7 100644 --- a/version.php +++ b/version.php @@ -25,8 +25,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2023100200; -$plugin->release = 2023100200; +$plugin->version = 2023101600; +$plugin->release = 2023101600; $plugin->requires = 2017051500; // Our lowest supported Moodle (3.3.0). $plugin->supported = [35, 401]; // Available as of Moodle 3.9.0 or later. // TODO $plugin->incompatible = ; // Available as of Moodle 3.9.0 or later.