1<?php
2
3namespace Drupal\media\EventSubscriber;
4
5use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
6use Drupal\Core\Config\ConfigCrudEvent;
7use Drupal\Core\Config\ConfigEvents;
8use Drupal\Core\Entity\EntityTypeManagerInterface;
9use Drupal\Core\Routing\RouteBuilderInterface;
10use Symfony\Component\EventDispatcher\EventSubscriberInterface;
11
12/**
13 * Listens to the config save event for media.settings.
14 */
15class MediaConfigSubscriber implements EventSubscriberInterface {
16
17  /**
18   * The route builder.
19   *
20   * @var \Drupal\Core\Routing\RouteBuilderInterface
21   */
22  protected $routeBuilder;
23
24  /**
25   * The cache tags invalidator.
26   *
27   * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface
28   */
29  protected $cacheTagsInvalidator;
30
31  /**
32   * The entity type manager.
33   *
34   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
35   */
36  protected $entityTypeManager;
37
38  /**
39   * Constructs the MediaConfigSubscriber.
40   *
41   * @param \Drupal\Core\Routing\RouteBuilderInterface $router_builder
42   *   The route builder.
43   * @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $cache_tags_invalidator
44   *   The cache tags invalidator.
45   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
46   *   The entity type manager.
47   */
48  public function __construct(RouteBuilderInterface $router_builder, CacheTagsInvalidatorInterface $cache_tags_invalidator, EntityTypeManagerInterface $entity_type_manager) {
49    $this->routeBuilder = $router_builder;
50    $this->cacheTagsInvalidator = $cache_tags_invalidator;
51    $this->entityTypeManager = $entity_type_manager;
52  }
53
54  /**
55   * Updates entity type definitions and ensures routes are rebuilt when needed.
56   *
57   * @param \Drupal\Core\Config\ConfigCrudEvent $event
58   *   The ConfigCrudEvent to process.
59   */
60  public function onSave(ConfigCrudEvent $event) {
61    $saved_config = $event->getConfig();
62    if ($saved_config->getName() === 'media.settings' && $event->isChanged('standalone_url')) {
63      $this->cacheTagsInvalidator->invalidateTags([
64        // The configuration change triggers entity type definition changes,
65        // which in turn triggers routes to appear or disappear.
66        // @see media_entity_type_alter()
67        'entity_types',
68        // The 'rendered' cache tag needs to be explicitly invalidated to ensure
69        // that all links to Media entities are re-rendered. Ideally, this would
70        // not be necessary; invalidating the 'entity_types' cache tag should be
71        // sufficient. But that cache tag would then need to be on nearly
72        // everything, resulting in excessive complexity. We prefer pragmatism.
73        'rendered',
74      ]);
75      // @todo Remove this when invalidating the 'entity_types' cache tag is
76      // respected by the entity type plugin manager. See
77      // https://www.drupal.org/project/drupal/issues/3001284 and
78      // https://www.drupal.org/project/drupal/issues/3013659.
79      $this->entityTypeManager->clearCachedDefinitions();
80      $this->routeBuilder->setRebuildNeeded();
81    }
82  }
83
84  /**
85   * {@inheritdoc}
86   */
87  public static function getSubscribedEvents() {
88    $events[ConfigEvents::SAVE][] = ['onSave'];
89    return $events;
90  }
91
92}
93