diff --git a/core/modules/action/action.migrate_drupal.yml b/core/modules/action/action.migrate_drupal.yml new file mode 100644 index 0000000000..b513752a62 --- /dev/null +++ b/core/modules/action/action.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + system: action + 7: + system: action diff --git a/core/modules/action/migrations/action_settings.yml b/core/modules/action/migrations/action_settings.yml index 4d332f801d..ae97dc607e 100644 --- a/core/modules/action/migrations/action_settings.yml +++ b/core/modules/action/migrations/action_settings.yml @@ -8,7 +8,7 @@ source: plugin: variable variables: - actions_max_stack - source_module: action + source_module: system process: recursion_limit: actions_max_stack destination: diff --git a/core/modules/aggregator/aggregator.migrate_drupal.yml b/core/modules/aggregator/aggregator.migrate_drupal.yml new file mode 100644 index 0000000000..fe63da70bf --- /dev/null +++ b/core/modules/aggregator/aggregator.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + aggregator: aggregator + 7: + aggregator: aggregator diff --git a/core/modules/ban/ban.migrate_drupal.yml b/core/modules/ban/ban.migrate_drupal.yml new file mode 100644 index 0000000000..34231fdd2d --- /dev/null +++ b/core/modules/ban/ban.migrate_drupal.yml @@ -0,0 +1,3 @@ +finished: + 7: + system: ban diff --git a/core/modules/block/block.migrate_drupal.yml b/core/modules/block/block.migrate_drupal.yml new file mode 100644 index 0000000000..74cdfc7191 --- /dev/null +++ b/core/modules/block/block.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + block: block + 7: + block: block diff --git a/core/modules/block_content/block_content.migrate_drupal.yml b/core/modules/block_content/block_content.migrate_drupal.yml new file mode 100644 index 0000000000..88391eed00 --- /dev/null +++ b/core/modules/block_content/block_content.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + block: block_content + 7: + block: block_content diff --git a/core/modules/block_content/src/Plugin/migrate/source/d7/BlockCustomTranslation.php b/core/modules/block_content/src/Plugin/migrate/source/d7/BlockCustomTranslation.php index 6115e12c61..6702ee14d1 100644 --- a/core/modules/block_content/src/Plugin/migrate/source/d7/BlockCustomTranslation.php +++ b/core/modules/block_content/src/Plugin/migrate/source/d7/BlockCustomTranslation.php @@ -11,7 +11,7 @@ * * @MigrateSource( * id = "d7_block_custom_translation", - * source_module = "block" + * source_module = "i18n_block" * ) */ class BlockCustomTranslation extends DrupalSqlBase { diff --git a/core/modules/book/book.migrate_drupal.yml b/core/modules/book/book.migrate_drupal.yml new file mode 100644 index 0000000000..c47d1e973f --- /dev/null +++ b/core/modules/book/book.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + book: book + 7: + book: book diff --git a/core/modules/color/color.migrate_drupal.yml b/core/modules/color/color.migrate_drupal.yml new file mode 100644 index 0000000000..60e95b99eb --- /dev/null +++ b/core/modules/color/color.migrate_drupal.yml @@ -0,0 +1,3 @@ +finished: + 7: + color: color diff --git a/core/modules/comment/comment.migrate_drupal.yml b/core/modules/comment/comment.migrate_drupal.yml new file mode 100644 index 0000000000..51dc1a0290 --- /dev/null +++ b/core/modules/comment/comment.migrate_drupal.yml @@ -0,0 +1,7 @@ +finished: + 6: + comment: comment + node: comment + 7: + comment: comment + node: comment diff --git a/core/modules/config_translation/config_translation.migrate_drupal.yml b/core/modules/config_translation/config_translation.migrate_drupal.yml new file mode 100644 index 0000000000..ac84a71873 --- /dev/null +++ b/core/modules/config_translation/config_translation.migrate_drupal.yml @@ -0,0 +1,28 @@ +finished: + 6: + i18nprofile: config_translation + 7: + i18n_variable: config_translation +not_finished: + 6: + # language content comment settings. + locale: language + # @TODO: Move to finished when remaining Drupal 6 i18n issues are resolved. + # See https://www.drupal.org/project/drupal/issues/2208401 + i18n: config_translation + # field labels and descriptions, synchronized fields. + i18ncck: config_translation + # Block, menu, taxonomy, User profiles. + i18nstrings: config_translation + i18ntaxonomy: config_translation + 7: + # language content comment settings. + locale: language + # @TODO: Move to finished when remaining Drupal 7 i18n issues are resolved. + # See https://www.drupal.org/project/drupal/issues/2208401 + i18n: config_translation + # field labels and descriptions, field options. + i18n_field: config_translation + i18n_string: config_translation + # localized. vocabulary language settings, taxonomy term language. + i18n_taxonomy: config_tanslation diff --git a/core/modules/contact/contact.migrate_drupal.yml b/core/modules/contact/contact.migrate_drupal.yml new file mode 100644 index 0000000000..6b186b4299 --- /dev/null +++ b/core/modules/contact/contact.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + contact: contact + 7: + contact: contact diff --git a/core/modules/content_translation/content_translation.migrate_drupal.yml b/core/modules/content_translation/content_translation.migrate_drupal.yml new file mode 100644 index 0000000000..fe20deea89 --- /dev/null +++ b/core/modules/content_translation/content_translation.migrate_drupal.yml @@ -0,0 +1,28 @@ +finished: + 6: + i18nblocks: content_translation + i18nmenu: content_translation + menu: content_translation + statistics: statistics + taxonomy: content_translation + 7: + entity_translation: content_translation + i18n_block: content_translation + menu: content_translation + statistics: statistics +not_finished: + # Also D6 an D7 node revision translations. + 6: + # @TODO: Move to finished when remaining Drupal 6 i18n issues are resolved. + # See https://www.drupal.org/project/drupal/issues/2208401 + i18n: content_translation + # Taxonomy term references. + i18ntaxonomy: content_translation + 7: + # @TODO: Move to finished when remaining Drupal 7 i18n issues are resolved. + # See https://www.drupal.org/project/drupal/issues/2208401 + i18n: content_translation + # menu links. + i18n_menu: content_translation + # localized. + i18n_taxonomy: content_translation diff --git a/core/modules/datetime/datetime.migrate_drupal.yml b/core/modules/datetime/datetime.migrate_drupal.yml new file mode 100644 index 0000000000..a4434b627e --- /dev/null +++ b/core/modules/datetime/datetime.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + date: datetime + 7: + date: datetime diff --git a/core/modules/dblog/dblog.migrate_drupal.yml b/core/modules/dblog/dblog.migrate_drupal.yml new file mode 100644 index 0000000000..b048ff1920 --- /dev/null +++ b/core/modules/dblog/dblog.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + dblog: dblog + 7: + dblog: dblog diff --git a/core/modules/field/field.migrate_drupal.yml b/core/modules/field/field.migrate_drupal.yml new file mode 100644 index 0000000000..53c6eb61e2 --- /dev/null +++ b/core/modules/field/field.migrate_drupal.yml @@ -0,0 +1,12 @@ +finished: + 6: + content: field + email: core + # Phone does not use a migrate field plugin so it is added here. + phone: field + 7: + email: core + entityreference: core + field: field + field_sql_storage: field + number: core diff --git a/core/modules/field/migrations/d6_field.yml b/core/modules/field/migrations/d6_field.yml index e25d7ae0c2..2c64f21ea0 100644 --- a/core/modules/field/migrations/d6_field.yml +++ b/core/modules/field/migrations/d6_field.yml @@ -10,6 +10,8 @@ source: constants: entity_type: node langcode: en + # Phone is here since it does not use a migrate field plugin. + source_module: phone process: entity_type: 'constants/entity_type' status: active diff --git a/core/modules/file/file.migrate_drupal.yml b/core/modules/file/file.migrate_drupal.yml new file mode 100644 index 0000000000..cfee09a25c --- /dev/null +++ b/core/modules/file/file.migrate_drupal.yml @@ -0,0 +1,8 @@ +finished: + 6: + filefield: file + system: file + upload: file + 7: + file: file + system: file diff --git a/core/modules/filter/filter.migrate_drupal.yml b/core/modules/filter/filter.migrate_drupal.yml new file mode 100644 index 0000000000..fa671e830d --- /dev/null +++ b/core/modules/filter/filter.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + filter: filter + 7: + filter: filter diff --git a/core/modules/forum/forum.migrate_drupal.yml b/core/modules/forum/forum.migrate_drupal.yml new file mode 100644 index 0000000000..5b91754541 --- /dev/null +++ b/core/modules/forum/forum.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + forum: forum + 7: + forum: forum diff --git a/core/modules/image/image.migrate_drupal.yml b/core/modules/image/image.migrate_drupal.yml new file mode 100644 index 0000000000..b87b9c7b1a --- /dev/null +++ b/core/modules/image/image.migrate_drupal.yml @@ -0,0 +1,6 @@ +finished: + 6: + imagecache: image + imagefield: image + 7: + image: image diff --git a/core/modules/language/language.migrate_drupal.yml b/core/modules/language/language.migrate_drupal.yml new file mode 100644 index 0000000000..25ac491a22 --- /dev/null +++ b/core/modules/language/language.migrate_drupal.yml @@ -0,0 +1,11 @@ +finished: + 6: + locale: + - language + - system + system: language + taxonomy: language + 7: + locale: + - language + - system diff --git a/core/modules/language/migrations/d6_language_negotiation_settings.yml b/core/modules/language/migrations/d6_language_negotiation_settings.yml index a4ae19b87d..e6bf27424b 100644 --- a/core/modules/language/migrations/d6_language_negotiation_settings.yml +++ b/core/modules/language/migrations/d6_language_negotiation_settings.yml @@ -7,7 +7,7 @@ source: plugin: variable variables: - language_negotiation - source_module: language + source_module: locale process: session/parameter: plugin: default_value diff --git a/core/modules/language/migrations/d6_language_types.yml b/core/modules/language/migrations/d6_language_types.yml index 5c54fc6fb9..47d62caf6b 100644 --- a/core/modules/language/migrations/d6_language_types.yml +++ b/core/modules/language/migrations/d6_language_types.yml @@ -7,7 +7,7 @@ source: plugin: variable variables: - language_negotiation - source_module: language + source_module: locale process: all: plugin: default_value diff --git a/core/modules/language/migrations/d7_language_types.yml b/core/modules/language/migrations/d7_language_types.yml index 017f2e2d6f..33df3cf0dc 100644 --- a/core/modules/language/migrations/d7_language_types.yml +++ b/core/modules/language/migrations/d7_language_types.yml @@ -13,7 +13,7 @@ source: - locale_language_providers_weight_language - locale_language_providers_weight_language_content - locale_language_providers_weight_language_url - source_module: language + source_module: locale process: all: plugin: language_types diff --git a/core/modules/link/link.migrate_drupal.yml b/core/modules/link/link.migrate_drupal.yml new file mode 100644 index 0000000000..4352ab4c76 --- /dev/null +++ b/core/modules/link/link.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + link: link + 7: + link: link diff --git a/core/modules/locale/locale.migrate_drupal.yml b/core/modules/locale/locale.migrate_drupal.yml new file mode 100644 index 0000000000..5d4e806b80 --- /dev/null +++ b/core/modules/locale/locale.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + locale: locale + 7: + locale: locale diff --git a/core/modules/menu_link_content/menu_link_content.migrate_drupal.yml b/core/modules/menu_link_content/menu_link_content.migrate_drupal.yml new file mode 100644 index 0000000000..c7111dc53e --- /dev/null +++ b/core/modules/menu_link_content/menu_link_content.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + menu: menu_link_content + 7: + menu: menu_link_content diff --git a/core/modules/menu_ui/menu_ui.migrate_drupal.yml b/core/modules/menu_ui/menu_ui.migrate_drupal.yml new file mode 100644 index 0000000000..55597fecfe --- /dev/null +++ b/core/modules/menu_ui/menu_ui.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + menu: menu_ui + 7: + menu: menu_ui diff --git a/core/modules/migrate/tests/src/Kernel/MigrateStatusTest.php b/core/modules/migrate/tests/src/Kernel/MigrateStatusTest.php index 7dc0b5b9b6..df9e770305 100644 --- a/core/modules/migrate/tests/src/Kernel/MigrateStatusTest.php +++ b/core/modules/migrate/tests/src/Kernel/MigrateStatusTest.php @@ -17,7 +17,7 @@ class MigrateStatusTest extends MigrateTestBase { public function testStatus() { // Create a minimally valid migration. $definition = [ - 'id' => 'migration_status_test', + 'id' => 'migrate_status_test', 'migration_tags' => ['Testing'], 'source' => ['plugin' => 'empty'], 'destination' => [ diff --git a/core/modules/migrate_drupal/migrate_drupal.migrate_drupal.yml b/core/modules/migrate_drupal/migrate_drupal.migrate_drupal.yml new file mode 100644 index 0000000000..db703dc95d --- /dev/null +++ b/core/modules/migrate_drupal/migrate_drupal.migrate_drupal.yml @@ -0,0 +1,4 @@ +finished: + 6: + nodereference: core + userreference: core diff --git a/core/modules/migrate_drupal/migrate_drupal.services.yml b/core/modules/migrate_drupal/migrate_drupal.services.yml index 7594b465fe..77a8b59dfd 100644 --- a/core/modules/migrate_drupal/migrate_drupal.services.yml +++ b/core/modules/migrate_drupal/migrate_drupal.services.yml @@ -25,3 +25,6 @@ services: - '@plugin.manager.migrate.field' - '@plugin.manager.migration' - '@logger.channel.migrate_drupal' + migrate_drupal.migration_state: + class: Drupal\migrate_drupal\MigrationState + arguments: ['@plugin.manager.migrate.field', '@module_handler', '@messenger', '@string_translation'] diff --git a/core/modules/migrate_drupal/src/MigrationState.php b/core/modules/migrate_drupal/src/MigrationState.php new file mode 100644 index 0000000000..df1cbe76aa --- /dev/null +++ b/core/modules/migrate_drupal/src/MigrationState.php @@ -0,0 +1,600 @@ +.migrate_drupal.yml file. + * + * The .migrate_drupal.yml file uses the following structure: + * + * # (optional) List of the source_module/destination_module(s) for the + * # migration sets that this module provides and are complete. + * finished: + * # One or more Drupal legacy version number mappings (i.e. 6 and/or 7). + * 6: + * # A mapping of legacy module machine names to either an array of modules + * # or a single destination module machine name to define this migration + * # set. + * : + * : + * - + * - + * 7: + * : + * : + * - + * - + * # (optional) List of the migration sets that this module provides, or will be + * # providing, that are incomplete or do not yet exist. + * not_finished: + * 6: + * : + * : + * - + * - + * + * Examples: + * + * @code + * finished: + * 6: + * node: node + * 7: + * node: node + * entity_translation: node + * not_finished: + * 7: + * commerce_product: commerce_product + * other_module: + * - other_module + * - further_module + * @endcode + * + * In this example the module has completed the upgrade path for data from the + * Drupal 6 and Drupal 7 Node modules to the Drupal 8 Node module and for data + * from the Drupal 7 Entity Translation module to the Drupal 8 Node module. + * + * @code + * finished: + * 6: + * pirate: pirate + * 7: + * pirate: pirate + * @endcode + * + * The Pirate module does not require an upgrade path. By declaring the upgrade + * finished the Pirate module will be included in the finished list. That is, + * as long as no other module has an entry "pirate: ' in its + * not_finished section. + */ +class MigrationState { + + use MessengerTrait; + use StringTranslationTrait; + + /** + * Source module upgrade state when all its migrations are complete. + * + * @var string + */ + const FINISHED = 'finished'; + + /** + * Source module upgrade state when all its migrations are not complete. + * + * @var string + */ + const NOT_FINISHED = 'not_finished'; + + /** + * The field plugin manager service. + * + * @var \Drupal\Core\Extension\ModuleHandler + */ + protected $moduleHandler; + + /** + * The field plugin manager service. + * + * @var \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface + */ + protected $fieldPluginManager; + + /** + * Source modules that will not be migrated determined using legacy method. + * + * @var array + */ + protected $unmigratedSourceModules = []; + + /** + * Source modules that will be migrated determined using legacy method, keyed + * by version. + * + * @var array + */ + protected $migratedSourceModules = []; + + /** + * An array of migration states declared for each source migration. + * + * States are keyed by version. Each value is an array keyed by name of the + * source module and the value is an array of all the states declared for this + * source module. + * + * @var array + */ + protected $stateBySource; + + /** + * An array of destinations declared for each source migration. + * + * Destinations are keyed by version. Each value is an array keyed by the name + * of the source module and the value is an array of the destination modules. + * + * @var array + */ + protected $declaredBySource; + + /** + * An array of migration source and destinations derived from migrations. + * + * The key is the source version and the value is an array where the key is + * the source module and the value is an array of destinations derived from + * migration plugins. + * + * @var array + */ + protected $disoveredBySource; + + /** + * An array of migration source and destinations. + * + * Values are derived from migration plugins and declared states. The key is + * the source version and the value is an array where the key is the source + * module and the value is an array of declared or derived destinations. + * + * @var array + */ + protected $destinations = []; + + /** + * Array of enabled modules. + * + * @var array + */ + protected $enabledModules = []; + + /** + * List of extensions that do not need an upgrade path. + * + * This property is an array where the keys are the major Drupal core version + * from which we are upgrading, and the values are arrays of extension names + * that do not need an upgrade path and are not names in the 'source_module' + * annotation for a migration. In other words, the functionality of these + * extensions has moved into core, or been dropped from core, and there isn't + * a Drupal 8 module of the same name. + * + * @var array[] + */ + protected $noUpgradePaths = [ + '6' => [ + 'blog', + 'blogapi', + 'calendarsignup', + 'color', + 'content_copy', + 'content_multigroup', + 'content_permissions', + 'date_api', + 'date_locale', + 'date_php4', + 'date_popup', + 'date_repeat', + 'date_timezone', + 'date_tools', + 'datepicker', + 'ddblock', + 'event', + 'fieldgroup', + 'filefield_meta', + 'help', + 'i18ncontent', + 'i18npoll', + 'i18nstrings', + 'i18nsync', + 'imageapi', + 'imageapi_gd', + 'imageapi_imagemagick', + 'imagecache_ui', + 'jquery_ui', + 'nodeaccess', + 'number', + 'openid', + 'php', + 'ping', + 'poll', + 'throttle', + 'tracker', + 'translation', + 'trigger', + 'variable', + 'variable_admin', + 'views_export', + 'views_ui', + ], + '7' => [ + 'blog', + 'bulk_export', + 'contextual', + 'ctools', + 'ctools_acces_ruleset', + 'ctools_ajax_sample', + 'ctools_custom_content', + 'dashboard', + 'date_all_day', + 'date_api', + 'date_context', + 'date_migrate', + 'date_popup', + 'date_repeat', + 'date_repeat_field', + 'date_tools', + 'date_views', + 'entity', + 'entity_feature', + 'entity_token', + 'entityreference', + 'field_ui', + 'help', + 'openid', + 'overlay', + 'page_manager', + 'php', + 'poll', + 'search_embedded_form', + 'search_extra_type', + 'search_node_tags', + 'simpletest', + 'stylizer', + 'term_depth', + 'title', + 'toolbar', + 'translation', + 'trigger', + 'views_content', + 'views_ui', + ], + ]; + + /** + * Construct a new MigrationState object. + * + * @param \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface $fieldPluginManager + * Field plugin manager. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler + * Module handler. + * @param \Drupal\Core\Messenger\MessengerInterface $messenger + * Messenger sevice. + * @param \Drupal\Core\StringTranslation\TranslationInterface $stringTranslation + * String translation service. + */ + public function __construct(MigrateFieldPluginManagerInterface $fieldPluginManager, ModuleHandlerInterface $moduleHandler, MessengerInterface $messenger, TranslationInterface $stringTranslation) { + $this->fieldPluginManager = $fieldPluginManager; + $this->moduleHandler = $moduleHandler; + $this->enabledModules = array_keys($this->moduleHandler->getModuleList()); + $this->enabledModules[] = 'core'; + $this->messenger = $messenger; + $this->stringTranslation = $stringTranslation; + } + + /** + * Gets the upgrade states for all enabled source modules. + * + * @param string $version + * The legacy drupal version. + * @param array $source_system_data + * The data from the source site system table. + * @param array $migrations + * An array of migrations. + * + * @return array + * An associative array of data with keys of state, source modules and a + * value which is a comma separated list of destination modules. + */ + public function getUpgradeStates($version, array $source_system_data, array $migrations) { + return $this->buildUpgradeState($version, $source_system_data, $migrations); + } + + /** + * Gets migration state information from *.migrate_drupal.yml. + * + * @return array + * An association array keyed by module of the finished and not_finished + * migrations for each module. + * */ + protected function getMigrationStates() { + // Always instantiate a new YamlDiscovery object so that we always search on + // the up-to-date list of modules. + $discovery = new YamlDiscovery('migrate_drupal', $this->moduleHandler->getModuleDirectories()); + return $discovery->findAll(); + } + + /** + * Determines migration state for each source module enabled on the source. + * + * If there are no migrations for a module and the module is listed in the + * NoUpgradePath list then the state is set to FINISHED. If it is not listed + * in NoUpgradePath list the state is set to NOT_FINISHED. + * + * If there are migrations for a module the following happens. If the + * destination module is 'core' the state is set to FINISHED. If there are + * any occurrences of 'not_finished' in the *.migrate_drupal.yml information + * for this source module then the state is set to NOT_FINISHED. And finally, + * if there is an occurrence of 'finished' the state is set to FINISHED. + * + * @param string $version + * The legacy drupal version. + * @param array $source_system_data + * The data from the source site system table. + * @param array $migrations + * An array of migrations. + * + * @return array + * An associative array of data with keys of state, source modules and a + * value which is a comma separated list of destination modules. + * Example. + * + * @code + * [ + * 'finished' => [ + * 'menu' => [ + * 'menu_link_content','menu_ui','system' + * ] + * ], + * ] + * @endcode + */ + protected function buildUpgradeState($version, array $source_system_data, array $migrations) { + // Remove core profiles from the system data. + unset($source_system_data['module']['standard'], $source_system_data['module']['minimal']); + $this->buildDiscoveredDestinationsBySource($version, $migrations, $source_system_data); + $this->buildDeclaredStateBySource($version); + + $upgrade_state = []; + // Loop through every source module that is enabled on the source site. + foreach ($source_system_data['module'] as $module) { + // The source plugins check requirements requires that all + // source_modules are enabled so do the same here. + if ($module['status']) { + $source_module = $module['name']; + // If there is not a declared state for this source module then use the + // legacy method for determining the migration state. + if (!isset($this->stateBySource[$version][$source_module])) { + @trigger_error(sprintf("Using migration plugin definitions to determine the migration state of the module '%s' is deprecated in Drupal 8.7. Add the module to a migrate_drupal.yml file. See https://www.drupal.org/node/2929443", $source_module), E_USER_DEPRECATED); + if (array_key_exists($source_module, $this->unmigratedSourceModules[$version])) { + $upgrade_state[static::NOT_FINISHED][$source_module] = ''; + continue; + } + if (array_key_exists($source_module, $this->migratedSourceModules[$version])) { + if (array_diff(array_keys($this->migratedSourceModules[$version][$source_module]), $this->enabledModules)) { + $upgrade_state[static::NOT_FINISHED][$source_module] = implode(', ', array_keys($this->migratedSourceModules[$version][$source_module])); + continue; + } + $upgrade_state[static::FINISHED][$source_module] = implode(', ', array_keys($this->migratedSourceModules[$version][$source_module])); + } + continue; + } + + $upgrade_state[$this->getSourceState($version, $source_module)][$source_module] = implode(', ', $this->getDestinationsForSource($version, $source_module)); + } + + } + foreach ($upgrade_state as $key => $value) { + ksort($upgrade_state[$key]); + } + return $upgrade_state; + } + + /** + * Builds migration source and destination module information. + * + * @param string $version + * The legacy Drupal version. + * @param array $migrations + * The discovered migrations. + * @param array $source_system_data + * The data from the source site system table. + */ + protected function buildDiscoveredDestinationsBySource($version, array $migrations, array $source_system_data) { + $discovered_upgrade_paths = []; + $table_data = []; + foreach ($migrations as $migration) { + $migration_id = $migration->getPluginId(); + $source_module = $migration->getSourcePlugin()->getSourceModule(); + if (!$source_module) { + $this->messenger() + ->addError($this->t('Source module not found for @migration_id.', ['@migration_id' => $migration_id])); + } + $destination_module = $migration->getDestinationPlugin() + ->getDestinationModule(); + if (!$destination_module) { + $this->messenger() + ->addError($this->t('Destination module not found for @migration_id.', ['@migration_id' => $migration_id])); + } + + if ($source_module && $destination_module) { + $discovered_upgrade_paths[$source_module][] = $destination_module; + $table_data[$source_module][$destination_module][$migration_id] = $migration->label(); + } + } + + // Add entries for the field plugins to discovered_upgrade_paths. + $definitions = $this->fieldPluginManager->getDefinitions(); + foreach ($definitions as $definition) { + // This is not strict so that we find field plugins with an annotation + // where the Drupal core version is an integer and when it is a string. + if (in_array($version, $definition['core'])) { + $source_module = $definition['source_module']; + $destination_module = $definition['destination_module']; + $discovered_upgrade_paths[$source_module][] = $destination_module; + $table_data[$source_module][$destination_module][$definition['id']] = $definition['id']; + } + } + // Add source_module and destination_module for modules that do not need + // an upgrade path and are enabled on the source site. + foreach ($this->noUpgradePaths[$version] as $extension) { + if (isset($source_system_data['module'][$extension]) && $source_system_data['module'][$extension]['status']) { + $table_data[$extension]['core'][$extension] = $extension; + } + } + ksort($table_data); + foreach ($table_data as $source_module => $destination_module_info) { + ksort($table_data[$source_module]); + } + $tmp = array_diff_key($source_system_data['module'], $table_data); + foreach ($tmp as $source_module => $module_data) { + if ($module_data['status']) { + $this->unmigratedSourceModules[$version][$source_module] = $module_data; + } + } + $this->migratedSourceModules[$version] = $table_data; + $this->disoveredBySource[$version] = array_map('array_unique', $discovered_upgrade_paths); + } + + /** + * Gets migration data from *.migrate_drupal.yml sorted by source module. + * + * @param string $version + * The legacy Drupal version. + */ + protected function buildDeclaredStateBySource($version) { + $migration_states = $this->getMigrationStates(); + + $state_by_source = []; + $dest_by_source = []; + $states = [static::FINISHED, static::NOT_FINISHED]; + foreach ($migration_states as $module => $info) { + foreach ($states as $state) { + if (isset($info[$state][$version])) { + foreach ($info[$state][$version] as $source => $destination) { + // Add the state. + $state_by_source[$source][] = $state; + // Add the destination modules. + $dest_by_source += [$source => []]; + $dest_by_source[$source] = array_merge($dest_by_source[$source], (array) $destination); + } + } + } + } + $this->stateBySource[$version] = array_map('array_unique', $state_by_source); + $this->declaredBySource[$version] = array_map('array_unique', $dest_by_source); + } + + /** + * Tests if a destination exists for the given source module. + * + * @param string $version + * Source version of Drupal. + * @param string $source_module + * Source module. + * + * @return string + * Migration state, either 'finished' or 'not_finished'. + */ + protected function getSourceState($version, $source_module) { + // The state is finished only when no declarations of 'not_finished' + // were found and each destination module is enabled. + if (!$destinations = $this->getDestinationsForSource($version, $source_module)) { + // No discovered or declared state. + return MigrationState::NOT_FINISHED; + } + if (in_array(MigrationState::NOT_FINISHED, $this->stateBySource[$version][$source_module], TRUE) || !in_array(MigrationState::FINISHED, $this->stateBySource[$version][$source_module], TRUE)) { + return MigrationState::NOT_FINISHED; + } + if (array_diff($destinations, $this->enabledModules)) { + return MigrationState::NOT_FINISHED; + } + return MigrationState::FINISHED; + } + + /** + * Get net destinations for source module. + * + * @param string $version + * Source version. + * @param string $source_module + * Source module. + * + * @return array + * Destination modules either declared by {modulename}.migrate_drupal.yml + * files or discovered from migration plugins. + */ + protected function getDestinationsForSource($version, $source_module) { + if (!isset($this->destinations[$version][$source_module])) { + $this->disoveredBySource[$version] += [$source_module => []]; + $this->declaredBySource[$version] += [$source_module => []]; + $destination = array_unique(array_merge($this->disoveredBySource[$version][$source_module], $this->declaredBySource[$version][$source_module])); + sort($destination); + $this->destinations[$version][$source_module] = $destination; + } + return $this->destinations[$version][$source_module]; + + } + +} diff --git a/core/modules/migrate_drupal/tests/modules/migrate_state_finished_test/migrate_state_finished_test.info.yml b/core/modules/migrate_drupal/tests/modules/migrate_state_finished_test/migrate_state_finished_test.info.yml new file mode 100644 index 0000000000..a040bc537e --- /dev/null +++ b/core/modules/migrate_drupal/tests/modules/migrate_state_finished_test/migrate_state_finished_test.info.yml @@ -0,0 +1,6 @@ +name: Migrate state active test +type: module +description: Tests the 'active' migrate state +package: Testing +version: VERSION +core: 8.x diff --git a/core/modules/migrate_drupal/tests/modules/migrate_state_finished_test/migrate_state_finished_test.migrate_drupal.yml b/core/modules/migrate_drupal/tests/modules/migrate_state_finished_test/migrate_state_finished_test.migrate_drupal.yml new file mode 100644 index 0000000000..28169879d1 --- /dev/null +++ b/core/modules/migrate_drupal/tests/modules/migrate_state_finished_test/migrate_state_finished_test.migrate_drupal.yml @@ -0,0 +1,20 @@ +finished: + 6: + # A field migration + # migrate_state_finished_test: migrate_state_finished_test + aggregator: migrate_state_finished_test + action: + - migrate_state_finished_test + - migrate_state_not_finished_test + 7: + # A field migration + # migrate_state_finished_test: migrate_state_finished_test + aggregator: migrate_state_finished_test + # Migrations + action: + - migrate_state_finished_test + - migrate_state_not_finished_test +not_finished: + 7: + # Migrations + action: system diff --git a/core/modules/migrate_drupal/tests/modules/migrate_state_finished_test/migrations/migrate_state_finished_test.yml b/core/modules/migrate_drupal/tests/modules/migrate_state_finished_test/migrations/migrate_state_finished_test.yml new file mode 100644 index 0000000000..bffca64c6a --- /dev/null +++ b/core/modules/migrate_drupal/tests/modules/migrate_state_finished_test/migrations/migrate_state_finished_test.yml @@ -0,0 +1,20 @@ +id: migrate_state_finished_test +label: Block content body field configuration +migration_tags: + - Drupal 6 + - Drupal 7 + - Configuration +source: + plugin: embedded_data + data_rows: + - + id: 1 + ids: + id: + type: string + source_module: action +process: [] +destination: + plugin: entity:field_config + destination_module: migrate_state_finished_test + diff --git a/core/modules/migrate_drupal/tests/modules/migrate_state_finished_test/migrations/migrate_state_finished_test1.yml b/core/modules/migrate_drupal/tests/modules/migrate_state_finished_test/migrations/migrate_state_finished_test1.yml new file mode 100644 index 0000000000..e4c6df0d88 --- /dev/null +++ b/core/modules/migrate_drupal/tests/modules/migrate_state_finished_test/migrations/migrate_state_finished_test1.yml @@ -0,0 +1,20 @@ +id: migrate_state_finished_test1 +label: Block content body field configuration +migration_tags: + - Drupal 6 + - Drupal 7 + - Configuration +source: + plugin: embedded_data + data_rows: + - + id: 1 + ids: + id: + type: string + source_module: action +process: [] +destination: + plugin: entity:field_config + destination_module: migrate_state_not_finished_test + diff --git a/core/modules/migrate_drupal/tests/modules/migrate_state_finished_test/src/Plugin/migrate/field/FieldLeft.php b/core/modules/migrate_drupal/tests/modules/migrate_state_finished_test/src/Plugin/migrate/field/FieldLeft.php new file mode 100644 index 0000000000..a411d01769 --- /dev/null +++ b/core/modules/migrate_drupal/tests/modules/migrate_state_finished_test/src/Plugin/migrate/field/FieldLeft.php @@ -0,0 +1,18 @@ +getUpgradeStates(7, [ + 'module' => [ + 'entity_test' => [ + 'name' => 'entity_test', + 'status' => TRUE, + ], + ], + ], []); + } + +} diff --git a/core/modules/migrate_drupal/tests/src/Kernel/StateFileExists.php b/core/modules/migrate_drupal/tests/src/Kernel/StateFileExists.php new file mode 100644 index 0000000000..47ed466ce5 --- /dev/null +++ b/core/modules/migrate_drupal/tests/src/Kernel/StateFileExists.php @@ -0,0 +1,105 @@ +container->get('module_handler'); + $all_modules = $this->coreModuleListDataProvider(); + $modules_enabled = $module_handler->getModuleList(); + $modules_to_enable = array_keys(array_diff_key($all_modules, $modules_enabled)); + $this->enableModules($modules_to_enable); + + // Modules with a migrate_drupal.yml file. + $has_state_file = (new YamlDiscovery('migrate_drupal', $module_handler->getModuleDirectories()))->findAll(); + + foreach ($this->stateFileRequired as $module) { + $this->assertArrayHasKey($module, $has_state_file, sprintf("Module '%s' should have a migrate_drupal.yml file", $module)); + } + $this->assertEquals(count($this->stateFileRequired), count($has_state_file)); + } + +} diff --git a/core/modules/migrate_drupal/tests/src/Kernel/ValidateMigrationStateTest.php b/core/modules/migrate_drupal/tests/src/Kernel/ValidateMigrationStateTest.php new file mode 100644 index 0000000000..913868dd59 --- /dev/null +++ b/core/modules/migrate_drupal/tests/src/Kernel/ValidateMigrationStateTest.php @@ -0,0 +1,170 @@ +enableAllModules(); + + // Build an array for each migration keyed by provider. The value is a + // string consisting of the version number, the provider, the source_module + // and the destination module. + $discovered = []; + $versions = ['6', '7']; + /** @var \Drupal\migrate\Plugin\MigrationPluginManager $plugin_manager */ + $plugin_manager = $this->container->get('plugin.manager.migration'); + foreach ($versions as $version) { + $migrations = $plugin_manager->createInstancesByTag('Drupal ' . $version); + /** @var \Drupal\migrate\Plugin\Migration $migration */ + foreach ($migrations as $migration) { + $definition = $migration->getPluginDefinition(); + if (is_array($definition['provider'])) { + $provider = reset($definition['provider']); + } + else { + $provider = $definition['provider']; + } + + $source_module = $migration->getSourcePlugin()->getSourceModule(); + $destination_module = $migration->getDestinationPlugin() + ->getDestinationModule(); + + $discovered[$version][] = implode(static::SEPARATOR, [ + $version, + $provider, + $source_module, + $destination_module, + ]); + } + } + + // Add the field migrations. + /** @var \Drupal\migrate\Plugin\MigrationPluginManager $plugin_manager */ + $definitions = $this->container->get('plugin.manager.migrate.field') + ->getDefinitions(); + foreach ($definitions as $key => $definition) { + foreach ($definition['core'] as $version) { + $discovered[$version][] = implode(static::SEPARATOR, [ + $version, + $definition['provider'], + $definition['source_module'], + $definition['destination_module'], + ]); + } + } + + // Get the declared migration state information from .migrate_drupal.yml + // and build an array of source modules and there migration state. The + // destination is not used yet but can be later for validating the + // source/destination pairs with the actual source/destination pairs in the + // migrate plugins. + $system_info = (new YamlDiscovery('migrate_drupal', \Drupal::moduleHandler()->getModuleDirectories()))->findAll(); + + $declared = []; + $states = [MigrationState::FINISHED, MigrationState::NOT_FINISHED]; + foreach ($system_info as $module => $info) { + foreach ($states as $state) { + if (isset($info[$state])) { + foreach ($info[$state] as $info_version => $migrate_info) { + foreach ($migrate_info as $source => $destination) { + // Do not add the source module i18nstrings or i18_string. The + // 18n migrations can have up to three source modules but only one + // can be handled in the migration. + if (($source !== 'i18nstrings') && ($source !== 'i18n_string')) { + foreach ((array) $destination as $dest) { + $key = [$info_version, $module, $source, trim($dest)]; + $declared[$info_version][$state][] = implode(static::SEPARATOR, $key); + } + } + } + } + } + } + } + + $versions = ['6', '7']; + foreach ($versions as $version) { + // Sort and make the array values unique. + sort($declared[$version][MigrationState::FINISHED]); + sort($declared[$version][MigrationState::NOT_FINISHED]); + $declared_unique[$version][MigrationState::FINISHED] = array_unique($declared[$version][MigrationState::FINISHED]); + $declared_unique[$version][MigrationState::NOT_FINISHED] = array_unique($declared[$version][MigrationState::NOT_FINISHED]); + sort($discovered[$version]); + $discovered_unique[$version] = array_unique($discovered[$version]); + + // Assert that each discovered migration has a corresponding declaration + // in a migrate_drupal.yml. + foreach ($discovered_unique[$version] as $datum) { + $data = str_getcsv($datum); + $in_finished = in_array($datum, $declared_unique[$version][MigrationState::FINISHED]); + $in_not_finished = in_array($datum, $declared_unique[$version][MigrationState::NOT_FINISHED]); + $found = $in_finished || $in_not_finished; + $this->assertTrue($found, sprintf("No migration state found for version '%s' with source_module '%s' and destination_module '%s' declared in module '%s'", $data[0], $data[2], $data[3], $data[1])); + } + + // Remove the declared finished from the discovered, leaving just the not + // finished, if there are any. These should have an entry in the declared + // not finished. + $discovered_not_finished = array_diff($discovered_unique[$version], $declared_unique[$version][MigrationState::FINISHED]); + foreach ($discovered_not_finished as $datum) { + $data = str_getcsv($datum); + $this->assertContains($datum, $declared_unique[$version][MigrationState::NOT_FINISHED], sprintf("No migration found for version '%s' with source_module '%s' and destination_module '%s' declared in module '%s'", $data[0], $data[2], $data[3], $data[1])); + } + } + } + + /** + * Enable all available modules. + */ + protected function enableAllModules() { + // Install all available modules. + $module_handler = $this->container->get('module_handler'); + $modules = $this->coreModuleListDataProvider(); + $modules_enabled = $module_handler->getModuleList(); + $modules_to_enable = array_keys(array_diff_key($modules, $modules_enabled)); + $this->enableModules($modules_to_enable); + return $modules; + } + +} diff --git a/core/modules/migrate_drupal/tests/src/Unit/MigrationStateUnitTest.php b/core/modules/migrate_drupal/tests/src/Unit/MigrationStateUnitTest.php new file mode 100644 index 0000000000..062241b9ad --- /dev/null +++ b/core/modules/migrate_drupal/tests/src/Unit/MigrationStateUnitTest.php @@ -0,0 +1,247 @@ +prophesize(MigrateFieldPluginManagerInterface::class); + $fieldPluginManager->getDefinitions()->willReturn([ + 'datetime' => [ + 'id' => 'datetime', + 'core' => [7], + 'source_module' => 'date', + 'destination_module' => 'datetime', + ], + 'link' => [ + 'id' => 'link', + 'core' => [6, 7], + 'source_module' => 'link', + 'destination_module' => 'link', + ], + ]); + $moduleHandler = $this->prophesize(ModuleHandlerInterface::class); + $moduleHandler->getModuleList()->willReturn([ + 'entity_test' => [], + 'node' => [], + 'link' => [], + 'rdf' => [], + ]); + vfsStreamWrapper::register(); + $root = new vfsStreamDirectory('modules'); + vfsStreamWrapper::setRoot($root); + $url = vfsStream::url('modules'); + + $files['node'] = << $contents) { + mkdir($url . '/' . $module); + file_put_contents($url . '/' . $module . '/' . $module . '.migrate_drupal.yml', $contents); + } + $moduleHandler->getModuleDirectories()->willReturn(array_combine(array_keys($files), array_map(function ($module) use ($url) { + return $url . '/' . $module; + }, array_keys($files)))); + $migrationState = new MigrationState($fieldPluginManager->reveal(), $moduleHandler->reveal(), $this->createMock(MessengerInterface::class), $this->getStringTranslationStub()); + $migration1 = $this->prophesize(MigrationInterface::class); + $source = $this->prophesize(MigrateSourceInterface::class); + $destination = $this->prophesize(MigrateDestinationInterface::class); + $source->getSourceModule()->willReturn('rdf'); + $destination->getDestinationModule()->willReturn('rdf'); + $migration1->getSourcePlugin()->willReturn($source->reveal()); + $migration1->getDestinationPlugin()->willReturn($destination->reveal()); + $migration1->getPluginId()->willReturn('rdf'); + $migration1->label()->willReturn('rdf'); + $migration2 = $this->prophesize(MigrationInterface::class); + $source = $this->prophesize(MigrateSourceInterface::class); + $destination = $this->prophesize(MigrateDestinationInterface::class); + $source->getSourceModule()->willReturn('filter'); + $destination->getDestinationModule()->willReturn('filter'); + $migration2->getSourcePlugin()->willReturn($source->reveal()); + $migration2->getDestinationPlugin()->willReturn($destination->reveal()); + $migration2->getPluginId()->willReturn('filter'); + $migration2->label()->willReturn('filter'); + $source_system_data = [ + 'module' => [ + 'entity_test' => [ + 'name' => 'entity_test', + 'status' => TRUE, + ], + 'rdf' => [ + 'name' => 'rdf', + 'status' => TRUE, + ], + 'node' => [ + 'name' => 'node', + 'status' => TRUE, + ], + 'date' => [ + 'name' => 'date', + 'status' => TRUE, + ], + 'link' => [ + 'name' => 'link', + 'status' => TRUE, + ], + 'search' => [ + 'name' => 'search', + 'status' => TRUE, + ], + 'filter' => [ + 'name' => 'filter', + 'status' => TRUE, + ], + 'comment' => [ + 'name' => 'comment', + 'status' => TRUE, + ], + 'standard' => [ + 'name' => 'standard', + 'status' => TRUE, + ], + 'color' => [ + 'name' => 'color', + 'status' => TRUE, + ], + 'user' => [ + 'name' => 'user', + 'status' => TRUE, + ], + 'profile' => [ + 'name' => 'profile', + 'status' => TRUE, + ], + // Disabled, hence ignored. + 'dblog' => [ + 'name' => 'dblog', + 'status' => FALSE, + ], + ], + ]; + $states = $migrationState->getUpgradeStates(7, $source_system_data, [$migration1->reveal(), $migration2->reveal()]); + $this->assertEquals([ + MigrationState::NOT_FINISHED => [ + // Declared not finished. + 'entity_test' => 'entity_test, entity_test_rev', + // Destination module comment is not enabled. + 'comment' => 'comment, node', + // Declared finished by one module but not finished by another. + 'user' => 'user', + // Not finished. + 'profile' => 'user', + // Not enabled and not declared. + 'color' => '', + // Destination module not enabled. + 'date' => 'datetime', + // Destination module not enabled. + 'filter' => 'filter', + // No discovered or declared state. + 'search' => '', + ], + MigrationState::FINISHED => [ + 'node' => 'node', + 'link' => 'link', + 'rdf' => 'rdf', + ], + ], $states); + $source_system_data['module']['content'] = [ + 'name' => 'content', + 'status' => TRUE, + ]; + unset($source_system_data['module']['rdf'], $source_system_data['module']['filter']); + $states = $migrationState->getUpgradeStates(6, $source_system_data, []); + $this->assertEquals([ + MigrationState::NOT_FINISHED => [ + // Declared not finished. + 'entity_test' => 'entity_test', + // Destination module comment is not enabled. + 'comment' => 'comment, node', + 'user' => 'user', + // Not finished. + 'profile' => 'user', + // Not declared and non compatible field plugin. + 'date' => '', + // No discovered or declared state. + 'search' => '', + ], + MigrationState::FINISHED => [ + 'node' => 'node', + 'content' => 'node', + // Update path not needed. + 'color' => 'core', + 'link' => 'link', + ], + ], $states); + } + +} diff --git a/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php b/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php index 6ef9dd564c..6dfff3cb7a 100644 --- a/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php +++ b/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php @@ -5,18 +5,26 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\State\StateInterface; use Drupal\Core\TempStore\PrivateTempStoreFactory; -use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface; use Drupal\migrate\Plugin\MigrationPluginManagerInterface; +use Drupal\migrate_drupal\MigrationState; +use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface; use Drupal\migrate_drupal_ui\Batch\MigrateUpgradeImportBatch; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Migrate Upgrade review form. * - * This confirmation form uses the source_module and destination_module - * properties on the source, destination and field plugins as well as the - * system data from the source to determine if there is a migration path for - * each module in the source. + * This confirmation form provides the user with a summary of all the modules + * enabled on the source site and whether they will be upgraded or not. Data + * from a module's .migrate_drupal.yml file and all the migration plugins + * (source, destination and field) for each enabled Drupal 8 module are used to + * decide the migration status for each enabled module on the source site. + * + * The migration status displayed on the Review page is a list of all the + * enabled modules on the source site divided into two categories, those that + * will not be upgraded and those that will be upgraded. The intention is to + * provide the admin with enough information to decide if it is OK to proceed + * with the upgrade. * * @internal */ @@ -51,101 +59,11 @@ class ReviewForm extends MigrateUpgradeFormBase { protected $migrations; /** - * List of extensions that do not need an upgrade path. + * Migration state service. * - * This property is an array where the keys are the major Drupal core version - * from which we are upgrading, and the values are arrays of extension names - * that do not need an upgrade path. - * - * @var array[] + * @var \Drupal\migrate_drupal\MigrationState */ - protected $noUpgradePaths = [ - '6' => [ - 'blog', - 'blogapi', - 'calendarsignup', - 'color', - 'content_copy', - 'content_multigroup', - 'content_permissions', - 'date_api', - 'date_locale', - 'date_php4', - 'date_popup', - 'date_repeat', - 'date_timezone', - 'date_tools', - 'datepicker', - 'ddblock', - 'event', - 'fieldgroup', - 'filefield_meta', - 'help', - 'i18nstrings', - 'i18nsync', - 'imageapi', - 'imageapi_gd', - 'imageapi_imagemagick', - 'imagecache_ui', - 'jquery_ui', - 'nodeaccess', - 'number', - 'openid', - 'php', - 'ping', - 'poll', - 'throttle', - 'tracker', - 'translation', - 'trigger', - 'variable', - 'variable_admin', - 'views_export', - 'views_ui', - ], - '7' => [ - 'blog', - 'bulk_export', - 'contextual', - 'ctools', - 'ctools_access_ruleset', - 'ctools_ajax_sample', - 'ctools_custom_content', - 'dashboard', - 'date_all_day', - 'date_api', - 'date_context', - 'date_migrate', - 'date_popup', - 'date_repeat', - 'date_repeat_field', - 'date_tools', - 'date_views', - 'entity', - 'entity_feature', - 'entity_token', - 'entityreference', - 'field_ui', - 'help', - 'openid', - 'overlay', - 'page_manager', - 'php', - 'poll', - 'search_embedded_form', - 'search_extra_type', - 'search_node_tags', - 'simpletest', - 'stylizer', - 'term_depth', - 'title', - 'toolbar', - 'translation', - 'trigger', - 'views_content', - 'views_ui', - ], - ]; + protected $migrationState; /** * ReviewForm constructor. @@ -158,12 +76,15 @@ class ReviewForm extends MigrateUpgradeFormBase { * The field plugin manager service. * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $tempstore_private * The private tempstore factory. + * @param \Drupal\migrate_drupal\MigrationState $migrationState + * Migration state service. */ - public function __construct(StateInterface $state, MigrationPluginManagerInterface $migration_plugin_manager, MigrateFieldPluginManagerInterface $field_plugin_manager, PrivateTempStoreFactory $tempstore_private) { + public function __construct(StateInterface $state, MigrationPluginManagerInterface $migration_plugin_manager, MigrateFieldPluginManagerInterface $field_plugin_manager, PrivateTempStoreFactory $tempstore_private, MigrationState $migrationState) { parent::__construct($tempstore_private); $this->state = $state; $this->pluginManager = $migration_plugin_manager; $this->fieldPluginManager = $field_plugin_manager; + $this->migrationState = $migrationState; } /** @@ -174,7 +95,8 @@ public static function create(ContainerInterface $container) { $container->get('state'), $container->get('plugin.manager.migration'), $container->get('plugin.manager.migrate.field'), - $container->get('tempstore.private') + $container->get('tempstore.private'), + $container->get('migrate_drupal.migration_state') ); } @@ -192,7 +114,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { // Get all the data needed for this form. $version = $this->store->get('version'); $this->migrations = $this->store->get('migrations'); - // Fetch the system data at the first opportunity. + // Fetch the source system data at the first opportunity. $system_data = $this->store->get('system_data'); // If data is missing or this is the wrong step, start over. @@ -204,58 +126,10 @@ public function buildForm(array $form, FormStateInterface $form_state) { $form = parent::buildForm($form, $form_state); $form['#title'] = $this->t('What will be upgraded?'); - // Get the source_module and destination_module for each migration. $migrations = $this->pluginManager->createInstances(array_keys($this->store->get('migrations'))); - $table_data = []; - foreach ($migrations as $migration) { - $migration_id = $migration->getPluginId(); - $source_module = $migration->getSourcePlugin()->getSourceModule(); - if (!$source_module) { - $this->messenger()->addError($this->t('Source module not found for @migration_id.', ['@migration_id' => $migration_id])); - } - $destination_module = $migration->getDestinationPlugin()->getDestinationModule(); - if (!$destination_module) { - $this->messenger()->addError($this->t('Destination module not found for @migration_id.', ['@migration_id' => $migration_id])); - } - - if ($source_module && $destination_module) { - $table_data[$source_module][$destination_module][$migration_id] = $migration->label(); - } - } - - // Get the source_module and destination_module from the field plugins. - $definitions = $this->fieldPluginManager->getDefinitions(); - foreach ($definitions as $definition) { - // This is not strict so that we find field plugins with an annotation - // where the Drupal core version is an integer and when it is a string. - if (in_array($version, $definition['core'])) { - $source_module = $definition['source_module']; - $destination_module = $definition['destination_module']; - $table_data[$source_module][$destination_module][$definition['id']] = $definition['id']; - } - } - - // Add source_module and destination_module for modules that do not need an - // upgrade path and are enabled on the source site. - foreach ($this->noUpgradePaths[$version] as $extension) { - if (isset($system_data['module'][$extension]) && $system_data['module'][$extension]['status']) { - $table_data[$extension]['core'][$extension] = $extension; - } - } - - // Sort the table by source module names and within that destination - // module names. - ksort($table_data); - foreach ($table_data as $source_module => $destination_module_info) { - ksort($table_data[$source_module]); - } - - // Remove core profiles from the system data. - foreach (['standard', 'minimal'] as $profile) { - unset($system_data['module'][$profile]); - } - $unmigrated_source_modules = array_diff_key($system_data['module'], $table_data); + // Get the upgrade states for the source modules. + $display = $this->migrationState->getUpgradeStates($version, $system_data, $migrations); // Missing migrations. $missing_module_list = [ @@ -263,7 +137,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#open' => TRUE, '#title' => $this->t('Modules that will not be upgraded'), '#summary_attributes' => ['id' => ['error']], - '#description' => $this->t('There are no modules installed on your new site to replace these modules. If you proceed with the upgrade now, configuration and/or content needed by these modules will not be available on your new site. For more information, see Review the pre-upgrade analysis in the Upgrading to Drupal 8 handbook.', [':review' => 'https://www.drupal.org/docs/8/upgrade/upgrade-using-web-browser#pre-upgrade-analysis', ':migrate' => 'https://www.drupal.org/docs/8/upgrade']), + '#description' => $this->t("The new site is missing modules corresponding to the old site's modules. Unless they are installed prior to the upgrade, configuration and/or content needed by them will not be available on your new site. Read the checklist to help decide what to do.", [':review' => 'https://www.drupal.org/docs/8/upgrade/upgrade-using-web-browser#pre-upgrade-analysis']), '#weight' => 2, ]; $missing_module_list['module_list'] = [ @@ -273,12 +147,14 @@ public function buildForm(array $form, FormStateInterface $form_state) { $this->t('Drupal 8'), ], ]; + $missing_count = 0; - ksort($unmigrated_source_modules); - foreach ($unmigrated_source_modules as $source_module => $module_data) { - if ($module_data['status']) { + if (isset($display[MigrationState::NOT_FINISHED])) { + foreach ($display[MigrationState::NOT_FINISHED] as $source_module => $destination_modules) { $missing_count++; - $missing_module_list['module_list'][$source_module] = [ + // Get the migration status for this $source_module, if a module of the + // same name exists on the destination site. + $missing_module_list['module_list'][] = [ 'source_module' => [ '#type' => 'html_tag', '#tag' => 'span', @@ -290,7 +166,9 @@ public function buildForm(array $form, FormStateInterface $form_state) { ], ], ], - 'destination_module' => ['#plain_text' => 'Not upgraded'], + 'destination_module' => [ + '#plain_text' => $destination_modules, + ], ]; } } @@ -300,7 +178,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#type' => 'details', '#title' => $this->t('Modules that will be upgraded'), '#summary_attributes' => ['id' => ['checked']], - '#weight' => 3, + '#weight' => 4, ]; $available_module_list['module_list'] = [ @@ -312,29 +190,26 @@ public function buildForm(array $form, FormStateInterface $form_state) { ]; $available_count = 0; - foreach ($table_data as $source_module => $destination_module_info) { - $available_count++; - $destination_details = []; - foreach ($destination_module_info as $destination_module => $migration_ids) { - $destination_details[$destination_module] = [ - '#type' => 'item', - '#plain_text' => $destination_module, - ]; - } - $available_module_list['module_list'][$source_module] = [ - 'source_module' => [ - '#type' => 'html_tag', - '#tag' => 'span', - '#value' => $source_module, - '#attributes' => [ - 'class' => [ - 'upgrade-analysis-report__status-icon', - 'upgrade-analysis-report__status-icon--checked', + if (isset($display[MigrationState::FINISHED])) { + foreach ($display[MigrationState::FINISHED] as $source_module => $destination_modules) { + $available_count++; + $available_module_list['module_list'][] = [ + 'source_module' => [ + '#type' => 'html_tag', + '#tag' => 'span', + '#value' => $source_module, + '#attributes' => [ + 'class' => [ + 'upgrade-analysis-report__status-icon', + 'upgrade-analysis-report__status-icon--checked', + ], ], ], - ], - 'destination_module' => $destination_details, - ]; + 'destination_module' => [ + '#plain_text' => $destination_modules, + ], + ]; + } } $counters = []; @@ -354,9 +229,8 @@ public function buildForm(array $form, FormStateInterface $form_state) { $counters[] = [ '#theme' => 'status_report_counter', '#amount' => $available_count, - '#text' => $this->formatPlural($available_count, 'Module will be upgraded', 'Modules will be upgraded'), - '#severity' => 'checked', - '#weight' => 1, + '#text' => $this->formatPlural($missing_count, 'Module will be upgraded', 'Modules will be upgraded'), + '#weight' => 2, ]; $general_info[] = $available_module_list; } diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php index f165bb7c8e..ed901febec 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php @@ -117,7 +117,7 @@ public function testMigrateUpgradeExecute() { // Ensure there are no errors about any other missing migration providers. $session->pageTextNotContains(t('module not found')); - // Test the upgrade paths. + // Test the review page. $available_paths = $this->getAvailablePaths(); $missing_paths = $this->getMissingPaths(); $this->assertReviewPage($session, $available_paths, $missing_paths); @@ -146,12 +146,7 @@ public function testMigrateUpgradeExecute() { $this->drupalPostForm(NULL, [], t('I acknowledge I may lose data. Continue anyway.')); $session->statusCodeEquals(200); - // Need to update available and missing path lists. - $all_available = $this->getAvailablePaths(); - $all_available[] = 'aggregator'; - $all_missing = $this->getMissingPaths(); - $all_missing = array_diff($all_missing, ['aggregator']); - $this->assertReviewPage($session, $all_available, $all_missing); + // Run the incremental migration and check the results. $this->drupalPostForm(NULL, [], t('Perform upgrade')); $session->pageTextContains(t('Congratulations, you upgraded Drupal!')); $this->assertMigrationResults($this->getEntityCountsIncremental(), $version); diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php index bc73aba4c4..14274bc572 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php @@ -169,13 +169,13 @@ protected function assertUpgradePaths(WebAssert $session, array $available_paths * Helper method to assert the text on the 'Upgrade analysis report' page. * * @param \Drupal\Tests\WebAssert $session - * The current session. - * @param array $all_available - * Array of modules that will be upgraded. - * @param array $all_missing - * Array of modules that will not be upgraded. + * The web-assert session. + * @param array $available_paths + * An array of modules that will be upgraded. + * @param array $missing_paths + * An array of modules that will not be upgraded. */ - protected function assertReviewPage(WebAssert $session, array $all_available, array $all_missing) { + protected function assertReviewPage(WebAssert $session, array $available_paths, array $missing_paths) { $this->assertText('What will be upgraded?'); // Ensure there are no errors about the missing modules from the test module. @@ -185,17 +185,7 @@ protected function assertReviewPage(WebAssert $session, array $all_available, ar // Ensure there are no errors about any other missing migration providers. $session->pageTextNotContains(t('module not found')); - // Test the available migration paths. - foreach ($all_available as $available) { - $session->elementExists('xpath', "//span[contains(@class, 'checked') and text() = '$available']"); - $session->elementNotExists('xpath', "//span[contains(@class, 'error') and text() = '$available']"); - } - - // Test the missing migration paths. - foreach ($all_missing as $missing) { - $session->elementExists('xpath', "//span[contains(@class, 'error') and text() = '$missing']"); - $session->elementNotExists('xpath', "//span[contains(@class, 'checked') and text() = '$missing']"); - } + $this->assertUpgradePaths($session, $available_paths, $missing_paths); } /** diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/MultilingualReviewPageTestBase.php b/core/modules/migrate_drupal_ui/tests/src/Functional/MultilingualReviewPageTestBase.php index a200de6b84..16a7797c57 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/MultilingualReviewPageTestBase.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MultilingualReviewPageTestBase.php @@ -84,7 +84,8 @@ public function testMigrateUpgradeReviewPage() { $this->drupalPostForm(NULL, $this->edits, t('Review upgrade')); $this->drupalPostForm(NULL, [], t('I acknowledge I may lose data. Continue anyway.')); - // Test the upgrade paths. + // Test the upgrade paths. First remove the module from the available paths + // list. $available_paths = $this->getAvailablePaths(); $available_paths = array_diff($available_paths, [$module]); $missing_paths = $this->getMissingPaths(); @@ -138,6 +139,16 @@ public function prepare() { $conditions->condition('name', 'simpletest'); $update->condition($conditions); $update->execute(); + + // Create entries for D8 test modules. + $insert = $this->sourceDatabase->insert('system') + ->fields([ + 'filename' => 'migrate_status_active_test', + 'name' => 'migrate_status_active_test', + 'type' => 'module', + 'status' => 1, + ]); + $insert->execute(); } /** diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MultilingualReviewPageTest.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MultilingualReviewPageTest.php index 32ca9a150d..12f82efe19 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MultilingualReviewPageTest.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MultilingualReviewPageTest.php @@ -11,6 +11,8 @@ * * @group migrate_drupal_6 * @group migrate_drupal_ui + * + * @group legacy */ class MultilingualReviewPageTest extends MultilingualReviewPageTestBase { @@ -31,6 +33,11 @@ class MultilingualReviewPageTest extends MultilingualReviewPageTestBase { 'update', // Required for translation migrations. 'migrate_drupal_multilingual', + // Test migrations states. + 'migrate_state_finished_test', + 'migrate_state_not_finished_test', + // Test missing migrate_drupal.yml. + 'migrate_state_no_file_test', ]; /** @@ -53,55 +60,20 @@ protected function getSourceBasePath() { */ protected function getAvailablePaths() { return [ + // Aggregator is set not_finished in migrate_sate_not_finished_test. 'aggregator', - 'block', - 'book', - 'comment', - 'contact', - 'content', - 'date', - 'dblog', - 'email', - 'filefield', - 'filter', - 'forum', - 'i18n', - 'i18nblocks', - 'i18ncck', - 'i18nmenu', - 'i18nprofile', - 'i18nstrings', - 'i18ntaxonomy', - 'imagecache', - 'imagefield', - 'language', - 'link', - 'locale', - 'menu', - 'node', - 'nodereference', - 'optionwidgets', - 'path', - 'profile', - 'search', - 'statistics', - 'syslog', - 'system', - 'taxonomy', - 'text', - 'update', - 'upload', - 'user', - 'userreference', - // Include modules that do not have an upgrade path, defined in the - // $noUpgradePath property in MigrateUpgradeForm. 'blog', 'blogapi', + 'book', 'calendarsignup', 'color', + 'comment', + 'contact', + 'content', 'content_copy', 'content_multigroup', 'content_permissions', + 'date', 'date_api', 'date_locale', 'date_php4', @@ -110,27 +82,57 @@ protected function getAvailablePaths() { 'date_timezone', 'date_tools', 'datepicker', + 'dblog', 'ddblock', + 'email', 'event', 'fieldgroup', + 'filefield', 'filefield_meta', + 'filter', + 'forum', 'help', + 'i18nblocks', + 'i18ncontent', + 'i18nmenu', + 'i18npoll', + 'i18nprofile', 'i18nsync', 'imageapi', 'imageapi_gd', 'imageapi_imagemagick', + 'imagecache', 'imagecache_ui', + 'imagefield', 'jquery_ui', + 'link', + 'menu', + 'node', 'nodeaccess', + 'nodereference', 'number', 'openid', + 'optionwidgets', + 'path', + 'phone', 'php', 'ping', 'poll', + 'profile', + 'search', + 'statistics', + 'syslog', + 'system', + 'taxonomy', + 'text', 'throttle', 'tracker', 'translation', 'trigger', + 'update', + 'upload', + 'user', + 'userreference', 'variable', 'variable_admin', 'views_export', @@ -143,13 +145,18 @@ protected function getAvailablePaths() { */ protected function getMissingPaths() { return [ + // Block is set not_finished in migrate_sate_not_finished_test. + 'block', 'devel', 'devel_generate', 'devel_node_access', - 'i18ncontent', - 'i18npoll', + 'i18n', + 'i18ncck', + 'i18nstrings', + 'i18ntaxonomy', 'i18nviews', - 'phone', + 'locale', + 'migrate_status_active_test', 'views', ]; } diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/NoMultilingualReviewPageTest.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/NoMultilingualReviewPageTest.php index cab85e79af..469a73ca89 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/NoMultilingualReviewPageTest.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/NoMultilingualReviewPageTest.php @@ -12,6 +12,8 @@ * * @group migrate_drupal_6 * @group migrate_drupal_ui + * + * @group legacy */ class NoMultilingualReviewPageTest extends NoMultilingualReviewPageTestBase { @@ -28,6 +30,11 @@ class NoMultilingualReviewPageTest extends NoMultilingualReviewPageTestBase { 'syslog', 'tracker', 'update', + // Test migrations states. + 'migrate_state_finished_test', + 'migrate_state_not_finished_test', + // Test missing migrate_drupal.yml. + 'migrate_state_no_file_test', ]; /** @@ -51,47 +58,18 @@ protected function getSourceBasePath() { protected function getAvailablePaths() { return [ 'aggregator', - 'block', - 'book', - 'comment', - 'contact', - 'content', - 'date', - 'dblog', - 'email', - 'filefield', - 'filter', - 'forum', - 'imagecache', - 'imagefield', - 'language', - 'link', - 'locale', - 'menu', - 'node', - 'nodereference', - 'optionwidgets', - 'path', - 'profile', - 'search', - 'statistics', - 'syslog', - 'system', - 'taxonomy', - 'text', - 'update', - 'upload', - 'user', - 'userreference', - // Include modules that do not have an upgrade path, defined in the - // $noUpgradePath property in MigrateUpgradeForm. 'blog', 'blogapi', + 'book', 'calendarsignup', 'color', + 'comment', + 'contact', + 'content', 'content_copy', 'content_multigroup', 'content_permissions', + 'date', 'date_api', 'date_locale', 'date_php4', @@ -100,28 +78,52 @@ protected function getAvailablePaths() { 'date_timezone', 'date_tools', 'datepicker', + 'dblog', 'ddblock', + 'email', 'event', 'fieldgroup', + 'filefield', 'filefield_meta', + 'filter', + 'forum', 'help', - 'i18nstrings', - 'i18nsync', 'imageapi', 'imageapi_gd', 'imageapi_imagemagick', + 'imagecache', 'imagecache_ui', + 'imagefield', 'jquery_ui', + 'link', + 'locale', + 'menu', + 'node', 'nodeaccess', + 'nodereference', 'number', 'openid', + 'optionwidgets', + 'path', + 'phone', 'php', 'ping', 'poll', + 'profile', + 'search', + 'statistics', + 'syslog', + 'system', + 'taxonomy', + 'text', 'throttle', 'tracker', 'translation', 'trigger', + 'update', + 'upload', + 'user', + 'userreference', 'variable', 'variable_admin', 'views_export', @@ -129,11 +131,20 @@ protected function getAvailablePaths() { ]; } + /** + * {@inheritdoc} + */ + protected function getIncompletePaths() { + return []; + } + /** * {@inheritdoc} */ protected function getMissingPaths() { return [ + // Block is set not_finished in migrate_state_not_finished_test. + 'block', 'devel', 'devel_generate', 'devel_node_access', @@ -144,9 +155,11 @@ protected function getMissingPaths() { 'i18nmenu', 'i18npoll', 'i18nprofile', + 'i18nstrings', + 'i18nsync', 'i18ntaxonomy', 'i18nviews', - 'phone', + 'migrate_status_active_test', 'views', ]; } diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/NoMultilingualTest.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/NoMultilingualTest.php index a3f4f10dc8..2508c5b807 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/NoMultilingualTest.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/NoMultilingualTest.php @@ -128,7 +128,6 @@ protected function getAvailablePaths() { 'forum', 'imagecache', 'imagefield', - 'language', 'link', 'locale', 'menu', diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/Upgrade6Test.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/Upgrade6Test.php index 37de86efcd..a01813c378 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/Upgrade6Test.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/Upgrade6Test.php @@ -12,6 +12,8 @@ * The test method is provided by the MigrateUpgradeTestBase class. * * @group migrate_drupal_ui + * + * @group legacy */ class Upgrade6Test extends MigrateUpgradeExecuteTestBase { @@ -130,39 +132,33 @@ protected function getAvailablePaths() { 'contact', 'content', 'date', - 'dblog', 'email', 'filefield', 'filter', 'forum', - 'i18n', 'i18nblocks', - 'i18ncck', + 'i18ncontent', 'i18nmenu', 'i18nprofile', - 'i18nstrings', - 'i18ntaxonomy', + 'i18nsync', 'imagecache', 'imagefield', - 'language', - 'link', - 'locale', 'menu', 'node', 'nodereference', 'optionwidgets', 'path', - 'profile', 'search', 'statistics', 'system', 'taxonomy', 'text', + 'translation', 'upload', 'user', 'userreference', // Include modules that do not have an upgrade path and are enabled in the - // source database, defined in the $noUpgradePath property + // source database', defined in the $noUpgradePath property // in MigrateUpgradeForm. 'date_api', 'date_timezone', @@ -180,7 +176,11 @@ protected function getAvailablePaths() { */ protected function getMissingPaths() { return [ - 'i18ncontent', + 'i18n', + 'i18ncck', + 'i18nstrings', + 'i18ntaxonomy', + 'locale', ]; } diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MultilingualReviewPageTest.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MultilingualReviewPageTest.php index 5bde4b88ae..d8b22f1c98 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MultilingualReviewPageTest.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MultilingualReviewPageTest.php @@ -11,6 +11,8 @@ * * @group migrate_drupal_7 * @group migrate_drupal_ui + * + * @group legacy */ class MultilingualReviewPageTest extends MultilingualReviewPageTestBase { @@ -30,6 +32,11 @@ class MultilingualReviewPageTest extends MultilingualReviewPageTestBase { 'update', // Required for translation migrations. 'migrate_drupal_multilingual', + // Test migrations states. + 'migrate_state_finished_test', + 'migrate_state_not_finished_test', + // Test missing migrate_drupal.yml. + 'migrate_state_no_file_test', ]; /** @@ -52,55 +59,21 @@ protected function getSourceBasePath() { */ protected function getAvailablePaths() { return [ - 'aggregator', - 'block', + 'blog', 'book', + 'bulk_export', 'color', 'comment', 'contact', - 'date', - 'dblog', - 'email', - 'field', - 'field_sql_storage', - 'file', - 'filter', - 'forum', - 'image', - 'i18n_block', - 'language', - 'link', - 'list', - 'locale', - 'menu', - 'node', - 'number', - 'options', - 'path', - 'phone', - 'rdf', - 'search', - 'shortcut', - 'statistics', - 'syslog', - 'system', - 'taxonomy', - 'text', - 'tracker', - 'update', - 'user', - // Include modules that do not have an upgrade path, defined in the - // $noUpgradePath property in MigrateUpgradeForm. - 'blog', - 'bulk_export', 'contextual', 'ctools', 'ctools_access_ruleset', 'ctools_ajax_sample', 'ctools_custom_content', 'dashboard', - 'date_all_day', + 'date', 'date_api', + 'date_all_day', 'date_context', 'date_migrate', 'date_popup', @@ -108,28 +81,58 @@ protected function getAvailablePaths() { 'date_repeat_field', 'date_tools', 'date_views', + 'dblog', + 'email', 'entity', 'entity_feature', 'entity_token', - 'entityreference', 'entity_translation', + 'entityreference', + 'field', + 'field_sql_storage', 'field_ui', + 'file', + 'filter', + 'forum', 'help', + 'i18n_block', + 'image', + 'link', + 'list', + 'locale', + 'menu', + 'node', + 'number', 'openid', + 'options', 'overlay', 'page_manager', + 'path', + 'phone', 'php', 'poll', + 'profile', + 'rdf', + 'search', 'search_embedded_form', 'search_extra_type', 'search_node_tags', + 'shortcut', 'simpletest', + 'statistics', 'stylizer', + 'syslog', + 'system', + 'taxonomy', 'term_depth', + 'text', 'title', 'toolbar', + 'tracker', 'translation', 'trigger', + 'update', + 'user', 'views_content', 'views_ui', ]; @@ -140,6 +143,11 @@ protected function getAvailablePaths() { */ protected function getMissingPaths() { return [ + // Action is set not_finished in migrate_sate_not_finished_test. + // Aggregator is set not_finished in migrate_sate_not_finished_test. + 'aggregator', + // Block is set not_finished in migrate_sate_not_finished_test. + 'block', 'entity_translation_i18n_menu', 'entity_translation_upgrade', 'i18n', @@ -157,7 +165,7 @@ protected function getMissingPaths() { 'i18n_translation', 'i18n_user', 'i18n_variable', - 'profile', + 'migrate_status_active_test', 'variable', 'variable_admin', 'variable_realm', diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/NoMultilingualTest.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/NoMultilingualTest.php index a3958a7bf8..176827223c 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/NoMultilingualTest.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/NoMultilingualTest.php @@ -164,6 +164,13 @@ protected function getAvailablePaths() { ]; } + /** + * {@inheritdoc} + */ + protected function getIncompletePaths() { + return []; + } + /** * {@inheritdoc} */ diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/Upgrade7Test.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/Upgrade7Test.php index 9f6178e665..009f06f82b 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/Upgrade7Test.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/Upgrade7Test.php @@ -12,6 +12,8 @@ * The test method is provided by the MigrateUpgradeTestBase class. * * @group migrate_drupal_ui + * + * @group legacy */ class Upgrade7Test extends MigrateUpgradeExecuteTestBase { @@ -128,21 +130,22 @@ protected function getAvailablePaths() { 'color', 'comment', 'contact', + 'ctools', 'date', 'dblog', 'email', + 'entity_translation', 'entityreference', 'field', 'field_sql_storage', 'file', 'filter', 'forum', + 'i18n_block', 'i18n_variable', 'image', - 'language', 'link', 'list', - 'locale', 'menu', 'node', 'number', @@ -156,6 +159,7 @@ protected function getAvailablePaths() { 'system', 'taxonomy', 'text', + 'title', 'user', // Include modules that do not have an upgrade path and are enabled in the // source database, defined in the $noUpgradePath property @@ -180,6 +184,9 @@ protected function getAvailablePaths() { protected function getMissingPaths() { return [ 'i18n', + 'i18n_field', + 'i18n_string', + 'locale', 'variable', 'variable_realm', 'variable_store', diff --git a/core/modules/node/node.migrate_drupal.yml b/core/modules/node/node.migrate_drupal.yml new file mode 100644 index 0000000000..4b7099e9e7 --- /dev/null +++ b/core/modules/node/node.migrate_drupal.yml @@ -0,0 +1,6 @@ +finished: + 6: + content: node + node: node + 7: + node: node diff --git a/core/modules/options/options.migrate_drupal.yml b/core/modules/options/options.migrate_drupal.yml new file mode 100644 index 0000000000..a523c6432a --- /dev/null +++ b/core/modules/options/options.migrate_drupal.yml @@ -0,0 +1,6 @@ +finished: + 6: + optionwidgets: options + 7: + options: options + list: options diff --git a/core/modules/path/path.migrate_drupal.yml b/core/modules/path/path.migrate_drupal.yml new file mode 100644 index 0000000000..d8066b950d --- /dev/null +++ b/core/modules/path/path.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + path: path + 7: + path: path diff --git a/core/modules/rdf/rdf.migrate_drupal.yml b/core/modules/rdf/rdf.migrate_drupal.yml new file mode 100644 index 0000000000..8e9205d12c --- /dev/null +++ b/core/modules/rdf/rdf.migrate_drupal.yml @@ -0,0 +1,3 @@ +finished: + 7: + rdf: rdf diff --git a/core/modules/search/search.migrate_drupal.yml b/core/modules/search/search.migrate_drupal.yml new file mode 100644 index 0000000000..6011126e13 --- /dev/null +++ b/core/modules/search/search.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + search: search + 7: + search: search diff --git a/core/modules/shortcut/shortcut.migrate_drupal.yml b/core/modules/shortcut/shortcut.migrate_drupal.yml new file mode 100644 index 0000000000..f7901621ad --- /dev/null +++ b/core/modules/shortcut/shortcut.migrate_drupal.yml @@ -0,0 +1,3 @@ +finished: + 7: + shortcut: shortcut diff --git a/core/modules/simpletest/simpletest.migrate_drupal.yml b/core/modules/simpletest/simpletest.migrate_drupal.yml new file mode 100644 index 0000000000..f195ad82f3 --- /dev/null +++ b/core/modules/simpletest/simpletest.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + simpletest: simpletest + 7: + simpletest: simpletest diff --git a/core/modules/statistics/statistics.migrate_drupal.yml b/core/modules/statistics/statistics.migrate_drupal.yml new file mode 100644 index 0000000000..6d8189f7a8 --- /dev/null +++ b/core/modules/statistics/statistics.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + statistics: statistics + 7: + statistics: statistics diff --git a/core/modules/syslog/syslog.migrate_drupal.yml b/core/modules/syslog/syslog.migrate_drupal.yml new file mode 100644 index 0000000000..7573f7bd4a --- /dev/null +++ b/core/modules/syslog/syslog.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + syslog: syslog + 7: + syslog: syslog diff --git a/core/modules/system/system.migrate_drupal.yml b/core/modules/system/system.migrate_drupal.yml new file mode 100644 index 0000000000..b6e79c9b71 --- /dev/null +++ b/core/modules/system/system.migrate_drupal.yml @@ -0,0 +1,92 @@ +finished: + 6: + menu: system + system: system + # The following do not need an upgrade path. + blog: core + blogapi: core + calendarsignup: core + color: color + content_copy: core + content_multigroup: core + content_permissions: core + date_api: core + date_locale: core + date_php4: core + date_popup: core + date_repeat: core + date_timezone: core + date_tools: core + datepicker: core + ddblock: core + event: core + fieldgroup: core + filefield_meta: core + help: core + i18ncontent: content_translation + i18npoll: content_translation + i18nstrings: content_translation + i18nsync: content_translation + imageapi: core + imageapi_gd: core + imageapi_imagemagick: core + imagecache_ui: core + jquery_ui: core + nodeaccess: core + number: core + openid: core + php: core + ping: core + poll: core + throttle: core + tracker: core + translation: core + trigger: core + variable: core + variable_admin: core + views_export: core + views_ui: core + 7: + menu: system + system: system + # The following do not need an upgrade path. + blog: core + bulk_export: core + contextual: core + ctools: core + ctools_access_ruleset: core + ctools_ajax_sample: core + ctools_custom_content: core + dashboard: core + date_all_day: core + date_api: core + date_context: core + date_migrate: core + date_popup: core + date_repeat: core + date_repeat_field: core + date_tools: core + date_views: core + entity: core + entity_feature: core + entity_token: core + entityreference: core + field_ui: core + help: core + openid: core + overlay: core + page_manager: core + php: core + poll: core + search_embedded_form: core + search_extra_type: core + search_node_tags: core + simpletest: core + stylizer: core + term_depth: core + title: core + toolbar: core + translation: core + trigger: core + views_content: core + views_ui: core diff --git a/core/modules/taxonomy/taxonomy.migrate_drupal.yml b/core/modules/taxonomy/taxonomy.migrate_drupal.yml new file mode 100644 index 0000000000..5dd3d6ba85 --- /dev/null +++ b/core/modules/taxonomy/taxonomy.migrate_drupal.yml @@ -0,0 +1,9 @@ +finished: + 6: + taxonomy: + - core + - taxonomy + 7: + taxonomy: + - core + - taxonomy diff --git a/core/modules/telephone/telephone.migrate_drupal.yml b/core/modules/telephone/telephone.migrate_drupal.yml new file mode 100644 index 0000000000..0a39c8184a --- /dev/null +++ b/core/modules/telephone/telephone.migrate_drupal.yml @@ -0,0 +1,3 @@ +finished: + 7: + phone: telephone diff --git a/core/modules/text/text.migrate_drupal.yml b/core/modules/text/text.migrate_drupal.yml new file mode 100644 index 0000000000..013d02356a --- /dev/null +++ b/core/modules/text/text.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + text: text + 7: + text: text diff --git a/core/modules/tracker/tracker.migrate_drupal.yml b/core/modules/tracker/tracker.migrate_drupal.yml new file mode 100644 index 0000000000..eb162ad896 --- /dev/null +++ b/core/modules/tracker/tracker.migrate_drupal.yml @@ -0,0 +1,3 @@ +finished: + 7: + tracker: tracker diff --git a/core/modules/update/update.migrate_drupal.yml b/core/modules/update/update.migrate_drupal.yml new file mode 100644 index 0000000000..b411c89220 --- /dev/null +++ b/core/modules/update/update.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + update: update + 7: + update: update diff --git a/core/modules/user/user.migrate_drupal.yml b/core/modules/user/user.migrate_drupal.yml new file mode 100644 index 0000000000..ddf6b8575d --- /dev/null +++ b/core/modules/user/user.migrate_drupal.yml @@ -0,0 +1,7 @@ +finished: + 6: + profile: user + user: user + 7: + profile: user + user: user