diff --git a/core/modules/migrate/src/Plugin/migrate/process/SubProcess.php b/core/modules/migrate/src/Plugin/migrate/process/SubProcess.php index 7902465d35c..2017017f2d6 100644 --- a/core/modules/migrate/src/Plugin/migrate/process/SubProcess.php +++ b/core/modules/migrate/src/Plugin/migrate/process/SubProcess.php @@ -2,6 +2,7 @@ namespace Drupal\migrate\Plugin\migrate\process; +use Drupal\migrate\MigrateException; use Drupal\migrate\ProcessPluginBase; use Drupal\migrate\MigrateExecutableInterface; use Drupal\migrate\Row; @@ -203,6 +204,9 @@ class SubProcess extends ProcessPluginBase { if (is_array($value) || $value instanceof \Traversable) { foreach ($value as $key => $new_value) { + if (!is_array($new_value)) { + 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']); $destination = $new_row->getDestination(); diff --git a/core/modules/migrate/tests/src/Unit/process/SubProcessTest.php b/core/modules/migrate/tests/src/Unit/process/SubProcessTest.php index bb566edee5b..e398036dfab 100644 --- a/core/modules/migrate/tests/src/Unit/process/SubProcessTest.php +++ b/core/modules/migrate/tests/src/Unit/process/SubProcessTest.php @@ -2,12 +2,12 @@ namespace Drupal\Tests\migrate\Unit\process; +use Drupal\migrate\MigrateException; use Drupal\migrate\MigrateExecutable; use Drupal\migrate\MigrateMessageInterface; use Drupal\migrate\Plugin\migrate\process\Get; use Drupal\migrate\Plugin\migrate\process\SubProcess; use Drupal\migrate\Row; -use Drupal\Tests\migrate\Unit\MigrateTestCase; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; // cspell:ignore baaa @@ -17,7 +17,7 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; * * @group migrate */ -class SubProcessTest extends MigrateTestCase { +class SubProcessTest extends MigrateProcessTestCase { /** * The sub_process plugin being tested. @@ -193,4 +193,52 @@ class SubProcessTest extends MigrateTestCase { ]; } + /** + * Tests behavior when source children are not arrays. + * + * @dataProvider providerTestSourceNotArray + */ + public function testSourceNotArray($source_values, $type) { + $process = new SubProcess(['process' => ['foo' => 'source_foo']], 'sub_process', []); + $this->expectException(MigrateException::class); + $this->expectExceptionMessage("Input array should hold elements of type array, instead element was of type '$type'"); + $process->transform($source_values, $this->migrateExecutable, $this->row, 'destination_property'); + } + + /** + * Data provider for testSourceNotArray(). + */ + public function providerTestSourceNotArray() { + return [ + 'strings cannot be subprocess items' => [ + ['strings', 'cannot', 'be', 'children'], + 'string', + ], + 'xml elements cannot be subprocess items' => [ + [new \SimpleXMLElement("Content")], + 'object', + ], + 'integers cannot be subprocess items' => [ + [1, 2, 3, 4], + 'integer', + ], + 'booleans cannot be subprocess items' => [ + [TRUE, FALSE], + 'boolean', + ], + 'null cannot be subprocess items' => [ + [NULL], + 'NULL', + ], + 'iterator cannot be subprocess items' => [ + [new \ArrayIterator(['some', 'array'])], + 'object', + ], + 'all subprocess items must be arrays' => [ + [['array'], 'not array'], + 'string', + ], + ]; + } + }