diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml index 78aedcc0ca..d4d181a8fd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml @@ -89,6 +89,7 @@ + diff --git a/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php b/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php index ae048ca43d..06adebf441 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php @@ -21,25 +21,40 @@ use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\RequestContextAwareInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** - * Initializes request attributes based on a matching route. + * Initializes the context from the request and sets request attributes based on a matching route. * * @author Fabien Potencier */ class RouterListener implements EventSubscriberInterface { private $matcher; + private $context; private $logger; - public function __construct($matcher, LoggerInterface $logger = null) + /** + * Constructor. + * + * @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher + * @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface) + * @param LoggerInterface|null $logger The logger + */ + public function __construct($matcher, RequestContext $context = null, LoggerInterface $logger = null) { if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) { throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); } + if (null === $context && !$matcher instanceof RequestContextAwareInterface) { + throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.'); + } + $this->matcher = $matcher; + $this->context = $context ?: $matcher->getContext(); $this->logger = $logger; } @@ -47,16 +62,17 @@ class RouterListener implements EventSubscriberInterface { $request = $event->getRequest(); - $this->matcher->getContext()->fromRequest($request); + // initialize the context that is also used by the generator (assuming matcher and generator share the same context instance) + $this->context->fromRequest($request); if ($request->attributes->has('_controller')) { // routing is already done return; } - // add attributes based on the path info (routing) + // add attributes based on the request (routing) try { - // matching requests is more powerful than matching URLs only, so try that first + // matching a request is more powerful than matching a URL path + context, so try that first if ($this->matcher instanceof RequestMatcherInterface) { $parameters = $this->matcher->matchRequest($request); } else { diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php index e5d358176e..3cd0e40edb 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php @@ -92,18 +92,13 @@ class RouterListenerTest extends \PHPUnit_Framework_TestCase $request = Request::create('http://localhost/'); $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); - $context = new RequestContext(); - $requestMatcher = $this->getMock('Symfony\Component\Routing\Matcher\RequestMatcherInterface'); - $requestMatcher->expects($this->any()) - ->method('getContext') - ->will($this->returnValue($context)); $requestMatcher->expects($this->once()) ->method('matchRequest') ->with($this->isInstanceOf('Symfony\Component\HttpFoundation\Request')) ->will($this->returnValue(array())); - $listener = new RouterListener($requestMatcher); + $listener = new RouterListener($requestMatcher, new RequestContext()); $listener->onKernelRequest($event); } diff --git a/src/Symfony/Component/Routing/Matcher/RequestMatcherInterface.php b/src/Symfony/Component/Routing/Matcher/RequestMatcherInterface.php index 6a5c235ac0..d636cd093c 100644 --- a/src/Symfony/Component/Routing/Matcher/RequestMatcherInterface.php +++ b/src/Symfony/Component/Routing/Matcher/RequestMatcherInterface.php @@ -12,16 +12,15 @@ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\RequestContextAwareInterface; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Exception\MethodNotAllowedException; /** - * UrlMatcherInterface is the interface that all URL matcher classes must implement. + * RequestMatcherInterface is the interface that all request matcher classes must implement. * * @author Fabien Potencier */ -interface RequestMatcherInterface extends RequestContextAwareInterface +interface RequestMatcherInterface { /** * Tries to match a request with a set of routes. diff --git a/src/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php b/src/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php index afccf8009e..1242c2e962 100644 --- a/src/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php +++ b/src/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php @@ -25,7 +25,7 @@ use Symfony\Component\Routing\Exception\MethodNotAllowedException; interface UrlMatcherInterface extends RequestContextAwareInterface { /** - * Tries to match a URL with a set of routes. + * Tries to match a URL path with a set of routes. * * If the matcher can not find information, it must throw one of the exceptions documented * below.