diff -r 000000000000 -r 7f95f8617b0b vendor/symfony/src/Symfony/Component/Routing/Matcher/UrlMatcher.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/symfony/src/Symfony/Component/Routing/Matcher/UrlMatcher.php Sat Sep 24 15:40:41 2011 +0200 @@ -0,0 +1,151 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher; + +use Symfony\Component\Routing\Exception\MethodNotAllowedException; +use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\RequestContext; + +/** + * UrlMatcher matches URL based on a set of routes. + * + * @author Fabien Potencier + * + * @api + */ +class UrlMatcher implements UrlMatcherInterface +{ + protected $context; + + private $routes; + + /** + * Constructor. + * + * @param RouteCollection $routes A RouteCollection instance + * @param RequestContext $context The context + * + * @api + */ + public function __construct(RouteCollection $routes, RequestContext $context) + { + $this->routes = $routes; + $this->context = $context; + } + + /** + * 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 + */ + public function getContext() + { + return $this->context; + } + + /** + * Tries to match a URL with a set of routes. + * + * @param string $pathinfo The path info to be parsed + * + * @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) + { + $this->allow = array(); + + if ($ret = $this->matchCollection($pathinfo, $this->routes)) { + return $ret; + } + + throw 0 < count($this->allow) + ? new MethodNotAllowedException(array_unique(array_map('strtoupper', $this->allow))) + : new ResourceNotFoundException(); + } + + protected function matchCollection($pathinfo, RouteCollection $routes) + { + $pathinfo = urldecode($pathinfo); + + foreach ($routes as $name => $route) { + if ($route instanceof RouteCollection) { + if (false === strpos($route->getPrefix(), '{') && $route->getPrefix() !== substr($pathinfo, 0, strlen($route->getPrefix()))) { + continue; + } + + if (!$ret = $this->matchCollection($pathinfo, $route)) { + continue; + } + + return $ret; + } + + $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; + } + + // check HTTP method requirement + if ($req = $route->getRequirement('_method')) { + // HEAD and GET are equivalent as per RFC + if ('HEAD' === $method = $this->context->getMethod()) { + $method = 'GET'; + } + + if (!in_array($method, $req = explode('|', strtoupper($req)))) { + $this->allow = array_merge($this->allow, $req); + + continue; + } + } + + return array_merge($this->mergeDefaults($matches, $route->getDefaults()), array('_route' => $name)); + } + } + + protected function mergeDefaults($params, $defaults) + { + $parameters = $defaults; + foreach ($params as $key => $value) { + if (!is_int($key)) { + $parameters[$key] = rawurldecode($value); + } + } + + return $parameters; + } +}