Commit 857023d1 authored by Jérôme Tamarelle's avatar Jérôme Tamarelle

[Routing] Replace the UrlMatcher by a RequestMatcher

parent 55cb6a17
......@@ -13,30 +13,72 @@ namespace Silex\Provider\Locale;
use Pimple\Container;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\EventListener\LocaleListener as BaseLocaleListener;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RequestContextAwareInterface;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Initializes the locale based on the current request.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jérôme Tamarelle <jerome@tamarelle.net>
*/
class LocaleListener extends BaseLocaleListener
class LocaleListener implements EventSubscriberInterface
{
protected $app;
private $app;
private $defaultLocale;
private $requestStack;
private $requestContext;
public function __construct(Container $app, RequestContextAwareInterface $router = null, RequestStack $requestStack = null)
public function __construct(Container $app, $defaultLocale = 'en', RequestStack $requestStack, RequestContext $requestContext = null)
{
parent::__construct($app['locale'], $router, $requestStack);
$this->app = $app;
$this->defaultLocale = $defaultLocale;
$this->requestStack = $requestStack;
$this->requestContext = $requestContext;
}
public function onKernelRequest(GetResponseEvent $event)
{
parent::onKernelRequest($event);
$request = $event->getRequest();
$request->setDefaultLocale($this->defaultLocale);
$this->setLocale($request);
$this->setRouterContext($request);
$this->app['locale'] = $event->getRequest()->getLocale();
$this->app['locale'] = $request->getLocale();
}
public function onKernelFinishRequest(FinishRequestEvent $event)
{
if (null !== $parentRequest = $this->requestStack->getParentRequest()) {
$this->setRouterContext($parentRequest);
}
}
private function setLocale(Request $request)
{
if ($locale = $request->attributes->get('_locale')) {
$request->setLocale($locale);
}
}
private function setRouterContext(Request $request)
{
if (null !== $this->requestContext) {
$this->requestContext->setParameter('_locale', $request->getLocale());
}
}
public static function getSubscribedEvents()
{
return array(
// must be registered after the Router to have access to the _locale
KernelEvents::REQUEST => array(array('onKernelRequest', 16)),
KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)),
);
}
}
......@@ -15,7 +15,6 @@ use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Silex\Api\EventListenerProviderInterface;
use Silex\Provider\Locale\LocaleListener;
use Silex\Provider\Routing\LazyUrlMatcher;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
......@@ -28,14 +27,7 @@ class LocaleServiceProvider implements ServiceProviderInterface, EventListenerPr
public function register(Container $app)
{
$app['locale.listener'] = function ($app) {
$urlMatcher = null;
if (isset($app['url_matcher'])) {
$urlMatcher = new LazyUrlMatcher(function () use ($app) {
return $app['url_matcher'];
});
}
return new LocaleListener($app, $urlMatcher, $app['request_stack']);
return new LocaleListener($app, $app['locale'], $app['request_stack'], isset($app['request_context']) ? $app['request_context'] : null);
};
$app['locale'] = 'en';
......
......@@ -11,15 +11,16 @@
namespace Silex\Provider\Routing;
use Symfony\Component\Routing\RequestContext as SymfonyRequestContext;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
/**
* Implements a lazy UrlMatcher.
*
* @author Igor Wiedler <igor@wiedler.ch>
* @author Jérôme Tamarelle <jerome@tamarelle.net>
*/
class LazyUrlMatcher implements UrlMatcherInterface
class LazyRequestMatcher implements RequestMatcherInterface
{
private $factory;
......@@ -29,41 +30,25 @@ class LazyUrlMatcher implements UrlMatcherInterface
}
/**
* Returns the corresponding UrlMatcherInterface instance.
* Returns the corresponding RequestMatcherInterface instance.
*
* @return UrlMatcherInterface
*/
public function getUrlMatcher()
public function getRequestMatcher()
{
$urlMatcher = call_user_func($this->factory);
if (!$urlMatcher instanceof UrlMatcherInterface) {
throw new \LogicException("Factory supplied to LazyUrlMatcher must return implementation of UrlMatcherInterface.");
$matcher = call_user_func($this->factory);
if (!$matcher instanceof RequestMatcherInterface) {
throw new \LogicException("Factory supplied to LazyRequestMatcher must return implementation of Symfony\Component\Routing\RequestMatcherInterface.");
}
return $urlMatcher;
return $matcher;
}
/**
* {@inheritdoc}
*/
public function match($pathinfo)
public function matchRequest(Request $request)
{
return $this->getUrlMatcher()->match($pathinfo);
}
/**
* {@inheritdoc}
*/
public function setContext(SymfonyRequestContext $context)
{
$this->getUrlMatcher()->setContext($context);
}
/**
* {@inheritdoc}
*/
public function getContext()
{
return $this->getUrlMatcher()->getContext();
return $this->getRequestMatcher()->matchRequest($request);
}
}
......@@ -15,7 +15,7 @@ use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Silex\Api\EventListenerProviderInterface;
use Silex\Provider\Routing\RedirectableUrlMatcher;
use Silex\Provider\Routing\LazyUrlMatcher;
use Silex\Provider\Routing\LazyRequestMatcher;
use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\HttpKernel\EventListener\RouterListener;
......@@ -34,7 +34,7 @@ class RoutingServiceProvider implements ServiceProviderInterface, EventListenerP
return new UrlGenerator($app['routes'], $app['request_context']);
};
$app['url_matcher'] = function () use ($app) {
$app['request_matcher'] = function () use ($app) {
return new RedirectableUrlMatcher($app['routes'], $app['request_context']);
};
......@@ -48,8 +48,8 @@ class RoutingServiceProvider implements ServiceProviderInterface, EventListenerP
};
$app['routing.listener'] = function () use ($app) {
$urlMatcher = new LazyUrlMatcher(function () use ($app) {
return $app['url_matcher'];
$urlMatcher = new LazyRequestMatcher(function () use ($app) {
return $app['request_matcher'];
});
return new RouterListener($urlMatcher, $app['request_context'], $app['logger'], $app['request_stack']);
......
......@@ -311,7 +311,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
};
$app['security.http_utils'] = function ($app) {
return new HttpUtils(isset($app['url_generator']) ? $app['url_generator'] : null, $app['url_matcher']);
return new HttpUtils(isset($app['url_generator']) ? $app['url_generator'] : null, $app['request_matcher']);
};
$app['security.last_error'] = $app->protect(function (Request $request) {
......
<?php
/*
* This file is part of the Silex framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Silex\Tests;
use Symfony\Component\HttpFoundation\Request;
use Silex\Provider\Routing\LazyRequestMatcher;
/**
* LazyRequestMatcher test case.
*
* @author Leszek Prabucki <leszek.prabucki@gmail.com>
*/
class LazyRequestMatcherTest extends \PHPUnit_Framework_TestCase
{
/**
* @covers Silex\LazyRequestMatcher::getResquestMatcher
*/
public function testUserMatcherIsCreatedLazily()
{
$callCounter = 0;
$requestMatcher = $this->getMock('Symfony\Component\Routing\Matcher\RequestMatcherInterface');
$matcher = new LazyRequestMatcher(function () use ($requestMatcher, &$callCounter) {
$callCounter++;
return $requestMatcher;
});
$this->assertEquals(0, $callCounter);
$request = Request::create('path');
$matcher->matchRequest($request);
$this->assertEquals(1, $callCounter);
}
/**
* @expectedException LogicException
* @expectedExceptionMessage Factory supplied to LazyRequestMatcher must return implementation of Symfony\Component\Routing\RequestMatcherInterface.
*/
public function testThatCanInjectResquestMatcherOnly()
{
$matcher = new LazyRequestMatcher(function () {
return 'someMatcher';
});
$request = Request::create('path');
$matcher->matchRequest($request);
}
/**
* @covers Silex\LazyRequestMatcher::matchRequest
*/
public function testMatchIsProxy()
{
$request = Request::create('path');
$matcher = $this->getMock('Symfony\Component\Routing\Matcher\RequestMatcherInterface');
$matcher->expects($this->once())
->method('matchRequest')
->with($request)
->will($this->returnValue('matcherReturnValue'));
$matcher = new LazyRequestMatcher(function () use ($matcher) {
return $matcher;
});
$result = $matcher->matchRequest($request);
$this->assertEquals('matcherReturnValue', $result);
}
}
<?php
/*
* This file is part of the Silex framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Silex\Tests;
use Silex\Provider\Routing\LazyUrlMatcher;
/**
* LazyUrlMatcher test case.
*
* @author Leszek Prabucki <leszek.prabucki@gmail.com>
*/
class LazyUrlMatcherTest extends \PHPUnit_Framework_TestCase
{
/**
* @covers Silex\LazyUrlMatcher::getUrlMatcher
*/
public function testUserMatcherIsCreatedLazily()
{
$callCounter = 0;
$urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface');
$matcher = new LazyUrlMatcher(function () use ($urlMatcher, &$callCounter) {
$callCounter++;
return $urlMatcher;
});
$this->assertEquals(0, $callCounter);
$matcher->match('path');
$this->assertEquals(1, $callCounter);
}
/**
* @expectedException LogicException
* @expectedExceptionMessage Factory supplied to LazyUrlMatcher must return implementation of UrlMatcherInterface.
*/
public function testThatCanInjectUrlMatcherOnly()
{
$matcher = new LazyUrlMatcher(function () {
return 'someMatcher';
});
$matcher->match('path');
}
/**
* @covers Silex\LazyUrlMatcher::match
*/
public function testMatchIsProxy()
{
$urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface');
$urlMatcher->expects($this->once())
->method('match')
->with('path')
->will($this->returnValue('matcherReturnValue'));
$matcher = new LazyUrlMatcher(function () use ($urlMatcher) {
return $urlMatcher;
});
$result = $matcher->match('path');
$this->assertEquals('matcherReturnValue', $result);
}
/**
* @covers Silex\LazyUrlMatcher::setContext
*/
public function testSetContextIsProxy()
{
$context = $this->getMock('Symfony\Component\Routing\RequestContext');
$urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface');
$urlMatcher->expects($this->once())
->method('setContext')
->with($context);
$matcher = new LazyUrlMatcher(function () use ($urlMatcher) {
return $urlMatcher;
});
$matcher->setContext($context);
}
/**
* @covers Silex\LazyUrlMatcher::getContext
*/
public function testGetContextIsProxy()
{
$context = $this->getMock('Symfony\Component\Routing\RequestContext');
$urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface');
$urlMatcher->expects($this->once())
->method('getContext')
->will($this->returnValue($context));
$matcher = new LazyUrlMatcher(function () use ($urlMatcher) {
return $urlMatcher;
});
$resultContext = $matcher->getContext();
$this->assertSame($resultContext, $context);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment