From 4ec07d680e55459e8ae86b82a18bc68c10e930c3 Mon Sep 17 00:00:00 2001 From: Dave Long <dave@longwaveconsulting.com> Date: Sat, 17 Feb 2024 15:45:25 +0000 Subject: [PATCH] Issue #3365895 by danflanagan8, benjifisher, mikelutz: When sub_process encounters a row skip, it should skip its internal row, and not bubble up to the outer row --- .../src/Plugin/migrate/process/SubProcess.php | 8 +- .../Kernel/process/SubProcessWithSkipTest.php | 144 ++++++++++++++++++ 2 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 core/modules/migrate/tests/src/Kernel/process/SubProcessWithSkipTest.php diff --git a/core/modules/migrate/src/Plugin/migrate/process/SubProcess.php b/core/modules/migrate/src/Plugin/migrate/process/SubProcess.php index 2017017f2d61..29115b66e306 100644 --- a/core/modules/migrate/src/Plugin/migrate/process/SubProcess.php +++ b/core/modules/migrate/src/Plugin/migrate/process/SubProcess.php @@ -3,6 +3,7 @@ namespace Drupal\migrate\Plugin\migrate\process; use Drupal\migrate\MigrateException; +use Drupal\migrate\MigrateSkipRowException; use Drupal\migrate\ProcessPluginBase; use Drupal\migrate\MigrateExecutableInterface; use Drupal\migrate\Row; @@ -208,7 +209,12 @@ public function transform($value, MigrateExecutableInterface $migrate_executable throw new MigrateException(sprintf("Input array should hold elements of type array, instead element was of type '%s'", gettype($new_value))); } $new_row = new Row($new_value + $source); - $migrate_executable->processRow($new_row, $this->configuration['process']); + try { + $migrate_executable->processRow($new_row, $this->configuration['process']); + } + catch (MigrateSkipRowException $e) { + continue; + } $destination = $new_row->getDestination(); if (array_key_exists('key', $this->configuration)) { $key = $this->transformKey($key, $migrate_executable, $new_row); diff --git a/core/modules/migrate/tests/src/Kernel/process/SubProcessWithSkipTest.php b/core/modules/migrate/tests/src/Kernel/process/SubProcessWithSkipTest.php new file mode 100644 index 000000000000..ad89fceeebf3 --- /dev/null +++ b/core/modules/migrate/tests/src/Kernel/process/SubProcessWithSkipTest.php @@ -0,0 +1,144 @@ +<?php + +namespace Drupal\Tests\migrate\Kernel\process; + +use Drupal\KernelTests\KernelTestBase; +use Drupal\migrate\MigrateExecutable; +use Drupal\migrate\Plugin\MigrationInterface; + +/** + * Tests process pipelines when a sub_process skips a row or process. + * + * @group migrate + */ +class SubProcessWithSkipTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['migrate']; + + /** + * Provides the test migration definition. + * + * @return array + */ + public function getDefinition() { + return [ + 'source' => [ + 'plugin' => 'embedded_data', + 'data_rows' => [ + [ + 'id' => 'skip_test', + 'my_array_of_arrays' => [ + [ + 'key_1' => 'foo', + 'key_2' => 'bar', + ], + [ + 'key_1' => NULL, + 'key_2' => 'baz', + ], + ], + ], + ], + 'ids' => [ + 'id' => ['type' => 'string'], + ], + ], + 'process' => [ + 'first' => [ + 'plugin' => 'default_value', + 'default_value' => 'something outside of sub_process', + ], + 'second' => [ + 'plugin' => 'sub_process', + 'source' => 'my_array_of_arrays', + 'process' => [ + 'prop_1' => [ + [ + 'plugin' => 'skip_on_empty', + 'source' => 'key_1', + ], + // We put a process after skip_on_empty to better test skipping + // a process. + [ + 'plugin' => 'get', + 'source' => 'key_2', + ], + ], + 'prop_2' => 'key_2', + ], + ], + ], + 'destination' => [ + 'plugin' => 'config', + 'config_name' => 'migrate_test.settings', + ], + ]; + } + + /** + * Test use of skip_on_empty within sub_process. + * + * @dataProvider providerTestSubProcessSkip + * + * @param string $method + * The method to use with skip_on_empty (row or process). + * @param array $expected_data + * The expected result of the migration. + */ + public function testSubProcessSkip(string $method, array $expected_data): void { + $definition = $this->getDefinition(); + $definition['process']['second']['process']['prop_1'][0]['method'] = $method; + + $migration = \Drupal::service('plugin.manager.migration')->createStubMigration($definition); + + $executable = new MigrateExecutable($migration); + $result = $executable->import(); + + // Migration needs to succeed before further assertions are made. + $this->assertSame(MigrationInterface::RESULT_COMPLETED, $result); + + // Compare with expected data. + $this->assertEquals($expected_data, \Drupal::config('migrate_test.settings')->get()); + } + + /** + * Data provider for testNotFoundSubProcess(). + * + * @return array + */ + public function providerTestSubProcessSkip(): array { + return [ + 'skip row' => [ + 'method' => 'row', + 'expected' => [ + 'first' => 'something outside of sub_process', + 'second' => [ + [ + 'prop_1' => 'bar', + 'prop_2' => 'bar', + ], + ], + ], + ], + 'skip process' => [ + 'method' => 'process', + 'expected' => [ + 'first' => 'something outside of sub_process', + 'second' => [ + [ + 'prop_1' => 'bar', + 'prop_2' => 'bar', + ], + [ + 'prop_2' => 'baz', + ], + ], + ], + ], + ]; + } + +} -- GitLab