Update to Drupal 8.0.0-beta15. For more information, see: https://www.drupal.org/node/2563023

This commit is contained in:
Pantheon Automation 2015-09-04 13:20:09 -07:00 committed by Greg Anderson
parent 2720a9ec4b
commit f3791f1da3
1898 changed files with 54300 additions and 11481 deletions

View file

@ -43,7 +43,9 @@ class RouteCompiler extends SymfonyRouteCompiler implements RouteCompilerInterfa
$stripped_path = static::getPathWithoutDefaults($route);
$fit = static::getFit($stripped_path);
$pattern_outline = static::getPatternOutline($stripped_path);
$num_parts = count(explode('/', trim($pattern_outline, '/')));
// We count the number of parts including any optional trailing parts. This
// allows the RouteProvider to filter candidate routes more efficiently.
$num_parts = count(explode('/', trim($route->getPath(), '/')));
return new CompiledRoute(
$fit,

View file

@ -7,6 +7,8 @@
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;
@ -43,6 +45,13 @@ class RoutePreloader implements EventSubscriberInterface {
*/
protected $nonAdminRoutesOnRebuild = array();
/**
* The cache backend used to skip the state loading.
*
* @var \Drupal\Core\Cache\CacheBackendInterface
*/
protected $cache;
/**
* Constructs a new RoutePreloader.
*
@ -50,10 +59,12 @@ class RoutePreloader implements EventSubscriberInterface {
* 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) {
public function __construct(RouteProviderInterface $route_provider, StateInterface $state, CacheBackendInterface $cache) {
$this->routeProvider = $route_provider;
$this->state = $state;
$this->cache = $cache;
}
/**
@ -65,7 +76,19 @@ class RoutePreloader implements EventSubscriberInterface {
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') {
if ($routes = $this->state->get('routing.non_admin_routes', [])) {
// 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);
}

View file

@ -7,7 +7,9 @@
namespace Drupal\Core\Routing;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
use Drupal\Core\Path\CurrentPathStack;
use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
use Drupal\Core\State\StateInterface;
@ -75,6 +77,13 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
*/
protected $cache;
/**
* The cache tag invalidator.
*
* @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface
*/
protected $cacheTagInvalidator;
/**
* A path processor manager for resolving the system path.
*
@ -82,6 +91,11 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
*/
protected $pathProcessor;
/**
* Cache ID prefix used to load routes.
*/
const ROUTE_LOAD_CID_PREFIX = 'route_provider.route_load:';
/**
* Constructs a new PathMatcher.
*
@ -95,16 +109,19 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
* The cache backend.
* @param \Drupal\Core\PathProcessor\InboundPathProcessorInterface $path_processor
* The path processor.
* @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $cache_tag_invalidator
* The cache tag invalidator.
* @param string $table
* The table in the database to use for matching.
* (Optional) The table in the database to use for matching. Defaults to 'router'
*/
public function __construct(Connection $connection, StateInterface $state, CurrentPathStack $current_path, CacheBackendInterface $cache_backend, InboundPathProcessorInterface $path_processor, $table = 'router') {
public function __construct(Connection $connection, StateInterface $state, CurrentPathStack $current_path, CacheBackendInterface $cache_backend, InboundPathProcessorInterface $path_processor, CacheTagsInvalidatorInterface $cache_tag_invalidator, $table = 'router') {
$this->connection = $connection;
$this->state = $state;
$this->tableName = $table;
$this->currentPath = $current_path;
$this->cache = $cache_backend;
$this->cacheTagInvalidator = $cache_tag_invalidator;
$this->pathProcessor = $path_processor;
$this->tableName = $table;
}
/**
@ -189,8 +206,18 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
$routes_to_load = array_diff($names, array_keys($this->routes), array_keys($this->serializedRoutes));
if ($routes_to_load) {
$result = $this->connection->query('SELECT name, route FROM {' . $this->connection->escapeTable($this->tableName) . '} WHERE name IN ( :names[] )', array(':names[]' => $routes_to_load));
$routes = $result->fetchAllKeyed();
$cid = static::ROUTE_LOAD_CID_PREFIX . hash('sha512', serialize($routes_to_load));
if ($cache = $this->cache->get($cid)) {
$routes = $cache->data;
}
else {
$result = $this->connection->query('SELECT name, route FROM {' . $this->connection->escapeTable($this->tableName) . '} WHERE name IN ( :names[] )', array(':names[]' => $routes_to_load));
$routes = $result->fetchAllKeyed();
$this->cache->set($cid, $routes, Cache::PERMANENT, ['routes']);
}
$this->serializedRoutes += $routes;
}
}
@ -298,11 +325,9 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
* Returns a route collection of matching routes.
*/
protected function getRoutesByPath($path) {
// Filter out each empty value, though allow '0' and 0, which would be
// filtered out by empty().
$parts = array_values(array_filter(explode('/', $path), function($value) {
return $value !== NULL && $value !== '';
}));
// Split the path up on the slashes, ignoring multiple slashes in a row
// or leading or trailing slashes.
$parts = preg_split('@/+@', $path, NULL, PREG_SPLIT_NO_EMPTY);
$collection = new RouteCollection();
@ -311,21 +336,36 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
return $collection;
}
$routes = $this->connection->query("SELECT name, route FROM {" . $this->connection->escapeTable($this->tableName) . "} WHERE pattern_outline IN ( :patterns[] ) ORDER BY fit DESC, name ASC", array(
':patterns[]' => $ancestors,
// The >= check on number_parts allows us to match routes with optional
// trailing wildcard parts as long as the pattern matches, since we
// dump the route pattern without those optional parts.
$routes = $this->connection->query("SELECT name, route, fit FROM {" . $this->connection->escapeTable($this->tableName) . "} WHERE pattern_outline IN ( :patterns[] ) AND number_parts >= :count_parts", array(
':patterns[]' => $ancestors, ':count_parts' => count($parts),
))
->fetchAllKeyed();
->fetchAll(\PDO::FETCH_ASSOC);
foreach ($routes as $name => $route) {
$route = unserialize($route);
if (preg_match($route->compile()->getRegex(), $path, $matches)) {
$collection->add($name, $route);
}
// We sort by fit and name in PHP to avoid a SQL filesort.
usort($routes, array($this, 'routeProviderRouteCompare'));
foreach ($routes as $row) {
$collection->add($row['name'], unserialize($row['route']));
}
return $collection;
}
/**
* Comparison function for usort on routes.
*/
public function routeProviderRouteCompare(array $a, array $b) {
if ($a['fit'] == $b['fit']) {
return strcmp($a['name'], $b['name']);
}
// Reverse sort from highest to lowest fit. PHP should cast to int, but
// the explicit cast makes this sort more robust against unexpected input.
return (int) $a['fit'] < (int) $b['fit'] ? 1 : -1;
}
/**
* {@inheritdoc}
*/
@ -339,6 +379,7 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
public function reset() {
$this->routes = array();
$this->serializedRoutes = array();
$this->cacheTagInvalidator->invalidateTags(['routes']);
}
/**