Commit 51df9f5a authored by Igor Wiedler's avatar Igor Wiedler

Create default set of listeners late

Right now the following subscribers are created together with the
dispatcher:

* app
* exception_handler
* ResponseListener
* RouterListener

With the exception_handler in particular this is an issue because you
can no longer change it after the dispatcher has been created. And it
gets created when you call before(), after() or error(). It means that
you cannot unset it for tests.

The RouterListener has a similar issue because you can no longer change
the UrlMatcher it uses. And you cannot move its creation into a request
listener, because request listeners cannot add other request listeners
(the new ones won't get executed anymore at that point).

This commit ensures that those listeners will be created a lot later,
allowing their dependencies to be modified before runtime.
parent bcb367ed
...@@ -80,11 +80,11 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe ...@@ -80,11 +80,11 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
$this['dispatcher'] = $this->share(function () use ($app) { $this['dispatcher'] = $this->share(function () use ($app) {
$dispatcher = new EventDispatcher(); $dispatcher = new EventDispatcher();
$dispatcher->addSubscriber($app); $dispatcher->addSubscriber($app);
if (isset($app['exception_handler'])) {
$dispatcher->addSubscriber($app['exception_handler']); $urlMatcher = new LazyUrlMatcher(function () use ($app) {
} return $app['url_matcher'];
$dispatcher->addSubscriber(new ResponseListener($app['charset'])); });
$dispatcher->addSubscriber(new RouterListener($app['url_matcher'])); $dispatcher->addSubscriber(new RouterListener($urlMatcher));
return $dispatcher; return $dispatcher;
}); });
...@@ -354,6 +354,19 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe ...@@ -354,6 +354,19 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
return $this['kernel']->handle($request, $type, $catch); return $this['kernel']->handle($request, $type, $catch);
} }
/**
* Handles onEarlyKernelRequest events.
*/
public function onEarlyKernelRequest(KernelEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()) {
if (isset($this['exception_handler'])) {
$this['dispatcher']->addSubscriber($this['exception_handler']);
}
$this['dispatcher']->addSubscriber(new ResponseListener($this['charset']));
}
}
/** /**
* Handles onKernelRequest events. * Handles onKernelRequest events.
*/ */
...@@ -434,7 +447,10 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe ...@@ -434,7 +447,10 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
static public function getSubscribedEvents() static public function getSubscribedEvents()
{ {
return array( return array(
KernelEvents::REQUEST => 'onKernelRequest', KernelEvents::REQUEST => array(
array('onEarlyKernelRequest', 256),
array('onKernelRequest')
),
KernelEvents::CONTROLLER => 'onKernelController', KernelEvents::CONTROLLER => 'onKernelController',
KernelEvents::RESPONSE => 'onKernelResponse', KernelEvents::RESPONSE => 'onKernelResponse',
KernelEvents::EXCEPTION => 'onKernelException', KernelEvents::EXCEPTION => 'onKernelException',
......
<?php
/*
* This file is part of the Silex framework.
*
* (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 Silex;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
/**
* Implements the RedirectableUrlMatcherInterface for Silex.
*
* @author Igor Wiedler <igor@wiedler.ch>
*/
class LazyUrlMatcher implements UrlMatcherInterface
{
private $factory;
private $urlMatcher;
public function __construct(\Closure $factory)
{
$this->factory = $factory;
}
public function getUrlMatcher()
{
$urlMatcher = call_user_func($this->factory);
if (!$urlMatcher instanceof UrlMatcherInterface) {
throw new \LogicException("Factory supplied to LazyUrlMatcher must return implementation of UrlMatcherInterface.");
}
return $urlMatcher;
}
/**
* {@inheritdoc}
*/
public function match($pathinfo)
{
return $this->getUrlMatcher()->match($pathinfo);
}
/**
* {@inheritdoc}
*/
public function setContext(RequestContext $context)
{
$this->getUrlMatcher()->setContext($context);
}
/**
* {@inheritdoc}
*/
public function getContext()
{
return $this->getUrlMatcher()->getContext();
}
}
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