Please See: Drupal8 Migrate API, Migrating Nodes From Drupal7 – Part 1 for Part-1 of this series. This is the continuation of the same.
Earlier in the series, we went through the process of configuration of the migration source and how a migration module can be written. We also configured the migration definition and source plugin for the nodes that were to be migrated. The migration is dependent of two other migrations: migrate_fruit_vitamins and migrate_fruit_images. Let’s us walk-through their implementations.
2.4 Migrating Taxonomy Terms
Let us create a file /config/install/migrate_plus.migration.migrate_fruit_vitamins.yml with the following content, which is the migration definition for terms that we are going to import from the source instance. The default migration template for taxonomy terms is found at /core/modules/taxonomy/migration_templates/d7_taxonomy_term.yml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
id: migrate_fruit_vitamins label: Migrate Vitamin Terms #migratio group migration_group: fruit dependencies: enforced: module: - fruit_migration source: plugin: migrate_fruit_vitamins # drupal7 connection name target: db_d7 process: tid: tid vid: vocbulary_machine_name name: name description: description weight: weight #for migrating term heirachy parent_id: - plugin: skip_on_empty method: process source: parent - plugin: migration_lookup migration: migrate_fruit_vitamins parent: plugin: default_value default_value: 0 source: '@parent_id' destination: plugin: entity:taxonomy_term |
Create a file \src\Plugin\migrate\source\Vitamins.php inside the module and add the following content to it. This will serve as the source plugin for the terms to be migrated. Let us extend the class Drupal\migrate\Plugin\migrate\source\SqlBase to write our own source plugin class for the terms. The particular methods that will be overridden are:
query()
defines the basic query used to retrieve data from the source table.
fields()
contains an array of the base fields within the source table.
getIds()
Defines the source fields uniquely identifying a source row.
prepareRow()
Adds additional data to the row. Any property we create using $row->setSourceProperty() will be available in the “process” step.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
<?php /** * @file * Contains \Drupal\migrate_custom\Plugin\migrate\source\Vitamins. */ namespace Drupal\fruit_migration\Plugin\migrate\source; use Drupal\migrate\Row; use Drupal\migrate\Plugin\migrate\source\SqlBase; /** * Import vitamins terms from Drupal7 instance * * @MigrateSource( * id = "migrate_fruit_vitamins", * ) */ class Vitamins extends SqlBase { /** * {@inheritdoc} */ public function query() { $query = $this->select('taxonomy_term_data', 'td'); $query->join('taxonomy_vocabulary', 'tv', 'tv.vid = td.vid'); $query->fields('td', array('tid', 'vid', 'name', 'description', 'weight', 'format')) ->distinct() ->condition('tv.machine_name', 'vitamins'); return $query; } /** * {@inheritdoc} */ public function fields() { return array( 'tid' => $this->t('The term ID.'), 'vid' => $this->t('Existing term VID'), 'name' => $this->t('The name of the term.'), 'description' => $this->t('The term description.'), 'weight' => $this->t('Weight'), 'parent' => $this->t("The Drupal term IDs of the term's parents."), ); } /** * {@inheritdoc} */ public function prepareRow(Row $row) { // Find parents for this row. $parents = $this->select('taxonomy_term_hierarchy', 'th') ->fields('th', array('parent', 'tid')) ->condition('tid', $row->getSourceProperty('tid')) ->execute() ->fetchCol(); $row->setSourceProperty('parent', $parents); $row->setSourceProperty('vocbulary_machine_name', 'vitamins'); return parent::prepareRow($row); } /** * {@inheritdoc} */ public function getIds() { $ids['tid']['type'] = 'integer'; return $ids; } } |
2.5 Migrating Images
Create a file /config/install/migrate_plus.migration.migrate_fruit_images.yml inside the module with the following content, which would be the migration definition for images to be migrated.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
id: migrate_fruit_images label: Fruit Images migration_group: fruit #Migration Sourec source: plugin: migrate_fruit_image constants: # Full path to the drupal7 installation directory. source_base_path: 'C:xampp\htdocs\drupal7' target: db_d7 process: fid: fid filename: filename source_full_path: - plugin: concat delimiter: / source: - constants/source_base_path - filepath - plugin: urlencode uri: plugin: file_copy source: - '@source_full_path' - uri filemime: filemime status: status created: timestamp changed: timestamp uid: uid destination: plugin: entity:file |
Create another file \src\Plugin\migrate\source\FruitImages.php and with the following content. This is the source plugin class for migration of the images. Here, the base plugin class Drupal\file\Plugin\migrate\source\d7\File is extended to implement the plugin.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
<?php /** * @file * Contains \Drupal\fruit_migration\Plugin\migrate\source\FruitImages. */ namespace Drupal\fruit_migration\Plugin\migrate\source; use Drupal\file\Plugin\migrate\source\d7\File; use Drupal\Core\Database\Query\Condition; use Drupal\migrate\Row; /** * Import fruit images form d7 * * @MigrateSource( * id = "migrate_fruit_image" * ) */ class FruitImages extends File { /** * {@inheritdoc} */ public function query() { $query = $this->select('file_managed', 'fm'); $query->join('field_data_field_fruit_image', 'fi', 'fi.field_fruit_image_fid = fm.fid'); $query->join('node', 'n', 'n.nid = fi.entity_id'); $query->fields('fm', ['fid', 'uid', 'filename', 'uri', 'filemime', 'status', 'timestamp']) ->distinct() ->condition('fi.bundle', 'fruit') ->orderBy('n.changed', 'DESC'); // Filter by scheme(s), if configured. if (isset($this->configuration['scheme'])) { $schemes = array(); // Accept either a single scheme, or a list. foreach ((array) $this->configuration['scheme'] as $scheme) { $schemes[] = rtrim($scheme) . '://'; } $schemes = array_map([$this->getDatabase(), 'escapeLike'], $schemes); // uri LIKE 'public://%' OR uri LIKE 'private://%' $conditions = new Condition('OR'); foreach ($schemes as $scheme) { $conditions->condition('uri', $scheme . '%', 'LIKE'); } $query->condition($conditions); } return $query; } } |
In the last step, create a fruit_migration.install file and implement the hook_uninstall function to remove the migration definitions upon uninstalling the module from the database.
1 2 3 4 5 6 7 8 9 |
/* * implements hook_uninstall */ function fruit_migration_uninstall() { \Drupal::entityManager()->getStorage('migration')->load('migrate_fruits')->delete(); \Drupal::entityManager()->getStorage('migration')->load('migrate_fruit_vitamins')->delete(); \Drupal::entityManager()->getStorage('migration')->load('migrate_fruit_images')->delete(); \Drupal::entityManager()->getStorage('migration_group')->load('fruit')->delete(); } |
Voila! We have successfully created our migration module. The structure of the module should look like the one below:
3. Running the migration
Once the module is successfully enabled, navigate to the drupal8(destination) installation directory in the command prompt and execute the command drush migrate-status. This will list all the migrations available and their statuses.
Run the command drush migrate-import –group=fruit from the command prompt to process all the migrations in the group fruit and import the corresponding data from the source.
Migrations can be run individually using the command drush migrate-import <migration_name>. More information about the Drush migrate commands can be found here.
Happy Migrating!!