diff --git a/src/Plugin/migrate/process/EntityGenerate.php b/src/Plugin/migrate/process/EntityGenerate.php new file mode 100644 index 0000000..d15eb9a --- /dev/null +++ b/src/Plugin/migrate/process/EntityGenerate.php @@ -0,0 +1,103 @@ +generateEntity($value); + } + + return $result; + } + + /** + * Generates stub entity for a given value. + * + * @param string $value + * Value to use in creation of stub entity. + * + * @return int|string + * The entity id of the generated entity. + */ + protected function generateEntity($value) { + return $this->entityManager + ->getStorage($this->lookupEntityType) + ->create($this->stub($value)) + ->save() + ->id(); + } + + /** + * Fabricate a stub entity. + * + * This is intended to be extended by implementing classes to provide for more + * dynamic default values, rather than just static ones. + * + * @param $value + * Value to use in creation of stub entity. + * + * @return array + * The stub entity. + */ + protected function stub($value) { + $stub = [$this->lookupValueKey => $value]; + + if ($this->lookupBundleKey) { + $stub[$this->lookupBundleKey] = $this->lookupBundle; + } + + // Gather any static default values for properties/fields. + if (isset($this->configuration['default_values']) && is_array($this->configuration['default_values'])) { + foreach ($this->configuration['default_values'] as $key => $value) { + $stub[$key] = $value; + } + } + + return $stub; + } + +} diff --git a/src/Plugin/migrate/process/EntityLookup.php b/src/Plugin/migrate/process/EntityLookup.php new file mode 100644 index 0000000..940d029 --- /dev/null +++ b/src/Plugin/migrate/process/EntityLookup.php @@ -0,0 +1,219 @@ +migration = $migration; + $this->entityManager = $entityManager; + $this->selectionPluginManager = $selectionPluginManager; + $this->destinationEntityType = substr($this->migration->getDestinationPlugin()->getPluginId(), 7); + $this->destinationBundleKey = $this->entityManager->getDefinition($this->destinationEntityType)->getKey('bundle'); + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $pluginId, $pluginDefinition, MigrationInterface $migration = NULL) { + return new static( + $configuration, + $pluginId, + $pluginDefinition, + $migration, + $container->get('entity.manager'), + $container->get('plugin.manager.entity_reference_selection') + ); + } + + /** + * {@inheritdoc} + */ + public function transform($value, MigrateExecutableInterface $migrateExecutable, Row $row, $destinationProperty) { + $this->determineLookupProperties($destinationProperty); + + return $this->query($value); + } + + /** + * Determine the lookup properties from config or target field configuration. + * + * @param string $destinationProperty + * The destination property currently worked on. This is only used together + * with the $row above. + */ + protected function determineLookupProperties($destinationProperty) { + if (!empty($this->configuration['value_key'])) { + $this->lookupValueKey = $this->configuration['value_key']; + } + if (!empty($this->configuration['bundle_key'])) { + $this->lookupBundleKey = $this->configuration['bundle_key']; + } + if (!empty($this->configuration['bundle'])) { + $this->lookupBundle = $this->configuration['bundle']; + } + if (!empty($this->configuration['entity_type'])) { + $this->lookupEntityType = $this->configuration['entity_type']; + } + + if (empty($this->lookupValueKey) || empty($this->lookupBundleKey) || $this->lookupBundle || empty($this->lookupEntityType)) { + // See if we can introspect the lookup properties from the destination field. + if (!empty($this->migration->getProcess()[$this->destinationBundleKey][0]['default_value'])) { + $destinationEntityBundle = $this->migration->getProcess()[$this->destinationBundleKey][0]['default_value']; + $fieldConfig = $this->entityManager->getFieldDefinitions($this->destinationEntityType, $destinationEntityBundle)[$destinationProperty]->getConfig($destinationEntityBundle); + if ($fieldConfig->getType() != 'entity_reference') { + throw new MigrateException('The entity_lookup plugin found no entity reference field.'); + } + + if (empty($this->lookupBundle)) { + $handlerSettings = $fieldConfig->getSetting('handler_settings'); + $bundles = array_filter((array) $handlerSettings['target_bundles']); + if (count($bundles) == 1) { + $this->lookupBundle = reset($bundles); + } + // This was added in 8.1.x is not supported in 8.0.x. + elseif (!empty($handlerSettings['auto_create']) && !empty($handlerSettings['auto_create_bundle'])) { + $this->lookupBundle = reset($handlerSettings['auto_create_bundle']); + } + } + + // Make an assumption that if the selection handler can target more than + // one type of entity that we will use the first entity type. + $this->lookupEntityType = $this->lookupEntityType ?: reset($this->selectionPluginManager->createInstance($fieldConfig->getSetting('handler'))->getPluginDefinition()['entity_types']); + $this->lookupValueKey = $this->lookupValueKey ?: $this->entityManager->getDefinition($this->lookupEntityType)->getKey('label'); + $this->lookupBundleKey = $this->lookupBundleKey ?: $this->entityManager->getDefinition($this->lookupEntityType)->getKey('bundle'); + } + } + + // If there aren't enough lookup properties available by now, then bail. + if (empty($this->lookupValueKey)) { + throw new MigrateException('The entity_lookup plugin requires a value_key, none located.'); + } + if (!empty($this->lookupBundleKey) && empty($this->lookupBundle)) { + throw new MigrateException('The entity_lookup plugin found no bundle but destination entity requires one.'); + } + if (empty($this->lookupEntityType)) { + throw new MigrateException('The entity_lookup plugin requires a entity_type, none located.'); + } + } + + /** + * Checks for the existence of some value. + * + * @param $value + * The value to query. + * + * @return mixed|bool + * Entity id if the queried entity exists. Otherwise FALSE. + */ + protected function query($value) { + // Entity queries typically are case-insensitive. Therefore, we need to + // handle case sensitive filtering as a post-query step. By default, it + // filters case insensitive. Change to true if that is not the desired + // outcome. + $ignoreCase = !empty($this->configuration['ignore_case']) ?: FALSE; + + $query = $this->entityManager->getStorage($this->lookupEntityType) + ->getQuery() + ->condition($this->lookupValueKey, $value); + if ($this->lookupBundleKey) { + $query->condition($this->lookupBundleKey, $this->lookupBundle); + } + $results = $query->execute(); + + // By default do a case-sensitive comparison. + if (!$ignoreCase) { + // Returns the entity's identifier. + foreach ($results as $identifier) { + if ($value === $this->entityManager->getStorage($this->lookupEntityType)->load($identifier)->{$this->lookupValueKey}->value) { + return $identifier; + } + } + } + + return reset($results); + } + +}