comparison modules/contrib/migrate_plus/src/Plugin/migrate/process/EntityLookup.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4c8ae668cc8c
1 <?php
2
3 /**
4 * @file
5 * Contains Drupal\migrate_plus\Plugin\migrate\process\EntityGenerate.
6 */
7
8 namespace Drupal\migrate_plus\Plugin\migrate\process;
9
10 use Drupal\Core\Entity\EntityManagerInterface;
11 use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface;
12 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
13 use Drupal\migrate\Plugin\MigrationInterface;
14 use Drupal\migrate\MigrateException;
15 use Drupal\migrate\MigrateExecutableInterface;
16 use Drupal\migrate\ProcessPluginBase;
17 use Drupal\migrate\Row;
18 use Symfony\Component\DependencyInjection\ContainerInterface;
19
20 /**
21 * This plugin looks for existing entities.
22 *
23 * @MigrateProcessPlugin(
24 * id = "entity_lookup",
25 * handle_multiples = TRUE
26 * )
27 *
28 * In its most simple form, this plugin needs no configuration. However, if the
29 * lookup properties cannot be determined through introspection, define them via
30 * configuration.
31 *
32 * Example usage with minimal configuration:
33 * @code
34 * destination:
35 * plugin: 'entity:node'
36 * process:
37 * type:
38 * plugin: default_value
39 * default_value: page
40 * field_tags:
41 * plugin: entity_lookup
42 * source: tags
43 * @endcode
44 *
45 * Example usage with full configuration:
46 * @code
47 * field_tags:
48 * plugin: entity_lookup
49 * source: tags
50 * value_key: name
51 * bundle_key: vid
52 * bundle: tags
53 * entity_type: taxonomy_term
54 * ignore_case: true
55 * @endcode
56 */
57 class EntityLookup extends ProcessPluginBase implements ContainerFactoryPluginInterface {
58
59 /** @var \Drupal\Core\Entity\EntityManagerInterface */
60 protected $entityManager;
61
62 /** @var \Drupal\migrate\Plugin\MigrationInterface */
63 protected $migration;
64
65 /** @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface */
66 protected $selectionPluginManager;
67
68 /** @var string */
69 protected $destinationEntityType;
70
71 /** @var string|bool */
72 protected $destinationBundleKey;
73
74 /** @var string */
75 protected $lookupValueKey;
76
77 /** @var string */
78 protected $lookupBundleKey;
79
80 /** @var string */
81 protected $lookupBundle;
82
83 /** @var string */
84 protected $lookupEntityType;
85
86 /** @var string */
87 protected $destinationProperty;
88
89 /**
90 * {@inheritdoc}
91 */
92 public function __construct(array $configuration, $pluginId, $pluginDefinition, MigrationInterface $migration, EntityManagerInterface $entityManager, SelectionPluginManagerInterface $selectionPluginManager) {
93 parent::__construct($configuration, $pluginId, $pluginDefinition);
94 $this->migration = $migration;
95 $this->entityManager = $entityManager;
96 $this->selectionPluginManager = $selectionPluginManager;
97 $pluginIdParts = explode(':', $this->migration->getDestinationPlugin()->getPluginId());
98 $this->destinationEntityType = empty($pluginIdParts[1]) ?: $pluginIdParts[1];
99 $this->destinationBundleKey = !$this->destinationEntityType ?: $this->entityManager->getDefinition($this->destinationEntityType)->getKey('bundle');
100 }
101
102 /**
103 * {@inheritdoc}
104 */
105 public static function create(ContainerInterface $container, array $configuration, $pluginId, $pluginDefinition, MigrationInterface $migration = NULL) {
106 return new static(
107 $configuration,
108 $pluginId,
109 $pluginDefinition,
110 $migration,
111 $container->get('entity.manager'),
112 $container->get('plugin.manager.entity_reference_selection')
113 );
114 }
115
116 /**
117 * {@inheritdoc}
118 */
119 public function transform($value, MigrateExecutableInterface $migrateExecutable, Row $row, $destinationProperty) {
120 $this->determineLookupProperties($destinationProperty);
121
122 $this->destinationProperty = $this->configuration['destination_field'];
123
124 return $this->query($value);
125 }
126
127 /**
128 * Determine the lookup properties from config or target field configuration.
129 *
130 * @param string $destinationProperty
131 * The destination property currently worked on. This is only used together
132 * with the $row above.
133 */
134 protected function determineLookupProperties($destinationProperty) {
135 if (!empty($this->configuration['value_key'])) {
136 $this->lookupValueKey = $this->configuration['value_key'];
137 }
138 if (!empty($this->configuration['bundle_key'])) {
139 $this->lookupBundleKey = $this->configuration['bundle_key'];
140 }
141 if (!empty($this->configuration['bundle'])) {
142 $this->lookupBundle = $this->configuration['bundle'];
143 }
144 if (!empty($this->configuration['entity_type'])) {
145 $this->lookupEntityType = $this->configuration['entity_type'];
146 }
147
148 if (empty($this->lookupValueKey) || empty($this->lookupBundleKey) || empty($this->lookupBundle) || empty($this->lookupEntityType)) {
149 // See if we can introspect the lookup properties from the destination field.
150 if (!empty($this->migration->getProcess()[$this->destinationBundleKey][0]['default_value'])) {
151 $destinationEntityBundle = $this->migration->getProcess()[$this->destinationBundleKey][0]['default_value'];
152 $fieldConfig = $this->entityManager->getFieldDefinitions($this->destinationEntityType, $destinationEntityBundle)[$destinationProperty]->getConfig($destinationEntityBundle);
153 if ($fieldConfig->getType() != 'entity_reference') {
154 throw new MigrateException('The entity_lookup plugin found no entity reference field.');
155 }
156
157 if (empty($this->lookupBundle)) {
158 $handlerSettings = $fieldConfig->getSetting('handler_settings');
159 $bundles = array_filter((array) $handlerSettings['target_bundles']);
160 if (count($bundles) == 1) {
161 $this->lookupBundle = reset($bundles);
162 }
163 // This was added in 8.1.x is not supported in 8.0.x.
164 elseif (!empty($handlerSettings['auto_create']) && !empty($handlerSettings['auto_create_bundle'])) {
165 $this->lookupBundle = reset($handlerSettings['auto_create_bundle']);
166 }
167 }
168
169 // Make an assumption that if the selection handler can target more than
170 // one type of entity that we will use the first entity type.
171 $this->lookupEntityType = $this->lookupEntityType ?: reset($this->selectionPluginManager->createInstance($fieldConfig->getSetting('handler'))->getPluginDefinition()['entity_types']);
172 $this->lookupValueKey = $this->lookupValueKey ?: $this->entityManager->getDefinition($this->lookupEntityType)->getKey('label');
173 $this->lookupBundleKey = $this->lookupBundleKey ?: $this->entityManager->getDefinition($this->lookupEntityType)->getKey('bundle');
174 }
175 }
176
177 // If there aren't enough lookup properties available by now, then bail.
178 if (empty($this->lookupValueKey)) {
179 throw new MigrateException('The entity_lookup plugin requires a value_key, none located.');
180 }
181 if (!empty($this->lookupBundleKey) && empty($this->lookupBundle)) {
182 throw new MigrateException('The entity_lookup plugin found no bundle but destination entity requires one.');
183 }
184 if (empty($this->lookupEntityType)) {
185 throw new MigrateException('The entity_lookup plugin requires a entity_type, none located.');
186 }
187 }
188
189 /**
190 * Checks for the existence of some value.
191 *
192 * @param $value
193 * The value to query.
194 *
195 * @return mixed|null
196 * Entity id if the queried entity exists. Otherwise NULL.
197 */
198 protected function query($value) {
199 // Entity queries typically are case-insensitive. Therefore, we need to
200 // handle case sensitive filtering as a post-query step. By default, it
201 // filters case insensitive. Change to true if that is not the desired
202 // outcome.
203 $ignoreCase = !empty($this->configuration['ignore_case']) ?: FALSE;
204
205 $multiple = is_array($value);
206
207 $query = $this->entityManager->getStorage($this->lookupEntityType)
208 ->getQuery()
209 ->condition($this->lookupValueKey, $value, $multiple ? 'IN' : NULL);
210
211 if ($this->lookupBundleKey) {
212 $query->condition($this->lookupBundleKey, $this->lookupBundle);
213 }
214 $results = $query->execute();
215
216 if (empty($results)) {
217 return NULL;
218 }
219
220 if ($multiple && !empty($this->destinationProperty)) {
221 array_walk($results, function (&$value) {
222 $value = [$this->destinationProperty => $value];
223 });
224
225 return array_values($results);
226 }
227
228 // By default do a case-sensitive comparison.
229 if (!$ignoreCase) {
230 // Returns the entity's identifier.
231 foreach ($results as $identifier) {
232 if ($value === $this->entityManager->getStorage($this->lookupEntityType)->load($identifier)->{$this->lookupValueKey}->value) {
233 return $identifier;
234 }
235 }
236 }
237
238 return reset($results);
239 }
240
241 }