diff --git a/core/modules/action/action.migrate.yml b/core/modules/action/action.migrate.yml new file mode 100644 index 0000000000..7a656547ca --- /dev/null +++ b/core/modules/action/action.migrate.yml @@ -0,0 +1,7 @@ +finished: + 6: + system: action + action: action + 7: + system: action + action: action diff --git a/core/modules/aggregator/aggregator.migrate.yml b/core/modules/aggregator/aggregator.migrate.yml new file mode 100644 index 0000000000..fe63da70bf --- /dev/null +++ b/core/modules/aggregator/aggregator.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + aggregator: aggregator + 7: + aggregator: aggregator diff --git a/core/modules/ban/ban.migrate.yml b/core/modules/ban/ban.migrate.yml new file mode 100644 index 0000000000..34231fdd2d --- /dev/null +++ b/core/modules/ban/ban.migrate.yml @@ -0,0 +1,3 @@ +finished: + 7: + system: ban diff --git a/core/modules/block/block.migrate.yml b/core/modules/block/block.migrate.yml new file mode 100644 index 0000000000..74cdfc7191 --- /dev/null +++ b/core/modules/block/block.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + block: block + 7: + block: block diff --git a/core/modules/block_content/block_content.migrate.yml b/core/modules/block_content/block_content.migrate.yml new file mode 100644 index 0000000000..88391eed00 --- /dev/null +++ b/core/modules/block_content/block_content.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + block: block_content + 7: + block: block_content diff --git a/core/modules/book/book.migrate.yml b/core/modules/book/book.migrate.yml new file mode 100644 index 0000000000..c47d1e973f --- /dev/null +++ b/core/modules/book/book.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + book: book + 7: + book: book diff --git a/core/modules/color/color.migrate.yml b/core/modules/color/color.migrate.yml new file mode 100644 index 0000000000..60e95b99eb --- /dev/null +++ b/core/modules/color/color.migrate.yml @@ -0,0 +1,3 @@ +finished: + 7: + color: color diff --git a/core/modules/comment/comment.migrate.yml b/core/modules/comment/comment.migrate.yml new file mode 100644 index 0000000000..51dc1a0290 --- /dev/null +++ b/core/modules/comment/comment.migrate.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.yml b/core/modules/config_translation/config_translation.migrate.yml new file mode 100644 index 0000000000..7b4518fed4 --- /dev/null +++ b/core/modules/config_translation/config_translation.migrate.yml @@ -0,0 +1,22 @@ +finished: + 6: + i18nprofile: config_translation + 7: + i18n_variable: config_translation +not_finished: + 6: + # language content comment settings. + locale: language + i18n: config_translation + # field labels and descriptions, synchronized fields. + i18ncck: config_translation + # + i18ntaxonomy: config_translation + 7: + # language content comment settings. + locale: language + i18n: config_translation + # field labels and descriptions, field options. + i18n_field: config_translation + # localized. vocabulary language settings, taxonomy term language. + i18n_taxonomy: config_translation diff --git a/core/modules/contact/contact.migrate.yml b/core/modules/contact/contact.migrate.yml new file mode 100644 index 0000000000..6b186b4299 --- /dev/null +++ b/core/modules/contact/contact.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + contact: contact + 7: + contact: contact diff --git a/core/modules/content_translation/content_translation.migrate.yml b/core/modules/content_translation/content_translation.migrate.yml new file mode 100644 index 0000000000..59d4f44172 --- /dev/null +++ b/core/modules/content_translation/content_translation.migrate.yml @@ -0,0 +1,23 @@ +finished: + 6: + i18nblocks: content_translation + i18nmenu: content_translation + menu: content_translation + statistics: statistics + taxonomy: content_translation + 7: + block: content_translation + entity_translation: content_translation + i18n_block: content_translation + menu: content_translation + statistics: statistics +not_finished: + # Also D6 an D7 node revision translations. + 6: + # Taxonomy term references. + i18ntaxonomy: content_translation + 7: + # menu links. + i18n_menu: content_translation + # localized. + i18n_taxonomy: content_translation diff --git a/core/modules/datetime/datetime.migrate.yml b/core/modules/datetime/datetime.migrate.yml new file mode 100644 index 0000000000..a4434b627e --- /dev/null +++ b/core/modules/datetime/datetime.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + date: datetime + 7: + date: datetime diff --git a/core/modules/dblog/dblog.migrate.yml b/core/modules/dblog/dblog.migrate.yml new file mode 100644 index 0000000000..b048ff1920 --- /dev/null +++ b/core/modules/dblog/dblog.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + dblog: dblog + 7: + dblog: dblog diff --git a/core/modules/field/field.migrate.yml b/core/modules/field/field.migrate.yml new file mode 100644 index 0000000000..1be6f48605 --- /dev/null +++ b/core/modules/field/field.migrate.yml @@ -0,0 +1,10 @@ +finished: + 6: + content: field + email: core + 7: + email: core + entityreference: core + field: field + field_sql_storage: field + number: core diff --git a/core/modules/file/file.migrate.yml b/core/modules/file/file.migrate.yml new file mode 100644 index 0000000000..cfee09a25c --- /dev/null +++ b/core/modules/file/file.migrate.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.yml b/core/modules/filter/filter.migrate.yml new file mode 100644 index 0000000000..fa671e830d --- /dev/null +++ b/core/modules/filter/filter.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + filter: filter + 7: + filter: filter diff --git a/core/modules/forum/forum.migrate.yml b/core/modules/forum/forum.migrate.yml new file mode 100644 index 0000000000..5b91754541 --- /dev/null +++ b/core/modules/forum/forum.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + forum: forum + 7: + forum: forum diff --git a/core/modules/image/image.migrate.yml b/core/modules/image/image.migrate.yml new file mode 100644 index 0000000000..b87b9c7b1a --- /dev/null +++ b/core/modules/image/image.migrate.yml @@ -0,0 +1,6 @@ +finished: + 6: + imagecache: image + imagefield: image + 7: + image: image diff --git a/core/modules/language/language.migrate.yml b/core/modules/language/language.migrate.yml new file mode 100644 index 0000000000..f50f8fdc29 --- /dev/null +++ b/core/modules/language/language.migrate.yml @@ -0,0 +1,7 @@ +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.yml b/core/modules/link/link.migrate.yml new file mode 100644 index 0000000000..4352ab4c76 --- /dev/null +++ b/core/modules/link/link.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + link: link + 7: + link: link diff --git a/core/modules/locale/locale.migrate.yml b/core/modules/locale/locale.migrate.yml new file mode 100644 index 0000000000..5d4e806b80 --- /dev/null +++ b/core/modules/locale/locale.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + locale: locale + 7: + locale: locale diff --git a/core/modules/menu_link_content/menu_link_content.migrate.yml b/core/modules/menu_link_content/menu_link_content.migrate.yml new file mode 100644 index 0000000000..cb21ebe01b --- /dev/null +++ b/core/modules/menu_link_content/menu_link_content.migrate.yml @@ -0,0 +1,6 @@ +finished: + 6: + menu: menu_link_content + 7: + menu: menu_link_content + diff --git a/core/modules/menu_ui/menu_ui.migrate.yml b/core/modules/menu_ui/menu_ui.migrate.yml new file mode 100644 index 0000000000..55597fecfe --- /dev/null +++ b/core/modules/menu_ui/menu_ui.migrate.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.yml b/core/modules/migrate_drupal/migrate_drupal.migrate.yml new file mode 100644 index 0000000000..db703dc95d --- /dev/null +++ b/core/modules/migrate_drupal/migrate_drupal.migrate.yml @@ -0,0 +1,4 @@ +finished: + 6: + nodereference: core + userreference: core diff --git a/core/modules/migrate_drupal/src/MigrationConfigurationTrait.php b/core/modules/migrate_drupal/src/MigrationConfigurationTrait.php index f17768ef3b..3b6f57d21e 100644 --- a/core/modules/migrate_drupal/src/MigrationConfigurationTrait.php +++ b/core/modules/migrate_drupal/src/MigrationConfigurationTrait.php @@ -97,7 +97,7 @@ protected function createDatabaseStateSettings(array $database, $drupal_version) * @return \Drupal\migrate\Plugin\MigrationInterface[] * The migrations for import. */ - protected function getMigrations($database_state_key, $drupal_version) { + public function getMigrations($database_state_key, $drupal_version) { $version_tag = 'Drupal ' . $drupal_version; $plugin_manager = \Drupal::service('plugin.manager.migration'); /** @var \Drupal\migrate\Plugin\Migration[] $all_migrations */ @@ -210,4 +210,22 @@ protected function getLegacyDrupalVersion(Connection $connection) { return $version_string ? substr($version_string, 0, 1) : FALSE; } + /** + * {@inheritdoc} + */ + protected function getMigrationStates($version) { + /** @var \Drupal\migrate_drupal_ui\MigrationState $migration_state */ + $migration_state = \Drupal::service('migrate_drupal_ui.migration_state'); + return $migration_state->getMigrationStates($version); + } + + /** + * {@inheritdoc} + */ + protected function getUpgradeCategory($version, array $source_system_data, array $migrations) { + /** @var \Drupal\migrate_drupal_ui\MigrationState $migration_state */ + $migration_state = \Drupal::service('migrate_drupal_ui.migration_state'); + return $migration_state->getUpgradeCategory($version, $source_system_data, $migrations); + } + } diff --git a/core/modules/migrate_drupal_multilingual/migrate_drupal_multilingual.migrate.yml b/core/modules/migrate_drupal_multilingual/migrate_drupal_multilingual.migrate.yml new file mode 100644 index 0000000000..d733618809 --- /dev/null +++ b/core/modules/migrate_drupal_multilingual/migrate_drupal_multilingual.migrate.yml @@ -0,0 +1,6 @@ +# Multilingual is not finished until this module is removed. +not_finished: + 6: + i18n: i18n + 7: + i18n: i18n diff --git a/core/modules/migrate_drupal_ui/migrate_drupal_ui.services.yml b/core/modules/migrate_drupal_ui/migrate_drupal_ui.services.yml new file mode 100644 index 0000000000..36196e8bbb --- /dev/null +++ b/core/modules/migrate_drupal_ui/migrate_drupal_ui.services.yml @@ -0,0 +1,4 @@ +services: + migrate_drupal_ui.migration_state: + class: Drupal\migrate_drupal_ui\MigrationState + diff --git a/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php b/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php index 6ef9dd564c..7661c9501f 100644 --- a/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php +++ b/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php @@ -5,24 +5,46 @@ 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\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.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 */ class ReviewForm extends MigrateUpgradeFormBase { /** + * Source modules status for will be upgraded. + * + * @var string + */ + const FINISHED = 'finished'; + + /** + * Source modules status for will not be upgraded. + * + * @var string + */ + const NOT_FINISHED = 'not_finished'; + + + /** * The state service. * * @var \Drupal\Core\State\StateInterface @@ -51,101 +73,11 @@ class ReviewForm extends MigrateUpgradeFormBase { protected $migrations; /** - * 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. + * Display data. * - * @var array[] + * @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', - '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 $display; /** * ReviewForm constructor. @@ -192,9 +124,14 @@ 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'); + // Remove core profiles from the system data. + foreach (['standard', 'minimal'] as $profile) { + unset($system_data['module'][$profile]); + } + // If data is missing or this is the wrong step, start over. if (!$version || !$this->migrations || !$system_data || ($this->store->get('step') != 'review')) { @@ -204,58 +141,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 categories for the migrations. + $display = $this->getUpgradeCategory($version, $system_data, $migrations); // Missing migrations. $missing_module_list = [ @@ -263,7 +152,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 +162,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[static::NOT_FINISHED])) { + foreach ($display[static::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 +181,9 @@ public function buildForm(array $form, FormStateInterface $form_state) { ], ], ], - 'destination_module' => ['#plain_text' => 'Not upgraded'], + 'destination_module' => [ + '#plain_text' => $destination_modules, + ], ]; } } @@ -300,7 +193,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 +205,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[static::FINISHED])) { + foreach ($display[static::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 +244,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/src/MigrationState.php b/core/modules/migrate_drupal_ui/src/MigrationState.php new file mode 100644 index 0000000000..9938c260f0 --- /dev/null +++ b/core/modules/migrate_drupal_ui/src/MigrationState.php @@ -0,0 +1,427 @@ + [ + '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', + ], + ]; + + /** + * Construct a new MigrationStatus object. + */ + public function __construct() { + $this->fieldPluginManager = \Drupal::service('plugin.manager.migrate.field'); + } + + /** + * Gets the upgrade status for a source module. + * + * @param string $version + * The legacy Drupal version. + * @param array $source_system_data + * The destination system data. + * @param array $migrations + * The migrations. + * + * @return array + * An associative array of data keyed by the display categories, 'error' + * and 'checked'. + * The migration state array. The key is the name of the source module and + * the value is a comma separated list of destination modules. For example, + * ['menu' => 'menu_link_content','menu_ui','system']. + */ + public function getUpgradeCategory($version, array $source_system_data, array $migrations) { + /** @var \Drupal\migrate_drupal_ui\MigrationState $migrate_status */ + $migration_state = \Drupal::service('migrate_drupal_ui.migration_state'); + return $migration_state->buildUpgradeCategory($version, $source_system_data, $migrations); + } + + /** + * Gets migration state information from *.migrate.yml. + * + * @param string $version + * The legacy Drupal version. + * + * @return array + * The migration state array. The key is the name of the source module and + * the value is a comma separated list of destination modules. For example, + * ['menu' => 'menu_link_content','menu_ui','system']. + */ + public function getMigrationStates($version) { + // Always instantiate a new YamlDiscovery object so that we always search on + // the up-to-date list of modules. + /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */ + $module_handler = \Drupal::service('module_handler'); + $discovery = new YamlDiscovery('migrate', $module_handler->getModuleDirectories()); + return $discovery->findAll(); + } + + /** + * Determines migration status 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 status is set to FINISHED. If it is not listed + * in NoUpgradePath list the status is to NOT_FINISHED. + * + * When there are migrations for a module the following happens. If the + * destination module is 'core' the status is set to FINISHED. If there are + * any occurrences of 'not_finished' in the .migrate.yml information for this + * source module then the status is set to NOT_FINISHED otherwise the status + * 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 keyed by the display categories, 'error' + * and 'checked'. + * The migration state array. The key is the name of the source module and + * the value is a comma separated list of destination modules. For example, + * ['menu' => 'menu_link_content','menu_ui','system']. + */ + protected function buildUpgradeCategory($version, array $source_system_data, array $migrations) { + $source_destinations = $this->getSourceDestinations($version, $migrations); + $by_source = $this->getMigrationStatesBySource($version); + $upgrade_category = []; + // Loop through every source module that is enabled on the source site. + foreach ($source_system_data['module'] as $module) { + $source_module = $module['name']; + if ($module['status']) { + // Set the defaults to display. + $destination_modules = []; + $migration_state = static::NOT_FINISHED; + + // If there is a declared state for this source module, check the + // actual migrations to decide the final state. + if (isset($by_source[$source_module])) { + // Get the destination modules for this source module. + $destination_modules = isset($source_destinations[$source_module]) ? $source_destinations[$source_module] : []; + foreach ($by_source[$source_module] as $destination_module) { + // Some field plugins use a destination_module of 'core'. + if ($destination_module === 'core') { + $migration_state = static::FINISHED; + continue; + } + // Check the destination site system info for the status of the + // migrations for this source_module. + if (isset($by_source[$source_module])) { + // If migrations and no declaration then it is not finished. + if (empty($by_source[$source_module])) { + $migration_state = static::NOT_FINISHED; + continue; + } + // If 'not_finished' declared then it is not finished. + if (in_array('not_finished', $by_source[$source_module])) { + $migration_state = static::NOT_FINISHED; + continue; + } + // If 'finished' declared then it is finished. + if (in_array('finished', $by_source[$source_module])) { + $migration_state = static::FINISHED; + } + } + } + } + else { + // This may be a no upgrade path. + if (in_array($source_module, $this->noUpgradePaths[$version])) { + $migration_state = static::FINISHED; + $destination_modules = ['core']; + } + } + $destination_modules = array_unique($destination_modules); + sort($destination_modules); + $category = $migration_state; + $upgrade_category[$category][$source_module] = implode(', ', $destination_modules); + } + } + foreach ($upgrade_category as $key => $value) { + ksort($upgrade_category[$key]); + } + return $upgrade_category; + } + + /** + * Builds migration source and destination module information. + * + * @param string $version + * The legacy Drupal version. + * @param array $migrations + * The discovered migrations. + * + * @return array + * Array of migrations, keyed by source_module and destination_module. Only + * migrations that have both a source_module and a destination_module + * definition are added to the array. + */ + protected function getSourceDestinations($version, array $migrations) { + $source_destinations = []; + 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) { + $source_destinations[$source_module][] = $destination_module; + } + } + + // Add entries for the field plugins to source_destinations. + $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']; + $source_destinations[$source_module][] = $destination_module; + } + } + + // Remove duplicate destination_modules. + foreach ($source_destinations as $key => $destination_modules) { + $source_destinations[$key] = array_unique($destination_modules); + } + return $source_destinations; + } + + /** + * Gets migration data from *.migrate.yml sorted by source module. + * + * @param string $version + * The legacy Drupal version. + * + * @return array + * An array of migration states declared for each source migration. The key + * is the name of the source module and the value is an array of all the + * categories declared for this source module. + * Example + * + * @code + * 'some_source_module' => [ + * 'finished', + * 'finished', + * 'not_finished', + * ] + * @endcode + */ + protected function getMigrationStatesBySource($version) { + $migration_states = $this->getMigrationStates($version); + + $by_source = []; + $states = ['finished', 'not_finished']; + foreach ($migration_states as $module => $info) { + foreach ($states as $state) { + if (isset($info[$state])) { + foreach ($info[$state] as $info_version => $migrate_info) { + if ($info_version == $version) { + foreach ($migrate_info as $source => $destination) { + $by_source[$source][] = $state; + } + } + } + } + } + } + return $by_source; + } + +} diff --git a/core/modules/migrate_drupal_ui/tests/modules/migrate_status_finished_test/migrate_status_finished_test.info.yml b/core/modules/migrate_drupal_ui/tests/modules/migrate_status_finished_test/migrate_status_finished_test.info.yml new file mode 100644 index 0000000000..c71b30f2c0 --- /dev/null +++ b/core/modules/migrate_drupal_ui/tests/modules/migrate_status_finished_test/migrate_status_finished_test.info.yml @@ -0,0 +1,6 @@ +name: 'Migrate status active test' +type: module +description: "Tests the 'active' migrate status" +package: Testing +version: VERSION +core: 8.x diff --git a/core/modules/migrate_drupal_ui/tests/modules/migrate_status_finished_test/migrate_status_finished_test.migrate.yml b/core/modules/migrate_drupal_ui/tests/modules/migrate_status_finished_test/migrate_status_finished_test.migrate.yml new file mode 100644 index 0000000000..4be42906ac --- /dev/null +++ b/core/modules/migrate_drupal_ui/tests/modules/migrate_status_finished_test/migrate_status_finished_test.migrate.yml @@ -0,0 +1,16 @@ +finished: + 6: + # A field migration + # migrate_status_finished_test: migrate_status_finished_test + aggregator: migrate_status_finished_test + action: migrate_status_finished_test, migrate_status_not_finished_test + 7: + # A field migration + # migrate_status_finished_test: migrate_status_finished_test + aggregator: migrate_status_finished_test + # Migrations + action: migrate_status_finished_test, migrate_status_not_finished_test +not_finished: + 7: + # Migrations + action: system diff --git a/core/modules/migrate_drupal_ui/tests/modules/migrate_status_finished_test/migrations/migrate_status_finished_test.yml b/core/modules/migrate_drupal_ui/tests/modules/migrate_status_finished_test/migrations/migrate_status_finished_test.yml new file mode 100644 index 0000000000..f39c1fad31 --- /dev/null +++ b/core/modules/migrate_drupal_ui/tests/modules/migrate_status_finished_test/migrations/migrate_status_finished_test.yml @@ -0,0 +1,20 @@ +id: migrate_status_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_status_finished_test + diff --git a/core/modules/migrate_drupal_ui/tests/modules/migrate_status_finished_test/migrations/migrate_status_finished_test1.yml b/core/modules/migrate_drupal_ui/tests/modules/migrate_status_finished_test/migrations/migrate_status_finished_test1.yml new file mode 100644 index 0000000000..3ee3254fe5 --- /dev/null +++ b/core/modules/migrate_drupal_ui/tests/modules/migrate_status_finished_test/migrations/migrate_status_finished_test1.yml @@ -0,0 +1,19 @@ +id: migrate_status_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_status_not_finished_test diff --git a/core/modules/migrate_drupal_ui/tests/modules/migrate_status_finished_test/src/Plugin/migrate/field/FieldLeft.php b/core/modules/migrate_drupal_ui/tests/modules/migrate_status_finished_test/src/Plugin/migrate/field/FieldLeft.php new file mode 100644 index 0000000000..c2bfcc81d5 --- /dev/null +++ b/core/modules/migrate_drupal_ui/tests/modules/migrate_status_finished_test/src/Plugin/migrate/field/FieldLeft.php @@ -0,0 +1,16 @@ +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..4cc71c8c33 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 @@ -31,6 +31,9 @@ class MultilingualReviewPageTest extends MultilingualReviewPageTestBase { 'update', // Required for translation migrations. 'migrate_drupal_multilingual', + // Test migrations statuses. + 'migrate_status_finished_test', + 'migrate_status_not_finished_test', ]; /** @@ -54,7 +57,6 @@ protected function getSourceBasePath() { protected function getAvailablePaths() { return [ 'aggregator', - 'block', 'book', 'comment', 'contact', @@ -65,18 +67,13 @@ protected function getAvailablePaths() { 'filefield', 'filter', 'forum', - 'i18n', 'i18nblocks', - 'i18ncck', 'i18nmenu', 'i18nprofile', 'i18nstrings', - 'i18ntaxonomy', 'imagecache', 'imagefield', - 'language', 'link', - 'locale', 'menu', 'node', 'nodereference', @@ -146,9 +143,15 @@ protected function getMissingPaths() { 'devel', 'devel_generate', 'devel_node_access', + 'block', + 'i18n', + 'i18ncck', 'i18ncontent', 'i18npoll', + 'i18ntaxonomy', 'i18nviews', + 'locale', + 'migrate_status_active_test', 'phone', '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..fdddedf121 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 @@ -64,7 +64,6 @@ protected function getAvailablePaths() { 'forum', 'imagecache', 'imagefield', - 'language', 'link', 'locale', 'menu', @@ -132,6 +131,13 @@ protected function getAvailablePaths() { /** * {@inheritdoc} */ + protected function getIncompletePaths() { + return []; + } + + /** + * {@inheritdoc} + */ protected function getMissingPaths() { return [ 'devel', @@ -146,6 +152,7 @@ protected function getMissingPaths() { 'i18nprofile', 'i18ntaxonomy', 'i18nviews', + 'migrate_status_active_test', 'phone', '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..c2cb25d0cc 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 @@ -130,39 +130,33 @@ protected function getAvailablePaths() { 'contact', 'content', 'date', - 'dblog', 'email', 'filefield', 'filter', 'forum', - 'i18n', 'i18nblocks', - 'i18ncck', '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 +174,11 @@ protected function getAvailablePaths() { */ protected function getMissingPaths() { return [ + 'i18n', + 'i18ncck', 'i18ncontent', + '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..4e7b314a2b 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 @@ -61,14 +61,13 @@ protected function getAvailablePaths() { 'date', 'dblog', 'email', - 'field', + 'entity_translation', 'field_sql_storage', 'file', 'filter', 'forum', 'image', 'i18n_block', - 'language', 'link', 'list', 'locale', @@ -112,7 +111,7 @@ protected function getAvailablePaths() { 'entity_feature', 'entity_token', 'entityreference', - 'entity_translation', + 'field', 'field_ui', 'help', 'openid', @@ -163,6 +162,7 @@ protected function getMissingPaths() { 'variable_realm', 'variable_store', 'variable_views', + 'migrate_status_active_test', 'views', ]; } 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 @@ -167,6 +167,13 @@ protected function getAvailablePaths() { /** * {@inheritdoc} */ + protected function getIncompletePaths() { + return []; + } + + /** + * {@inheritdoc} + */ protected function getMissingPaths() { return [ // These modules are in the missing path list because they are installed 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..7c465d5e32 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 @@ -128,21 +128,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 +157,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 +182,9 @@ protected function getAvailablePaths() { protected function getMissingPaths() { return [ 'i18n', + 'i18n_field', + 'i18n_string', + 'locale', 'variable', 'variable_realm', 'variable_store', diff --git a/core/modules/migrate_drupal_ui/tests/src/Kernel/ValidateMigrationStateTest.php b/core/modules/migrate_drupal_ui/tests/src/Kernel/ValidateMigrationStateTest.php new file mode 100644 index 0000000000..289fbc32ed --- /dev/null +++ b/core/modules/migrate_drupal_ui/tests/src/Kernel/ValidateMigrationStateTest.php @@ -0,0 +1,160 @@ +enableAllModules(); + + /** @var \Drupal\migrate\Plugin\MigrationPluginManager $plugin_manager */ + $plugin_manager = $this->container->get('plugin.manager.migration'); + + // 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. + $migration_data = []; + $migration_data_with_migration = []; + $versions = ['6', '7']; + foreach ($versions as $version) { + $migrations = $plugin_manager->createInstancesByTag('Drupal ' . $version); + /** @var \Drupal\migrate\Plugin\Migration $migration */ + foreach ($migrations as $migration) { + $id = $migration->getBaseId(); + $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(); + + $tmp = implode(static::SEPARATOR, [ + $version, + $provider, + $source_module, + $destination_module, + ]); + $migration_data[] = $tmp; + $migration_data_with_migration[$tmp][] = $id; + } + } + + /** @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) { + $tmp = implode(static::SEPARATOR, [ + $version, + $definition['provider'], + $definition['source_module'], + $definition['destination_module'], + ]); + $migration_data[] = $tmp; + $migration_data_with_migration[$tmp][] = $definition['id']; + } + } + + // Get the migrate information from .migrate.yml and build an array of + // source modules and there migration status. 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 = $this->getMigrationStates($version); + + $system_data = []; + $properties = ['finished', 'not_finished']; + foreach ($system_info as $module => $info) { + foreach ($properties as $property) { + if (isset($info[$property])) { + foreach ($info[$property] as $info_version => $migrate_info) { + foreach ($migrate_info as $source => $destination) { + // Destination is a CSV. + $tmp = str_getcsv($destination); + foreach ($tmp as $dest) { + $key = [$info_version, $module, $source, trim($dest)]; + $system_data[$property][] = implode(static::SEPARATOR, $key); + } + } + } + } + } + } + + sort($system_data['finished']); + sort($system_data['not_finished']); + $system_data_unique['finished'] = array_unique($system_data['finished']); + $system_data_unique['not_finished'] = array_unique($system_data['not_finished']); + sort($migration_data); + $migration_data_unique = array_unique($migration_data); + + // Assert that each migration status declared finished in .migrate.yml is in + // the list of discovered migrations. The migrations not finished are not + // checked because the migration does not need to exist yet. + foreach ($system_data_unique['finished'] as $datum) { + $data = str_getcsv($datum); + $msg = 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]); + $this->assertContains($datum, $migration_data_unique, $msg); + } + + // Assert that each migration has a corresponding declaration in the system + // .migrate.yml files. + foreach ($migration_data_unique as $datum) { + $data = str_getcsv($datum); + $msg = sprintf("No migrate status found for version '%s' with source_module '%s' and destination_module '%s' declared in module '%s'", $data[0], $data[2], $data[3], $data[1]); + $in_finished = in_array($datum, $system_data_unique['finished']); + $in_not_finished = in_array($datum, $system_data_unique['not_finished']); + $found = $in_finished || $in_not_finished; + $this->assertTrue($found, $msg); + } + } + + /** + * 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); + } + +} diff --git a/core/modules/node/node.migrate.yml b/core/modules/node/node.migrate.yml new file mode 100644 index 0000000000..4b7099e9e7 --- /dev/null +++ b/core/modules/node/node.migrate.yml @@ -0,0 +1,6 @@ +finished: + 6: + content: node + node: node + 7: + node: node diff --git a/core/modules/options/options.migrate.yml b/core/modules/options/options.migrate.yml new file mode 100644 index 0000000000..a523c6432a --- /dev/null +++ b/core/modules/options/options.migrate.yml @@ -0,0 +1,6 @@ +finished: + 6: + optionwidgets: options + 7: + options: options + list: options diff --git a/core/modules/path/path.migrate.yml b/core/modules/path/path.migrate.yml new file mode 100644 index 0000000000..d8066b950d --- /dev/null +++ b/core/modules/path/path.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + path: path + 7: + path: path diff --git a/core/modules/rdf/rdf.migrate.yml b/core/modules/rdf/rdf.migrate.yml new file mode 100644 index 0000000000..8e9205d12c --- /dev/null +++ b/core/modules/rdf/rdf.migrate.yml @@ -0,0 +1,3 @@ +finished: + 7: + rdf: rdf diff --git a/core/modules/search/search.migrate.yml b/core/modules/search/search.migrate.yml new file mode 100644 index 0000000000..6011126e13 --- /dev/null +++ b/core/modules/search/search.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + search: search + 7: + search: search diff --git a/core/modules/shortcut/shortcut.migrate.yml b/core/modules/shortcut/shortcut.migrate.yml new file mode 100644 index 0000000000..f7901621ad --- /dev/null +++ b/core/modules/shortcut/shortcut.migrate.yml @@ -0,0 +1,3 @@ +finished: + 7: + shortcut: shortcut diff --git a/core/modules/simpletest/simpletest.migrate.yml b/core/modules/simpletest/simpletest.migrate.yml new file mode 100644 index 0000000000..f195ad82f3 --- /dev/null +++ b/core/modules/simpletest/simpletest.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + simpletest: simpletest + 7: + simpletest: simpletest diff --git a/core/modules/statistics/statistics.migrate.yml b/core/modules/statistics/statistics.migrate.yml new file mode 100644 index 0000000000..6d8189f7a8 --- /dev/null +++ b/core/modules/statistics/statistics.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + statistics: statistics + 7: + statistics: statistics diff --git a/core/modules/syslog/syslog.migrate.yml b/core/modules/syslog/syslog.migrate.yml new file mode 100644 index 0000000000..7573f7bd4a --- /dev/null +++ b/core/modules/syslog/syslog.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + syslog: syslog + 7: + syslog: syslog diff --git a/core/modules/system/system.migrate.yml b/core/modules/system/system.migrate.yml new file mode 100644 index 0000000000..0175174a28 --- /dev/null +++ b/core/modules/system/system.migrate.yml @@ -0,0 +1,7 @@ +finished: + 6: + menu: system + system: system + 7: + menu: system + system: system diff --git a/core/modules/taxonomy/taxonomy.migrate.yml b/core/modules/taxonomy/taxonomy.migrate.yml new file mode 100644 index 0000000000..cc2bb13e8f --- /dev/null +++ b/core/modules/taxonomy/taxonomy.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + taxonomy: core, taxonomy + 7: + taxonomy: core, taxonomy diff --git a/core/modules/telephone/telephone.migrate.yml b/core/modules/telephone/telephone.migrate.yml new file mode 100644 index 0000000000..0a39c8184a --- /dev/null +++ b/core/modules/telephone/telephone.migrate.yml @@ -0,0 +1,3 @@ +finished: + 7: + phone: telephone diff --git a/core/modules/text/text.migrate.yml b/core/modules/text/text.migrate.yml new file mode 100644 index 0000000000..013d02356a --- /dev/null +++ b/core/modules/text/text.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + text: text + 7: + text: text diff --git a/core/modules/tracker/tracker.migrate.yml b/core/modules/tracker/tracker.migrate.yml new file mode 100644 index 0000000000..eb162ad896 --- /dev/null +++ b/core/modules/tracker/tracker.migrate.yml @@ -0,0 +1,3 @@ +finished: + 7: + tracker: tracker diff --git a/core/modules/update/update.migrate.yml b/core/modules/update/update.migrate.yml new file mode 100644 index 0000000000..b411c89220 --- /dev/null +++ b/core/modules/update/update.migrate.yml @@ -0,0 +1,5 @@ +finished: + 6: + update: update + 7: + update: update diff --git a/core/modules/user/user.migrate.yml b/core/modules/user/user.migrate.yml new file mode 100644 index 0000000000..ddf6b8575d --- /dev/null +++ b/core/modules/user/user.migrate.yml @@ -0,0 +1,7 @@ +finished: + 6: + profile: user + user: user + 7: + profile: user + user: user