1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* @file |
5
|
|
|
* Contains \Drupal\entity_browser\Plugin\Field\FieldWidget\EntityReference. |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace Drupal\entity_browser\Plugin\Field\FieldWidget; |
9
|
|
|
|
10
|
|
|
use Drupal\Component\Utility\Html; |
11
|
|
|
use Drupal\Component\Utility\NestedArray; |
12
|
|
|
use Drupal\Core\Entity\ContentEntityInterface; |
13
|
|
|
use Drupal\Core\Entity\EntityManagerInterface; |
14
|
|
|
use Drupal\Core\Field\FieldDefinitionInterface; |
15
|
|
|
use Drupal\Core\Field\FieldItemListInterface; |
16
|
|
|
use Drupal\Core\Field\FieldStorageDefinitionInterface; |
17
|
|
|
use Drupal\Core\Field\WidgetBase; |
18
|
|
|
use Drupal\Core\Form\FormStateInterface; |
19
|
|
|
use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface; |
20
|
|
|
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; |
21
|
|
|
use Drupal\Core\Url; |
22
|
|
|
use Drupal\entity_browser\Events\Events; |
23
|
|
|
use Drupal\entity_browser\Events\RegisterJSCallbacks; |
24
|
|
|
use Drupal\entity_browser\FieldWidgetDisplayManager; |
25
|
|
|
use Symfony\Component\DependencyInjection\ContainerInterface; |
26
|
|
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Plugin implementation of the 'entity_reference' widget for entity browser. |
30
|
|
|
|
31
|
|
|
* @FieldWidget( |
32
|
|
|
* id = "entity_browser_entity_reference", |
33
|
|
|
* label = @Translation("Entity browser"), |
34
|
|
|
* description = @Translation("Uses entity browser to select entities."), |
35
|
|
|
* multiple_values = TRUE, |
36
|
|
|
* field_types = { |
37
|
|
|
* "entity_reference" |
38
|
|
|
* } |
39
|
|
|
* ) |
40
|
|
|
*/ |
41
|
|
|
class EntityReference extends WidgetBase implements ContainerFactoryPluginInterface { |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Entity manager service |
45
|
|
|
* |
46
|
|
|
* @var \Drupal\Core\Entity\EntityManagerInterface |
47
|
|
|
*/ |
48
|
|
|
protected $entityManager; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Field widget display plugin manager. |
52
|
|
|
* |
53
|
|
|
* @var \Drupal\entity_browser\FieldWidgetDisplayManager |
54
|
|
|
*/ |
55
|
|
|
protected $fieldDisplayManager; |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface |
59
|
|
|
*/ |
60
|
|
|
protected $keyValue; |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* The depth of the delete button. |
64
|
|
|
* |
65
|
|
|
* This property exists so it can be changed if subclasses |
66
|
|
|
* |
67
|
|
|
* @var int |
68
|
|
|
*/ |
69
|
|
|
protected static $deleteDepth = 4; |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* Constructs widget plugin. |
73
|
|
|
* |
74
|
|
|
* @param string $plugin_id |
75
|
|
|
* The plugin_id for the plugin instance. |
76
|
|
|
* @param mixed $plugin_definition |
77
|
|
|
* The plugin implementation definition. |
78
|
|
|
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition |
79
|
|
|
* The definition of the field to which the widget is associated. |
80
|
|
|
* @param array $settings |
81
|
|
|
* The widget settings. |
82
|
|
|
* @param array $third_party_settings |
83
|
|
|
* Any third party settings. |
84
|
|
|
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager |
85
|
|
|
* Entity manager service. |
86
|
|
|
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher |
87
|
|
|
* Event dispatcher. |
88
|
|
|
* @param \Drupal\entity_browser\FieldWidgetDisplayManager $field_display_manager |
89
|
|
|
* Field widget display plugin manager. |
90
|
|
|
* @param \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface $key_value |
91
|
|
|
* The key value store. |
92
|
|
|
*/ |
93
|
|
View Code Duplication |
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityManagerInterface $entity_manager, EventDispatcherInterface $event_dispatcher, FieldWidgetDisplayManager $field_display_manager, KeyValueStoreExpirableInterface $key_value) { |
|
|
|
|
94
|
|
|
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings); |
95
|
|
|
$this->entityManager = $entity_manager; |
96
|
|
|
$this->fieldDisplayManager = $field_display_manager; |
97
|
|
|
$this->keyValue = $key_value; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* {@inheritdoc} |
102
|
|
|
*/ |
103
|
|
|
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { |
104
|
|
|
return new static( |
105
|
|
|
$plugin_id, |
106
|
|
|
$plugin_definition, |
107
|
|
|
$configuration['field_definition'], |
108
|
|
|
$configuration['settings'], |
109
|
|
|
$configuration['third_party_settings'], |
110
|
|
|
$container->get('entity.manager'), |
111
|
|
|
$container->get('event_dispatcher'), |
112
|
|
|
$container->get('plugin.manager.entity_browser.field_widget_display'), |
113
|
|
|
$container->get('keyvalue.expirable')->get('entity_browser') |
114
|
|
|
); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* {@inheritdoc} |
119
|
|
|
*/ |
120
|
|
|
public static function defaultSettings() { |
121
|
|
|
return array( |
122
|
|
|
'entity_browser' => NULL, |
123
|
|
|
'open' => FALSE, |
124
|
|
|
'field_widget_display' => NULL, |
125
|
|
|
'field_widget_edit' => TRUE, |
126
|
|
|
'field_widget_remove' => TRUE, |
127
|
|
|
'field_widget_display_settings' => [], |
128
|
|
|
) + parent::defaultSettings(); |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
/** |
132
|
|
|
* {@inheritdoc} |
133
|
|
|
*/ |
134
|
|
|
public function settingsForm(array $form, FormStateInterface $form_state) { |
135
|
|
|
$element = parent::settingsForm($form, $form_state); |
136
|
|
|
|
137
|
|
|
$browsers = []; |
138
|
|
|
/** @var \Drupal\entity_browser\EntityBrowserInterface $browser */ |
139
|
|
|
foreach ($this->entityManager->getStorage('entity_browser')->loadMultiple() as $browser) { |
140
|
|
|
$browsers[$browser->id()] = $browser->label(); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
$element['entity_browser'] = [ |
144
|
|
|
'#title' => t('Entity browser'), |
145
|
|
|
'#type' => 'select', |
146
|
|
|
'#default_value' => $this->getSetting('entity_browser'), |
147
|
|
|
'#options' => $browsers, |
148
|
|
|
]; |
149
|
|
|
|
150
|
|
|
$target_type = $this->fieldDefinition->getFieldStorageDefinition()->getSetting('target_type'); |
151
|
|
|
$entity_type = \Drupal::entityTypeManager()->getStorage($target_type)->getEntityType(); |
152
|
|
|
|
153
|
|
|
$displays = []; |
154
|
|
|
foreach ($this->fieldDisplayManager->getDefinitions() as $id => $definition) { |
155
|
|
|
if ($this->fieldDisplayManager->createInstance($id)->isApplicable($entity_type)) { |
156
|
|
|
$displays[$id] = $definition['label']; |
157
|
|
|
} |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
$id = Html::getUniqueId('field-' . $this->fieldDefinition->getName() . '-display-settings-wrapper'); |
161
|
|
|
$element['field_widget_display'] = [ |
162
|
|
|
'#title' => t('Entity display plugin'), |
163
|
|
|
'#type' => 'select', |
164
|
|
|
'#default_value' => $this->getSetting('field_widget_display'), |
165
|
|
|
'#options' => $displays, |
166
|
|
|
'#ajax' => [ |
167
|
|
|
'callback' => array($this, 'updateSettingsAjax'), |
168
|
|
|
'wrapper' => $id, |
169
|
|
|
], |
170
|
|
|
]; |
171
|
|
|
|
172
|
|
|
$element['field_widget_edit'] = [ |
173
|
|
|
'#title' => t('Display Edit button'), |
174
|
|
|
'#type' => 'checkbox', |
175
|
|
|
'#default_value' => $this->getSetting('field_widget_edit') |
176
|
|
|
]; |
177
|
|
|
|
178
|
|
|
$element['field_widget_remove'] = [ |
179
|
|
|
'#title' => t('Display Remove button'), |
180
|
|
|
'#type' => 'checkbox', |
181
|
|
|
'#default_value' => $this->getSetting('field_widget_remove') |
182
|
|
|
]; |
183
|
|
|
|
184
|
|
|
$element['open'] = [ |
185
|
|
|
'#title' => t('Show widget details as open by default'), |
186
|
|
|
'#type' => 'checkbox', |
187
|
|
|
'#default_value' => $this->getSetting('open') |
188
|
|
|
]; |
189
|
|
|
|
190
|
|
|
$element['field_widget_display_settings'] = [ |
191
|
|
|
'#type' => 'fieldset', |
192
|
|
|
'#title' => t('Entity display plugin configuration'), |
193
|
|
|
'#tree' => TRUE, |
194
|
|
|
'#prefix' => '<div id="' . $id . '">', |
195
|
|
|
'#suffix' => '</div>', |
196
|
|
|
]; |
197
|
|
|
|
198
|
|
|
if ($this->getSetting('field_widget_display')) { |
199
|
|
|
$element['field_widget_display_settings'] += $this->fieldDisplayManager |
200
|
|
|
->createInstance( |
201
|
|
|
$form_state->getValue( |
202
|
|
|
['fields', $this->fieldDefinition->getName(), 'settings_edit_form', 'settings', 'field_widget_display'], |
203
|
|
|
$this->getSetting('field_widget_display') |
204
|
|
|
), |
205
|
|
|
$form_state->getValue( |
206
|
|
|
['fields', $this->fieldDefinition->getName(), 'settings_edit_form', 'settings', 'field_widget_display_settings'], |
207
|
|
|
$this->getSetting('field_widget_display_settings') |
208
|
|
|
) + ['entity_type' => $this->fieldDefinition->getFieldStorageDefinition()->getSetting('target_type')] |
209
|
|
|
) |
210
|
|
|
->settingsForm($form, $form_state); |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
return $element; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
/** |
217
|
|
|
* Ajax callback that updates field widget display settings fieldset. |
218
|
|
|
*/ |
219
|
|
|
public function updateSettingsAjax(array $form, FormStateInterface $form_state) { |
220
|
|
|
return $form['fields'][$this->fieldDefinition->getName()]['plugin']['settings_edit_form']['settings']['field_widget_display_settings']; |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* {@inheritdoc} |
225
|
|
|
*/ |
226
|
|
|
public function settingsSummary() { |
227
|
|
|
$summary = []; |
228
|
|
|
$entity_browser_id = $this->getSetting('entity_browser'); |
229
|
|
|
$field_widget_display = $this->getSetting('field_widget_display'); |
230
|
|
|
|
231
|
|
|
if (empty($entity_browser_id)) { |
232
|
|
|
return [t('No entity browser selected.')]; |
233
|
|
|
} |
234
|
|
|
else { |
235
|
|
|
$browser = $this->entityManager->getStorage('entity_browser') |
236
|
|
|
->load($entity_browser_id); |
237
|
|
|
$summary[] = t('Entity browser: @browser', ['@browser' => $browser->label()]); |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
if (!empty($field_widget_display)) { |
241
|
|
|
$plugin = $this->fieldDisplayManager->getDefinition($field_widget_display); |
242
|
|
|
$summary[] = t('Entity display: @name', ['@name' => $plugin['label']]); |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
return $summary; |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
/** |
249
|
|
|
* {@inheritdoc} |
250
|
|
|
*/ |
251
|
|
|
function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { |
|
|
|
|
252
|
|
|
$entity_type = $this->fieldDefinition->getFieldStorageDefinition()->getSetting('target_type'); |
253
|
|
|
$entity_storage = $this->entityManager->getStorage($entity_type); |
254
|
|
|
|
255
|
|
|
$ids = []; |
256
|
|
|
$entities = []; |
257
|
|
|
|
258
|
|
|
// Determine if we're submitting and if submit came from this widget. |
259
|
|
|
$is_relevant_submit = FALSE; |
260
|
|
|
if (($trigger = $form_state->getTriggeringElement())) { |
261
|
|
|
// Can be triggered by hidden target_id element or "Remove" button. |
262
|
|
|
if (end($trigger['#parents']) === 'target_id' || (end($trigger['#parents']) === 'remove_button')) { |
263
|
|
|
$is_relevant_submit = TRUE; |
264
|
|
|
|
265
|
|
|
// In case there are more instances of this widget on the same page we |
266
|
|
|
// need to check if submit came from this instance. |
267
|
|
|
$field_name_key = end($trigger['#parents']) === 'target_id' ? 2 : static::$deleteDepth + 1; |
268
|
|
|
$field_name_key = sizeof($trigger['#parents']) - $field_name_key; |
269
|
|
|
$is_relevant_submit &= ($trigger['#parents'][$field_name_key] === $this->fieldDefinition->getName()); |
270
|
|
|
} |
271
|
|
|
}; |
272
|
|
|
|
273
|
|
|
if ($is_relevant_submit) { |
274
|
|
|
// Submit was triggered by hidden "target_id" element when entities were |
275
|
|
|
// added via entity browser. |
276
|
|
View Code Duplication |
if (!empty($trigger['#ajax']['event']) && $trigger['#ajax']['event'] == 'entity_browser_value_updated') { |
|
|
|
|
277
|
|
|
$parents = $trigger['#parents']; |
278
|
|
|
} |
279
|
|
|
// Submit was triggered by one of the "Remove" buttons. We need to walk |
280
|
|
|
// few levels up to read value of "target_id" element. |
281
|
|
|
elseif ($trigger['#type'] == 'submit' && strpos($trigger['#name'], $this->fieldDefinition->getName() . '_remove_') === 0) { |
282
|
|
|
$parents = array_merge(array_slice($trigger['#parents'], 0, -static::$deleteDepth), ['target_id']); |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
if (isset($parents) && $value = $form_state->getValue($parents)) { |
286
|
|
|
$ids = explode(' ', $value); |
287
|
|
|
$entities = $entity_storage->loadMultiple($ids); |
288
|
|
|
} |
289
|
|
|
} |
290
|
|
|
// We are loading for for the first time so we need to load any existing |
291
|
|
|
// values that might already exist on the entity. Also, remove any leftover |
292
|
|
|
// data from removed entity references. |
293
|
|
|
else { |
294
|
|
|
foreach ($items as $item) { |
295
|
|
|
$entity = $entity_storage->load($item->target_id); |
296
|
|
|
if (!empty($entity)) { |
297
|
|
|
$entities[$item->target_id] = $entity; |
298
|
|
|
} |
299
|
|
|
} |
300
|
|
|
$ids = array_keys($entities); |
301
|
|
|
} |
302
|
|
|
$ids = array_filter($ids); |
303
|
|
|
|
304
|
|
|
$hidden_id = Html::getUniqueId('edit-' . $this->fieldDefinition->getName() . '-target-id'); |
305
|
|
|
$details_id = Html::getUniqueId('edit-' . $this->fieldDefinition->getName()); |
306
|
|
|
/** @var \Drupal\entity_browser\EntityBrowserInterface $entity_browser */ |
307
|
|
|
$entity_browser = $this->entityManager->getStorage('entity_browser')->load($this->getSetting('entity_browser')); |
308
|
|
|
|
309
|
|
|
$element += [ |
310
|
|
|
'#id' => $details_id, |
311
|
|
|
'#type' => 'details', |
312
|
|
|
'#open' => !empty($ids) || $this->getSetting('open'), |
313
|
|
|
'target_id' => [ |
314
|
|
|
'#type' => 'hidden', |
315
|
|
|
'#id' => $hidden_id, |
316
|
|
|
// We need to repeat ID here as it is otherwise skipped when rendering. |
317
|
|
|
'#attributes' => ['id' => $hidden_id], |
318
|
|
|
'#default_value' => $ids, |
319
|
|
|
// #ajax is officially not supported for hidden elements but if we |
320
|
|
|
// specify event manually it works. |
321
|
|
|
'#ajax' => [ |
322
|
|
|
'callback' => [get_class($this), 'updateWidgetCallback'], |
323
|
|
|
'wrapper' => $details_id, |
324
|
|
|
'event' => 'entity_browser_value_updated', |
325
|
|
|
], |
326
|
|
|
], |
327
|
|
|
]; |
328
|
|
|
|
329
|
|
|
|
330
|
|
|
// Gather and set validators. |
331
|
|
|
// @todo Is there a better place to do that? |
332
|
|
|
$cardinality = $this->fieldDefinition->getFieldStorageDefinition()->getCardinality(); |
333
|
|
|
$validators = $this->prepareValidators(['cardinality' => ['min' => $cardinality]]); |
334
|
|
|
|
335
|
|
|
if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED || count($ids) < $cardinality) { |
336
|
|
|
$element['entity_browser'] = $entity_browser->getDisplay()->displayEntityBrowser($validators); |
337
|
|
|
$element['#attached']['library'][] = 'entity_browser/entity_reference'; |
338
|
|
|
$element['#attached']['drupalSettings']['entity_browser'] = [ |
339
|
|
|
$entity_browser->getDisplay()->getUuid() => [ |
340
|
|
|
'cardinality' => $this->fieldDefinition->getFieldStorageDefinition()->getCardinality(), |
341
|
|
|
'selector' => '#'.$element['target_id']['#attributes']['id'], |
342
|
|
|
] |
343
|
|
|
]; |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
$field_parents = $element['#field_parents']; |
347
|
|
|
|
348
|
|
|
$element['current'] = $this->displayCurrentSelection($details_id, $field_parents, $entities); |
349
|
|
|
|
350
|
|
|
return $element; |
351
|
|
|
} |
352
|
|
|
|
353
|
|
|
/** |
354
|
|
|
* {@inheritdoc} |
355
|
|
|
*/ |
356
|
|
|
public function massageFormValues(array $values, array $form, FormStateInterface $form_state) { |
357
|
|
|
$ids = empty($values['target_id']) ? [] : explode(' ', trim($values['target_id'])); |
358
|
|
|
$return = []; |
359
|
|
|
foreach ($ids as $id) { |
360
|
|
|
$return[]['target_id'] = $id; |
361
|
|
|
} |
362
|
|
|
|
363
|
|
|
return $return; |
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
/** |
367
|
|
|
* AJAX form callback. |
368
|
|
|
*/ |
369
|
|
|
public static function updateWidgetCallback(array &$form, FormStateInterface $form_state) { |
370
|
|
|
$trigger = $form_state->getTriggeringElement(); |
371
|
|
|
// AJAX requests can be triggered by hidden "target_id" element when entities |
372
|
|
|
// are added or by one of the "Remove" buttons. Depending on that we need to |
373
|
|
|
// figure out where root of the widget is in the form structure and use this |
374
|
|
|
// information to return correct part of the form. |
375
|
|
View Code Duplication |
if (!empty($trigger['#ajax']['event']) && $trigger['#ajax']['event'] == 'entity_browser_value_updated') { |
|
|
|
|
376
|
|
|
$parents = array_slice($trigger['#array_parents'], 0, -1); |
377
|
|
|
} |
378
|
|
|
elseif ($trigger['#type'] == 'submit' && strpos($trigger['#name'], '_remove_')) { |
379
|
|
|
$parents = array_slice($trigger['#array_parents'], 0, -static::$deleteDepth); |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
return NestedArray::getValue($form, $parents); |
|
|
|
|
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* Submit callback for remove buttons. |
387
|
|
|
*/ |
388
|
|
|
public static function removeItemSubmit(&$form, FormStateInterface $form_state) { |
389
|
|
|
$triggering_element = $form_state->getTriggeringElement(); |
390
|
|
|
if (!empty($triggering_element['#attributes']['data-entity-id'])) { |
391
|
|
|
$id = $triggering_element['#attributes']['data-entity-id']; |
392
|
|
|
$parents = array_slice($triggering_element['#parents'], 0, -static::$deleteDepth); |
393
|
|
|
$array_parents = array_slice($triggering_element['#array_parents'], 0, -static::$deleteDepth); |
394
|
|
|
|
395
|
|
|
// Find and remove correct entity. |
396
|
|
|
$values = explode(' ', $form_state->getValue(array_merge($parents, ['target_id']))); |
397
|
|
|
$values = array_filter( |
398
|
|
|
$values, |
399
|
|
|
function($item) use ($id) { return $item != $id; } |
400
|
|
|
); |
401
|
|
|
$values = implode(' ', $values); |
402
|
|
|
|
403
|
|
|
// Set new value for this widget. |
404
|
|
|
$target_id_element = &NestedArray::getValue($form, array_merge($array_parents, ['target_id'])); |
405
|
|
|
$form_state->setValueForElement($target_id_element, $values); |
406
|
|
|
NestedArray::setValue($form_state->getUserInput(), $target_id_element['#parents'], $values); |
407
|
|
|
|
408
|
|
|
// Rebuild form. |
409
|
|
|
$form_state->setRebuild(); |
410
|
|
|
} |
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
/** |
414
|
|
|
* Builds the render array for displaying the current results. |
415
|
|
|
* |
416
|
|
|
* @param string $details_id |
417
|
|
|
* The ID for the details element. |
418
|
|
|
* @param string[] $field_parents |
419
|
|
|
* Field parents. |
420
|
|
|
* @param \Drupal\Core\Entity\ContentEntityInterface[] $entities |
421
|
|
|
* |
422
|
|
|
* @return array |
423
|
|
|
* The render array for the current selection. |
424
|
|
|
*/ |
425
|
|
|
protected function displayCurrentSelection($details_id, $field_parents, $entities) { |
426
|
|
|
|
427
|
|
|
$field_widget_display = $this->fieldDisplayManager->createInstance( |
428
|
|
|
$this->getSetting('field_widget_display'), |
429
|
|
|
$this->getSetting('field_widget_display_settings') + ['entity_type' => $this->fieldDefinition->getFieldStorageDefinition()->getSetting('target_type')] |
430
|
|
|
); |
431
|
|
|
|
432
|
|
|
return [ |
433
|
|
|
'#theme_wrappers' => ['container'], |
434
|
|
|
'#attributes' => ['class' => ['entities-list']], |
435
|
|
|
'items' => array_map( |
436
|
|
|
function (ContentEntityInterface $entity) use ($field_widget_display, $details_id, $field_parents) { |
437
|
|
|
$display = $field_widget_display->view($entity); |
438
|
|
|
if (is_string($display)) { |
439
|
|
|
$display = ['#markup' => $display]; |
440
|
|
|
} |
441
|
|
|
return [ |
442
|
|
|
'#theme_wrappers' => ['container'], |
443
|
|
|
'#attributes' => [ |
444
|
|
|
'class' => ['item-container', Html::getClass($field_widget_display->getPluginId())], |
445
|
|
|
'data-entity-id' => $entity->id() |
446
|
|
|
], |
447
|
|
|
'display' => $display, |
448
|
|
|
'remove_button' => [ |
449
|
|
|
'#type' => 'submit', |
450
|
|
|
'#value' => $this->t('Remove'), |
451
|
|
|
'#ajax' => [ |
452
|
|
|
'callback' => [get_class($this), 'updateWidgetCallback'], |
453
|
|
|
'wrapper' => $details_id, |
454
|
|
|
], |
455
|
|
|
'#submit' => [[get_class($this), 'removeItemSubmit']], |
456
|
|
|
'#name' => $this->fieldDefinition->getName() . '_remove_' . $entity->id(), |
457
|
|
|
'#limit_validation_errors' => [array_merge($field_parents, [$this->fieldDefinition->getName()])], |
458
|
|
|
'#attributes' => ['data-entity-id' => $entity->id()], |
459
|
|
|
'#access' => (bool) $this->getSetting('field_widget_remove') |
460
|
|
|
], |
461
|
|
|
'edit_button' => [ |
462
|
|
|
'#type' => 'submit', |
463
|
|
|
'#value' => $this->t('Edit'), |
464
|
|
|
'#ajax' => [ |
465
|
|
|
'url' => Url::fromRoute( |
466
|
|
|
'entity_browser.edit_form', [ |
467
|
|
|
'entity_type' => $entity->getEntityTypeId(), |
468
|
|
|
'entity' => $entity->id() |
469
|
|
|
] |
470
|
|
|
) |
471
|
|
|
], |
472
|
|
|
'#access' => (bool) $this->getSetting('field_widget_edit') |
473
|
|
|
] |
474
|
|
|
]; |
475
|
|
|
}, |
476
|
|
|
$entities |
477
|
|
|
), |
478
|
|
|
]; |
479
|
|
|
} |
480
|
|
|
|
481
|
|
|
/** |
482
|
|
|
* Prepare validators. |
483
|
|
|
* |
484
|
|
|
* Saves Entity Browser Widget validators in key/value storage if an identical |
485
|
|
|
* set of constraints is not already stored there. |
486
|
|
|
* |
487
|
|
|
* @param array $validators |
488
|
|
|
* An array where keys are validator ids and values configurations for them. |
489
|
|
|
* |
490
|
|
|
* @return string |
491
|
|
|
* The hash generated from hashing the validators array. |
492
|
|
|
*/ |
493
|
|
|
public function prepareValidators(array $validators) { |
494
|
|
|
// Generate the hash that we use as key for the key/value. |
495
|
|
|
$hash = md5(serialize($validators)); |
496
|
|
|
|
497
|
|
|
if (!$this->keyValue->has($hash)) { |
498
|
|
|
$this->keyValue->set($hash, $validators); |
499
|
|
|
} |
500
|
|
|
|
501
|
|
|
return $hash; |
502
|
|
|
} |
503
|
|
|
|
504
|
|
|
/** |
505
|
|
|
* Get validators. |
506
|
|
|
* |
507
|
|
|
* @param \Drupal\entity_browser\string $hash |
508
|
|
|
* The hash generated from hashing the validators array. |
509
|
|
|
* |
510
|
|
|
* @return mixed |
511
|
|
|
* An array where keys are validator ids and values configurations for them |
512
|
|
|
* or empty array if no validators are stored. |
513
|
|
|
*/ |
514
|
|
|
public function getValidators($hash) { |
515
|
|
|
return $this->keyValue->get($hash, []); |
516
|
|
|
} |
517
|
|
|
} |
518
|
|
|
|
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.