Commit 8132d62c authored by alexpott's avatar alexpott

Revert "Issue #2810303 by dawehner, Crell, klausi, tim.plunkett, Wim Leers:...

Revert "Issue #2810303 by dawehner, Crell, klausi, tim.plunkett, Wim Leers: Reunite the router: One router to rule them all"

This reverts commit 21a86f3a.
parent ef01ed23
...@@ -801,7 +801,6 @@ services: ...@@ -801,7 +801,6 @@ services:
router.matcher.final_matcher: router.matcher.final_matcher:
class: Drupal\Core\Routing\UrlMatcher class: Drupal\Core\Routing\UrlMatcher
arguments: ['@path.current'] arguments: ['@path.current']
deprecated: The "%service_id%" service is deprecated. You should use the 'router.no_access_checks' service instead.
router.matcher: router.matcher:
class: Symfony\Cmf\Component\Routing\NestedMatcher\NestedMatcher class: Symfony\Cmf\Component\Routing\NestedMatcher\NestedMatcher
arguments: ['@router.route_provider'] arguments: ['@router.route_provider']
...@@ -809,7 +808,6 @@ services: ...@@ -809,7 +808,6 @@ services:
- [setFinalMatcher, ['@router.matcher.final_matcher']] - [setFinalMatcher, ['@router.matcher.final_matcher']]
tags: tags:
- { name: service_collector, tag: non_lazy_route_filter, call: addRouteFilter } - { 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: route_filter.lazy_collector:
class: Drupal\Core\Routing\LazyRouteFilter class: Drupal\Core\Routing\LazyRouteFilter
tags: tags:
...@@ -848,15 +846,11 @@ services: ...@@ -848,15 +846,11 @@ services:
arguments: ['@router.request_context', '@router.matcher', '@url_generator'] arguments: ['@router.request_context', '@router.matcher', '@url_generator']
tags: tags:
- { name: service_collector, tag: non_lazy_route_enhancer, call: addRouteEnhancer } - { 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: router.no_access_checks:
class: \Drupal\Core\Routing\Router class: Symfony\Cmf\Component\Routing\ChainRouter
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 }
calls: calls:
- [setContext, ['@router.request_context']] - [setContext, ['@router.request_context']]
- [add, ['@router.dynamic']]
router.path_roots_subscriber: router.path_roots_subscriber:
class: Drupal\Core\EventSubscriber\PathRootsSubscriber class: Drupal\Core\EventSubscriber\PathRootsSubscriber
arguments: ['@state'] arguments: ['@state']
......
...@@ -5,12 +5,10 @@ ...@@ -5,12 +5,10 @@
use Drupal\Core\Access\AccessManagerInterface; use Drupal\Core\Access\AccessManagerInterface;
use Drupal\Core\Access\AccessResultReasonInterface; use Drupal\Core\Access\AccessResultReasonInterface;
use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountInterface;
use Symfony\Cmf\Component\Routing\ChainRouter;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
use Symfony\Component\Routing\RequestContext as SymfonyRequestContext; 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. * A router class for Drupal with access check and upcasting.
...@@ -18,11 +16,11 @@ ...@@ -18,11 +16,11 @@
class AccessAwareRouter implements AccessAwareRouterInterface { 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. * The access manager.
...@@ -41,15 +39,15 @@ class AccessAwareRouter implements AccessAwareRouterInterface { ...@@ -41,15 +39,15 @@ class AccessAwareRouter implements AccessAwareRouterInterface {
/** /**
* Constructs a router for Drupal with access check and upcasting. * Constructs a router for Drupal with access check and upcasting.
* *
* @param \Symfony\Component\Routing\Matcher\RequestMatcherInterface $router * @param \Symfony\Cmf\Component\Routing\ChainRouter $chain_router
* The router doing the actual routing. * The chain router doing the actual routing.
* @param \Drupal\Core\Access\AccessManagerInterface $access_manager * @param \Drupal\Core\Access\AccessManagerInterface $access_manager
* The access manager. * The access manager.
* @param \Drupal\Core\Session\AccountInterface $account * @param \Drupal\Core\Session\AccountInterface $account
* The account to use in access checks. * The account to use in access checks.
*/ */
public function __construct(RequestMatcherInterface $router, AccessManagerInterface $access_manager, AccountInterface $account) { public function __construct(ChainRouter $chain_router, AccessManagerInterface $access_manager, AccountInterface $account) {
$this->router = $router; $this->chainRouter = $chain_router;
$this->accessManager = $access_manager; $this->accessManager = $access_manager;
$this->account = $account; $this->account = $account;
} }
...@@ -58,26 +56,23 @@ public function __construct(RequestMatcherInterface $router, AccessManagerInterf ...@@ -58,26 +56,23 @@ public function __construct(RequestMatcherInterface $router, AccessManagerInterf
* {@inheritdoc} * {@inheritdoc}
*/ */
public function __call($name, $arguments) { public function __call($name, $arguments) {
// Ensure to call every other function to the router. // Ensure to call every other function to the chained router.
return call_user_func_array([$this->router, $name], $arguments); // @todo Sadly does the ChainRouter not implement an interface in CMF.
return call_user_func_array([$this->chainRouter, $name], $arguments);
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function setContext(SymfonyRequestContext $context) { public function setContext(SymfonyRequestContext $context) {
if ($this->router instanceof RequestContextAwareInterface) { $this->chainRouter->setContext($context);
$this->router->setContext($context);
}
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getContext() { public function getContext() {
if ($this->router instanceof RequestContextAwareInterface) { return $this->chainRouter->getContext();
return $this->router->getContext();
}
} }
/** /**
...@@ -87,7 +82,7 @@ public function getContext() { ...@@ -87,7 +82,7 @@ public function getContext() {
* Thrown when access checking failed. * Thrown when access checking failed.
*/ */
public function matchRequest(Request $request) { public function matchRequest(Request $request) {
$parameters = $this->router->matchRequest($request); $parameters = $this->chainRouter->matchRequest($request);
$request->attributes->add($parameters); $request->attributes->add($parameters);
$this->checkAccess($request); $this->checkAccess($request);
// We can not return $parameters because the access check can change the // We can not return $parameters because the access check can change the
...@@ -119,18 +114,14 @@ protected function checkAccess(Request $request) { ...@@ -119,18 +114,14 @@ protected function checkAccess(Request $request) {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getRouteCollection() { public function getRouteCollection() {
if ($this->router instanceof RouterInterface) { return $this->chainRouter->getRouteCollection();
return $this->router->getRouteCollection();
}
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) { public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) {
if ($this->router instanceof UrlGeneratorInterface) { return $this->chainRouter->generate($name, $parameters, $referenceType);
return $this->router->generate($name, $parameters, $referenceType);
}
} }
/** /**
......
<?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);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment