From c0aaeb1c79510cbee15a3942c46a7494b4c401eb Mon Sep 17 00:00:00 2001 From: Jason den Dulk Date: Mon, 15 May 2023 15:53:34 +1000 Subject: [PATCH] Issue 722: Throw exception when cannot open input. --- classes/local/step/reader_csv.php | 40 +++++++++++++----------- tests/tool_dataflows_reader_csv_test.php | 29 +++++++++++++++++ 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/classes/local/step/reader_csv.php b/classes/local/step/reader_csv.php index a156015c..fcb85fca 100644 --- a/classes/local/step/reader_csv.php +++ b/classes/local/step/reader_csv.php @@ -64,28 +64,30 @@ public function csv_contents_generator() { $strheaders = $config->headers; $path = $this->enginestep->engine->resolve_path($config->path); - if (($handle = fopen($path, 'r')) !== false) { - try { - // Prepare and resolve headers. - if (empty($strheaders)) { - $strheaders = fgets($handle); - } + if (($handle = @fopen($path, 'r')) === false) { + throw new \moodle_exception('writer_stream:failed_to_open_stream', 'tool_dataflows', '', $path); + } + + try { + // Prepare and resolve headers. + if (empty($strheaders)) { + $strheaders = fgets($handle); + } - // At this point, if headers is false, then the file is empty, and - // so it should continue as if the file finished. - if ($strheaders === false) { - return; - } + // At this point, if headers is false, then the file is empty, and + // so it should continue as if the file finished. + if ($strheaders === false) { + return; + } - // Convert header string to an actual headers array. - $headers = str_getcsv($strheaders, $config->delimiter); - while (($data = fgetcsv($handle, $maxlinelength, $config->delimiter)) !== false) { - $record = array_combine($headers, $data); - yield (object) $record; - } - } finally { - fclose($handle); + // Convert header string to an actual headers array. + $headers = str_getcsv($strheaders, $config->delimiter); + while (($data = fgetcsv($handle, $maxlinelength, $config->delimiter)) !== false) { + $record = array_combine($headers, $data); + yield (object) $record; } + } finally { + fclose($handle); } } diff --git a/tests/tool_dataflows_reader_csv_test.php b/tests/tool_dataflows_reader_csv_test.php index cfd42574..30b7ef1c 100644 --- a/tests/tool_dataflows_reader_csv_test.php +++ b/tests/tool_dataflows_reader_csv_test.php @@ -36,6 +36,9 @@ */ class tool_dataflows_reader_csv_test extends \advanced_testcase { + /** @var string|null Input path for reader to read from. */ + protected $inputpath = null; + /** * Set up before each test */ @@ -43,6 +46,7 @@ protected function setUp(): void { parent::setUp(); $this->resetAfterTest(); + $this->inputpath = null; set_config('permitted_dirs', '/tmp', 'tool_dataflows'); } @@ -127,6 +131,31 @@ public function test_csv_with_custom_headers_configured() { $this->assertEquals($expected, $output); } + /** + * Tests for an invalid input stream. + */ + public function test_bad_input_stream() { + [$dataflow, $steps] = $this->create_dataflow(); + $path = 'path/to/nowhere'; + + $reader = $steps[$dataflow->steps->reader->id]; + $reader->config = Yaml::dump([ + 'path' => $path, + 'headers' => '', + 'delimiter' => ',', + ]); + + $this->expectException('\moodle_exception'); + + // Execute. + ob_start(); + $engine = new engine($dataflow); + $this->expectExceptionMessage(get_string('writer_stream:failed_to_open_stream', + 'tool_dataflows', $engine->resolve_path($path))); + $engine->execute(); + ob_get_clean(); + } + /** * Dataflow creation helper function *