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