Migration setup

You can generate migrations for your Drupal 7 content and configuration using the Migrate Drupal module. The Migrate Drupal module is based on the Migrate API.

The generated content migrations work fine for your standard fields from the field module but Migrate API doesn’t provide out of the box migrate plugins for custom fields. A way to migrate them is by customizing the migration.

Custom migration for domain access records

I had to write a custom migration for the domain access records. The domain access module manages access for nodes and users on multiple domains.

The challenge for those records was that they’re stored completely differently in Drupal 7. The Migrate API can’t fetch their data out of the box into a row. For less complex fields you could implement a custom process plugin. In this, you’d hook yourself into the process of a migration from a single field. There, you can transform your data as needed, such as filtering, mapping, or generally transforming values.

Matching data structures

To migrate complex data from source to destination it is often helpful to model their relationship in an entity relation diagram.

As you can see in the following picture Drupal 8 splits the fields for the domain access records into separate tables while Drupal 7 stores multiple fields in one table.

Entity relation diagram of domain records in Drupal 7 and Drupal 8
Domain access records, Drupal 7 vs. Drupal 8

Extending a migration plugin

Existing plugins can be extended with additional data through protected and public methods. The Drupal\migrate\Row class has a method setSourceProperty() which allows you to add properties on the source row. Afterwards, you can access the new property in your migration YAML file in the same format as standard fields from the field module.

field_YOUR_CUSTOM_FIELD:
 -
   plugin: sub_process
   source: ADDED_SOURCE_PROPERTY
   process:
     ID_XY: PROPERTY_ATTRIBUTE

To shorten the feedback loop while developing use this drush command:
drush mim migration_id --limit=1 --idlist=YOUR_ID --update
With the combination of --limit and --idlist only the rows listed in --idlist are being migrated and it stops after reaching the limit of --limit.

Conclusion

Do you need to migrate data into Drupal? I learned that going through the following steps is helpful:

  1. Check if there’s a migration template for your case. These exist for nearly all sources with relevant plugins. Generate them automatically with Migrate Drupal for Drupal-to-Drupal migrations.
  2. Get yourself an overview of the data structure for the more complex fields. If Migrate API doesn’t provide a plugin that contains the field data in its source row, implement a custom migration, or extend an existing one.
  3. Do you have to deal with multiple field values? Check out the SubProcess plugin.
  4. In a custom process plugin, the properties are accessible from the fetched row. That’s how you’re able to filter, map, or transform those properties as you like.