Completed
Push — 8.x-1.x ( 1579f4...ca1f2a )
by Janez
02:49
created

WidgetBase::requiresJsCommands()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Drupal\entity_browser;
4
5
use Drupal\Core\Entity\EntityTypeManagerInterface;
6
use Drupal\Core\Plugin\PluginBase;
7
use Drupal\Core\Form\FormStateInterface;
8
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
9
use Drupal\entity_browser\Events\EntitySelectionEvent;
10
use Drupal\entity_browser\Events\Events;
11
use Symfony\Component\DependencyInjection\ContainerInterface;
12
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
13
use Symfony\Component\Validator\ConstraintViolationList;
14
15
/**
16
 * Base class for widget plugins.
17
 */
18
abstract class WidgetBase extends PluginBase implements WidgetInterface, ContainerFactoryPluginInterface {
19
20
  use PluginConfigurationFormTrait;
21
22
  /**
23
   * Plugin id.
24
   *
25
   * @var string
26
   */
27
  protected $id;
28
29
  /**
30
   * Plugin uuid.
31
   *
32
   * @var string
33
   */
34
  protected $uuid;
35
  /**
36
   * Plugin label.
37
   *
38
   * @var string
39
   */
40
  protected $label;
41
42
  /**
43
   * Plugin weight.
44
   *
45
   * @var int
46
   */
47
  protected $weight;
48
49
  /**
50
   * Event dispatcher service.
51
   *
52
   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
53
   */
54
  protected $eventDispatcher;
55
56
  /**
57
   * Entity type manager service.
58
   *
59
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
60
   */
61
  protected $entityTypeManager;
62
63
  /**
64
   * The Widget Validation Manager service.
65
   *
66
   * @var \Drupal\entity_browser\WidgetValidationManager
67
   */
68
  protected $validationManager;
69
70
  /**
71
   * WidgetBase constructor.
72
   *
73
   * @param array $configuration
74
   *   A configuration array containing information about the plugin instance.
75
   * @param string $plugin_id
76
   *   The plugin_id for the plugin instance.
77
   * @param mixed $plugin_definition
78
   *   The plugin implementation definition.
79
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
80
   *   Event dispatcher service.
81
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
82
   *   The entity type manager service.
83
   * @param \Drupal\entity_browser\WidgetValidationManager $validation_manager
84
   *   The Widget Validation Manager service.
85
   */
86 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...
87
    parent::__construct($configuration, $plugin_id, $plugin_definition);
88
    $this->eventDispatcher = $event_dispatcher;
89
    $this->entityTypeManager = $entity_type_manager;
90
    $this->validationManager = $validation_manager;
91
    $this->setConfiguration($configuration);
92
  }
93
94
  /**
95
   * {@inheritdoc}
96
   */
97 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...
98
    return new static(
99
      $configuration,
100
      $plugin_id,
101
      $plugin_definition,
102
      $container->get('event_dispatcher'),
103
      $container->get('entity_type.manager'),
104
      $container->get('plugin.manager.entity_browser.widget_validation')
105
    );
106
  }
107
108
  /**
109
   * {@inheritdoc}
110
   */
111
  public function getForm(array &$original_form, FormStateInterface $form_state, array $additional_widget_parameters) {
112
    $form = [];
113
114
    // Allow configuration overrides at runtime based on form state to enable
115
    // use cases where the instance of a widget may have contextual
116
    // configuration like field settings. "widget_context" doesn't have to be
117
    // used in this way, if a widget doesn't want its default configuration
118
    // overwritten it can not call this method and implement its own logic.
119
    foreach ($this->defaultConfiguration() as $key => $value) {
120
      if ($form_state->has(['entity_browser', 'widget_context', $key]) && isset($this->configuration[$key])) {
121
        $this->configuration[$key] = $form_state->get(['entity_browser', 'widget_context', $key]);
122
      }
123
    }
124
125
    // Check if widget supports auto select functionality and expose config to
126
    // front-end javascript.
127
    $autoSelect = FALSE;
128
    if ($this->getPluginDefinition()['auto_select']) {
129
      $autoSelect = $this->configuration['auto_select'];
130
      $form['#attached']['drupalSettings']['entity_browser_widget']['auto_select'] = $autoSelect;
131
    }
132
133
    // In case of auto select, widget will handle adding entities in JS.
134
    if (!$autoSelect) {
135
      $form['actions'] = [
136
        '#type' => 'actions',
137
        'submit' => [
138
          '#type' => 'submit',
139
          '#value' => $this->configuration['submit_text'],
140
          '#eb_widget_main_submit' => TRUE,
141
          '#attributes' => ['class' => ['is-entity-browser-submit']],
142
          '#button_type' => 'primary',
143
        ],
144
      ];
145
    }
146
147
    return $form;
148
  }
149
150
  /**
151
   * {@inheritdoc}
152
   */
153
  public function defaultConfiguration() {
154
    $defaultConfig = [
155
      'submit_text' => $this->t('Select entities'),
156
    ];
157
158
    // If auto select is supported by Widget, append default configuration.
159
    if ($this->getPluginDefinition()['auto_select']) {
160
      $defaultConfig['auto_select'] = FALSE;
161
    }
162
163
    return $defaultConfig;
164
  }
165
166
  /**
167
   * {@inheritdoc}
168
   */
169
  public function getConfiguration() {
170
    return [
171
      'settings' => array_diff_key(
172
        $this->configuration,
173
        ['entity_browser_id' => 0]
174
      ),
175
      'uuid' => $this->uuid(),
176
      'weight' => $this->getWeight(),
177
      'label' => $this->label(),
178
      'id' => $this->id(),
179
    ];
180
  }
181
182
  /**
183
   * {@inheritdoc}
184
   */
185
  public function setConfiguration(array $configuration) {
186
    $configuration += [
187
      'settings' => [],
188
      'uuid' => '',
189
      'weight' => '',
190
      'label' => '',
191
      'id' => '',
192
    ];
193
194
    $this->configuration = $configuration['settings'] + $this->defaultConfiguration();
195
    $this->label = $configuration['label'];
196
    $this->weight = $configuration['weight'];
197
    $this->uuid = $configuration['uuid'];
198
    $this->id = $configuration['id'];
199
  }
200
201
  /**
202
   * {@inheritdoc}
203
   */
204
  public function calculateDependencies() {
205
    return [];
206
  }
207
208
  /**
209
   * {@inheritdoc}
210
   */
211
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
212
    $form['submit_text'] = [
213
      '#type' => 'textfield',
214
      '#title' => $this->t('Submit button text'),
215
      '#default_value' => $this->configuration['submit_text'],
216
    ];
217
218
    // Allow "auto_select" setting when auto_select is supported by widget.
219
    if ($this->getPluginDefinition()['auto_select']) {
220
      $form['auto_select'] = [
221
        '#type' => 'checkbox',
222
        '#title' => $this->t('Automatically submit selection'),
223
        '#default_value' => $this->configuration['auto_select'],
224
      ];
225
    }
226
227
    return $form;
228
  }
229
230
  /**
231
   * {@inheritdoc}
232
   */
233
  public function id() {
234
    return $this->id;
235
  }
236
237
  /**
238
   * {@inheritdoc}
239
   */
240
  public function uuid() {
241
    return $this->uuid;
242
  }
243
244
  /**
245
   * {@inheritdoc}
246
   */
247
  public function label() {
248
    return $this->label;
249
  }
250
251
  /**
252
   * {@inheritdoc}
253
   */
254
  public function setLabel($label) {
255
    $this->label = $label;
256
    return $this;
257
  }
258
259
  /**
260
   * {@inheritdoc}
261
   */
262
  public function getWeight() {
263
    return $this->weight;
264
  }
265
266
  /**
267
   * {@inheritdoc}
268
   */
269
  public function setWeight($weight) {
270
    $this->weight = $weight;
271
    return $this;
272
  }
273
274
  /**
275
   * Prepares the entities without saving them.
276
   *
277
   * We need this method when we want to validate or perform other operations
278
   * before submit.
279
   *
280
   * @param array $form
281
   *   Complete form.
282
   * @param \Drupal\Core\Form\FormStateInterface $form_state
283
   *   The form state object.
284
   *
285
   * @return \Drupal\Core\Entity\EntityInterface[]
286
   *   Array of entities.
287
   */
288
  abstract protected function prepareEntities(array $form, FormStateInterface $form_state);
289
290
  /**
291
   * {@inheritdoc}
292
   */
293
  public function validate(array &$form, FormStateInterface $form_state) {
294
    $entities = $this->prepareEntities($form, $form_state);
295
    $validators = $form_state->get(['entity_browser', 'validators']);
296
    if ($validators) {
297
      $violations = $this->runWidgetValidators($entities, $validators);
298
      foreach ($violations as $violation) {
299
        $form_state->setError($form['widget'], $violation->getMessage());
300
      }
301
    }
302
  }
303
304
  /**
305
   * Run widget validators.
306
   *
307
   * @param array $entities
308
   *   Array of entity ids to validate.
309
   * @param array $validators
310
   *   Array of widget validator ids.
311
   *
312
   * @return \Symfony\Component\Validator\ConstraintViolationListInterface
313
   *   A list of constraint violations. If the list is empty, validation
314
   *   succeeded.
315
   */
316
  protected function runWidgetValidators(array $entities, $validators = []) {
317
    $violations = new ConstraintViolationList();
318
    foreach ($validators as $validator_id => $options) {
319
      /** @var \Drupal\entity_browser\WidgetValidationInterface $widget_validator */
320
      $widget_validator = $this->validationManager->createInstance($validator_id, []);
321
      if ($widget_validator) {
322
        $violations->addAll($widget_validator->validate($entities, $options));
323
      }
324
    }
325
326
    return $violations;
327
  }
328
329
  /**
330
   * {@inheritdoc}
331
   */
332
  public function submit(array &$element, array &$form, FormStateInterface $form_state) {}
333
334
  /**
335
   * Dispatches event that informs all subscribers about new selected entities.
336
   *
337
   * @param array $entities
338
   *   Array of entities.
339
   */
340
  protected function selectEntities(array $entities, FormStateInterface $form_state) {
341
    $selected_entities = &$form_state->get(['entity_browser', 'selected_entities']);
342
    $selected_entities = array_merge($selected_entities, $entities);
343
344
    $this->eventDispatcher->dispatch(
345
      Events::SELECTED,
346
      new EntitySelectionEvent(
347
        $this->configuration['entity_browser_id'],
348
        $form_state->get(['entity_browser', 'instance_uuid']),
349
        $entities
350
      ));
351
  }
352
353
  /**
354
   * {@inheritdoc}
355
   */
356
  public function requiresJsCommands() {
357
    return $this->getPluginDefinition()['auto_select'] && $this->getConfiguration()['settings']['auto_select'];
358
  }
359
360
}
361