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

EntityBrowserForm::isFunctionalForm()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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