3 namespace Drupal\entity_browser\Form;
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;
16 * The entity browser form.
18 class EntityBrowserForm extends FormBase implements EntityBrowserFormInterface {
21 * UUID generator service.
23 * @var \Drupal\Component\Uuid\UuidInterface
25 protected $uuidGenerator;
28 * The entity browser object.
30 * @var \Drupal\entity_browser\EntityBrowserInterface
32 protected $entityBrowser;
35 * The entity browser selection storage.
37 * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
39 protected $selectionStorage;
42 * Constructs a EntityBrowserForm object.
44 * @param \Drupal\Component\Uuid\UuidInterface $uuid_generator
45 * The UUID generator service.
46 * @param \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface $selection_storage
49 public function __construct(UuidInterface $uuid_generator, KeyValueStoreExpirableInterface $selection_storage) {
50 $this->uuidGenerator = $uuid_generator;
51 $this->selectionStorage = $selection_storage;
57 public static function create(ContainerInterface $container) {
59 $container->get('uuid'),
60 $container->get('entity_browser.selection_storage')
67 public function getFormId() {
68 return 'entity_browser_' . $this->entityBrowser->id() . '_form';
74 public function setEntityBrowser(EntityBrowserInterface $entity_browser) {
75 $this->entityBrowser = $entity_browser;
79 * Initializes form state.
81 * @param \Drupal\Core\Form\FormStateInterface $form_state
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'));
91 $form_state->set(['entity_browser', 'instance_uuid'], $this->uuidGenerator->generate());
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);
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);
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);
116 $this->isFunctionalForm();
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']);
122 $form['#browser_parts'] = [
123 'widget_selector' => 'widget_selector',
124 'widget' => 'widget',
125 'selection_display' => 'selection_display',
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
135 ->get($this->getCurrentWidget($form_state))
136 ->getForm($form, $form_state, $this->entityBrowser->getAdditionalWidgetParameters());
138 $form[$form['#browser_parts']['selection_display']] = $this->entityBrowser
139 ->getSelectionDisplay()
140 ->getForm($form, $form_state);
142 if ($this->entityBrowser->getDisplay() instanceof DisplayAjaxInterface) {
143 $this->entityBrowser->getDisplay()->addAjax($form);
146 $form['#attached']['library'][] = 'entity_browser/entity_browser';
152 * Check if entity browser with selected configuration combination can work.
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();
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.');
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);
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);
184 // Only call widget submit if we didn't change the widget.
185 if ($original_widget == $this->getCurrentWidget($form_state)) {
188 ->get($this->getCurrentWidget($form_state))
189 ->submit($form[$form['#browser_parts']['widget']], $form, $form_state);
192 ->getSelectionDisplay()
193 ->submit($form, $form_state);
196 if (!$this->isSelectionCompleted($form_state)) {
197 $form_state->setRebuild();
200 $this->entityBrowser->getDisplay()->selectionCompleted($this->getSelectedEntities($form_state));
205 * Returns the widget that is currently selected.
207 * @param \Drupal\Core\Form\FormStateInterface $form_state
208 * The current state of the form.
211 * ID of currently selected widget.
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());
219 return $form_state->get('entity_browser_current_widget');
223 * Sets widget that is currently active.
225 * @param string $widget
226 * New active widget UUID.
227 * @param \Drupal\Core\Form\FormStateInterface $form_state
230 protected function setCurrentWidget($widget, FormStateInterface $form_state) {
231 $form_state->set('entity_browser_current_widget', $widget);
235 * Indicates selection is done.
237 * @param \Drupal\Core\Form\FormStateInterface $form_state
241 * Indicates selection is done.
243 protected function isSelectionCompleted(FormStateInterface $form_state) {
244 return (bool) $form_state->get(['entity_browser', 'selection_completed']);
248 * Returns currently selected entities.
250 * @param \Drupal\Core\Form\FormStateInterface $form_state
253 * @return \Drupal\Core\Entity\EntityInterface[]
254 * Array of currently selected entities.
256 protected function getSelectedEntities(FormStateInterface $form_state) {
257 return $form_state->get(['entity_browser', 'selected_entities']);