From 2a967c4a927c930a967064d96637be152fb99ed2 Mon Sep 17 00:00:00 2001 From: Nathaniel Catchpole Date: Fri, 9 Dec 2016 11:14:12 +0000 Subject: [PATCH] Issue #2826200 by claudiu.cristea, pfrenssen: Don't let the whole migration crash on a download failure --- .../src/Plugin/migrate/process/Download.php | 9 ++- .../process/DownloadFunctionalTest.php | 81 +++++++++++++++++++ 2 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 core/modules/migrate/tests/src/Functional/process/DownloadFunctionalTest.php diff --git a/core/modules/migrate/src/Plugin/migrate/process/Download.php b/core/modules/migrate/src/Plugin/migrate/process/Download.php index 08c9b57b19a..2014085e042 100644 --- a/core/modules/migrate/src/Plugin/migrate/process/Download.php +++ b/core/modules/migrate/src/Plugin/migrate/process/Download.php @@ -108,8 +108,13 @@ class Download extends ProcessPluginBase implements ContainerFactoryPluginInterf // Stream the request body directly to the final destination stream. $this->configuration['guzzle_options']['sink'] = $destination_stream; - // Make the request. Guzzle throws an exception for anything other than 200. - $this->httpClient->get($source, $this->configuration['guzzle_options']); + try { + // Make the request. Guzzle throws an exception for anything but 200. + $this->httpClient->get($source, $this->configuration['guzzle_options']); + } + catch (\Exception $e) { + throw new MigrateException("{$e->getMessage()} ($source)"); + } return $final_destination; } diff --git a/core/modules/migrate/tests/src/Functional/process/DownloadFunctionalTest.php b/core/modules/migrate/tests/src/Functional/process/DownloadFunctionalTest.php new file mode 100644 index 00000000000..2a73d702ee6 --- /dev/null +++ b/core/modules/migrate/tests/src/Functional/process/DownloadFunctionalTest.php @@ -0,0 +1,81 @@ +baseUrl}/not-existent-404"; + $valid_url = "{$this->baseUrl}/core/misc/favicon.ico"; + + $definition = [ + 'source' => [ + 'plugin' => 'embedded_data', + 'data_rows' => [ + ['url' => $invalid_url, 'uri' => 'public://first.txt'], + ['url' => $valid_url, 'uri' => 'public://second.ico'], + ], + 'ids' => [ + 'url' => ['type' => 'string'], + ], + ], + 'process' => [ + 'uri' => [ + 'plugin' => 'download', + 'source' => ['url', 'uri'], + ] + ], + 'destination' => [ + 'plugin' => 'entity:file', + ], + ]; + + $migration = \Drupal::service('plugin.manager.migration')->createStubMigration($definition); + + $executable = new MigrateExecutable($migration, new MigrateMessage()); + $result = $executable->import(); + + // Check that the migration has completed. + $this->assertEquals($result, MigrationInterface::RESULT_COMPLETED); + + /** @var \Drupal\migrate\Plugin\MigrateIdMapInterface $id_map_plugin */ + $id_map_plugin = $migration->getIdMap(); + + // Check that the first row was marked as failed in the id map table. + $map_row = $id_map_plugin->getRowBySource(['url' => $invalid_url]); + $this->assertEquals(MigrateIdMapInterface::STATUS_FAILED, $map_row['source_row_status']); + $this->assertNull($map_row['destid1']); + + // Check that a message with the thrown exception has been logged. + $messages = $id_map_plugin->getMessageIterator(['url' => $invalid_url])->fetchAll(); + $this->assertCount(1, $messages); + $message = reset($messages); + $this->assertEquals("Cannot read from non-readable stream ($invalid_url)", $message->message); + $this->assertEquals(MigrationInterface::MESSAGE_ERROR, $message->level); + + // Check that the second row was migrated successfully. + $map_row = $id_map_plugin->getRowBySource(['url' => $valid_url]); + $this->assertEquals(MigrateIdMapInterface::STATUS_IMPORTED, $map_row['source_row_status']); + $this->assertEquals(1, $map_row['destid1']); + } + +}