RouteBuilder.php 4.23 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 Drupal\Component\Discovery\YamlDiscovery;
11 12 13 14 15
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Yaml\Parser;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;

16
use Drupal\Core\Extension\ModuleHandlerInterface;
17
use Drupal\Core\Lock\LockBackendInterface;
18 19 20 21 22 23 24 25 26

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

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

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

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

48
  /**
49 50 51 52 53 54 55 56
   * The yaml discovery used to find all the .routing.yml files.
   *
   * @var \Drupal\Component\Discovery\YamlDiscovery
   */
  protected $yamlDiscovery;

  /**
   * The module handler.
57 58 59 60 61
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

62
  /**
63
   * Construcs the RouteBuilder using the passed MatcherDumperInterface.
64
   *
65
   * @param \Drupal\Core\Routing\MatcherDumperInterface $dumper
66
   *   The matcher dumper used to store the route information.
67 68
   * @param \Drupal\Core\Lock\LockBackendInterface $lock
   *   The lock backend.
69
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher
70
   *   The event dispatcher to notify of routes.
71 72
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The module handler.
73
   */
74
  public function __construct(MatcherDumperInterface $dumper, LockBackendInterface $lock, EventDispatcherInterface $dispatcher, ModuleHandlerInterface $module_handler) {
75
    $this->dumper = $dumper;
76
    $this->lock = $lock;
77
    $this->dispatcher = $dispatcher;
78
    $this->moduleHandler = $module_handler;
79 80
  }

81 82
  /**
   * Rebuilds the route info and dumps to dumper.
83 84 85
   *
   * @return bool
   *   Returns TRUE if the rebuild succeeds, FALSE otherwise.
86
   */
87
  public function rebuild() {
88 89 90 91 92
    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');
93
      return FALSE;
94 95
    }

96
    $yaml_discovery = $this->getYamlDiscovery();
97

98
    foreach ($yaml_discovery->findAll() as $provider => $routes) {
99
      $collection = new RouteCollection();
100 101 102 103 104 105 106 107

      foreach ($routes as $name => $route_info) {
        $route_info += array(
          'defaults' => array(),
          'requirements' => array(),
          'options' => array(),
        );

108
        $route = new Route($route_info['path'], $route_info['defaults'], $route_info['requirements'], $route_info['options']);
109
        $collection->add($name, $route);
110
      }
111

112
      $this->dispatcher->dispatch(RoutingEvents::ALTER, new RouteBuildEvent($collection, $provider));
113
      $this->dumper->addRoutes($collection);
114
      $this->dumper->dump(array('provider' => $provider));
115
    }
116 117 118 119 120 121

    // 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);
122
    $this->dumper->dump(array('provider' => 'dynamic_routes'));
123

124
    $this->lock->release('router_rebuild');
125 126 127 128 129 130 131 132 133 134 135 136 137 138
    return TRUE;
  }

  /**
   * Returns the YAML discovery for getting all the .routing.yml files.
   *
   * @return \Drupal\Component\Discovery\YamlDiscovery
   *   The yaml discovery.
   */
  protected function getYamlDiscovery() {
    if (!isset($this->yamlDiscovery)) {
      $this->yamlDiscovery = new YamlDiscovery('routing', $this->moduleHandler->getModuleDirectories());
    }
    return $this->yamlDiscovery;
139 140 141
  }

}