.../media_library/media_library.services.yml | 6 +- .../media_library/src/Event/MediaLibraryEvents.php | 29 -------- .../src/Event/MediaLibrarySelectionEvent.php | 85 ---------------------- .../MediaLibraryWidgetSubscriber.php | 50 ------------- .../modules/media_library/src/Form/AddFormBase.php | 42 +++++------ .../media_library/src/Form/FileUploadForm.php | 12 +-- core/modules/media_library/src/Form/OEmbedForm.php | 12 +-- .../src/MediaLibraryFieldWidgetOpener.php | 43 +++++++++++ .../src/MediaLibraryOpenerInterface.php | 46 ++++++++++++ .../media_library/src/MediaLibraryState.php | 6 +- .../Field/FieldWidget/MediaLibraryWidget.php | 54 ++------------ .../Plugin/views/field/MediaLibrarySelectForm.php | 18 ++--- 12 files changed, 140 insertions(+), 263 deletions(-) diff --git a/core/modules/media_library/media_library.services.yml b/core/modules/media_library/media_library.services.yml index 87958dc040..1cd3af98c5 100644 --- a/core/modules/media_library/media_library.services.yml +++ b/core/modules/media_library/media_library.services.yml @@ -2,11 +2,9 @@ services: media_library.ui_builder: class: Drupal\media_library\MediaLibraryUiBuilder arguments: ['@entity_type.manager', '@request_stack', '@views.executable', '@form_builder'] - media_library.widget_event_subscriber: - class: Drupal\media_library\EventSubscriber\MediaLibraryWidgetSubscriber - tags: - - { name: event_subscriber } media_library.route_subscriber: class: Drupal\media_library\Routing\RouteSubscriber tags: - { name: event_subscriber } + media_library.field_widget: + class: Drupal\media_library\MediaLibraryFieldWidgetOpener diff --git a/core/modules/media_library/src/Event/MediaLibraryEvents.php b/core/modules/media_library/src/Event/MediaLibraryEvents.php deleted file mode 100644 index 5de86995ad..0000000000 --- a/core/modules/media_library/src/Event/MediaLibraryEvents.php +++ /dev/null @@ -1,29 +0,0 @@ -state = $state; - $this->selectedIds = $selected_ids; - $this->response = new AjaxResponse(); - } - - /** - * Gets the media library state. - * - * @return \Drupal\media_library\MediaLibraryState - * The media library state. - */ - public function getState() { - return $this->state; - } - - /** - * Gets the selected media IDs. - * - * @return int[] - * The selected media IDs. - */ - public function getSelectedIds() { - return $this->selectedIds; - } - - /** - * Gets the AJAX response. - * - * @return \Drupal\Core\Ajax\AjaxResponse - * The AJAX response. - */ - public function getResponse() { - return $this->response; - } - -} diff --git a/core/modules/media_library/src/EventSubscriber/MediaLibraryWidgetSubscriber.php b/core/modules/media_library/src/EventSubscriber/MediaLibraryWidgetSubscriber.php deleted file mode 100644 index 76e8218c12..0000000000 --- a/core/modules/media_library/src/EventSubscriber/MediaLibraryWidgetSubscriber.php +++ /dev/null @@ -1,50 +0,0 @@ -getState(); - - // We only want to respond to opener IDs of media library entity reference - // widgets. - $widget_id = MediaLibraryWidget::getFieldWidgetIdFromOpenerId($state->getOpenerId()); - if (!$widget_id) { - return; - } - - // Create a comma-separated list of media IDs, insert them in the hidden - // field of the widget, and trigger the field update via the hidden submit - // button. - $ids = implode(',', $event->getSelectedIds()); - $response = $event->getResponse(); - $response - ->addCommand(new InvokeCommand("[data-media-library-widget-value=\"$widget_id\"]", 'val', [$ids])) - ->addCommand(new InvokeCommand("[data-media-library-widget-update=\"$widget_id\"]", 'trigger', ['mousedown'])); - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents() { - $events[MediaLibraryEvents::SELECTION][] = ['onMediaLibrarySelection']; - return $events; - } - -} diff --git a/core/modules/media_library/src/Form/AddFormBase.php b/core/modules/media_library/src/Form/AddFormBase.php index 5a46494af3..7ca7c49ef4 100644 --- a/core/modules/media_library/src/Form/AddFormBase.php +++ b/core/modules/media_library/src/Form/AddFormBase.php @@ -6,6 +6,7 @@ use Drupal\Core\Ajax\CloseDialogCommand; use Drupal\Core\Ajax\InvokeCommand; use Drupal\Core\Ajax\ReplaceCommand; +use Drupal\Core\DependencyInjection\ClassResolverInterface; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; @@ -15,11 +16,8 @@ use Drupal\media\MediaInterface; use Drupal\media\MediaTypeInterface; use Drupal\media_library\Ajax\UpdateSelectionCommand; -use Drupal\media_library\Event\MediaLibraryEvents; -use Drupal\media_library\Event\MediaLibrarySelectionEvent; use Drupal\media_library\MediaLibraryUiBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * Provides a base class for creating media items from within the media library. @@ -60,11 +58,11 @@ abstract class AddFormBase extends FormBase { protected $viewBuilder; /** - * The event dispatcher. + * The class resolver. * - * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface + * @var \Drupal\Core\DependencyInjection\ClassResolverInterface */ - protected $eventDispatcher; + protected $classResolver; /** * Constructs a AddFormBase object. @@ -73,18 +71,18 @@ abstract class AddFormBase extends FormBase { * The entity type manager. * @param \Drupal\media_library\MediaLibraryUiBuilder $library_ui_builder * The media library UI builder. - * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface|null $event_dispatcher - * (optional) The event dispatcher. + * @param \Drupal\Core\DependencyInjection\ClassResolverInterface|null $class_resolver + * (optional) The class resolver. */ - public function __construct(EntityTypeManagerInterface $entity_type_manager, MediaLibraryUiBuilder $library_ui_builder, EventDispatcherInterface $event_dispatcher = NULL) { + public function __construct(EntityTypeManagerInterface $entity_type_manager, MediaLibraryUiBuilder $library_ui_builder, ClassResolverInterface $class_resolver = NULL) { $this->entityTypeManager = $entity_type_manager; $this->libraryUiBuilder = $library_ui_builder; $this->viewBuilder = $this->entityTypeManager->getViewBuilder('media'); - if (!$event_dispatcher) { - @trigger_error('The event_dispatcher service must be passed to AddFormBase::__construct(), it is required before Drupal 9.0.0.', E_USER_DEPRECATED); - $event_dispatcher = \Drupal::service('event_dispatcher'); + if (!$class_resolver) { + @trigger_error('The class_resolver service must be passed to AddFormBase::__construct(), it is required before Drupal 9.0.0.', E_USER_DEPRECATED); + $class_resolver = \Drupal::service('class_resolver'); } - $this->eventDispatcher = $event_dispatcher; + $this->classResolver = $class_resolver; } /** @@ -94,7 +92,7 @@ public static function create(ContainerInterface $container) { return new static( $container->get('entity_type.manager'), $container->get('media_library.ui_builder'), - $container->get('event_dispatcher') + $container->get('class_resolver') ); } @@ -748,14 +746,14 @@ public function updateWidget(array &$form, FormStateInterface $form_state) { return $media->id(); }, $this->getCurrentMediaItems($form_state)); - // Dispatch an event to allow openers to handle the selection. - $selection_event = new MediaLibrarySelectionEvent($this->getMediaLibraryState($form_state), $current_media_ids); - $this->eventDispatcher->dispatch(MediaLibraryEvents::SELECTION, $selection_event); - - // Return the AJAX response to handle the selection and close the media - // library dialog. - return $selection_event->getResponse() - ->addCommand(new CloseDialogCommand()); + // Allow the opener service to handle the selection. + $media_library_state = $this->getMediaLibraryState($form_state); + $service_id = $media_library_state->getOpenerId(); + $response = $this->classResolver->getInstanceFromDefinition($service_id)->respondToSelection( + $current_media_ids, + $media_library_state + ); + return $response->addCommand(new CloseDialogCommand()); } /** diff --git a/core/modules/media_library/src/Form/FileUploadForm.php b/core/modules/media_library/src/Form/FileUploadForm.php index 391e61d14a..67bd7ce489 100644 --- a/core/modules/media_library/src/Form/FileUploadForm.php +++ b/core/modules/media_library/src/Form/FileUploadForm.php @@ -2,6 +2,7 @@ namespace Drupal\media_library\Form; +use Drupal\Core\DependencyInjection\ClassResolverInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; @@ -20,7 +21,6 @@ use Drupal\media\MediaTypeInterface; use Drupal\media_library\MediaLibraryUiBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * Creates a form to create media entities from uploaded files. @@ -66,11 +66,11 @@ class FileUploadForm extends AddFormBase { * The renderer service. * @param \Drupal\Core\File\FileSystemInterface $file_system * The file system service. - * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface|null $event_dispatcher - * (optional) The event dispatcher. + * @param \Drupal\Core\DependencyInjection\ClassResolverInterface|null $class_resolver + * (optional) The class resolver. */ - public function __construct(EntityTypeManagerInterface $entity_type_manager, MediaLibraryUiBuilder $library_ui_builder, ElementInfoManagerInterface $element_info, RendererInterface $renderer, FileSystemInterface $file_system, EventDispatcherInterface $event_dispatcher = NULL) { - parent::__construct($entity_type_manager, $library_ui_builder, $event_dispatcher); + public function __construct(EntityTypeManagerInterface $entity_type_manager, MediaLibraryUiBuilder $library_ui_builder, ElementInfoManagerInterface $element_info, RendererInterface $renderer, FileSystemInterface $file_system, ClassResolverInterface $class_resolver = NULL) { + parent::__construct($entity_type_manager, $library_ui_builder, $class_resolver); $this->elementInfo = $element_info; $this->renderer = $renderer; $this->fileSystem = $file_system; @@ -86,7 +86,7 @@ public static function create(ContainerInterface $container) { $container->get('element_info'), $container->get('renderer'), $container->get('file_system'), - $container->get('event_dispatcher') + $container->get('class_resolver') ); } diff --git a/core/modules/media_library/src/Form/OEmbedForm.php b/core/modules/media_library/src/Form/OEmbedForm.php index 44df2ee064..68cf73e35a 100644 --- a/core/modules/media_library/src/Form/OEmbedForm.php +++ b/core/modules/media_library/src/Form/OEmbedForm.php @@ -2,6 +2,7 @@ namespace Drupal\media_library\Form; +use Drupal\Core\DependencyInjection\ClassResolverInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\FormBuilderInterface; use Drupal\Core\Form\FormStateInterface; @@ -12,7 +13,6 @@ use Drupal\media\Plugin\media\Source\OEmbedInterface; use Drupal\media_library\MediaLibraryUiBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * Creates a form to create media entities from oEmbed URLs. @@ -49,11 +49,11 @@ class OEmbedForm extends AddFormBase { * The oEmbed URL resolver service. * @param \Drupal\media\OEmbed\ResourceFetcherInterface $resource_fetcher * The oEmbed resource fetcher service. - * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface|null $event_dispatcher - * (optional) The event dispatcher. + * @param \Drupal\Core\DependencyInjection\ClassResolverInterface|null $class_resolver + * (optional) The class resolver. */ - public function __construct(EntityTypeManagerInterface $entity_type_manager, MediaLibraryUiBuilder $library_ui_builder, UrlResolverInterface $url_resolver, ResourceFetcherInterface $resource_fetcher, EventDispatcherInterface $event_dispatcher = NULL) { - parent::__construct($entity_type_manager, $library_ui_builder, $event_dispatcher); + public function __construct(EntityTypeManagerInterface $entity_type_manager, MediaLibraryUiBuilder $library_ui_builder, UrlResolverInterface $url_resolver, ResourceFetcherInterface $resource_fetcher, ClassResolverInterface $class_resolver = NULL) { + parent::__construct($entity_type_manager, $library_ui_builder, $class_resolver); $this->urlResolver = $url_resolver; $this->resourceFetcher = $resource_fetcher; } @@ -67,7 +67,7 @@ public static function create(ContainerInterface $container) { $container->get('media_library.ui_builder'), $container->get('media.oembed.url_resolver'), $container->get('media.oembed.resource_fetcher'), - $container->get('event_dispatcher') + $container->get('class_resolver') ); } diff --git a/core/modules/media_library/src/MediaLibraryFieldWidgetOpener.php b/core/modules/media_library/src/MediaLibraryFieldWidgetOpener.php new file mode 100644 index 0000000000..a6422aa557 --- /dev/null +++ b/core/modules/media_library/src/MediaLibraryFieldWidgetOpener.php @@ -0,0 +1,43 @@ +get('field_widget_id'); + if (!$widget_id) { + return new \UnexpectedValueException(); + } + + // Create a comma-separated list of media IDs, insert them in the hidden + // field of the widget, and trigger the field update via the hidden submit + // button. + $ids = implode(',', $selected_ids); + $response + ->addCommand(new InvokeCommand("[data-media-library-widget-value=\"$widget_id\"]", 'val', [$ids])) + ->addCommand(new InvokeCommand("[data-media-library-widget-update=\"$widget_id\"]", 'trigger', ['mousedown'])); + + return $response; + } + +} diff --git a/core/modules/media_library/src/MediaLibraryOpenerInterface.php b/core/modules/media_library/src/MediaLibraryOpenerInterface.php new file mode 100644 index 0000000000..6245534063 --- /dev/null +++ b/core/modules/media_library/src/MediaLibraryOpenerInterface.php @@ -0,0 +1,46 @@ +get('media_library_opener_id'); diff --git a/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php b/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php index 8805e7537c..5d7c72477d 100644 --- a/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php +++ b/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php @@ -473,13 +473,12 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen // Create a new media library URL with the correct state parameters. $selected_type_id = reset($allowed_media_type_ids); $remaining = $cardinality_unlimited ? FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED : $remaining; - // Create a unique opener ID with a fixed prefix for entity reference field - // widgets. The opener ID could be used to check access to the media library - // and used by the media library select/add forms to add the selected/added - // media items to the widget. - $opener_id = 'widget:' . $field_widget_id; - - $state = MediaLibraryState::create($opener_id, $allowed_media_type_ids, $selected_type_id, $remaining); + $state = MediaLibraryState::create('media_library.field_widget', $allowed_media_type_ids, $selected_type_id, $remaining); + // This particular media library opener needs some extra metadata for its + // \Drupal\media_library\MediaLibraryOpenerInterface::getSelectionResponse() + // to be able to target the element whose 'data-media-library-widget-value' + // attribute is the same as $field_widget_id. + $state->set('field_widget_id', $field_widget_id); // Add a button that will load the Media library in a modal using AJAX. $element['media_library_open_button'] = [ @@ -898,45 +897,4 @@ protected static function setFieldState(array $element, FormStateInterface $form static::setWidgetState($element['#field_parents'], $element['#field_name'], $form_state, $field_state); } - /** - * Gets the field name from an opener ID. - * - * @param string $opener_id - * The opener ID of the media library. - * - * @return string|null - * The field name or NULL if the opener ID is not valid for the widget. - */ - public static function getFieldNameFromOpenerId($opener_id) { - $widget_id = static::getFieldWidgetIdFromOpenerId($opener_id); - - if (!$widget_id) { - return NULL; - } - - list($field_name) = explode(':', $widget_id); - return $field_name; - } - - /** - * Gets the widget ID from an opener ID. - * - * @param string $opener_id - * The opener ID of the media library. - * - * @return string|null - * The widget ID or NULL if the opener ID is not valid for the widget. - * - * @see \Drupal\media_library\MediaLibraryState - */ - public static function getFieldWidgetIdFromOpenerId($opener_id) { - // Media library widget IDs are always prefixed with 'widget:' in the opener - // ID of the media library state. - // @see ::formElement() - if (preg_match('/^widget:([a-z0-9\.:_-]+)$/', $opener_id, $matches)) { - return $matches[1]; - } - return NULL; - } - } diff --git a/core/modules/media_library/src/Plugin/views/field/MediaLibrarySelectForm.php b/core/modules/media_library/src/Plugin/views/field/MediaLibrarySelectForm.php index 212aefdef7..689960827c 100644 --- a/core/modules/media_library/src/Plugin/views/field/MediaLibrarySelectForm.php +++ b/core/modules/media_library/src/Plugin/views/field/MediaLibrarySelectForm.php @@ -6,8 +6,6 @@ use Drupal\Core\Form\FormBuilderInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; -use Drupal\media_library\Event\MediaLibraryEvents; -use Drupal\media_library\Event\MediaLibrarySelectionEvent; use Drupal\media_library\MediaLibraryState; use Drupal\views\Plugin\views\field\FieldPluginBase; use Drupal\views\Render\ViewsRenderPipelineMarkup; @@ -128,14 +126,14 @@ public static function updateWidget(array &$form, FormStateInterface $form_state $field_id = $form_state->getTriggeringElement()['#field_id']; $selected_ids = array_filter(explode(',', $form_state->getValue($field_id, []))); - // Dispatch an event to allow openers to handle the selection. - $selection_event = new MediaLibrarySelectionEvent(MediaLibraryState::fromRequest($form_state->get('view')->getRequest()), $selected_ids); - \Drupal::service('event_dispatcher')->dispatch(MediaLibraryEvents::SELECTION, $selection_event); - - // Return the AJAX response to handle the selection and close the media - // library dialog. - return $selection_event->getResponse() - ->addCommand(new CloseDialogCommand()); + // Allow the opener service to handle the selection. + $media_library_state = MediaLibraryState::fromRequest($form_state->get('view')->getRequest()); + $service_id = $media_library_state->getOpenerId(); + $response = \Drupal::service($service_id)->respondToSelection( + $selected_ids, + $media_library_state + ); + return $response->addCommand(new CloseDialogCommand()); } /**