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', 'selection_completed'], FALSE);
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);
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);
115 $this->isFunctionalForm();
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']);
121 $form['#browser_parts'] = [
122 'widget_selector' => 'widget_selector',
123 'widget' => 'widget',
124 'selection_display' => 'selection_display',
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
134 ->get($this->getCurrentWidget($form_state))
135 ->getForm($form, $form_state, $this->entityBrowser->getAdditionalWidgetParameters());
137 $form[$form['#browser_parts']['selection_display']] = $this->entityBrowser
138 ->getSelectionDisplay()
139 ->getForm($form, $form_state);
141 if ($this->entityBrowser->getDisplay() instanceof DisplayAjaxInterface) {
142 $this->entityBrowser->getDisplay()->addAjax($form);
145 $form['#attached']['library'][] = 'entity_browser/entity_browser';
151 * Check if entity browser with selected configuration combination can work.
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();
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.');
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);
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);
183 // Only call widget submit if we didn't change the widget.
184 if ($original_widget == $this->getCurrentWidget($form_state)) {
187 ->get($this->getCurrentWidget($form_state))
188 ->submit($form[$form['#browser_parts']['widget']], $form, $form_state);
191 ->getSelectionDisplay()
192 ->submit($form, $form_state);
195 if (!$this->isSelectionCompleted($form_state)) {
196 $form_state->setRebuild();
199 $this->entityBrowser->getDisplay()->selectionCompleted($this->getSelectedEntities($form_state));
204 * Returns the widget that is currently selected.
206 * @param \Drupal\Core\Form\FormStateInterface $form_state
207 * The current state of the form.
210 * ID of currently selected widget.
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());
218 return $form_state->get('entity_browser_current_widget');
222 * Sets widget that is currently active.
224 * @param string $widget
225 * New active widget UUID.
226 * @param \Drupal\Core\Form\FormStateInterface $form_state
229 protected function setCurrentWidget($widget, FormStateInterface $form_state) {
230 $form_state->set('entity_browser_current_widget', $widget);
234 * Indicates selection is done.
236 * @param \Drupal\Core\Form\FormStateInterface $form_state
240 * Indicates selection is done.
242 protected function isSelectionCompleted(FormStateInterface $form_state) {
243 return (bool) $form_state->get(['entity_browser', 'selection_completed']);
247 * Returns currently selected entities.
249 * @param \Drupal\Core\Form\FormStateInterface $form_state
252 * @return \Drupal\Core\Entity\EntityInterface[]
253 * Array of currently selected entities.
255 protected function getSelectedEntities(FormStateInterface $form_state) {
256 return $form_state->get(['entity_browser', 'selected_entities']);