class DynamicRouter

A flexible router accepting matcher and generator through injection and using the RouteEnhancer concept to generate additional data on the routes.

@author Larry Garfield @author David Buchmann

Hierarchy

Expanded class hierarchy of DynamicRouter

1 file declares its use of DynamicRouter
DynamicRouterTest.php in drupal/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing/Tests/Routing/DynamicRouterTest.php
1 string reference to 'DynamicRouter'
core.services.yml in drupal/core/core.services.yml
drupal/core/core.services.yml

File

drupal/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing/DynamicRouter.php, line 26

Namespace

Symfony\Cmf\Component\Routing
View source
class DynamicRouter implements RouterInterface, RequestMatcherInterface, ChainedRouterInterface {

  /**
   * @var RequestMatcherInterface|UrlMatcherInterface
   */
  protected $matcher;

  /**
   * @var UrlGeneratorInterface
   */
  protected $generator;

  /**
   * @var RouteEnhancerInterface[]
   */
  protected $enhancers = array();

  /**
   * Cached sorted list of enhancers
   *
   * @var RouteEnhancerInterface[]
   */
  protected $sortedEnhancers = array();

  /**
   * The regexp pattern that needs to be matched before a dynamic lookup is made
   *
   * @var string
   */
  protected $uriFilterRegexp;

  /**
   * @var RequestContext
   */
  protected $context;

  /**
   * @param RequestContext                              $context
   * @param RequestMatcherInterface|UrlMatcherInterface $matcher
   * @param UrlGeneratorInterface                       $generator
   * @param string                                      $uriFilterRegexp
   */
  public function __construct(RequestContext $context, $matcher, UrlGeneratorInterface $generator, $uriFilterRegexp = '') {
    $this->context = $context;
    if (!$matcher instanceof RequestMatcherInterface && !$matcher instanceof UrlMatcherInterface) {
      throw new \InvalidArgumentException('Invalid $matcher');
    }
    $this->matcher = $matcher;
    $this->generator = $generator;
    $this->uriFilterRegexp = $uriFilterRegexp;
    $this->generator
      ->setContext($context);
  }

  /**
   * Not implemented.
   */
  public function getRouteCollection() {
    return new RouteCollection();
  }

  /**
   * @return RequestMatcherInterface|UrlMatcherInterface
   */
  public function getMatcher() {

    /* we may not set the context in DynamicRouter::setContext as this
     * would lead to symfony cache warmup problems.
     * a request matcher does not need the request context separately as it
     * can get it from the request.
     */
    if ($this->matcher instanceof RequestContextAwareInterface) {
      $this->matcher
        ->setContext($this
        ->getContext());
    }
    return $this->matcher;
  }

  /**
   * @return UrlGeneratorInterface
   */
  public function getGenerator() {
    $this->generator
      ->setContext($this
      ->getContext());
    return $this->generator;
  }

  /**
   * Generates a URL from the given parameters.
   *
   * If the generator is not able to generate the url, it must throw the
   * RouteNotFoundException as documented below.
   *
   * @param string  $name       The name of the route
   * @param mixed   $parameters An array of parameters
   * @param Boolean $absolute   Whether to generate an absolute URL
   *
   * @return string The generated URL
   *
   * @throws RouteNotFoundException if route doesn't exist
   *
   * @api
   */
  public function generate($name, $parameters = array(), $absolute = false) {
    return $this
      ->getGenerator()
      ->generate($name, $parameters, $absolute);
  }

  /**
   * Delegate to our generator
   *
   * {@inheritDoc}
   */
  public function supports($name) {
    if ($this->generator instanceof VersatileGeneratorInterface) {
      return $this->generator
        ->supports($name);
    }
    return is_string($name);
  }

  /**
   * Tries to match a URL path with a set of routes.
   *
   * If the matcher can not find information, it must throw one of the
   * exceptions documented below.
   *
   * @param string $pathinfo The path info to be parsed (raw format, i.e. not
   *      urldecoded)
   *
   * @return array An array of parameters
   *
   * @throws ResourceNotFoundException If the resource could not be found
   * @throws MethodNotAllowedException If the resource was found but the
   *      request method is not allowed
   *
   * @api
   */
  public function match($pathinfo) {
    if (!empty($this->uriFilterRegexp) && !preg_match($this->uriFilterRegexp, $pathinfo)) {
      throw new ResourceNotFoundException("{$pathinfo} does not match the '{$this->uriFilterRegexp}' pattern");
    }
    $matcher = $this
      ->getMatcher();
    if (!$matcher instanceof UrlMatcherInterface) {
      throw new \InvalidArgumentException('Wrong matcher type, you need to call matchRequest');
    }
    $defaults = $matcher
      ->match($pathinfo);
    return $this
      ->applyRouteEnhancers($defaults, Request::create($pathinfo));
  }

  /**
   * Tries to match a request with a set of routes and returns the array of
   * information for that route.
   *
   * If the matcher can not find information, it must throw one of the
   * exceptions documented below.
   *
   * @param Request $request The request to match
   *
   * @return array An array of parameters
   *
   * @throws ResourceNotFoundException If no matching resource could be found
   * @throws MethodNotAllowedException If a matching resource was found but
   *      the request method is not allowed
   */
  public function matchRequest(Request $request) {
    if (!empty($this->uriFilterRegexp) && !preg_match($this->uriFilterRegexp, $request
      ->getPathInfo())) {
      throw new ResourceNotFoundException("{$request->getPathInfo()} does not match the '{$this->uriFilterRegexp}' pattern");
    }
    $matcher = $this
      ->getMatcher();
    if ($matcher instanceof UrlMatcherInterface) {

      // the match method will enhance the route $defaults
      return $this
        ->match($request
        ->getPathInfo());
    }
    $defaults = $matcher
      ->matchRequest($request);
    return $this
      ->applyRouteEnhancers($defaults, $request);
  }

  /**
   * Apply the route enhancers to the defaults, according to priorities
   *
   * @param array   $defaults
   * @param Request $request
   *
   * @return array
   */
  protected function applyRouteEnhancers($defaults, Request $request) {
    foreach ($this
      ->getRouteEnhancers() as $enhancer) {
      $defaults = $enhancer
        ->enhance($defaults, $request);
    }
    return $defaults;
  }

  /**
   * Add route enhancers to the router to let them generate information on
   * matched routes.
   *
   * The order of the enhancers is determined by the priority, the higher the
   * value, the earlier the enhancer is run.
   *
   * @param RouteEnhancerInterface $enhancer
   * @param int                    $priority
   */
  public function addRouteEnhancer(RouteEnhancerInterface $enhancer, $priority = 0) {
    if (empty($this->enhancers[$priority])) {
      $this->enhancers[$priority] = array();
    }
    $this->enhancers[$priority][] = $enhancer;
    $this->sortedEnhancers = array();
    return $this;
  }

  /**
   * Sorts the enhancers and flattens them.
   *
   * @return RouteEnhancerInterface[] the enhancers ordered by priority
   */
  public function getRouteEnhancers() {
    if (empty($this->sortedEnhancers)) {
      $this->sortedEnhancers = $this
        ->sortRouteEnhancers();
    }
    return $this->sortedEnhancers;
  }

  /**
   * Sort enhancers by priority.
   *
   * The highest priority number is the highest priority (reverse sorting).
   *
   * @return RouteEnhancerInterface[] the sorted enhancers
   */
  protected function sortRouteEnhancers() {
    $sortedEnhancers = array();
    krsort($this->enhancers);
    foreach ($this->enhancers as $enhancers) {
      $sortedEnhancers = array_merge($sortedEnhancers, $enhancers);
    }
    return $sortedEnhancers;
  }

  /**
   * Sets the request context.
   *
   * @param RequestContext $context The context
   *
   * @api
   */
  public function setContext(RequestContext $context) {
    $this->context = $context;
  }

  /**
   * Gets the request context.
   *
   * @return RequestContext The context
   *
   * @api
   */
  public function getContext() {
    return $this->context;
  }

  /**
   * {@inheritDoc}
   *
   * Forwards to the generator.
   */
  public function getRouteDebugMessage($name, array $parameters = array()) {
    if ($this->generator instanceof VersatileGeneratorInterface) {
      return $this->generator
        ->getRouteDebugMessage($name, $parameters);
    }
    return "Route '{$name}' not found";
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DynamicRouter::$context protected property
DynamicRouter::$enhancers protected property
DynamicRouter::$generator protected property
DynamicRouter::$matcher protected property
DynamicRouter::$sortedEnhancers protected property Cached sorted list of enhancers
DynamicRouter::$uriFilterRegexp protected property The regexp pattern that needs to be matched before a dynamic lookup is made
DynamicRouter::addRouteEnhancer public function Add route enhancers to the router to let them generate information on matched routes.
DynamicRouter::applyRouteEnhancers protected function Apply the route enhancers to the defaults, according to priorities
DynamicRouter::generate public function Generates a URL from the given parameters. Overrides UrlGeneratorInterface::generate
DynamicRouter::getContext public function Gets the request context. Overrides RequestContextAwareInterface::getContext
DynamicRouter::getGenerator public function
DynamicRouter::getMatcher public function
DynamicRouter::getRouteCollection public function Not implemented. Overrides RouterInterface::getRouteCollection
DynamicRouter::getRouteDebugMessage public function Forwards to the generator. Overrides VersatileGeneratorInterface::getRouteDebugMessage
DynamicRouter::getRouteEnhancers public function Sorts the enhancers and flattens them.
DynamicRouter::match public function Tries to match a URL path with a set of routes. Overrides UrlMatcherInterface::match
DynamicRouter::matchRequest public function Tries to match a request with a set of routes and returns the array of information for that route. Overrides RequestMatcherInterface::matchRequest
DynamicRouter::setContext public function Sets the request context. Overrides RequestContextAwareInterface::setContext
DynamicRouter::sortRouteEnhancers protected function Sort enhancers by priority.
DynamicRouter::supports public function Delegate to our generator Overrides VersatileGeneratorInterface::supports
DynamicRouter::__construct public function
UrlGeneratorInterface::ABSOLUTE_PATH constant Generates an absolute path, e.g. "/dir/file".
UrlGeneratorInterface::ABSOLUTE_URL constant Generates an absolute URL, e.g. "http://example.com/dir/file".
UrlGeneratorInterface::NETWORK_PATH constant Generates a network path, e.g. "//example.com/dir/file". Such reference reuses the current scheme but specifies the host.
UrlGeneratorInterface::RELATIVE_PATH constant Generates a relative path based on the current request path, e.g. "../parent-file".