You are here

class UrlMatcher in Zircon Profile 8

Same name in this branch
  1. 8 vendor/symfony-cmf/routing/NestedMatcher/UrlMatcher.php \Symfony\Cmf\Component\Routing\NestedMatcher\UrlMatcher
  2. 8 vendor/symfony/routing/Matcher/UrlMatcher.php \Symfony\Component\Routing\Matcher\UrlMatcher
  3. 8 core/lib/Drupal/Core/Routing/UrlMatcher.php \Drupal\Core\Routing\UrlMatcher
Same name and namespace in other branches
  1. 8.0 vendor/symfony/routing/Matcher/UrlMatcher.php \Symfony\Component\Routing\Matcher\UrlMatcher

UrlMatcher matches URL based on a set of routes.

@author Fabien Potencier <fabien@symfony.com>

Hierarchy

Expanded class hierarchy of UrlMatcher

3 files declare their use of UrlMatcher
RedirectableUrlMatcher.php in vendor/symfony/routing/Tests/Fixtures/RedirectableUrlMatcher.php
UrlMatcher.php in vendor/symfony-cmf/routing/NestedMatcher/UrlMatcher.php
UrlMatcherTest.php in vendor/symfony/routing/Tests/Matcher/UrlMatcherTest.php

File

vendor/symfony/routing/Matcher/UrlMatcher.php, line 28

Namespace

Symfony\Component\Routing\Matcher
View source
class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface {
  const REQUIREMENT_MATCH = 0;
  const REQUIREMENT_MISMATCH = 1;
  const ROUTE_MATCH = 2;

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

  /**
   * @var array
   */
  protected $allow = array();

  /**
   * @var RouteCollection
   */
  protected $routes;
  protected $request;
  protected $expressionLanguage;

  /**
   * @var ExpressionFunctionProviderInterface[]
   */
  protected $expressionLanguageProviders = array();

  /**
   * Constructor.
   *
   * @param RouteCollection $routes  A RouteCollection instance
   * @param RequestContext  $context The context
   */
  public function __construct(RouteCollection $routes, RequestContext $context) {
    $this->routes = $routes;
    $this->context = $context;
  }

  /**
   * {@inheritdoc}
   */
  public function setContext(RequestContext $context) {
    $this->context = $context;
  }

  /**
   * {@inheritdoc}
   */
  public function getContext() {
    return $this->context;
  }

  /**
   * {@inheritdoc}
   */
  public function match($pathinfo) {
    $this->allow = array();
    if ($ret = $this
      ->matchCollection(rawurldecode($pathinfo), $this->routes)) {
      return $ret;
    }
    throw 0 < count($this->allow) ? new MethodNotAllowedException(array_unique($this->allow)) : new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo));
  }

  /**
   * {@inheritdoc}
   */
  public function matchRequest(Request $request) {
    $this->request = $request;
    $ret = $this
      ->match($request
      ->getPathInfo());
    $this->request = null;
    return $ret;
  }
  public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) {
    $this->expressionLanguageProviders[] = $provider;
  }

  /**
   * Tries to match a URL with a set of routes.
   *
   * @param string          $pathinfo The path info to be parsed
   * @param RouteCollection $routes   The set of routes
   *
   * @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
   */
  protected function matchCollection($pathinfo, RouteCollection $routes) {
    foreach ($routes as $name => $route) {
      $compiledRoute = $route
        ->compile();

      // check the static prefix of the URL first. Only use the more expensive preg_match when it matches
      if ('' !== $compiledRoute
        ->getStaticPrefix() && 0 !== strpos($pathinfo, $compiledRoute
        ->getStaticPrefix())) {
        continue;
      }
      if (!preg_match($compiledRoute
        ->getRegex(), $pathinfo, $matches)) {
        continue;
      }
      $hostMatches = array();
      if ($compiledRoute
        ->getHostRegex() && !preg_match($compiledRoute
        ->getHostRegex(), $this->context
        ->getHost(), $hostMatches)) {
        continue;
      }

      // check HTTP method requirement
      if ($requiredMethods = $route
        ->getMethods()) {

        // HEAD and GET are equivalent as per RFC
        if ('HEAD' === ($method = $this->context
          ->getMethod())) {
          $method = 'GET';
        }
        if (!in_array($method, $requiredMethods)) {
          $this->allow = array_merge($this->allow, $requiredMethods);
          continue;
        }
      }
      $status = $this
        ->handleRouteRequirements($pathinfo, $name, $route);
      if (self::ROUTE_MATCH === $status[0]) {
        return $status[1];
      }
      if (self::REQUIREMENT_MISMATCH === $status[0]) {
        continue;
      }
      return $this
        ->getAttributes($route, $name, array_replace($matches, $hostMatches));
    }
  }

  /**
   * Returns an array of values to use as request attributes.
   *
   * As this method requires the Route object, it is not available
   * in matchers that do not have access to the matched Route instance
   * (like the PHP and Apache matcher dumpers).
   *
   * @param Route  $route      The route we are matching against
   * @param string $name       The name of the route
   * @param array  $attributes An array of attributes from the matcher
   *
   * @return array An array of parameters
   */
  protected function getAttributes(Route $route, $name, array $attributes) {
    $attributes['_route'] = $name;
    return $this
      ->mergeDefaults($attributes, $route
      ->getDefaults());
  }

  /**
   * Handles specific route requirements.
   *
   * @param string $pathinfo The path
   * @param string $name     The route name
   * @param Route  $route    The route
   *
   * @return array The first element represents the status, the second contains additional information
   */
  protected function handleRouteRequirements($pathinfo, $name, Route $route) {

    // expression condition
    if ($route
      ->getCondition() && !$this
      ->getExpressionLanguage()
      ->evaluate($route
      ->getCondition(), array(
      'context' => $this->context,
      'request' => $this->request,
    ))) {
      return array(
        self::REQUIREMENT_MISMATCH,
        null,
      );
    }

    // check HTTP scheme requirement
    $scheme = $this->context
      ->getScheme();
    $status = $route
      ->getSchemes() && !$route
      ->hasScheme($scheme) ? self::REQUIREMENT_MISMATCH : self::REQUIREMENT_MATCH;
    return array(
      $status,
      null,
    );
  }

  /**
   * Get merged default parameters.
   *
   * @param array $params   The parameters
   * @param array $defaults The defaults
   *
   * @return array Merged default parameters
   */
  protected function mergeDefaults($params, $defaults) {
    foreach ($params as $key => $value) {
      if (!is_int($key)) {
        $defaults[$key] = $value;
      }
    }
    return $defaults;
  }
  protected function getExpressionLanguage() {
    if (null === $this->expressionLanguage) {
      if (!class_exists('Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage')) {
        throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
      }
      $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders);
    }
    return $this->expressionLanguage;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
UrlMatcher::$allow protected property
UrlMatcher::$context protected property
UrlMatcher::$expressionLanguage protected property
UrlMatcher::$expressionLanguageProviders protected property
UrlMatcher::$request protected property
UrlMatcher::$routes protected property
UrlMatcher::addExpressionLanguageProvider public function
UrlMatcher::getAttributes protected function Returns an array of values to use as request attributes. 1
UrlMatcher::getContext public function Gets the request context. Overrides RequestContextAwareInterface::getContext
UrlMatcher::getExpressionLanguage protected function
UrlMatcher::handleRouteRequirements protected function Handles specific route requirements. 1
UrlMatcher::match public function Tries to match a URL path with a set of routes. Overrides UrlMatcherInterface::match 5
UrlMatcher::matchCollection protected function Tries to match a URL with a set of routes. 1
UrlMatcher::matchRequest public function Tries to match a request with a set of routes. Overrides RequestMatcherInterface::matchRequest
UrlMatcher::mergeDefaults protected function Get merged default parameters.
UrlMatcher::REQUIREMENT_MATCH constant
UrlMatcher::REQUIREMENT_MISMATCH constant
UrlMatcher::ROUTE_MATCH constant
UrlMatcher::setContext public function Sets the request context. Overrides RequestContextAwareInterface::setContext
UrlMatcher::__construct public function Constructor. 4