Completed
Push — 8.x-1.x ( 591469...d3c594 )
by Janez
02:00
created

EntityBrowserForm::validateForm()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 2
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Drupal\entity_browser\Form;
4
5
use Drupal\Component\Uuid\UuidInterface;
6
use Drupal\Core\Config\ConfigException;
7
use Drupal\Core\Form\FormBase;
8
use Drupal\Core\Form\FormStateInterface;
9
use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface;
10
use Drupal\entity_browser\DisplayAjaxInterface;
11
use Drupal\entity_browser\EntityBrowserFormInterface;
12
use Drupal\entity_browser\EntityBrowserInterface;
13
use Symfony\Component\DependencyInjection\ContainerInterface;
14
use Drupal\Core\Render\RendererInterface;
15
16
/**
17
 * The entity browser form.
18
 */
19
class EntityBrowserForm extends FormBase implements EntityBrowserFormInterface {
20
21
  /**
22
   * UUID generator service.
23
   *
24
   * @var \Drupal\Component\Uuid\UuidInterface
25
   */
26
  protected $uuidGenerator;
27
28
  /**
29
   * The entity browser object.
30
   *
31
   * @var \Drupal\entity_browser\EntityBrowserInterface
32
   */
33
  protected $entityBrowser;
34
35
  /**
36
   * The entity browser selection storage.
37
   *
38
   * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
39
   */
40
  protected $selectionStorage;
41
42
  /**
43
   * The renderer service.
44
   *
45
   * @var \Drupal\Core\Render\RendererInterface
46
   */
47
  protected $renderer;
48
49
  /**
50
   * Constructs a EntityBrowserForm object.
51
   *
52
   * @param \Drupal\Component\Uuid\UuidInterface $uuid_generator
53
   *   The UUID generator service.
54
   * @param \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface $selection_storage
55
   *   Selection storage.
56
   * @param \Drupal\Core\Render\RendererInterface $renderer
57
   *   The renderer service.
58
   */
59
  public function __construct(UuidInterface $uuid_generator, KeyValueStoreExpirableInterface $selection_storage, RendererInterface $renderer) {
60
    $this->uuidGenerator = $uuid_generator;
61
    $this->selectionStorage = $selection_storage;
62
    $this->renderer = $renderer;
63
  }
64
65
  /**
66
   * {@inheritdoc}
67
   */
68
  public static function create(ContainerInterface $container) {
69
    return new static(
70
      $container->get('uuid'),
71
      $container->get('entity_browser.selection_storage'),
72
      $container->get('renderer')
73
    );
74
  }
75
76
  /**
77
   * {@inheritdoc}
78
   */
79
  public function getFormId() {
80
    return 'entity_browser_' . $this->entityBrowser->id() . '_form';
81
  }
82
83
  /**
84
   * {@inheritdoc}
85
   */
86
  public function setEntityBrowser(EntityBrowserInterface $entity_browser) {
87
    $this->entityBrowser = $entity_browser;
88
  }
89
90
  /**
91
   * {@inheritdoc}
92
   */
93
  public function getEntityBrowser() {
94
    return $this->entityBrowser;
95
  }
96
97
  /**
98
   * Initializes form state.
99
   *
100
   * @param \Drupal\Core\Form\FormStateInterface $form_state
101
   *   Form state object.
102
   */
103
  protected function init(FormStateInterface $form_state) {
104
    // Flag that this form has been initialized.
105
    $form_state->set('entity_form_initialized', TRUE);
106
    if ($this->getRequest()->query->has('uuid')) {
107
      $form_state->set(['entity_browser', 'instance_uuid'], $this->getRequest()->query->get('uuid'));
108
    }
109
    else {
110
      $form_state->set(['entity_browser', 'instance_uuid'], $this->uuidGenerator->generate());
111
    }
112
    $form_state->set(['entity_browser', 'selected_entities'], []);
113
    $form_state->set(['entity_browser', 'validators'], []);
114
    $form_state->set(['entity_browser', 'widget_context'], []);
115
    $form_state->set(['entity_browser', 'selection_completed'], FALSE);
116
117
    // Initialize form state with persistent data, if present.
118
    if ($storage = $this->selectionStorage->get($form_state->get(['entity_browser', 'instance_uuid']))) {
119
      foreach ($storage as $key => $value) {
120
        $form_state->set(['entity_browser', $key], $value);
121
      }
122
    }
123
  }
124
125
  /**
126
   * {@inheritdoc}
127
   */
128
  public function buildForm(array $form, FormStateInterface $form_state) {
129
    // During the initial form build, add this form object to the form state and
130
    // allow for initial preparation before form building and processing.
131
    if (!$form_state->has('entity_form_initialized')) {
132
      $this->init($form_state);
133
    }
134
135
    $this->isFunctionalForm();
136
137
    $form['#attributes']['class'][] = 'entity-browser-form';
138
    if (!empty($form_state->get(['entity_browser', 'instance_uuid']))) {
139
      $form['#attributes']['data-entity-browser-uuid'] = $form_state->get(['entity_browser', 'instance_uuid']);
140
    }
141
    $form['#browser_parts'] = [
142
      'widget_selector' => 'widget_selector',
143
      'widget' => 'widget',
144
      'selection_display' => 'selection_display',
145
    ];
146
147
    if (!($current_widget_id = $this->getCurrentWidget($form_state))) {
148
      drupal_set_message($this->t('No widgets are available.'), 'warning');
149
      return $form;
150
    }
151
152
    $this->entityBrowser
153
      ->getWidgetSelector()
154
      ->setDefaultWidget($current_widget_id);
155
    $form[$form['#browser_parts']['widget_selector']] = $this->entityBrowser
156
      ->getWidgetSelector()
157
      ->getForm($form, $form_state);
158
159
    $widget = $this->entityBrowser->getWidget($current_widget_id);
160
    if ($widget->access()->isAllowed()) {
161
      $form[$form['#browser_parts']['widget']] = $widget->getForm($form, $form_state, $this->entityBrowser->getAdditionalWidgetParameters());
162
    }
163
    else {
164
      drupal_set_message($this->t('Access to the widget forbidden.'), 'warning');
165
    }
166
167
    // Add cache access cache metadata from the widgets to the form directly as
168
    // it is affected.
169
    foreach ($this->entityBrowser->getWidgets() as $widget) {
170
      /** @var \Drupal\entity_browser\WidgetInterface $widget */
171
      $this->renderer->addCacheableDependency($form, $widget->access());
172
    }
173
174
    $form[$form['#browser_parts']['selection_display']] = $this->entityBrowser
175
      ->getSelectionDisplay()
176
      ->getForm($form, $form_state);
177
178
    if ($this->entityBrowser->getDisplay() instanceof DisplayAjaxInterface) {
179
      $this->entityBrowser->getDisplay()->addAjax($form);
180
    }
181
182
    $form['#attached']['library'][] = 'entity_browser/entity_browser';
183
184
    return $form;
185
  }
186
187
  /**
188
   * Check if entity browser with selected configuration combination can work.
189
   */
190
  protected function isFunctionalForm() {
191
    /** @var \Drupal\entity_browser\WidgetInterface $widget */
192
    foreach ($this->entityBrowser->getWidgets() as $widget) {
193
      /** @var \Drupal\entity_browser\SelectionDisplayInterface $selectionDisplay */
194
      $selectionDisplay = $this->entityBrowser->getSelectionDisplay();
195
196
      if ($widget->requiresJsCommands() && !$selectionDisplay->supportsJsCommands()) {
197
        throw new ConfigException('Used entity browser selection display cannot work in combination with settings defined for used selection widget.');
198
      }
199
    }
200
  }
201
202
  /**
203
   * {@inheritdoc}
204
   */
205
  public function validateForm(array &$form, FormStateInterface $form_state) {
206
    $this->entityBrowser->getWidgetSelector()->validate($form, $form_state);
207
    $this->entityBrowser->getWidgets()->get($this->getCurrentWidget($form_state))->validate($form, $form_state);
208
    $this->entityBrowser->getSelectionDisplay()->validate($form, $form_state);
209
  }
210
211
  /**
212
   * {@inheritdoc}
213
   */
214
  public function submitForm(array &$form, FormStateInterface $form_state) {
215
    $original_widget = $this->getCurrentWidget($form_state);
216
    if ($new_widget = $this->entityBrowser->getWidgetSelector()->submit($form, $form_state)) {
217
      $this->setCurrentWidget($new_widget, $form_state);
218
    }
219
220
    // Only call widget submit if we didn't change the widget.
221
    if ($original_widget == $this->getCurrentWidget($form_state)) {
222
      $this->entityBrowser
223
        ->getWidgets()
224
        ->get($this->getCurrentWidget($form_state))
225
        ->submit($form[$form['#browser_parts']['widget']], $form, $form_state);
226
227
      $this->entityBrowser
228
        ->getSelectionDisplay()
229
        ->submit($form, $form_state);
230
    }
231
232
    if (!$this->isSelectionCompleted($form_state)) {
233
      $form_state->setRebuild();
234
    }
235
    else {
236
      $this->entityBrowser->getDisplay()->selectionCompleted($this->getSelectedEntities($form_state));
237
    }
238
  }
239
240
  /**
241
   * Returns the widget that is currently selected.
242
   *
243
   * @param \Drupal\Core\Form\FormStateInterface $form_state
244
   *   The current state of the form.
245
   *
246
   * @return string
247
   *   ID of currently selected widget.
248
   */
249
  protected function getCurrentWidget(FormStateInterface $form_state) {
250
    // Do not use has() as that returns TRUE if the value is NULL.
251
    if (!$form_state->get('entity_browser_current_widget')) {
252
      $form_state->set('entity_browser_current_widget', $this->entityBrowser->getFirstWidget());
253
    }
254
255
    return $form_state->get('entity_browser_current_widget');
256
  }
257
258
  /**
259
   * Sets widget that is currently active.
260
   *
261
   * @param string $widget
262
   *   New active widget UUID.
263
   * @param \Drupal\Core\Form\FormStateInterface $form_state
264
   *   Form state.
265
   */
266
  protected function setCurrentWidget($widget, FormStateInterface $form_state) {
267
    $form_state->set('entity_browser_current_widget', $widget);
268
  }
269
270
  /**
271
   * Indicates selection is done.
272
   *
273
   * @param \Drupal\Core\Form\FormStateInterface $form_state
274
   *   Form state.
275
   *
276
   * @return bool
277
   *   Indicates selection is done.
278
   */
279
  protected function isSelectionCompleted(FormStateInterface $form_state) {
280
    return (bool) $form_state->get(['entity_browser', 'selection_completed']);
281
  }
282
283
  /**
284
   * Returns currently selected entities.
285
   *
286
   * @param \Drupal\Core\Form\FormStateInterface $form_state
287
   *   Form state.
288
   *
289
   * @return \Drupal\Core\Entity\EntityInterface[]
290
   *   Array of currently selected entities.
291
   */
292
  protected function getSelectedEntities(FormStateInterface $form_state) {
293
    return $form_state->get(['entity_browser', 'selected_entities']);
294
  }
295
296
}
297