123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- <?php
- /*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * 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 <fabien@symfony.com>
- */
- class UrlMatcher implements UrlMatcherInterface
- {
- protected $context;
- private $routes;
- /**
- * 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;
- }
- /**
- * Sets the request context.
- *
- * @param RequestContext $context The context
- */
- 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
- */
- 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)
- {
- 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;
- }
- }
|