You are here

trait ValidateMigrationStateTestTrait in Drupal 8

Same name and namespace in other branches
  1. 9 core/modules/migrate_drupal/tests/src/Traits/ValidateMigrationStateTestTrait.php \Drupal\Tests\migrate_drupal\Traits\ValidateMigrationStateTestTrait
  2. 10 core/modules/migrate_drupal/tests/src/Traits/ValidateMigrationStateTestTrait.php \Drupal\Tests\migrate_drupal\Traits\ValidateMigrationStateTestTrait

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

Hierarchy

2 files declare their use of ValidateMigrationStateTestTrait
ValidateMigrationStateTest.php in core/modules/migrate_drupal/tests/src/Kernel/d6/ValidateMigrationStateTest.php
ValidateMigrationStateTest.php in core/modules/migrate_drupal/tests/src/Kernel/d7/ValidateMigrationStateTest.php

File

core/modules/migrate_drupal/tests/src/Traits/ValidateMigrationStateTestTrait.php, line 19

Namespace

Drupal\Tests\migrate_drupal\Traits
View source
trait ValidateMigrationStateTestTrait {
  use FileSystemModuleDiscoveryDataProviderTrait;
  use MigrationConfigurationTrait;

  /**
   * 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() {

    // Level separator of destination and source properties.
    $separator = ',';
    $this
      ->enableAllModules();
    $version = (string) $this
      ->getLegacyDrupalVersion($this->sourceDatabase);

    // 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 = [];

    /** @var \Drupal\migrate\Plugin\MigrationPluginManager $plugin_manager */
    $plugin_manager = $this->container
      ->get('plugin.manager.migration');
    $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[] = implode($separator, [
        $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) {
      if (isset($definition['core'][$version])) {
        $discovered[] = implode($separator, [
          $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][$version])) {
          foreach ($info[$state][$version] 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 = [
                  $module,
                  $source,
                  trim($dest),
                ];
                $declared[$state][] = implode($separator, $key);
              }
            }
          }
        }
      }
    }

    // Sort and make the array values unique.
    sort($declared[MigrationState::FINISHED]);
    sort($declared[MigrationState::NOT_FINISHED]);
    $declared_unique[MigrationState::FINISHED] = array_unique($declared[MigrationState::FINISHED]);
    $declared_unique[MigrationState::NOT_FINISHED] = array_unique($declared[MigrationState::NOT_FINISHED]);
    sort($discovered);
    $discovered_unique = array_unique($discovered);

    // Assert that each discovered migration has a corresponding declaration
    // in a migrate_drupal.yml.
    foreach ($discovered_unique as $datum) {
      $data = str_getcsv($datum);
      $in_finished = in_array($datum, $declared_unique[MigrationState::FINISHED]);
      $in_not_finished = in_array($datum, $declared_unique[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'", $version, $data[1], $data[2], $data[0]));
    }

    // 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, $declared_unique[MigrationState::FINISHED]);
    foreach ($discovered_not_finished as $datum) {
      $data = str_getcsv($datum);
      $this
        ->assertContains($datum, $declared_unique[MigrationState::NOT_FINISHED], sprintf("No migration found for version '%s' with source_module '%s' and destination_module '%s' declared in module '%s'", $version, $data[1], $data[2], $data[0]));
    }
  }

  /**
   * 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;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
FileSystemModuleDiscoveryDataProviderTrait::coreModuleListDataProvider public function A data provider that lists every module in core.
MigrationConfigurationTrait::$configFactory protected property The config factory service.
MigrationConfigurationTrait::$followUpMigrationTags protected property The follow-up migration tags.
MigrationConfigurationTrait::$migrationPluginManager protected property The migration plugin manager service.
MigrationConfigurationTrait::$state protected property The state service.
MigrationConfigurationTrait::createDatabaseStateSettings protected function Creates the necessary state entries for SqlBase::getDatabase() to work.
MigrationConfigurationTrait::getConfigFactory protected function Gets the config factory service.
MigrationConfigurationTrait::getConnection protected function Gets the database connection for the source Drupal database.
MigrationConfigurationTrait::getFollowUpMigrationTags protected function Returns the follow-up migration tags.
MigrationConfigurationTrait::getLegacyDrupalVersion public static function Determines what version of Drupal the source database contains.
MigrationConfigurationTrait::getMigrationPluginManager protected function Gets the migration plugin manager service.
MigrationConfigurationTrait::getMigrations protected function Gets the migrations for import.
MigrationConfigurationTrait::getState protected function Gets the state service.
MigrationConfigurationTrait::getSystemData protected function Gets the system data from the system table of the source Drupal database.
ValidateMigrationStateTestTrait::enableAllModules protected function Enable all available modules.
ValidateMigrationStateTestTrait::testMigrationState public function Tests the migration information in .migrate_drupal.yml.