diff --git a/core/modules/field/migration_templates/d7_field.yml b/core/modules/field/migration_templates/d7_field.yml index 18135af..07b7a0a 100644 --- a/core/modules/field/migration_templates/d7_field.yml +++ b/core/modules/field/migration_templates/d7_field.yml @@ -34,7 +34,10 @@ process: phone: telephone text_long: text_long text_with_summary: text_with_summary - translatable: translatable + # Translatable is not migrated and the Drupal 8 default of true is used. + # If translatble is false in field storage then the field can not be + # set to translatable via the UI. + #translatable: translatable cardinality: cardinality settings: plugin: d7_field_settings diff --git a/core/modules/field/migration_templates/d7_field_instance.yml b/core/modules/field/migration_templates/d7_field_instance.yml index b6d2497..3ed97bb 100644 --- a/core/modules/field/migration_templates/d7_field_instance.yml +++ b/core/modules/field/migration_templates/d7_field_instance.yml @@ -27,6 +27,7 @@ process: source: - default_value - widget_settings + translatable: translatable destination: plugin: entity:field_config migration_dependencies: diff --git a/core/modules/field/src/Plugin/migrate/source/d7/FieldInstance.php b/core/modules/field/src/Plugin/migrate/source/d7/FieldInstance.php index 7aa281f..d7fd3ca 100644 --- a/core/modules/field/src/Plugin/migrate/source/d7/FieldInstance.php +++ b/core/modules/field/src/Plugin/migrate/source/d7/FieldInstance.php @@ -26,6 +26,7 @@ public function query() { ->condition('fc.deleted', 0) ->condition('fc.storage_active', 1) ->fields('fc', array('type')); + $query->addField('fc', 'data', 'data_fc'); $query->innerJoin('field_config', 'fc', 'fci.field_id = fc.id'); @@ -81,6 +82,19 @@ public function prepareRow(Row $row) { // This is for parity with the d6_field_instance plugin. $row->setSourceProperty('widget_type', $data['widget']['type']); + // If node translations are enabled for this content type, set translatable + // to true. + $translatable = FALSE; + if ($row->getSourceProperty('entity_type') == 'node') { + if ($this->variableGet('language_content_type_' . $row->getSourceProperty('bundle'), 0) == 2) { + $translatable = TRUE; + } + } + else { + $data = unserialize($row->getSourceProperty('data_fc')); + $translatable = $data['translatable']; + } + $row->setSourceProperty('translatable', $translatable); return parent::prepareRow($row); } diff --git a/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldInstanceTest.php b/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldInstanceTest.php index 2fa6d5c..50f513b 100644 --- a/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldInstanceTest.php +++ b/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldInstanceTest.php @@ -81,7 +81,7 @@ protected function createType($id) { * @param bool $is_required * Whether or not the field is required. */ - protected function assertEntity($id, $expected_label, $expected_field_type, $is_required) { + protected function assertEntity($id, $expected_label, $expected_field_type, $is_required, $expected_translatable ) { list ($expected_entity_type, $expected_bundle, $expected_name) = explode('.', $id); /** @var \Drupal\field\FieldConfigInterface $field */ @@ -94,6 +94,7 @@ protected function assertEntity($id, $expected_label, $expected_field_type, $is_ $this->assertIdentical($expected_name, $field->getName()); $this->assertEqual($is_required, $field->isRequired()); $this->assertIdentical($expected_entity_type . '.' . $expected_name, $field->getFieldStorageDefinition()->id()); + $this->assertSame($expected_translatable, $field->isTranslatable()); } /** @@ -113,37 +114,37 @@ protected function assertLinkFields($id, $title_setting) { * Tests migrating D7 field instances to field_config entities. */ public function testFieldInstances() { - $this->assertEntity('comment.comment_node_page.comment_body', 'Comment', 'text_long', TRUE); - $this->assertEntity('node.page.body', 'Body', 'text_with_summary', FALSE); - $this->assertEntity('comment.comment_node_article.comment_body', 'Comment', 'text_long', TRUE); - $this->assertEntity('node.article.body', 'Body', 'text_with_summary', FALSE); - $this->assertEntity('node.article.field_tags', 'Tags', 'entity_reference', FALSE); - $this->assertEntity('node.article.field_image', 'Image', 'image', FALSE); - $this->assertEntity('comment.comment_node_blog.comment_body', 'Comment', 'text_long', TRUE); - $this->assertEntity('node.blog.body', 'Body', 'text_with_summary', FALSE); - $this->assertEntity('comment.comment_node_book.comment_body', 'Comment', 'text_long', TRUE); - $this->assertEntity('node.book.body', 'Body', 'text_with_summary', FALSE); - $this->assertEntity('node.forum.taxonomy_forums', 'Forums', 'entity_reference', TRUE); - $this->assertEntity('comment.comment_node_forum.comment_body', 'Comment', 'text_long', TRUE); - $this->assertEntity('node.forum.body', 'Body', 'text_with_summary', FALSE); - $this->assertEntity('comment.comment_node_test_content_type.comment_body', 'Comment', 'text_long', TRUE); - $this->assertEntity('node.test_content_type.field_boolean', 'Boolean', 'boolean', FALSE); - $this->assertEntity('node.test_content_type.field_email', 'Email', 'email', FALSE); - $this->assertEntity('node.test_content_type.field_phone', 'Phone', 'telephone', TRUE); - $this->assertEntity('node.test_content_type.field_date', 'Date', 'datetime', FALSE); - $this->assertEntity('node.test_content_type.field_date_with_end_time', 'Date With End Time', 'datetime', FALSE); - $this->assertEntity('node.test_content_type.field_file', 'File', 'file', FALSE); - $this->assertEntity('node.test_content_type.field_float', 'Float', 'float', FALSE); - $this->assertEntity('node.test_content_type.field_images', 'Images', 'image', TRUE); - $this->assertEntity('node.test_content_type.field_integer', 'Integer', 'integer', TRUE); - $this->assertEntity('node.test_content_type.field_link', 'Link', 'link', FALSE); - $this->assertEntity('node.test_content_type.field_text_list', 'Text List', 'list_string', FALSE); - $this->assertEntity('node.test_content_type.field_integer_list', 'Integer List', 'list_integer', FALSE); - $this->assertEntity('node.test_content_type.field_long_text', 'Long text', 'text_with_summary', FALSE); - $this->assertEntity('node.test_content_type.field_term_reference', 'Term Reference', 'entity_reference', FALSE); - $this->assertEntity('node.test_content_type.field_text', 'Text', 'text', FALSE); - $this->assertEntity('comment.comment_node_test_content_type.field_integer', 'Integer', 'integer', FALSE); - $this->assertEntity('user.user.field_file', 'File', 'file', FALSE); + $this->assertEntity('comment.comment_node_page.comment_body', 'Comment', 'text_long', TRUE, FALSE); + $this->assertEntity('node.page.body', 'Body', 'text_with_summary', FALSE, FALSE); + $this->assertEntity('comment.comment_node_article.comment_body', 'Comment', 'text_long', TRUE, FALSE); + $this->assertEntity('node.article.body', 'Body', 'text_with_summary', FALSE, TRUE); + $this->assertEntity('node.article.field_tags', 'Tags', 'entity_reference', FALSE, TRUE); + $this->assertEntity('node.article.field_image', 'Image', 'image', FALSE, TRUE); + $this->assertEntity('comment.comment_node_blog.comment_body', 'Comment', 'text_long', TRUE, FALSE); + $this->assertEntity('node.blog.body', 'Body', 'text_with_summary', FALSE, TRUE); + $this->assertEntity('comment.comment_node_book.comment_body', 'Comment', 'text_long', TRUE, FALSE); + $this->assertEntity('node.book.body', 'Body', 'text_with_summary', FALSE, FALSE); + $this->assertEntity('node.forum.taxonomy_forums', 'Forums', 'entity_reference', TRUE, FALSE); + $this->assertEntity('comment.comment_node_forum.comment_body', 'Comment', 'text_long', TRUE, FALSE); + $this->assertEntity('node.forum.body', 'Body', 'text_with_summary', FALSE, FALSE); + $this->assertEntity('comment.comment_node_test_content_type.comment_body', 'Comment', 'text_long', TRUE, FALSE); + $this->assertEntity('node.test_content_type.field_boolean', 'Boolean', 'boolean', FALSE, FALSE); + $this->assertEntity('node.test_content_type.field_email', 'Email', 'email', FALSE, FALSE); + $this->assertEntity('node.test_content_type.field_phone', 'Phone', 'telephone', TRUE, FALSE); + $this->assertEntity('node.test_content_type.field_date', 'Date', 'datetime', FALSE, FALSE); + $this->assertEntity('node.test_content_type.field_date_with_end_time', 'Date With End Time', 'datetime', FALSE, FALSE); + $this->assertEntity('node.test_content_type.field_file', 'File', 'file', FALSE, FALSE); + $this->assertEntity('node.test_content_type.field_float', 'Float', 'float', FALSE, FALSE); + $this->assertEntity('node.test_content_type.field_images', 'Images', 'image', TRUE, FALSE); + $this->assertEntity('node.test_content_type.field_integer', 'Integer', 'integer', TRUE, FALSE); + $this->assertEntity('node.test_content_type.field_link', 'Link', 'link', FALSE, FALSE); + $this->assertEntity('node.test_content_type.field_text_list', 'Text List', 'list_string', FALSE, FALSE); + $this->assertEntity('node.test_content_type.field_integer_list', 'Integer List', 'list_integer', FALSE, FALSE); + $this->assertEntity('node.test_content_type.field_long_text', 'Long text', 'text_with_summary', FALSE, FALSE); + $this->assertEntity('node.test_content_type.field_term_reference', 'Term Reference', 'entity_reference', FALSE, FALSE); + $this->assertEntity('node.test_content_type.field_text', 'Text', 'text', FALSE, FALSE); + $this->assertEntity('comment.comment_node_test_content_type.field_integer', 'Integer', 'integer', FALSE, FALSE); + $this->assertEntity('user.user.field_file', 'File', 'file', FALSE, FALSE); $this->assertLinkFields('node.test_content_type.field_link', DRUPAL_OPTIONAL); $this->assertLinkFields('node.article.field_link', DRUPAL_DISABLED); diff --git a/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldTest.php b/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldTest.php index b1c2fb8..52cb23a 100644 --- a/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldTest.php +++ b/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldTest.php @@ -60,8 +60,6 @@ protected function assertEntity($id, $expected_type, $expected_translatable, $ex $this->assertTrue($field instanceof FieldStorageConfigInterface); $this->assertIdentical($expected_name, $field->getName()); $this->assertIdentical($expected_type, $field->getType()); - // FieldStorageConfig::$translatable is TRUE by default, so it is useful - // to test for FALSE here. $this->assertEqual($expected_translatable, $field->isTranslatable()); $this->assertIdentical($expected_entity_type, $field->getTargetEntityTypeId()); @@ -78,28 +76,28 @@ protected function assertEntity($id, $expected_type, $expected_translatable, $ex * Tests migrating D7 fields to field_storage_config entities. */ public function testFields() { - $this->assertEntity('node.body', 'text_with_summary', FALSE, 1); - $this->assertEntity('node.field_long_text', 'text_with_summary', FALSE, 1); - $this->assertEntity('comment.comment_body', 'text_long', FALSE, 1); - $this->assertEntity('node.field_file', 'file', FALSE, 1); - $this->assertEntity('user.field_file', 'file', FALSE, 1); - $this->assertEntity('node.field_float', 'float', FALSE, 1); - $this->assertEntity('node.field_image', 'image', FALSE, 1); - $this->assertEntity('node.field_images', 'image', FALSE, 1); - $this->assertEntity('node.field_integer', 'integer', FALSE, 1); - $this->assertEntity('comment.field_integer', 'integer', FALSE, 1); - $this->assertEntity('node.field_integer_list', 'list_integer', FALSE, 1); - $this->assertEntity('node.field_link', 'link', FALSE, 1); - $this->assertEntity('node.field_tags', 'entity_reference', FALSE, -1); - $this->assertEntity('node.field_term_reference', 'entity_reference', FALSE, 1); - $this->assertEntity('node.taxonomy_forums', 'entity_reference', FALSE, 1); - $this->assertEntity('node.field_text', 'text', FALSE, 1); - $this->assertEntity('node.field_text_list', 'list_string', FALSE, 3); - $this->assertEntity('node.field_boolean', 'boolean', FALSE, 1); - $this->assertEntity('node.field_email', 'email', FALSE, -1); - $this->assertEntity('node.field_phone', 'telephone', FALSE, 1); - $this->assertEntity('node.field_date', 'datetime', FALSE, 1); - $this->assertEntity('node.field_date_with_end_time', 'datetime', FALSE, 1); + $this->assertEntity('node.body', 'text_with_summary', TRUE, 1); + $this->assertEntity('node.field_long_text', 'text_with_summary', TRUE, 1); + $this->assertEntity('comment.comment_body', 'text_long', TRUE, 1); + $this->assertEntity('node.field_file', 'file', TRUE, 1); + $this->assertEntity('user.field_file', 'file', TRUE, 1); + $this->assertEntity('node.field_float', 'float', TRUE, 1); + $this->assertEntity('node.field_image', 'image', TRUE, 1); + $this->assertEntity('node.field_images', 'image', TRUE, 1); + $this->assertEntity('node.field_integer', 'integer', TRUE, 1); + $this->assertEntity('comment.field_integer', 'integer', TRUE, 1); + $this->assertEntity('node.field_integer_list', 'list_integer', TRUE, 1); + $this->assertEntity('node.field_link', 'link', TRUE, 1); + $this->assertEntity('node.field_tags', 'entity_reference', TRUE, -1); + $this->assertEntity('node.field_term_reference', 'entity_reference', TRUE, 1); + $this->assertEntity('node.taxonomy_forums', 'entity_reference', TRUE, 1); + $this->assertEntity('node.field_text', 'text', TRUE, 1); + $this->assertEntity('node.field_text_list', 'list_string', TRUE, 3); + $this->assertEntity('node.field_boolean', 'boolean', TRUE, 1); + $this->assertEntity('node.field_email', 'email', TRUE, -1); + $this->assertEntity('node.field_phone', 'telephone', TRUE, 1); + $this->assertEntity('node.field_date', 'datetime', TRUE, 1); + $this->assertEntity('node.field_date_with_end_time', 'datetime', TRUE, 1); // Assert that the taxonomy term reference fields are referencing the // correct entity type. diff --git a/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d7/FieldInstanceTest.php b/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d7/FieldInstanceTest.php index a0b8ec1..259c9f1 100644 --- a/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d7/FieldInstanceTest.php +++ b/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d7/FieldInstanceTest.php @@ -94,6 +94,7 @@ public function providerSource() { ], 'description' => '', 'required' => FALSE, + 'data_fc' => 'a:6:{s:12:"entity_types";a:1:{i:0;s:4:"node";}s:12:"translatable";b:0;s:8:"settings";a:0:{}s:7:"storage";a:4:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";i:1;}s:12:"foreign keys";a:1:{s:6:"format";a:2:{s:5:"table";s:13:"filter_format";s:7:"columns";a:1:{s:6:"format";s:6:"format";}}}s:7:"indexes";a:1:{s:6:"format";a:1:{i:0;s:6:"format";}}}', ], ]; diff --git a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php index 2d60c46..ebd6352 100644 --- a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php +++ b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php @@ -350,6 +350,10 @@ class MigrateUpgradeForm extends ConfirmFormBase { 'source_module' => 'node', 'destination_module' => 'node', ], + 'd7_node_translation' => [ + 'source_module' => 'node', + 'destination_module' => 'node', + ], 'd7_node_title_label' => [ 'source_module' => 'node', 'destination_module' => 'node', diff --git a/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php b/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php index 74d4237..ceb6ec9 100644 --- a/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php +++ b/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php @@ -50,7 +50,7 @@ protected function getEntityCounts() { 'image_style' => 6, 'language_content_settings' => 2, 'migration' => 73, - 'node' => 3, + 'node' => 2, 'node_type' => 6, 'rdf_mapping' => 5, 'search_page' => 2, diff --git a/core/modules/node/migration_templates/d7_node.yml b/core/modules/node/migration_templates/d7_node.yml index b763534..a056bf2 100644 --- a/core/modules/node/migration_templates/d7_node.yml +++ b/core/modules/node/migration_templates/d7_node.yml @@ -6,7 +6,10 @@ deriver: Drupal\node\Plugin\migrate\D7NodeDeriver source: plugin: d7_node process: - nid: nid + # In D7, nodes always have a tnid, but it's zero for untranslated nodes. + # We normalize it to equal the nid in that case. + # @see \Drupal\node\Plugin\migrate\source\d7\Node::prepareRow(). + nid: tnid vid: vid langcode: plugin: default_value diff --git a/core/modules/node/migration_templates/d7_node.yml b/core/modules/node/migration_templates/d7_node_translation.yml similarity index 72% copy from core/modules/node/migration_templates/d7_node.yml copy to core/modules/node/migration_templates/d7_node_translation.yml index b763534..157e9d6 100644 --- a/core/modules/node/migration_templates/d7_node.yml +++ b/core/modules/node/migration_templates/d7_node_translation.yml @@ -1,13 +1,14 @@ -id: d7_node -label: Nodes +id: d7_node_translation +label: Node translations migration_tags: - Drupal 7 deriver: Drupal\node\Plugin\migrate\D7NodeDeriver source: plugin: d7_node + translations: true process: - nid: nid - vid: vid + nid: tnid + type: type langcode: plugin: default_value source: language @@ -24,9 +25,14 @@ process: revision_timestamp: timestamp destination: plugin: entity:node + translations: true + content_translation_update_definitions: + - node migration_dependencies: required: - d7_user - d7_node_type + - language optional: - d7_field_instance +provider: migrate_drupal diff --git a/core/modules/node/src/Plugin/migrate/D7NodeDeriver.php b/core/modules/node/src/Plugin/migrate/D7NodeDeriver.php index bd3d8b9..fcac62f 100644 --- a/core/modules/node/src/Plugin/migrate/D7NodeDeriver.php +++ b/core/modules/node/src/Plugin/migrate/D7NodeDeriver.php @@ -39,33 +39,58 @@ class D7NodeDeriver extends DeriverBase implements ContainerDeriverInterface { protected $cckPluginManager; /** - * D7NodeDeriver constructor. + * Whether or not to include translations. * + * @var bool + */ + protected $includeTranslations; + + /** + * D7NodeDeriver constructor. * @param string $base_plugin_id * The base plugin ID for the plugin ID. * @param \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface $cck_manager * The CCK plugin manager. + * @param bool $translations + * Whether or not to include translations. */ - public function __construct($base_plugin_id, MigrateCckFieldPluginManagerInterface $cck_manager) { + public function __construct($base_plugin_id, MigrateCckFieldPluginManagerInterface $cck_manager, $translations) { $this->basePluginId = $base_plugin_id; $this->cckPluginManager = $cck_manager; + $this->includeTranslations = $translations; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, $base_plugin_id) { + // Translations don't make sense unless we have content_translation. return new static( $base_plugin_id, - $container->get('plugin.manager.migrate.cckfield') + $container->get('plugin.manager.migrate.cckfield'), + $container->get('module_handler')->moduleExists('content_translation') ); } /** - * {@inheritdoc} + * Gets the definition of all derivatives of a base plugin. + * + * @param array $base_plugin_definition + * The definition array of the base plugin. + * + * @return array + * An array of full derivative definitions keyed on derivative id. + * + * @see \Drupal\Component\Plugin\Derivative\DeriverBase::getDerivativeDefinition() */ public function getDerivativeDefinitions($base_plugin_definition) { - $fields = []; + if ($base_plugin_definition['id'] == 'd7_node_translation' && !$this->includeTranslations) { + // Refuse to generate anything. + return $this->derivatives; + } + + // Read all CCK field instance definitions in the source database. + $fields = array(); try { $source_plugin = static::getSourcePlugin('d7_field_instance'); $source_plugin->checkRequirements(); @@ -95,6 +120,13 @@ public function getDerivativeDefinitions($base_plugin_definition) { $values['source']['node_type'] = $node_type; $values['destination']['default_bundle'] = $node_type; + // If this migration is based on the d7_node_revision migration or + // is for translations of nodes, it should explicitly depend on the + // corresponding d7_node variant. + if (in_array($base_plugin_definition['id'], ['d7_node_revision', 'd7_node_translation'])) { + $values['migration_dependencies']['required'][] = 'd7_node:' . $node_type; + } + $migration = \Drupal::service('plugin.manager.migration')->createStubMigration($values); if (isset($fields[$node_type])) { foreach ($fields[$node_type] as $field_name => $info) { @@ -121,7 +153,6 @@ public function getDerivativeDefinitions($base_plugin_definition) { // MigrationPluginManager gathers up the migration definitions but we do // not actually have a Drupal 7 source database. } - return $this->derivatives; } diff --git a/core/modules/node/src/Plugin/migrate/source/d7/Node.php b/core/modules/node/src/Plugin/migrate/source/d7/Node.php index 6286d5f..87dddde 100644 --- a/core/modules/node/src/Plugin/migrate/source/d7/Node.php +++ b/core/modules/node/src/Plugin/migrate/source/d7/Node.php @@ -4,6 +4,7 @@ use Drupal\migrate\Row; use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity; +use Drupal\Core\Database\Query\SelectInterface; /** * Drupal 7 node source from database. @@ -49,6 +50,8 @@ public function query() { $query->addField('nr', 'uid', 'revision_uid'); $query->innerJoin('node', 'n', static::JOIN); + $this->handleTranslations($query); + if (isset($this->configuration['node_type'])) { $query->condition('n.type', $this->configuration['node_type']); } @@ -66,6 +69,11 @@ public function prepareRow(Row $row) { $vid = $row->getSourceProperty('vid'); $row->setSourceProperty($field, $this->getFieldValues('node', $field, $nid, $vid)); } + + // Make sure we always have a translation set. + if ($row->getSourceProperty('tnid') == 0) { + $row->setSourceProperty('tnid', $row->getSourceProperty('nid')); + } return parent::prepareRow($row); } @@ -101,4 +109,21 @@ public function getIds() { return $ids; } + /** + * Adapt our query for translations. + * + * @param \Drupal\Core\Database\Query\SelectInterface $query + * The generated query. + */ + protected function handleTranslations(SelectInterface $query) { + // Check whether or not we want translations. + if (empty($this->configuration['translations'])) { + // No translations: Yield untranslated nodes, or default translations. + $query->where('n.tnid = 0 OR n.tnid = n.nid'); + } + else { + // Translations: Yield only non-default translations. + $query->where('n.tnid <> 0 AND n.tnid <> n.nid'); + } + } } diff --git a/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeDeriverTest.php b/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeDeriverTest.php new file mode 100644 index 0000000..e51a40c --- /dev/null +++ b/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeDeriverTest.php @@ -0,0 +1,50 @@ +pluginManager = $this->container->get('plugin.manager.migration'); + } + + /** + * Test node translation migrations with translation disabled. + */ + public function testNoTranslations() { + // Without content_translation, there should be no translation migrations. + $migrations = $this->pluginManager->createInstances('d7_node_translation'); + $this->assertSame([], $migrations, + "No node translation migrations without content_translation"); + } + + /** + * Test node translation migrations with translation enabled. + */ + public function testTranslations() { + // With content_translation, there should be translation migrations for + // each content type. + $this->enableModules(['language', 'content_translation', 'node', 'filter']); + $migrations = $this->pluginManager->createInstances('d7_node_translation'); + $this->assertArrayHasKey('d7_node_translation:article', $migrations, + "Node translation migrations exist after content_translation installed"); + } + +} diff --git a/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeTest.php b/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeTest.php index f7b98bd..df56f82 100644 --- a/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeTest.php +++ b/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeTest.php @@ -14,10 +14,12 @@ class MigrateNodeTest extends MigrateDrupal7TestBase { public static $modules = array( + 'content_translation', 'comment', 'datetime', 'filter', 'image', + 'language', 'link', 'node', 'taxonomy', @@ -40,6 +42,7 @@ protected function setUp() { $this->installSchema('system', ['sequences']); $this->executeMigrations([ + 'language', 'd7_user_role', 'd7_user', 'd7_node_type', @@ -48,7 +51,7 @@ protected function setUp() { 'd7_field', 'd7_field_instance', 'd7_node', - 'd7_node:article', + 'd7_node_translation', ]); } @@ -144,9 +147,15 @@ public function testNode() { $this->assertIdentical('Click Here', $node->field_link->title); $node = Node::load(2); + $this->assertIdentical('en', $node->langcode->value); $this->assertIdentical("...is that it's the absolute best show ever. Trust me, I would know.", $node->body->value); + $this->assertIdentical('The thing about Deep Space 9', $node->title->value); $this->assertIdentical('internal:/', $node->field_link->uri); $this->assertIdentical('Home', $node->field_link->title); + $this->assertTrue($node->hasTranslation('is'), "Node 2 has an Icelandic translation"); + + // Node 3 is a translation of node 2, and should not be imported separately. + $this->assertNull(Node::load(3), "Node 3 doesn't exist in D8, it was a translation"); } } diff --git a/core/modules/node/tests/src/Kernel/Plugin/migrate/source/d7/NodeTest.php b/core/modules/node/tests/src/Kernel/Plugin/migrate/source/d7/NodeTest.php index 6b19b95..33db209 100644 --- a/core/modules/node/tests/src/Kernel/Plugin/migrate/source/d7/NodeTest.php +++ b/core/modules/node/tests/src/Kernel/Plugin/migrate/source/d7/NodeTest.php @@ -77,7 +77,40 @@ public function providerSource() { 'tnid' => 0, 'translate' => 0, ], - + [ + // Node fields. + 'nid' => 6, + 'vid' => 6, + 'type' => 'article', + 'language' => 'en', + 'title' => 'node title 5', + 'uid' => 1, + 'status' => 1, + 'created' => 1279291908, + 'changed' => 1279309993, + 'comment' => 0, + 'promote' => 1, + 'sticky' => 0, + 'tnid' => 6, + 'translate' => 0, + ], + [ + // Node fields. + 'nid' => 7, + 'vid' => 7, + 'type' => 'article', + 'language' => 'fr', + 'title' => 'fr - node title 5', + 'uid' => 1, + 'status' => 1, + 'created' => 1279292908, + 'changed' => 1279310993, + 'comment' => 0, + 'promote' => 1, + 'sticky' => 0, + 'tnid' => 6, + 'translate' => 0, + ], ]; $tests[0]['source_data']['node_revision'] = [ [ @@ -119,6 +152,33 @@ public function providerSource() { 'promote' => 1, 'sticky' => 0, ], + [ + // Node fields. + 'nid' => 6, + 'vid' => 6, + 'uid' => 1, + 'title' => 'node title 5', + 'log' => '', + 'timestamp' => 1279309993, + 'status' => 1, + 'comment' => 0, + 'promote' => 1, + 'sticky' => 0, + + ], + [ + // Node fields. + 'nid' => 7, + 'vid' => 7, + 'uid' => 1, + 'title' => 'fr - node title 5', + 'log' => '', + 'timestamp' => 1279310993, + 'status' => 1, + 'comment' => 0, + 'promote' => 1, + 'sticky' => 0, + ], ]; $tests[0]['source_data']['field_config_instance'] = [ [ @@ -131,7 +191,7 @@ public function providerSource() { 'deleted' => '0', ], [ - 'id' => '2', + 'id' => '3', 'field_id' => '2', 'field_name' => 'body', 'entity_type' => 'node', @@ -153,6 +213,54 @@ public function providerSource() { 'body_summary' => '', 'body_format' => 'filtered_html', ], + [ + 'entity_type' => 'node', + 'bundle' => 'page', + 'deleted' => '0', + 'entity_id' => '2', + 'revision_id' => '2', + 'language' => 'en', + 'delta' => '0', + 'body_value' => 'body 2', + 'body_summary' => '', + 'body_format' => 'filtered_html', + ], + [ + 'entity_type' => 'node', + 'bundle' => 'page', + 'deleted' => '0', + 'entity_id' => '5', + 'revision_id' => '5', + 'language' => 'en', + 'delta' => '0', + 'body_value' => 'body 5', + 'body_summary' => '', + 'body_format' => 'filtered_html', + ], + [ + 'entity_type' => 'node', + 'bundle' => 'page', + 'deleted' => '0', + 'entity_id' => '6', + 'revision_id' => '6', + 'language' => 'en', + 'delta' => '0', + 'body_value' => 'body 6', + 'body_summary' => '', + 'body_format' => 'filtered_html', + ], + [ + 'entity_type' => 'node', + 'bundle' => 'page', + 'deleted' => '0', + 'entity_id' => '7', + 'revision_id' => '7', + 'language' => 'fr', + 'delta' => '0', + 'body_value' => 'fr - body 6', + 'body_summary' => '', + 'body_format' => 'filtered_html', + ], ]; // The expected results. @@ -172,8 +280,9 @@ public function providerSource() { 'comment' => 2, 'promote' => 1, 'sticky' => 0, - 'tnid' => 0, + 'tnid' => 1, 'translate' => 0, + // Node revision fields. 'log' => '', 'timestamp' => 1279051598, 'body' => [ @@ -199,10 +308,17 @@ public function providerSource() { 'comment' => 0, 'promote' => 1, 'sticky' => 0, - 'tnid' => 0, + 'tnid' => 2, 'translate' => 0, 'log' => '', 'timestamp' => 1279308993, + 'body' => [ + [ + 'value' => 'body 2', + 'summary' => '', + 'format' => 'filtered_html', + ], + ], ], [ // Node fields. @@ -219,10 +335,44 @@ public function providerSource() { 'comment' => 0, 'promote' => 1, 'sticky' => 0, - 'tnid' => 0, + 'tnid' => 5, 'translate' => 0, 'log' => '', 'timestamp' => 1279308993, + 'body' => [ + [ + 'value' => 'body 5', + 'summary' => '', + 'format' => 'filtered_html', + ], + ], + ], + [ + // Node fields. + 'nid' => 6, + 'vid' => 6, + 'type' => 'article', + 'language' => 'en', + 'title' => 'node title 5', + 'node_uid' => 1, + 'revision_uid' => 1, + 'status' => 1, + 'created' => 1279291908, + 'changed' => 1279309993, + 'comment' => 0, + 'promote' => 1, + 'sticky' => 0, + 'tnid' => 6, + 'translate' => 0, + 'log' => '', + 'timestamp' => 1279309993, + 'body' => [ + [ + 'value' => 'body 6', + 'summary' => '', + 'format' => 'filtered_html', + ], + ], ], ]; diff --git a/core/modules/node/tests/src/Kernel/Plugin/migrate/source/d7/NodeTranslationTest.php b/core/modules/node/tests/src/Kernel/Plugin/migrate/source/d7/NodeTranslationTest.php new file mode 100644 index 0000000..03c90c3 --- /dev/null +++ b/core/modules/node/tests/src/Kernel/Plugin/migrate/source/d7/NodeTranslationTest.php @@ -0,0 +1,70 @@ + 7, + 'vid' => 7, + 'type' => 'article', + 'language' => 'fr', + 'title' => 'fr - node title 5', + 'node_uid' => 1, + 'revision_uid' => 1, + 'status' => 1, + 'created' => 1279292908, + 'changed' => 1279310993, + 'comment' => 0, + 'promote' => 1, + 'sticky' => 0, + 'tnid' => 6, + 'translate' => 0, + // Node revision fields. + 'log' => '', + 'timestamp' => 1279310993, + 'body' => [ + [ + 'value' => 'fr - body 6', + 'summary' => '', + 'format' => 'filtered_html', + ], + ], + ], + ]; + + // Do an automatic count. + $tests[0]['expected_count'] = NULL; + + // Set up source plugin configuration. + $tests[0]['configuration'] = [ + 'translations' => TRUE, + ]; + + return $tests; + } + +}