vendor/symfony/src/Symfony/Component/Routing/Matcher/UrlMatcher.php
changeset 0 7f95f8617b0b
equal deleted inserted replaced
-1:000000000000 0:7f95f8617b0b
       
     1 <?php
       
     2 
       
     3 /*
       
     4  * This file is part of the Symfony package.
       
     5  *
       
     6  * (c) Fabien Potencier <fabien@symfony.com>
       
     7  *
       
     8  * For the full copyright and license information, please view the LICENSE
       
     9  * file that was distributed with this source code.
       
    10  */
       
    11 
       
    12 namespace Symfony\Component\Routing\Matcher;
       
    13 
       
    14 use Symfony\Component\Routing\Exception\MethodNotAllowedException;
       
    15 use Symfony\Component\Routing\Exception\ResourceNotFoundException;
       
    16 use Symfony\Component\Routing\Route;
       
    17 use Symfony\Component\Routing\RouteCollection;
       
    18 use Symfony\Component\Routing\RequestContext;
       
    19 
       
    20 /**
       
    21  * UrlMatcher matches URL based on a set of routes.
       
    22  *
       
    23  * @author Fabien Potencier <fabien@symfony.com>
       
    24  *
       
    25  * @api
       
    26  */
       
    27 class UrlMatcher implements UrlMatcherInterface
       
    28 {
       
    29     protected $context;
       
    30 
       
    31     private $routes;
       
    32 
       
    33     /**
       
    34      * Constructor.
       
    35      *
       
    36      * @param RouteCollection $routes  A RouteCollection instance
       
    37      * @param RequestContext  $context The context
       
    38      *
       
    39      * @api
       
    40      */
       
    41     public function __construct(RouteCollection $routes, RequestContext $context)
       
    42     {
       
    43         $this->routes = $routes;
       
    44         $this->context = $context;
       
    45     }
       
    46 
       
    47     /**
       
    48      * Sets the request context.
       
    49      *
       
    50      * @param RequestContext $context The context
       
    51      *
       
    52      * @api
       
    53      */
       
    54     public function setContext(RequestContext $context)
       
    55     {
       
    56         $this->context = $context;
       
    57     }
       
    58 
       
    59     /**
       
    60      * Gets the request context.
       
    61      *
       
    62      * @return RequestContext The context
       
    63      */
       
    64     public function getContext()
       
    65     {
       
    66         return $this->context;
       
    67     }
       
    68 
       
    69     /**
       
    70      * Tries to match a URL with a set of routes.
       
    71      *
       
    72      * @param  string $pathinfo The path info to be parsed
       
    73      *
       
    74      * @return array An array of parameters
       
    75      *
       
    76      * @throws ResourceNotFoundException If the resource could not be found
       
    77      * @throws MethodNotAllowedException If the resource was found but the request method is not allowed
       
    78      *
       
    79      * @api
       
    80      */
       
    81     public function match($pathinfo)
       
    82     {
       
    83         $this->allow = array();
       
    84 
       
    85         if ($ret = $this->matchCollection($pathinfo, $this->routes)) {
       
    86             return $ret;
       
    87         }
       
    88 
       
    89         throw 0 < count($this->allow)
       
    90             ? new MethodNotAllowedException(array_unique(array_map('strtoupper', $this->allow)))
       
    91             : new ResourceNotFoundException();
       
    92     }
       
    93 
       
    94     protected function matchCollection($pathinfo, RouteCollection $routes)
       
    95     {
       
    96         $pathinfo = urldecode($pathinfo);
       
    97 
       
    98         foreach ($routes as $name => $route) {
       
    99             if ($route instanceof RouteCollection) {
       
   100                 if (false === strpos($route->getPrefix(), '{') && $route->getPrefix() !== substr($pathinfo, 0, strlen($route->getPrefix()))) {
       
   101                     continue;
       
   102                 }
       
   103 
       
   104                 if (!$ret = $this->matchCollection($pathinfo, $route)) {
       
   105                     continue;
       
   106                 }
       
   107 
       
   108                 return $ret;
       
   109             }
       
   110 
       
   111             $compiledRoute = $route->compile();
       
   112 
       
   113             // check the static prefix of the URL first. Only use the more expensive preg_match when it matches
       
   114             if ('' !== $compiledRoute->getStaticPrefix() && 0 !== strpos($pathinfo, $compiledRoute->getStaticPrefix())) {
       
   115                 continue;
       
   116             }
       
   117 
       
   118             if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) {
       
   119                 continue;
       
   120             }
       
   121 
       
   122             // check HTTP method requirement
       
   123             if ($req = $route->getRequirement('_method')) {
       
   124                 // HEAD and GET are equivalent as per RFC
       
   125                 if ('HEAD' === $method = $this->context->getMethod()) {
       
   126                     $method = 'GET';
       
   127                 }
       
   128 
       
   129                 if (!in_array($method, $req = explode('|', strtoupper($req)))) {
       
   130                     $this->allow = array_merge($this->allow, $req);
       
   131 
       
   132                     continue;
       
   133                 }
       
   134             }
       
   135 
       
   136             return array_merge($this->mergeDefaults($matches, $route->getDefaults()), array('_route' => $name));
       
   137         }
       
   138     }
       
   139 
       
   140     protected function mergeDefaults($params, $defaults)
       
   141     {
       
   142         $parameters = $defaults;
       
   143         foreach ($params as $key => $value) {
       
   144             if (!is_int($key)) {
       
   145                 $parameters[$key] = rawurldecode($value);
       
   146             }
       
   147         }
       
   148 
       
   149         return $parameters;
       
   150     }
       
   151 }