/** * {@inheritdoc} */ public function buildMigrations(array $template) { $migrations = []; // Read all field instance definitions in the source database. $fields = array(); foreach ($this->getSourcePlugin('d7_field_instance', $template['source']) as $field) { $info = $field->getSource(); $fields[$info['entity_type']][$info['bundle']][$info['field_name']] = $info; } foreach ($this->getSourcePlugin('d7_node_type', $template['source']) as $node_type) { $bundle = $node_type->getSourceProperty('type'); $values = $template; $values['id'] .= '__' . $bundle; $values['label'] = $this->t('@label (@type)', ['@label' => $values['label'], '@type' => $node_type->getSourceProperty('name')]); $values['source']['node_type'] = $bundle; $migration = Migration::create($values); if (isset($fields['node'][$bundle])) { foreach ($fields['node'][$bundle] as $field => $data) { if ($this->cckPluginManager->hasDefinition($data['type'])) { $this->getCckPlugin($data['type'])->processCckFieldValues($migration, $field, $data); } else { $migration->setProcessOfProperty($field, $field); } } } $migrations[] = $migration; } return $migrations; }
/** * {@inheritdoc} */ public function buildMigrations(array $template) { $migrations = []; // Read all CCK field instance definitions in the source database. $fields = array(); foreach ($this->getSourcePlugin('d6_field_instance', $template['source']) as $field) { $info = $field->getSource(); $fields[$info['type_name']][$info['field_name']] = $info; } foreach ($this->getSourcePlugin('d6_node_type', $template['source']) as $row) { $node_type = $row->getSourceProperty('type'); $values = $template; $values['id'] = $template['id'] . '__' . $node_type; $label = $template['label']; $values['label'] = $this->t("@label (@type)", ['@label' => $label, '@type' => $node_type]); $values['source']['node_type'] = $node_type; $migration = Migration::create($values); if (isset($fields[$node_type])) { foreach ($fields[$node_type] as $field => $info) { if ($this->cckPluginManager->hasDefinition($info['type'])) { $this->getCckPlugin($info['type'])->processCckFieldValues($migration, $field, $info); } else { $migration->setProcessOfProperty($field, $field); } } } $migrations[] = $migration; } return $migrations; }
/** * Tests the embedded_data source plugin. */ public function testEmbeddedData() { $data_rows = [['key' => '1', 'field1' => 'f1value1', 'field2' => 'f2value1'], ['key' => '2', 'field1' => 'f1value2', 'field2' => 'f2value2']]; $ids = ['key' => ['type' => 'integer']]; $config = ['id' => 'sample_data', 'migration_tags' => ['Embedded data test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => $data_rows, 'ids' => $ids], 'process' => [], 'destination' => ['plugin' => 'null']]; $migration = Migration::create($config); $source = $migration->getSourcePlugin(); // Validate the plugin returns the source data that was provided. $results = []; /** @var Row $row */ foreach ($source as $row) { $data_row = $row->getSource(); // The "data" row returned by getSource() also includes all source // configuration - we remove it so we see only the data itself. unset($data_row['plugin']); unset($data_row['data_rows']); unset($data_row['ids']); $results[] = $data_row; } $this->assertIdentical($results, $data_rows); // Validate the public APIs. $this->assertIdentical($source->count(), count($data_rows)); $this->assertIdentical($source->getIds(), $ids); $expected_fields = ['key' => 'key', 'field1' => 'field1', 'field2' => 'field2']; $this->assertIdentical($source->fields(), $expected_fields); }
/** * {@inheritdoc} */ public function buildMigrations(array $template) { $migrations = []; $fields = []; foreach ($this->getSourcePlugin('d7_field_instance', $template['source']) as $field) { $entity_type = $field->getSourceProperty('entity_type'); $bundle = $field->getSourceProperty('bundle'); $field_name = $field->getSourceProperty('field_name'); $fields[$entity_type][$bundle][$field_name] = $field->getSource(); } foreach ($this->getSourcePlugin('d7_node_type', $template['source']) as $node_type) { $bundle = $node_type->getSourceProperty('type'); $values = $template; $values['id'] .= '__' . $bundle; $values['label'] = $this->t('@label (@type)', ['@label' => $values['label'], '@type' => $node_type->getSourceProperty('name')]); $values['source']['node_type'] = $bundle; $migration = Migration::create($values); if (isset($fields['node'][$bundle])) { foreach (array_keys($fields['node'][$bundle]) as $field) { $migration->setProcessOfProperty($field, $field); } } $migrations[] = $migration; } return $migrations; }
/** * {@inheritdoc} */ public function buildMigrations(array $template) { $migration = Migration::create($template); $source_plugin = $migration->getSourcePlugin(); // The source plugin will throw RequirementsException if CCK is not enabled, // in which case there is nothing else for us to do. if ($source_plugin instanceof RequirementsInterface) { try { $source_plugin->checkRequirements(); } catch (RequirementsException $e) { return [$migration]; } } // Loop through every field that will be migrated. foreach ($source_plugin as $field) { $field_type = $field->getSourceProperty('type'); // Each field type should only be processed once. if (in_array($field_type, $this->processedFieldTypes)) { continue; } elseif ($this->cckPluginManager->hasDefinition($field_type)) { $this->processedFieldTypes[] = $field_type; // Allow the cckfield plugin to alter the migration as necessary so that // it knows how to handle fields of this type. $this->cckPluginManager->createInstance($field_type, [], $migration)->{$this->configuration['cck_plugin_method']}($migration); } } return [$migration]; }
/** * Tests creation of stubs when weight is mapped. */ public function testStubWithWeightMapping() { // Create a vocabulary via migration for the terms to reference. $vocabulary_data_rows = [['id' => '1', 'name' => 'tags']]; $ids = ['id' => ['type' => 'integer']]; $config = ['id' => 'vocabularies', 'migration_tags' => ['Stub test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => $vocabulary_data_rows, 'ids' => $ids], 'process' => ['vid' => 'id', 'name' => 'name'], 'destination' => ['plugin' => 'entity:taxonomy_vocabulary']]; $vocabulary_migration = Migration::create($config); $vocabulary_executable = new MigrateExecutable($vocabulary_migration, $this); $vocabulary_executable->import(); // We have a term referencing an unmigrated parent, forcing a stub to be // created. $term_data_rows = [['id' => '1', 'vocab' => '1', 'name' => 'music', 'parent' => '2']]; $ids = ['id' => ['type' => 'integer']]; $config = ['id' => 'terms', 'migration_tags' => ['Import and rollback test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => $term_data_rows, 'ids' => $ids], 'process' => ['tid' => 'id', 'vid' => 'vocab', 'name' => 'name', 'weight' => 'weight', 'parent' => ['plugin' => 'migration', 'migration' => 'terms', 'source' => 'parent']], 'destination' => ['plugin' => 'entity:taxonomy_term'], 'migration_dependencies' => ['required' => ['vocabularies']]]; $term_migration = Migration::create($config); $term_migration->save(); $term_executable = new MigrateExecutable($term_migration, $this); $term_executable->import(); // Load the referenced term, which should exist as a stub. /** @var \Drupal\Core\Entity\ContentEntityBase $stub_entity */ $stub_entity = Term::load(2); $this->assertTrue($stub_entity, 'Stub successfully created'); if ($stub_entity) { $this->assertIdentical(count($stub_entity->validate()), 0, 'Stub is a valid entity'); } }
/** * {@inheritdoc} */ public function setUp() { parent::setUp(); $this->installConfig(['system']); // A simple migration, which will generate a message to the id map because // the concat plugin throws an exception if its source is not an array. $config = ['id' => 'sample_data', 'migration_tags' => ['Message test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => [['name' => 'source_message', 'value' => 'a message']], 'ids' => ['name' => ['type' => 'string']]], 'process' => ['message' => ['plugin' => 'concat', 'source' => 'value']], 'destination' => ['plugin' => 'config', 'config_name' => 'system.maintenance']]; $this->migration = Migration::create($config); }
/** * Create a stub of the given entity type. * * @param string $entity_type_id * The entity type we are stubbing. * * @return int * ID of the created entity. */ protected function createStub($entity_type_id) { // Create a dummy migration to pass to the destination plugin. $config = ['id' => 'dummy', 'migration_tags' => ['Stub test'], 'source' => ['plugin' => 'empty'], 'process' => [], 'destination' => ['plugin' => 'entity:' . $entity_type_id]]; $migration = Migration::create($config); $destination_plugin = $migration->getDestinationPlugin(TRUE); $stub_row = new Row([], [], TRUE); $destination_ids = $destination_plugin->import($stub_row); return reset($destination_ids); }
/** * Tests Migration::set() * * @covers ::set() */ public function testSetInvalidation() { $migration = Migration::create(['source' => ['plugin' => 'empty'], 'destination' => ['plugin' => 'entity:entity_view_mode']]); $this->assertEqual('empty', $migration->getSourcePlugin()->getPluginId()); $this->assertEqual('entity:entity_view_mode', $migration->getDestinationPlugin()->getPluginId()); // Test the source plugin is invalidated. $migration->set('source', ['plugin' => 'd6_field']); $this->assertEqual('d6_field', $migration->getSourcePlugin()->getPluginId()); // Test the destination plugin is invalidated. $migration->set('destination', ['plugin' => 'null']); $this->assertEqual('null', $migration->getDestinationPlugin()->getPluginId()); }
/** * @covers ::calculateDependencies */ public function testCalculateDependencies() { $fixture_migrations = ['d6_node__article' => 'd6_node', 'd6_node__page' => 'd6_node', 'd6_variables' => 'd6_variables']; foreach ($fixture_migrations as $id => $template) { $values = ['id' => $id, 'template' => $template, 'source' => ['plugin' => 'empty'], 'destination' => ['plugin' => 'null'], 'migration_tags' => []]; Migration::create($values)->save(); } $values = ['migration_dependencies' => ['required' => ['d6_node:*', 'd6_variables']], 'source' => ['plugin' => 'empty'], 'destination' => ['plugin' => 'null']]; $migration = new Migration($values, 'migration'); $expected = ['migrate.migration.d6_node__article', 'migrate.migration.d6_node__page', 'migrate.migration.d6_variables']; $migration->calculateDependencies(); $this->assertEquals($expected, $migration->getDependencies()['config']); }
/** * Tests migration interruptions. */ public function testMigrateEvents() { // Run a simple little migration, which should trigger one of each event // other than map_delete. $config = ['id' => 'sample_data', 'migration_tags' => ['Interruption test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => [['data' => 'dummy value'], ['data' => 'dummy value2']], 'ids' => ['data' => ['type' => 'string']]], 'process' => ['value' => 'data'], 'destination' => ['plugin' => 'dummy']]; $migration = Migration::create($config); /** @var MigrationInterface $migration */ $executable = new MigrateExecutable($migration, new MigrateMessage()); // When the import runs, the first row imported will trigger an interruption. $result = $executable->import(); $this->assertEqual($result, MigrationInterface::RESULT_INCOMPLETE); // The status should have been reset to IDLE. $this->assertEqual($migration->getStatus(), MigrationInterface::STATUS_IDLE); }
/** * Returns a fully initialized instance of a source plugin. * * @param string $plugin_id * The plugin ID. * @param array $configuration * (optional) Additional configuration for the plugin. * * @return \Drupal\migrate\Plugin\MigrateSourceInterface|\Drupal\migrate\Plugin\RequirementsInterface * The fully initialized source plugin. */ protected function getSourcePlugin($plugin_id, array $configuration = []) { $configuration['plugin'] = $plugin_id; // By default, SqlBase subclasses will try to join on a map table. But in // this case we're trying to use the source plugin as a detached iterator // over the source data, so we don't want to join on (or create) the map // table. // @see SqlBase::initializeIterator() $configuration['ignore_map'] = TRUE; // Source plugins are tightly coupled to migration entities, so we need // to create a fake migration in order to properly initialize the plugin. $values = ['id' => uniqid(), 'source' => $configuration, 'destination' => ['plugin' => 'null']]; return Migration::create($values)->getSourcePlugin(); }
/** * Turn all the migration templates for the specified drupal version into * real migration entities so we can test them. * * @param string $version * Drupal version as provided in migration_tags - e.g., 'Drupal 6'. */ protected function installMigrations($version) { $migration_templates = \Drupal::service('migrate.template_storage')->findTemplatesByTag($version); foreach ($migration_templates as $template) { try { $migration = Migration::create($template); $migration->save(); } catch (PluginNotFoundException $e) { // Migrations requiring modules not enabled will throw an exception. // Ignoring this exception is equivalent to placing config in the // optional subdirectory - the migrations we require for the test will // be successfully saved. } } }
/** * {@inheritdoc} */ public function buildMigrations(array $template) { $migration = Migration::create($template); // @TODO The source plugin should accept a database connection. // @see https://www.drupal.org/node/2552791 $source_plugin = $this->getSourcePlugin('d6_profile_field', $template['source']); try { $source_plugin->checkRequirements(); } catch (RequirementsException $e) { return []; } foreach ($source_plugin as $field) { $migration->setProcessOfProperty($field->getSourceProperty('name'), $field->getSourceProperty('name')); } return [$migration]; }
/** * Test different connection types. */ public function testStatus() { // Create a minimally valid migration. $configuration = ['id' => 'migration_status_test', 'migration_tags' => ['Testing'], 'source' => ['plugin' => 'empty'], 'destination' => ['plugin' => 'config', 'config_name' => 'migrate_test.settings'], 'process' => ['foo' => 'bar']]; $migration = Migration::create($configuration); $migration->save(); // Default status is idle. $status = $migration->getStatus(); $this->assertIdentical($status, MigrationInterface::STATUS_IDLE); // Test setting and retrieving all known status values. $status_list = array(MigrationInterface::STATUS_IDLE, MigrationInterface::STATUS_IMPORTING, MigrationInterface::STATUS_ROLLING_BACK, MigrationInterface::STATUS_STOPPING, MigrationInterface::STATUS_DISABLED); foreach ($status_list as $status) { $migration->setStatus($status); $this->assertIdentical($migration->getStatus(), $status); } }
/** * Tests migration interruptions. */ public function testPrepareRowSkip() { // Run a simple little migration with two data rows which should be skipped // in different ways. $config = ['id' => 'sample_data', 'migration_tags' => ['prepare_row test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => [['id' => '1', 'data' => 'skip_and_record'], ['id' => '2', 'data' => 'skip_and_dont_record']], 'ids' => ['id' => ['type' => 'string']]], 'process' => ['value' => 'data'], 'destination' => ['plugin' => 'config', 'config_name' => 'migrate_test.settings'], 'load' => ['plugin' => 'null']]; $migration = Migration::create($config); $executable = new MigrateExecutable($migration, new MigrateMessage()); $result = $executable->import(); $this->assertEqual($result, MigrationInterface::RESULT_COMPLETED); $id_map_plugin = $migration->getIdMap(); // The first row is recorded in the map as ignored. $map_row = $id_map_plugin->getRowBySource(['id' => 1]); $this->assertEqual(MigrateIdMapInterface::STATUS_IGNORED, $map_row['source_row_status']); // The second row is not recorded in the map. $map_row = $id_map_plugin->getRowBySource(['id' => 2]); $this->assertFalse($map_row); }
/** * {@inheritdoc} */ public function buildMigrations(array $template) { $migration = Migration::create($template); // Loop through every field that will be migrated. foreach ($migration->getSourcePlugin() as $field) { $field_type = $field->getSourceProperty('type'); // Each field type should only be processed once. if (in_array($field_type, $this->processedFieldTypes)) { continue; } elseif ($this->cckPluginManager->hasDefinition($field_type)) { $this->processedFieldTypes[] = $field_type; // Allow the cckfield plugin to alter the migration as necessary so that // it knows how to handle fields of this type. $this->cckPluginManager->createInstance($field_type, [], $migration)->{$this->configuration['cck_plugin_method']}($migration); } } return [$migration]; }
/** * Builds migration entities from templates. * * @param array $templates * The parsed templates (each of which is an array parsed from YAML), keyed * by ID. * * @return \Drupal\migrate\Entity\MigrationInterface[] * The migration entities derived from the templates. */ public function createMigrations(array $templates) { /** @var \Drupal\migrate\Entity\MigrationInterface[] $migrations */ $migrations = []; foreach ($templates as $template_id => $template) { if (isset($template['builder'])) { $variants = $this->builderManager->createInstance($template['builder']['plugin'], $template['builder'])->buildMigrations($template); } else { $variants = array(Migration::create($template)); } /** @var \Drupal\migrate\Entity\MigrationInterface[] $variants */ foreach ($variants as $variant) { $variant->set('template', $template_id); } $migrations = array_merge($migrations, $variants); } return $migrations; }
/** * 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; } $migration_ids[] = $migration_id; $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::mergeDeep($template, $migration_info); } else { $migration_info = $template; } if ($migration_info && !Migration::load($migration_id)) { $migration = Migration::create($migration_info); $migration->save(); } } // Load all the migrations at once so they're correctly ordered. foreach (entity_load_multiple('migration', $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; }
/** * Tests migration events. */ public function testMigrateEvents() { // Run a simple little migration, which should trigger one of each event // other than map_delete. $config = ['id' => 'sample_data', 'migration_tags' => ['Event test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => [['data' => 'dummy value']], 'ids' => ['data' => ['type' => 'string']]], 'process' => ['value' => 'data'], 'destination' => ['plugin' => 'dummy']]; $migration = Migration::create($config); /** @var MigrationInterface $migration */ $executable = new MigrateExecutable($migration, new MigrateMessage()); // As the import runs, events will be dispatched, recording the received // information in state. $executable->import(); // Validate from the recorded state that the events were received. $event = $this->state->get('migrate_events_test.pre_import_event', []); $this->assertIdentical($event['event_name'], MigrateEvents::PRE_IMPORT); $this->assertIdentical($event['migration']->id(), $migration->id()); $event = $this->state->get('migrate_events_test.post_import_event', []); $this->assertIdentical($event['event_name'], MigrateEvents::POST_IMPORT); $this->assertIdentical($event['migration']->id(), $migration->id()); $event = $this->state->get('migrate_events_test.map_save_event', []); $this->assertIdentical($event['event_name'], MigrateEvents::MAP_SAVE); // Validating the last row processed. $this->assertIdentical($event['fields']['sourceid1'], 'dummy value'); $this->assertIdentical($event['fields']['destid1'], 'dummy value'); $this->assertIdentical($event['fields']['source_row_status'], 0); $event = $this->state->get('migrate_events_test.map_delete_event', []); $this->assertIdentical($event, []); $event = $this->state->get('migrate_events_test.pre_row_save_event', []); $this->assertIdentical($event['event_name'], MigrateEvents::PRE_ROW_SAVE); $this->assertIdentical($event['migration']->id(), $migration->id()); // Validating the last row processed. $this->assertIdentical($event['row']->getSourceProperty('data'), 'dummy value'); $event = $this->state->get('migrate_events_test.post_row_save_event', []); $this->assertIdentical($event['event_name'], MigrateEvents::POST_ROW_SAVE); $this->assertIdentical($event['migration']->id(), $migration->id()); // Validating the last row processed. $this->assertIdentical($event['row']->getSourceProperty('data'), 'dummy value'); $this->assertIdentical($event['destination_id_values']['value'], 'dummy value'); // Generate a map delete event. $migration->getIdMap()->delete(['data' => 'dummy value']); $event = $this->state->get('migrate_events_test.map_delete_event', []); $this->assertIdentical($event['event_name'], MigrateEvents::MAP_DELETE); $this->assertIdentical($event['source_id'], ['data' => 'dummy value']); }
/** * Tests preserving the admin user's password. */ public function testAdminPasswordPreserved() { $user_data_rows = [['id' => '1', 'username' => 'site_admin', 'password' => 'new_password', 'email' => '*****@*****.**'], ['id' => '2', 'username' => 'random_user', 'password' => 'random_password', 'email' => '*****@*****.**']]; $ids = ['id' => ['type' => 'integer']]; $config = ['id' => 'users', 'migration_tags' => ['Admin password test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => $user_data_rows, 'ids' => $ids], 'process' => ['uid' => 'id', 'name' => 'username', 'mail' => 'email', 'pass' => 'password'], 'destination' => ['plugin' => 'entity:user']]; $migration = Migration::create($config); $this->executeMigration($migration); // Verify that admin username and email were changed, but password was not. /** @var \Drupal\user\Entity\User $admin_account */ $admin_account = User::load(1); $this->assertIdentical($admin_account->getUsername(), 'site_admin'); $this->assertIdentical($admin_account->getEmail(), '*****@*****.**'); $this->assertIdentical($admin_account->getPassword(), $this->originalPasswords[1]); // Verify that everything changed for the regular user. /** @var \Drupal\user\Entity\User $user_account */ $user_account = User::load(2); $this->assertIdentical($user_account->getUsername(), 'random_user'); $this->assertIdentical($user_account->getEmail(), '*****@*****.**'); $this->assertNotIdentical($user_account->getPassword(), $this->originalPasswords[2]); }
/** * {@inheritdoc} */ public function buildMigrations(array $template) { $migrations = []; // Read all CCK field instance definitions in the source database. $fields = array(); $source_plugin = $this->getSourcePlugin('d6_field_instance', $template['source']); try { $source_plugin->checkRequirements(); foreach ($source_plugin as $field) { $info = $field->getSource(); $fields[$info['type_name']][$info['field_name']] = $info; } } catch (RequirementsException $e) { // Don't do anything; $fields will be empty. } foreach ($this->getSourcePlugin('d6_node_type', $template['source']) as $row) { $node_type = $row->getSourceProperty('type'); $values = $template; $values['id'] = $template['id'] . '__' . $node_type; $label = $template['label']; $values['label'] = $this->t("@label (@type)", ['@label' => $label, '@type' => $node_type]); $values['source']['node_type'] = $node_type; // If this migration is based on the d6_node_revision template, it should // explicitly depend on the corresponding d6_node variant. if ($template['id'] == 'd6_node_revision') { $values['migration_dependencies']['required'][] = 'd6_node__' . $node_type; } $migration = Migration::create($values); if (isset($fields[$node_type])) { foreach ($fields[$node_type] as $field => $info) { if ($this->cckPluginManager->hasDefinition($info['type'])) { $this->getCckPlugin($info['type'])->processCckFieldValues($migration, $field, $info); } else { $migration->setProcessOfProperty($field, $field); } } } $migrations[] = $migration; } return $migrations; }
/** * {@inheritdoc} */ public function buildMigrations(array $template) { $migrations = []; foreach ($this->getSourcePlugin('d6_node_type', $template['source']) as $row) { $node_type = $row->getSourceProperty('type'); $values = $template; $values['id'] = $template['id'] . '__' . $node_type; $migration = Migration::create($values); $fields = $this->getSourcePlugin('d6_field_instance', ['node_type' => $node_type] + $template['source']); foreach ($fields as $field) { $data = $field->getSource(); if ($this->cckPluginManager->hasDefinition($data['type'])) { $this->getCckPlugin($data['type'])->processCckFieldValues($migration, $data['field_name'], $data); } else { $migration->setProcessOfProperty($data['field_name'], $data['field_name']); } } $migrations[] = $migration; } return $migrations; }
/** * {@inheritdoc} */ public function buildMigrations(array $template) { $migration = Migration::create($template); if ($this->moduleHandler->moduleExists('field')) { $template['source']['entity_type'] = 'user'; $source_plugin = $this->getSourcePlugin('d7_field_instance', $template['source']); foreach ($source_plugin as $field) { $field_name = $field->getSourceProperty('field_name'); $migration->setProcessOfProperty($field_name, $field_name); } } try { $profile_fields = $this->getSourcePlugin('profile_field', $template['source']); // Ensure that Profile is enabled in the source DB. $profile_fields->checkRequirements(); foreach ($profile_fields as $field) { $field_name = $field->getSourceProperty('name'); $migration->setProcessOfProperty($field_name, $field_name); } } catch (RequirementsException $e) { // Profile is not enabled in the source DB, so don't do anything. } return [$migration]; }
/** * Tests rolling back configuration and content entities. */ public function testRollback() { // We use vocabularies to demonstrate importing and rolling back // configuration entities. $vocabulary_data_rows = [['id' => '1', 'name' => 'categories', 'weight' => '2'], ['id' => '2', 'name' => 'tags', 'weight' => '1']]; $ids = ['id' => ['type' => 'integer']]; $config = ['id' => 'vocabularies', 'migration_tags' => ['Import and rollback test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => $vocabulary_data_rows, 'ids' => $ids], 'process' => ['vid' => 'id', 'name' => 'name', 'weight' => 'weight'], 'destination' => ['plugin' => 'entity:taxonomy_vocabulary']]; $vocabulary_migration = Migration::create($config); $vocabulary_id_map = $vocabulary_migration->getIdMap(); $this->assertTrue($vocabulary_migration->getDestinationPlugin()->supportsRollback()); // Import and validate vocabulary config entities were created. $vocabulary_executable = new MigrateExecutable($vocabulary_migration, $this); $vocabulary_executable->import(); foreach ($vocabulary_data_rows as $row) { /** @var Vocabulary $vocabulary */ $vocabulary = Vocabulary::load($row['id']); $this->assertTrue($vocabulary); $map_row = $vocabulary_id_map->getRowBySource(['id' => $row['id']]); $this->assertNotNull($map_row['destid1']); } // We use taxonomy terms to demonstrate importing and rolling back content // entities. $term_data_rows = [['id' => '1', 'vocab' => '1', 'name' => 'music'], ['id' => '2', 'vocab' => '2', 'name' => 'Bach'], ['id' => '3', 'vocab' => '2', 'name' => 'Beethoven']]; $ids = ['id' => ['type' => 'integer']]; $config = ['id' => 'terms', 'migration_tags' => ['Import and rollback test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => $term_data_rows, 'ids' => $ids], 'process' => ['tid' => 'id', 'vid' => 'vocab', 'name' => 'name'], 'destination' => ['plugin' => 'entity:taxonomy_term'], 'migration_dependencies' => ['required' => ['vocabularies']]]; $term_migration = Migration::create($config); $term_id_map = $term_migration->getIdMap(); $this->assertTrue($term_migration->getDestinationPlugin()->supportsRollback()); // Pre-create a term, to make sure it isn't deleted on rollback. $preserved_term_ids[] = 1; $new_term = Term::create(['tid' => 1, 'vid' => 1, 'name' => 'music']); $new_term->save(); // Import and validate term entities were created. $term_executable = new MigrateExecutable($term_migration, $this); $term_executable->import(); // Also explicitly mark one row to be preserved on rollback. $preserved_term_ids[] = 2; $map_row = $term_id_map->getRowBySource(['id' => 2]); $dummy_row = new Row(['id' => 2], $ids); $term_id_map->saveIdMapping($dummy_row, [$map_row['destid1']], $map_row['source_row_status'], MigrateIdMapInterface::ROLLBACK_PRESERVE); foreach ($term_data_rows as $row) { /** @var Term $term */ $term = Term::load($row['id']); $this->assertTrue($term); $map_row = $term_id_map->getRowBySource(['id' => $row['id']]); $this->assertNotNull($map_row['destid1']); } // Rollback and verify the entities are gone. $term_executable->rollback(); foreach ($term_data_rows as $row) { $term = Term::load($row['id']); if (in_array($row['id'], $preserved_term_ids)) { $this->assertNotNull($term); } else { $this->assertNull($term); } $map_row = $term_id_map->getRowBySource(['id' => $row['id']]); $this->assertFalse($map_row); } $vocabulary_executable->rollback(); foreach ($vocabulary_data_rows as $row) { $term = Vocabulary::load($row['id']); $this->assertNull($term); $map_row = $vocabulary_id_map->getRowBySource(['id' => $row['id']]); $this->assertFalse($map_row); } // Test that simple configuration is not rollbackable. $term_setting_rows = [['id' => 1, 'override_selector' => '0', 'terms_per_page_admin' => '10']]; $ids = ['id' => ['type' => 'integer']]; $config = ['id' => 'taxonomy_settings', 'migration_tags' => ['Import and rollback test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => $term_setting_rows, 'ids' => $ids], 'process' => ['override_selector' => 'override_selector', 'terms_per_page_admin' => 'terms_per_page_admin'], 'destination' => ['plugin' => 'config', 'config_name' => 'taxonomy.settings'], 'migration_dependencies' => ['required' => ['vocabularies']]]; $settings_migration = Migration::create($config); $this->assertFalse($settings_migration->getDestinationPlugin()->supportsRollback()); }
/** * {@inheritdoc} * * @todo: Create the migration with the correct parameters for using stub * entities for entity references. */ public function migrateContentFromTemp(EntityTypeInterface $entity_type) { $id = $entity_type->id() . '__from_tmp'; if (!($migration = Migration::load($id))) { $values = ['id' => $id, 'label' => '', 'process' => $this->getFieldMap($entity_type), 'source' => ['plugin' => 'tempstore'], 'destination' => ['plugin' => 'multiversion']]; $migration = Migration::create($values); $migration->save(); } $this->executeMigration($migration); return $this; }
/** * Tests rolling back configuration and content entities. */ public function testRollback() { // We use vocabularies to demonstrate importing and rolling back // configuration entities. $vocabulary_data_rows = [['id' => '1', 'name' => 'categories', 'weight' => '2'], ['id' => '2', 'name' => 'tags', 'weight' => '1']]; $ids = ['id' => ['type' => 'integer']]; $config = ['id' => 'vocabularies', 'migration_tags' => ['Import and rollback test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => $vocabulary_data_rows, 'ids' => $ids], 'process' => ['vid' => 'id', 'name' => 'name', 'weight' => 'weight'], 'destination' => ['plugin' => 'entity:taxonomy_vocabulary']]; $vocabulary_migration = Migration::create($config); $vocabulary_id_map = $vocabulary_migration->getIdMap(); $this->assertTrue($vocabulary_migration->getDestinationPlugin()->supportsRollback()); // Import and validate vocabulary config entities were created. $vocabulary_executable = new MigrateExecutable($vocabulary_migration, $this); $vocabulary_executable->import(); foreach ($vocabulary_data_rows as $row) { /** @var Vocabulary $vocabulary */ $vocabulary = Vocabulary::load($row['id']); $this->assertTrue($vocabulary); $map_row = $vocabulary_id_map->getRowBySource(['id' => $row['id']]); $this->assertNotNull($map_row['destid1']); } // We use taxonomy terms to demonstrate importing and rolling back // content entities. $term_data_rows = [['id' => '1', 'vocab' => '1', 'name' => 'music'], ['id' => '2', 'vocab' => '2', 'name' => 'Bach'], ['id' => '3', 'vocab' => '2', 'name' => 'Beethoven']]; $ids = ['id' => ['type' => 'integer']]; $config = ['id' => 'terms', 'migration_tags' => ['Import and rollback test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => $term_data_rows, 'ids' => $ids], 'process' => ['tid' => 'id', 'vid' => 'vocab', 'name' => 'name'], 'destination' => ['plugin' => 'entity:taxonomy_term'], 'migration_dependencies' => ['required' => ['vocabularies']]]; $term_migration = Migration::create($config); $term_id_map = $term_migration->getIdMap(); $this->assertTrue($term_migration->getDestinationPlugin()->supportsRollback()); // Import and validate term entities were created. $term_executable = new MigrateExecutable($term_migration, $this); $term_executable->import(); foreach ($term_data_rows as $row) { /** @var Term $term */ $term = Term::load($row['id']); $this->assertTrue($term); $map_row = $term_id_map->getRowBySource(['id' => $row['id']]); $this->assertNotNull($map_row['destid1']); } // Rollback and verify the entities are gone. $term_executable->rollback(); foreach ($term_data_rows as $row) { $term = Term::load($row['id']); $this->assertNull($term); $map_row = $term_id_map->getRowBySource(['id' => $row['id']]); $this->assertFalse($map_row); } $vocabulary_executable->rollback(); foreach ($vocabulary_data_rows as $row) { $term = Vocabulary::load($row['id']); $this->assertNull($term); $map_row = $vocabulary_id_map->getRowBySource(['id' => $row['id']]); $this->assertFalse($map_row); } // Test that simple configuration is not rollbackable. $term_setting_rows = [['id' => 1, 'override_selector' => '0', 'terms_per_page_admin' => '10']]; $ids = ['id' => ['type' => 'integer']]; $config = ['id' => 'taxonomy_settings', 'migration_tags' => ['Import and rollback test'], 'source' => ['plugin' => 'embedded_data', 'data_rows' => $term_setting_rows, 'ids' => $ids], 'process' => ['override_selector' => 'override_selector', 'terms_per_page_admin' => 'terms_per_page_admin'], 'destination' => ['plugin' => 'config', 'config_name' => 'taxonomy.settings'], 'migration_dependencies' => ['required' => ['vocabularies']]]; $settings_migration = Migration::create($config); $this->assertFalse($settings_migration->getDestinationPlugin()->supportsRollback()); }
protected function execute(InputInterface $input, OutputInterface $output) { $template_storage = \Drupal::service('migrate.template_storage'); $this->registerMigrateDB($input, $output); $this->migrateConnection = $this->getDBConnection($output, 'default', 'migrate'); if (!($drupal_version = $this->getLegacyDrupalVersion($this->migrateConnection))) { $output->writeln('[-] <error>' . $this->trans('commands.migrate.setup.questions.not-drupal') . '</error>'); return; } $database_state['key'] = 'upgrade'; $database_state['database'] = $this->getDBInfo(); $database_state_key = 'migrate_upgrade_' . $drupal_version; \Drupal::state()->set($database_state_key, $database_state); $version_tag = 'Drupal ' . $drupal_version; $migration_templates = $template_storage->findTemplatesByTag($version_tag); $migrations = []; $builderManager = \Drupal::service('plugin.manager.migrate.builder'); foreach ($migration_templates as $template_id => $template) { if (isset($template['builder'])) { $variants = $builderManager->createInstance($template['builder']['plugin'], $template['builder'])->buildMigrations($template); } else { $variants = array(Migration::create($template)); } /** * @var \Drupal\migrate\Entity\MigrationInterface[] $variants */ foreach ($variants as $variant) { $variant->set('template', $template_id); } $migrations = array_merge($migrations, $variants); } 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) { $output->writeln('[-] <error>' . $e->getMessage() . '</error>'); } catch (PluginNotFoundException $e) { $output->writeln('[-] <error>' . $e->getMessage() . '</error>'); } } if (empty($migration_ids)) { if (empty($migrations)) { $output->writeln('[-] <info>' . sprintf($this->trans('commands.migrate.setup.messages.migrations-not-found'), count($migrations)) . '</info>'); } else { $output->writeln('[-] <error>' . sprintf($this->trans('commands.migrate.setup.messages.migrations-already-exist'), count($migrations)) . '</error>'); } } else { $output->writeln('[-] <info>' . sprintf($this->trans('commands.migrate.setup.messages.migrations-created'), count($migrations), $version_tag) . '</info>'); } }
/** * {@inheritdoc} */ public function buildMigrations(array $template) { $migrations = []; foreach ($this->getVocabularyIdMap($template['source']) as $source_vid => $destination_vid) { $values = $template; $values['id'] .= '__' . $source_vid; $values['source']['vid'] = $source_vid; $migration = Migration::create($values); $migration->setProcessOfProperty($destination_vid, 'tid'); $migrations[] = $migration; } return $migrations; }