diff -u b/core/modules/field/config/schema/field.source.schema.yml b/core/modules/field/config/schema/field.source.schema.yml --- b/core/modules/field/config/schema/field.source.schema.yml +++ b/core/modules/field/config/schema/field.source.schema.yml @@ -63,0 +64,8 @@ + +migrate.source.d7_field_instance_per_view_mode: + type: migrate_source_sql + label: 'Drupal 7 field instance per view mode' + mapping: + constants: + type: migrate_entity_constant + label: 'Constants' diff -u b/core/modules/field/src/Tests/Migrate/d7/MigrateFieldInstanceTest.php b/core/modules/field/src/Tests/Migrate/d7/MigrateFieldInstanceTest.php --- b/core/modules/field/src/Tests/Migrate/d7/MigrateFieldInstanceTest.php +++ b/core/modules/field/src/Tests/Migrate/d7/MigrateFieldInstanceTest.php @@ -45,7 +45,6 @@ protected function setUp() { parent::setUp(); $this->installConfig(static::$modules); - $this->loadDumps(['FieldConfig.php', 'FieldConfigInstance.php']); $this->createType('page'); $this->createType('article'); $this->createType('blog'); diff -u b/core/modules/field/src/Tests/Migrate/d7/MigrateFieldInstanceWidgetSettingsTest.php b/core/modules/field/src/Tests/Migrate/d7/MigrateFieldInstanceWidgetSettingsTest.php --- b/core/modules/field/src/Tests/Migrate/d7/MigrateFieldInstanceWidgetSettingsTest.php +++ b/core/modules/field/src/Tests/Migrate/d7/MigrateFieldInstanceWidgetSettingsTest.php @@ -94,7 +94,6 @@ 'd7_field_instance' => [], ]; $this->prepareMigrations($id_mappings); - $this->loadDumps(['FieldConfig.php', 'FieldConfigInstance.php']); $this->executeMigration('d7_field_instance_widget_settings'); } diff -u b/core/modules/field/src/Tests/Migrate/d7/MigrateFieldTest.php b/core/modules/field/src/Tests/Migrate/d7/MigrateFieldTest.php --- b/core/modules/field/src/Tests/Migrate/d7/MigrateFieldTest.php +++ b/core/modules/field/src/Tests/Migrate/d7/MigrateFieldTest.php @@ -43,7 +43,6 @@ protected function setUp() { parent::setUp(); $this->installConfig(static::$modules); - $this->loadDumps(['FieldConfig.php', 'FieldConfigInstance.php']); $this->executeMigration('d7_field'); } diff -u b/core/modules/field/tests/src/Unit/Plugin/migrate/source/d7/FieldInstanceTest.php b/core/modules/field/tests/src/Unit/Plugin/migrate/source/d7/FieldInstanceTest.php --- b/core/modules/field/tests/src/Unit/Plugin/migrate/source/d7/FieldInstanceTest.php +++ b/core/modules/field/tests/src/Unit/Plugin/migrate/source/d7/FieldInstanceTest.php @@ -25,8 +25,6 @@ ), ); - // We need to set up the database contents; it's easier to do that below. - // These are sample result queries. protected $expectedResults = array( array( 'field_name' => 'body', diff -u b/core/modules/field/tests/src/Unit/Plugin/migrate/source/d7/FieldTest.php b/core/modules/field/tests/src/Unit/Plugin/migrate/source/d7/FieldTest.php --- b/core/modules/field/tests/src/Unit/Plugin/migrate/source/d7/FieldTest.php +++ b/core/modules/field/tests/src/Unit/Plugin/migrate/source/d7/FieldTest.php @@ -25,8 +25,6 @@ ), ); - // We need to set up the database contents; it's easier to do that below. - // These are sample result queries. protected $expectedResults = array( array( 'field_name' => 'field_file', only in patch2: unchanged: --- /dev/null +++ b/core/modules/field/migration_templates/d7_field_formatter_settings.yml @@ -0,0 +1,70 @@ +id: d7_field_formatter_settings +label: Drupal 7 field formatter configuration +migration_tags: + - Drupal 7 +source: + plugin: d7_field_instance_per_view_mode + constants: + third_party_settings: { } +process: + # We skip field types that don't exist because they weren't migrated by the + # field migration. + field_type_exists: + - + plugin: migration + migration: d7_field + source: + - field_name + - entity_type + - + plugin: extract + index: + - 0 + - + plugin: skip_on_empty + method: row + entity_type: entity_type + bundle: bundle + view_mode: + - + plugin: migration + migration: d7_view_mode + source: + - entity_type + - view_mode + - + plugin: extract + index: + - 1 + - + plugin: static_map + bypass: true + map: + full: default + field_name: field_name + "options/label": label + "options/weight": weight + # The formatter to use. + "options/type": + - + plugin: static_map + bypass: true + source: type + map: + date_default: datetime_default + email_default: email_mailto + hidden: ~ + link_default: link + phone: basic_string + taxonomy_term_reference_link: entity_reference_label + - + plugin: skip_on_empty + method: row + "options/settings": settings + "options/third_party_settings": 'constants/third_party_settings' +destination: + plugin: component_entity_display +migration_dependencies: + required: + - d7_field_instance + - d7_view_mode only in patch2: unchanged: --- /dev/null +++ b/core/modules/field/migration_templates/d7_view_mode.yml @@ -0,0 +1,27 @@ +id: d7_view_mode +label: Drupal 7 view modes +migration_tags: + - Drupal 7 +source: + plugin: d7_view_mode +process: + mode: + plugin: static_map + source: view_mode + bypass: true + map: + default: full + label: + plugin: static_map + source: view_mode + map: + search_index: "Search index" + search_result: "Search result" + rss: "RSS" + print: "Print" + teaser: "Teaser" + full: "Full" + default: "Full" + targetEntityType: entity_type +destination: + plugin: entity:entity_view_mode only in patch2: unchanged: --- /dev/null +++ b/core/modules/field/src/Plugin/migrate/source/d7/FieldInstancePerViewMode.php @@ -0,0 +1,91 @@ +prepareQuery()->execute(); + foreach ($result as $field_instance) { + $data = unserialize($field_instance['data']); + // We don't need to include the serialized data in the returned rows. + unset($field_instance['data']); + foreach ($data['display'] as $view_mode => $info) { + $rows[] = array_merge($field_instance, $info, array('view_mode' => $view_mode)); + } + } + return new \ArrayIterator($rows); + } + + /** + * {@inheritdoc} + */ + public function query() { + return $this->select('field_config_instance', 'fci') + ->fields('fci', array('entity_type', 'bundle', 'field_name', 'data')); + } + + /** + * {@inheritdoc} + */ + public function fields() { + return array( + 'entity_type' => $this->t('The entity type ID.'), + 'bundle' => $this->t('The bundle ID.'), + 'field_name' => $this->t('Machine name of the field.'), + 'view_mode' => $this->t('The original machine name of the view mode.'), + 'label' => $this->t('The display label of the field.'), + 'type' => $this->t('The formatter ID.'), + 'settings' => $this->t('Array of formatter-specific settings.'), + 'module' => $this->t('The module providing the formatter.'), + 'weight' => $this->t('Display weight of the field.'), + ); + } + + /** + * {@inheritdoc} + */ + public function getIds() { + return array( + 'entity_type' => array( + 'type' => 'string', + ), + 'bundle' => array( + 'type' => 'string', + ), + 'view_mode' => array( + 'type' => 'string', + ), + 'field_name' => array( + 'type' => 'string', + ), + ); + } + + /** + * {@inheritdoc} + */ + public function count() { + return $this->initializeIterator()->count(); + } + +} only in patch2: unchanged: --- /dev/null +++ b/core/modules/field/src/Plugin/migrate/source/d7/ViewMode.php @@ -0,0 +1,78 @@ +prepareQuery()->execute(); + foreach ($result as $field_instance) { + $data = unserialize($field_instance['data']); + foreach (array_keys($data['display']) as $view_mode) { + $key = $field_instance['entity_type'] . '.' . $view_mode; + $rows[$key] = [ + 'entity_type' => $field_instance['entity_type'], + 'view_mode' => $view_mode, + ]; + } + } + return new \ArrayIterator($rows); + } + + /** + * {@inheritdoc} + */ + public function fields() { + return [ + 'view_mode' => $this->t('The view mode ID.'), + 'entity_type' => $this->t('The entity type ID.'), + ]; + } + + /** + * {@inheritdoc} + */ + public function query() { + return $this->select('field_config_instance', 'fci') + ->fields('fci', ['entity_type', 'data']); + } + + /** + * {@inheritdoc} + */ + public function getIds() { + return [ + 'entity_type' => [ + 'type' => 'string', + ], + 'view_mode' => [ + 'type' => 'string', + ], + ]; + } + + /** + * {@inheritdoc} + */ + public function count() { + return $this->initializeIterator()->count(); + } + +} only in patch2: unchanged: --- /dev/null +++ b/core/modules/field/src/Tests/Migrate/d7/MigrateFieldFormatterSettingsTest.php @@ -0,0 +1,205 @@ +installEntitySchema('comment'); + CommentType::create([ + 'id' => 'comment_node_page', + 'label' => $this->randomMachineName(), + ])->save(); + CommentType::create([ + 'id' => 'comment_node_article', + 'label' => $this->randomMachineName(), + ])->save(); + CommentType::create([ + 'id' => 'comment_node_blog', + 'label' => $this->randomMachineName(), + ])->save(); + CommentType::create([ + 'id' => 'comment_node_book', + 'label' => $this->randomMachineName(), + ])->save(); + CommentType::create([ + 'id' => 'comment_node_forum', + 'label' => $this->randomMachineName(), + ])->save(); + CommentType::create([ + 'id' => 'comment_node_test_content_type', + 'label' => $this->randomMachineName(), + ])->save(); + + $this->installEntitySchema('node'); + NodeType::create([ + 'type' => 'page', + 'label' => $this->randomMachineName(), + ])->save(); + NodeType::create([ + 'type' => 'article', + 'label' => $this->randomMachineName(), + ])->save(); + NodeType::create([ + 'type' => 'blog', + 'label' => $this->randomMachineName(), + ])->save(); + NodeType::create([ + 'type' => 'book', + 'label' => $this->randomMachineName(), + ])->save(); + NodeType::create([ + 'type' => 'forum', + 'label' => $this->randomMachineName(), + ])->save(); + NodeType::create([ + 'type' => 'test_content_type', + 'label' => $this->randomMachineName(), + ])->save(); + + $this->executeMigration('d7_field'); + $this->executeMigration('d7_field_instance'); + $this->executeMigration('d7_view_mode'); + $this->executeMigration('d7_field_formatter_settings'); + } + + protected function assertEntity($id) { + $display = EntityViewDisplay::load($id); + $this->assertTrue($display instanceof EntityViewDisplayInterface); + } + + protected function assertComponent($display_id, $component_id, $type, $label, $weight) { + $component = EntityViewDisplay::load($display_id)->getComponent($component_id); + $this->assertTrue(is_array($component)); + $this->assertIdentical($type, $component['type']); + $this->assertIdentical($label, $component['label']); + $this->assertIdentical($weight, $component['weight']); + } + + /** + * Asserts that a particular component is NOT included in a display. + * + * @param string $display_id + * The display ID. + * @param string $component_id + * The component ID. + */ + protected function assertComponentNotExists($display_id, $component_id) { + $component = EntityViewDisplay::load($display_id)->getComponent($component_id); + $this->assertTrue(is_null($component)); + } + + /** + * Tests migration of D7 field formatter settings. + */ + public function testMigration() { + $this->assertEntity('comment.comment_node_article.default'); + $this->assertComponent('comment.comment_node_article.default', 'comment_body', 'text_default', 'hidden', 0); + + $this->assertEntity('comment.comment_node_blog.default'); + $this->assertComponent('comment.comment_node_blog.default', 'comment_body', 'text_default', 'hidden', 0); + + $this->assertEntity('comment.comment_node_book.default'); + $this->assertComponent('comment.comment_node_book.default', 'comment_body', 'text_default', 'hidden', 0); + + $this->assertEntity('comment.comment_node_forum.default'); + $this->assertComponent('comment.comment_node_forum.default', 'comment_body', 'text_default', 'hidden', 0); + + $this->assertEntity('comment.comment_node_page.default'); + $this->assertComponent('comment.comment_node_page.default', 'comment_body', 'text_default', 'hidden', 0); + + $this->assertEntity('comment.comment_node_test_content_type.default'); + $this->assertComponent('comment.comment_node_test_content_type.default', 'comment_body', 'text_default', 'hidden', 0); + $this->assertComponent('comment.comment_node_test_content_type.default', 'field_integer', 'number_integer', 'above', 1); + + $this->assertEntity('node.article.default'); + $this->assertComponent('node.article.default', 'body', 'text_default', 'hidden', 0); + $this->assertComponent('node.article.default', 'field_tags', 'entity_reference_label', 'above', 10); + $this->assertComponent('node.article.default', 'field_image', 'image', 'hidden', -1); + + $this->assertEntity('node.article.teaser'); + $this->assertComponent('node.article.teaser', 'body', 'text_summary_or_trimmed', 'hidden', 0); + $this->assertComponent('node.article.teaser', 'field_tags', 'entity_reference_label', 'above', 10); + $this->assertComponent('node.article.teaser', 'field_image', 'image', 'hidden', -1); + + $this->assertEntity('node.blog.default'); + $this->assertComponent('node.blog.default', 'body', 'text_default', 'hidden', 0); + + $this->assertEntity('node.blog.teaser'); + $this->assertComponent('node.blog.teaser', 'body', 'text_summary_or_trimmed', 'hidden', 0); + + $this->assertEntity('node.book.default'); + $this->assertComponent('node.book.default', 'body', 'text_default', 'hidden', 0); + + $this->assertEntity('node.book.teaser'); + $this->assertComponent('node.book.teaser', 'body', 'text_summary_or_trimmed', 'hidden', 0); + + $this->assertEntity('node.forum.default'); + $this->assertComponent('node.forum.default', 'body', 'text_default', 'hidden', 11); + $this->assertComponent('node.forum.default', 'taxonomy_forums', 'entity_reference_label', 'above', 10); + + $this->assertEntity('node.forum.teaser'); + $this->assertComponent('node.forum.teaser', 'body', 'text_summary_or_trimmed', 'hidden', 11); + $this->assertComponent('node.forum.teaser', 'taxonomy_forums', 'entity_reference_label', 'above', 10); + + $this->assertEntity('node.page.default'); + $this->assertComponent('node.page.default', 'body', 'text_default', 'hidden', 0); + + $this->assertEntity('node.page.teaser'); + $this->assertComponent('node.page.teaser', 'body', 'text_summary_or_trimmed', 'hidden', 0); + + $this->assertEntity('node.test_content_type.default'); + $this->assertComponent('node.test_content_type.default', 'field_boolean', 'list_default', 'above', 0); + $this->assertComponent('node.test_content_type.default', 'field_email', 'email_mailto', 'above', 1); + // Phone formatters are not mapped and should default to basic_string. + $this->assertComponent('node.test_content_type.default', 'field_phone', 'basic_string', 'above', 2); + $this->assertComponent('node.test_content_type.default', 'field_date', 'datetime_default', 'above', 3); + $this->assertComponent('node.test_content_type.default', 'field_date_with_end_time', 'datetime_default', 'above', 4); + $this->assertComponent('node.test_content_type.default', 'field_file', 'file_default', 'above', 5); + $this->assertComponent('node.test_content_type.default', 'field_float', 'number_decimal', 'above', 6); + $this->assertComponent('node.test_content_type.default', 'field_images', 'image', 'above', 7); + $this->assertComponent('node.test_content_type.default', 'field_integer', 'number_integer', 'above', 8); + $this->assertComponent('node.test_content_type.default', 'field_link', 'link', 'above', 9); + $this->assertComponent('node.test_content_type.default', 'field_text_list', 'list_default', 'above', 10); + $this->assertComponent('node.test_content_type.default', 'field_integer_list', 'list_default', 'above', 11); + $this->assertComponent('node.test_content_type.default', 'field_long_text', 'text_default', 'above', 12); + $this->assertComponentNotExists('node.test_content_type.default', 'field_term_reference'); + $this->assertComponentNotExists('node.test_content_type.default', 'field_text'); + + $this->assertEntity('user.user.default'); + $this->assertComponent('user.user.default', 'field_file', 'file_default', 'above', 0); + } + +} only in patch2: unchanged: --- /dev/null +++ b/core/modules/field/src/Tests/Migrate/d7/MigrateViewModeTest.php @@ -0,0 +1,63 @@ +installEntitySchema('comment'); + $this->installEntitySchema('node'); + $this->executeMigration('d7_view_mode'); + } + + /** + * Asserts various aspects of a view mode entity. + * + * @param string $id + * The entity ID. + * @param string $label + * The expected label of the view mode. + * @param string $entity_type + * The expected entity type ID which owns the view mode. + * @param bool $status + * The expected status of the view mode. + */ + protected function assertEntity($id, $label, $entity_type) { + /** @var \Drupal\Core\Entity\EntityViewModeInterface $view_mode */ + $view_mode = EntityViewMode::load($id); + $this->assertTrue($view_mode instanceof EntityViewModeInterface); + $this->assertIdentical($label, $view_mode->label()); + $this->assertIdentical($entity_type, $view_mode->getTargetType()); + } + + /** + * Tests migration of D7 view mode variables to D8 config entities. + */ + public function testMigration() { + $this->assertEntity('comment.full', 'Full', 'comment'); + $this->assertEntity('node.teaser', 'Teaser', 'node'); + $this->assertEntity('node.full', 'Full', 'node'); + $this->assertEntity('user.full', 'Full', 'user'); + } + +} only in patch2: unchanged: --- /dev/null +++ b/core/modules/field/tests/src/Unit/Plugin/migrate/source/d7/FieldInstancePerViewModeTest.php @@ -0,0 +1,73 @@ + 'test', + 'source' => array( + 'plugin' => 'd7_field_instance_per_view_mode', + ), + ); + + protected $expectedResults = array( + array( + 'entity_type' => 'node', + 'bundle' => 'page', + 'field_name' => 'body', + 'label' => 'hidden', + 'type' => 'text_default', + 'settings' => array(), + 'module' => 'text', + 'weight' => 0, + 'view_mode' => 'default', + ), + array( + 'entity_type' => 'node', + 'bundle' => 'page', + 'field_name' => 'body', + 'label' => 'hidden', + 'type' => 'text_summary_or_trimmed', + 'settings' => array( + 'trim_length' => 600, + ), + 'module' => 'text', + 'weight' => 0, + 'view_mode' => 'teaser', + ), + ); + + /** + * Prepopulate contents with results. + */ + protected function setUp() { + $this->databaseContents['field_config_instance'] = array( + array( + 'id' => '2', + 'field_id' => '2', + 'field_name' => 'body', + 'entity_type' => 'node', + 'bundle' => 'page', + 'data' => 'a:6:{s:5:"label";s:4:"Body";s:6:"widget";a:4:{s:4:"type";s:26:"text_textarea_with_summary";s:8:"settings";a:2:{s:4:"rows";i:20;s:12:"summary_rows";i:5;}s:6:"weight";i:-4;s:6:"module";s:4:"text";}s:8:"settings";a:3:{s:15:"display_summary";b:1;s:15:"text_processing";i:1;s:18:"user_register_form";b:0;}s:7:"display";a:2:{s:7:"default";a:5:{s:5:"label";s:6:"hidden";s:4:"type";s:12:"text_default";s:8:"settings";a:0:{}s:6:"module";s:4:"text";s:6:"weight";i:0;}s:6:"teaser";a:5:{s:5:"label";s:6:"hidden";s:4:"type";s:23:"text_summary_or_trimmed";s:8:"settings";a:1:{s:11:"trim_length";i:600;}s:6:"module";s:4:"text";s:6:"weight";i:0;}}s:8:"required";b:0;s:11:"description";s:0:"";}', + 'deleted' => '0', + ), + ); + parent::setUp(); + } + +} only in patch2: unchanged: --- /dev/null +++ b/core/modules/field/tests/src/Unit/Plugin/migrate/source/d7/ViewModeTest.php @@ -0,0 +1,83 @@ + 'test', + 'source' => array( + 'plugin' => 'd7_view_mode', + ), + ); + + protected $expectedResults = array( + array( + 'entity_type' => 'node', + 'view_mode' => 'default', + ), + array( + 'entity_type' => 'node', + 'view_mode' => 'teaser', + ), + array( + 'entity_type' => 'user', + 'view_mode' => 'default', + ), + array( + 'entity_type' => 'comment', + 'view_mode' => 'default', + ), + ); + + /** + * Prepopulate contents with results. + */ + protected function setUp() { + $this->databaseContents['field_config_instance'] = array( + array( + 'id' => '13', + 'field_id' => '2', + 'field_name' => 'body', + 'entity_type' => 'node', + 'bundle' => 'forum', + 'data' => 'a:6:{s:5:"label";s:4:"Body";s:6:"widget";a:4:{s:4:"type";s:26:"text_textarea_with_summary";s:8:"settings";a:2:{s:4:"rows";i:20;s:12:"summary_rows";i:5;}s:6:"weight";i:1;s:6:"module";s:4:"text";}s:8:"settings";a:3:{s:15:"display_summary";b:1;s:15:"text_processing";i:1;s:18:"user_register_form";b:0;}s:7:"display";a:2:{s:7:"default";a:5:{s:5:"label";s:6:"hidden";s:4:"type";s:12:"text_default";s:8:"settings";a:0:{}s:6:"module";s:4:"text";s:6:"weight";i:11;}s:6:"teaser";a:5:{s:5:"label";s:6:"hidden";s:4:"type";s:23:"text_summary_or_trimmed";s:8:"settings";a:1:{s:11:"trim_length";i:600;}s:6:"module";s:4:"text";s:6:"weight";i:11;}}s:8:"required";b:0;s:11:"description";s:0:"";}', + 'deleted' => '0', + ), + array( + 'id' => '33', + 'field_id' => '11', + 'field_name' => 'field_file', + 'entity_type' => 'user', + 'bundle' => 'user', + 'data' => 'a:6:{s:5:"label";s:4:"File";s:6:"widget";a:5:{s:6:"weight";s:1:"8";s:4:"type";s:12:"file_generic";s:6:"module";s:4:"file";s:6:"active";i:1;s:8:"settings";a:1:{s:18:"progress_indicator";s:8:"throbber";}}s:8:"settings";a:5:{s:14:"file_directory";s:0:"";s:15:"file_extensions";s:3:"txt";s:12:"max_filesize";s:0:"";s:17:"description_field";i:0;s:18:"user_register_form";i:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:12:"file_default";s:8:"settings";a:0:{}s:6:"module";s:4:"file";s:6:"weight";i:0;}}s:8:"required";i:0;s:11:"description";s:0:"";}', + 'deleted' => '0', + ), + array( + 'id' => '12', + 'field_id' => '1', + 'field_name' => 'comment_body', + 'entity_type' => 'comment', + 'bundle' => 'comment_node_forum', + 'data' => 'a:6:{s:5:"label";s:7:"Comment";s:8:"settings";a:2:{s:15:"text_processing";i:1;s:18:"user_register_form";b:0;}s:8:"required";b:1;s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:6:"hidden";s:4:"type";s:12:"text_default";s:6:"weight";i:0;s:8:"settings";a:0:{}s:6:"module";s:4:"text";}}s:6:"widget";a:4:{s:4:"type";s:13:"text_textarea";s:8:"settings";a:1:{s:4:"rows";i:5;}s:6:"weight";i:0;s:6:"module";s:4:"text";}s:11:"description";s:0:"";}', + 'deleted' => '0', + ), + ); + parent::setUp(); + } + +} only in patch2: unchanged: --- a/core/modules/migrate_drupal/src/Plugin/migrate/builder/d6/CckBuilder.php +++ b/core/modules/migrate_drupal/src/Plugin/migrate/builder/d6/CckBuilder.php @@ -7,6 +7,7 @@ namespace Drupal\migrate_drupal\Plugin\migrate\builder\d6; +use Drupal\Core\Database\Connection; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\migrate\Plugin\migrate\builder\BuilderBase; use Drupal\migrate\Plugin\MigratePluginManager; only in patch2: unchanged: --- a/core/modules/node/migration_templates/d6_view_modes.yml +++ b/core/modules/node/migration_templates/d6_view_modes.yml @@ -7,7 +7,6 @@ source: constants: targetEntityType: node status: true - process: mode: plugin: static_map