Issue #2936365 by quietone, mikelutz, heddn, larowlan, masipila, effulgentsia, maxocub, Gábor Hojtsy, webchick, phenaproxima, jhodgdon, catch: Migrate UI - allow modules to declare the state of their migrations
parent
0d82715b4b
commit
c1734c6185
|
|
@ -8,7 +8,7 @@ source:
|
|||
plugin: variable
|
||||
variables:
|
||||
- actions_max_stack
|
||||
source_module: action
|
||||
source_module: system
|
||||
process:
|
||||
recursion_limit: actions_max_stack
|
||||
destination:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
system: action
|
||||
7:
|
||||
system: action
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
aggregator: aggregator
|
||||
7:
|
||||
aggregator: aggregator
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
finished:
|
||||
7:
|
||||
system: ban
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
block: block
|
||||
7:
|
||||
block: block
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
block: block_content
|
||||
7:
|
||||
block: block_content
|
||||
|
|
@ -11,7 +11,7 @@ use Drupal\content_translation\Plugin\migrate\source\I18nQueryTrait;
|
|||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_block_custom_translation",
|
||||
* source_module = "block"
|
||||
* source_module = "i18n_block"
|
||||
* )
|
||||
*/
|
||||
class BlockCustomTranslation extends DrupalSqlBase {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
book: book
|
||||
7:
|
||||
book: book
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
finished:
|
||||
7:
|
||||
color: color
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
finished:
|
||||
6:
|
||||
comment: comment
|
||||
node: comment
|
||||
7:
|
||||
comment: comment
|
||||
node: comment
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
contact: contact
|
||||
7:
|
||||
contact: contact
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
finished:
|
||||
6:
|
||||
i18nblocks:
|
||||
- block
|
||||
- block_content
|
||||
- content_translation
|
||||
i18nmenu:
|
||||
- content_translation
|
||||
- menu_link_content
|
||||
locale: content_translation
|
||||
menu: content_translation
|
||||
statistics: statistics
|
||||
taxonomy: content_translation
|
||||
7:
|
||||
entity_translation: content_translation
|
||||
i18n_block:
|
||||
- block
|
||||
- block_content
|
||||
- content_translation
|
||||
locale: content_translation
|
||||
menu: content_translation
|
||||
statistics: statistics
|
||||
|
||||
not_finished:
|
||||
# Also D6 and 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
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
date: datetime
|
||||
7:
|
||||
date: datetime
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
dblog: dblog
|
||||
7:
|
||||
dblog: dblog
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
finished:
|
||||
6:
|
||||
filefield: file
|
||||
system: file
|
||||
upload: file
|
||||
7:
|
||||
file: file
|
||||
system: file
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
filter: filter
|
||||
7:
|
||||
filter: filter
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
forum: forum
|
||||
7:
|
||||
forum: forum
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
finished:
|
||||
6:
|
||||
imagecache: image
|
||||
imagefield: image
|
||||
7:
|
||||
image: image
|
||||
|
|
@ -7,7 +7,7 @@ source:
|
|||
plugin: variable
|
||||
variables:
|
||||
- language_negotiation
|
||||
source_module: language
|
||||
source_module: locale
|
||||
process:
|
||||
session/parameter:
|
||||
plugin: default_value
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ source:
|
|||
plugin: variable
|
||||
variables:
|
||||
- language_negotiation
|
||||
source_module: language
|
||||
source_module: locale
|
||||
process:
|
||||
all:
|
||||
plugin: default_value
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
finished:
|
||||
6:
|
||||
locale:
|
||||
- language
|
||||
- system
|
||||
system: language
|
||||
taxonomy: language
|
||||
7:
|
||||
locale:
|
||||
- language
|
||||
- system
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
link: link
|
||||
7:
|
||||
link: link
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
locale: locale
|
||||
7:
|
||||
locale: locale
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
menu: menu_link_content
|
||||
7:
|
||||
menu: menu_link_content
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
menu: menu_ui
|
||||
7:
|
||||
menu: menu_ui
|
||||
|
|
@ -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' => [
|
||||
|
|
|
|||
|
|
@ -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']
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
# The modules listed here do not have an migration. A status of finished is
|
||||
# assigned so that they appear in the will not be upgraded list on the Review
|
||||
# form.
|
||||
finished:
|
||||
6:
|
||||
nodereference: core
|
||||
userreference: core
|
||||
# Blog requires node.
|
||||
blog: node
|
||||
# The following do not have an upgrade path.
|
||||
blogapi: core
|
||||
calendarsignup: core
|
||||
color: core
|
||||
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
|
||||
# i18n modules require content_translation.
|
||||
i18ncontent: content_translation
|
||||
i18npoll: content_translation
|
||||
i18nstrings: content_translation
|
||||
i18nsync: content_translation
|
||||
imageapi: core
|
||||
imageapi_gd: core
|
||||
imageapi_imagemagick: core
|
||||
imagecache_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:
|
||||
# Blog requires node.
|
||||
blog: node
|
||||
# The following do not need have an upgrade path.
|
||||
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
|
||||
|
|
@ -0,0 +1,494 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal;
|
||||
|
||||
use Drupal\Core\Discovery\YamlDiscovery;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Messenger\MessengerInterface;
|
||||
use Drupal\Core\Messenger\MessengerTrait;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||
use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface;
|
||||
|
||||
/**
|
||||
* Determines the migrate state for all modules enabled on the source.
|
||||
*
|
||||
* Retrieves migrate info from *.migrate_drupal.yml files.
|
||||
*
|
||||
* Knowing which modules will be upgraded and those that will not is needed by
|
||||
* anyone upgrading a legacy Drupal version. This service provides that
|
||||
* information by analyzing the existing migrations and data in
|
||||
* migrate_drupal.yml files. Modules that are enabled or disabled in the source
|
||||
* are included in the analysis modules that are uninstalled are ignored.
|
||||
*
|
||||
* Deciding the upgrade state of a source module is a complicated task. A
|
||||
* destination module is not limited in any way to the source modules or the
|
||||
* current major version destination modules it is providing migrations for. We
|
||||
* see this in core where the Drupal 6 Menu module is upgraded by having
|
||||
* migrations in three Drupal 8 modules; menu_link_content, menu_ui and system.
|
||||
* If migrations for any of those three modules are not complete or if any of
|
||||
* them are not installed on the destination site then the Drupal 6 Menu module
|
||||
* cannot be listed as upgraded. If any one of the conditions are not met then
|
||||
* it should be listed as will not be upgraded.
|
||||
*
|
||||
* Another challenge is to ensure that legacy source modules that do not need an
|
||||
* upgrade path are handled correctly. These will not have migrations but should
|
||||
* be listed as will be upgraded, which even though there are not migrations
|
||||
* under the hood, it lets a site admin know that upgrading with this module
|
||||
* enabled is safe.
|
||||
*
|
||||
* There is not enough information in the existing system to determine the
|
||||
* correct state of the upgrade path for these, and other scenarios.
|
||||
*
|
||||
* The solution is for every destination module that is the successor to a
|
||||
* module built for a legacy Drupal version to declare the state of the upgrade
|
||||
* path(s) for the module. A module's upgrade path from a previous version may
|
||||
* consist of one or more migrations sets. Each migration set definition
|
||||
* consists of a source module supporting a legacy Drupal version, and one or
|
||||
* more current destination modules. This allows a module to indicate that a
|
||||
* provided migration set requires additional modules to be enabled in the
|
||||
* destination.
|
||||
*
|
||||
* A migration set can be marked 'finished', which indicates that all
|
||||
* migrations that are going to be provided by this destination module for this
|
||||
* migration set have been written and are complete. A migration set may also
|
||||
* be marked 'not_finished' which indicates that the module either has not
|
||||
* provided any migrations for the set, or needs to provide additional
|
||||
* migrations to complete the set. Note that other modules may still provide
|
||||
* additional finished or not_finished migrations for the same migration set.
|
||||
*
|
||||
* Modules inform the upgrade process of the migration sets by adding them to
|
||||
* their <module_name>.migrate_drupal.yml file.
|
||||
*
|
||||
* The <module_name>.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.
|
||||
* <source_module_1>: <destination_module_1>
|
||||
* <source_module_2>:
|
||||
* - <destination_module_1>
|
||||
* - <destination_module_2>
|
||||
* 7:
|
||||
* <source_module_1>: <destination_module_1>
|
||||
* <source_module_2>:
|
||||
* - <destination_module_1>
|
||||
* - <destination_module_2>
|
||||
* # (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:
|
||||
* <source_module_1>: <destination_module_1>
|
||||
* <source_module_2>:
|
||||
* - <destination_module_1>
|
||||
* - <destination_module_2>
|
||||
*
|
||||
* 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: <any module name>' 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 $discoveredBySource;
|
||||
|
||||
/**
|
||||
* 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 = [];
|
||||
|
||||
/**
|
||||
* 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', array_map(function (&$value) {
|
||||
return $value . '/migrations/state';
|
||||
}, $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 no declared state the state is
|
||||
* set to NOT_FINISHED. When a module does not need any migrations, such as
|
||||
* Overlay, a state of finished is declared in system.migrate_drupal.yml.
|
||||
*
|
||||
* 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])) {
|
||||
// No migrations found for this source module.
|
||||
if (!empty($this->unmigratedSourceModules[$version]) && array_key_exists($source_module, $this->unmigratedSourceModules[$version])) {
|
||||
$upgrade_state[static::NOT_FINISHED][$source_module] = '';
|
||||
continue;
|
||||
}
|
||||
if (!empty($this->migratedSourceModules[$version]) && array_key_exists($source_module, $this->migratedSourceModules[$version])) {
|
||||
@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_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'];
|
||||
}
|
||||
}
|
||||
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->discoveredBySource[$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->discoveredBySource[$version] += [$source_module => []];
|
||||
$this->declaredBySource[$version] += [$source_module => []];
|
||||
$destination = array_unique(array_merge($this->discoveredBySource[$version][$source_module], $this->declaredBySource[$version][$source_module]));
|
||||
sort($destination);
|
||||
$this->destinations[$version][$source_module] = $destination;
|
||||
}
|
||||
return $this->destinations[$version][$source_module];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
name: Migrate state active test
|
||||
type: module
|
||||
description: Tests the 'active' migrate state
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\migrate_state_active_test\Plugin\migrate\field\d7;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
|
||||
|
||||
/**
|
||||
* Field migration for testing migration states.
|
||||
*
|
||||
* @MigrateField(
|
||||
* id = "fieldleft",
|
||||
* core = {6,7},
|
||||
* source_module = "aggregator",
|
||||
* destination_module = "migrate_state_finished_test"
|
||||
* )
|
||||
*/
|
||||
class FieldLeft extends FieldPluginBase {
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\migrate_state_active_test\Plugin\migrate\field\d7;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
|
||||
|
||||
/**
|
||||
* Field migration for testing migration states.
|
||||
*
|
||||
* @MigrateField(
|
||||
* id = "fieldright",
|
||||
* core = {6,7},
|
||||
* source_module = "aggregator",
|
||||
* destination_module = "migrate_state_finished_test"
|
||||
* )
|
||||
*/
|
||||
class FieldRight extends FieldPluginBase {
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
name: Migrate state no migrate_drupal.yml file test
|
||||
type: module
|
||||
description: Has a migration but Does not have a migrate_drupal.yml file.
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
id: migrate_state_no_file_test
|
||||
label: Test
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: embedded_data
|
||||
data_rows:
|
||||
-
|
||||
id: 1
|
||||
ids:
|
||||
id:
|
||||
type: string
|
||||
source_module: migrate_state_no_file_test
|
||||
process: []
|
||||
destination:
|
||||
plugin: entity:field_config
|
||||
destination_module: migrate_state_no_file_test
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
name: Migrate state no migration and no migrate_drupal.yml file test
|
||||
type: module
|
||||
description: Does not have a migration or migrate_drupal.yml file.
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
name: Migrate state incomplete test
|
||||
type: module
|
||||
description: Tests the 'incomplete' migrate state
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
id: migrate_state_not_finished_test
|
||||
label: Migrate state incomplete test
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: embedded_data
|
||||
data_rows:
|
||||
-
|
||||
entity_type: block_content
|
||||
ids:
|
||||
entity_type:
|
||||
type: string
|
||||
source_module: block
|
||||
process:
|
||||
entity_type: entity_type
|
||||
destination:
|
||||
plugin: entity:field_config
|
||||
destination_module: migrate_state_not_finished_test
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
not_finished:
|
||||
6:
|
||||
block: migrate_state_not_finished_test
|
||||
7:
|
||||
# Override any finished declarations for this field plugin.
|
||||
aggregator: field_left
|
||||
# Override any finished declarations for this migration.
|
||||
action: migrate_state_not_finished_test
|
||||
block: migrate_state_not_finished_test
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Defines a class for testing deprecation error from MigrationState.
|
||||
*
|
||||
* @group migrate_drupal
|
||||
* @group legacy
|
||||
*/
|
||||
class MigrationStateDeprecationTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'migrate_drupal',
|
||||
'migrate',
|
||||
'migrate_state_no_file_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* Tests migration state deprecation notice.
|
||||
*
|
||||
* Test that a module with a migration but without a .migrate_drupal.yml
|
||||
* trigger deprecation errors.
|
||||
*
|
||||
* @doesNotPerformAssertions
|
||||
* @expectedDeprecation Using migration plugin definitions to determine the migration state of the module 'migrate_state_no_file_test' is deprecated in Drupal 8.7. Add the module to a migrate_drupal.yml file. See https://www.drupal.org/node/2929443
|
||||
*/
|
||||
public function testUndeclaredDestinationDeprecation() {
|
||||
$plugin_manager = \Drupal::service('plugin.manager.migration');
|
||||
$all_migrations = $plugin_manager->createInstancesByTag('Drupal 7');
|
||||
|
||||
\Drupal::service('migrate_drupal.migration_state')
|
||||
->getUpgradeStates(7, [
|
||||
'module' => [
|
||||
'migrate_state_no_file_test' => [
|
||||
'name' => 'migrate_state_no_file_test',
|
||||
'status' => TRUE,
|
||||
],
|
||||
],
|
||||
], ['import' => $all_migrations['migrate_state_no_file_test']]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel;
|
||||
|
||||
use Drupal\Component\Discovery\YamlDiscovery;
|
||||
use Drupal\KernelTests\FileSystemModuleDiscoveryDataProviderTrait;
|
||||
use Drupal\migrate_drupal\MigrationConfigurationTrait;
|
||||
|
||||
/**
|
||||
* Tests that core modules have a migrate_drupal.yml file as needed.
|
||||
*
|
||||
* Checks that each module that requires a migrate_drupal.yml has the file.
|
||||
* Because more that one migrate_drupal.yml file may have the same entry the
|
||||
* ValidateMigrationStateTest, which validates the file contents, is not able
|
||||
* to determine that all the required files exits.
|
||||
*
|
||||
* @group migrate_drupal
|
||||
*/
|
||||
class StateFileExists extends MigrateDrupalTestBase {
|
||||
|
||||
use FileSystemModuleDiscoveryDataProviderTrait;
|
||||
use MigrationConfigurationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
// Test migrations states.
|
||||
'migrate_state_finished_test',
|
||||
'migrate_state_not_finished_test',
|
||||
// Test missing migrate_drupal.yml.
|
||||
'migrate_state_no_file_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* Modules that should have a migrate_drupal.yml file.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $stateFileRequired = [
|
||||
'action',
|
||||
'aggregator',
|
||||
'ban',
|
||||
'block',
|
||||
'block_content',
|
||||
'book',
|
||||
'color',
|
||||
'comment',
|
||||
'config_translation',
|
||||
'contact',
|
||||
'content_translation',
|
||||
'datetime',
|
||||
'dblog',
|
||||
'field',
|
||||
'file',
|
||||
'filter',
|
||||
'forum',
|
||||
'image',
|
||||
'language',
|
||||
'link',
|
||||
'locale',
|
||||
'menu_link_content',
|
||||
'migrate_state_finished_test',
|
||||
'migrate_state_not_finished_test',
|
||||
'menu_ui',
|
||||
'migrate_drupal',
|
||||
'node',
|
||||
'options',
|
||||
'path',
|
||||
'rdf',
|
||||
'search',
|
||||
'shortcut',
|
||||
'simpletest',
|
||||
'statistics',
|
||||
'syslog',
|
||||
'system',
|
||||
'taxonomy',
|
||||
'telephone',
|
||||
'text',
|
||||
'tracker',
|
||||
'update',
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* Tests that the migrate_drupal.yml files exist as needed.
|
||||
*/
|
||||
public function testMigrationState() {
|
||||
// Install all available modules.
|
||||
$module_handler = $this->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', array_map(function (&$value) {
|
||||
return $value . '/migrations/state';
|
||||
}, $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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel;
|
||||
|
||||
use Drupal\Component\Discovery\YamlDiscovery;
|
||||
use Drupal\KernelTests\FileSystemModuleDiscoveryDataProviderTrait;
|
||||
use Drupal\migrate_drupal\MigrationState;
|
||||
|
||||
/**
|
||||
* Tests the migration state information in module.migrate_drupal.yml.
|
||||
*
|
||||
* This test checks that the discovered upgrade paths, which are based on the
|
||||
* source_module and destination_module definition matches the declared
|
||||
* upgrade paths in all the migrate_drupal.yml files.
|
||||
*
|
||||
* @group migrate_drupal
|
||||
*/
|
||||
class ValidateMigrationStateTest extends MigrateDrupalTestBase {
|
||||
|
||||
use FileSystemModuleDiscoveryDataProviderTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
// Test migrations states.
|
||||
'migrate_state_finished_test',
|
||||
'migrate_state_not_finished_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* Level separator of destination and source properties.
|
||||
*/
|
||||
const SEPARATOR = ',';
|
||||
|
||||
/**
|
||||
* Tests the migration information in .migrate_drupal.yml.
|
||||
*
|
||||
* Checks that every discovered pair has a corresponding declaration in the
|
||||
* declared pairs. The alternate check, that each declared pair has a
|
||||
* corresponding discovered pair is not possible because declarations can be
|
||||
* made for the two cases where migrations are yet to be written and where
|
||||
* migrations are not needed.
|
||||
*/
|
||||
public function testMigrationState() {
|
||||
$this->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', array_map(function (&$value) {
|
||||
return $value . '/migrations/state/';
|
||||
}, \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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,618 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Unit;
|
||||
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Messenger\MessengerInterface;
|
||||
use Drupal\migrate\Plugin\MigrateDestinationInterface;
|
||||
use Drupal\migrate\Plugin\MigrateSourceInterface;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate_drupal\MigrationState;
|
||||
use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use org\bovigo\vfs\vfsStream;
|
||||
use org\bovigo\vfs\vfsStreamDirectory;
|
||||
use org\bovigo\vfs\vfsStreamWrapper;
|
||||
|
||||
/**
|
||||
* Defines a class for testing \Drupal\migrate_drupal\MigrationState.
|
||||
*
|
||||
* @group migrate_drupal
|
||||
* @group legacy
|
||||
*
|
||||
* @coversDefaultClass \Drupal\migrate_drupal\MigrationState
|
||||
*/
|
||||
class MigrationStateUnitTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests ::getUpgradeStates.
|
||||
*
|
||||
* @dataProvider providerGetUpgradeStates
|
||||
*
|
||||
* @covers ::getUpgradeStates
|
||||
* @covers ::buildDiscoveredDestinationsBySource
|
||||
* @covers ::buildDeclaredStateBySource
|
||||
* @covers ::buildUpgradeState
|
||||
* @covers ::getMigrationStates
|
||||
* @covers ::getSourceState
|
||||
* @covers ::getDestinationsForSource
|
||||
*/
|
||||
public function testGetUpgradeStates($modules_to_enable, $files, $field_plugins, $migrations, $source_system_data, $expected_7, $expected_6) {
|
||||
$fieldPluginManager = $this->prophesize(MigrateFieldPluginManagerInterface::class);
|
||||
$fieldPluginManager->getDefinitions()->willReturn($field_plugins);
|
||||
$moduleHandler = $this->prophesize(ModuleHandlerInterface::class);
|
||||
$moduleHandler->getModuleList()->willReturn($modules_to_enable);
|
||||
vfsStreamWrapper::register();
|
||||
$root = new vfsStreamDirectory('modules');
|
||||
vfsStreamWrapper::setRoot($root);
|
||||
$url = vfsStream::url('modules');
|
||||
|
||||
foreach ($files as $module => $contents) {
|
||||
$path = $url . '/' . $module . '/migrations/state';
|
||||
mkdir($path, '0755', TRUE);
|
||||
file_put_contents($path . '/' . $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());
|
||||
|
||||
$all_migrations = [];
|
||||
foreach ($migrations as $name => $values) {
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
$source = $this->prophesize(MigrateSourceInterface::class);
|
||||
$destination = $this->prophesize(MigrateDestinationInterface::class);
|
||||
$source->getSourceModule()->willReturn($values['source_module']);
|
||||
$destination->getDestinationModule()
|
||||
->willReturn($values['destination_module']);
|
||||
$migration->getSourcePlugin()->willReturn($source->reveal());
|
||||
$migration->getDestinationPlugin()->willReturn($destination->reveal());
|
||||
$migration->getPluginId()->willReturn($name);
|
||||
$migration->label()->willReturn($name);
|
||||
$all_migrations[] = $migration->reveal();
|
||||
}
|
||||
|
||||
// Tests Drupal 7 states.
|
||||
$states = $migrationState->getUpgradeStates(7, $source_system_data, $all_migrations);
|
||||
$this->assertEquals($expected_7, $states);
|
||||
$source_system_data['module']['content'] = [
|
||||
'name' => 'content',
|
||||
'status' => TRUE,
|
||||
];
|
||||
|
||||
// Tests Drupal 6 states.
|
||||
unset($source_system_data['module']['rdf'], $source_system_data['module']['filter']);
|
||||
$states = $migrationState->getUpgradeStates(6, $source_system_data, []);
|
||||
$this->assertEquals($expected_6, $states);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testGetUpgradeStates.
|
||||
*/
|
||||
public function providerGetUpgradeStates() {
|
||||
|
||||
// Tests multiple scenarios:
|
||||
// Not enabled and not declared.
|
||||
// Destination module is not enabled.
|
||||
// Destination module not enabled.
|
||||
// Declared not finished.
|
||||
// Not finished.
|
||||
// No discovered or declared state.
|
||||
// Declared finished by one module but not finished by another.
|
||||
// Not declared and non compatible field plugin.
|
||||
// Update path not needed.
|
||||
$tests[0] = [
|
||||
'modules_to_enable' => [
|
||||
'entity_test' => [],
|
||||
'node' => [],
|
||||
'link' => [],
|
||||
'rdf' => [],
|
||||
],
|
||||
'files' => [
|
||||
'node' => <<<NODE
|
||||
finished:
|
||||
6:
|
||||
content: node
|
||||
node: node
|
||||
7:
|
||||
node: node
|
||||
NODE
|
||||
,
|
||||
'entity_test' => <<<ENTITY_TEST
|
||||
not_finished:
|
||||
6:
|
||||
entity_test: entity_test
|
||||
7:
|
||||
entity_test:
|
||||
- entity_test
|
||||
- entity_test_rev
|
||||
ENTITY_TEST
|
||||
,
|
||||
'comment' => <<<COMMENT
|
||||
finished:
|
||||
6:
|
||||
comment:
|
||||
- comment
|
||||
- node
|
||||
7:
|
||||
comment:
|
||||
- comment
|
||||
- node
|
||||
COMMENT
|
||||
,
|
||||
'user' => <<<USER
|
||||
finished:
|
||||
6:
|
||||
user: user
|
||||
7:
|
||||
user: user
|
||||
USER
|
||||
,
|
||||
'profile' => <<<PROFILE
|
||||
not_finished:
|
||||
6:
|
||||
profile: user
|
||||
7:
|
||||
profile: user
|
||||
PROFILE
|
||||
,
|
||||
],
|
||||
'field_plugins' => [
|
||||
'datetime' => [
|
||||
'id' => 'datetime',
|
||||
'core' => [7],
|
||||
'source_module' => 'date',
|
||||
'destination_module' => 'datetime',
|
||||
],
|
||||
'link' => [
|
||||
'id' => 'link',
|
||||
'core' => [6, 7],
|
||||
'source_module' => 'link',
|
||||
'destination_module' => 'link',
|
||||
],
|
||||
],
|
||||
'migrations' => [
|
||||
'rdf' => [
|
||||
'source_module' => 'rdf',
|
||||
'destination_module' => 'rdf',
|
||||
],
|
||||
'filter' => [
|
||||
'source_module' => 'filter',
|
||||
'destination_module' => '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,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
'expected_7' => [
|
||||
MigrationState::NOT_FINISHED => [
|
||||
// Not enabled and not declared.
|
||||
'color' => '',
|
||||
// Destination module comment is not enabled.
|
||||
'comment' => 'comment, node',
|
||||
// Destination module not enabled.
|
||||
'date' => 'datetime',
|
||||
// Declared not finished.
|
||||
'entity_test' => 'entity_test, entity_test_rev',
|
||||
// Destination module not enabled.
|
||||
'filter' => 'filter',
|
||||
// Not finished.
|
||||
'profile' => 'user',
|
||||
// No discovered or declared state.
|
||||
'search' => '',
|
||||
// Declared finished by one module but not finished by another.
|
||||
'user' => 'user',
|
||||
],
|
||||
MigrationState::FINISHED => [
|
||||
'link' => 'link',
|
||||
'node' => 'node',
|
||||
'rdf' => 'rdf',
|
||||
],
|
||||
],
|
||||
'expected_6' => [
|
||||
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' => '',
|
||||
'color' => '',
|
||||
],
|
||||
MigrationState::FINISHED => [
|
||||
'node' => 'node',
|
||||
'content' => 'node',
|
||||
// Update path not needed.
|
||||
'link' => 'link',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Test menu migration with all three required destination modules enabled.
|
||||
$tests[1] = [
|
||||
'modules_to_enable' => [
|
||||
'menu_link_content' => [],
|
||||
'menu_ui' => [],
|
||||
'system' => [],
|
||||
],
|
||||
'files' => [
|
||||
'system' => <<<SYSTEM
|
||||
finished:
|
||||
6:
|
||||
menu:
|
||||
- system
|
||||
- menu_link_content
|
||||
- menu_ui
|
||||
7:
|
||||
menu:
|
||||
- system
|
||||
- menu_link_content
|
||||
- menu_ui
|
||||
SYSTEM
|
||||
,
|
||||
'menu_link_content' => <<<MENU_LINK_CONTENT
|
||||
finished:
|
||||
6:
|
||||
menu: menu_link_content
|
||||
7:
|
||||
menu: menu_link_content
|
||||
MENU_LINK_CONTENT
|
||||
,
|
||||
'menu' => <<<MENU_UI
|
||||
finished:
|
||||
6:
|
||||
menu: menu_ui
|
||||
7:
|
||||
menu: menu_ui
|
||||
MENU_UI
|
||||
,
|
||||
],
|
||||
'field_plugins' => [],
|
||||
'migrations' => [
|
||||
'system' => [
|
||||
'source_module' => 'menu',
|
||||
'destination_module' => 'system',
|
||||
],
|
||||
'menu_ui' => [
|
||||
'source_module' => 'menu',
|
||||
'destination_module' => 'menu_ui',
|
||||
],
|
||||
'menu_link_content' => [
|
||||
'source_module' => 'menu',
|
||||
'destination_module' => 'menu_link_content',
|
||||
],
|
||||
],
|
||||
'source_system_data' => [
|
||||
'module' => [
|
||||
'menu' => [
|
||||
'name' => 'menu',
|
||||
'status' => TRUE,
|
||||
],
|
||||
'system' => [
|
||||
'name' => 'system',
|
||||
'status' => TRUE,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
'expected_7' => [
|
||||
MigrationState::NOT_FINISHED => [
|
||||
'system' => '',
|
||||
],
|
||||
MigrationState::FINISHED => [
|
||||
'menu' => 'menu_link_content, menu_ui, system',
|
||||
],
|
||||
],
|
||||
'expected_6' => [
|
||||
MigrationState::NOT_FINISHED => [
|
||||
'system' => '',
|
||||
'content' => '',
|
||||
],
|
||||
MigrationState::FINISHED => [
|
||||
'menu' => 'menu_link_content, menu_ui, system',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Test menu migration with menu_link_content uninstalled.
|
||||
$tests[2] = $tests[1];
|
||||
unset($tests[2]['modules_to_enable']['menu_link_content']);
|
||||
unset($tests[2]['files']['menu_link_content']);
|
||||
unset($tests[2]['migrations']['menu_link_content']);
|
||||
$tests[2]['expected_7'] = [
|
||||
MigrationState::NOT_FINISHED => [
|
||||
'menu' => 'menu_link_content, menu_ui, system',
|
||||
'system' => '',
|
||||
],
|
||||
];
|
||||
$tests[2]['expected_6'] = [
|
||||
MigrationState::NOT_FINISHED => [
|
||||
'menu' => 'menu_link_content, menu_ui, system',
|
||||
'system' => '',
|
||||
'content' => '',
|
||||
],
|
||||
];
|
||||
|
||||
// Test menu migration with menu_ui uninstalled.
|
||||
$tests[3] = $tests[1];
|
||||
unset($tests[3]['modules_to_enable']['menu_ui']);
|
||||
unset($tests[3]['files']['menu_ui']);
|
||||
unset($tests[3]['migrations']['menu_ui']);
|
||||
$tests[3]['expected_7'] = [
|
||||
MigrationState::NOT_FINISHED => [
|
||||
'menu' => 'menu_link_content, menu_ui, system',
|
||||
'system' => '',
|
||||
],
|
||||
];
|
||||
$tests[3]['expected_6'] = [
|
||||
MigrationState::NOT_FINISHED => [
|
||||
'menu' => 'menu_link_content, menu_ui, system',
|
||||
'system' => '',
|
||||
'content' => '',
|
||||
],
|
||||
];
|
||||
|
||||
// Test an i18n migration with all three required destination modules
|
||||
// enabled.
|
||||
$tests[4] = [
|
||||
'modules_to_enable' => [
|
||||
'block' => [],
|
||||
'block_content' => [],
|
||||
'content_translation' => [],
|
||||
'system' => [],
|
||||
],
|
||||
'files' => [
|
||||
'system' => <<<SYSTEM
|
||||
finished:
|
||||
6:
|
||||
i18nblocks:
|
||||
- block
|
||||
- block_content
|
||||
- content_translation
|
||||
7:
|
||||
i18nblocks:
|
||||
- block
|
||||
- block_content
|
||||
- content_translation
|
||||
SYSTEM
|
||||
,
|
||||
'block' => <<<BLOCK
|
||||
finished:
|
||||
6:
|
||||
block: block
|
||||
7:
|
||||
block: block
|
||||
BLOCK
|
||||
,
|
||||
'block_content' => <<<BLOCK_CONTENT
|
||||
finished:
|
||||
6:
|
||||
block: block_content
|
||||
7:
|
||||
block: block_content
|
||||
BLOCK_CONTENT
|
||||
,
|
||||
],
|
||||
'field_plugins' => [],
|
||||
'migrations' => [
|
||||
'block' => [
|
||||
'source_module' => 'block',
|
||||
'destination_module' => 'block',
|
||||
],
|
||||
'block_content' => [
|
||||
'source_module' => 'block',
|
||||
'destination_module' => 'block_content',
|
||||
],
|
||||
'i18nblocks' => [
|
||||
'source_module' => 'i18nblocks',
|
||||
'destination_module' => 'content_translation',
|
||||
],
|
||||
],
|
||||
'source_system_data' => [
|
||||
'module' => [
|
||||
'block' => [
|
||||
'name' => 'block',
|
||||
'status' => TRUE,
|
||||
],
|
||||
'i18nblocks' => [
|
||||
'name' => 'i18nblocks',
|
||||
'status' => TRUE,
|
||||
],
|
||||
'system' => [
|
||||
'name' => 'system',
|
||||
'status' => TRUE,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
'expected_7' => [
|
||||
MigrationState::NOT_FINISHED => [
|
||||
'system' => '',
|
||||
],
|
||||
MigrationState::FINISHED => [
|
||||
'block' => 'block, block_content',
|
||||
'i18nblocks' => 'block, block_content, content_translation',
|
||||
],
|
||||
],
|
||||
'expected_6' => [
|
||||
MigrationState::NOT_FINISHED => [
|
||||
'system' => '',
|
||||
'content' => '',
|
||||
],
|
||||
MigrationState::FINISHED => [
|
||||
'block' => 'block, block_content',
|
||||
'i18nblocks' => 'block, block_content, content_translation',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Test i18n_block migration with block uninstalled.
|
||||
$tests[5] = $tests[4];
|
||||
unset($tests[5]['modules_to_enable']['block']);
|
||||
unset($tests[5]['files']['block']);
|
||||
unset($tests[5]['migrations']['block']);
|
||||
$tests[5]['expected_7'] = [
|
||||
MigrationState::NOT_FINISHED => [
|
||||
'system' => '',
|
||||
'i18nblocks' => 'block, block_content, content_translation',
|
||||
],
|
||||
MigrationState::FINISHED => [
|
||||
'block' => 'block_content',
|
||||
],
|
||||
];
|
||||
$tests[5]['expected_6'] = [
|
||||
MigrationState::NOT_FINISHED => [
|
||||
'system' => '',
|
||||
'content' => '',
|
||||
'i18nblocks' => 'block, block_content, content_translation',
|
||||
],
|
||||
MigrationState::FINISHED => [
|
||||
'block' => 'block_content',
|
||||
],
|
||||
];
|
||||
|
||||
// Tests modules that don't require an upgrade path.
|
||||
$tests[6] = [
|
||||
'modules_to_enable' => [
|
||||
'system' => [],
|
||||
'content_translation' => [],
|
||||
],
|
||||
'files' => [
|
||||
'system' => <<<SYSTEM
|
||||
finished:
|
||||
6:
|
||||
help: core
|
||||
i18ncontent: content_translation
|
||||
7:
|
||||
help: core
|
||||
i18ncontent: content_translation
|
||||
SYSTEM
|
||||
,
|
||||
],
|
||||
'field_plugins' => [],
|
||||
'migrations' => [],
|
||||
'source_system_data' => [
|
||||
'module' => [
|
||||
'system' => [
|
||||
'name' => 'system',
|
||||
'status' => TRUE,
|
||||
],
|
||||
'help' => [
|
||||
'name' => 'help',
|
||||
'status' => TRUE,
|
||||
],
|
||||
'i18ncontent' => [
|
||||
'name' => 'i18ncontent',
|
||||
'status' => TRUE,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
'expected_7' => [
|
||||
MigrationState::NOT_FINISHED => [
|
||||
'system' => '',
|
||||
],
|
||||
MigrationState::FINISHED => [
|
||||
'help' => 'core',
|
||||
'i18ncontent' => 'content_translation',
|
||||
],
|
||||
],
|
||||
'expected_6' => [
|
||||
MigrationState::NOT_FINISHED => [
|
||||
'system' => '',
|
||||
'content' => '',
|
||||
],
|
||||
MigrationState::FINISHED => [
|
||||
'help' => 'core',
|
||||
'i18ncontent' => 'content_translation',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$tests[7] = $tests[6];
|
||||
unset($tests[7]['modules_to_enable']['content_translation']);
|
||||
$tests[7]['expected_7'] = [
|
||||
MigrationState::NOT_FINISHED => [
|
||||
'system' => '',
|
||||
'i18ncontent' => 'content_translation',
|
||||
],
|
||||
MigrationState::FINISHED => [
|
||||
'help' => 'core',
|
||||
],
|
||||
];
|
||||
$tests[7]['expected_6'] = [
|
||||
MigrationState::NOT_FINISHED => [
|
||||
'system' => '',
|
||||
'content' => '',
|
||||
'i18ncontent' => 'content_translation',
|
||||
],
|
||||
MigrationState::FINISHED => [
|
||||
'help' => 'core',
|
||||
],
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -5,18 +5,26 @@ namespace Drupal\migrate_drupal_ui\Form;
|
|||
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 @@ class ReviewForm extends MigrateUpgradeFormBase {
|
|||
$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 @@ class ReviewForm extends MigrateUpgradeFormBase {
|
|||
// 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 @@ class ReviewForm extends MigrateUpgradeFormBase {
|
|||
$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 @@ class ReviewForm extends MigrateUpgradeFormBase {
|
|||
'#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 <a href=":review">Review the pre-upgrade analysis</a> in the <a href=":migrate">Upgrading to Drupal 8</a> 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. <a href=':review'>Read the checklist</a> 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 @@ class ReviewForm extends MigrateUpgradeFormBase {
|
|||
$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 @@ class ReviewForm extends MigrateUpgradeFormBase {
|
|||
],
|
||||
],
|
||||
],
|
||||
'destination_module' => ['#plain_text' => 'Not upgraded'],
|
||||
'destination_module' => [
|
||||
'#plain_text' => $destination_modules,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -300,7 +178,7 @@ class ReviewForm extends MigrateUpgradeFormBase {
|
|||
'#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 @@ class ReviewForm extends MigrateUpgradeFormBase {
|
|||
];
|
||||
|
||||
$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 = [];
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ abstract class MigrateUpgradeExecuteTestBase extends MigrateUpgradeTestBase {
|
|||
// 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 @@ abstract class MigrateUpgradeExecuteTestBase extends MigrateUpgradeTestBase {
|
|||
$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);
|
||||
|
|
|
|||
|
|
@ -169,13 +169,13 @@ abstract class MigrateUpgradeTestBase extends BrowserTestBase {
|
|||
* 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 @@ abstract class MigrateUpgradeTestBase extends BrowserTestBase {
|
|||
// 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -36,11 +36,11 @@ abstract class MultilingualReviewPageTestBase extends MigrateUpgradeTestBase {
|
|||
* Overlay.
|
||||
*
|
||||
* To do this all modules in the source fixtures are enabled, except test and
|
||||
* example modules. This means that we can test that the modules listed in the
|
||||
* the $noUpgradePath property of the update form class are correct, since
|
||||
* there will be no available migrations which declare those modules as their
|
||||
* source_module. It is assumed that the test fixtures include all modules
|
||||
* that have moved to or dropped from core.
|
||||
* example modules. This means that we can test that the modules that do not
|
||||
* need any migrations, such as Overlay, since there will be no available
|
||||
* migrations which declare those modules as their source_module. It is
|
||||
* assumed that the test fixtures include all modules that have moved to or
|
||||
* dropped from core.
|
||||
*
|
||||
* The upgrade review form will also display errors for each migration that
|
||||
* does not have a source_module definition. That function is not tested here.
|
||||
|
|
@ -68,10 +68,9 @@ abstract class MultilingualReviewPageTestBase extends MigrateUpgradeTestBase {
|
|||
$missing_paths = $this->getMissingPaths();
|
||||
$this->assertUpgradePaths($session, $available_paths, $missing_paths);
|
||||
|
||||
// Check there are no errors when a module in noUpgradePaths is not in the
|
||||
// source system tables. Test with a module that is listed in noUpgradePaths
|
||||
// for both Drupal 6 and Drupal 7.
|
||||
// @see \Drupal\migrate_drupal_ui\Form\ReviewForm::$noUpgradePaths
|
||||
// Check there are no errors when a module does not have any migrations and
|
||||
// does not need any. Test with a module that is was in both Drupal 6 and
|
||||
// Drupal 7 core.
|
||||
$module = 'help';
|
||||
$query = $this->sourceDatabase->delete('system');
|
||||
$query->condition('type', 'module');
|
||||
|
|
@ -84,7 +83,8 @@ abstract class MultilingualReviewPageTestBase extends MigrateUpgradeTestBase {
|
|||
$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 +138,16 @@ abstract class MultilingualReviewPageTestBase extends MigrateUpgradeTestBase {
|
|||
$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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ use Drupal\Tests\migrate_drupal_ui\Functional\MultilingualReviewPageTestBase;
|
|||
*
|
||||
* @group migrate_drupal_6
|
||||
* @group migrate_drupal_ui
|
||||
*
|
||||
* @group legacy
|
||||
*/
|
||||
class MultilingualReviewPageTest extends MultilingualReviewPageTestBase {
|
||||
|
||||
|
|
@ -31,6 +33,13 @@ 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',
|
||||
// Test missing migrate_drupal.yml.
|
||||
'migrate_state_no_upgrade_path',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -53,55 +62,20 @@ class MultilingualReviewPageTest extends MultilingualReviewPageTestBase {
|
|||
*/
|
||||
protected function getAvailablePaths() {
|
||||
return [
|
||||
// Aggregator is set not_finished in migrate_sate_not_finished_test.
|
||||
'aggregator',
|
||||
'block',
|
||||
'blog',
|
||||
'blogapi',
|
||||
'book',
|
||||
'calendarsignup',
|
||||
'color',
|
||||
'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',
|
||||
'calendarsignup',
|
||||
'color',
|
||||
'content_copy',
|
||||
'content_multigroup',
|
||||
'content_permissions',
|
||||
'date',
|
||||
'date_api',
|
||||
'date_locale',
|
||||
'date_php4',
|
||||
|
|
@ -110,27 +84,57 @@ class MultilingualReviewPageTest extends MultilingualReviewPageTestBase {
|
|||
'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 +147,18 @@ class MultilingualReviewPageTest extends MultilingualReviewPageTestBase {
|
|||
*/
|
||||
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',
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ use Drupal\Tests\migrate_drupal_ui\Functional\NoMultilingualReviewPageTestBase;
|
|||
*
|
||||
* @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 @@ class NoMultilingualReviewPageTest extends NoMultilingualReviewPageTestBase {
|
|||
protected function getAvailablePaths() {
|
||||
return [
|
||||
'aggregator',
|
||||
'block',
|
||||
'blog',
|
||||
'blogapi',
|
||||
'book',
|
||||
'calendarsignup',
|
||||
'color',
|
||||
'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',
|
||||
'calendarsignup',
|
||||
'color',
|
||||
'content_copy',
|
||||
'content_multigroup',
|
||||
'content_permissions',
|
||||
'date',
|
||||
'date_api',
|
||||
'date_locale',
|
||||
'date_php4',
|
||||
|
|
@ -100,28 +78,52 @@ class NoMultilingualReviewPageTest extends NoMultilingualReviewPageTestBase {
|
|||
'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 @@ class NoMultilingualReviewPageTest extends NoMultilingualReviewPageTestBase {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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 @@ class NoMultilingualReviewPageTest extends NoMultilingualReviewPageTestBase {
|
|||
'i18nmenu',
|
||||
'i18npoll',
|
||||
'i18nprofile',
|
||||
'i18nstrings',
|
||||
'i18nsync',
|
||||
'i18ntaxonomy',
|
||||
'i18nviews',
|
||||
'phone',
|
||||
'migrate_status_active_test',
|
||||
'views',
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,6 @@ class NoMultilingualTest extends MigrateUpgradeExecuteTestBase {
|
|||
'forum',
|
||||
'imagecache',
|
||||
'imagefield',
|
||||
'language',
|
||||
'link',
|
||||
'locale',
|
||||
'menu',
|
||||
|
|
@ -146,8 +145,7 @@ class NoMultilingualTest extends MigrateUpgradeExecuteTestBase {
|
|||
'user',
|
||||
'userreference',
|
||||
// Include modules that do not have an upgrade path and are enabled in the
|
||||
// source database, defined in the $noUpgradePath property
|
||||
// in MigrateUpgradeForm.
|
||||
// source database.
|
||||
'date_api',
|
||||
'date_timezone',
|
||||
'event',
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ use Drupal\user\Entity\User;
|
|||
* The test method is provided by the MigrateUpgradeTestBase class.
|
||||
*
|
||||
* @group migrate_drupal_ui
|
||||
*
|
||||
* @group legacy
|
||||
*/
|
||||
class Upgrade6Test extends MigrateUpgradeExecuteTestBase {
|
||||
|
||||
|
|
@ -130,40 +132,33 @@ class Upgrade6Test extends MigrateUpgradeExecuteTestBase {
|
|||
'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
|
||||
// in MigrateUpgradeForm.
|
||||
// source database'.
|
||||
'date_api',
|
||||
'date_timezone',
|
||||
'event',
|
||||
|
|
@ -180,7 +175,11 @@ class Upgrade6Test extends MigrateUpgradeExecuteTestBase {
|
|||
*/
|
||||
protected function getMissingPaths() {
|
||||
return [
|
||||
'i18ncontent',
|
||||
'i18n',
|
||||
'i18ncck',
|
||||
'i18nstrings',
|
||||
'i18ntaxonomy',
|
||||
'locale',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ use Drupal\Tests\migrate_drupal_ui\Functional\MultilingualReviewPageTestBase;
|
|||
*
|
||||
* @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 @@ class MultilingualReviewPageTest extends MultilingualReviewPageTestBase {
|
|||
*/
|
||||
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 @@ class MultilingualReviewPageTest extends MultilingualReviewPageTestBase {
|
|||
'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 @@ class MultilingualReviewPageTest extends MultilingualReviewPageTestBase {
|
|||
*/
|
||||
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',
|
||||
'breakpoints',
|
||||
'entity_translation_i18n_menu',
|
||||
'entity_translation_upgrade',
|
||||
|
|
@ -162,7 +170,7 @@ class MultilingualReviewPageTest extends MultilingualReviewPageTestBase {
|
|||
'i18n_user',
|
||||
'i18n_variable',
|
||||
'picture',
|
||||
'profile',
|
||||
'migrate_status_active_test',
|
||||
'variable',
|
||||
'variable_admin',
|
||||
'variable_realm',
|
||||
|
|
|
|||
|
|
@ -148,8 +148,7 @@ class NoMultilingualTest extends MigrateUpgradeExecuteTestBase {
|
|||
'text',
|
||||
'user',
|
||||
// Include modules that do not have an upgrade path and are enabled in the
|
||||
// source database, defined in the $noUpgradePath property
|
||||
// in MigrateUpgradeForm.
|
||||
// source database.
|
||||
'blog',
|
||||
'contextual',
|
||||
'date_api',
|
||||
|
|
@ -164,6 +163,13 @@ class NoMultilingualTest extends MigrateUpgradeExecuteTestBase {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getIncompletePaths() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ use Drupal\user\Entity\User;
|
|||
* The test method is provided by the MigrateUpgradeTestBase class.
|
||||
*
|
||||
* @group migrate_drupal_ui
|
||||
*
|
||||
* @group legacy
|
||||
*/
|
||||
class Upgrade7Test extends MigrateUpgradeExecuteTestBase {
|
||||
|
||||
|
|
@ -128,21 +130,22 @@ class Upgrade7Test extends MigrateUpgradeExecuteTestBase {
|
|||
'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,10 +159,10 @@ class Upgrade7Test extends MigrateUpgradeExecuteTestBase {
|
|||
'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
|
||||
// in MigrateUpgradeForm.
|
||||
// source database.
|
||||
'blog',
|
||||
'contextual',
|
||||
'date_api',
|
||||
|
|
@ -180,6 +183,9 @@ class Upgrade7Test extends MigrateUpgradeExecuteTestBase {
|
|||
protected function getMissingPaths() {
|
||||
return [
|
||||
'i18n',
|
||||
'i18n_field',
|
||||
'i18n_string',
|
||||
'locale',
|
||||
'variable',
|
||||
'variable_realm',
|
||||
'variable_store',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
finished:
|
||||
6:
|
||||
content: node
|
||||
node: node
|
||||
7:
|
||||
node: node
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
finished:
|
||||
6:
|
||||
optionwidgets: options
|
||||
7:
|
||||
options: options
|
||||
list: options
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
path: path
|
||||
7:
|
||||
path: path
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
finished:
|
||||
7:
|
||||
rdf: rdf
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
search: search
|
||||
7:
|
||||
search: search
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
finished:
|
||||
7:
|
||||
shortcut: shortcut
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
simpletest: simpletest
|
||||
7:
|
||||
simpletest: simpletest
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
statistics: statistics
|
||||
7:
|
||||
statistics: statistics
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
syslog: syslog
|
||||
7:
|
||||
syslog: syslog
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
finished:
|
||||
6:
|
||||
menu:
|
||||
- system
|
||||
- menu_link_content
|
||||
- menu_ui
|
||||
system: system
|
||||
# An upgrade path is not needed for jquery_ui.
|
||||
jquery_ui: core
|
||||
7:
|
||||
menu:
|
||||
- system
|
||||
- menu_link_content
|
||||
- menu_ui
|
||||
system: system
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
finished:
|
||||
6:
|
||||
taxonomy:
|
||||
- core
|
||||
- taxonomy
|
||||
7:
|
||||
taxonomy:
|
||||
- core
|
||||
- taxonomy
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
finished:
|
||||
7:
|
||||
phone: telephone
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
text: text
|
||||
7:
|
||||
text: text
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
finished:
|
||||
7:
|
||||
tracker: tracker
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
finished:
|
||||
6:
|
||||
update: update
|
||||
7:
|
||||
update: update
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
finished:
|
||||
6:
|
||||
profile: user
|
||||
user: user
|
||||
7:
|
||||
profile: user
|
||||
user: user
|
||||
Loading…
Reference in New Issue