/** * {@inheritdoc} */ protected function setUp() { parent::setUp(); $id_mappings = array('d6_node:*' => array(array(array(0), array(0)))); $this->prepareMigrations($id_mappings); $migrations = Migration::loadMultiple(['d6_term_node:*']); array_walk($migrations, [$this, 'executeMigration']); }
/** * Set up the relevant migrations for import from the provided database * connection. * * @param \Drupal\Core\Database\Database $database * Database array representing the source Drupal database. * @param string $source_base_path * Address of the source Drupal site (e.g., http://example.com/). * * @return array */ protected function createMigrations(array $database, $source_base_path) { // Set up the connection. Database::addConnectionInfo('upgrade', 'default', $database); $connection = Database::getConnection('default', 'upgrade'); if (!($drupal_version = $this->getLegacyDrupalVersion($connection))) { throw new \Exception($this->t('Source database does not contain a recognizable Drupal version.')); } $database_state['key'] = 'upgrade'; $database_state['database'] = $database; $database_state_key = 'migrate_upgrade_' . $drupal_version; \Drupal::state()->set($database_state_key, $database_state); $version_tag = 'Drupal ' . $drupal_version; $template_storage = \Drupal::service('migrate.template_storage'); $migration_templates = $template_storage->findTemplatesByTag($version_tag); foreach ($migration_templates as $id => $template) { $migration_templates[$id]['source']['database_state_key'] = $database_state_key; // Configure file migrations so they can find the files. if ($template['destination']['plugin'] == 'entity:file') { if ($source_base_path) { // Make sure we have a single trailing slash. $source_base_path = rtrim($source_base_path, '/') . '/'; $migration_templates[$id]['destination']['source_base_path'] = $source_base_path; } } } // Let the builder service create our migration configuration entities from // the templates, expanding them to multiple entities where necessary. /** @var \Drupal\migrate\MigrationBuilder $builder */ $builder = \Drupal::service('migrate.migration_builder'); $migrations = $builder->createMigrations($migration_templates); $migration_ids = []; foreach ($migrations as $migration) { try { if ($migration->getSourcePlugin() instanceof RequirementsInterface) { $migration->getSourcePlugin()->checkRequirements(); } if ($migration->getDestinationPlugin() instanceof RequirementsInterface) { $migration->getDestinationPlugin()->checkRequirements(); } // Don't try to resave migrations that already exist. if (!Migration::load($migration->id())) { $migration->save(); } $migration_ids[] = $migration->id(); } catch (RequirementsException $e) { } catch (PluginNotFoundException $e) { } } // loadMultiple will sort the migrations in dependency order. return array_keys(Migration::loadMultiple($migration_ids)); }
/** * Tests that the order is correct when loading several migrations. */ public function testMigrateDependenciesOrder() { $migration_items = array('d6_comment', 'd6_filter_format', 'd6_node__page'); $migrations = Migration::loadMultiple($migration_items); $expected_order = array('d6_filter_format', 'd6_node__page', 'd6_comment'); $this->assertIdentical(array_keys($migrations), $expected_order); $expected_requirements = array('d6_node__article', 'd6_node__company', 'd6_node__employee', 'd6_node__event', 'd6_node__page', 'd6_node__sponsor', 'd6_node__story', 'd6_node__test_event', 'd6_node__test_page', 'd6_node__test_planet', 'd6_node__test_story', 'd6_node_type', 'd6_node_settings', 'd6_filter_format', 'd6_user', 'd6_comment_type', 'd6_comment_entity_display', 'd6_comment_entity_form_display'); // Migration dependencies for comment include dependencies for node // migration as well. $actual_requirements = $migrations['d6_comment']->get('requirements'); $this->assertIdentical(count($actual_requirements), count($expected_requirements)); foreach ($expected_requirements as $requirement) { $this->assertIdentical($actual_requirements[$requirement], $requirement); } }
/** * {@inheritdoc} */ protected function setUp() { parent::setUp(); $id_mappings = array('d6_node:*' => array(array(array(1), array(1)))); $this->prepareMigrations($id_mappings); // Create our users for the node authors. $query = Database::getConnection('default', 'migrate')->query('SELECT * FROM {users} WHERE uid NOT IN (0, 1)'); while (($row = $query->fetchAssoc()) !== FALSE) { $user = entity_create('user', $row); $user->enforceIsNew(); $user->save(); } $migrations = Migration::loadMultiple(['d6_node_revision:*']); array_walk($migrations, [$this, 'executeMigration']); }
/** * Test the complete Drupal migration. */ public function testDrupal() { $classes = $this->getTestClassesList(); foreach ($classes as $class) { if (is_subclass_of($class, '\\Drupal\\migrate\\Tests\\MigrateDumpAlterInterface')) { $class::migrateDumpAlter($this); } } // Run every migration in the order specified by the storage controller. $migrations = Migration::loadMultiple(static::$migrations); array_walk($migrations, [$this, 'executeMigration']); foreach ($classes as $class) { $test_object = new $class($this->testId); $test_object->databasePrefix = $this->databasePrefix; $test_object->container = $this->container; // run() does a lot of setup and tear down work which we don't need: // it would setup a new database connection and wouldn't find the // Drupal dump. Also by skipping the setUp() methods there are no id // mappings or entities prepared. The tests run against solely migrated // data. foreach (get_class_methods($test_object) as $method) { if (strtolower(substr($method, 0, 4)) == 'test') { // Insert a fail record. This will be deleted on completion to ensure // that testing completed. $method_info = new \ReflectionMethod($class, $method); $caller = array('file' => $method_info->getFileName(), 'line' => $method_info->getStartLine(), 'function' => $class . '->' . $method . '()'); $completion_check_id = TestBase::insertAssert($this->testId, $class, FALSE, 'The test did not complete due to a fatal error.', 'Completion check', $caller); // Run the test method. try { $test_object->{$method}(); } catch (\Exception $e) { $this->exceptionHandler($e); } // Remove the completion check record. TestBase::deleteAssert($completion_check_id); } } // Add the pass/fail/exception/debug results. foreach ($this->results as $key => &$value) { $value += $test_object->results[$key]; } } }
/** * Executes a set of migrations in dependency order. * * @param string[] $ids * Array of migration IDs, in any order. */ protected function executeMigrations(array $ids) { $migrations = Migration::loadMultiple($ids); array_walk($migrations, [$this, 'executeMigration']); }
/** * Saves the migrations for import from the provided template connection. * * @param array $migration_templates * Migration template. * * @return array * The migration IDs sorted in dependency order. */ protected function createMigrations(array $migration_templates) { $migration_ids = []; $migrations = $this->getMigrations($migration_templates); foreach ($migrations as $migration) { // Don't try to resave migrations that already exist. if (!Migration::load($migration->id())) { $migration->save(); } $migration_ids[] = $migration->id(); } // loadMultiple will sort the migrations in dependency order. return array_keys(Migration::loadMultiple($migration_ids)); }
/** * Prepare any dependent migrations. * * @param array $id_mappings * A list of id mappings keyed by migration ids. Each id mapping is a list * of two arrays, the first are source ids and the second are destination * ids. */ protected function prepareMigrations(array $id_mappings) { foreach ($id_mappings as $migration_id => $data) { // Use loadMultiple() here in order to load all variants. foreach (Migration::loadMultiple([$migration_id]) as $migration) { // Mark the dependent migrations as complete. $migration->setMigrationResult(MigrationInterface::RESULT_COMPLETED); $id_map = $migration->getIdMap(); $id_map->setMessage($this); $source_ids = $migration->getSourcePlugin()->getIds(); foreach ($data as $id_mapping) { $row = new Row(array_combine(array_keys($source_ids), $id_mapping[0]), $source_ids); $id_map->saveIdMapping($row, $id_mapping[1]); } } } }
/** * Drush execution method. Runs imports on the supplied manifest. */ public function import() { /** @var \Drupal\migrate\MigrateTemplateStorage $template_storage */ $template_storage = \Drupal::service('migrate.template_storage'); $this->setupLegacyDb(); $migration_ids = []; $migrations = []; foreach ($this->migrationList as $migration_info) { if (is_array($migration_info)) { // The migration is stored as the key in the info array. $migration_id = key($migration_info); } else { // If it wasn't an array then the info is just the migration_id. $migration_id = $migration_info; } $template = $template_storage->getTemplateByName($migration_id) ?: []; if (is_array($migration_info)) { // If there is some existing global overrides then we merge them in. if (isset($GLOBALS['config'][$migration_id])) { $migration_info = NestedArray::mergeDeep($GLOBALS['config'][$migration_id], $migration_info); } $migration_info = NestedArray::mergeDeepArray([$template, $migration_info], TRUE); } else { $migration_info = $template; } if ($migration_info) { /** @var \Drupal\migrate\Entity\Migration[] $migrations */ $migrations = \Drupal::service('migrate.migration_builder')->createMigrations([$migration_id => $migration_info]); foreach ($migrations as $migration) { $migration_ids[] = $migration->id(); if (!Migration::load($migration->id())) { $migration->save(); } } // We use these migration_ids to run migrations. If we didn't create // anything we pass it on and this will trigger non-existent migrations // messages or resolved by migration loading. // @todo this can return false positives in the non-existent migration // logic if the builder explicitly returned no results. For example, no // taxonomies will cause some things to be empty. if (!$migrations) { $migration_ids[] = $migration_id; } } } // Load all the migrations at once so they're correctly ordered. foreach (Migration::loadMultiple($migration_ids) as $migration) { $executable = $this->executeMigration($migration); // Store all the migrations for later. $migrations[$migration->id()] = array('executable' => $executable, 'migration' => $migration, 'source' => $migration->get('source'), 'destination' => $migration->get('destination')); } // Warn the user if any migrations were not found. $nonexistent_migrations = array_diff($migration_ids, array_keys($migrations)); if (count($nonexistent_migrations) > 0) { drush_log(dt('The following migrations were not found: @migrations', array('@migrations' => implode(', ', $nonexistent_migrations))), 'warning'); } return $migrations; }