Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Core\EventSubscriber;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Core\Cache\CacheableMetadata;
|
Chris@0
|
6 use Drupal\Core\Cache\CacheableResponseInterface;
|
Chris@0
|
7 use Drupal\Core\Session\AccountInterface;
|
Chris@0
|
8 use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
Chris@0
|
9 use Symfony\Component\HttpKernel\KernelEvents;
|
Chris@0
|
10 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
Chris@0
|
11
|
Chris@0
|
12 /**
|
Chris@0
|
13 * Response subscriber to handle finished responses for the anonymous user.
|
Chris@0
|
14 */
|
Chris@0
|
15 class AnonymousUserResponseSubscriber implements EventSubscriberInterface {
|
Chris@0
|
16
|
Chris@0
|
17 /**
|
Chris@0
|
18 * The current user.
|
Chris@0
|
19 *
|
Chris@0
|
20 * @var \Drupal\Core\Session\AccountInterface
|
Chris@0
|
21 */
|
Chris@0
|
22 protected $currentUser;
|
Chris@0
|
23
|
Chris@0
|
24 /**
|
Chris@0
|
25 * Constructs an AnonymousUserResponseSubscriber object.
|
Chris@0
|
26 *
|
Chris@0
|
27 * @param \Drupal\Core\Session\AccountInterface $current_user
|
Chris@0
|
28 * The current user.
|
Chris@0
|
29 */
|
Chris@0
|
30 public function __construct(AccountInterface $current_user) {
|
Chris@0
|
31 $this->currentUser = $current_user;
|
Chris@0
|
32 }
|
Chris@0
|
33
|
Chris@0
|
34 /**
|
Chris@0
|
35 * Adds a cache tag if the 'user.permissions' cache context is present.
|
Chris@0
|
36 *
|
Chris@0
|
37 * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
|
Chris@0
|
38 * The event to process.
|
Chris@0
|
39 */
|
Chris@0
|
40 public function onRespond(FilterResponseEvent $event) {
|
Chris@0
|
41 if (!$event->isMasterRequest()) {
|
Chris@0
|
42 return;
|
Chris@0
|
43 }
|
Chris@0
|
44
|
Chris@0
|
45 if (!$this->currentUser->isAnonymous()) {
|
Chris@0
|
46 return;
|
Chris@0
|
47 }
|
Chris@0
|
48
|
Chris@0
|
49 $response = $event->getResponse();
|
Chris@0
|
50 if (!$response instanceof CacheableResponseInterface) {
|
Chris@0
|
51 return;
|
Chris@0
|
52 }
|
Chris@0
|
53
|
Chris@0
|
54 // The 'user.permissions' cache context ensures that if the permissions for
|
Chris@0
|
55 // a role are modified, users are not served stale render cache content.
|
Chris@0
|
56 // But, when entire responses are cached in reverse proxies, the value for
|
Chris@0
|
57 // the cache context is never calculated, causing the stale response to not
|
Chris@0
|
58 // be invalidated. Therefore, when varying by permissions and the current
|
Chris@0
|
59 // user is the anonymous user, also add the cache tag for the 'anonymous'
|
Chris@0
|
60 // role.
|
Chris@0
|
61 if (in_array('user.permissions', $response->getCacheableMetadata()->getCacheContexts())) {
|
Chris@0
|
62 $per_permissions_response_for_anon = new CacheableMetadata();
|
Chris@0
|
63 $per_permissions_response_for_anon->setCacheTags(['config:user.role.anonymous']);
|
Chris@0
|
64 $response->addCacheableDependency($per_permissions_response_for_anon);
|
Chris@0
|
65 }
|
Chris@0
|
66 }
|
Chris@0
|
67
|
Chris@0
|
68 /**
|
Chris@0
|
69 * Registers the methods in this class that should be listeners.
|
Chris@0
|
70 *
|
Chris@0
|
71 * @return array
|
Chris@0
|
72 * An array of event listener definitions.
|
Chris@0
|
73 */
|
Chris@0
|
74 public static function getSubscribedEvents() {
|
Chris@0
|
75 // Priority 5, so that it runs before FinishResponseSubscriber, but after
|
Chris@0
|
76 // event subscribers that add the associated cacheability metadata (which
|
Chris@0
|
77 // have priority 10). This one is conditional, so must run after those.
|
Chris@0
|
78 $events[KernelEvents::RESPONSE][] = ['onRespond', 5];
|
Chris@0
|
79 return $events;
|
Chris@0
|
80 }
|
Chris@0
|
81
|
Chris@0
|
82 }
|