diff -u b/core/modules/filter/migration_templates/d6_filter_format.yml b/core/modules/filter/migration_templates/d6_filter_format.yml --- b/core/modules/filter/migration_templates/d6_filter_format.yml +++ b/core/modules/filter/migration_templates/d6_filter_format.yml @@ -16,12 +16,16 @@ key: '@id' process: id: - # Because the bypass flag is not set, the row will be skipped - # entirely if the filter ID cannot be determined. + # If the filter ID cannot be mapped, it will be passed through + # unchanged because the bypass flag is set. The filter_id plugin + # will flatten the input value and default it to filter_null (the + # fallback filter plugin ID) if the flattened input value is not + # a valid plugin ID. plugin: filter_id source: - module - delta + bypass: true map: filter: - filter_html diff -u b/core/modules/filter/src/Plugin/migrate/process/FilterID.php b/core/modules/filter/src/Plugin/migrate/process/FilterID.php --- b/core/modules/filter/src/Plugin/migrate/process/FilterID.php +++ b/core/modules/filter/src/Plugin/migrate/process/FilterID.php @@ -4,6 +4,7 @@ use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\StringTranslation\TranslationInterface; use Drupal\migrate\MigrateExecutableInterface; use Drupal\migrate\Plugin\migrate\process\StaticMap; use Drupal\migrate\Plugin\MigrationInterface; @@ -35,10 +36,13 @@ * The plugin definition. * @param \Drupal\Component\Plugin\PluginManagerInterface $filter_manager * The filter plugin manager. + * @param TranslationInterface $translator + * (optional) The string translation service. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, PluginManagerInterface $filter_manager) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, PluginManagerInterface $filter_manager, TranslationInterface $translator = NULL) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->filterManager = $filter_manager; + $this->stringTranslation = $translator; } /** @@ -49,7 +53,8 @@ $configuration, $plugin_id, $plugin_definition, - $container->get('plugin.manager.filter') + $container->get('plugin.manager.filter'), + $container->get('string_translation') ); } @@ -59,20 +64,24 @@ public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { $plugin_id = parent::transform($value, $migrate_executable, $row, $destination_property); + // If the static map is bypassed on failure, the returned plugin ID will be + // an array if $value was. Plugin IDs cannot be arrays, so flatten it before + // passing it into the filter manager. + if (is_array($plugin_id)) { + $plugin_id = implode(':', $plugin_id); + } + if ($this->filterManager->hasDefinition($plugin_id)) { return $plugin_id; } else { $fallback = $this->filterManager->getFallbackPluginId($plugin_id); - if (is_array($value)) { - $value = implode(', ', $value); - } - $message = $this->t('Filter @id could not be mapped to an existing filter plugin; defaulting to @fallback.', [ - '@id' => $value, + $message = $this->t('Filter @plugin_id could not be mapped to an existing filter plugin; defaulting to @fallback.', [ + '@plugin_id' => $plugin_id, '@fallback' => $fallback, ]); - $migrate_executable->saveMessage($message, MigrationInterface::MESSAGE_WARNING); + $migrate_executable->saveMessage((string) $message, MigrationInterface::MESSAGE_WARNING); return $fallback; } reverted: --- b/core/modules/filter/tests/src/Unit/Plugin/migrate/process/FilterIdTest.php +++ /dev/null @@ -1,146 +0,0 @@ -filterManager = $this->prophesize(FilterPluginManager::class); - $this->executable = $this->prophesize(MigrateExecutableInterface::class); - - $this->filterManager - ->hasDefinition('filter_html') - ->willReturn(TRUE); - - $this->filterManager - ->hasDefinition('php_code') - ->willReturn(FALSE); - - $this->filterManager - ->getFallbackPluginId(Argument::type('string')) - ->willReturn('filter_null'); - - // Mock the string translation service, since the plugin will translate - // any message it saves. - $translator = $this->prophesize(TranslationInterface::class); - - $translator - ->translate( - Argument::type('string') - ) - ->willReturnArgument(0); - - $translator - ->translate( - Argument::type('string'), - Argument::type('array') - ) - ->willReturnArgument(0); - - $container = new ContainerBuilder(); - $container->set('string_translation', $translator->reveal()); - - \Drupal::setContainer($container); - } - - /** - * Tests the filter_id plugin. - * - * @param mixed $value - * The input value to the plugin. - * @param string $expected_value - * The output value expected from the plugin. - * @param PredictionInterface $message_saved - * A prediction for if and how the MigrateExecutable's saveMessage() method - * will be called. - * - * @dataProvider testProvider - * - * @covers ::transform - */ - public function test($value, $expected_value, PredictionInterface $message_saved) { - $plugin = new FilterID( - [ - 'bypass' => TRUE, - 'map' => [ - 'foo' => 'filter_html', - 'baz' => 'php_code', - ], - ], - 'filter_id', - [], - $this->filterManager->reveal() - ); - - $this->executable - ->saveMessage( - Argument::any(), - Argument::type('integer') - ) - ->should($message_saved); - - $row = new Row([], []); - $output_value = $plugin->transform($value, $this->executable->reveal(), $row, 'foo'); - - $this->assertSame($expected_value, $output_value); - $this->executable->checkProphecyMethodsPredictions(); - } - - /** - * The test data provider. - * - * @return array - */ - public function testProvider() { - return [ - // The filter ID is mapped, and the plugin exists. - ['foo', 'filter_html', new NoCallsPrediction], - // The filter ID isn't mapped, but it's unchanged from the source (i.e., - // it bypasses the static map) and the plugin exists. - ['filter_html', 'filter_html', new NoCallsPrediction], - // The filter ID is mapped, but the plugin does not exist. - ['baz', 'filter_null', new CallPrediction], - // The filter ID isn't mapped, but it's unchanged from the source (i.e., - // it bypasses the static map) but the plugin does not exist. - ['php_code', 'filter_null', new CallPrediction], - ]; - } - -} only in patch2: unchanged: --- /dev/null +++ b/core/modules/filter/tests/src/Kernel/Plugin/migrate/process/FilterIdTest.php @@ -0,0 +1,119 @@ +executable = $this->getMock(MigrateExecutableInterface::class); + } + + /** + * Tests the filter_id plugin. + * + * @param mixed $value + * The input value to the plugin. + * @param string $expected_value + * The output value expected from the plugin. + * @param string $invalid_id + * (optional) The invalid plugin ID which is expected to be logged by the + * MigrateExecutable object. + * + * @dataProvider testProvider + * + * @covers ::transform + */ + public function test($value, $expected_value, $invalid_id = NULL) { + $configuration = [ + 'bypass' => TRUE, + 'map' => [ + 'foo' => 'filter_html', + 'baz' => 'php_code', + ], + ]; + $plugin = FilterID::create($this->container, $configuration, 'filter_id', []); + + if (isset($invalid_id)) { + $this->executable + ->expects($this->exactly(1)) + ->method('saveMessage') + ->with( + 'Filter ' . $invalid_id . ' could not be mapped to an existing filter plugin; defaulting to filter_null.', + MigrationInterface::MESSAGE_WARNING + ); + } + + $row = new Row([], []); + $output_value = $plugin->transform($value, $this->executable, $row, 'foo'); + + $this->assertSame($expected_value, $output_value); + } + + /** + * The test data provider. + * + * @return array + */ + public function testProvider() { + return [ + // The filter ID is mapped, and the plugin exists. + [ + 'foo', + 'filter_html', + ], + // The filter ID isn't mapped, but it's unchanged from the source (i.e., + // it bypasses the static map) and the plugin exists. + [ + 'filter_html', + 'filter_html', + ], + // The filter ID is mapped, but the plugin does not exist. + [ + 'baz', + 'filter_null', + 'php_code', + ], + // The filter ID isn't mapped, but it's unchanged from the source (i.e., + // it bypasses the static map) but the plugin does not exist. + [ + 'php_code', + 'filter_null', + 'php_code', + ], + [ + ['filter', 1], + 'filter_null', + 'filter:1', + ], + ]; + } + +}