diff --git a/core/modules/filter/src/Plugin/migrate/process/FilterID.php b/core/modules/filter/src/Plugin/migrate/process/FilterID.php index 14f88408a1c462abc67723e9c38cdea92caca8b6..27973eae16050cf7d0a60e92cf9915e8f90ed0ae 100644 --- a/core/modules/filter/src/Plugin/migrate/process/FilterID.php +++ b/core/modules/filter/src/Plugin/migrate/process/FilterID.php @@ -7,7 +7,6 @@ use Drupal\Core\StringTranslation\TranslationInterface; use Drupal\filter\Plugin\FilterInterface; use Drupal\migrate\MigrateExecutableInterface; -use Drupal\migrate\MigrateSkipProcessException; use Drupal\migrate\Plugin\migrate\process\StaticMap; use Drupal\migrate\Plugin\MigrationInterface; use Drupal\migrate\Row; @@ -86,7 +85,8 @@ public function transform($value, MigrateExecutableInterface $migrate_executable if (in_array(static::getSourceFilterType($value), [FilterInterface::TYPE_TRANSFORM_REVERSIBLE, FilterInterface::TYPE_TRANSFORM_IRREVERSIBLE], TRUE)) { $message = sprintf('Filter %s could not be mapped to an existing filter plugin; omitted since it is a transformation-only filter. Install and configure a successor after the migration.', $plugin_id); $migrate_executable->saveMessage($message, MigrationInterface::MESSAGE_INFORMATIONAL); - throw new MigrateSkipProcessException("The transformation-only filter $plugin_id was skipped."); + $this->stopPipeline(); + return NULL; } $fallback = $this->filterManager->getFallbackPluginId($plugin_id); diff --git a/core/modules/filter/tests/src/Kernel/Plugin/migrate/process/FilterIdTest.php b/core/modules/filter/tests/src/Kernel/Plugin/migrate/process/FilterIdTest.php index 04dfe6818fa931ad1fd04724ec58e38a96a5d698..9435f71c438b7d91c03698e40b52498228158477 100644 --- a/core/modules/filter/tests/src/Kernel/Plugin/migrate/process/FilterIdTest.php +++ b/core/modules/filter/tests/src/Kernel/Plugin/migrate/process/FilterIdTest.php @@ -5,7 +5,6 @@ use Drupal\filter\Plugin\migrate\process\FilterID; use Drupal\KernelTests\KernelTestBase; use Drupal\migrate\MigrateExecutableInterface; -use Drupal\migrate\MigrateSkipProcessException; use Drupal\migrate\Plugin\MigrationInterface; use Drupal\migrate\Row; @@ -47,7 +46,7 @@ protected function setUp(): void { * @param string $invalid_id * (optional) The invalid plugin ID which is expected to be logged by the * MigrateExecutable object. - * @param bool $skip_exception + * @param bool $stop_pipeline * (optional) Set to TRUE if we expect the filter to be skipped because it * is a transformation-only filter. * @@ -55,7 +54,7 @@ protected function setUp(): void { * * @covers ::transform */ - public function testTransform($value, $expected_value, $invalid_id = NULL, $skip_exception = FALSE) { + public function testTransform($value, $expected_value, $invalid_id = NULL, $stop_pipeline = FALSE) { $configuration = [ 'bypass' => TRUE, 'map' => [ @@ -65,7 +64,7 @@ public function testTransform($value, $expected_value, $invalid_id = NULL, $skip ]; $plugin = FilterID::create($this->container, $configuration, 'filter_id', []); - if ($skip_exception) { + if ($stop_pipeline) { $this->executable ->expects($this->exactly(1)) ->method('saveMessage') @@ -73,8 +72,6 @@ public function testTransform($value, $expected_value, $invalid_id = NULL, $skip sprintf('Filter %s could not be mapped to an existing filter plugin; omitted since it is a transformation-only filter. Install and configure a successor after the migration.', $value), MigrationInterface::MESSAGE_INFORMATIONAL ); - $this->expectException(MigrateSkipProcessException::class); - $this->expectExceptionMessage(sprintf("The transformation-only filter %s was skipped.", $value)); } if (isset($invalid_id)) { @@ -91,6 +88,7 @@ public function testTransform($value, $expected_value, $invalid_id = NULL, $skip $output_value = $plugin->transform($value, $this->executable, $row, 'foo'); $this->assertSame($expected_value, $output_value); + $this->assertSame($stop_pipeline, $plugin->isPipelineStopped()); } /** @@ -128,7 +126,7 @@ public static function provideFilters() { ], 'transformation-only D7 contrib filter' => [ 'editor_align', - '', + NULL, NULL, TRUE, ], diff --git a/core/modules/migrate/src/Plugin/migrate/process/MigrationLookup.php b/core/modules/migrate/src/Plugin/migrate/process/MigrationLookup.php index 8e7ca733a9c2f2e5879ae6ec6fe916a8032857c8..367ed28153fde9d0df1fdd838ccc89834ed05717 100644 --- a/core/modules/migrate/src/Plugin/migrate/process/MigrationLookup.php +++ b/core/modules/migrate/src/Plugin/migrate/process/MigrationLookup.php @@ -6,7 +6,6 @@ use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\migrate\MigrateException; use Drupal\migrate\MigrateLookupInterface; -use Drupal\migrate\MigrateSkipProcessException; use Drupal\migrate\MigrateSkipRowException; use Drupal\migrate\MigrateStubInterface; use Drupal\migrate\ProcessPluginBase; @@ -114,9 +113,11 @@ * @endcode * * If the source value passed in to the plugin is NULL, boolean FALSE, an empty - * array or an empty string, the plugin will throw a - * MigrateSkipProcessException, causing further plugins in the process to be - * skipped. + * array or an empty string, the plugin will return NULL and stop further + * processing on the pipeline. This is done for backwards compatibility reasons, + * and future versions of this plugin should simply return NULL and allow + * processing to continue. + * @see https://www.drupal.org/project/drupal/issues/3246666 * * @see \Drupal\migrate\Plugin\MigrateProcessInterface * @@ -187,7 +188,6 @@ public static function create(ContainerInterface $container, array $configuratio /** * {@inheritdoc} * - * @throws \Drupal\migrate\MigrateSkipProcessException * @throws \Drupal\migrate\MigrateException */ public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { @@ -205,6 +205,9 @@ public function transform($value, MigrateExecutableInterface $migrate_executable } $lookup_value = (array) $lookup_value; $this->skipInvalid($lookup_value); + if ($this->isPipelineStopped()) { + return NULL; + } $source_id_values[$lookup_migration_id] = $lookup_value; // Re-throw any PluginException as a MigrateException so the executable @@ -281,12 +284,10 @@ public function transform($value, MigrateExecutableInterface $migrate_executable * * @param array $value * The incoming value to check. - * - * @throws \Drupal\migrate\MigrateSkipProcessException */ protected function skipInvalid(array $value) { if (!array_filter($value, [$this, 'isValid'])) { - throw new MigrateSkipProcessException(); + $this->stopPipeline(); } } diff --git a/core/modules/migrate/src/Plugin/migrate/process/SkipOnEmpty.php b/core/modules/migrate/src/Plugin/migrate/process/SkipOnEmpty.php index 4d0a7625c8af67edb5169a9bc215854459e4fd2b..cc258bc6da0d55f4ef8b67040a49ddca41a08a77 100644 --- a/core/modules/migrate/src/Plugin/migrate/process/SkipOnEmpty.php +++ b/core/modules/migrate/src/Plugin/migrate/process/SkipOnEmpty.php @@ -123,10 +123,6 @@ public function row($value, MigrateExecutableInterface $migrate_executable, Row * * @return mixed * The input value, $value, if it is not empty. - * - * @throws \Drupal\migrate\MigrateSkipProcessException - * Thrown if the source property is not set and rest of the process should - * be skipped. */ public function process($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { if (!$value) { diff --git a/core/modules/migrate/src/Plugin/migrate/process/SubProcess.php b/core/modules/migrate/src/Plugin/migrate/process/SubProcess.php index 29115b66e306bf1aa5842e82cf38b9a725cb3354..1f7d6b8a94ffe382dd8a9043d7c0d316ed410a03 100644 --- a/core/modules/migrate/src/Plugin/migrate/process/SubProcess.php +++ b/core/modules/migrate/src/Plugin/migrate/process/SubProcess.php @@ -220,9 +220,8 @@ public function transform($value, MigrateExecutableInterface $migrate_executable $key = $this->transformKey($key, $migrate_executable, $new_row); } // Do not save the result if the key is NULL. The configured process - // pipeline used in transformKey() will return NULL if a - // MigrateSkipProcessException is thrown. - // @see \Drupal\filter\Plugin\migrate\process\FilterID + // pipeline used in transformKey() will return NULL if the key can not + // be transformed. if ($key !== NULL) { $return[$key] = $destination; } diff --git a/core/modules/migrate/tests/src/Unit/process/MigrationLookupTest.php b/core/modules/migrate/tests/src/Unit/process/MigrationLookupTest.php index 5699e30723d69783b0f00ab214b5f0b58a9aa83e..d054deb50d08fddac73aa2831f9e47d4be6b1e29 100644 --- a/core/modules/migrate/tests/src/Unit/process/MigrationLookupTest.php +++ b/core/modules/migrate/tests/src/Unit/process/MigrationLookupTest.php @@ -5,7 +5,6 @@ namespace Drupal\Tests\migrate\Unit\process; use Drupal\migrate\MigrateException; -use Drupal\migrate\MigrateSkipProcessException; use Drupal\migrate\Plugin\MigrationInterface; use Drupal\migrate\Plugin\migrate\process\MigrationLookup; use Drupal\migrate\Plugin\MigrateIdMapInterface; @@ -90,8 +89,9 @@ public function testSkipInvalid($value) { $migration_plugin_manager->createInstances(['foo']) ->willReturn(['foo' => $migration_plugin->reveal()]); $migration = MigrationLookup::create($this->prepareContainer(), $configuration, '', [], $migration_plugin->reveal()); - $this->expectException(MigrateSkipProcessException::class); - $migration->transform($value, $this->migrateExecutable, $this->row, 'foo'); + $result = $migration->transform($value, $this->migrateExecutable, $this->row, 'foo'); + $this->assertTrue($migration->isPipelineStopped()); + $this->assertNull($result); } /** @@ -164,9 +164,10 @@ public static function noSkipValidDataProvider() { * @param string|array $expected_value * The expected value(s) of the migration process plugin. * - * @dataProvider successfulLookupDataProvider + * @throws \Drupal\Component\Plugin\Exception\PluginException + * @throws \Drupal\migrate\MigrateException * - * @throws \Drupal\migrate\MigrateSkipProcessException + * @dataProvider successfulLookupDataProvider */ public function testSuccessfulLookup(array $source_id_values, array $destination_id_values, $source_value, $expected_value) { $migration_plugin = $this->prophesize(MigrationInterface::class);