1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace NuvoleWeb\Drupal\Driver\Cores; |
4
|
|
|
|
5
|
|
|
use function bovigo\assert\assert; |
6
|
|
|
use function bovigo\assert\predicate\hasKey; |
7
|
|
|
use function bovigo\assert\predicate\isNotEmpty; |
8
|
|
|
use function bovigo\assert\predicate\isNotEqualTo; |
9
|
|
|
use Drupal\Core\Cache\Cache; |
10
|
|
|
use Drupal\Driver\Cores\Drupal8 as OriginalDrupal8; |
11
|
|
|
use Drupal\file\Entity\File; |
12
|
|
|
use Drupal\menu_link_content\Entity\MenuLinkContent; |
13
|
|
|
use Drupal\node\Entity\Node; |
14
|
|
|
use Drupal\node\Entity\NodeType; |
15
|
|
|
use Drupal\system\Entity\Menu; |
16
|
|
|
use Drupal\taxonomy\Entity\Term; |
17
|
|
|
use Drupal\taxonomy\Entity\Vocabulary; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* Class Drupal8. |
21
|
|
|
* |
22
|
|
|
* @package NuvoleWeb\Drupal\Driver\Cores |
23
|
|
|
*/ |
24
|
|
|
class Drupal8 extends OriginalDrupal8 implements CoreInterface { |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* {@inheritdoc} |
28
|
|
|
*/ |
29
|
|
View Code Duplication |
public function convertLabelToNodeTypeId($type) { |
|
|
|
|
30
|
|
|
// First suppose that the id has been passed. |
31
|
|
|
if (NodeType::load($type)) { |
32
|
|
|
return $type; |
33
|
|
|
} |
34
|
|
|
$storage = \Drupal::entityTypeManager()->getStorage('node_type'); |
35
|
|
|
$result = $storage->loadByProperties(['name' => $type]); |
36
|
|
|
assert($result, isNotEmpty()); |
37
|
|
|
return key($result); |
38
|
|
|
} |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* {@inheritdoc} |
42
|
|
|
*/ |
43
|
|
View Code Duplication |
public function convertLabelToTermTypeId($type) { |
|
|
|
|
44
|
|
|
// First suppose that the id has been passed. |
45
|
|
|
if (Vocabulary::load($type)) { |
46
|
|
|
return $type; |
47
|
|
|
} |
48
|
|
|
$storage = \Drupal::entityTypeManager()->getStorage('taxonomy_vocabulary'); |
49
|
|
|
$result = $storage->loadByProperties(['name' => $type]); |
50
|
|
|
assert($result, isNotEmpty()); |
51
|
|
|
return key($result); |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* {@inheritdoc} |
56
|
|
|
*/ |
57
|
|
View Code Duplication |
public function loadNodeByName($title) { |
|
|
|
|
58
|
|
|
$result = \Drupal::entityQuery('node') |
59
|
|
|
->condition('title', $title) |
60
|
|
|
->condition('status', NODE_PUBLISHED) |
61
|
|
|
->range(0, 1) |
62
|
|
|
->execute(); |
63
|
|
|
assert($result, isNotEmpty()); |
64
|
|
|
$nid = current($result); |
65
|
|
|
return Node::load($nid); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* {@inheritdoc} |
70
|
|
|
*/ |
71
|
|
|
public function getEntityIdByLabel($entity_type, $bundle, $label) { |
72
|
|
|
/** @var \Drupal\node\NodeStorage $storage */ |
73
|
|
|
$storage = \Drupal::entityTypeManager()->getStorage($entity_type); |
74
|
|
|
$bundle_key = $storage->getEntityType()->getKey('bundle'); |
75
|
|
|
$label_key = $storage->getEntityType()->getKey('label'); |
76
|
|
|
|
77
|
|
|
$query = \Drupal::entityQuery($entity_type); |
78
|
|
|
if ($bundle) { |
79
|
|
|
$query->condition($bundle_key, $bundle); |
80
|
|
|
} |
81
|
|
|
$query->condition($label_key, $label); |
82
|
|
|
$query->range(0, 1); |
83
|
|
|
|
84
|
|
|
$result = $query->execute(); |
85
|
|
|
assert($result, isNotEmpty(), __METHOD__ . ": No Entity {$entity_type} with name {$label} found."); |
86
|
|
|
return current($result); |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* {@inheritdoc} |
91
|
|
|
*/ |
92
|
|
|
public function loadUserByName($name) { |
93
|
|
|
$user = user_load_by_name($name); |
94
|
|
|
assert($user, isNotEqualTo(FALSE)); |
95
|
|
|
return $user; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* {@inheritdoc} |
100
|
|
|
*/ |
101
|
|
|
public function nodeAccess($op, $name, $node) { |
102
|
|
|
$account = $this->loadUserByName($name); |
103
|
|
|
return $node->access($op, $account); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* {@inheritdoc} |
108
|
|
|
*/ |
109
|
|
|
public function getNodeId($node) { |
110
|
|
|
return $node->id(); |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* {@inheritdoc} |
115
|
|
|
*/ |
116
|
|
View Code Duplication |
public function loadTaxonomyTermByName($type, $name) { |
|
|
|
|
117
|
|
|
$result = \Drupal::entityQuery('taxonomy_term') |
118
|
|
|
->condition('name', $name) |
119
|
|
|
->condition('vid', $type) |
120
|
|
|
->range(0, 1) |
121
|
|
|
->execute(); |
122
|
|
|
assert($result, isNotEmpty()); |
123
|
|
|
$id = current($result); |
124
|
|
|
return Term::load($id); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* {@inheritdoc} |
129
|
|
|
*/ |
130
|
|
|
public function getTaxonomyTermId($term) { |
131
|
|
|
return $term->id(); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* {@inheritdoc} |
136
|
|
|
*/ |
137
|
|
|
public function loadMenuItemByTitle($menu_name, $title) { |
138
|
|
|
$items = \Drupal::entityTypeManager()->getStorage('menu_link_content') |
139
|
|
|
->loadByProperties([ |
140
|
|
|
'menu_name' => $menu_name, |
141
|
|
|
'title' => $title, |
142
|
|
|
]); |
143
|
|
|
if (!empty($items)) { |
144
|
|
|
return array_shift($items); |
145
|
|
|
} |
146
|
|
|
else { |
147
|
|
|
return NULL; |
148
|
|
|
} |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
/** |
152
|
|
|
* {@inheritdoc} |
153
|
|
|
*/ |
154
|
|
|
public function createMenuStructure($menu_name, $menu_items) { |
155
|
|
|
if (!Menu::load($menu_name)) { |
156
|
|
|
throw new \InvalidArgumentException("Menu '{$menu_name}' not found."); |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
$weight = 0; |
160
|
|
|
$menu_links = []; |
161
|
|
|
foreach ($menu_items as $menu_item) { |
162
|
|
|
$values = [ |
163
|
|
|
'title' => $menu_item['title'], |
164
|
|
|
'link' => ['uri' => $menu_item['uri']], |
165
|
|
|
'menu_name' => $menu_name, |
166
|
|
|
'weight' => $weight++, |
167
|
|
|
]; |
168
|
|
|
|
169
|
|
|
// Assign parent item. |
170
|
|
|
if ($menu_item['parent']) { |
171
|
|
|
$values['parent'] = $menu_item['parent']; |
172
|
|
|
$parent = $this->loadMenuItemByTitle($menu_name, $menu_item['parent']); |
173
|
|
|
if ($parent) { |
174
|
|
|
$values['parent'] = $parent->getPluginId(); |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
// Create menu link. |
179
|
|
|
$menu_link = MenuLinkContent::create($values); |
180
|
|
|
$menu_link->save(); |
181
|
|
|
$menu_links[] = $menu_link; |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
return $menu_links; |
|
|
|
|
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
/** |
188
|
|
|
* {@inheritdoc} |
189
|
|
|
*/ |
190
|
|
|
public function clearMenuCache() { |
191
|
|
|
\Drupal::cache('menu')->invalidateAll(); |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* {@inheritdoc} |
196
|
|
|
*/ |
197
|
|
|
public function invalidateCacheTags(array $tags) { |
198
|
|
|
Cache::invalidateTags($tags); |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* Create an entity. |
203
|
|
|
* |
204
|
|
|
* @param string $entity_type |
205
|
|
|
* Entity type. |
206
|
|
|
* @param array $values |
207
|
|
|
* The Values to create the entity with. |
208
|
|
|
* @param bool $save |
209
|
|
|
* Indicate whether to directly save the entity or not. |
210
|
|
|
* |
211
|
|
|
* @return EntityInterface |
212
|
|
|
* Entity object. |
213
|
|
|
*/ |
214
|
|
|
public function entityCreate($entity_type, $values, $save = TRUE) { |
215
|
|
|
if (!is_array($values)) { |
216
|
|
|
// Cast an object to array to be compatible with nodeCreate(). |
217
|
|
|
$values = (array) $values; |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
$entity = $this->getStubEntity($entity_type, $values); |
221
|
|
|
|
222
|
|
|
foreach ($values as $name => $value) { |
223
|
|
|
$definition = $this->getFieldDefinition($entity->getEntityTypeId(), $name); |
224
|
|
|
$settings = $definition->getSettings(); |
225
|
|
|
switch ($definition->getType()) { |
226
|
|
|
case 'entity_reference': |
227
|
|
|
if (in_array($settings['target_type'], ['node', 'taxonomy_term'])) { |
228
|
|
|
// @todo: only supports single values for the moment. |
229
|
|
|
$id = $this->getEntityIdByLabel($settings['target_type'], NULL, $value); |
230
|
|
|
$entity->{$name}->setValue($id); |
231
|
|
|
} |
232
|
|
|
break; |
233
|
|
|
|
234
|
|
|
case 'entity_reference_revisions': |
235
|
|
|
$entities = []; |
236
|
|
|
foreach ($value as $target_values) { |
237
|
|
|
assert($target_values, hasKey('type'), __METHOD__ . ": Required fields 'type' not found."); |
238
|
|
|
$entities[] = $this->entityCreate($settings['target_type'], $target_values, FALSE); |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
$entity->{$name}->setValue($entities); |
242
|
|
|
break; |
243
|
|
|
|
244
|
|
|
case 'image': |
245
|
|
|
$entity->{$name}->setValue(['target_id' => $this->saveFile($value)->id()]); |
246
|
|
|
break; |
247
|
|
|
} |
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
if ($save) { |
251
|
|
|
$entity->save(); |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
return $entity; |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
/** |
258
|
|
|
* {@inheritdoc} |
259
|
|
|
*/ |
260
|
|
|
public function entityLoad($entity_type, $entity_id) { |
261
|
|
|
return \Drupal::entityTypeManager()->getStorage($entity_type)->load($entity_id); |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
/** |
265
|
|
|
* {@inheritdoc} |
266
|
|
|
*/ |
267
|
|
|
public function entityDelete($entity) { |
268
|
|
|
$entity->delete(); |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
/** |
272
|
|
|
* {@inheritdoc} |
273
|
|
|
*/ |
274
|
|
|
public function entityAddTranslation($entity, $language, array $values) { |
275
|
|
|
/** @var ContentEntityInterface $translation */ |
276
|
|
|
$translation = $this->getStubEntity($entity->getEntityTypeId(), $values); |
277
|
|
|
|
278
|
|
|
foreach ($values as $name => $value) { |
279
|
|
|
$definition = $this->getFieldDefinition($translation->getEntityTypeId(), $name); |
280
|
|
|
$settings = $definition->getSettings(); |
281
|
|
|
$source_values = $entity->get($name)->getValue(); |
282
|
|
|
switch ($definition->getType()) { |
283
|
|
|
case 'entity_reference': |
284
|
|
|
if (in_array($settings['target_type'], ['node', 'taxonomy_term'])) { |
285
|
|
|
// @todo: only supports single values for the moment. |
286
|
|
|
$translation->{$name}->setValue($source_values); |
287
|
|
|
} |
288
|
|
|
break; |
289
|
|
|
|
290
|
|
|
case 'entity_reference_revisions': |
|
|
|
|
291
|
|
|
|
292
|
|
|
// When reference field is translatable then we will need to create |
293
|
|
|
// new entities and reference them. |
294
|
|
|
// @link https://www.drupal.org/node/2461695 |
295
|
|
|
if ($definition->isTranslatable()) { |
296
|
|
|
$target_values = []; |
297
|
|
|
foreach ($source_values as $key => $item) { |
298
|
|
|
$_entity = $this->entityCreate($settings['target_type'], $value[$key]); |
299
|
|
|
$target_values[] = [ |
300
|
|
|
'target_id' => $_entity->id(), |
301
|
|
|
'target_revision_id' => $_entity->getRevisionId(), |
302
|
|
|
]; |
303
|
|
|
} |
304
|
|
|
$translation->{$name}->setValue($target_values); |
305
|
|
|
} |
306
|
|
|
else { |
307
|
|
|
// Recurse over the referenced entities. |
308
|
|
|
$source = $this->entityLoad($settings['target_type'], $item['target_id']); |
|
|
|
|
309
|
|
|
$this->entityAddTranslation($source, $language, $value[$key]); |
|
|
|
|
310
|
|
|
} |
311
|
|
|
break; |
312
|
|
|
} |
313
|
|
|
} |
314
|
|
|
|
315
|
|
|
// Add the translation to the entity. |
316
|
|
|
$translation = $entity->addTranslation($language, $translation->toArray()); |
317
|
|
|
|
318
|
|
|
$translation->save(); |
319
|
|
|
|
320
|
|
|
return $translation; |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
/** |
324
|
|
|
* Get field definition. |
325
|
|
|
* |
326
|
|
|
* @param string $entity_type |
327
|
|
|
* Entity type machine name. |
328
|
|
|
* @param string $field_name |
329
|
|
|
* Field machine name. |
330
|
|
|
* |
331
|
|
|
* @return \Drupal\Core\Field\FieldStorageDefinitionInterface |
332
|
|
|
* Field definition. |
333
|
|
|
*/ |
334
|
|
|
protected function getFieldDefinition($entity_type, $field_name) { |
335
|
|
|
$definitions = \Drupal::service('entity_field.manager')->getFieldStorageDefinitions($entity_type); |
336
|
|
|
assert($definitions, hasKey($field_name), __METHOD__ . ": Field '{$field_name}' not found for entity type '{$entity_type}'."); |
337
|
|
|
return $definitions[$field_name]; |
338
|
|
|
} |
339
|
|
|
|
340
|
|
|
/** |
341
|
|
|
* Get stub entity. |
342
|
|
|
* |
343
|
|
|
* @param string $entity_type |
344
|
|
|
* Entity type. |
345
|
|
|
* @param array $values |
346
|
|
|
* Entity values. |
347
|
|
|
* |
348
|
|
|
* @return \Drupal\Core\Entity\EntityInterface |
349
|
|
|
* Entity object. |
350
|
|
|
*/ |
351
|
|
|
protected function getStubEntity($entity_type, array $values) { |
352
|
|
|
return \Drupal::entityTypeManager()->getStorage($entity_type)->create($values); |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
/** |
356
|
|
|
* Save a file and return its id. |
357
|
|
|
* |
358
|
|
|
* @param string $source |
359
|
|
|
* Source path relative to Drupal installation root. |
360
|
|
|
* |
361
|
|
|
* @return \Drupal\Core\Entity\EntityInterface |
362
|
|
|
* Saved file object. |
363
|
|
|
*/ |
364
|
|
|
protected function saveFile($source) { |
365
|
|
|
$name = basename($source); |
366
|
|
|
$path = realpath(DRUPAL_ROOT . '/'. $source); |
367
|
|
|
$uri = file_unmanaged_copy($path, 'public://' . $name, FILE_EXISTS_REPLACE); |
368
|
|
|
$file = File::create(['uri' => $uri]); |
369
|
|
|
$file->save(); |
370
|
|
|
return $file; |
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
} |
374
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.