comparison core/lib/Drupal/Core/Routing/RoutePreloader.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4c8ae668cc8c
1 <?php
2
3 namespace Drupal\Core\Routing;
4
5 use Drupal\Core\Cache\Cache;
6 use Drupal\Core\Cache\CacheBackendInterface;
7 use Drupal\Core\State\StateInterface;
8 use Symfony\Component\EventDispatcher\Event;
9 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
10 use Symfony\Component\HttpKernel\Event\KernelEvent;
11 use Symfony\Component\HttpKernel\KernelEvents;
12
13 /**
14 * Defines a class which preloads non-admin routes.
15 *
16 * On an actual site we want to avoid too many database queries so we build a
17 * list of all routes which most likely appear on the actual site, which are all
18 * HTML routes not starting with "/admin".
19 */
20 class RoutePreloader implements EventSubscriberInterface {
21
22 /**
23 * The route provider.
24 *
25 * @var \Drupal\Core\Routing\RouteProviderInterface|\Drupal\Core\Routing\PreloadableRouteProviderInterface
26 */
27 protected $routeProvider;
28
29 /**
30 * The state key value store.
31 *
32 * @var \Drupal\Core\State\StateInterface
33 */
34 protected $state;
35
36 /**
37 * Contains the non-admin routes while rebuilding the routes.
38 *
39 * @var array
40 */
41 protected $nonAdminRoutesOnRebuild = [];
42
43 /**
44 * The cache backend used to skip the state loading.
45 *
46 * @var \Drupal\Core\Cache\CacheBackendInterface
47 */
48 protected $cache;
49
50 /**
51 * Constructs a new RoutePreloader.
52 *
53 * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
54 * The route provider.
55 * @param \Drupal\Core\State\StateInterface $state
56 * The state key value store.
57 * @param \Drupal\Core\Cache\CacheBackendInterface $cache
58 */
59 public function __construct(RouteProviderInterface $route_provider, StateInterface $state, CacheBackendInterface $cache) {
60 $this->routeProvider = $route_provider;
61 $this->state = $state;
62 $this->cache = $cache;
63 }
64
65 /**
66 * Loads all non-admin routes right before the actual page is rendered.
67 *
68 * @param \Symfony\Component\HttpKernel\Event\KernelEvent $event
69 * The event to process.
70 */
71 public function onRequest(KernelEvent $event) {
72 // Only preload on normal HTML pages, as they will display menu links.
73 if ($this->routeProvider instanceof PreloadableRouteProviderInterface && $event->getRequest()->getRequestFormat() == 'html') {
74
75 // Ensure that the state query is cached to skip the database query, if
76 // possible.
77 $key = 'routing.non_admin_routes';
78 if ($cache = $this->cache->get($key)) {
79 $routes = $cache->data;
80 }
81 else {
82 $routes = $this->state->get($key, []);
83 $this->cache->set($key, $routes, Cache::PERMANENT, ['routes']);
84 }
85
86 if ($routes) {
87 // Preload all the non-admin routes at once.
88 $this->routeProvider->preLoadRoutes($routes);
89 }
90 }
91 }
92
93 /**
94 * Alters existing routes for a specific collection.
95 *
96 * @param \Drupal\Core\Routing\RouteBuildEvent $event
97 * The route build event.
98 */
99 public function onAlterRoutes(RouteBuildEvent $event) {
100 $collection = $event->getRouteCollection();
101 foreach ($collection->all() as $name => $route) {
102 if (strpos($route->getPath(), '/admin/') !== 0 && $route->getPath() != '/admin') {
103 $this->nonAdminRoutesOnRebuild[] = $name;
104 }
105 }
106 $this->nonAdminRoutesOnRebuild = array_unique($this->nonAdminRoutesOnRebuild);
107 }
108
109 /**
110 * Store the non admin routes in state when the route building is finished.
111 *
112 * @param \Symfony\Component\EventDispatcher\Event $event
113 * The route finish event.
114 */
115 public function onFinishedRoutes(Event $event) {
116 $this->state->set('routing.non_admin_routes', $this->nonAdminRoutesOnRebuild);
117 $this->nonAdminRoutesOnRebuild = [];
118 }
119
120 /**
121 * {@inheritdoc}
122 */
123 public static function getSubscribedEvents() {
124 // Set a really low priority to catch as many as possible routes.
125 $events[RoutingEvents::ALTER] = ['onAlterRoutes', -1024];
126 $events[RoutingEvents::FINISHED] = ['onFinishedRoutes'];
127 // Load the routes before the controller is executed (which happens after
128 // the kernel request event).
129 $events[KernelEvents::REQUEST][] = ['onRequest'];
130 return $events;
131 }
132
133 }