340e425fd3cdb896f4d4f266aba1ac78ed23e440
[yaffs-website] / Form / EntityBrowserForm.php
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', 'widget_context'], []);
96     $form_state->set(['entity_browser', 'selection_completed'], FALSE);
97
98     // Initialize form state with persistent data, if present.
99     if ($storage = $this->selectionStorage->get($form_state->get(['entity_browser', 'instance_uuid']))) {
100       foreach ($storage as $key => $value) {
101         $form_state->set(['entity_browser', $key], $value);
102       }
103     }
104   }
105
106   /**
107    * {@inheritdoc}
108    */
109   public function buildForm(array $form, FormStateInterface $form_state) {
110     // During the initial form build, add this form object to the form state and
111     // allow for initial preparation before form building and processing.
112     if (!$form_state->has('entity_form_initialized')) {
113       $this->init($form_state);
114     }
115
116     $this->isFunctionalForm();
117
118     $form['#attributes']['class'][] = 'entity-browser-form';
119     if (!empty($form_state->get(['entity_browser', 'instance_uuid']))) {
120       $form['#attributes']['data-entity-browser-uuid'] = $form_state->get(['entity_browser', 'instance_uuid']);
121     }
122     $form['#browser_parts'] = [
123       'widget_selector' => 'widget_selector',
124       'widget' => 'widget',
125       'selection_display' => 'selection_display',
126     ];
127     $this->entityBrowser
128       ->getWidgetSelector()
129       ->setDefaultWidget($this->getCurrentWidget($form_state));
130     $form[$form['#browser_parts']['widget_selector']] = $this->entityBrowser
131       ->getWidgetSelector()
132       ->getForm($form, $form_state);
133     $form[$form['#browser_parts']['widget']] = $this->entityBrowser
134       ->getWidgets()
135       ->get($this->getCurrentWidget($form_state))
136       ->getForm($form, $form_state, $this->entityBrowser->getAdditionalWidgetParameters());
137
138     $form[$form['#browser_parts']['selection_display']] = $this->entityBrowser
139       ->getSelectionDisplay()
140       ->getForm($form, $form_state);
141
142     if ($this->entityBrowser->getDisplay() instanceof DisplayAjaxInterface) {
143       $this->entityBrowser->getDisplay()->addAjax($form);
144     }
145
146     $form['#attached']['library'][] = 'entity_browser/entity_browser';
147
148     return $form;
149   }
150
151   /**
152    * Check if entity browser with selected configuration combination can work.
153    */
154   protected function isFunctionalForm() {
155     /** @var \Drupal\entity_browser\WidgetInterface $widget */
156     foreach ($this->entityBrowser->getWidgets() as $widget) {
157       /** @var \Drupal\entity_browser\SelectionDisplayInterface $selectionDisplay */
158       $selectionDisplay = $this->entityBrowser->getSelectionDisplay();
159
160       if ($widget->requiresJsCommands() && !$selectionDisplay->supportsJsCommands()) {
161         throw new ConfigException('Used entity browser selection display cannot work in combination with settings defined for used selection widget.');
162       }
163     }
164   }
165
166   /**
167    * {@inheritdoc}
168    */
169   public function validateForm(array &$form, FormStateInterface $form_state) {
170     $this->entityBrowser->getWidgetSelector()->validate($form, $form_state);
171     $this->entityBrowser->getWidgets()->get($this->getCurrentWidget($form_state))->validate($form, $form_state);
172     $this->entityBrowser->getSelectionDisplay()->validate($form, $form_state);
173   }
174
175   /**
176    * {@inheritdoc}
177    */
178   public function submitForm(array &$form, FormStateInterface $form_state) {
179     $original_widget = $this->getCurrentWidget($form_state);
180     if ($new_widget = $this->entityBrowser->getWidgetSelector()->submit($form, $form_state)) {
181       $this->setCurrentWidget($new_widget, $form_state);
182     }
183
184     // Only call widget submit if we didn't change the widget.
185     if ($original_widget == $this->getCurrentWidget($form_state)) {
186       $this->entityBrowser
187         ->getWidgets()
188         ->get($this->getCurrentWidget($form_state))
189         ->submit($form[$form['#browser_parts']['widget']], $form, $form_state);
190
191       $this->entityBrowser
192         ->getSelectionDisplay()
193         ->submit($form, $form_state);
194     }
195
196     if (!$this->isSelectionCompleted($form_state)) {
197       $form_state->setRebuild();
198     }
199     else {
200       $this->entityBrowser->getDisplay()->selectionCompleted($this->getSelectedEntities($form_state));
201     }
202   }
203
204   /**
205    * Returns the widget that is currently selected.
206    *
207    * @param \Drupal\Core\Form\FormStateInterface $form_state
208    *   The current state of the form.
209    *
210    * @return string
211    *   ID of currently selected widget.
212    */
213   protected function getCurrentWidget(FormStateInterface $form_state) {
214     // Do not use has() as that returns TRUE if the value is NULL.
215     if (!$form_state->get('entity_browser_current_widget')) {
216       $form_state->set('entity_browser_current_widget', $this->entityBrowser->getFirstWidget());
217     }
218
219     return $form_state->get('entity_browser_current_widget');
220   }
221
222   /**
223    * Sets widget that is currently active.
224    *
225    * @param string $widget
226    *   New active widget UUID.
227    * @param \Drupal\Core\Form\FormStateInterface $form_state
228    *   Form state.
229    */
230   protected function setCurrentWidget($widget, FormStateInterface $form_state) {
231     $form_state->set('entity_browser_current_widget', $widget);
232   }
233
234   /**
235    * Indicates selection is done.
236    *
237    * @param \Drupal\Core\Form\FormStateInterface $form_state
238    *   Form state.
239    *
240    * @return bool
241    *   Indicates selection is done.
242    */
243   protected function isSelectionCompleted(FormStateInterface $form_state) {
244     return (bool) $form_state->get(['entity_browser', 'selection_completed']);
245   }
246
247   /**
248    * Returns currently selected entities.
249    *
250    * @param \Drupal\Core\Form\FormStateInterface $form_state
251    *   Form state.
252    *
253    * @return \Drupal\Core\Entity\EntityInterface[]
254    *   Array of currently selected entities.
255    */
256   protected function getSelectedEntities(FormStateInterface $form_state) {
257     return $form_state->get(['entity_browser', 'selected_entities']);
258   }
259
260 }