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;
14 use Drupal\Core\Render\RendererInterface;
17 * The entity browser form.
19 class EntityBrowserForm extends FormBase implements EntityBrowserFormInterface {
22 * UUID generator service.
24 * @var \Drupal\Component\Uuid\UuidInterface
26 protected $uuidGenerator;
29 * The entity browser object.
31 * @var \Drupal\entity_browser\EntityBrowserInterface
33 protected $entityBrowser;
36 * The entity browser selection storage.
38 * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
40 protected $selectionStorage;
43 * The renderer service.
45 * @var \Drupal\Core\Render\RendererInterface
50 * Constructs a EntityBrowserForm object.
52 * @param \Drupal\Component\Uuid\UuidInterface $uuid_generator
53 * The UUID generator service.
54 * @param \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface $selection_storage
56 * @param \Drupal\Core\Render\RendererInterface $renderer
57 * The renderer service.
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;
68 public static function create(ContainerInterface $container) {
70 $container->get('uuid'),
71 $container->get('entity_browser.selection_storage'),
72 $container->get('renderer')
79 public function getFormId() {
80 return 'entity_browser_' . $this->entityBrowser->id() . '_form';
86 public function setEntityBrowser(EntityBrowserInterface $entity_browser) {
87 $this->entityBrowser = $entity_browser;
93 public function getEntityBrowser() {
94 return $this->entityBrowser;
98 * Initializes form state.
100 * @param \Drupal\Core\Form\FormStateInterface $form_state
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'));
110 $form_state->set(['entity_browser', 'instance_uuid'], $this->uuidGenerator->generate());
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);
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);
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);
135 $this->isFunctionalForm();
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']);
141 $form['#browser_parts'] = [
142 'widget_selector' => 'widget_selector',
143 'widget' => 'widget',
144 'selection_display' => 'selection_display',
147 if (!($current_widget_id = $this->getCurrentWidget($form_state))) {
148 drupal_set_message($this->t('No widgets are available.'), 'warning');
153 ->getWidgetSelector()
154 ->setDefaultWidget($current_widget_id);
155 $form[$form['#browser_parts']['widget_selector']] = $this->entityBrowser
156 ->getWidgetSelector()
157 ->getForm($form, $form_state);
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());
164 drupal_set_message($this->t('Access to the widget forbidden.'), 'warning');
167 // Add cache access cache metadata from the widgets to the form directly as
169 foreach ($this->entityBrowser->getWidgets() as $widget) {
170 /** @var \Drupal\entity_browser\WidgetInterface $widget */
171 $this->renderer->addCacheableDependency($form, $widget->access());
174 $form[$form['#browser_parts']['selection_display']] = $this->entityBrowser
175 ->getSelectionDisplay()
176 ->getForm($form, $form_state);
178 if ($this->entityBrowser->getDisplay() instanceof DisplayAjaxInterface) {
179 $this->entityBrowser->getDisplay()->addAjax($form);
182 $form['#attached']['library'][] = 'entity_browser/entity_browser';
188 * Check if entity browser with selected configuration combination can work.
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();
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.');
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);
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);
220 // Only call widget submit if we didn't change the widget.
221 if ($original_widget == $this->getCurrentWidget($form_state)) {
224 ->get($this->getCurrentWidget($form_state))
225 ->submit($form[$form['#browser_parts']['widget']], $form, $form_state);
228 ->getSelectionDisplay()
229 ->submit($form, $form_state);
232 if (!$this->isSelectionCompleted($form_state)) {
233 $form_state->setRebuild();
236 $this->entityBrowser->getDisplay()->selectionCompleted($this->getSelectedEntities($form_state));
241 * Returns the widget that is currently selected.
243 * @param \Drupal\Core\Form\FormStateInterface $form_state
244 * The current state of the form.
247 * ID of currently selected widget.
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());
255 return $form_state->get('entity_browser_current_widget');
259 * Sets widget that is currently active.
261 * @param string $widget
262 * New active widget UUID.
263 * @param \Drupal\Core\Form\FormStateInterface $form_state
266 protected function setCurrentWidget($widget, FormStateInterface $form_state) {
267 $form_state->set('entity_browser_current_widget', $widget);
271 * Indicates selection is done.
273 * @param \Drupal\Core\Form\FormStateInterface $form_state
277 * Indicates selection is done.
279 protected function isSelectionCompleted(FormStateInterface $form_state) {
280 return (bool) $form_state->get(['entity_browser', 'selection_completed']);
284 * Returns currently selected entities.
286 * @param \Drupal\Core\Form\FormStateInterface $form_state
289 * @return \Drupal\Core\Entity\EntityInterface[]
290 * Array of currently selected entities.
292 protected function getSelectedEntities(FormStateInterface $form_state) {
293 return $form_state->get(['entity_browser', 'selected_entities']);