merged branch niklasf/request-matcher-interface (PR #4363)

Commits
-------

2277500 [Routing][HttpKernel] Add RequestMatcherInterface.

Discussion
----------

[Routing][HttpKernel] Add RequestMatcherInterface.

First try at implementing #4351.

Bug fix: no
Feature addition: yes
Backwards compatibility break: no
Fixes the following tickets: -
Todo: -
License of the code: MIT

---------------------------------------------------------------------------

by travisbot at 2012-05-21T19:37:07Z

This pull request [fails](http://travis-ci.org/symfony/symfony/builds/1392716) (merged 457496db into ea33d4d3).

---------------------------------------------------------------------------

by travisbot at 2012-05-21T19:47:51Z

This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1392939) (merged 78effa98 into ea33d4d3).

---------------------------------------------------------------------------

by everzet at 2012-05-21T20:17:03Z

No tests?

---------------------------------------------------------------------------

by travisbot at 2012-05-21T20:18:18Z

This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1393392) (merged 6564fb6a into ea33d4d3).

---------------------------------------------------------------------------

by schmittjoh at 2012-05-21T20:35:14Z

You need to remove the type-hint from the constructor, and probably add an exception instead where the matching methods are called to ensure that either ``UrlMatcherInterface``, or ``RequestMatcherInterface`` were passed. Alternatively, you could also add such a check to the constructor.

---------------------------------------------------------------------------

by fabpot at 2012-05-22T06:52:01Z

related to symfony/symfony#4020

---------------------------------------------------------------------------

by niklasf at 2012-05-25T11:11:45Z

Reverted the changes to UrlMatcher.php.

---------------------------------------------------------------------------

by fabpot at 2012-05-25T12:46:06Z

@niklasf: it looks good now except for the listener constructor (see @schmittjoh suggestion above). Can you fix that and add some unit tests to ensure that everything works as expected? Thanks.

---------------------------------------------------------------------------

by stof at 2012-05-25T12:52:59Z

Another solution could be to make the ``RequestMatcherInterface`` extend the ``MatcherInterface`` to keep the typehint in the constructor

---------------------------------------------------------------------------

by fabpot at 2012-05-25T13:52:26Z

I thought about that as well, but that does not make sense.

---------------------------------------------------------------------------

by stof at 2012-05-25T14:12:19Z

Well, the RouterInterface extends UrlMatcherInterface anyway (and it should stay this way as it would be a huge BC break) so I guess most people will implement both interfaces when implementing the RquestMatcherInterface

---------------------------------------------------------------------------

by travisbot at 2012-05-25T15:26:22Z

This pull request [fails](http://travis-ci.org/symfony/symfony/builds/1433963) (merged 8f36204c into ff4d446c).

---------------------------------------------------------------------------

by travisbot at 2012-05-25T15:33:13Z

This pull request [fails](http://travis-ci.org/symfony/symfony/builds/1433996) (merged 6d2f2cd9 into ff4d446c).

---------------------------------------------------------------------------

by travisbot at 2012-05-25T15:39:01Z

This pull request [fails](http://travis-ci.org/symfony/symfony/builds/1434060) (merged 3c1d89e2 into ff4d446c).

---------------------------------------------------------------------------

by travisbot at 2012-05-25T22:06:34Z

This pull request [fails](http://travis-ci.org/symfony/symfony/builds/1437398) (merged 3ab997c1 into ff4d446c).

---------------------------------------------------------------------------

by travisbot at 2012-05-25T22:06:47Z

This pull request [fails](http://travis-ci.org/symfony/symfony/builds/1437385) (merged d8c0e387 into ff4d446c).

---------------------------------------------------------------------------

by fabpot at 2012-05-26T06:41:31Z

Can you add a note in the CHANGELOG of the component?

---------------------------------------------------------------------------

by travisbot at 2012-05-26T08:12:40Z

This pull request [fails](http://travis-ci.org/symfony/symfony/builds/1440435) (merged c7458733 into 9e951991).

---------------------------------------------------------------------------

by niklasf at 2012-05-26T08:14:41Z

@fabpot: Sorry, not sure how: Under 2.1.0 or in a new section? As the first or last entry of the list?

---------------------------------------------------------------------------

by stof at 2012-05-26T10:20:23Z

@niklasf the new interface should be mentioned in the changelog of the Routing component

---------------------------------------------------------------------------

by travisbot at 2012-05-26T10:30:06Z

This pull request [fails](http://travis-ci.org/symfony/symfony/builds/1440837) (merged 34ea86a9 into 9e951991).

---------------------------------------------------------------------------

by niklasf at 2012-06-02T15:27:01Z

Ah ... so there were two pitfalls:

- PHPUnit clones the arguments of mocked functions. So they wouldn't equal.
- createGetResponseEventForUri() disables routing on purpose. So not using that helper, now.

Tests should be passing.

---------------------------------------------------------------------------

by travisbot at 2012-06-02T15:30:28Z

This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1509054) (merged 7fab0118 into 1541fe26).
This commit is contained in:
Fabien Potencier 2012-06-09 21:38:41 +02:00
commit 1787992d0c
4 changed files with 85 additions and 5 deletions

View File

@ -20,6 +20,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
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\EventDispatcher\EventSubscriberInterface;
/**
@ -29,12 +30,16 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
*/
class RouterListener implements EventSubscriberInterface
{
private $urlMatcher;
private $matcher;
private $logger;
public function __construct(UrlMatcherInterface $urlMatcher, LoggerInterface $logger = null)
public function __construct($matcher, LoggerInterface $logger = null)
{
$this->urlMatcher = $urlMatcher;
if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) {
throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.');
}
$this->matcher = $matcher;
$this->logger = $logger;
}
@ -43,7 +48,7 @@ class RouterListener implements EventSubscriberInterface
$request = $event->getRequest();
if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()) {
$this->urlMatcher->getContext()->fromRequest($request);
$this->matcher->getContext()->fromRequest($request);
}
if ($request->attributes->has('_controller')) {
@ -53,7 +58,12 @@ class RouterListener implements EventSubscriberInterface
// add attributes based on the path info (routing)
try {
$parameters = $this->urlMatcher->match($request->getPathInfo());
// matching requests is more powerful than matching URLs only, so try that first
if ($this->matcher instanceof RequestMatcherInterface) {
$parameters = $this->matcher->matchRequest($request);
} else {
$parameters = $this->matcher->match($request->getPathInfo());
}
if (null !== $this->logger) {
$this->logger->info(sprintf('Matched route "%s" (parameters: %s)', $parameters['_route'], $this->parametersToString($parameters)));

View File

@ -77,4 +77,33 @@ class RouterListenerTest extends \PHPUnit_Framework_TestCase
return new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST);
}
/**
* @expectedException \InvalidArgumentException
*/
public function testInvalidMatcher()
{
new RouterListener(new \stdClass());
}
public function testRequestMatcher()
{
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$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->onKernelRequest($event);
}
}

View File

@ -4,6 +4,7 @@ CHANGELOG
2.1.0
-----
* added RequestMatcherInterface
* added RequestContext::fromRequest()
* the UrlMatcher does not throw a \LogicException anymore when the required
scheme is not the current one

View File

@ -0,0 +1,40 @@
<?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\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.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
interface RequestMatcherInterface extends RequestContextAwareInterface
{
/**
* Tries to match a request with a set of routes.
*
* If the matcher can not find information, it must throw one of the exceptions documented
* below.
*
* @param Request $request The request to match
*
* @return array An array of parameters
*
* @throws ResourceNotFoundException If no matching resource could be found
* @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed
*/
function matchRequest(Request $request);
}