Newer
Older
<?php
/**
* @file
* Definition of Drupal\Core\Routing\RouteBuilder.
*/
namespace Drupal\Core\Routing;
use Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Yaml\Parser;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
use Drupal\Core\Lock\LockBackendInterface;
/**
* Managing class for rebuilding the router table.
*
* Because this class makes use of the modules system, it cannot currently
* be unit tested.
*/
class RouteBuilder {
/**
* The dumper to which we should send collected routes.
*
* @var \Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface
*/
protected $dumper;
Angie Byron
committed
/**
* The used lock backend instance.
*
* @var \Drupal\Core\Lock\LockBackendInterface $lock
*/
protected $lock;
/**
* The event dispatcher to notify of routes.
*
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
protected $dispatcher;
* Construcs the RouteBuilder using the passed MatcherDumperInterface.
Angie Byron
committed
* @param \Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface $dumper
* The matcher dumper used to store the route information.
Angie Byron
committed
* @param \Drupal\Core\Lock\LockBackendInterface $lock
* The lock backend.
* @param \Symfony\Component\EventDispatcherEventDispatcherInterface
* The event dispatcher to notify of routes.
public function __construct(MatcherDumperInterface $dumper, LockBackendInterface $lock, EventDispatcherInterface $dispatcher) {
$this->dumper = $dumper;
Angie Byron
committed
$this->lock = $lock;
$this->dispatcher = $dispatcher;
}
/**
* Rebuilds the route info and dumps to dumper.
*/
public function rebuild() {
Angie Byron
committed
if (!$this->lock->acquire('router_rebuild')) {
// Wait for another request that is already doing this work.
// We choose to block here since otherwise the routes might not be
// available, resulting in a 404.
$this->lock->wait('router_rebuild');
return;
}
$parser = new Parser();
// We need to manually call each module so that we can know which module
// a given item came from.
// @todo Use an injected Extension service rather than module_list():
// http://drupal.org/node/1331486.
foreach (module_list() as $module) {
$collection = new RouteCollection();
$routing_file = DRUPAL_ROOT . '/' . drupal_get_path('module', $module) . '/' . $module . '.routing.yml';
if (file_exists($routing_file)) {
$routes = $parser->parse(file_get_contents($routing_file));
if (!empty($routes)) {
foreach ($routes as $name => $route_info) {
$defaults = isset($route_info['defaults']) ? $route_info['defaults'] : array();
$requirements = isset($route_info['requirements']) ? $route_info['requirements'] : array();
$options = isset($route_info['options']) ? $route_info['options'] : array();
$route = new Route($route_info['pattern'], $defaults, $requirements, $options);
$collection->add($name, $route);
}
}
}
$this->dispatcher->dispatch(RoutingEvents::ALTER, new RouteBuildEvent($collection, $module));
$this->dumper->addRoutes($collection);
$this->dumper->dump(array('route_set' => $module));
}
// Now allow modules to register additional, dynamic routes.
$collection = new RouteCollection();
$this->dispatcher->dispatch(RoutingEvents::DYNAMIC, new RouteBuildEvent($collection, 'dynamic_routes'));
$this->dispatcher->dispatch(RoutingEvents::ALTER, new RouteBuildEvent($collection, 'dynamic_routes'));
$this->dumper->addRoutes($collection);
$this->dumper->dump(array('route_set' => 'dynamic_routes'));
Angie Byron
committed
$this->lock->release('router_rebuild');