1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Drupal\entity_browser\Plugin\EntityBrowser\SelectionDisplay; |
4
|
|
|
|
5
|
|
|
use Drupal\Core\Entity\EntityManagerInterface; |
6
|
|
|
use Drupal\Core\Form\FormStateInterface; |
7
|
|
|
use Drupal\entity_browser\FieldWidgetDisplayManager; |
8
|
|
|
use Drupal\entity_browser\SelectionDisplayBase; |
9
|
|
|
use Symfony\Component\DependencyInjection\ContainerInterface; |
10
|
|
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Show current selection and delivers selected entities. |
14
|
|
|
* |
15
|
|
|
* @EntityBrowserSelectionDisplay( |
16
|
|
|
* id = "multi_step_display", |
17
|
|
|
* label = @Translation("Multi step selection display"), |
18
|
|
|
* description = @Translation("Show current selection display and delivers selected entities.") |
19
|
|
|
* ) |
20
|
|
|
*/ |
21
|
|
|
class MultiStepDisplay extends SelectionDisplayBase { |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* Field widget display plugin manager. |
25
|
|
|
* |
26
|
|
|
* @var \Drupal\entity_browser\FieldWidgetDisplayManager |
27
|
|
|
*/ |
28
|
|
|
protected $fieldDisplayManager; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Constructs widget plugin. |
32
|
|
|
* |
33
|
|
|
* @param array $configuration |
34
|
|
|
* A configuration array containing information about the plugin instance. |
35
|
|
|
* @param string $plugin_id |
36
|
|
|
* The plugin_id for the plugin instance. |
37
|
|
|
* @param mixed $plugin_definition |
38
|
|
|
* The plugin implementation definition. |
39
|
|
|
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher |
40
|
|
|
* Event dispatcher service. |
41
|
|
|
* @param \Drupal\Core\Entity\EntityManagerInterface |
42
|
|
|
* Entity manager service. |
43
|
|
|
* @param \Drupal\entity_browser\FieldWidgetDisplayManager $field_display_manager |
44
|
|
|
* Field widget display plugin manager. |
45
|
|
|
*/ |
46
|
|
|
public function __construct(array $configuration, $plugin_id, $plugin_definition, EventDispatcherInterface $event_dispatcher, EntityManagerInterface $entity_manager, FieldWidgetDisplayManager $field_display_manager) { |
47
|
|
|
parent::__construct($configuration, $plugin_id, $plugin_definition, $event_dispatcher, $entity_manager); |
48
|
|
|
$this->fieldDisplayManager = $field_display_manager; |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* {@inheritdoc} |
53
|
|
|
*/ |
54
|
|
View Code Duplication |
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { |
|
|
|
|
55
|
|
|
return new static( |
56
|
|
|
$configuration, |
57
|
|
|
$plugin_id, |
58
|
|
|
$plugin_definition, |
59
|
|
|
$container->get('event_dispatcher'), |
60
|
|
|
$container->get('entity.manager'), |
61
|
|
|
$container->get('plugin.manager.entity_browser.field_widget_display') |
62
|
|
|
); |
63
|
|
|
} |
64
|
|
|
/** |
65
|
|
|
* {@inheritdoc} |
66
|
|
|
*/ |
67
|
|
|
public function defaultConfiguration() { |
68
|
|
|
return [ |
69
|
|
|
'entity_type' => 'node', |
70
|
|
|
'display' => 'label', |
71
|
|
|
'display_settings' => [], |
72
|
|
|
'select_text' => 'Use selected', |
73
|
|
|
] + parent::defaultConfiguration(); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* {@inheritdoc} |
78
|
|
|
*/ |
79
|
|
|
public function getForm(array &$original_form, FormStateInterface $form_state) { |
80
|
|
|
$selected_entities = $form_state->get(['entity_browser', 'selected_entities']); |
81
|
|
|
|
82
|
|
|
$form = []; |
83
|
|
|
$form['#attached']['library'][] = 'entity_browser/multi_step_display'; |
84
|
|
|
$form['selected'] = [ |
85
|
|
|
'#theme_wrappers' => ['container'], |
86
|
|
|
'#attributes' => ['class' => ['entities-list']], |
87
|
|
|
'#tree' => TRUE |
88
|
|
|
]; |
89
|
|
|
foreach ($selected_entities as $id => $entity) { |
90
|
|
|
$display_plugin = $this->fieldDisplayManager->createInstance( |
91
|
|
|
$this->configuration['display'], |
92
|
|
|
$this->configuration['display_settings'] + ['entity_type' => $this->configuration['entity_type']] |
93
|
|
|
); |
94
|
|
|
$display = $display_plugin->view($entity); |
95
|
|
|
if (is_string($display)) { |
96
|
|
|
$display = ['#markup' => $display]; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
$form['selected']['items_'. $entity->id()] = [ |
100
|
|
|
'#theme_wrappers' => ['container'], |
101
|
|
|
'#attributes' => [ |
102
|
|
|
'class' => ['item-container'], |
103
|
|
|
'data-entity-id' => $entity->id() |
104
|
|
|
], |
105
|
|
|
'display' => $display, |
106
|
|
|
'remove_button' => [ |
107
|
|
|
'#type' => 'submit', |
108
|
|
|
'#value' => $this->t('Remove'), |
109
|
|
|
'#submit' => [[get_class($this), 'removeItemSubmit']], |
110
|
|
|
'#name' => 'remove_' . $entity->id(), |
111
|
|
|
'#attributes' => [ |
112
|
|
|
'data-row-id' => $id, |
113
|
|
|
'data-remove-entity' => 'items_' . $entity->id(), |
114
|
|
|
] |
115
|
|
|
], |
116
|
|
|
'weight' => [ |
117
|
|
|
'#type' => 'hidden', |
118
|
|
|
'#default_value' => $id, |
119
|
|
|
'#attributes' => ['class' => ['weight']] |
120
|
|
|
] |
121
|
|
|
]; |
122
|
|
|
} |
123
|
|
|
$form['use_selected'] = [ |
124
|
|
|
'#type' => 'submit', |
125
|
|
|
'#value' => $this->t($this->configuration['select_text']), |
126
|
|
|
'#name' => 'use_selected', |
127
|
|
|
'#access' => empty($selected_entities) ? FALSE : TRUE, |
128
|
|
|
]; |
129
|
|
|
|
130
|
|
|
return $form; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* Submit callback for remove buttons. |
135
|
|
|
* |
136
|
|
|
* @param array $form |
137
|
|
|
* @param \Drupal\Core\Form\FormStateInterface $form_state |
138
|
|
|
*/ |
139
|
|
|
public static function removeItemSubmit(array &$form, FormStateInterface $form_state) { |
140
|
|
|
$triggering_element = $form_state->getTriggeringElement(); |
141
|
|
|
|
142
|
|
|
// Remove weight of entity being removed. |
143
|
|
|
$form_state->unsetValue(['selected', $triggering_element['#attributes']['data-remove-entity']]); |
144
|
|
|
|
145
|
|
|
// Remove entity itself. |
146
|
|
|
$selected_entities = &$form_state->get(['entity_browser', 'selected_entities']); |
147
|
|
|
unset($selected_entities[$triggering_element['#attributes']['data-row-id']]); |
148
|
|
|
|
149
|
|
|
static::saveNewOrder($form_state); |
150
|
|
|
$form_state->setRebuild(); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* {@inheritdoc} |
155
|
|
|
*/ |
156
|
|
|
public function submit(array &$form, FormStateInterface $form_state) { |
157
|
|
|
$this->saveNewOrder($form_state); |
158
|
|
|
if ($form_state->getTriggeringElement()['#name'] == 'use_selected') { |
159
|
|
|
$this->selectionDone($form_state); |
160
|
|
|
} |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* Saves new ordering of entities based on weight. |
165
|
|
|
* |
166
|
|
|
* @param FormStateInterface $form_state |
167
|
|
|
* Form state. |
168
|
|
|
*/ |
169
|
|
|
public static function saveNewOrder(FormStateInterface $form_state) { |
170
|
|
|
$selected = $form_state->getValue('selected'); |
171
|
|
|
if (!empty($selected)) { |
172
|
|
|
$weights = array_column($selected, 'weight'); |
173
|
|
|
$selected_entities = $form_state->get(['entity_browser', 'selected_entities']); |
174
|
|
|
|
175
|
|
|
// If we added new entities to the selection at this step we won't have |
176
|
|
|
// weights for them so we have to fake them. |
177
|
|
|
if (sizeof($weights) < sizeof($selected_entities)) { |
178
|
|
|
for ($new_weigth = (max($weights) + 1); $new_weigth < sizeof($selected_entities); $new_weigth++) { |
|
|
|
|
179
|
|
|
$weights[] = $new_weigth; |
180
|
|
|
} |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
$ordered = array_combine($weights, $selected_entities); |
184
|
|
|
ksort($ordered); |
185
|
|
|
$form_state->set(['entity_browser', 'selected_entities'], $ordered); |
186
|
|
|
} |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* {@inheritdoc} |
191
|
|
|
*/ |
192
|
|
|
public function buildConfigurationForm(array $form, FormStateInterface $form_state) { |
193
|
|
|
$default_entity_type = $form_state->getValue('entity_type', $this->configuration['entity_type']); |
194
|
|
|
$default_display = $form_state->getValue('display', $this->configuration['display']); |
195
|
|
|
$default_display_settings = $form_state->getValue('display_settings', $this->configuration['display_settings']); |
196
|
|
|
$default_display_settings += ['entity_type' => $default_entity_type]; |
197
|
|
|
|
198
|
|
|
$form['#prefix'] = '<div id="multi-step-form-wrapper">'; |
199
|
|
|
$form['#suffix'] = '</div>'; |
200
|
|
|
|
201
|
|
|
$entity_types = []; |
202
|
|
|
foreach ($this->entityManager->getDefinitions() as $entity_type_id => $entity_type) { |
203
|
|
|
/** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */ |
204
|
|
|
$entity_types[$entity_type_id] = $entity_type->getLabel(); |
205
|
|
|
} |
206
|
|
|
$form['entity_type'] = [ |
207
|
|
|
'#type' => 'select', |
208
|
|
|
'#title' => $this->t('Entity type'), |
209
|
|
|
'#description' => $this->t("Entity browser itself does not need information about entity type being selected. It can actually select entities of different type. However, some of the display plugins need to know which entity type they are operating with. Display plugins that do not need this info will ignore this configuration value."), |
210
|
|
|
'#default_value' => $default_entity_type, |
211
|
|
|
'#options' => $entity_types, |
212
|
|
|
'#ajax' => [ |
213
|
|
|
'callback' => [$this, 'updateSettingsAjax'], |
214
|
|
|
'wrapper' => 'multi-step-form-wrapper', |
215
|
|
|
], |
216
|
|
|
]; |
217
|
|
|
|
218
|
|
|
$displays = []; |
219
|
|
|
foreach ($this->fieldDisplayManager->getDefinitions() as $display_plugin_id => $definition) { |
220
|
|
|
$entity_type = $this->entityManager->getDefinition($default_entity_type); |
221
|
|
|
if ($this->fieldDisplayManager->createInstance($display_plugin_id)->isApplicable($entity_type)) { |
222
|
|
|
$displays[$display_plugin_id] = $definition['label']; |
223
|
|
|
} |
224
|
|
|
} |
225
|
|
|
$form['display'] = [ |
226
|
|
|
'#title' => t('Entity display plugin'), |
227
|
|
|
'#type' => 'select', |
228
|
|
|
'#default_value' => $default_display, |
229
|
|
|
'#options' => $displays, |
230
|
|
|
'#ajax' => [ |
231
|
|
|
'callback' => [$this, 'updateSettingsAjax'], |
232
|
|
|
'wrapper' => 'multi-step-form-wrapper', |
233
|
|
|
], |
234
|
|
|
]; |
235
|
|
|
|
236
|
|
|
$form['display_settings'] = [ |
237
|
|
|
'#type' => 'container', |
238
|
|
|
'#title' => t('Entity display plugin configuration'), |
239
|
|
|
'#tree' => TRUE, |
240
|
|
|
]; |
241
|
|
|
if ($default_display_settings) { |
|
|
|
|
242
|
|
|
$display_plugin = $this->fieldDisplayManager |
243
|
|
|
->createInstance($default_display, $default_display_settings); |
244
|
|
|
|
245
|
|
|
$form['display_settings'] += $display_plugin->settingsForm($form, $form_state); |
246
|
|
|
} |
247
|
|
|
$form['select_text'] = [ |
248
|
|
|
'#type' => 'textfield', |
249
|
|
|
'#title' => $this->t('Select button text'), |
250
|
|
|
'#default_value' => $this->configuration['select_text'], |
251
|
|
|
'#description' => $this->t('Text to display on the entity browser select button.'), |
252
|
|
|
]; |
253
|
|
|
|
254
|
|
|
return $form; |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
/** |
258
|
|
|
* Ajax callback that updates multi-step plugin configuration form on AJAX updates. |
259
|
|
|
*/ |
260
|
|
|
public function updateSettingsAjax(array $form, FormStateInterface $form_state) { |
261
|
|
|
return $form; |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
} |
265
|
|
|
|
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.