WidgetBase::setWeight()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Drupal\entity_browser;
4
5
use Drupal\Component\Utility\NestedArray;
6
use Drupal\Core\Access\AccessResult;
7
use Drupal\Core\Entity\EntityTypeManagerInterface;
8
use Drupal\Core\Plugin\PluginBase;
9
use Drupal\Core\Form\FormStateInterface;
10
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
11
use Drupal\entity_browser\Events\EntitySelectionEvent;
12
use Drupal\entity_browser\Events\Events;
13
use Symfony\Component\DependencyInjection\ContainerInterface;
14
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
15
use Symfony\Component\Validator\ConstraintViolationList;
16
17
/**
18
 * Base class for widget plugins.
19
 */
20
abstract class WidgetBase extends PluginBase implements WidgetInterface, ContainerFactoryPluginInterface {
21
22
  use PluginConfigurationFormTrait;
23
24
  /**
25
   * Plugin id.
26
   *
27
   * @var string
28
   */
29
  protected $id;
30
31
  /**
32
   * Plugin uuid.
33
   *
34
   * @var string
35
   */
36
  protected $uuid;
37
  /**
38
   * Plugin label.
39
   *
40
   * @var string
41
   */
42
  protected $label;
43
44
  /**
45
   * Plugin weight.
46
   *
47
   * @var int
48
   */
49
  protected $weight;
50
51
  /**
52
   * Event dispatcher service.
53
   *
54
   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
55
   */
56
  protected $eventDispatcher;
57
58
  /**
59
   * Entity type manager service.
60
   *
61
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
62
   */
63
  protected $entityTypeManager;
64
65
  /**
66
   * The Widget Validation Manager service.
67
   *
68
   * @var \Drupal\entity_browser\WidgetValidationManager
69
   */
70
  protected $validationManager;
71
72
  /**
73
   * WidgetBase constructor.
74
   *
75
   * @param array $configuration
76
   *   A configuration array containing information about the plugin instance.
77
   * @param string $plugin_id
78
   *   The plugin_id for the plugin instance.
79
   * @param mixed $plugin_definition
80
   *   The plugin implementation definition.
81
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
82
   *   Event dispatcher service.
83
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
84
   *   The entity type manager service.
85
   * @param \Drupal\entity_browser\WidgetValidationManager $validation_manager
86
   *   The Widget Validation Manager service.
87
   */
88 View Code Duplication
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EventDispatcherInterface $event_dispatcher, EntityTypeManagerInterface $entity_type_manager, WidgetValidationManager $validation_manager) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
89
    parent::__construct($configuration, $plugin_id, $plugin_definition);
90
    $this->eventDispatcher = $event_dispatcher;
91
    $this->entityTypeManager = $entity_type_manager;
92
    $this->validationManager = $validation_manager;
93
    $this->setConfiguration($configuration);
94
  }
95
96
  /**
97
   * {@inheritdoc}
98
   */
99 View Code Duplication
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
100
    return new static(
101
      $configuration,
102
      $plugin_id,
103
      $plugin_definition,
104
      $container->get('event_dispatcher'),
105
      $container->get('entity_type.manager'),
106
      $container->get('plugin.manager.entity_browser.widget_validation')
107
    );
108
  }
109
110
  /**
111
   * {@inheritdoc}
112
   */
113
  public function getForm(array &$original_form, FormStateInterface $form_state, array $additional_widget_parameters) {
114
    $form = [];
115
116
    if ($form_state->has(['entity_browser', 'widget_context'])) {
117
      $this->handleWidgetContext($form_state->get(['entity_browser', 'widget_context']));
118
    }
119
120
    // Check if widget supports auto select functionality and expose config to
121
    // front-end javascript.
122
    $autoSelect = FALSE;
123
    if ($this->getPluginDefinition()['auto_select']) {
124
      $autoSelect = $this->configuration['auto_select'];
125
      $form['#attached']['drupalSettings']['entity_browser_widget']['auto_select'] = $autoSelect;
126
    }
127
128
    // In case of auto select, widget will handle adding entities in JS.
129
    if (!$autoSelect) {
130
      $form['actions'] = [
131
        '#type' => 'actions',
132
        'submit' => [
133
          '#type' => 'submit',
134
          '#value' => $this->configuration['submit_text'],
135
          '#eb_widget_main_submit' => TRUE,
136
          '#attributes' => ['class' => ['is-entity-browser-submit']],
137
          '#button_type' => 'primary',
138
        ],
139
      ];
140
    }
141
142
    return $form;
143
  }
144
145
  /**
146
   * {@inheritdoc}
147
   */
148
  public function defaultConfiguration() {
149
    $defaultConfig = [
150
      'submit_text' => $this->t('Select entities'),
151
    ];
152
153
    // If auto select is supported by Widget, append default configuration.
154
    if ($this->getPluginDefinition()['auto_select']) {
155
      $defaultConfig['auto_select'] = FALSE;
156
    }
157
158
    return $defaultConfig;
159
  }
160
161
  /**
162
   * {@inheritdoc}
163
   */
164
  public function getConfiguration() {
165
    return [
166
      'settings' => array_diff_key(
167
        $this->configuration,
168
        ['entity_browser_id' => 0]
169
      ),
170
      'uuid' => $this->uuid(),
171
      'weight' => $this->getWeight(),
172
      'label' => $this->label(),
173
      'id' => $this->id(),
174
    ];
175
  }
176
177
  /**
178
   * {@inheritdoc}
179
   */
180
  public function setConfiguration(array $configuration) {
181
    $configuration += [
182
      'settings' => [],
183
      'uuid' => '',
184
      'weight' => '',
185
      'label' => '',
186
      'id' => '',
187
    ];
188
189
    $this->configuration = NestedArray::mergeDeep(
190
      $this->defaultConfiguration(),
191
      $configuration['settings']
192
    );
193
    $this->label = $configuration['label'];
194
    $this->weight = $configuration['weight'];
195
    $this->uuid = $configuration['uuid'];
196
    $this->id = $configuration['id'];
197
  }
198
199
  /**
200
   * {@inheritdoc}
201
   */
202
  public function calculateDependencies() {
203
    return [];
204
  }
205
206
  /**
207
   * {@inheritdoc}
208
   */
209
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
210
    $form['submit_text'] = [
211
      '#type' => 'textfield',
212
      '#title' => $this->t('Submit button text'),
213
      '#default_value' => $this->configuration['submit_text'],
214
    ];
215
216
    // Allow "auto_select" setting when auto_select is supported by widget.
217
    if ($this->getPluginDefinition()['auto_select']) {
218
      $form['auto_select'] = [
219
        '#type' => 'checkbox',
220
        '#title' => $this->t('Automatically submit selection'),
221
        '#default_value' => $this->configuration['auto_select'],
222
      ];
223
    }
224
225
    return $form;
226
  }
227
228
  /**
229
   * {@inheritdoc}
230
   */
231
  public function id() {
232
    return $this->id;
233
  }
234
235
  /**
236
   * {@inheritdoc}
237
   */
238
  public function uuid() {
239
    return $this->uuid;
240
  }
241
242
  /**
243
   * {@inheritdoc}
244
   */
245
  public function label() {
246
    return $this->label;
247
  }
248
249
  /**
250
   * {@inheritdoc}
251
   */
252
  public function setLabel($label) {
253
    $this->label = $label;
254
    return $this;
255
  }
256
257
  /**
258
   * {@inheritdoc}
259
   */
260
  public function getWeight() {
261
    return $this->weight;
262
  }
263
264
  /**
265
   * {@inheritdoc}
266
   */
267
  public function setWeight($weight) {
268
    $this->weight = $weight;
269
    return $this;
270
  }
271
272
  /**
273
   * Prepares the entities without saving them.
274
   *
275
   * We need this method when we want to validate or perform other operations
276
   * before submit.
277
   *
278
   * @param array $form
279
   *   Complete form.
280
   * @param \Drupal\Core\Form\FormStateInterface $form_state
281
   *   The form state object.
282
   *
283
   * @return \Drupal\Core\Entity\EntityInterface[]
284
   *   Array of entities.
285
   */
286
  abstract protected function prepareEntities(array $form, FormStateInterface $form_state);
287
288
  /**
289
   * {@inheritdoc}
290
   */
291
  public function validate(array &$form, FormStateInterface $form_state) {
292
    $entities = $this->prepareEntities($form, $form_state);
293
    $validators = $form_state->get(['entity_browser', 'validators']);
294
    if ($validators) {
295
      $violations = $this->runWidgetValidators($entities, $validators);
296
      foreach ($violations as $violation) {
297
        $form_state->setError($form['widget'], $violation->getMessage());
298
      }
299
    }
300
  }
301
302
  /**
303
   * Run widget validators.
304
   *
305
   * @param array $entities
306
   *   Array of entity ids to validate.
307
   * @param array $validators
308
   *   Array of widget validator ids.
309
   *
310
   * @return \Symfony\Component\Validator\ConstraintViolationListInterface
311
   *   A list of constraint violations. If the list is empty, validation
312
   *   succeeded.
313
   */
314
  protected function runWidgetValidators(array $entities, $validators = []) {
315
    $violations = new ConstraintViolationList();
316
    foreach ($validators as $validator_id => $options) {
317
      /** @var \Drupal\entity_browser\WidgetValidationInterface $widget_validator */
318
      $widget_validator = $this->validationManager->createInstance($validator_id, []);
319
      if ($widget_validator) {
320
        $violations->addAll($widget_validator->validate($entities, $options));
321
      }
322
    }
323
324
    return $violations;
325
  }
326
327
  /**
328
   * {@inheritdoc}
329
   */
330
  public function submit(array &$element, array &$form, FormStateInterface $form_state) {}
331
332
  /**
333
   * Dispatches event that informs all subscribers about new selected entities.
334
   *
335
   * @param array $entities
336
   *   Array of entities.
337
   */
338
  protected function selectEntities(array $entities, FormStateInterface $form_state) {
339
    $selected_entities = &$form_state->get(['entity_browser', 'selected_entities']);
340
    $selected_entities = array_merge($selected_entities, $entities);
341
342
    $this->eventDispatcher->dispatch(
343
      Events::SELECTED,
344
      new EntitySelectionEvent(
345
        $this->configuration['entity_browser_id'],
346
        $form_state->get(['entity_browser', 'instance_uuid']),
347
        $entities
348
      ));
349
  }
350
351
  /**
352
   * {@inheritdoc}
353
   */
354
  public function requiresJsCommands() {
355
    return $this->getPluginDefinition()['auto_select'] && $this->getConfiguration()['settings']['auto_select'];
356
  }
357
358
  /**
359
   * Allow configuration overrides at runtime based on widget context passed to
360
   * this widget from the Entity Browser element.
361
   *
362
   * Widgets can override this method to replace the default behavior of
363
   * replacing configuration with widget context if array keys match.
364
   *
365
   * @param array $widget_context
366
   *   The widget context.
367
   */
368
  protected function handleWidgetContext($widget_context) {
369
    foreach ($this->defaultConfiguration() as $key => $value) {
370
      if (isset($widget_context[$key]) && isset($this->configuration[$key])) {
371
        $this->configuration[$key] = $widget_context[$key];
372
      }
373
    }
374
  }
375
376
  /**
377
   * {@inheritdoc}
378
   */
379
  public function access() {
380
    return AccessResult::allowed();
381
  }
382
383
}
384