Drupal
Try this one weird trick with the Migrate API
One weird introduction
One of the key concepts of the Drupal Migrate API is the so-called process pipeline, in which we pass a value that is transformed by a series of process plugins. From time to time we find ourselves in the middle of a process pipeline wishing we could easily reference the current value in the process pipeline. I even created an issue on Drupal.org asking for this feature. As it turns out, the feature already exists! That is, as long as you know this one weird trick...
One weird trick
How do you reference the current value of the process pipeline? Use null
as the source. Seriously!
One weird example
Consider the following process pipeline:
process:
field_my_field:
- plugin: callback
callable: strtolower
source: my_source_string
- plugin: concat
source:
- null
- null
delimiter: +
If the value of my_source_string
is Drupal, the value of field_my_field
will be drupal+drupal.
You could try that out in Migrate Sandbox.
What's more, one can use a tilde (~
) within YAML to indicate a null value. That means we can use ~
in place of null
when specifying the source
:
process:
field_my_field:
- plugin: callback
callable: strtolower
source: my_source_string
- plugin: concat
source:
- ~
- ~
delimiter: +
That gives us the same result. This syntax is particularly satisfying because ~
resembles water flowing through a pipeline!
One weird explanation
In case you're curious as to why that works, we need to look at a few lines of the Get process plugin.
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
$source = $this->configuration['source'];
$properties = is_string($source) ? [$source] : $source;
$return = [];
foreach ($properties as $property) {
if ($property || (string) $property === '0') {
$return[] = $row->get($property);
}
else {
$return[] = $value;
}
}
...
}
If the process plugin is configured with a source
and the configured value is null
, that else
block runs. Whatever value was passed to the plugin is returned. Wait, we never used get
though, did we? It turns out that any time the source
is configured, an instance of the get
plugin gets thrown into the pipeline automatically. So indeed the weird explanation is pretty weird, perhaps so weird that it's not worth the effort to understand.
Is this trick a good idea?
I reported this behavior to the current maintainers of the Migrate API and it was news to them. Indeed, the behavior is not documented in get
and doesn't appear to be documented anywhere else. So is this a feature or a bug? I've heard it said that an undocumented feature is a bug. I'm personally leaning toward glitch, like Minus World in Super Mario Bros. Whatever you call it, this one weird trick may be just what you need in your next migration.