From 828b769e4e3fa9326f9c0a3d786e8ce159d2d28b Mon Sep 17 00:00:00 2001 From: webchick <drupal@webchick.net> Date: Mon, 2 Nov 2015 10:03:04 -0800 Subject: [PATCH] Issue #2324649 by phenaproxima, svendecabooter, benjy, Berdir: Migrate text fields correctly based on their text_processing setting --- .../field/migration_templates/d6_field.yml | 11 +-- .../migrate/process/d6/FieldIdGenerator.php | 30 -------- .../Plugin/migrate/process/d6/FieldType.php | 76 +++++++++++++++++++ .../Migrate/d6/MigrateFieldInstanceTest.php | 5 +- .../src/Tests/Migrate/d6/MigrateFieldTest.php | 6 +- .../src/Plugin/migrate/cckfield/FileField.php | 12 ++- .../src/Plugin/migrate/cckfield/LinkField.php | 4 +- .../migrate_drupal.services.yml | 7 +- .../src/Annotation/MigrateCckField.php | 40 ++++++++++ .../src/Plugin/MigrateCckFieldInterface.php | 12 +++ .../migrate/cckfield/CckFieldPluginBase.php | 15 ++++ .../cckfield/TaxonomyTermReference.php | 4 +- .../src/Plugin/migrate/cckfield/TextField.php | 34 ++++++++- .../tests/src/Unit/Migrate/TextFieldTest.php | 46 +++++++++++ 14 files changed, 255 insertions(+), 47 deletions(-) delete mode 100644 core/modules/field/src/Plugin/migrate/process/d6/FieldIdGenerator.php create mode 100644 core/modules/field/src/Plugin/migrate/process/d6/FieldType.php create mode 100644 core/modules/migrate_drupal/src/Annotation/MigrateCckField.php diff --git a/core/modules/field/migration_templates/d6_field.yml b/core/modules/field/migration_templates/d6_field.yml index dbe35055474c..ec29aadf0957 100644 --- a/core/modules/field/migration_templates/d6_field.yml +++ b/core/modules/field/migration_templates/d6_field.yml @@ -17,7 +17,7 @@ process: field_name: field_name type: - - plugin: static_map + plugin: field_type source: - type - widget_type @@ -37,12 +37,6 @@ process: optionwidgets_select: list_float optionwidgets_buttons: list_float optionwidgets_onoff: boolean - text: - optionwidgets_select: list_string - optionwidgets_buttons: list_string - optionwidgets_onoff: boolean - text_textfield: text - text_textarea: text_long email: email_textfield: email filefield: @@ -118,6 +112,9 @@ process: phone_textfield: telephone int_phone: phone_textfield: telephone + - + plugin: skip_on_empty + method: row cardinality: plugin: static_map bypass: true diff --git a/core/modules/field/src/Plugin/migrate/process/d6/FieldIdGenerator.php b/core/modules/field/src/Plugin/migrate/process/d6/FieldIdGenerator.php deleted file mode 100644 index 93eca113d860..000000000000 --- a/core/modules/field/src/Plugin/migrate/process/d6/FieldIdGenerator.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/** - * @file - * Contains \Drupal\field\Plugin\migrate\process\d6\FieldIdGenerator. - */ - -namespace Drupal\field\Plugin\migrate\process\d6; - -use Drupal\migrate\MigrateExecutableInterface; -use Drupal\migrate\ProcessPluginBase; -use Drupal\migrate\Row; - -/** - * Generate the file name for field config entities. - * - * @MigrateProcessPlugin( - * id = "field_id_generator" - * ) - */ -class FieldIdGenerator extends ProcessPluginBase { - - /** - * {@inheritdoc} - */ - public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { - return $value[0] . "." . $value[1]; - } - -} diff --git a/core/modules/field/src/Plugin/migrate/process/d6/FieldType.php b/core/modules/field/src/Plugin/migrate/process/d6/FieldType.php new file mode 100644 index 000000000000..2c36275baaf1 --- /dev/null +++ b/core/modules/field/src/Plugin/migrate/process/d6/FieldType.php @@ -0,0 +1,76 @@ +<?php + +/** + * @file + * Contains \Drupal\field\Plugin\migrate\process\d6\FieldType. + */ + +namespace Drupal\field\Plugin\migrate\process\d6; + +use Drupal\Component\Plugin\Exception\PluginNotFoundException; +use Drupal\Component\Plugin\PluginManagerInterface; +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\migrate\MigrateExecutableInterface; +use Drupal\migrate\Plugin\migrate\process\StaticMap; +use Drupal\migrate\Row; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * @MigrateProcessPlugin( + * id = "field_type" + * ) + */ +class FieldType extends StaticMap implements ContainerFactoryPluginInterface { + + /** + * The cckfield plugin manager. + * + * @var \Drupal\Component\Plugin\PluginManagerInterface + */ + protected $cckPluginManager; + + /** + * Constructs a FieldType plugin. + * + * @param array $configuration + * The plugin configuration. + * @param string $plugin_id + * The plugin ID. + * @param mixed $plugin_definition + * The plugin definition. + * @param \Drupal\Component\Plugin\PluginManagerInterface $cck_plugin_manager + * The cckfield plugin manager. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, PluginManagerInterface $cck_plugin_manager) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + $this->cckPluginManager = $cck_plugin_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('plugin.manager.migrate.cckfield') + ); + } + + /** + * {@inheritdoc} + */ + public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { + list ($field_type, $widget_type) = $value; + + try { + return $this->cckPluginManager->createInstance($field_type) + ->getFieldType($row); + } + catch (PluginNotFoundException $e) { + return parent::transform($value, $migrate_executable, $row, $destination_property); + } + } + +} diff --git a/core/modules/field/src/Tests/Migrate/d6/MigrateFieldInstanceTest.php b/core/modules/field/src/Tests/Migrate/d6/MigrateFieldInstanceTest.php index c3c0cb62c248..8f0e96bacc1e 100644 --- a/core/modules/field/src/Tests/Migrate/d6/MigrateFieldInstanceTest.php +++ b/core/modules/field/src/Tests/Migrate/d6/MigrateFieldInstanceTest.php @@ -27,10 +27,11 @@ public function testFieldInstanceMigration() { $entity = Node::create(['type' => 'story']); // Test a text field. + /** @var \Drupal\field\FieldConfigInterface $field */ $field = FieldConfig::load('node.story.field_test'); $this->assertIdentical('Text Field', $field->label()); - $expected = array('max_length' => 255); - $this->assertIdentical($expected, $field->getSettings()); + // field_test is a text_long field, which have no settings. + $this->assertIdentical([], $field->getSettings()); $this->assertIdentical('text for default value', $entity->field_test->value); // Test a number field. diff --git a/core/modules/field/src/Tests/Migrate/d6/MigrateFieldTest.php b/core/modules/field/src/Tests/Migrate/d6/MigrateFieldTest.php index 4eb9426c5de1..1eb5ad6599c2 100644 --- a/core/modules/field/src/Tests/Migrate/d6/MigrateFieldTest.php +++ b/core/modules/field/src/Tests/Migrate/d6/MigrateFieldTest.php @@ -33,9 +33,9 @@ public function testFields() { // Text field. /** @var \Drupal\field\Entity\FieldStorageConfig $field_storage */ $field_storage = FieldStorageConfig::load('node.field_test'); - $expected = array('max_length' => 255); - $this->assertIdentical("text", $field_storage->getType(), t('Field type is @fieldtype. It should be text.', array('@fieldtype' => $field_storage->getType()))); - $this->assertIdentical($expected, $field_storage->getSettings(), "Field type text settings are correct"); + $this->assertIdentical('text_long', $field_storage->getType()); + // text_long fields do not have settings. + $this->assertIdentical([], $field_storage->getSettings()); // Integer field. $field_storage = FieldStorageConfig::load('node.field_test_two'); diff --git a/core/modules/file/src/Plugin/migrate/cckfield/FileField.php b/core/modules/file/src/Plugin/migrate/cckfield/FileField.php index d275dcff5cd1..022f01e98ba3 100644 --- a/core/modules/file/src/Plugin/migrate/cckfield/FileField.php +++ b/core/modules/file/src/Plugin/migrate/cckfield/FileField.php @@ -8,10 +8,13 @@ namespace Drupal\file\Plugin\migrate\cckfield; use Drupal\migrate\Entity\MigrationInterface; +use Drupal\migrate\Row; use Drupal\migrate_drupal\Plugin\migrate\cckfield\CckFieldPluginBase; /** - * @PluginID("filefield") + * @MigrateCckField( + * id = "filefield" + * ) */ class FileField extends CckFieldPluginBase { @@ -49,4 +52,11 @@ public function processCckFieldValues(MigrationInterface $migration, $field_name $migration->mergeProcessOfProperty($field_name, $process); } + /** + * {@inheritdoc} + */ + public function getFieldType(Row $row) { + return $row->getSourceProperty('widget_type') == 'imagefield_widget' ? 'image' : 'file'; + } + } diff --git a/core/modules/link/src/Plugin/migrate/cckfield/LinkField.php b/core/modules/link/src/Plugin/migrate/cckfield/LinkField.php index 394dc43111d8..327cbdaadb00 100644 --- a/core/modules/link/src/Plugin/migrate/cckfield/LinkField.php +++ b/core/modules/link/src/Plugin/migrate/cckfield/LinkField.php @@ -11,7 +11,9 @@ use Drupal\migrate_drupal\Plugin\migrate\cckfield\CckFieldPluginBase; /** - * @PluginID("link") + * @MigrateCckField( + * id = "link" + * ) */ class LinkField extends CckFieldPluginBase { diff --git a/core/modules/migrate_drupal/migrate_drupal.services.yml b/core/modules/migrate_drupal/migrate_drupal.services.yml index 00730b4ce1ec..2807b5f4b74c 100644 --- a/core/modules/migrate_drupal/migrate_drupal.services.yml +++ b/core/modules/migrate_drupal/migrate_drupal.services.yml @@ -1,4 +1,9 @@ services: plugin.manager.migrate.cckfield: class: Drupal\migrate\Plugin\MigratePluginManager - arguments: [cckfield, '@container.namespaces', '@cache.discovery', '@module_handler'] + arguments: + - cckfield + - '@container.namespaces' + - '@cache.discovery' + - '@module_handler' + - '\Drupal\migrate_drupal\Annotation\MigrateCckField' diff --git a/core/modules/migrate_drupal/src/Annotation/MigrateCckField.php b/core/modules/migrate_drupal/src/Annotation/MigrateCckField.php new file mode 100644 index 000000000000..b7edf0ef33bb --- /dev/null +++ b/core/modules/migrate_drupal/src/Annotation/MigrateCckField.php @@ -0,0 +1,40 @@ +<?php + +/** + * @file + * Contains \Drupal\migrate_drupal\Annotation\MigrateCckField. + */ + +namespace Drupal\migrate_drupal\Annotation; + +use Drupal\Component\Annotation\Plugin; + +/** + * Defines a cckfield plugin annotation object. + * + * cckfield plugins are variously responsible for handling the migration of + * CCK fields from Drupal 6 to Drupal 8. They are allowed to alter CCK-related + * migrations when migrations are being generated, and can compute destination + * field types for individual fields during the actual migration process. + * + * Plugin Namespace: Plugin\migrate\cckfield + * + * @Annotation + */ +class MigrateCckField extends Plugin { + + /** + * The plugin ID. + * + * @var string + */ + public $id; + + /** + * Map of D6 and D7 field types to D8 field type plugin IDs. + * + * @var string[] + */ + public $type_map = []; + +} diff --git a/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldInterface.php b/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldInterface.php index 7f8bb5aec3d1..dbe499d9064a 100644 --- a/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldInterface.php +++ b/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldInterface.php @@ -9,6 +9,7 @@ use Drupal\Component\Plugin\PluginInspectionInterface; use Drupal\migrate\Entity\MigrationInterface; +use Drupal\migrate\Row; /** * Provides an interface for all CCK field type plugins. @@ -77,4 +78,15 @@ public function getFieldWidgetMap(); */ public function processCckFieldValues(MigrationInterface $migration, $field_name, $data); + /** + * Computes the destination type of a migrated field. + * + * @param \Drupal\migrate\Row $row + * The field being migrated. + * + * @return string + * The destination field type. + */ + public function getFieldType(Row $row); + } diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/cckfield/CckFieldPluginBase.php b/core/modules/migrate_drupal/src/Plugin/migrate/cckfield/CckFieldPluginBase.php index 783a36fb8bdf..38b96df20765 100644 --- a/core/modules/migrate_drupal/src/Plugin/migrate/cckfield/CckFieldPluginBase.php +++ b/core/modules/migrate_drupal/src/Plugin/migrate/cckfield/CckFieldPluginBase.php @@ -9,6 +9,7 @@ use Drupal\Core\Plugin\PluginBase; use Drupal\migrate\Entity\MigrationInterface; +use Drupal\migrate\Row; use Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface; /** @@ -70,4 +71,18 @@ public function processFieldFormatter(MigrationInterface $migration) { $migration->mergeProcessOfProperty('options/type', $process); } + /** + * {@inheritdoc} + */ + public function getFieldType(Row $row) { + $field_type = $row->getSourceProperty('type'); + + if (isset($this->pluginDefinition['type_map'][$field_type])) { + return $this->pluginDefinition['type_map'][$field_type]; + } + else { + return $field_type; + } + } + } diff --git a/core/modules/taxonomy/src/Plugin/migrate/cckfield/TaxonomyTermReference.php b/core/modules/taxonomy/src/Plugin/migrate/cckfield/TaxonomyTermReference.php index 2ce428e05c6e..d6de1eca0123 100644 --- a/core/modules/taxonomy/src/Plugin/migrate/cckfield/TaxonomyTermReference.php +++ b/core/modules/taxonomy/src/Plugin/migrate/cckfield/TaxonomyTermReference.php @@ -11,7 +11,9 @@ use Drupal\migrate_drupal\Plugin\migrate\cckfield\CckFieldPluginBase; /** - * @PluginID("taxonomy_term_reference") + * @MigrateCckField( + * id = "taxonomy_term_reference" + * ) */ class TaxonomyTermReference extends CckFieldPluginBase { diff --git a/core/modules/text/src/Plugin/migrate/cckfield/TextField.php b/core/modules/text/src/Plugin/migrate/cckfield/TextField.php index 71e811224d9c..a386b5ffe566 100644 --- a/core/modules/text/src/Plugin/migrate/cckfield/TextField.php +++ b/core/modules/text/src/Plugin/migrate/cckfield/TextField.php @@ -8,10 +8,13 @@ namespace Drupal\text\Plugin\migrate\cckfield; use Drupal\migrate\Entity\MigrationInterface; +use Drupal\migrate\Row; use Drupal\migrate_drupal\Plugin\migrate\cckfield\CckFieldPluginBase; /** - * @PluginID("text") + * @MigrateCckField( + * id = "text" + * ) */ class TextField extends CckFieldPluginBase { @@ -91,4 +94,33 @@ public function processCckFieldValues(MigrationInterface $migration, $field_name $migration->setProcessOfProperty($field_name, $process); } + /** + * {@inheritdoc} + */ + public function getFieldType(Row $row) { + $widget_type = $row->getSourceProperty('widget_type'); + + if ($widget_type == 'text_textfield') { + $settings = $row->getSourceProperty('global_settings'); + $field_type = $settings['text_processing'] ? 'text' : 'string'; + if (empty($settings['max_length']) || $settings['max_length'] > 255) { + $field_type .= '_long'; + } + return $field_type; + } + else { + switch ($widget_type) { + case 'optionwidgets_buttons': + case 'optionwidgets_select': + return 'list_string'; + case 'optionwidgets_onoff': + return 'boolean'; + case 'text_textarea': + return 'text_long'; + default: + break; + } + } + } + } diff --git a/core/modules/text/tests/src/Unit/Migrate/TextFieldTest.php b/core/modules/text/tests/src/Unit/Migrate/TextFieldTest.php index 89b8c2619da7..117919dada84 100644 --- a/core/modules/text/tests/src/Unit/Migrate/TextFieldTest.php +++ b/core/modules/text/tests/src/Unit/Migrate/TextFieldTest.php @@ -8,6 +8,7 @@ namespace Drupal\Tests\text\Unit\Migrate; use Drupal\migrate\Entity\MigrationInterface; +use Drupal\migrate\Row; use Drupal\Tests\UnitTestCase; use Drupal\text\Plugin\migrate\cckfield\TextField; use Prophecy\Argument; @@ -121,4 +122,49 @@ public function testProcessBooleanTextExplicitValues() { $this->assertSame($expected, $this->migration->getProcess()['process']); } + /** + * Data provider for testGetFieldType(). + */ + public function getFieldTypeProvider() { + return array( + array('string_long', 'text_textfield', array( + 'text_processing' => FALSE, + )), + array('string', 'text_textfield', array( + 'text_processing' => FALSE, + 'max_length' => 128, + )), + array('string_long', 'text_textfield', array( + 'text_processing' => FALSE, + 'max_length' => 4096, + )), + array('text_long', 'text_textfield', array( + 'text_processing' => TRUE, + )), + array('text', 'text_textfield', array( + 'text_processing' => TRUE, + 'max_length' => 128, + )), + array('text_long', 'text_textfield', array( + 'text_processing' => TRUE, + 'max_length' => 4096, + )), + array('list_string', 'optionwidgets_buttons'), + array('list_string', 'optionwidgets_select'), + array('boolean', 'optionwidgets_onoff'), + array('text_long', 'text_textarea'), + array(NULL, 'undefined'), + ); + } + + /** + * @covers ::getFieldType + * @dataProvider getFieldTypeProvider + */ + public function testGetFieldType($expected_type, $widget_type, array $settings = array()) { + $row = new Row(array('widget_type' => $widget_type), array('widget_type' => array())); + $row->setSourceProperty('global_settings', $settings); + $this->assertSame($expected_type, $this->plugin->getFieldType($row)); + } + } -- GitLab