3 namespace Drupal\entity_embed\Form;
5 use Drupal\Component\Utility\Html;
6 use Drupal\Component\Utility\Unicode;
7 use Drupal\Core\Ajax\AjaxResponse;
8 use Drupal\Core\Ajax\CloseModalDialogCommand;
9 use Drupal\Core\Ajax\HtmlCommand;
10 use Drupal\Core\Ajax\SetDialogTitleCommand;
11 use Drupal\Core\Entity\EntityFieldManagerInterface;
12 use Drupal\Core\Entity\EntityInterface;
13 use Drupal\Core\Entity\EntityTypeManagerInterface;
14 use Drupal\Core\Extension\ModuleHandlerInterface;
15 use Drupal\Core\Form\FormBase;
16 use Drupal\Core\Form\FormBuilderInterface;
17 use Drupal\Core\Form\FormStateInterface;
18 use Drupal\editor\Ajax\EditorDialogSave;
19 use Drupal\editor\EditorInterface;
20 use Drupal\embed\EmbedButtonInterface;
21 use Drupal\entity_browser\Events\Events;
22 use Drupal\entity_browser\Events\RegisterJSCallbacks;
23 use Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayManager;
24 use Drupal\Component\Serialization\Json;
25 use Symfony\Component\DependencyInjection\ContainerInterface;
26 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
29 * Provides a form to embed entities by specifying data attributes.
31 class EntityEmbedDialog extends FormBase {
34 * The entity embed display manager.
36 * @var \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayManager
38 protected $entityEmbedDisplayManager;
43 * @var \Drupal\Core\Form\FormBuilderInterface
45 protected $formBuilder;
48 * The entity type manager service.
50 * @var \Drupal\Core\Entity\EntityTypeManagerInterface
52 protected $entityTypeManager;
55 * Event dispatcher service.
57 * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
59 protected $eventDispatcher;
64 * @var \Drupal\entity_browser\EntityBrowserInterface
66 protected $entityBrowser;
69 * The entity field manager.
71 * @var \Drupal\Core\Entity\EntityFieldManager
73 protected $entityFieldManager;
76 * The module handler service.
78 * @var \Drupal\Core\Extension\ModuleHandlerInterface
80 protected $moduleHandler;
83 * The entity browser settings from the entity embed button.
85 protected $entityBrowserSettings = [];
88 * Constructs a EntityEmbedDialog object.
90 * @param \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayManager $entity_embed_display_manager
92 * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
94 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
95 * The entity type manager service.
96 * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
97 * Event dispatcher service.
98 * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
99 * The entity field manager.
100 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
101 * The module handler.
103 public function __construct(EntityEmbedDisplayManager $entity_embed_display_manager, FormBuilderInterface $form_builder, EntityTypeManagerInterface $entity_type_manager, EventDispatcherInterface $event_dispatcher, EntityFieldManagerInterface $entity_field_manager, ModuleHandlerInterface $module_handler) {
104 $this->entityEmbedDisplayManager = $entity_embed_display_manager;
105 $this->formBuilder = $form_builder;
106 $this->entityTypeManager = $entity_type_manager;
107 $this->eventDispatcher = $event_dispatcher;
108 $this->entityFieldManager = $entity_field_manager;
109 $this->moduleHandler = $module_handler;
115 public static function create(ContainerInterface $container) {
117 $container->get('plugin.manager.entity_embed.display'),
118 $container->get('form_builder'),
119 $container->get('entity_type.manager'),
120 $container->get('event_dispatcher'),
121 $container->get('entity_field.manager'),
122 $container->get('module_handler')
129 public function getFormId() {
130 return 'entity_embed_dialog';
136 * @param \Drupal\editor\EditorInterface $editor
137 * The editor to which this dialog corresponds.
138 * @param \Drupal\embed\EmbedButtonInterface $embed_button
139 * The URL button to which this dialog corresponds.
141 public function buildForm(array $form, FormStateInterface $form_state, EditorInterface $editor = NULL, EmbedButtonInterface $embed_button = NULL) {
142 $values = $form_state->getValues();
143 $input = $form_state->getUserInput();
144 // Set embed button element in form state, so that it can be used later in
145 // validateForm() function.
146 $form_state->set('embed_button', $embed_button);
147 $form_state->set('editor', $editor);
148 // Initialize entity element with form attributes, if present.
149 $entity_element = empty($values['attributes']) ? array() : $values['attributes'];
150 $entity_element += empty($input['attributes']) ? array() : $input['attributes'];
151 // The default values are set directly from \Drupal::request()->request,
152 // provided by the editor plugin opening the dialog.
153 if (!$form_state->get('entity_element')) {
154 $form_state->set('entity_element', isset($input['editor_object']) ? $input['editor_object'] : array());
156 $entity_element += $form_state->get('entity_element');
158 'data-entity-type' => $embed_button->getTypeSetting('entity_type'),
159 'data-entity-uuid' => '',
160 'data-entity-embed-display' => 'entity_reference:entity_reference_entity_view',
161 'data-entity-embed-display-settings' => isset($form_state->get('entity_element')['data-entity-embed-settings']) ? $form_state->get('entity_element')['data-entity-embed-settings'] : [],
163 $form_state->set('entity_element', $entity_element);
164 $entity = $this->entityTypeManager->getStorage($entity_element['data-entity-type'])
165 ->loadByProperties(['uuid' => $entity_element['data-entity-uuid']]);
166 $form_state->set('entity', current($entity) ?: NULL);
168 if (!$form_state->get('step')) {
169 // If an entity has been selected, then always skip to the embed options.
170 if ($form_state->get('entity')) {
171 $form_state->set('step', 'embed');
174 $form_state->set('step', 'select');
178 $form['#tree'] = TRUE;
179 $form['#attached']['library'][] = 'editor/drupal.editor.dialog';
180 $form['#attached']['library'][] = 'entity_embed/drupal.entity_embed.dialog';
181 $form['#prefix'] = '<div id="entity-embed-dialog-form">';
182 $form['#suffix'] = '</div>';
183 $form['#attributes']['class'][] = 'entity-embed-dialog-step--' . $form_state->get('step');
185 $this->loadEntityBrowser($form_state);
187 if ($form_state->get('step') == 'select') {
188 $form = $this->buildSelectStep($form, $form_state);
190 elseif ($form_state->get('step') == 'review') {
191 $form = $this->buildReviewStep($form, $form_state);
193 elseif ($form_state->get('step') == 'embed') {
194 $form = $this->buildEmbedStep($form, $form_state);
201 * Form constructor for the entity selection step.
204 * An associative array containing the structure of the form.
205 * @param \Drupal\Core\Form\FormStateInterface $form_state
206 * The current state of the form.
209 * The form structure.
211 public function buildSelectStep(array &$form, FormStateInterface $form_state) {
212 // Entity element is calculated on every AJAX request/submit. See ::buildForm().
213 $entity_element = $form_state->get('entity_element');
214 /** @var \Drupal\embed\EmbedButtonInterface $embed_button */
215 $embed_button = $form_state->get('embed_button');
216 $entity = $form_state->get('entity');
218 $form['attributes']['data-entity-type'] = array(
220 '#value' => $entity_element['data-entity-type'],
223 $label = $this->t('Label');
224 // Attempt to display a better label if we can by getting it from
225 // the label field definition.
226 $entity_type = $this->entityTypeManager->getDefinition($entity_element['data-entity-type']);
227 if ($entity_type->isSubclassOf('\Drupal\Core\Entity\FieldableEntityInterface') && $entity_type->hasKey('label')) {
228 $field_definitions = $this->entityFieldManager->getBaseFieldDefinitions($entity_type->id());
229 if (isset($field_definitions[$entity_type->getKey('label')])) {
230 $label = $field_definitions[$entity_type->getKey('label')]->getLabel();
234 $form['#title'] = $this->t('Select @type to embed', array('@type' => $entity_type->getLowercaseLabel()));
236 if ($this->entityBrowser) {
237 $this->eventDispatcher->addListener(Events::REGISTER_JS_CALLBACKS, [$this, 'registerJSCallback']);
238 $form['entity_browser'] = [
239 '#type' => 'entity_browser',
240 '#entity_browser' => $this->entityBrowser->id(),
242 '#entity_browser_validators' => [
243 'entity_type' => ['type' => $entity_element['data-entity-type']],
248 $form['entity_id'] = array(
249 '#type' => 'entity_autocomplete',
250 '#target_type' => $entity_element['data-entity-type'],
252 '#default_value' => $entity,
254 '#description' => $this->t('Type label and pick the right one from suggestions. Note that the unique ID will be saved.'),
256 if ($bundles = $embed_button->getTypeSetting('bundles')) {
257 $form['entity_id']['#selection_settings']['target_bundles'] = $bundles;
261 $form['attributes']['data-entity-uuid'] = array(
263 '#title' => $entity_element['data-entity-uuid'],
265 $form['actions'] = array(
266 '#type' => 'actions',
269 $form['actions']['save_modal'] = array(
271 '#value' => $this->t('Next'),
272 '#button_type' => 'primary',
273 // No regular submit-handler. This form only works via JavaScript.
274 '#submit' => array(),
276 'callback' => '::submitSelectStep',
290 * Form constructor for the entity review step.
293 * An associative array containing the structure of the form.
294 * @param \Drupal\Core\Form\FormStateInterface $form_state
295 * The current state of the form.
298 * The form structure.
300 public function buildReviewStep(array &$form, FormStateInterface $form_state) {
301 /** @var \Drupal\Core\Entity\EntityInterface $entity */
302 $entity = $form_state->get('entity');
304 $form['#title'] = $this->t('Review selected @type', array('@type' => $entity->getEntityType()->getLowercaseLabel()));
306 $form['selection'] = [
307 '#markup' => $entity->label(),
310 $form['actions'] = array(
311 '#type' => 'actions',
314 $form['actions']['back'] = array(
316 '#value' => $this->t('Replace selection'),
317 // No regular submit-handler. This form only works via JavaScript.
318 '#submit' => array(),
320 'callback' => '::submitAndShowSelect',
325 $form['actions']['save_modal'] = array(
327 '#value' => $this->t('Next'),
328 '#button_type' => 'primary',
329 // No regular submit-handler. This form only works via JavaScript.
330 '#submit' => array(),
332 'callback' => '::submitAndShowEmbed',
346 * Form constructor for the entity embedding step.
349 * An associative array containing the structure of the form.
350 * @param \Drupal\Core\Form\FormStateInterface $form_state
351 * The current state of the form.
354 * The form structure.
356 public function buildEmbedStep(array $form, FormStateInterface $form_state) {
357 // Entity element is calculated on every AJAX request/submit. See ::buildForm().
358 $entity_element = $form_state->get('entity_element');
359 /** @var \Drupal\embed\EmbedButtonInterface $embed_button */
360 $embed_button = $form_state->get('embed_button');
361 /** @var \Drupal\editor\EditorInterface $editor */
362 $editor = $form_state->get('editor');
363 /** @var \Drupal\Core\Entity\EntityInterface $entity */
364 $entity = $form_state->get('entity');
365 $values = $form_state->getValues();
367 $form['#title'] = $this->t('Embed @type', array('@type' => $entity->getEntityType()->getLowercaseLabel()));
371 $entity_label = $entity->link();
373 catch (\Exception $e) {
374 // Construct markup of the link to the entity manually if link() fails.
375 // @see https://www.drupal.org/node/2402533
376 $entity_label = '<a href="' . $entity->url() . '">' . $entity->label() . '</a>';
379 $form['entity'] = array(
381 '#title' => $this->t('Selected entity'),
382 '#markup' => $entity_label,
384 $form['attributes']['data-entity-type'] = array(
386 '#value' => $entity_element['data-entity-type'],
388 $form['attributes']['data-entity-uuid'] = array(
390 '#value' => $entity_element['data-entity-uuid'],
393 // Build the list of allowed Entity Embed Display plugins.
394 $display_plugin_options = $this->getDisplayPluginOptions($embed_button, $entity);
396 // If the currently selected display is not in the available options,
397 // use the first from the list instead. This can happen if an alter
398 // hook customizes the list based on the entity.
399 if (!isset($display_plugin_options[$entity_element['data-entity-embed-display']])) {
400 $entity_element['data-entity-embed-display'] = key($display_plugin_options);
403 // The default Entity Embed Display plugin has been deprecated by the
404 // rendered entity field formatter.
405 if ($entity_element['data-entity-embed-display'] === 'default') {
406 $entity_element['data-entity-embed-display'] = 'entity_reference:entity_reference_entity_view';
409 $form['attributes']['data-entity-embed-display'] = array(
411 '#title' => $this->t('Display as'),
412 '#options' => $display_plugin_options,
413 '#default_value' => $entity_element['data-entity-embed-display'],
416 'callback' => '::updatePluginConfigurationForm',
417 'wrapper' => 'data-entity-embed-display-settings-wrapper',
420 // Hide the selection if only one option is available.
421 '#access' => count($display_plugin_options) > 1,
423 $form['attributes']['data-entity-embed-display-settings'] = array(
424 '#type' => 'container',
425 '#prefix' => '<div id="data-entity-embed-display-settings-wrapper">',
426 '#suffix' => '</div>',
428 $form['attributes']['data-embed-button'] = array(
430 '#value' => $embed_button->id(),
432 $plugin_id = !empty($values['attributes']['data-entity-embed-display']) ? $values['attributes']['data-entity-embed-display'] : $entity_element['data-entity-embed-display'];
433 if (!empty($plugin_id)) {
434 if (is_string($entity_element['data-entity-embed-display-settings'])) {
435 $entity_element['data-entity-embed-display-settings'] = Json::decode($entity_element['data-entity-embed-display-settings']);
437 $display = $this->entityEmbedDisplayManager->createInstance($plugin_id, $entity_element['data-entity-embed-display-settings']);
438 $display->setContextValue('entity', $entity);
439 $display->setAttributes($entity_element);
440 $form['attributes']['data-entity-embed-display-settings'] += $display->buildConfigurationForm($form, $form_state);
443 // When Drupal core's filter_align is being used, the text editor may
444 // offer the ability to change the alignment.
445 if ($editor->getFilterFormat()->filters('filter_align')->status) {
446 $form['attributes']['data-align'] = array(
447 '#title' => $this->t('Align'),
450 '' => $this->t('None'),
451 'left' => $this->t('Left'),
452 'center' => $this->t('Center'),
453 'right' => $this->t('Right'),
455 '#default_value' => isset($entity_element['data-align']) ? $entity_element['data-align'] : '',
456 '#wrapper_attributes' => array('class' => array('container-inline')),
457 '#attributes' => array('class' => array('container-inline')),
461 // When Drupal core's filter_caption is being used, the text editor may
462 // offer the ability to add a caption.
463 if ($editor->getFilterFormat()->filters('filter_caption')->status) {
464 $form['attributes']['data-caption'] = array(
465 '#title' => $this->t('Caption'),
466 '#type' => 'textfield',
467 '#default_value' => isset($entity_element['data-caption']) ? Html::decodeEntities($entity_element['data-caption']) : '',
468 '#element_validate' => array('::escapeValue'),
472 $form['actions'] = array(
473 '#type' => 'actions',
475 $form['actions']['back'] = array(
477 '#value' => $this->t('Back'),
478 // No regular submit-handler. This form only works via JavaScript.
479 '#submit' => array(),
481 'callback' => !empty($this->entityBrowserSettings['display_review']) ? '::submitAndShowReview' : '::submitAndShowSelect',
485 $form['actions']['save_modal'] = array(
487 '#value' => $this->t('Embed'),
488 '#button_type' => 'primary',
489 // No regular submit-handler. This form only works via JavaScript.
490 '#submit' => array(),
492 'callback' => '::submitEmbedStep',
503 public function validateForm(array &$form, FormStateInterface $form_state) {
504 parent::validateForm($form, $form_state);
506 if ($form_state->get('step') == 'select') {
507 $this->validateSelectStep($form, $form_state);
509 elseif ($form_state->get('step') == 'embed') {
510 $this->validateEmbedStep($form, $form_state);
515 * Form validation handler for the entity selection step.
518 * An associative array containing the structure of the form.
519 * @param \Drupal\Core\Form\FormStateInterface $form_state
520 * The current state of the form.
522 public function validateSelectStep(array $form, FormStateInterface $form_state) {
523 if ($form_state->hasValue(['entity_browser', 'entities'])) {
524 $id = $form_state->getValue(['entity_browser', 'entities', 0])->id();
525 $element = $form['entity_browser'];
528 $id = trim($form_state->getValue(['entity_id']));
529 $element = $form['entity_id'];
532 $entity_type = $form_state->getValue(['attributes', 'data-entity-type']);
534 if ($entity = $this->entityTypeManager->getStorage($entity_type)->load($id)) {
535 if (!$entity->access('view')) {
536 $form_state->setError($element, $this->t('Unable to access @type entity @id.', array('@type' => $entity_type, '@id' => $id)));
539 if ($uuid = $entity->uuid()) {
540 $form_state->setValueForElement($form['attributes']['data-entity-uuid'], $uuid);
543 $form_state->setError($element, $this->t('Cannot embed @type entity @id because it does not have a UUID.', array('@type' => $entity_type, '@id' => $id)));
546 // Ensure that at least one Entity Embed Display plugin is present
547 // before proceeding to the next step. Raise an error otherwise.
548 $embed_button = $form_state->get('embed_button');
549 $display_plugin_options = $this->getDisplayPluginOptions($embed_button, $entity);
550 // If no plugin is available after taking the intersection, raise error.
551 // Also log an exception.
552 if (empty($display_plugin_options)) {
553 $form_state->setError($element, $this->t('No display options available for the selected entity. Please select another entity.'));
554 $this->logger('entity_embed')->warning('No display options available for "@type:" entity "@id" while embedding using button "@button". Please ensure that at least one Entity Embed Display plugin is allowed for this embed button which is available for this entity.', array('@type' => $entity_type, '@id' => $entity->id(), '@button' => $embed_button->id()));
559 $form_state->setError($element, $this->t('Unable to load @type entity @id.', array('@type' => $entity_type, '@id' => $id)));
564 * Form validation handler for the entity embedding step.
567 * An associative array containing the structure of the form.
568 * @param \Drupal\Core\Form\FormStateInterface $form_state
569 * The current state of the form.
571 public function validateEmbedStep(array $form, FormStateInterface $form_state) {
572 // Validate configuration forms for the Entity Embed Display plugin used.
573 $entity_element = $form_state->getValue('attributes');
574 $entity = $this->entityTypeManager->getStorage($entity_element['data-entity-type'])
575 ->loadByProperties(['uuid' => $entity_element['data-entity-uuid']]);
576 $entity = current($entity) ?: NULL;
577 $plugin_id = $entity_element['data-entity-embed-display'];
578 $plugin_settings = !empty($entity_element['data-entity-embed-display-settings']) ? $entity_element['data-entity-embed-display-settings'] : array();
579 $display = $this->entityEmbedDisplayManager->createInstance($plugin_id, $plugin_settings);
580 $display->setContextValue('entity', $entity);
581 $display->setAttributes($entity_element);
582 $display->validateConfigurationForm($form, $form_state);
588 public function submitForm(array &$form, FormStateInterface $form_state) {}
591 * Form submission handler to update the plugin configuration form.
595 * @param \Drupal\Core\Form\FormStateInterface $form_state
598 public function updatePluginConfigurationForm(array &$form, FormStateInterface $form_state) {
599 return $form['attributes']['data-entity-embed-display-settings'];
603 * Form submission handler to to another step of the form.
607 * @param \Drupal\Core\Form\FormStateInterface $form_state
610 * @return \Drupal\Core\Ajax\AjaxResponse
613 public function submitStep(array &$form, FormStateInterface $form_state, $step) {
614 $response = new AjaxResponse();
616 $form_state->set('step', $step);
617 $form_state->setRebuild(TRUE);
618 $rebuild_form = $this->formBuilder->rebuildForm('entity_embed_dialog', $form_state, $form);
619 unset($rebuild_form['#prefix'], $rebuild_form['#suffix']);
620 $response->addCommand(new HtmlCommand('#entity-embed-dialog-form', $rebuild_form));
621 $response->addCommand(new SetDialogTitleCommand('', $rebuild_form['#title']));
627 * Form submission handler for the entity selection step.
629 * On success will send the user to the next step of the form to select the
630 * embed display settings. On form errors, this will rebuild the form and
631 * display the error messages.
635 * @param \Drupal\Core\Form\FormStateInterface $form_state
638 * @return \Drupal\Core\Ajax\AjaxResponse
641 public function submitSelectStep(array &$form, FormStateInterface $form_state) {
642 $response = new AjaxResponse();
644 // Display errors in form, if any.
645 if ($form_state->hasAnyErrors()) {
646 unset($form['#prefix'], $form['#suffix']);
647 $form['status_messages'] = array(
648 '#type' => 'status_messages',
651 $response->addCommand(new HtmlCommand('#entity-embed-dialog-form', $form));
654 $form_state->set('step', !empty($this->entityBrowserSettings['display_review']) ? 'review' : 'embed');
655 $form_state->setRebuild(TRUE);
656 $rebuild_form = $this->formBuilder->rebuildForm('entity_embed_dialog', $form_state, $form);
657 unset($rebuild_form['#prefix'], $rebuild_form['#suffix']);
658 $response->addCommand(new HtmlCommand('#entity-embed-dialog-form', $rebuild_form));
659 $response->addCommand(new SetDialogTitleCommand('', $rebuild_form['#title']));
666 * Submit and show select step after submit.
670 * @param \Drupal\Core\Form\FormStateInterface $form_state
673 * @return \Drupal\Core\Ajax\AjaxResponse
676 public function submitAndShowSelect(array &$form, FormStateInterface $form_state) {
677 return $this->submitStep($form, $form_state, 'select');
681 * Submit and show review step after submit.
685 * @param \Drupal\Core\Form\FormStateInterface $form_state
688 * @return \Drupal\Core\Ajax\AjaxResponse
691 public function submitAndShowReview(array &$form, FormStateInterface $form_state) {
692 return $this->submitStep($form, $form_state, 'review');
696 * Submit and show embed step after submit.
700 * @param \Drupal\Core\Form\FormStateInterface $form_state
703 * @return \Drupal\Core\Ajax\AjaxResponse
706 public function submitAndShowEmbed(array $form, FormStateInterface $form_state) {
707 return $this->submitStep($form, $form_state, 'embed');
711 * Form submission handler for the entity embedding step.
713 * On success this will submit the command to save the embedded entity with
714 * the configured display settings to the WYSIWYG element, and then close the
715 * modal dialog. On form errors, this will rebuild the form and display the
719 * An associative array containing the structure of the form.
720 * @param FormStateInterface $form_state
721 * An associative array containing the current state of the form.
723 * @return \Drupal\Core\Ajax\AjaxResponse
726 public function submitEmbedStep(array &$form, FormStateInterface $form_state) {
727 $response = new AjaxResponse();
729 // Submit configuration form the selected Entity Embed Display plugin.
730 $entity_element = $form_state->getValue('attributes');
731 $entity = $this->entityTypeManager->getStorage($entity_element['data-entity-type'])
732 ->loadByProperties(['uuid' => $entity_element['data-entity-uuid']]);
733 $entity = current($entity);
734 $plugin_id = $entity_element['data-entity-embed-display'];
735 $plugin_settings = !empty($entity_element['data-entity-embed-display-settings']) ? $entity_element['data-entity-embed-display-settings'] : array();
736 $display = $this->entityEmbedDisplayManager->createInstance($plugin_id, $plugin_settings);
737 $display->setContextValue('entity', $entity);
738 $display->setAttributes($entity_element);
739 $display->submitConfigurationForm($form, $form_state);
741 $values = $form_state->getValues();
742 // Display errors in form, if any.
743 if ($form_state->hasAnyErrors()) {
744 unset($form['#prefix'], $form['#suffix']);
745 $form['status_messages'] = array(
746 '#type' => 'status_messages',
749 $response->addCommand(new HtmlCommand('#entity-embed-dialog-form', $form));
752 // Serialize entity embed settings to JSON string.
753 if (!empty($values['attributes']['data-entity-embed-display-settings'])) {
754 $values['attributes']['data-entity-embed-display-settings'] = Json::encode($values['attributes']['data-entity-embed-display-settings']);
757 // Filter out empty attributes.
758 $values['attributes'] = array_filter($values['attributes'], function($value) {
759 return (bool) Unicode::strlen((string) $value);
762 // Allow other modules to alter the values before getting submitted to the WYSIWYG.
763 $this->moduleHandler->alter('entity_embed_values', $values, $entity, $display, $form_state);
765 $response->addCommand(new EditorDialogSave($values));
766 $response->addCommand(new CloseModalDialogCommand());
773 * Form element validation handler; Escapes the value an element.
775 * This should be used for any element in the embed form which may contain
776 * HTML that should be serialized as an attribute element on the embed.
778 public static function escapeValue($element, FormStateInterface $form_state) {
779 if ($value = trim($element['#value'])) {
780 $form_state->setValueForElement($element, Html::escape($value));
785 * Returns the allowed Entity Embed Display plugins given an embed button and
788 * @param \Drupal\embed\EmbedButtonInterface $embed_button
790 * @param \Drupal\Core\Entity\EntityInterface $entity
794 * List of allowed Entity Embed Display plugins.
796 public function getDisplayPluginOptions(EmbedButtonInterface $embed_button, EntityInterface $entity) {
797 $plugins = $this->entityEmbedDisplayManager->getDefinitionOptionsForEntity($entity);
799 if ($allowed_plugins = $embed_button->getTypeSetting('display_plugins')) {
800 $plugins = array_intersect_key($plugins, array_flip($allowed_plugins));
808 * Registers JS callback that gets entities from entity browser and updates
809 * form values accordingly.
811 public function registerJSCallback(RegisterJSCallbacks $event) {
812 if ($event->getBrowserID() == $this->entityBrowser->id()) {
813 $event->registerCallback('Drupal.entityEmbedDialog.selectionCompleted');
818 * Load the current entity browser and its settings from the form state.
820 * @param \Drupal\Core\Form\FormStateInterface $form_state
822 protected function loadEntityBrowser(FormStateInterface $form_state) {
823 $this->entityBrowser = NULL;
824 $this->entityBrowserSettings = [];
826 /** @var \Drupal\embed\EmbedButtonInterface $embed_button */
827 $embed_button = $form_state->get('embed_button');
829 if ($embed_button && $entity_browser_id = $embed_button->getTypePlugin()->getConfigurationValue('entity_browser')) {
830 $this->entityBrowser = $this->entityTypeManager->getStorage('entity_browser')->load($entity_browser_id);
831 $this->entityBrowserSettings = $embed_button->getTypePlugin()->getConfigurationValue('entity_browser_settings');