Mercurial > hg > isophonics-drupal-site
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/lib/Drupal/Core/Routing/RoutePreloader.php Wed Nov 29 16:09:58 2017 +0000 @@ -0,0 +1,133 @@ +<?php + +namespace Drupal\Core\Routing; + +use Drupal\Core\Cache\Cache; +use Drupal\Core\Cache\CacheBackendInterface; +use Drupal\Core\State\StateInterface; +use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Event\KernelEvent; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * Defines a class which preloads non-admin routes. + * + * On an actual site we want to avoid too many database queries so we build a + * list of all routes which most likely appear on the actual site, which are all + * HTML routes not starting with "/admin". + */ +class RoutePreloader implements EventSubscriberInterface { + + /** + * The route provider. + * + * @var \Drupal\Core\Routing\RouteProviderInterface|\Drupal\Core\Routing\PreloadableRouteProviderInterface + */ + protected $routeProvider; + + /** + * The state key value store. + * + * @var \Drupal\Core\State\StateInterface + */ + protected $state; + + /** + * Contains the non-admin routes while rebuilding the routes. + * + * @var array + */ + protected $nonAdminRoutesOnRebuild = []; + + /** + * The cache backend used to skip the state loading. + * + * @var \Drupal\Core\Cache\CacheBackendInterface + */ + protected $cache; + + /** + * Constructs a new RoutePreloader. + * + * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider + * The route provider. + * @param \Drupal\Core\State\StateInterface $state + * The state key value store. + * @param \Drupal\Core\Cache\CacheBackendInterface $cache + */ + public function __construct(RouteProviderInterface $route_provider, StateInterface $state, CacheBackendInterface $cache) { + $this->routeProvider = $route_provider; + $this->state = $state; + $this->cache = $cache; + } + + /** + * Loads all non-admin routes right before the actual page is rendered. + * + * @param \Symfony\Component\HttpKernel\Event\KernelEvent $event + * The event to process. + */ + public function onRequest(KernelEvent $event) { + // Only preload on normal HTML pages, as they will display menu links. + if ($this->routeProvider instanceof PreloadableRouteProviderInterface && $event->getRequest()->getRequestFormat() == 'html') { + + // Ensure that the state query is cached to skip the database query, if + // possible. + $key = 'routing.non_admin_routes'; + if ($cache = $this->cache->get($key)) { + $routes = $cache->data; + } + else { + $routes = $this->state->get($key, []); + $this->cache->set($key, $routes, Cache::PERMANENT, ['routes']); + } + + if ($routes) { + // Preload all the non-admin routes at once. + $this->routeProvider->preLoadRoutes($routes); + } + } + } + + /** + * Alters existing routes for a specific collection. + * + * @param \Drupal\Core\Routing\RouteBuildEvent $event + * The route build event. + */ + public function onAlterRoutes(RouteBuildEvent $event) { + $collection = $event->getRouteCollection(); + foreach ($collection->all() as $name => $route) { + if (strpos($route->getPath(), '/admin/') !== 0 && $route->getPath() != '/admin') { + $this->nonAdminRoutesOnRebuild[] = $name; + } + } + $this->nonAdminRoutesOnRebuild = array_unique($this->nonAdminRoutesOnRebuild); + } + + /** + * Store the non admin routes in state when the route building is finished. + * + * @param \Symfony\Component\EventDispatcher\Event $event + * The route finish event. + */ + public function onFinishedRoutes(Event $event) { + $this->state->set('routing.non_admin_routes', $this->nonAdminRoutesOnRebuild); + $this->nonAdminRoutesOnRebuild = []; + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + // Set a really low priority to catch as many as possible routes. + $events[RoutingEvents::ALTER] = ['onAlterRoutes', -1024]; + $events[RoutingEvents::FINISHED] = ['onFinishedRoutes']; + // Load the routes before the controller is executed (which happens after + // the kernel request event). + $events[KernelEvents::REQUEST][] = ['onRequest']; + return $events; + } + +}