diff --git a/core/modules/field/src/Plugin/migrate/process/FieldFormatterFallback.php b/core/modules/field/src/Plugin/migrate/process/FieldFormatterFallback.php index afd235dbeb..d6f38b0d45 100644 --- a/core/modules/field/src/Plugin/migrate/process/FieldFormatterFallback.php +++ b/core/modules/field/src/Plugin/migrate/process/FieldFormatterFallback.php @@ -13,10 +13,13 @@ use Symfony\Component\DependencyInjection\ContainerInterface; /** - * Transforms field formatter plugin id. + * Transforms field formatter plugin ID. * - * Transform a non-mapped field formatter plugin_id to the D8 default formatter - * when the D8 target plugin_id is not available. + * Transform a non-mapped field formatter plugin ID to the D8 default formatter + * when the destination plugin ID is not available. + * + * Saves a migrate message with MigrationInterface::MESSAGE_NOTICE severity on + * fallback. * * Available configuration keys: * - field_type: The name of the field type. @@ -51,12 +54,12 @@ class FieldFormatterFallback extends ProcessPluginBase implements ContainerFacto protected $formatterPluginManager; /** - * Constructs a FieldTypeDefaults plugin instance. + * Constructs a FieldFormatterFallback plugin instance. * * @param array $configuration * A configuration array containing information about the plugin instance. * @param string $plugin_id - * The plugin_id for the plugin instance. + * The plugin ID for the plugin instance. * @param mixed $plugin_definition * The plugin implementation definition. * @param \Drupal\migrate\Plugin\MigrationInterface $migration @@ -64,7 +67,7 @@ class FieldFormatterFallback extends ProcessPluginBase implements ContainerFacto * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager * The field type manager. * @param \Drupal\Core\Field\FormatterPluginManager $formatter_plugin_manager - * The formatter manager (no interface available). + * The formatter manager. */ public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, FieldTypePluginManagerInterface $field_type_manager, FormatterPluginManager $formatter_plugin_manager) { parent::__construct($configuration, $plugin_id, $plugin_definition); @@ -100,14 +103,14 @@ public function transform($value, MigrateExecutableInterface $migrate_executable throw new MigrateException('Field type is required for the default field formatter.'); } - // If the target field formatter plugin id is not available on the - // destination site, we will replace it with the default formatter. - // The 'hidden' value is special in Drupal 7, and not a formatter. + // If the required field formatter plugin ID is not available on the + // destination site, we map it to the default formatter of the given field + // type. The 'hidden' value is special in Drupal 7, and not a formatter. if ($value && $value !== 'hidden' && !$this->formatterPluginManager->hasDefinition($value) && $this->fieldTypeManager->hasDefinition($field_type)) { $field_type_definition = $this->fieldTypeManager->getDefinition($field_type); $fallback = $field_type_definition['default_formatter']; - $message = sprintf('The field formatter plugin id %s (used on field type %s) could not be mapped to an existing formatter plugin; defaulting to %s and dropping all formatter settings. Either redo the migration with the module installed that provides an equivalent formatter plugin, or modify the entity view display after the migration and manually choose the right field formatter.', $value, $field_type, $fallback); + $message = sprintf('The field formatter plugin ID %s (used on field type %s) could not be mapped to an existing formatter plugin; defaulting to %s and dropping all formatter settings. Either redo the migration with the module installed that provides an equivalent formatter plugin, or modify the entity view display after the migration and manually choose the right field formatter.', $value, $field_type, $fallback); $migrate_executable->saveMessage($message, MigrationInterface::MESSAGE_NOTICE); return $fallback; diff --git a/core/modules/field/src/Plugin/migrate/process/FieldWidgetFallback.php b/core/modules/field/src/Plugin/migrate/process/FieldWidgetFallback.php index 9557fdbdc2..bafaa1e4d2 100644 --- a/core/modules/field/src/Plugin/migrate/process/FieldWidgetFallback.php +++ b/core/modules/field/src/Plugin/migrate/process/FieldWidgetFallback.php @@ -13,10 +13,27 @@ use Symfony\Component\DependencyInjection\ContainerInterface; /** - * Transforms field widget plugin id. + * Transforms field widget plugin ID. * - * Transform field widget plugin_id to the D8 default if the D8 target is not - * available. + * Transform field widget plugin ID to the D8 default widget if the destination + * widget plugin id is unavailable. + * + * Saves a migrate message with MigrationInterface::MESSAGE_NOTICE severity on + * fallback. + * + * Available configuration keys: + * - field_type: The name of the field type. + * - source: The input value - must be a string (optional). + * - skip_message: Omit the default migration message when fallback was needed. + * Optional boolean, defaults to FALSE. + * + * @code + * process: + * destination_key: + * plugin: field_widget_fallback + * field_type: '@field_type' + * source: source_property + * @endcode * * @MigrateProcessPlugin( * id = "field_widget_fallback" @@ -39,12 +56,12 @@ class FieldWidgetFallback extends ProcessPluginBase implements ContainerFactoryP protected $widgetPluginManager; /** - * Constructs a FieldWidgetDefaults plugin instance. + * Constructs a FieldWidgetFallback plugin instance. * * @param array $configuration * A configuration array containing information about the plugin instance. * @param string $plugin_id - * The plugin_id for the plugin instance. + * The plugin ID for the plugin instance. * @param mixed $plugin_definition * The plugin implementation definition. * @param \Drupal\migrate\Plugin\MigrationInterface $migration @@ -52,7 +69,7 @@ class FieldWidgetFallback extends ProcessPluginBase implements ContainerFactoryP * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager * The field type manager. * @param \Drupal\Core\Field\WidgetPluginManager $widget_plugin_manager - * The field widget manager (no interface). + * The field widget manager. */ public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, FieldTypePluginManagerInterface $field_type_manager, WidgetPluginManager $widget_plugin_manager) { parent::__construct($configuration, $plugin_id, $plugin_definition); @@ -81,22 +98,20 @@ public static function create(ContainerInterface $container, array $configuratio */ public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { if (empty($this->configuration['field_type'])) { - throw new MigrateException('Field type is required for the default field formatter.'); + throw new MigrateException('Field type is required for the default field widget.'); } $field_type = $row->get($this->configuration['field_type']); if (empty($field_type)) { - throw new MigrateException('Field type is required for the default field formatter.'); + throw new MigrateException('Field type is required for the default field widget.'); } - // If the target field widget plugin id is not available on the - // destination site, we will replace it with the default widget. - // Default value settings will be ignored. + // If the required field widget plugin ID is not available on the + // destination, we replace it with the field's default widget. if (!empty($value) && $this->fieldTypeManager->hasDefinition($field_type) && !$this->widgetPluginManager->hasDefinition($value)) { $field_type_definition = $this->fieldTypeManager->getDefinition($field_type); $fallback = $field_type_definition['default_widget']; if (!isset($this->configuration['skip_message']) || empty($this->configuration['skip_message'])) { - xdebug_break(); $message = sprintf('The field widget plugin id %s (used on field type %s) could not be mapped to an existing widget plugin; defaulting to %s and dropping all widget settings. Either redo the migration with the module installed that provides an equivalent plugin, or modify the entity form display after the migration and manually choose the right field widget.', $value, $field_type, $fallback); $migrate_executable->saveMessage($message, MigrationInterface::MESSAGE_NOTICE); } diff --git a/core/modules/migrate/src/Plugin/migrate/process/NullIfNotEqual.php b/core/modules/migrate/src/Plugin/migrate/process/NullIfNotEqual.php index 2d6f52021e..21bd890428 100644 --- a/core/modules/migrate/src/Plugin/migrate/process/NullIfNotEqual.php +++ b/core/modules/migrate/src/Plugin/migrate/process/NullIfNotEqual.php @@ -10,7 +10,7 @@ /** * Transforms a value by variable comparison. * - * Changes a source value to null if the two given variable are not equal. + * Changes the source value to null if the two given variables are not equal. * * Available configuration keys: * - values_to_compare: array of the values to compare. @@ -39,10 +39,8 @@ public function transform($value, MigrateExecutableInterface $migrate_executable throw new MigrateException('values_to_compare is a required key for plugin null_if_not_equal.'); } list($pid_original_raw, $pid_final_raw) = $this->configuration['values_to_compare']; - $pid_original = $row->get($pid_original_raw); - $pid_final = $row->get($pid_final_raw); - if ($pid_original !== $pid_final) { - $value = NULL; + if ($row->get($pid_original_raw) !== $row->get($pid_final_raw)) { + return NULL; } return $value; diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/field/FieldPluginBase.php b/core/modules/migrate_drupal/src/Plugin/migrate/field/FieldPluginBase.php index 15555697fe..d65f79d4fb 100644 --- a/core/modules/migrate_drupal/src/Plugin/migrate/field/FieldPluginBase.php +++ b/core/modules/migrate_drupal/src/Plugin/migrate/field/FieldPluginBase.php @@ -85,35 +85,25 @@ public function alterFieldWidgetMigration(MigrationInterface $migration) { $process['map'][$source_widget] = $destination_widget; } - $process_plugins_to_merge = []; - // @todo This is only a 'cosmetic' fix for FieldDiscoveryTest. - try { - $process_plugins_all = $migration->getProcessPlugins(); - } - catch (\Exception $e) { - // FieldDiscoveryTest! - $process_plugins_all = []; - } + $process_plugins_all = $migration->getProcessPlugins(); + // Loop on every destination property... foreach ($process_plugins_all as $destination_key => $process_plugins) { + // ..and on their process plugins. foreach ($process_plugins as $process_plugin_key => $process_plugin) { - if ($process_plugin->getPluginId() === 'static_map' && !empty($process_plugin->configuration['field_widget_map_alter'])) { - // Get always precedes a static_map. - $process_plugins_to_merge[$destination_key][] = $process_plugin_key - 1; - } - } - } - - if (!empty($process_plugins_to_merge)) { - foreach ($process_plugins_to_merge as $destination_key => $process_plugin_keys) { - foreach ($process_plugin_keys as $process_plugin_key) { - $migration->mergeProcessOfProperty($destination_key, [$process_plugin_key => $process]); + if (empty($process_plugin->configuration['field_widget_map_alter']) || $process_plugin->getPluginId() !== 'static_map') { + continue; } + // If this is a static map tagged with 'field_widget_map_alter', we + // merge the previously discovererd widget mapping. + // We get normalized process plugins. If the source is set in this + // static_map plugin, we have an (implicit) preceding get plugin, and + // we have to lower the destination plugin key by 1. + $key = isset($process_plugin->configuration['source']) && is_numeric($process_plugin_key) ? + $process_plugin_key - 1 : $process_plugin_key; + $migration->mergeProcessOfProperty($destination_key, [$key => $process]); } } - else { - $migration->mergeProcessOfProperty('options/type', ['type' => $process]); - } } /** @@ -174,36 +164,22 @@ public function alterFieldFormatterMigration(MigrationInterface $migration) { $process['map'][$plugin_id][$source_format] = $destination_format; } - $process_plugins_to_merge = []; - // @todo This is only a 'cosmetic' fix for FieldDiscoveryTest. - try { - $process_plugins_all = $migration->getProcessPlugins(); - } - catch (\Exception $e) { - // FieldDiscoveryTest! - $process_plugins_all = []; - } + $process_plugins_all = $migration->getProcessPlugins(); + // Loop on every destination property... foreach ($process_plugins_all as $destination_key => $process_plugins) { + // ..and on their process plugins. foreach ($process_plugins as $process_plugin_key => $process_plugin) { - if ($process_plugin->getPluginId() === 'static_map' && !empty($process_plugin->configuration['field_formatter_map_alter'])) { - // Get always precedes a static_map. - $process_plugins_to_merge[$destination_key][] = $process_plugin_key - 1; - } - } - } - - if (!empty($process_plugins_to_merge)) { - foreach ($process_plugins_to_merge as $destination_key => $process_plugin_keys) { - foreach ($process_plugin_keys as $process_plugin_key) { - $migration->mergeProcessOfProperty($destination_key, [$process_plugin_key => $process]); + if (empty($process_plugin->configuration['field_formatter_map_alter']) || $process_plugin->getPluginId() !== 'static_map') { + continue; } + // If this is a static map tagged with 'field_formatter_map_alter', we + // merge the formatter mapping. + $key = isset($process_plugin->configuration['source']) ? + $process_plugin_key - 1 : $process_plugin_key; + $migration->mergeProcessOfProperty($destination_key, [$key => $process]); } } - // @todo This is only a 'cosmetic' fix for FieldDiscoveryTest. - else { - $migration->mergeProcessOfProperty('options/type', [0 => $process]); - } } /** diff --git a/core/modules/migrate_drupal/tests/src/Kernel/d7/FieldDiscoveryTest.php b/core/modules/migrate_drupal/tests/src/Kernel/d7/FieldDiscoveryTest.php index 092b5bf699..be80414c7e 100644 --- a/core/modules/migrate_drupal/tests/src/Kernel/d7/FieldDiscoveryTest.php +++ b/core/modules/migrate_drupal/tests/src/Kernel/d7/FieldDiscoveryTest.php @@ -165,8 +165,8 @@ public function testAddAllFieldProcesses() { * @covers ::addAllFieldProcesses * @dataProvider addAllFieldProcessesAltersData */ - public function testAddAllFieldProcessesAlters($field_plugin_method, $expected_process) { - $this->assertFieldProcess($this->fieldDiscovery, $this->migrationPluginManager, FieldDiscoveryInterface::DRUPAL_7, $field_plugin_method, $expected_process); + public function testAddAllFieldProcessesAlters($field_plugin_method, $expected_process, $initial_process) { + $this->assertFieldProcess($this->fieldDiscovery, $this->migrationPluginManager, FieldDiscoveryInterface::DRUPAL_7, $field_plugin_method, $expected_process, NULL, NULL, $initial_process); } /** @@ -193,12 +193,15 @@ public function addAllFieldProcessesAltersData() { ], ], ], + 'initial_process' => [], ], 'Field Formatter' => [ 'field_plugin_method' => 'alterFieldFormatterMigration', 'expected_process' => [ 'options/type' => [ 0 => [ + 'plugin' => 'static_map', + 'field_formatter_map_alter' => TRUE, 'map' => [ 'taxonomy_term_reference' => [ 'taxonomy_term_reference_link' => 'entity_reference_label', @@ -241,12 +244,23 @@ public function addAllFieldProcessesAltersData() { ], ], ], + 'initial_process' => [ + 'options/type' => [ + 0 => [ + 'plugin' => 'static_map', + 'field_formatter_map_alter' => TRUE, + 'map' => [], + ], + ], + ], ], 'Field Widget' => [ 'field_plugin_method' => 'alterFieldWidgetMigration', 'expected_process' => [ 'options/type' => [ - 'type' => [ + 0 => [ + 'plugin' => 'static_map', + 'field_widget_map_alter' => TRUE, 'map' => [ 'd7_text' => 'd7_text_default', 'number_default' => 'number_default_default', @@ -265,6 +279,15 @@ public function addAllFieldProcessesAltersData() { ], ], ], + 'initial_process' => [ + 'options/type' => [ + 0 => [ + 'plugin' => 'static_map', + 'field_widget_map_alter' => TRUE, + 'map' => [], + ], + ], + ], ], ]; } diff --git a/core/modules/migrate_drupal/tests/src/Traits/FieldDiscoveryTestTrait.php b/core/modules/migrate_drupal/tests/src/Traits/FieldDiscoveryTestTrait.php index 34a16ad85e..581009950f 100644 --- a/core/modules/migrate_drupal/tests/src/Traits/FieldDiscoveryTestTrait.php +++ b/core/modules/migrate_drupal/tests/src/Traits/FieldDiscoveryTestTrait.php @@ -28,12 +28,17 @@ trait FieldDiscoveryTestTrait { * (optional) The entity type id. * @param string $bundle * (optional) The bundle. + * @param array $initial_process + * (optional) The initial process. */ - public function assertFieldProcess(FieldDiscoveryInterface $field_discovery, MigrationPluginManagerInterface $migration_plugin_manager, $core, $field_plugin_method = NULL, array $expected_process = [], $entity_type_id = NULL, $bundle = NULL) { + public function assertFieldProcess(FieldDiscoveryInterface $field_discovery, MigrationPluginManagerInterface $migration_plugin_manager, $core, $field_plugin_method = NULL, array $expected_process = [], $entity_type_id = NULL, $bundle = NULL, $initial_process = []) { $definition = [ 'migration_tags' => ['Drupal ' . $core], 'field_plugin_method' => $field_plugin_method, ]; + if (!empty($initial_process)) { + $definition['process'] = $initial_process; + } $migration = $migration_plugin_manager->createStubMigration($definition); if ($bundle) { $field_discovery->addBundleFieldProcesses($migration, $entity_type_id, $bundle);