RouteBuilder.php 3.79 KB
Newer Older
1 2
<?php

3 4 5 6 7
/**
 * @file
 * Definition of Drupal\Core\Routing\RouteBuilder.
 */

8 9
namespace Drupal\Core\Routing;

10
use Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface;
11 12 13 14 15 16
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;
17 18 19 20 21 22 23 24 25

/**
 * Managing class for rebuilding the router table.
 *
 * Because this class makes use of the modules system, it cannot currently
 * be unit tested.
 */
class RouteBuilder {

26 27 28 29 30
  /**
   * The dumper to which we should send collected routes.
   *
   * @var \Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface
   */
31 32
  protected $dumper;

33 34 35 36 37 38 39
  /**
   * The used lock backend instance.
   *
   * @var \Drupal\Core\Lock\LockBackendInterface $lock
   */
  protected $lock;

40 41 42 43 44 45 46
  /**
   * The event dispatcher to notify of routes.
   *
   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
   */
  protected $dispatcher;

47
  /**
48
   * Construcs the RouteBuilder using the passed MatcherDumperInterface.
49
   *
50
   * @param \Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface $dumper
51
   *   The matcher dumper used to store the route information.
52 53
   * @param \Drupal\Core\Lock\LockBackendInterface $lock
   *   The lock backend.
54 55
   * @param \Symfony\Component\EventDispatcherEventDispatcherInterface
   *   The event dispatcher to notify of routes.
56
   */
57
  public function __construct(MatcherDumperInterface $dumper, LockBackendInterface $lock, EventDispatcherInterface $dispatcher) {
58
    $this->dumper = $dumper;
59
    $this->lock = $lock;
60
    $this->dispatcher = $dispatcher;
61 62
  }

63 64 65
  /**
   * Rebuilds the route info and dumps to dumper.
   */
66
  public function rebuild() {
67 68 69 70 71 72 73 74
    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;
    }

75 76
    $parser = new Parser();

77 78
    // We need to manually call each module so that we can know which module
    // a given item came from.
79 80 81
    // @todo Use an injected Extension service rather than module_list():
    //   http://drupal.org/node/1331486.
    foreach (module_list() as $module) {
82
      $collection = new RouteCollection();
83
      $routing_file = DRUPAL_ROOT . '/' . drupal_get_path('module', $module) . '/' . $module . '.routing.yml';
84 85 86 87 88 89
      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();
90 91
            $options = isset($route_info['options']) ? $route_info['options'] : array();
            $route = new Route($route_info['pattern'], $defaults, $requirements, $options);
92 93 94 95 96 97
            $collection->add($name, $route);
          }
        }
      }
      $this->dispatcher->dispatch(RoutingEvents::ALTER, new RouteBuildEvent($collection, $module));
      $this->dumper->addRoutes($collection);
98 99
      $this->dumper->dump(array('route_set' => $module));
    }
100 101 102 103 104 105 106 107

    // 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'));

108
    $this->lock->release('router_rebuild');
109 110 111
  }

}