X-Git-Url: http://aleph1.co.uk/gitweb/?a=blobdiff_plain;f=web%2Fcore%2Flib%2FDrupal%2FCore%2FRouting%2FRouter.php;h=c6c5dc0aa7662d805ee1688f0c80adc8f800d017;hb=1c1cb0980bfa6caf0c24cce671b6bb541dc87583;hp=e949c5efb862a166d555b046d0cedb75fa346ef6;hpb=a2bd1bf0c2c1f1a17d188f4dc0726a45494cefae;p=yaffs-website diff --git a/web/core/lib/Drupal/Core/Routing/Router.php b/web/core/lib/Drupal/Core/Routing/Router.php index e949c5efb..c6c5dc0aa 100644 --- a/web/core/lib/Drupal/Core/Routing/Router.php +++ b/web/core/lib/Drupal/Core/Routing/Router.php @@ -3,9 +3,9 @@ namespace Drupal\Core\Routing; use Drupal\Core\Path\CurrentPathStack; -use Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface as BaseRouteEnhancerInterface; +use Drupal\Core\Routing\Enhancer\RouteEnhancerInterface; use Symfony\Cmf\Component\Routing\LazyRouteCollection; -use Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface as BaseRouteFilterInterface; +use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Cmf\Component\Routing\RouteProviderInterface as BaseRouteProviderInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Exception\MethodNotAllowedException; @@ -53,31 +53,17 @@ class Router extends UrlMatcher implements RequestMatcherInterface, RouterInterf /** * The list of available enhancers. * - * @var \Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface[] + * @var \Drupal\Core\Routing\EnhancerInterface[] */ protected $enhancers = []; - /** - * Cached sorted list of enhancers. - * - * @var \Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface[] - */ - protected $sortedEnhancers; - /** * The list of available route filters. * - * @var \Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface[] + * @var \Drupal\Core\Routing\FilterInterface[] */ protected $filters = []; - /** - * Cached sorted list route filters. - * - * @var \Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface[] - */ - protected $sortedFilters; - /** * The URL generator. * @@ -102,36 +88,23 @@ class Router extends UrlMatcher implements RequestMatcherInterface, RouterInterf } /** - * Adds a route enhancer to the list of used route enhancers. - * - * @param \Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface $route_enhancer - * A route enhancer. - * @param int $priority - * (optional) The priority of the enhancer. Higher number enhancers will be - * used first. + * Adds a route filter. * - * @return $this + * @param \Drupal\Core\Routing\FilterInterface $route_filter + * The route filter. */ - public function addRouteEnhancer(BaseRouteEnhancerInterface $route_enhancer, $priority = 0) { - $this->enhancers[$priority][] = $route_enhancer; - return $this; + public function addRouteFilter(FilterInterface $route_filter) { + $this->filters[] = $route_filter; } /** - * Adds a route filter to the list of used route filters. + * Adds a route enhancer. * - * @param \Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface $route_filter - * A route filter. - * @param int $priority - * (optional) The priority of the filter. Higher number filters will be used - * first. - * - * @return $this + * @param \Drupal\Core\Routing\EnhancerInterface $route_enhancer + * The route enhancer. */ - public function addRouteFilter(BaseRouteFilterInterface $route_filter, $priority = 0) { - $this->filters[$priority][] = $route_filter; - - return $this; + public function addRouteEnhancer(EnhancerInterface $route_enhancer) { + $this->enhancers[] = $route_enhancer; } /** @@ -148,7 +121,11 @@ class Router extends UrlMatcher implements RequestMatcherInterface, RouterInterf */ public function matchRequest(Request $request) { $collection = $this->getInitialRouteCollection($request); + if ($collection->count() === 0) { + throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $this->currentPath->getPath())); + } $collection = $this->applyRouteFilters($collection, $request); + $collection = $this->applyFitOrder($collection); if ($ret = $this->matchCollection(rawurldecode($this->currentPath->getPath($request)), $collection)) { return $this->applyRouteEnhancers($ret, $request); @@ -276,46 +253,16 @@ class Router extends UrlMatcher implements RequestMatcherInterface, RouterInterf * from route enhancers. */ protected function applyRouteEnhancers($defaults, Request $request) { - foreach ($this->getRouteEnhancers() as $enhancer) { + foreach ($this->enhancers as $enhancer) { + if ($enhancer instanceof RouteEnhancerInterface && !$enhancer->applies($defaults[RouteObjectInterface::ROUTE_OBJECT])) { + continue; + } $defaults = $enhancer->enhance($defaults, $request); } return $defaults; } - /** - * Sorts the enhancers and flattens them. - * - * @return \Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface[] - * The enhancers ordered by priority. - */ - public function getRouteEnhancers() { - if (!isset($this->sortedEnhancers)) { - $this->sortedEnhancers = $this->sortRouteEnhancers(); - } - - return $this->sortedEnhancers; - } - - /** - * Sort enhancers by priority. - * - * The highest priority number is the highest priority (reverse sorting). - * - * @return \Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface[] - * The sorted enhancers. - */ - protected function sortRouteEnhancers() { - $sortedEnhancers = []; - krsort($this->enhancers); - - foreach ($this->enhancers as $enhancers) { - $sortedEnhancers = array_merge($sortedEnhancers, $enhancers); - } - - return $sortedEnhancers; - } - /** * Applies all route filters to a given route collection. * @@ -333,7 +280,7 @@ class Router extends UrlMatcher implements RequestMatcherInterface, RouterInterf protected function applyRouteFilters(RouteCollection $collection, Request $request) { // Route filters are expected to throw an exception themselves if they // end up filtering the list down to 0. - foreach ($this->getRouteFilters() as $filter) { + foreach ($this->filters as $filter) { $collection = $filter->filter($collection, $request); } @@ -341,36 +288,41 @@ class Router extends UrlMatcher implements RequestMatcherInterface, RouterInterf } /** - * Sorts the filters and flattens them. + * Reapplies the fit order to a RouteCollection object. * - * @return \Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface[] - * The filters ordered by priority - */ - public function getRouteFilters() { - if (!isset($this->sortedFilters)) { - $this->sortedFilters = $this->sortFilters(); - } - - return $this->sortedFilters; - } - - /** - * Sort filters by priority. + * Route filters can reorder route collections. For example, routes with an + * explicit _format requirement will be preferred. This can result in a less + * fit route being used. For example, as a result of filtering /user/% comes + * before /user/login. In order to not break this fundamental property of + * routes, we need to reapply the fit order. We also need to ensure that order + * within each group of the same fit is preserved. * - * The highest priority number is the highest priority (reverse sorting). + * @param \Symfony\Component\Routing\RouteCollection $collection + * The route collection. * - * @return \Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface[] - * The sorted filters. + * @return \Symfony\Component\Routing\RouteCollection + * The reordered route collection. */ - protected function sortFilters() { - $sortedFilters = []; - krsort($this->filters); - - foreach ($this->filters as $filters) { - $sortedFilters = array_merge($sortedFilters, $filters); + protected function applyFitOrder(RouteCollection $collection) { + $buckets = []; + // Sort all the routes by fit descending. + foreach ($collection->all() as $name => $route) { + $fit = $route->compile()->getFit(); + $buckets += [$fit => []]; + $buckets[$fit][] = [$name, $route]; } + krsort($buckets); + + $flattened = array_reduce($buckets, 'array_merge', []); - return $sortedFilters; + // Add them back onto a new route collection. + $collection = new RouteCollection(); + foreach ($flattened as $pair) { + $name = $pair[0]; + $route = $pair[1]; + $collection->add($name, $route); + } + return $collection; } /**