Drupal 8 Migrate Process Plugin: migration_lookup_target_ids
I was having some difficulties using the migration_lookup process plugin. I wrote this plugin so that I could make sense of how the migration lookup was working and the data that it was returning. The plugin ended up being something that I use after every migration_lookup as it seems to ensure error-free lookups. YMMV.
UPDATE: After moving from Drupal 8.5 to 8.7.3 I had to make some changes to this.
There is almost certainly an out-of-the-box way of writing migration YML so that this plugin is not needed. For now, my 2-year old D8 site will live on with this plugin.
Drupal 8.7.3
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
<?php namespace Drupal\mymodule_migrate\Plugin\migrate\process; use Drupal\migrate\MigrateExecutableInterface; use Drupal\migrate\ProcessPluginBase; use Drupal\migrate\Row; /** * Converts Migration Lookup results into target_id and target_revision_id. * * Use this after using migration_lookup for entity reference and entity * reference revisions migrations. This solves issues with inconsistencies * between paragraph and node lookups. * * Example: * * @code * process: * field_team_players: * - * plugin: skip_on_empty * method: process * source: player_ids * - * plugin: migration_lookup * migration: player_node * - * plugin: migration_lookup_target_ids * @endcode * * @see \Drupal\migrate\Plugin\MigrateProcessInterface * * @MigrateProcessPlugin( * id = "migration_lookup_target_ids", * handle_multiples = TRUE * ) */ class MigrationLookupTargetIds extends ProcessPluginBase { /** * {@inheritdoc} */ public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { // Prevent exception and subsequent row import failure if $value is NULL. if (is_null($value)) { return $value; } // Make sure we are always operating on an array. if (is_string($value)) { $value = [$value]; } // Loop through each subitem. // $subitem may have 1 or 2 elements depending on the migration source. // Each subitem can be one of the following: // - Single string value (converted to array before processing (below)). // - Array with single element (string). // - Array with two elements, both strings. foreach ($value as $key => &$subitem) { if (is_string($subitem)) { $subitem = [$subitem]; } // Make sure we have a single-dimensional array. if (is_array($subitem[0]) && count($subitem) == 1) { $subitem = $subitem[0]; } if (!empty($subitem)) { $this->processTargetIds($subitem); } } return $value; } /** * Change indexes from numeric to target_id and target_revision_id. * * @param array $value * Array of one or two values (two for entity reference revisions only) */ private function processTargetIds(array &$value) { $value['target_id'] = $value[0]; unset($value[0]); if (!empty($value[1])) { // Entity reference revisions require this. $value['target_revision_id'] = $value[1]; unset($value[1]); } } } |
Drupal 8.5:
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
<?php namespace Drupal\mymodule_migrate\Plugin\migrate\process; use Drupal\migrate\MigrateExecutableInterface; use Drupal\migrate\ProcessPluginBase; use Drupal\migrate\Row; /** * Converts Migration Lookup results into target_id and target_revision_id. * * Use this after using migration_lookup for entity reference and entity * reference revisions migrations. This solves issues with inconsistencies * between paragraph and node lookups. * * Example: * * @code * process: * field_team_players: * - * plugin: skip_on_empty * method: process * source: player_ids * - * plugin: migration_lookup * migration: player_node * - * plugin: migration_lookup_target_ids * @endcode * * @see \Drupal\migrate\Plugin\MigrateProcessInterface * * @MigrateProcessPlugin( * id = "migration_lookup_target_ids", * handle_multiples = TRUE * ) */ class MigrationLookupTargetIds extends ProcessPluginBase { /** * {@inheritdoc} */ public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { if (empty($value)) { // Ignore empty values. return $value; } // Make sure we are always operating on an array. if (is_string($value)) { $value = [$value]; } // If the first item is a string there's no need to loop. Process one value. // $value may have one or two elements depending on the migration source. if (is_string($value[0])) { $this->processTargetIds($value); } else { // Loop through each subitem. // $subitem may have 1 or 2 elements depending on the migration source. // Each subitem can be one of the following: // - Single string value (converted to array before processing (below)). // - Array with single element (string). // - Array with two elements, both strings. foreach ($value as $key => &$subitem) { if (is_string($subitem)) { $subitem = [$subitem]; } $this->processTargetIds($subitem); } } return $value; } /** * Change indexes from numeric to target_id and target_revision_id. * * @param array $value * Array of one or two values (two for entity reference revisions only) */ private function processTargetIds(array &$value) { $value['target_id'] = $value[0]; unset($value[0]); if (!empty($value[1])) { // Entity reference revisions require this. $value['target_revision_id'] = $value[1]; unset($value[1]); } } } |
2 Comments
mstrelan
Thanks for this plugin. I found when creating stub paragraphs migration_lookup will return a keyed array of “id” and “revision_id”. I modified this plugin to convert these keys to “target_id” and “target_revision_id” if they were found. See drupal.org issue 2890690 for reference.
Eduard
Thank you! I think this is really good, you should feature request in https://www.drupal.org/project/migrate_plus so all the comunity can profit from it.