[Routing] Remove a weird dependency

This commit is contained in:
Victor Berchet 2012-02-07 17:15:28 +01:00
parent 11e3516583
commit d86e1eb71c
4 changed files with 65 additions and 24 deletions

View File

@ -242,6 +242,7 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
### Routing ### Routing
* the UrlMatcher does not throw a \LogicException any more when the required scheme is not the current one
* added a TraceableUrlMatcher * added a TraceableUrlMatcher
* added the possibility to define default values and requirements for placeholders in prefix, including imported routes * added the possibility to define default values and requirements for placeholders in prefix, including imported routes
* added RouterInterface::getRouteCollection * added RouterInterface::getRouteCollection

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Routing\Matcher; namespace Symfony\Component\Routing\Matcher;
use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Route;
/** /**
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
@ -20,8 +21,6 @@ use Symfony\Component\Routing\Exception\ResourceNotFoundException;
*/ */
abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface
{ {
private $trailingSlashTest = false;
/** /**
* @see UrlMatcher::match() * @see UrlMatcher::match()
* *
@ -36,18 +35,28 @@ abstract class RedirectableUrlMatcher extends UrlMatcher implements Redirectable
throw $e; throw $e;
} }
// try with a / at the end try {
$this->trailingSlashTest = true; parent::match($pathinfo.'/');
return $this->redirect($pathinfo.'/', null);
return $this->match($pathinfo.'/'); } catch (ResourceNotFoundException $e2) {
} throw $e;
}
if ($this->trailingSlashTest) {
$this->trailingSlashTest = false;
return $this->redirect($pathinfo, null);
} }
return $parameters; return $parameters;
} }
/**
* {@inheritDoc}
*/
protected function handleRouteRequirements($pathinfo, $name, Route $route)
{
// check HTTP scheme requirement
$scheme = $route->getRequirement('_scheme');
if ($scheme && $this->context->getScheme() !== $scheme) {
return array(self::ROUTE_MATCH, $this->redirect($pathinfo, $name, $scheme));
}
return array(self::REQUIREMENT_MATCH, null);
}
} }

View File

@ -15,7 +15,7 @@ use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; use Symfony\Component\Routing\Route;
/** /**
* UrlMatcher matches URL based on a set of routes. * UrlMatcher matches URL based on a set of routes.
@ -26,6 +26,10 @@ use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface;
*/ */
class UrlMatcher implements UrlMatcherInterface class UrlMatcher implements UrlMatcherInterface
{ {
const REQUIREMENT_MATCH = 0;
const REQUIREMENT_MISMATCH = 1;
const ROUTE_MATCH = 2;
protected $context; protected $context;
private $routes; private $routes;
@ -84,6 +88,17 @@ class UrlMatcher implements UrlMatcherInterface
: new ResourceNotFoundException(); : new ResourceNotFoundException();
} }
/**
* 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) protected function matchCollection($pathinfo, RouteCollection $routes)
{ {
$pathinfo = urldecode($pathinfo); $pathinfo = urldecode($pathinfo);
@ -126,21 +141,38 @@ class UrlMatcher implements UrlMatcherInterface
} }
} }
// check HTTP scheme requirement $status = $this->handleRouteRequirements($pathinfo, $name, $route);
if ($scheme = $route->getRequirement('_scheme')) {
if (!$this instanceof RedirectableUrlMatcherInterface) {
throw new \LogicException('The "_scheme" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.');
}
if ($this->context->getScheme() !== $scheme) { if (self::ROUTE_MATCH === $status[0]) {
return $this->redirect($pathinfo, $name, $scheme); return $status[1];
} }
if (self::REQUIREMENT_MISMATCH === $status[0]) {
continue;
} }
return array_merge($this->mergeDefaults($matches, $route->getDefaults()), array('_route' => $name)); return array_merge($this->mergeDefaults($matches, $route->getDefaults()), array('_route' => $name));
} }
} }
/**
* Handles specific route requirements.
*
* @param string $pathinfo The path
* @param string $name The route name
* @param string $route The route
*
* @return array The first element represents the status, the second contains additional information
*/
protected function handleRouteRequirements($pathinfo, $name, Route $route)
{
// check HTTP scheme requirement
$scheme = $route->getRequirement('_scheme');
$status = $scheme && $scheme !== $this->context->getScheme() ? self::REQUIREMENT_MISMATCH : self::REQUIREMENT_MATCH;
return array($status, null);
}
protected function mergeDefaults($params, $defaults) protected function mergeDefaults($params, $defaults)
{ {
$parameters = $defaults; $parameters = $defaults;

View File

@ -207,14 +207,13 @@ class UrlMatcherTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* @expectedException \LogicException * @expectedException Symfony\Component\Routing\Exception\ResourceNotFoundException
*/ */
public function testSchemeRequirement() public function testSchemeRequirement()
{ {
$coll = new RouteCollection(); $coll = new RouteCollection();
$coll->add('foo', new Route('/foo', array(), array('_scheme' => 'https'))); $coll->add('foo', new Route('/foo', array(), array('_scheme' => 'https')));
$matcher = new UrlMatcher($coll, new RequestContext()); $matcher = new UrlMatcher($coll, new RequestContext());
$matcher->match('/foo'); $matcher->match('/foo');
} }
} }