Revert "Issue #2810303 by dawehner, Crell, klausi, tim.plunkett, Wim Leers: Reunite the router: One router to rule them all"
This reverts commit 21a86f3a46
.
8.3.x
parent
ef01ed2393
commit
8132d62c05
|
@ -801,7 +801,6 @@ services:
|
|||
router.matcher.final_matcher:
|
||||
class: Drupal\Core\Routing\UrlMatcher
|
||||
arguments: ['@path.current']
|
||||
deprecated: The "%service_id%" service is deprecated. You should use the 'router.no_access_checks' service instead.
|
||||
router.matcher:
|
||||
class: Symfony\Cmf\Component\Routing\NestedMatcher\NestedMatcher
|
||||
arguments: ['@router.route_provider']
|
||||
|
@ -809,7 +808,6 @@ services:
|
|||
- [setFinalMatcher, ['@router.matcher.final_matcher']]
|
||||
tags:
|
||||
- { name: service_collector, tag: non_lazy_route_filter, call: addRouteFilter }
|
||||
deprecated: The "%service_id%" service is deprecated. You should use the 'router.no_access_checks' service instead.
|
||||
route_filter.lazy_collector:
|
||||
class: Drupal\Core\Routing\LazyRouteFilter
|
||||
tags:
|
||||
|
@ -848,15 +846,11 @@ services:
|
|||
arguments: ['@router.request_context', '@router.matcher', '@url_generator']
|
||||
tags:
|
||||
- { name: service_collector, tag: non_lazy_route_enhancer, call: addRouteEnhancer }
|
||||
deprecated: The "%service_id%" service is deprecated. You should use the 'router.no_access_checks' service instead.
|
||||
router.no_access_checks:
|
||||
class: \Drupal\Core\Routing\Router
|
||||
arguments: ['@router.route_provider', '@path.current', '@url_generator']
|
||||
tags:
|
||||
- { name: service_collector, tag: non_lazy_route_enhancer, call: addRouteEnhancer }
|
||||
- { name: service_collector, tag: non_lazy_route_filter, call: addRouteFilter }
|
||||
class: Symfony\Cmf\Component\Routing\ChainRouter
|
||||
calls:
|
||||
- [setContext, ['@router.request_context']]
|
||||
- [add, ['@router.dynamic']]
|
||||
router.path_roots_subscriber:
|
||||
class: Drupal\Core\EventSubscriber\PathRootsSubscriber
|
||||
arguments: ['@state']
|
||||
|
|
|
@ -5,12 +5,10 @@ namespace Drupal\Core\Routing;
|
|||
use Drupal\Core\Access\AccessManagerInterface;
|
||||
use Drupal\Core\Access\AccessResultReasonInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Symfony\Cmf\Component\Routing\ChainRouter;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
|
||||
use Symfony\Component\Routing\RequestContext as SymfonyRequestContext;
|
||||
use Symfony\Component\Routing\RequestContextAwareInterface;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
|
||||
/**
|
||||
* A router class for Drupal with access check and upcasting.
|
||||
|
@ -18,11 +16,11 @@ use Symfony\Component\Routing\RouterInterface;
|
|||
class AccessAwareRouter implements AccessAwareRouterInterface {
|
||||
|
||||
/**
|
||||
* The router doing the actual routing.
|
||||
* The chain router doing the actual routing.
|
||||
*
|
||||
* @var \Symfony\Component\Routing\Matcher\RequestMatcherInterface
|
||||
* @var \Symfony\Cmf\Component\Routing\ChainRouter
|
||||
*/
|
||||
protected $router;
|
||||
protected $chainRouter;
|
||||
|
||||
/**
|
||||
* The access manager.
|
||||
|
@ -41,15 +39,15 @@ class AccessAwareRouter implements AccessAwareRouterInterface {
|
|||
/**
|
||||
* Constructs a router for Drupal with access check and upcasting.
|
||||
*
|
||||
* @param \Symfony\Component\Routing\Matcher\RequestMatcherInterface $router
|
||||
* The router doing the actual routing.
|
||||
* @param \Symfony\Cmf\Component\Routing\ChainRouter $chain_router
|
||||
* The chain router doing the actual routing.
|
||||
* @param \Drupal\Core\Access\AccessManagerInterface $access_manager
|
||||
* The access manager.
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The account to use in access checks.
|
||||
*/
|
||||
public function __construct(RequestMatcherInterface $router, AccessManagerInterface $access_manager, AccountInterface $account) {
|
||||
$this->router = $router;
|
||||
public function __construct(ChainRouter $chain_router, AccessManagerInterface $access_manager, AccountInterface $account) {
|
||||
$this->chainRouter = $chain_router;
|
||||
$this->accessManager = $access_manager;
|
||||
$this->account = $account;
|
||||
}
|
||||
|
@ -58,26 +56,23 @@ class AccessAwareRouter implements AccessAwareRouterInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function __call($name, $arguments) {
|
||||
// Ensure to call every other function to the router.
|
||||
return call_user_func_array([$this->router, $name], $arguments);
|
||||
// Ensure to call every other function to the chained router.
|
||||
// @todo Sadly does the ChainRouter not implement an interface in CMF.
|
||||
return call_user_func_array([$this->chainRouter, $name], $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setContext(SymfonyRequestContext $context) {
|
||||
if ($this->router instanceof RequestContextAwareInterface) {
|
||||
$this->router->setContext($context);
|
||||
}
|
||||
$this->chainRouter->setContext($context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContext() {
|
||||
if ($this->router instanceof RequestContextAwareInterface) {
|
||||
return $this->router->getContext();
|
||||
}
|
||||
return $this->chainRouter->getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,7 +82,7 @@ class AccessAwareRouter implements AccessAwareRouterInterface {
|
|||
* Thrown when access checking failed.
|
||||
*/
|
||||
public function matchRequest(Request $request) {
|
||||
$parameters = $this->router->matchRequest($request);
|
||||
$parameters = $this->chainRouter->matchRequest($request);
|
||||
$request->attributes->add($parameters);
|
||||
$this->checkAccess($request);
|
||||
// We can not return $parameters because the access check can change the
|
||||
|
@ -119,18 +114,14 @@ class AccessAwareRouter implements AccessAwareRouterInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRouteCollection() {
|
||||
if ($this->router instanceof RouterInterface) {
|
||||
return $this->router->getRouteCollection();
|
||||
}
|
||||
return $this->chainRouter->getRouteCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) {
|
||||
if ($this->router instanceof UrlGeneratorInterface) {
|
||||
return $this->router->generate($name, $parameters, $referenceType);
|
||||
}
|
||||
return $this->chainRouter->generate($name, $parameters, $referenceType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,301 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Core\Routing;
|
||||
|
||||
use Drupal\Core\Path\CurrentPathStack;
|
||||
use Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface as BaseRouteEnhancerInterface;
|
||||
use Symfony\Cmf\Component\Routing\LazyRouteCollection;
|
||||
use Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface as BaseRouteFilterInterface;
|
||||
use Symfony\Cmf\Component\Routing\RouteProviderInterface as BaseRouteProviderInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
|
||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
|
||||
/**
|
||||
* Router implementation in Drupal.
|
||||
*
|
||||
* A router determines, for an incoming request, the active controller, which is
|
||||
* a callable that creates a response.
|
||||
*
|
||||
* It consists of several steps, of which each are explained in more details
|
||||
* below:
|
||||
* 1. Get a collection of routes which potentially match the current request.
|
||||
* This is done by the route provider. See ::getInitialRouteCollection().
|
||||
* 2. Filter the collection down further more. For example this filters out
|
||||
* routes applying to other formats: See ::applyRouteFilters()
|
||||
* 3. Find the best matching route out of the remaining ones, by applying a
|
||||
* regex. See ::matchCollection().
|
||||
* 4. Enhance the list of route attributes, for example loading entity objects.
|
||||
* See ::applyRouteEnhancers().
|
||||
*
|
||||
* This implementation uses ideas of the following routers:
|
||||
* - \Symfony\Cmf\Component\Routing\DynamicRouter
|
||||
* - \Drupal\Core\Routing\UrlMatcher
|
||||
* - \Symfony\Cmf\Component\Routing\NestedMatcher\NestedMatcher
|
||||
*
|
||||
* @see \Symfony\Cmf\Component\Routing\DynamicRouter
|
||||
* @see \Drupal\Core\Routing\UrlMatcher
|
||||
* @see \Symfony\Cmf\Component\Routing\NestedMatcher\NestedMatcher
|
||||
*/
|
||||
class Router extends UrlMatcher implements RequestMatcherInterface, RouterInterface {
|
||||
|
||||
/**
|
||||
* The route provider responsible for the first-pass match.
|
||||
*
|
||||
* @var \Symfony\Cmf\Component\Routing\RouteProviderInterface
|
||||
*/
|
||||
protected $routeProvider;
|
||||
|
||||
/**
|
||||
* The list of available enhancers.
|
||||
*
|
||||
* @var \Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface[]
|
||||
*/
|
||||
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[]
|
||||
*/
|
||||
protected $filters = [];
|
||||
|
||||
/**
|
||||
* Cached sorted list route filters.
|
||||
*
|
||||
* @var \Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface[]
|
||||
*/
|
||||
protected $sortedFilters;
|
||||
|
||||
/**
|
||||
* The URL generator.
|
||||
*
|
||||
* @var \Symfony\Component\Routing\Generator\UrlGeneratorInterface
|
||||
*/
|
||||
protected $urlGenerator;
|
||||
|
||||
/**
|
||||
* Constructs a new Router.
|
||||
*
|
||||
* @param \Symfony\Cmf\Component\Routing\RouteProviderInterface $route_provider
|
||||
* The route provider.
|
||||
* @param \Drupal\Core\Path\CurrentPathStack $current_path
|
||||
* The current path stack.
|
||||
* @param \Symfony\Component\Routing\Generator\UrlGeneratorInterface $url_generator
|
||||
* The URL generator.
|
||||
*/
|
||||
public function __construct(BaseRouteProviderInterface $route_provider, CurrentPathStack $current_path, UrlGeneratorInterface $url_generator) {
|
||||
parent::__construct($current_path);
|
||||
$this->routeProvider = $route_provider;
|
||||
$this->urlGenerator = $url_generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addRouteEnhancer(BaseRouteEnhancerInterface $route_enhancer, $priority = 0) {
|
||||
$this->enhancers[$priority][] = $route_enhancer;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a route filter to the list of used route filters.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public function addRouteFilter(BaseRouteFilterInterface $route_filter, $priority = 0) {
|
||||
$this->filters[$priority][] = $route_filter;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function match($pathinfo) {
|
||||
$request = Request::create($pathinfo);
|
||||
|
||||
return $this->matchRequest($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function matchRequest(Request $request) {
|
||||
$collection = $this->getInitialRouteCollection($request);
|
||||
$collection = $this->applyRouteFilters($collection, $request);
|
||||
|
||||
if ($ret = $this->matchCollection(rawurldecode($this->currentPath->getPath($request)), $collection)) {
|
||||
return $this->applyRouteEnhancers($ret, $request);
|
||||
}
|
||||
|
||||
throw 0 < count($this->allow)
|
||||
? new MethodNotAllowedException(array_unique($this->allow))
|
||||
: new ResourceNotFoundException(sprintf('No routes found for "%s".', $this->currentPath->getPath()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of potential matching routes for a request.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request.
|
||||
*
|
||||
* @return \Symfony\Component\Routing\RouteCollection
|
||||
* The initial fetched route collection.
|
||||
*/
|
||||
protected function getInitialRouteCollection(Request $request) {
|
||||
return $this->routeProvider->getRouteCollectionForRequest($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the route enhancers to the defaults, according to priorities.
|
||||
*
|
||||
* @param array $defaults
|
||||
* The defaults coming from the final matched route.
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The request.
|
||||
*
|
||||
* @return array
|
||||
* The request attributes after applying the enhancers. This might consist
|
||||
* raw values from the URL but also upcasted values, like entity objects,
|
||||
* from route enhancers.
|
||||
*/
|
||||
protected function applyRouteEnhancers($defaults, Request $request) {
|
||||
foreach ($this->getRouteEnhancers() as $enhancer) {
|
||||
$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.
|
||||
*
|
||||
* This method reduces the sets of routes further down, for example by
|
||||
* checking the HTTP method.
|
||||
*
|
||||
* @param \Symfony\Component\Routing\RouteCollection $collection
|
||||
* The route collection.
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The request.
|
||||
*
|
||||
* @return \Symfony\Component\Routing\RouteCollection
|
||||
* The filtered/sorted route collection.
|
||||
*/
|
||||
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) {
|
||||
$collection = $filter->filter($collection, $request);
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the filters and flattens them.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* The highest priority number is the highest priority (reverse sorting).
|
||||
*
|
||||
* @return \Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface[]
|
||||
* The sorted filters.
|
||||
*/
|
||||
protected function sortFilters() {
|
||||
$sortedFilters = [];
|
||||
krsort($this->filters);
|
||||
|
||||
foreach ($this->filters as $filters) {
|
||||
$sortedFilters = array_merge($sortedFilters, $filters);
|
||||
}
|
||||
|
||||
return $sortedFilters;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRouteCollection() {
|
||||
return new LazyRouteCollection($this->routeProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) {
|
||||
@trigger_error('Use the \Drupal\Core\Url object instead', E_USER_DEPRECATED);
|
||||
return $this->urlGenerator->generate($name, $parameters, $referenceType);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue