Completed
Pull Request — 8.x-1.x (#153)
by
unknown
02:46
created

WidgetBase::requiresJsCommands()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
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
    // In case of auto submitting, widget will handle adding entities in JS.
126
    $form['#attached']['drupalSettings']['entity_browser_widget']['auto_select'] = $this->configuration['auto_select'];
127
    if (!$this->configuration['auto_select']) {
128
      $form['actions'] = [
129
        '#type' => 'actions',
130
        'submit' => [
131
          '#type' => 'submit',
132
          '#value' => $this->configuration['submit_text'],
133
          '#eb_widget_main_submit' => TRUE,
134
          '#attributes' => ['class' => ['is-entity-browser-submit']],
135
        ],
136
      ];
137
    }
138
139
    return $form;
140
  }
141
142
  /**
143
   * {@inheritdoc}
144
   */
145
  public function defaultConfiguration() {
146
    return [
147
      'submit_text' => $this->t('Select entities'),
148
      'auto_select' => FALSE,
149
    ];
150
  }
151
152
  /**
153
   * {@inheritdoc}
154
   */
155
  public function getConfiguration() {
156
    return [
157
      'settings' => array_diff_key(
158
        $this->configuration,
159
        ['entity_browser_id' => 0]
160
      ),
161
      'uuid' => $this->uuid(),
162
      'weight' => $this->getWeight(),
163
      'label' => $this->label(),
164
      'id' => $this->id(),
165
    ];
166
  }
167
168
  /**
169
   * {@inheritdoc}
170
   */
171
  public function setConfiguration(array $configuration) {
172
    $configuration += [
173
      'settings' => [],
174
      'uuid' => '',
175
      'weight' => '',
176
      'label' => '',
177
      'id' => '',
178
    ];
179
180
    $this->configuration = $configuration['settings'] + $this->defaultConfiguration();
181
    $this->label = $configuration['label'];
182
    $this->weight = $configuration['weight'];
183
    $this->uuid = $configuration['uuid'];
184
    $this->id = $configuration['id'];
185
  }
186
187
  /**
188
   * {@inheritdoc}
189
   */
190
  public function calculateDependencies() {
191
    return [];
192
  }
193
194
  /**
195
   * {@inheritdoc}
196
   */
197
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
198
    $form['submit_text'] = [
199
      '#type' => 'textfield',
200
      '#title' => $this->t('Submit button text'),
201
      '#default_value' => $this->configuration['submit_text'],
202
    ];
203
204
    // Allow "auto_select" setting when autoSelect is supported by widget.
205
    $form['auto_select'] = [
206
      '#type' => 'checkbox',
207
      '#title' => $this->t('Automatically submit selection'),
208
      '#default_value' => $this->configuration['auto_select'],
209
      '#disabled' => !$this->getPluginDefinition()['autoSelect'],
210
    ];
211
212
    return $form;
213
  }
214
215
  /**
216
   * {@inheritdoc}
217
   */
218
  public function id() {
219
    return $this->id;
220
  }
221
222
  /**
223
   * {@inheritdoc}
224
   */
225
  public function uuid() {
226
    return $this->uuid;
227
  }
228
229
  /**
230
   * {@inheritdoc}
231
   */
232
  public function label() {
233
    return $this->label;
234
  }
235
236
  /**
237
   * {@inheritdoc}
238
   */
239
  public function setLabel($label) {
240
    $this->label = $label;
241
    return $this;
242
  }
243
244
  /**
245
   * {@inheritdoc}
246
   */
247
  public function getWeight() {
248
    return $this->weight;
249
  }
250
251
  /**
252
   * {@inheritdoc}
253
   */
254
  public function setWeight($weight) {
255
    $this->weight = $weight;
256
    return $this;
257
  }
258
259
  /**
260
   * Prepares the entities without saving them.
261
   *
262
   * We need this method when we want to validate or perform other operations
263
   * before submit.
264
   *
265
   * @param array $form
266
   *   Complete form.
267
   * @param \Drupal\Core\Form\FormStateInterface $form_state
268
   *   The form state object.
269
   *
270
   * @return \Drupal\Core\Entity\EntityInterface[]
271
   *   Array of entities.
272
   */
273
  abstract protected function prepareEntities(array $form, FormStateInterface $form_state);
274
275
  /**
276
   * {@inheritdoc}
277
   */
278
  public function validate(array &$form, FormStateInterface $form_state) {
279
    $entities = $this->prepareEntities($form, $form_state);
280
    $validators = $form_state->get(['entity_browser', 'validators']);
281
    if ($validators) {
282
      $violations = $this->runWidgetValidators($entities, $validators);
283
      foreach ($violations as $violation) {
284
        $form_state->setError($form['widget'], $violation->getMessage());
285
      }
286
    }
287
  }
288
289
  /**
290
   * Run widget validators.
291
   *
292
   * @param array $entities
293
   *   Array of entity ids to validate.
294
   * @param array $validators
295
   *   Array of widget validator ids.
296
   *
297
   * @return \Symfony\Component\Validator\ConstraintViolationListInterface
298
   *   A list of constraint violations. If the list is empty, validation
299
   *   succeeded.
300
   */
301
  protected function runWidgetValidators(array $entities, $validators = []) {
302
    $violations = new ConstraintViolationList();
303
    foreach ($validators as $validator_id => $options) {
304
      /** @var \Drupal\entity_browser\WidgetValidationInterface $widget_validator */
305
      $widget_validator = $this->validationManager->createInstance($validator_id, []);
306
      if ($widget_validator) {
307
        $violations->addAll($widget_validator->validate($entities, $options));
308
      }
309
    }
310
311
    return $violations;
312
  }
313
314
  /**
315
   * {@inheritdoc}
316
   */
317
  public function submit(array &$element, array &$form, FormStateInterface $form_state) {}
318
319
  /**
320
   * Dispatches event that informs all subscribers about new selected entities.
321
   *
322
   * @param array $entities
323
   *   Array of entities.
324
   */
325
  protected function selectEntities(array $entities, FormStateInterface $form_state) {
326
    $selected_entities = &$form_state->get(['entity_browser', 'selected_entities']);
327
    $selected_entities = array_merge($selected_entities, $entities);
328
329
    $this->eventDispatcher->dispatch(
330
      Events::SELECTED,
331
      new EntitySelectionEvent(
332
        $this->configuration['entity_browser_id'],
333
        $form_state->get(['entity_browser', 'instance_uuid']),
334
        $entities
335
      ));
336
  }
337
338
  /**
339
   * {@inheritdoc}
340
   */
341
  public function requiresJsCommands() {
342
    return $this->getConfiguration()['settings']['auto_select'];
343
  }
344
345
}
346