Same name and namespace in other branches
  1. 9 core/modules/migrate/src/Plugin/migrate/process/MigrationLookup.php \Drupal\migrate\Plugin\migrate\process\MigrationLookup

Looks up the value of a property based on a previous migration.

It is important to maintain relationships among content coming from the source site. For example, on the source site, a given user account may have an ID of 123, but the Drupal user account created from it may have a uid of 456. The migration process maintains the relationships between source and destination identifiers in map tables, and this information is leveraged by the migration_lookup process plugin.

Available configuration keys

  • migration: A single migration ID, or an array of migration IDs.
  • source_ids: (optional) An array keyed by migration IDs with values that are a list of source properties.
  • stub_id: (optional) Identifies the migration which will be used to create any stub entities.
  • no_stub: (optional) Prevents the creation of a stub entity when no relationship is found in the migration map.

Examples:

Consider a node migration, where you want to maintain authorship. Let's assume that users are previously migrated in a migration named 'users'. The 'users' migration saved the mapping between the source and destination IDs in a map table. The node migration example below maps the node 'uid' property so that we first take the source 'author' value and then do a lookup for the corresponding Drupal user ID from the map table.


process:
  uid:
    plugin: migration_lookup
    migration: users
    source: author

The value of 'migration' can be a list of migration IDs. When using multiple migrations it is possible each use different source identifiers. In this case one can use source_ids which is an array keyed by the migration IDs and the value is a list of source properties. See example below.


process:
  uid:
    plugin: migration_lookup
      migration:
        - users
        - members
      source_ids:
        users:
          - author
        members:
          - id

If the migration_lookup plugin does not find the source ID in the migration map it will create a stub entity for the relationship to use. This stub is generated by the migration provided. In the case of multiple migrations the first value of the migration list will be used, but you can select the migration you wish to use by using the stub_id configuration key. The example below uses 'members' migration to create stub entities.


process:
  uid:
    plugin: migration_lookup
    migration:
      - users
      - members
    stub_id: members

To prevent the creation of a stub entity when no relationship is found in the migration map, 'no_stub' configuration can be used as shown below.


process:
  uid:
    plugin: migration_lookup
    migration: users
    no_stub: true
    source: author

If the source value passed in to the plugin is NULL, boolean FALSE, an empty array or an empty string, the plugin will throw a MigrateSkipProcessException, causing further plugins in the process to be skipped.

Plugin annotation


@MigrateProcessPlugin(
  id = "migration_lookup"
)

Hierarchy

Expanded class hierarchy of MigrationLookup

See also

\Drupal\migrate\Plugin\MigrateProcessInterface

2 files declare their use of MigrationLookup
LegacyMigrationLookupTest.php in core/modules/migrate/tests/src/Unit/process/LegacyMigrationLookupTest.php
MigrationLookupTest.php in core/modules/migrate/tests/src/Unit/process/MigrationLookupTest.php

File

core/modules/migrate/src/Plugin/migrate/process/MigrationLookup.php, line 109

Namespace

Drupal\migrate\Plugin\migrate\process
View source
class MigrationLookup extends ProcessPluginBase implements ContainerFactoryPluginInterface {

  /**
   * The migration to be executed.
   *
   * @var \Drupal\migrate\Plugin\MigrationInterface
   */
  protected $migration;

  /**
   * The migrate lookup service.
   *
   * @var \Drupal\migrate\MigrateLookupInterface
   */
  protected $migrateLookup;

  /**
   * The migrate stub service.
   *
   * @var \Drupal\migrate\MigrateStubInterface
   */
  protected $migrateStub;

  /**
   * Constructs a MigrationLookup object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\migrate\Plugin\MigrationInterface $migration
   *   The Migration the plugin is being used in.
   * @param \Drupal\migrate\MigrateLookupInterface $migrate_lookup
   *   The migrate lookup service.
   * @param \Drupal\migrate\MigrateStubInterface $migrate_stub
   *   The migrate stub service.
   */

  // @codingStandardsIgnoreLine
  public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, $migrate_lookup, $migrate_stub = NULL) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    if (!$migrate_lookup instanceof MigrateLookupInterface) {
      @trigger_error('Not passing the migrate lookup service as the fifth parameter to ' . __METHOD__ . ' is deprecated in drupal:8.8.0 and will throw a type error in drupal:9.0.0. Pass an instance of \\Drupal\\migrate\\MigrateLookupInterface. See https://www.drupal.org/node/3047268', E_USER_DEPRECATED);
      $migrate_lookup = \Drupal::service('migrate.lookup');
    }
    if (!$migrate_stub instanceof MigrateStubInterface) {
      @trigger_error('Not passing the migrate stub service as the sixth parameter to ' . __METHOD__ . ' is deprecated in drupal:8.8.0 and will throw a type error in drupal:9.0.0. Pass an instance of \\Drupal\\migrate\\MigrateStubInterface. See https://www.drupal.org/node/3047268', E_USER_DEPRECATED);
      $migrate_stub = \Drupal::service('migrate.stub');
    }
    $this->migration = $migration;
    $this->migrateLookup = $migrate_lookup;
    $this->migrateStub = $migrate_stub;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
    return new static($configuration, $plugin_id, $plugin_definition, $migration, $container
      ->get('migrate.lookup'), $container
      ->get('migrate.stub'));
  }

  /**
   * {@inheritdoc}
   *
   * @throws \Drupal\migrate\MigrateSkipProcessException
   * @throws \Drupal\migrate\MigrateException
   */
  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
    $lookup_migration_ids = (array) $this->configuration['migration'];
    $self = FALSE;
    $destination_ids = NULL;
    $source_id_values = [];
    foreach ($lookup_migration_ids as $lookup_migration_id) {
      if ($lookup_migration_id == $this->migration
        ->id()) {
        $self = TRUE;
      }
      if (isset($this->configuration['source_ids'][$lookup_migration_id])) {
        $value = array_values($row
          ->getMultiple($this->configuration['source_ids'][$lookup_migration_id]));
      }
      if (!is_array($value)) {
        $value = [
          $value,
        ];
      }
      $this
        ->skipInvalid($value);
      $source_id_values[$lookup_migration_id] = $value;

      // Re-throw any PluginException as a MigrateException so the executable
      // can shut down the migration.
      try {
        $destination_id_array = $this->migrateLookup
          ->lookup($lookup_migration_id, $value);
      } catch (PluginNotFoundException $e) {
        $destination_id_array = [];
      } catch (MigrateException $e) {
        throw $e;
      } catch (\Exception $e) {
        throw new MigrateException(sprintf('A %s was thrown while processing this migration lookup', gettype($e)), $e
          ->getCode(), $e);
      }
      if ($destination_id_array) {
        $destination_ids = array_values(reset($destination_id_array));
        break;
      }
    }
    if (!$destination_ids && !empty($this->configuration['no_stub'])) {
      return NULL;
    }
    if (!$destination_ids && ($self || isset($this->configuration['stub_id']) || count($lookup_migration_ids) == 1)) {

      // If the lookup didn't succeed, figure out which migration will do the
      // stubbing.
      if ($self) {
        $stub_migration = $this->migration
          ->id();
      }
      elseif (isset($this->configuration['stub_id'])) {
        $stub_migration = $this->configuration['stub_id'];
      }
      else {
        $stub_migration = reset($lookup_migration_ids);
      }

      // Rethrow any exception as a MigrateException so the executable can shut
      // down the migration.
      try {
        $destination_ids = $this->migrateStub
          ->createStub($stub_migration, $source_id_values[$stub_migration], [], FALSE);
      } catch (\LogicException $e) {

        // For BC reasons, we must allow attempting to stub a derived migration.
      } catch (PluginNotFoundException $e) {

        // For BC reasons, we must allow attempting to stub a non-existent
        // migration.
      } catch (MigrateException $e) {
        throw $e;
      } catch (MigrateSkipRowException $e) {
        throw $e;
      } catch (\Exception $e) {
        throw new MigrateException(sprintf('A(n) %s was thrown while attempting to stub.', gettype($e)), $e
          ->getCode(), $e);
      }
    }
    if ($destination_ids) {
      if (count($destination_ids) == 1) {
        return reset($destination_ids);
      }
      else {
        return $destination_ids;
      }
    }
  }

  /**
   * Skips the migration process entirely if the value is invalid.
   *
   * @param array $value
   *   The incoming value to check.
   *
   * @throws \Drupal\migrate\MigrateSkipProcessException
   */
  protected function skipInvalid(array $value) {
    if (!array_filter($value, [
      $this,
      'isValid',
    ])) {
      throw new MigrateSkipProcessException();
    }
  }

  /**
   * Determines if the value is valid for lookup.
   *
   * The only values considered invalid are: NULL, FALSE, [] and "".
   *
   * @param string $value
   *   The value to test.
   *
   * @return bool
   *   Return true if the value is valid.
   */
  protected function isValid($value) {
    return !in_array($value, [
      NULL,
      FALSE,
      [],
      "",
    ], TRUE);
  }

  /**
   * Create a stub row source for later import as stub data.
   *
   * This simple wrapper of the Row constructor allows sub-classing plugins to
   * have more control over the row.
   *
   * @param array $values
   *   An array of values to add as properties on the object.
   * @param array $source_ids
   *   An array containing the IDs of the source using the keys as the field
   *   names.
   *
   * @return \Drupal\migrate\Row
   *   The stub row.
   *
   * @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use the
   *   migrate.stub service to create stubs.
   *
   * @see https://www.drupal.org/node/3047268
   */
  protected function createStubRow(array $values, array $source_ids) {
    @trigger_error(__METHOD__ . ' is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use the migrate.stub service to create stubs. See https://www.drupal.org/node/3047268', E_USER_DEPRECATED);
    return new Row($values, $source_ids, TRUE);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
MigrationLookup::$migrateLookup protected property The migrate lookup service.
MigrationLookup::$migrateStub protected property The migrate stub service.
MigrationLookup::$migration protected property The migration to be executed.
MigrationLookup::create public static function Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface::create
MigrationLookup::createStubRow Deprecated protected function Create a stub row source for later import as stub data.
MigrationLookup::isValid protected function Determines if the value is valid for lookup.
MigrationLookup::skipInvalid protected function Skips the migration process entirely if the value is invalid.
MigrationLookup::transform public function Overrides ProcessPluginBase::transform
MigrationLookup::__construct public function Constructs a \Drupal\Component\Plugin\PluginBase object. Overrides PluginBase::__construct
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
ProcessPluginBase::multiple public function Indicates whether the returned value requires multiple handling. Overrides MigrateProcessInterface::multiple 3
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.