Writing Custom Process Plugins using the Drupal 8 Migrate API

Migrate in Drupal 7 didn't explicitly have the concept of a process plugin but under the hood you were using the "Get" process plugin when you wrote code like $this->addFieldMapping('source', 'destination');

The Drupal 8 Migrate API has taken advantage of the new plugin system to provide a flexible way to process fields. In core, we already have a handful of process plugin examples including the Get plugin. I wouldn't look at the Get plugin for a simple example however.

Why Process Plugins?

The purpose of a process plugin is simply to take a value in and spit a new value out. The plugin can transform the data in anyway it sees fit but if you are following best practices you should ensure that a plugin does only one thing, definitely lean towards multiple process plugins as needed. From our experience so far, process plugins are usually quite simple and often less than 10 lines of code.

Let's take a look at the FileUri plugin. modules/migrate/lib/Drupal/migrate_drupal/Plugin/migrate_drupal/process/FileUri.php

  1. <?php
  2. namespace Drupal\migrate_drupal\Plugin\migrate\process\d6;
  4. use Drupal\migrate\MigrateException;
  5. use Drupal\migrate\MigrateExecutable;
  6. use Drupal\migrate\ProcessPluginBase;
  7. use Drupal\migrate\Row;
  9. /**
  10.  * Process the file url into a D8 compatible URL.
  11.  *
  12.  * @MigrateProcessPlugin(
  13.  * id = "file_uri"
  14.  * )
  15.  */
  16. class FileUri extends ProcessPluginBase {
  18. /**
  19.   * {@inheritdoc}
  20.   */
  21. public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
  23. list($filepath, $file_directory_path, $is_public) = $value;
  25. // Strip the files path from the uri instead of using basename
  26. // so any additional folders in the path are preserved.
  27. $uri = preg_replace('/^' . preg_quote($file_directory_path, '/') . '/', '', $filepath);
  29. return $is_public ? "public://$uri" : "private://$uri";
  30. }
  32. }
  33. ?>

Ignoring the namespace and the use statements which we've all seen before, the first thing of interest is the annotation. Identical to other plugins throughout core, we simply have to define the id key on top of our class and we have a valid migration process plugin.

The MigrateProcessInterface

ProcessPluginBase which we're extending in the above example implements the MigrateProcessInterface. This gives us the transform method which we must implement. The transform method is passed the fields specified in the YAML, transforms the value and return the new data. And that's all there is to it, easy right?

Now lets look at how we use the plugin in our YAML.

  1. id: d6_file
  2. source:
  3.   plugin: d6_file
  4. process:
  5.   filename: filename
  6.   uri:
  7.   plugin: file_uri
  8.   source:
  9. - filepath
  10. - file_directory_path
  11. - is_public
  12.   filemime: filemime
  13.   filesize: filesize
  14.   status: status
  15.   changed: timestamp
  16. destination:
  17.   plugin: entity:file

This is an entire migration (cool right?) but we're only interested specifically in:

  1. uri:
  2.   plugin: file_uri
  3.   source:
  4. - filepath
  5. - file_directory_path
  6. - is_public

The above piece of YAML says, set the destination key uri to the return value of the file_uri plugin which takes an array containing the filepath, file_directory_path and is_public values from the source. Process plugins will run for every row in the source and calculate the required new value for the field they're applied to.

The Process Pipeline

One thing you should be aware of is that the migration process is a pipeline. That is, previously calculated values are passed onto the next process so we can chain plugins. Let's take a look.

  1. process:
  2.   id:
  3. -
  4.   plugin: machine_name
  5.   source: name
  6. -
  7.   plugin: dedupe_entity
  8.   entity_type: user_role
  9.   field: id
  10. -
  11.   plugin: user_update_8002

The above snippet was taken from the Drupal 6 to Drupal 8 user role migration and uses a combination of three process plugins to calculate the required value for the id key. You can read more about the pipeline in the drupal.org documentation.

Author Info

Ben Dougherty

In his free time Ben can be found lurking in the Drupal issue queues, chatting in #drupal-contribute and listening to Oasis. He is known for his superhuman debugging abilities and occasionally enjoys a beer or two.

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.