Commit e41c673b authored by Igor Wiedler's avatar Igor Wiedler

update to the latest Symfony2 code base (new EventDispatcher)

bschussek made significant changes to the EventDispatcher implementation
to make it similar to the one Doctrine2 uses.

most significant change in this commit is that returning something from
an error handler will now stop propagation.
parent 8d41c599
<?php
/*
* This file is part of the Symfony 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;
/**
* @author Igor Wiedler <igor@wiedler.ch>
*/
final class Events
{
const onSilexBefore = 'onSilexBefore';
const onSilexAfter = 'onSilexAfter';
const onSilexError = 'onSilexError';
}
...@@ -13,11 +13,13 @@ namespace Silex; ...@@ -13,11 +13,13 @@ namespace Silex;
use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\Controller\ControllerResolver; use Symfony\Component\HttpKernel\Controller\ControllerResolver;
use Symfony\Component\HttpKernel\Event\KernelEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route; use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\Matcher\UrlMatcher; use Symfony\Component\Routing\Matcher\UrlMatcher;
...@@ -27,10 +29,11 @@ use Symfony\Component\Routing\Matcher\UrlMatcher; ...@@ -27,10 +29,11 @@ use Symfony\Component\Routing\Matcher\UrlMatcher;
* *
* @author Fabien Potencier <fabien.potencier@symfony-project.org> * @author Fabien Potencier <fabien.potencier@symfony-project.org>
*/ */
class Framework extends HttpKernel class Framework extends HttpKernel implements EventSubscriberInterface
{ {
protected $routes; private $dispatcher;
protected $request; private $routes;
private $request;
/** /**
* Constructor. * Constructor.
...@@ -39,15 +42,13 @@ class Framework extends HttpKernel ...@@ -39,15 +42,13 @@ class Framework extends HttpKernel
{ {
$this->routes = new RouteCollection(); $this->routes = new RouteCollection();
$dispatcher = new EventDispatcher(); $this->dispatcher = new EventDispatcher();
$dispatcher->connect('core.request', array($this, 'parseRequest')); $this->dispatcher->addSubscriber($this);
$dispatcher->connect('core.request', array($this, 'runBeforeFilters')); $this->dispatcher->addListener(\Symfony\Component\HttpKernel\Events::onCoreView, $this, -10);
$dispatcher->connect('core.view', array($this, 'handleStringResponse'), -10);
$dispatcher->connect('core.response', array($this, 'runAfterFilters'));
$dispatcher->connect('core.exception', array($this, 'handleException'));
$resolver = new ControllerResolver(); $resolver = new ControllerResolver();
parent::__construct($dispatcher, $resolver); parent::__construct($this->dispatcher, $resolver);
} }
/** /**
...@@ -172,7 +173,7 @@ class Framework extends HttpKernel ...@@ -172,7 +173,7 @@ class Framework extends HttpKernel
*/ */
public function before($callback) public function before($callback)
{ {
$this->dispatcher->connect('silex.before', $callback); $this->dispatcher->addListener(Events::onSilexBefore, $callback);
return $this; return $this;
} }
...@@ -190,7 +191,7 @@ class Framework extends HttpKernel ...@@ -190,7 +191,7 @@ class Framework extends HttpKernel
*/ */
public function after($callback) public function after($callback)
{ {
$this->dispatcher->connect('silex.after', $callback); $this->dispatcher->addListener(Events::onSilexAfter, $callback);
return $this; return $this;
} }
...@@ -202,9 +203,11 @@ class Framework extends HttpKernel ...@@ -202,9 +203,11 @@ class Framework extends HttpKernel
* as an argument. If a controller throws an exception, an error handler * as an argument. If a controller throws an exception, an error handler
* can return a specific response. * can return a specific response.
* *
* When an exception occurs, all registered error handlers will be called. * When an exception occurs, all handlers will be called, until one returns
* The first response a handler returns (it may also return nothing) will * something (a string or a Response object), at which point that will be
* then be served. * returned to the client.
*
* For this reason you should add logging handlers before output handlers.
* *
* This method is chainable. * This method is chainable.
* *
...@@ -214,13 +217,12 @@ class Framework extends HttpKernel ...@@ -214,13 +217,12 @@ class Framework extends HttpKernel
*/ */
public function error($callback) public function error($callback)
{ {
$this->dispatcher->connect('silex.error', function(EventInterface $event) use ($callback) { $this->dispatcher->addListener(Events::onSilexError, function(GetResponseForErrorEvent $event) use ($callback) {
$exception = $event->get('exception'); $exception = $event->getException();
$result = $callback($exception); $result = $callback->__invoke($exception);
if (null !== $result) { if (null !== $result) {
$event->setProcessed(); $event->setStringResponse($result);
return $result;
} }
}); });
...@@ -244,13 +246,11 @@ class Framework extends HttpKernel ...@@ -244,13 +246,11 @@ class Framework extends HttpKernel
} }
/** /**
* Handler for core.request * Handler for onCoreRequest.
*
* @see __construct()
*/ */
public function parseRequest(EventInterface $event) public function onCoreRequest(KernelEvent $event)
{ {
$this->request = $event->get('request'); $this->request = $event->getRequest();
$matcher = new UrlMatcher($this->routes, array( $matcher = new UrlMatcher($this->routes, array(
'base_url' => $this->request->getBaseUrl(), 'base_url' => $this->request->getBaseUrl(),
...@@ -259,85 +259,64 @@ class Framework extends HttpKernel ...@@ -259,85 +259,64 @@ class Framework extends HttpKernel
'is_secure' => $this->request->isSecure(), 'is_secure' => $this->request->isSecure(),
)); ));
if (false === $attributes = $matcher->match($this->request->getPathInfo())) { if (false !== $attributes = $matcher->match($this->request->getPathInfo())) {
return false; $this->request->attributes->add($attributes);
} }
$this->request->attributes->add($attributes); $this->dispatcher->dispatch(Events::onSilexBefore);
} }
/** /**
* Handler for core.request * Handles string responses.
* *
* Runs before filters right after the request comes in. * Handler for onCoreView.
*
* @see __construct()
*/ */
public function runBeforeFilters(EventInterface $event) public function onCoreView(GetResponseForControllerResultEvent $event)
{ {
$this->dispatcher->notify(new Event(null, 'silex.before')); $response = $event->getControllerResult();
$converter = new StringResponseConverter();
$event->setResponse($converter->convert($response));
} }
/** /**
* Handler for core.view * Runs after filters.
*
* Calls parseStringResponse to handle string responses.
* *
* @see __construct() * Handler for onCoreResponse.
* @see parseStringResponse()
*/
public function handleStringResponse(EventInterface $event)
{
$response = $event->get('controller_value');
if ( ! $response instanceof Response) {
$event->setProcessed(true);
return $this->parseStringResponse($response);
}
}
/**
* Converts string responses to Response objects.
*/ */
protected function parseStringResponse($response) public function onCoreResponse(Event $event)
{ {
if ( ! $response instanceof Response) { $this->dispatcher->dispatch(Events::onSilexAfter);
return new Response((string) $response);
} else {
return $response;
}
} }
/** /**
* Handler for core.view * Executes registered error handlers until a response is returned,
* in which case it returns it to the client.
* *
* Runs after filters. * Handler for onCoreException.
* *
* @see __construct() * @see error()
*/ */
public function runAfterFilters(EventInterface $event, $response) public function onCoreException(GetResponseForExceptionEvent $event)
{ {
$this->dispatcher->notify(new Event(null, 'silex.after')); $errorEvent = new GetResponseForErrorEvent($this, $event->getRequest(), $event->getRequestType(), $event->getException());
$this->dispatcher->dispatch(Events::onSilexError, $errorEvent);
return $response; if ($errorEvent->hasResponse()) {
$event->setResponse($errorEvent->getResponse());
}
} }
/** /**
* Handler for core.exception * {@inheritdoc}
*
* Executes registered error handlers until a response is returned,
* in which case it returns it to the client.
*
* @see error()
*/ */
public function handleException(EventInterface $event) static public function getSubscribedEvents()
{ {
$errorEvent = new Event(null, 'silex.error', $event->all()); // onCoreView listener is added manually because it has lower priority
$result = $this->dispatcher->notifyUntil($errorEvent);
if ($errorEvent->isProcessed()) { return array(
$event->setProcessed(); \Symfony\Component\HttpKernel\Events::onCoreRequest,
$response = $this->parseStringResponse($result); \Symfony\Component\HttpKernel\Events::onCoreResponse,
return $response; \Symfony\Component\HttpKernel\Events::onCoreException,
} );
} }
} }
<?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 Silex;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Request;
/**
* GetResponseForExceptionEvent with additional setStringResponse method
*
* setStringResponse will convert strings to response objects.
*
* @author Igor Wiedler <igor@wiedler.ch>
*/
class GetResponseForErrorEvent extends GetResponseForExceptionEvent
{
public function setStringResponse($response)
{
$converter = new StringResponseConverter();
$this->setResponse($converter->convert($response));
}
}
\ No newline at end of file
<?php
/*
* This file is part of the Silex framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Silex;
use Symfony\Component\HttpFoundation\Response;
/**
* Converts string responses to Response objects.
*
* @author Igor Wiedler <igor@wiedler.ch>
*/
class StringResponseConverter
{
/**
* Do the conversion
*
* @param $response The response string
* @return A response object
*/
public function convert($response)
{
if ( ! $response instanceof Response) {
return new Response((string) $response);
} else {
return $response;
}
}
}
Subproject commit 9e2262e6a40468cb3e50237c4d7759afbf574efe Subproject commit 6ace6af537da1e42ccefdb5c6143a3e62f801552
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