376c376 < index 3f9439dd3b..fac09cbcb3 100644 --- > index 3f9439dd3b..f9bb4e7ac8 100644 379,387c379 < @@ -11,6 +11,7 @@ < use Drupal\migrate\Exception\RequirementsException; < use Drupal\migrate\MigrateExecutable; < use Drupal\migrate\Plugin\RequirementsInterface; < +use Drupal\migrate_drupal\NodeMigrateType; < < /** < * Implements hook_help(). < @@ -46,7 +47,8 @@ function migrate_drupal_migration_plugins_alter(&$definitions) { --- > @@ -46,7 +46,8 @@ function migrate_drupal_migration_plugins_alter(&$definitions) { 397c389 < @@ -89,6 +91,164 @@ function migrate_drupal_migration_plugins_alter(&$definitions) { --- > @@ -89,6 +90,5 @@ function migrate_drupal_migration_plugins_alter(&$definitions) { 401,558c393 < + } < + < + // If the complete node migrate_map tables have data then the any migration < + // use a node migration in a migration_lookup needs to be altered to use < + // both the classic and complete node migration. < + if ((new NodeMigrateType)->getNodeMigrateType($definitions, NULL) !== NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC) { < + < + // Anonymous function to replace classic node migration plugin IDs with the < + // complete plugin ID. < + $replace_with_complete_migration = function (&$value) { < + if (is_string($value)) { < + $value = preg_replace('/d([67])_(node|node_translation|node_revision)($|:.*)/', 'd$1_node_complete$3', $value); < + } < + return $value; < + }; < + // Alter references to the classic node migration to the complete node < + // migration in all relevant core migrations. The references altered are < + // those in migration_dependencies and in the process pipeline. In the < + // process pipeline we are concerned with references to classic node < + // migrations in a migration_lookup process. < + // < + // The process pipeline is altered so that the migration_lookup returns < + // the correct IDs. For example, the classic d6_node_revision migration < + // has a single ID, the revision ID, but the d6_node_complete has three IDs, < + // the node ID, the revision ID and the language. To ensure the pipeline < + // works for both migrations we need to insert a process to return only < + // the revision ID if the complete node migration was used. < + // < + // Example: d6_term_node_revision < + // < + // Before < + // vid: < + // - < + // plugin: migration_lookup < + // migration: d6_node_revision < + // source: vid < + // - < + // plugin: skip_on_empty < + // method: row < + // After < + // vid: < + // - < + // plugin: migration_lookup < + // migration: < + // - d6_node_revision < + // - d6_node_complete < + // source: vid < + // - < + // plugin: skip_on_empty < + // method: row < + // - < + // plugin: node_complete_node_lookup < + // < + // The classic node migrations are not altered. < + // < + // See \Drupal\migrate_drupal\Plugin\migrate\process\NodeCompleteNodeLookup < + // See \Drupal\migrate_drupal\Plugin\migrate\process\NodeCompleteNodeRevisionLookup < + // See \Drupal\migrate_drupal\Plugin\migrate\process\NodeCompleteNodeTranslationLookup < + foreach ($definitions as &$definition) { < + $is_node_classic_migration = preg_match('/d([67])_(node|node_translation|node_revision)($|:.*)/', $definition['id']); < + if (!$is_node_classic_migration && isset($definition['migration_dependencies'])) { < + array_walk_recursive($definition['migration_dependencies'], $replace_with_complete_migration); < + } < + < + // Alter the migration_lookup process so the node ID is returned. < + if (preg_match('/d6_term_node($|:.*)/', $definition['id'])) { < + $tmp = $definition['process']['nid'][0]['migration']; < + $definition['process']['nid'][0]['migration'] = _insert_migration($tmp); < + $definition['process']['nid'][2] = [ < + 'plugin' => 'node_complete_node_lookup', < + ]; < + } < + // Alter the migration_lookup process so the revision ID is returned. < + if (preg_match('/d6_term_node_revision($|:.*)/', $definition['id'])) { < + $tmp = $definition['process']['vid'][0]['migration']; < + $definition['process']['vid'][0]['migration'] = _insert_migration($tmp); < + $definition['process']['vid'][2] = [ < + 'plugin' => 'node_complete_node_revision_lookup', < + ]; < + } < + // Alter the migration_lookup process so the node ID and langcode are < + // returned. < + if (preg_match('/d6_term_node_translation($|:.*)/', $definition['id'])) { < + $tmp = $definition['process']['dest_nid'][0]['migration']; < + $definition['process']['dest_nid'][0]['migration'] = _insert_migration($tmp); < + $definition['process']['dest_nid'][2] = [ < + 'plugin' => 'node_complete_node_translation_lookup', < + ]; < + } < + } < < + // Alter the migration_lookup process so the node ID is returned. < + if (isset($definitions['d6_comment'])) { < + $tmp = $definitions['d6_comment']['process']['entity_id'][0]['migration']; < + $definitions['d6_comment']['process']['entity_id'][0]['migration'] = _insert_migration($tmp); < + $definitions['d6_comment']['process']['entity_id'][2] = [ < + 'plugin' => 'node_complete_node_lookup', < + ]; < + } < + // Alter the migration_lookup process so the node ID and langcode are < + // returned. < + if (isset($definitions['d6_url_alias'])) { < + $tmp = $definitions['d6_url_alias']['process']['node_translation'][2]['migration']; < + $definitions['d6_url_alias']['process']['node_translation'][2]['migration'] = _insert_migration($tmp); < + $definitions['d6_url_alias']['process']['node_translation'][3] = [ < + 'plugin' => 'node_complete_node_translation_lookup', < + ]; < + } < + // Alter the migration_lookup process so the node ID is returned. < + if (isset($definitions['d7_comment'])) { < + $tmp = $definitions['d7_comment']['process']['entity_id'][0]['migration']; < + $definitions['d7_comment']['process']['entity_id'][0]['migration'] = _insert_migration($tmp); < + $definitions['d7_comment']['process']['entity_id'][2] = [ < + 'plugin' => 'node_complete_node_lookup', < + ]; < + } < + // Alter the migration_lookup process so the node ID and langcode are < + // returned. < + if (isset($definitions['d7_url_alias'])) { < + $tmp = $definitions['d7_url_alias']['process']['node_translation'][2]['migration']; < + $definitions['d7_url_alias']['process']['node_translation'][2]['migration'] = _insert_migration($tmp); < + $definitions['d7_url_alias']['process']['node_translation'][3] = [ < + 'plugin' => 'node_complete_node_translation_lookup', < + ]; < + } < + // Alter the migration_lookup process so the node ID is returned. < + if (isset($definitions['statistics_node_counter'])) { < + $tmp = $definitions['statistics_node_counter']['process']['nid'][0]['migration']; < + $definitions['statistics_node_counter']['process']['nid'][0]['migration'] = _insert_migration($tmp); < + $definitions['statistics_node_counter']['process']['nid'][2] = [ < + 'plugin' => 'node_complete_node_lookup', < + ]; < + } < + // Alter the migration_lookup process to include the complete node migration. < + // A node_complete_node*_lookup process is not needed because the < + // migration_lookup is followed by an extract process which will get the < + // node ID. < + if (isset($definitions['node_translation_menu_links'])) { < + $tmp = $definitions['node_translation_menu_links']['process']['new_nid'][4]['migration']; < + $definitions['node_translation_menu_links']['process']['new_nid'][4]['migration'] = _insert_migration($tmp); < + } < + } < +} < + < +/** < + * Add dN_node_complete to the migrations array of a migration_lookup plugin. < + * < + * @internal < + * Only to be used by migrate_drupal_migration_plugins_alter(). < + */ < +function _insert_migration($migrations) { < + if (!is_array($migrations)) { < + $migrations = [$migrations]; < + } < + $new_migration_list = []; < + foreach ($migrations as $migration) { < + $tmp = substr($migration, 0, 2) . '_node_complete'; < + array_unshift($new_migration_list, $tmp, $migration); --- > - 560d394 < + return array_unique($new_migration_list); 563c397 < index 8cb60347bc..3e98a6e9f2 100644 --- > index 8cb60347bc..52937b9a70 100644 566c400 < @@ -121,8 +121,30 @@ protected function createDatabaseStateSettings(array $database, $drupal_version) --- > @@ -121,8 +121,29 @@ protected function createDatabaseStateSettings(array $database, $drupal_version) 574,578c408,411 < + // If this source database is multilingual then we must run only the < + // dN_node_complete migration and not any other dN_node* migration or the < + // entity translation migrations. Conversely, if the source database is not < + // multilingual then we want to run all dN_node* migrations except < + // dN_node_complete. Here we unset the migrations we don't want to run. --- > + // Unset the node migrations that should not run based on the type of node > + // migration. That is, if this is a complete node migration then unset the > + // classic node migrations and if this is a classic node migration then > + // unset the complete node migrations. 582c415 < + $patterns = '/(d' . $drupal_version . '_node:)|(d' . $drupal_version . '_node_translation:)|(d' . $drupal_version . '_node_revision:)|(entity_translation)/'; --- > + $patterns = '/(d' . $drupal_version . '_node:)|(d' . $drupal_version . '_node_translation:)|(d' . $drupal_version . '_node_revision:)|(d7_node_entity_translation:)/'; 1027c860 < index fafbed003a..37984eddd9 100644 --- > index f34c6e1594..937ee79e20 100644 1858c1691 < @@ -41439,14 +41812,14 @@ --- > @@ -42239,14 +42612,14 @@ 1875c1708 < @@ -41455,14 +41828,14 @@ --- > @@ -42255,14 +42628,14 @@ 1892c1725 < @@ -41471,14 +41844,14 @@ --- > @@ -42271,14 +42644,14 @@ 1909c1742 < @@ -41487,14 +41860,14 @@ --- > @@ -42287,14 +42660,14 @@ 1926c1759 < @@ -41956,9 +42329,9 @@ --- > @@ -42756,9 +43129,9 @@ 1939c1772 < @@ -41968,9 +42341,9 @@ --- > @@ -42768,9 +43141,9 @@ 1952c1785 < @@ -41980,8 +42353,8 @@ --- > @@ -42780,8 +43153,8 @@ 1963c1796 < @@ -41992,9 +42365,9 @@ --- > @@ -42792,9 +43165,9 @@ 1976c1809 < @@ -42060,6 +42433,54 @@ --- > @@ -42860,6 +43233,54 @@ 31134,31483d30966 < diff --git a/core/modules/migrate_drupal/tests/src/Kernel/MigrationPluginAlterTest.php b/core/modules/migrate_drupal/tests/src/Kernel/MigrationPluginAlterTest.php < index 335c44cab7..ab21459038 100644 < --- a/core/modules/migrate_drupal/tests/src/Kernel/MigrationPluginAlterTest.php < +++ b/core/modules/migrate_drupal/tests/src/Kernel/MigrationPluginAlterTest.php < @@ -2,15 +2,18 @@ < < namespace Drupal\Tests\migrate_drupal\Kernel; < < +use Drupal\migrate_drupal\NodeMigrateType; < use Drupal\Tests\migrate\Kernel\MigrateTestBase; < +use Drupal\Tests\migrate_drupal\Traits\NodeMigrateTypeTestTrait; < < /** < - * Tests migrate_drupal_migrations_plugin_alter for d6 term node migrations. < + * Tests migrate_drupal_migrations_plugin_alter. < * < * @group migrate_drupal < */ < class MigrationPluginAlterTest extends MigrateTestBase { < < + use NodeMigrateTypeTestTrait; < /** < * {@inheritdoc} < */ < @@ -25,12 +28,27 @@ protected function setUp() { < } < < /** < - * Tests migrate_drupal_migrations_plugin_alter without content_translation. < + * Tests migrate_drupal_migrations_plugin_alter. < + * < + * @param array $modules < + * An array of modules to install. < + * @param string $type < + * The type of node migration, 'classic' or 'complete'. < + * @param array $migration_definitions < + * An array of migration definitions. < + * @param array $expected < + * The expected results. < * < * @dataProvider providerMigrationPluginAlter < + * < + * @throws \Drupal\Core\Extension\MissingDependencyException < */ < - public function testMigrationPluginAlterNoTranslation($source, $expected) { < - $definitions = $source; < + public function testMigrationPluginAlter(array $modules, $type, array $migration_definitions, array $expected) { < + /** @var \Drupal\Core\Extension\ModuleInstaller $module_installer */ < + $module_installer = \Drupal::service('module_installer'); < + $module_installer->install($modules); < + $this->makeNodeMigrateMapTable($type, '6'); < + $definitions = $migration_definitions; < migrate_drupal_migration_plugins_alter($definitions); < // Ensure the results have an 'id' key. < foreach ($definitions as $definition) { < @@ -45,19 +63,29 @@ public function testMigrationPluginAlterNoTranslation($source, $expected) { < public function providerMigrationPluginAlter() { < $tests = []; < < - // Test without a d6_taxonomy_vocabulary definition. < - $tests[0]['source_data'] = [ < + // Tests migrations that should never be altered, once without an extra < + // module installed and then with content_translation installed. < + $system_site_migration = [ < + 'system_site' => [ < + 'id' => 'system_site', < + 'source' => [ < + 'plugin' => 'variable', < + 'variables' => [ < + 'site_name', < + 'site_mail', < + ], < + 'source_module' => 'system', < + ], < + 'process' => [], < + ], < + ]; < + $migrations = [ < 'test' => [ < 'id' => 'test', < 'process' => [ < 'nid' => 'nid', < ], < ], < - ]; < - $tests[0]['expected_data'] = $tests[0]['source_data']; < - < - // Test with a d6_taxonomy_vocabulary definition. < - $tests[1]['source_data'] = [ < 'd6_taxonomy_vocabulary' => [ < 'id' => 'd6_taxonomy_vocabulary', < 'process' => [ < @@ -66,116 +94,137 @@ public function providerMigrationPluginAlter() { < ], < ], < ], < - 'test' => [ < - 'id' => 'test', < + ]; < + $migrations += $system_site_migration; < + $tests[0]['modules'] = []; < + $tests[0]['type'] = NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC; < + $tests[0]['migrations'] = $migrations; < + $tests[0]['expected_data'] = $tests[0]['migrations']; < + < + $tests[1] = $tests[0]; < + $tests[1]['modules'] = ['content_translation']; < + < + $tests[2] = $tests[0]; < + $tests[2]['modules'] = []; < + $tests[2]['type'] = NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC; < + < + // Test d6_term_node and d6_term_node revisions are not altered without < + // d6_taxonomy_vocabulary. d6_term_node_translation is not changed. < + $migrations_src = [ < + 'd6_term_node:2' => [ < + 'id' => 'd6_term_node:2', < 'process' => [ < - 'nid' => 'nid', < + 'nid' => [ < + [ < + 'plugin' => 'migration_lookup', < + 'migration' => 'd6_node', < + 'source' => 'nid', < + ], < + ], < + ], < + 'destination' => [ < + 'plugin' => 'entity:node', < ], < ], < - ]; < - $tests[1]['expected_data'] = $tests[1]['source_data']; < - < - // Test with a d6_taxonomy_vocabulary and term_node definitions. < - $tests[2] = $tests[1]; < - $tests[2]['source_data']['d6_term_node:2'] = [ < - 'id' => 'd6_term_node:2', < - 'process' => [ < - 'vid' => [ < - 'plugin' => 'machine_name', < + 'd6_term_node_revision:4' => [ < + 'id' => 'd6_term_node_revision:4', < + 'process' => [ < + 'vid' => [ < + [ < + 'plugin' => 'migration_lookup', < + 'migration' => 'd6_node_revision', < + 'source' => 'vid', < + ], < + ], < ], < ], < - ]; < - $tests[2]['source_data']['d6_term_node_revision:4'] = [ < - 'id' => 'd6_term_node_revision:4', < - 'process' => [ < - 'vid' => [ < - 'plugin' => 'machine_name', < + 'd6_term_node_translation:2' => [ < + 'id' => 'd6_term_node_translation:2', < + 'process' => [ < + 'dest_nid' => [ < + [ < + 'plugin' => 'migration_lookup', < + 'migration' => 'd6_node_translation', < + 'source' => 'nid', < + ], < + ], < ], < ], < ]; < < - $tests[2]['expected_data'] = $tests[2]['source_data']; < - $tests[2]['expected_data']['d6_term_node:2']['process']['taxonomy_forums'] = 'tid'; < - $tests[2]['expected_data']['d6_term_node_revision:4']['process']['field_'] = 'tid'; < + $tests[3]['modules'] = []; < + $tests[3]['type'] = NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC; < + $tests[3]['migrations'] = $migrations_src + $system_site_migration; < + $tests[3]['expected_data'] = $tests[3]['migrations']; < < - // Test with a d6_taxonomy_vocabulary and term_node_translation definition. < - $tests[3] = $tests[1]; < - $tests[3]['source_data']['d6_term_node_translation:2'] = [ < - 'id' => 'd6_term_node_translation:2', < + // d6_term_node and d6_term_node revisions altered with < + // d6_taxonomy_vocabulary. d6_term_node_translation is not altered. < + $migrations_src['d6_taxonomy_vocabulary'] = [ < + 'id' => 'd6_taxonomy_vocabulary', < 'process' => [ < 'vid' => [ < 'plugin' => 'machine_name', < ], < ], < ]; < + $tests[4]['modules'] = []; < + $tests[4]['type'] = NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC; < + $tests[4]['migrations'] = $migrations_src + $system_site_migration; < + $tests[4]['expected_data'] = $tests[4]['migrations']; < + $tests[4]['expected_data']['d6_term_node:2']['process']['taxonomy_forums'] = 'tid'; < + $tests[4]['expected_data']['d6_term_node_revision:4']['process']['field_'] = 'tid'; < < - $tests[3]['expected_data'] = $tests[3]['source_data']; < - return $tests; < - } < + // d6_term_node and d6_term_node revisions altered with < + // d6_taxonomy_vocabulary. d6_term_node_translation is also altered < + // when content_translation is enabled. < + $tests[5]['modules'] = ['content_translation']; < + $tests[5]['type'] = NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC; < + $tests[5]['migrations'] = $migrations_src + $system_site_migration; < + $tests[5]['expected_data'] = $tests[5]['migrations']; < + $tests[5]['expected_data']['d6_term_node:2']['process']['taxonomy_forums'] = 'tid'; < + $tests[5]['expected_data']['d6_term_node_revision:4']['process']['field_'] = 'tid'; < + $tests[5]['expected_data']['d6_term_node_translation:2']['process']['taxonomy_forums'] = 'tid'; < < - /** < - * Tests migrate_drupal_migrations_plugin_alter. < - * < - * @dataProvider providerMigrationPluginAlterTranslation < - */ < - public function testMigrationPluginAlterTranslation($source, $expected) { < - /** @var \Drupal\Core\Extension\ModuleInstaller $module_installer */ < - $module_installer = \Drupal::service('module_installer'); < - $module_installer->install(['content_translation']); < - $definitions = $source; < - migrate_drupal_migration_plugins_alter($definitions); < - // Ensure the results have an 'id' key. < - foreach ($definitions as $definition) { < - $this->assertArrayHasKey('id', $definition); < - } < - $this->assertSame($expected, $definitions); < - < - } < - < - /** < - * Data provider for providerMigrationPluginAlterTranslation(). < - */ < - public function providerMigrationPluginAlterTranslation() { < - $tests = []; < - < - // Test with a d6_taxonomy_vocabulary definition and < - // d6_term_node_translation definitions. < - $tests[0]['source_data'] = [ < - 'd6_taxonomy_vocabulary' => [ < - 'id' => 'd6_taxonomy_vocabulary', < - 'process' => [ < - 'vid' => [ < - 'plugin' => 'machine_name', < - ], < - ], < - ], < - 'test' => [ < - 'id' => 'test', < - 'process' => [ < - 'nid' => 'nid', < - ], < + // Tests term node migrations when complete type migration. < + $tests[6] = $tests[2]; < + $tests[6]['modules'] = ['content_translation']; < + $tests[6]['type'] = 'complete'; < + $tests[6]['migrations'] = $migrations_src + $system_site_migration; < + $tests[6]['expected_data'] = $tests[5]['expected_data']; < + $tests[6]['expected_data']['d6_term_node:2']['process']['nid'][0] = [ < + 'plugin' => 'migration_lookup', < + 'migration' => [ < + 'd6_node_complete', < + 'd6_node', < ], < - 'd6_term_node_translation:2' => [ < - 'id' => 'd6_term_node_translation:2', < - 'process' => [ < - 'vid' => [ < - 'plugin' => 'machine_name', < - ], < - ], < + 'source' => 'nid', < + ]; < + $tests[6]['expected_data']['d6_term_node:2']['process']['nid'][2] = [ < + 'plugin' => 'node_complete_node_lookup', < + ]; < + $tests[6]['expected_data']['d6_term_node_revision:4']['process']['vid'][0] = [ < + 'plugin' => 'migration_lookup', < + 'migration' => [ < + 'd6_node_complete', < + 'd6_node_revision', < ], < - 'd6_term_node_translation:4' => [ < - 'id' => 'd6_term_node_translation:4', < - 'process' => [ < - 'vid' => [ < - 'plugin' => 'machine_name', < - ], < - ], < + 'source' => 'vid', < + ]; < + $tests[6]['expected_data']['d6_term_node_revision:4']['process']['vid'][2] = [ < + 'plugin' => 'node_complete_node_revision_lookup', < + ]; < + $tests[6]['expected_data']['d6_term_node_translation:2']['process']['dest_nid'][0] = [ < + 'plugin' => 'migration_lookup', < + 'migration' => [ < + 'd6_node_complete', < + 'd6_node_translation', < ], < + 'source' => 'nid', < + ]; < + $tests[6]['expected_data']['d6_term_node_translation:2']['process']['dest_nid'][2] = [ < + 'plugin' => 'node_complete_node_translation_lookup', < ]; < < - $tests[0]['expected_data'] = $tests[0]['source_data']; < - $tests[0]['expected_data']['d6_term_node_translation:2']['process']['taxonomy_forums'] = 'tid'; < - $tests[0]['expected_data']['d6_term_node_translation:4']['process']['field_'] = 'tid'; < return $tests; < } < < @@ -203,6 +252,12 @@ protected function setupDb() { < 'size' => 'normal', < 'default' => '0', < ], < + 'schema_version' => [ < + 'type' => 'int', < + 'not null' => TRUE, < + 'size' => 'normal', < + 'default' => '-1', < + ], < ], < ]); < $this->sourceDatabase->insert('system') < @@ -210,11 +265,19 @@ protected function setupDb() { < 'name', < 'type', < 'status', < + 'schema_version', < ]) < ->values([ < 'name' => 'taxonomy', < 'type' => 'module', < 'status' => '1', < + 'schema_version' => '6001', < + ]) < + ->values([ < + 'name' => 'system', < + 'type' => 'module', < + 'status' => '1', < + 'schema_version' => '6056', < ]) < ->execute(); < 32254c31737 < index ba16905e72..616ffd896e 100644 --- > index 0e5d21b266..b093336561 100644 32290,32291c31773,31774 < - 'language_content_settings' => 18, < + 'language_content_settings' => 17, --- > - 'language_content_settings' => 24, > + 'language_content_settings' => 23, 32296c31779 < 'menu' => 6, --- > 'menu' => 7, 32312c31795 < @@ -189,7 +207,6 @@ protected function getMissingPaths() { --- > @@ -190,7 +208,6 @@ protected function getMissingPaths() { 32437a31921,32100 > diff --git a/core/modules/node/node.module b/core/modules/node/node.module > index 4899ddce67..b0cc472e51 100644 > --- a/core/modules/node/node.module > +++ b/core/modules/node/node.module > @@ -26,6 +26,7 @@ > use Drupal\field\Entity\FieldConfig; > use Drupal\field\Entity\FieldStorageConfig; > use Drupal\language\ConfigurableLanguageInterface; > +use Drupal\migrate_drupal\NodeMigrateType; > use Drupal\node\Entity\Node; > use Drupal\node\Entity\NodeType; > use Drupal\node\NodeInterface; > @@ -1461,3 +1462,167 @@ function node_comment_delete($comment) { > function node_config_translation_info_alter(&$info) { > $info['node_type']['class'] = 'Drupal\node\ConfigTranslation\NodeTypeMapper'; > } > + > +/** > + * Implements hook_migration_plugins_alter(). > + */ > +function node_migration_plugins_alter(array &$definitions) { > + // If the complete node migrate_map tables have data then the any migration > + // use a node migration in a migration_lookup needs to be altered to use > + // both the classic and complete node migration. > + if ((new NodeMigrateType)->getNodeMigrateType($definitions, NULL) !== NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC) { > + > + // Anonymous function to replace classic node migration plugin IDs with the > + // complete plugin ID. > + $replace_with_complete_migration = function (&$value) { > + if (is_string($value)) { > + $value = preg_replace('/d([67])_(node|node_translation|node_revision)($|:.*)/', 'd$1_node_complete$3', $value); > + } > + return $value; > + }; > + // Alter references to the classic node migration to the complete node > + // migration in all relevant core migrations. The references altered are > + // those in migration_dependencies and in the process pipeline. In the > + // process pipeline we are concerned with references to classic node > + // migrations in a migration_lookup process. > + // > + // The process pipeline is altered so that the migration_lookup returns > + // the correct IDs. For example, the classic d6_node_revision migration > + // has a single ID, the revision ID, but the d6_node_complete has three IDs, > + // the node ID, the revision ID and the language. To ensure the pipeline > + // works for both migrations we need to insert a process to return only > + // the revision ID if the complete node migration was used. > + // > + // Example: d6_term_node_revision > + // > + // Before > + // vid: > + // - > + // plugin: migration_lookup > + // migration: d6_node_revision > + // source: vid > + // - > + // plugin: skip_on_empty > + // method: row > + // After > + // vid: > + // - > + // plugin: migration_lookup > + // migration: > + // - d6_node_revision > + // - d6_node_complete > + // source: vid > + // - > + // plugin: skip_on_empty > + // method: row > + // - > + // plugin: node_complete_node_lookup > + // > + // The classic node migrations are not altered. > + // > + // See \Drupal\migrate_drupal\Plugin\migrate\process\NodeCompleteNodeLookup > + // See \Drupal\migrate_drupal\Plugin\migrate\process\NodeCompleteNodeRevisionLookup > + // See \Drupal\migrate_drupal\Plugin\migrate\process\NodeCompleteNodeTranslationLookup > + foreach ($definitions as &$definition) { > + $is_node_classic_migration = preg_match('/d([67])_(node|node_translation|node_revision)($|:.*)/', $definition['id']); > + if (!$is_node_classic_migration && isset($definition['migration_dependencies'])) { > + array_walk_recursive($definition['migration_dependencies'], $replace_with_complete_migration); > + } > + > + // Alter the migration_lookup process so the node ID is returned. > + if (preg_match('/d6_term_node($|:.*)/', $definition['id'])) { > + $tmp = $definition['process']['nid'][0]['migration']; > + $definition['process']['nid'][0]['migration'] = _insert_migration($tmp); > + $definition['process']['nid'][2] = [ > + 'plugin' => 'node_complete_node_lookup', > + ]; > + } > + // Alter the migration_lookup process so the revision ID is returned. > + if (preg_match('/d6_term_node_revision($|:.*)/', $definition['id'])) { > + $tmp = $definition['process']['vid'][0]['migration']; > + $definition['process']['vid'][0]['migration'] = _insert_migration($tmp); > + $definition['process']['vid'][2] = [ > + 'plugin' => 'node_complete_node_revision_lookup', > + ]; > + } > + // Alter the migration_lookup process so the node ID and langcode are > + // returned. > + if (preg_match('/d6_term_node_translation($|:.*)/', $definition['id'])) { > + $tmp = $definition['process']['dest_nid'][0]['migration']; > + $definition['process']['dest_nid'][0]['migration'] = _insert_migration($tmp); > + $definition['process']['dest_nid'][2] = [ > + 'plugin' => 'node_complete_node_translation_lookup', > + ]; > + } > + } > + > + // Alter the migration_lookup process so the node ID is returned. > + if (isset($definitions['d6_comment'])) { > + $tmp = $definitions['d6_comment']['process']['entity_id'][0]['migration']; > + $definitions['d6_comment']['process']['entity_id'][0]['migration'] = _insert_migration($tmp); > + $definitions['d6_comment']['process']['entity_id'][2] = [ > + 'plugin' => 'node_complete_node_lookup', > + ]; > + } > + // Alter the migration_lookup process so the node ID and langcode are > + // returned. > + if (isset($definitions['d6_url_alias'])) { > + $tmp = $definitions['d6_url_alias']['process']['node_translation'][2]['migration']; > + $definitions['d6_url_alias']['process']['node_translation'][2]['migration'] = _insert_migration($tmp); > + $definitions['d6_url_alias']['process']['node_translation'][3] = [ > + 'plugin' => 'node_complete_node_translation_lookup', > + ]; > + } > + // Alter the migration_lookup process so the node ID is returned. > + if (isset($definitions['d7_comment'])) { > + $tmp = $definitions['d7_comment']['process']['entity_id'][0]['migration']; > + $definitions['d7_comment']['process']['entity_id'][0]['migration'] = _insert_migration($tmp); > + $definitions['d7_comment']['process']['entity_id'][2] = [ > + 'plugin' => 'node_complete_node_lookup', > + ]; > + } > + // Alter the migration_lookup process so the node ID and langcode are > + // returned. > + if (isset($definitions['d7_url_alias'])) { > + $tmp = $definitions['d7_url_alias']['process']['node_translation'][2]['migration']; > + $definitions['d7_url_alias']['process']['node_translation'][2]['migration'] = _insert_migration($tmp); > + $definitions['d7_url_alias']['process']['node_translation'][3] = [ > + 'plugin' => 'node_complete_node_translation_lookup', > + ]; > + } > + // Alter the migration_lookup process so the node ID is returned. > + if (isset($definitions['statistics_node_counter'])) { > + $tmp = $definitions['statistics_node_counter']['process']['nid'][0]['migration']; > + $definitions['statistics_node_counter']['process']['nid'][0]['migration'] = _insert_migration($tmp); > + $definitions['statistics_node_counter']['process']['nid'][2] = [ > + 'plugin' => 'node_complete_node_lookup', > + ]; > + } > + // Alter the migration_lookup process to include the complete node migration. > + // A node_complete_node*_lookup process is not needed because the > + // migration_lookup is followed by an extract process which will get the > + // node ID. > + if (isset($definitions['node_translation_menu_links'])) { > + $tmp = $definitions['node_translation_menu_links']['process']['new_nid'][4]['migration']; > + $definitions['node_translation_menu_links']['process']['new_nid'][4]['migration'] = _insert_migration($tmp); > + } > + } > +} > + > +/** > + * Add dN_node_complete to the migrations array of a migration_lookup plugin. > + * > + * @internal > + * Only to be used by node_migration_plugins_alter(). > + */ > +function _insert_migration($migrations) { > + if (!is_array($migrations)) { > + $migrations = [$migrations]; > + } > + $new_migration_list = []; > + foreach ($migrations as $migration) { > + $tmp = substr($migration, 0, 2) . '_node_complete'; > + array_unshift($new_migration_list, $tmp, $migration); > + } > + return array_unique($new_migration_list); > +} 32495c32158 < index 0000000000..679d23b3c8 --- > index 0000000000..c6a3fb4fd2 32498c32161 < @@ -0,0 +1,114 @@ --- > @@ -0,0 +1,115 @@ 32525a32189 > + $query->orderBy('nr.vid'); 35689a35354,35721 > > diff --git a/core/modules/migrate_drupal/tests/src/Kernel/MigrationPluginAlterTest.php b/core/modules/node/tests/src/Kernel/MigrationPluginAlterTest.php > similarity index 50% > rename from core/modules/migrate_drupal/tests/src/Kernel/MigrationPluginAlterTest.php > rename to core/modules/node/tests/src/Kernel/MigrationPluginAlterTest.php > index 335c44cab7..d4cd7b6b25 100644 > --- a/core/modules/migrate_drupal/tests/src/Kernel/MigrationPluginAlterTest.php > +++ b/core/modules/node/tests/src/Kernel/MigrationPluginAlterTest.php > @@ -1,20 +1,27 @@ > > -namespace Drupal\Tests\migrate_drupal\Kernel; > +namespace Drupal\Tests\node\Kernel; > > +use Drupal\migrate_drupal\NodeMigrateType; > use Drupal\Tests\migrate\Kernel\MigrateTestBase; > +use Drupal\Tests\migrate_drupal\Traits\NodeMigrateTypeTestTrait; > > /** > - * Tests migrate_drupal_migrations_plugin_alter for d6 term node migrations. > +<<<<<<< HEAD:core/modules/node/tests/src/Kernel/MigrationPluginAlterTest.php > + * Tests node_migrations_plugin_alter. > +======= > + * Tests migrate_drupal_migrations_plugin_alter. > +>>>>>>> a:core/modules/migrate_drupal/tests/src/Kernel/MigrationPluginAlterTest.php > * > - * @group migrate_drupal > + * @group node > */ > class MigrationPluginAlterTest extends MigrateTestBase { > > + use NodeMigrateTypeTestTrait; > /** > * {@inheritdoc} > */ > - public static $modules = ['migrate_drupal', 'taxonomy']; > + public static $modules = ['migrate_drupal', 'node', 'taxonomy']; > > /** > * {@inheritdoc} > @@ -25,13 +32,30 @@ protected function setUp() { > } > > /** > - * Tests migrate_drupal_migrations_plugin_alter without content_translation. > + * Tests migrate_drupal_migrations_plugin_alter. > + * > + * @param array $modules > + * An array of modules to install. > + * @param string $type > + * The type of node migration, 'classic' or 'complete'. > + * @param array $migration_definitions > + * An array of migration definitions. > + * @param array $expected > + * The expected results. > * > * @dataProvider providerMigrationPluginAlter > + * > + * @throws \Drupal\Core\Extension\MissingDependencyException > */ > - public function testMigrationPluginAlterNoTranslation($source, $expected) { > - $definitions = $source; > + public function testMigrationPluginAlter(array $modules, $type, array $migration_definitions, array $expected) { > + /** @var \Drupal\Core\Extension\ModuleInstaller $module_installer */ > + $module_installer = \Drupal::service('module_installer'); > + $module_installer->install($modules); > + // Version 6 is used so that term node migrations are tested. > + $this->makeNodeMigrateMapTable($type, '6'); > + $definitions = $migration_definitions; > migrate_drupal_migration_plugins_alter($definitions); > + node_migration_plugins_alter($definitions); > // Ensure the results have an 'id' key. > foreach ($definitions as $definition) { > $this->assertArrayHasKey('id', $definition); > @@ -45,19 +69,29 @@ public function testMigrationPluginAlterNoTranslation($source, $expected) { > public function providerMigrationPluginAlter() { > $tests = []; > > - // Test without a d6_taxonomy_vocabulary definition. > - $tests[0]['source_data'] = [ > + // Tests migrations that should never be altered, once without an extra > + // module installed and then with content_translation installed. > + $system_site_migration = [ > + 'system_site' => [ > + 'id' => 'system_site', > + 'source' => [ > + 'plugin' => 'variable', > + 'variables' => [ > + 'site_name', > + 'site_mail', > + ], > + 'source_module' => 'system', > + ], > + 'process' => [], > + ], > + ]; > + $migrations = [ > 'test' => [ > 'id' => 'test', > 'process' => [ > 'nid' => 'nid', > ], > ], > - ]; > - $tests[0]['expected_data'] = $tests[0]['source_data']; > - > - // Test with a d6_taxonomy_vocabulary definition. > - $tests[1]['source_data'] = [ > 'd6_taxonomy_vocabulary' => [ > 'id' => 'd6_taxonomy_vocabulary', > 'process' => [ > @@ -66,116 +100,137 @@ public function providerMigrationPluginAlter() { > ], > ], > ], > - 'test' => [ > - 'id' => 'test', > + ]; > + $migrations += $system_site_migration; > + $tests[0]['modules'] = []; > + $tests[0]['type'] = NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC; > + $tests[0]['migrations'] = $migrations; > + $tests[0]['expected_data'] = $tests[0]['migrations']; > + > + $tests[1] = $tests[0]; > + $tests[1]['modules'] = ['content_translation']; > + > + $tests[2] = $tests[0]; > + $tests[2]['modules'] = []; > + $tests[2]['type'] = NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC; > + > + // Test d6_term_node and d6_term_node revisions are not altered without > + // d6_taxonomy_vocabulary. d6_term_node_translation is not changed. > + $migrations_src = [ > + 'd6_term_node:2' => [ > + 'id' => 'd6_term_node:2', > 'process' => [ > - 'nid' => 'nid', > + 'nid' => [ > + [ > + 'plugin' => 'migration_lookup', > + 'migration' => 'd6_node', > + 'source' => 'nid', > + ], > + ], > + ], > + 'destination' => [ > + 'plugin' => 'entity:node', > ], > ], > - ]; > - $tests[1]['expected_data'] = $tests[1]['source_data']; > - > - // Test with a d6_taxonomy_vocabulary and term_node definitions. > - $tests[2] = $tests[1]; > - $tests[2]['source_data']['d6_term_node:2'] = [ > - 'id' => 'd6_term_node:2', > - 'process' => [ > - 'vid' => [ > - 'plugin' => 'machine_name', > + 'd6_term_node_revision:4' => [ > + 'id' => 'd6_term_node_revision:4', > + 'process' => [ > + 'vid' => [ > + [ > + 'plugin' => 'migration_lookup', > + 'migration' => 'd6_node_revision', > + 'source' => 'vid', > + ], > + ], > ], > ], > - ]; > - $tests[2]['source_data']['d6_term_node_revision:4'] = [ > - 'id' => 'd6_term_node_revision:4', > - 'process' => [ > - 'vid' => [ > - 'plugin' => 'machine_name', > + 'd6_term_node_translation:2' => [ > + 'id' => 'd6_term_node_translation:2', > + 'process' => [ > + 'dest_nid' => [ > + [ > + 'plugin' => 'migration_lookup', > + 'migration' => 'd6_node_translation', > + 'source' => 'nid', > + ], > + ], > ], > ], > ]; > > - $tests[2]['expected_data'] = $tests[2]['source_data']; > - $tests[2]['expected_data']['d6_term_node:2']['process']['taxonomy_forums'] = 'tid'; > - $tests[2]['expected_data']['d6_term_node_revision:4']['process']['field_'] = 'tid'; > + $tests[3]['modules'] = []; > + $tests[3]['type'] = NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC; > + $tests[3]['migrations'] = $migrations_src + $system_site_migration; > + $tests[3]['expected_data'] = $tests[3]['migrations']; > > - // Test with a d6_taxonomy_vocabulary and term_node_translation definition. > - $tests[3] = $tests[1]; > - $tests[3]['source_data']['d6_term_node_translation:2'] = [ > - 'id' => 'd6_term_node_translation:2', > + // d6_term_node and d6_term_node revisions altered with > + // d6_taxonomy_vocabulary. d6_term_node_translation is not altered. > + $migrations_src['d6_taxonomy_vocabulary'] = [ > + 'id' => 'd6_taxonomy_vocabulary', > 'process' => [ > 'vid' => [ > 'plugin' => 'machine_name', > ], > ], > ]; > + $tests[4]['modules'] = []; > + $tests[4]['type'] = NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC; > + $tests[4]['migrations'] = $migrations_src + $system_site_migration; > + $tests[4]['expected_data'] = $tests[4]['migrations']; > + $tests[4]['expected_data']['d6_term_node:2']['process']['taxonomy_forums'] = 'tid'; > + $tests[4]['expected_data']['d6_term_node_revision:4']['process']['field_'] = 'tid'; > > - $tests[3]['expected_data'] = $tests[3]['source_data']; > - return $tests; > - } > + // d6_term_node and d6_term_node revisions altered with > + // d6_taxonomy_vocabulary. d6_term_node_translation is also altered > + // when content_translation is enabled. > + $tests[5]['modules'] = ['content_translation']; > + $tests[5]['type'] = NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC; > + $tests[5]['migrations'] = $migrations_src + $system_site_migration; > + $tests[5]['expected_data'] = $tests[5]['migrations']; > + $tests[5]['expected_data']['d6_term_node:2']['process']['taxonomy_forums'] = 'tid'; > + $tests[5]['expected_data']['d6_term_node_revision:4']['process']['field_'] = 'tid'; > + $tests[5]['expected_data']['d6_term_node_translation:2']['process']['taxonomy_forums'] = 'tid'; > > - /** > - * Tests migrate_drupal_migrations_plugin_alter. > - * > - * @dataProvider providerMigrationPluginAlterTranslation > - */ > - public function testMigrationPluginAlterTranslation($source, $expected) { > - /** @var \Drupal\Core\Extension\ModuleInstaller $module_installer */ > - $module_installer = \Drupal::service('module_installer'); > - $module_installer->install(['content_translation']); > - $definitions = $source; > - migrate_drupal_migration_plugins_alter($definitions); > - // Ensure the results have an 'id' key. > - foreach ($definitions as $definition) { > - $this->assertArrayHasKey('id', $definition); > - } > - $this->assertSame($expected, $definitions); > - > - } > - > - /** > - * Data provider for providerMigrationPluginAlterTranslation(). > - */ > - public function providerMigrationPluginAlterTranslation() { > - $tests = []; > - > - // Test with a d6_taxonomy_vocabulary definition and > - // d6_term_node_translation definitions. > - $tests[0]['source_data'] = [ > - 'd6_taxonomy_vocabulary' => [ > - 'id' => 'd6_taxonomy_vocabulary', > - 'process' => [ > - 'vid' => [ > - 'plugin' => 'machine_name', > - ], > - ], > - ], > - 'test' => [ > - 'id' => 'test', > - 'process' => [ > - 'nid' => 'nid', > - ], > + // Tests term node migrations when complete type migration. > + $tests[6] = $tests[2]; > + $tests[6]['modules'] = ['content_translation']; > + $tests[6]['type'] = 'complete'; > + $tests[6]['migrations'] = $migrations_src + $system_site_migration; > + $tests[6]['expected_data'] = $tests[5]['expected_data']; > + $tests[6]['expected_data']['d6_term_node:2']['process']['nid'][0] = [ > + 'plugin' => 'migration_lookup', > + 'migration' => [ > + 'd6_node_complete', > + 'd6_node', > ], > - 'd6_term_node_translation:2' => [ > - 'id' => 'd6_term_node_translation:2', > - 'process' => [ > - 'vid' => [ > - 'plugin' => 'machine_name', > - ], > - ], > + 'source' => 'nid', > + ]; > + $tests[6]['expected_data']['d6_term_node:2']['process']['nid'][2] = [ > + 'plugin' => 'node_complete_node_lookup', > + ]; > + $tests[6]['expected_data']['d6_term_node_revision:4']['process']['vid'][0] = [ > + 'plugin' => 'migration_lookup', > + 'migration' => [ > + 'd6_node_complete', > + 'd6_node_revision', > ], > - 'd6_term_node_translation:4' => [ > - 'id' => 'd6_term_node_translation:4', > - 'process' => [ > - 'vid' => [ > - 'plugin' => 'machine_name', > - ], > - ], > + 'source' => 'vid', > + ]; > + $tests[6]['expected_data']['d6_term_node_revision:4']['process']['vid'][2] = [ > + 'plugin' => 'node_complete_node_revision_lookup', > + ]; > + $tests[6]['expected_data']['d6_term_node_translation:2']['process']['dest_nid'][0] = [ > + 'plugin' => 'migration_lookup', > + 'migration' => [ > + 'd6_node_complete', > + 'd6_node_translation', > ], > + 'source' => 'nid', > + ]; > + $tests[6]['expected_data']['d6_term_node_translation:2']['process']['dest_nid'][2] = [ > + 'plugin' => 'node_complete_node_translation_lookup', > ]; > > - $tests[0]['expected_data'] = $tests[0]['source_data']; > - $tests[0]['expected_data']['d6_term_node_translation:2']['process']['taxonomy_forums'] = 'tid'; > - $tests[0]['expected_data']['d6_term_node_translation:4']['process']['field_'] = 'tid'; > return $tests; > } > > @@ -203,6 +258,12 @@ protected function setupDb() { > 'size' => 'normal', > 'default' => '0', > ], > + 'schema_version' => [ > + 'type' => 'int', > + 'not null' => TRUE, > + 'size' => 'normal', > + 'default' => '-1', > + ], > ], > ]); > $this->sourceDatabase->insert('system') > @@ -210,11 +271,19 @@ protected function setupDb() { > 'name', > 'type', > 'status', > + 'schema_version', > ]) > ->values([ > 'name' => 'taxonomy', > 'type' => 'module', > 'status' => '1', > + 'schema_version' => '6001', > + ]) > + ->values([ > + 'name' => 'system', > + 'type' => 'module', > + 'status' => '1', > + 'schema_version' => '6056', > ]) > ->execute();