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,16 +190,10 @@ class ReviewForm extends MigrateUpgradeFormBase {
 | 
			
		|||
    ];
 | 
			
		||||
 | 
			
		||||
    $available_count = 0;
 | 
			
		||||
    foreach ($table_data as $source_module => $destination_module_info) {
 | 
			
		||||
    if (isset($display[MigrationState::FINISHED])) {
 | 
			
		||||
      foreach ($display[MigrationState::FINISHED] as $source_module => $destination_modules) {
 | 
			
		||||
        $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] = [
 | 
			
		||||
        $available_module_list['module_list'][] = [
 | 
			
		||||
          'source_module' => [
 | 
			
		||||
            '#type' => 'html_tag',
 | 
			
		||||
            '#tag' => 'span',
 | 
			
		||||
| 
						 | 
				
			
			@ -333,9 +205,12 @@ class ReviewForm extends MigrateUpgradeFormBase {
 | 
			
		|||
              ],
 | 
			
		||||
            ],
 | 
			
		||||
          ],
 | 
			
		||||
        'destination_module' => $destination_details,
 | 
			
		||||
          'destination_module' => [
 | 
			
		||||
            '#plain_text' => $destination_modules,
 | 
			
		||||
          ],
 | 
			
		||||
        ];
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $counters = [];
 | 
			
		||||
    $general_info = [];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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