Commit 056fc32f authored by Fabien Potencier's avatar Fabien Potencier

refactored Silex events (refs #503, refs #504, refs #452)

Removed the SilexEvents class. Using the standard Symfony events allows
us to be more flexible (the priorities are the same as the one from
Symfony, so you can hook at any place into the HTTP handling).

Updated documentation to make it accurate with the current behavior, and
extended it to explain the flexibility the developer has.
parent 52a2fdaf
......@@ -47,9 +47,11 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
{
const VERSION = '1.0-DEV';
const EARLY_EVENT = 512;
const LATE_EVENT = -512;
private $providers = array();
private $booted = false;
private $beforeDispatched = false;
/**
* Constructor.
......@@ -281,7 +283,11 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
*/
public function before($callback, $priority = 0)
{
$this['dispatcher']->addListener(SilexEvents::BEFORE, function (GetResponseEvent $event) use ($callback) {
$this['dispatcher']->addListener(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($callback) {
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
$ret = call_user_func($callback, $event->getRequest());
if ($ret instanceof Response) {
......@@ -301,8 +307,10 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
*/
public function after($callback, $priority = 0)
{
$this['dispatcher']->addListener(SilexEvents::AFTER, function (FilterResponseEvent $event) use ($callback) {
$this['dispatcher']->addListener(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($callback) {
if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()) {
call_user_func($callback, $event->getRequest(), $event->getResponse());
}
}, $priority);
}
......@@ -317,7 +325,7 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
*/
public function finish($callback, $priority = 0)
{
$this['dispatcher']->addListener(SilexEvents::FINISH, function (PostResponseEvent $event) use ($callback) {
$this['dispatcher']->addListener(KernelEvents::TERMINATE, function (PostResponseEvent $event) use ($callback) {
call_user_func($callback, $event->getRequest(), $event->getResponse());
}, $priority);
}
......@@ -349,11 +357,12 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
*
* @param mixed $callback Error handler callback, takes an Exception argument
* @param integer $priority The higher this value, the earlier an event
* listener will be triggered in the chain (defaults to 0)
* listener will be triggered in the chain (defaults to -8)
*/
public function error($callback, $priority = 0)
public function error($callback, $priority = -8)
{
$this['dispatcher']->addListener(SilexEvents::ERROR, function (GetResponseForExceptionEvent $event) use ($callback) {
$app = $this;
$this['dispatcher']->addListener(KernelEvents::EXCEPTION, function (GetResponseForExceptionEvent $event) use ($callback, $app) {
$exception = $event->getException();
if (is_array($callback)) {
......@@ -498,8 +507,6 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
$this->boot();
}
$this->beforeDispatched = false;
$current = HttpKernelInterface::SUB_REQUEST === $type ? $this['request'] : $this['request_error'];
$this['request'] = $request;
......@@ -540,22 +547,11 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
* Runs before filters.
*
* @param GetResponseEvent $event The event to handle
*
* @see before()
*/
public function onKernelRequest(GetResponseEvent $event)
{
$this['locale'] = $event->getRequest()->getLocale();
if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()) {
$this->beforeDispatched = true;
$this['dispatcher']->dispatch(SilexEvents::BEFORE, $event);
if ($event->hasResponse()) {
return;
}
}
$this['route_before_middlewares_trigger']($event);
}
......@@ -592,53 +588,10 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
* Runs after filters.
*
* @param FilterResponseEvent $event The event to handle
*
* @see after()
*/
public function onKernelResponse(FilterResponseEvent $event)
{
$this['route_after_middlewares_trigger']($event);
if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()) {
$this['dispatcher']->dispatch(SilexEvents::AFTER, $event);
}
}
/**
* Runs finish filters.
*
* @param PostResponseEvent $event The event to handle
*
* @see finish()
*/
public function onKernelTerminate(PostResponseEvent $event)
{
$this['dispatcher']->dispatch(SilexEvents::FINISH, $event);
}
/**
* Runs error filters.
*
* Executes registered error handlers until a response is returned,
* in which case it returns it to the client.
*
* @param GetResponseForExceptionEvent $event The event to handle
*
* @see error()
*/
public function onKernelException(GetResponseForExceptionEvent $event)
{
if (!$this->beforeDispatched) {
$this->beforeDispatched = true;
try {
$this['dispatcher']->dispatch(SilexEvents::BEFORE, $event);
} catch (\Exception $e) {
// as we are already handling an exception, ignore this one
// even if it might have been thrown on purpose by the developer
}
}
$this['dispatcher']->dispatch(SilexEvents::ERROR, $event);
}
/**
......@@ -649,12 +602,10 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
return array(
KernelEvents::REQUEST => array(
array('onEarlyKernelRequest', 256),
array('onKernelRequest')
array('onKernelRequest', -128)
),
KernelEvents::CONTROLLER => 'onKernelController',
KernelEvents::RESPONSE => 'onKernelResponse',
KernelEvents::EXCEPTION => array('onKernelException', -10),
KernelEvents::TERMINATE => 'onKernelTerminate',
KernelEvents::RESPONSE => array('onKernelResponse', 128),
KernelEvents::VIEW => array('onKernelView', -10),
);
}
......
......@@ -14,6 +14,7 @@ namespace Silex;
use Symfony\Component\HttpKernel\Debug\ExceptionHandler as DebugExceptionHandler;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Defaults exception handler.
......@@ -41,6 +42,6 @@ class ExceptionHandler implements EventSubscriberInterface
*/
public static function getSubscribedEvents()
{
return array(SilexEvents::ERROR => array('onSilexError', -255));
return array(KernelEvents::EXCEPTION => array('onSilexError', -255));
}
}
<?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;
/**
* The Silex events.
*
* @author Igor Wiedler <igor@wiedler.ch>
*/
final class SilexEvents
{
const BEFORE = 'silex.before';
const AFTER = 'silex.after';
const FINISH = 'silex.finish';
const ERROR = 'silex.error';
}
......@@ -147,7 +147,7 @@ class BeforeAfterFilterTest extends \PHPUnit_Framework_TestCase
$app->before(function () use (&$i) {
$i++;
});
}, Application::EARLY_EVENT);
$app->after(function () use (&$i) {
$i++;
......@@ -193,18 +193,18 @@ class BeforeAfterFilterTest extends \PHPUnit_Framework_TestCase
$app = new Application();
$app->before(function () use ($app) {
$app['locale'] = $app['request']->get('locale');
$app['project'] = $app['request']->get('project');
});
$app->match('/foo/{locale}', function () use ($app) {
return $app['locale'];
$app->match('/foo/{project}', function () use ($app) {
return $app['project'];
});
$request = Request::create('/foo/en');
$this->assertEquals('en', $app->handle($request)->getContent());
$request = Request::create('/foo/bar');
$this->assertEquals('bar', $app->handle($request)->getContent());
$request = Request::create('/foo/de');
$this->assertEquals('de', $app->handle($request)->getContent());
$request = Request::create('/foo/baz');
$this->assertEquals('baz', $app->handle($request)->getContent());
}
public function testBeforeFilterAccessesRequestAndCanReturnResponse()
......
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