Merge branch 'events'

* events:
  [FrameworkBundle] fixed the traceable event manager
  [EventDispatcher] made order deterministic (first registered one stay first) -- this makes the new system more compatible with the old one
  [FrameworkBundle] fixed class loading order
  fixed various bugs introduced during the event system migration
  renamed filterCore* to onCore*
  fixed CS
  fixed phpdoc
  renamed some methods in the event dispatcher
  [HttpKernel] Removed unused onCoreSecurity event
  [Security] Fixed method names in the Firewall listeners
  [HttpKernel] Added more code documentation to the HttpKernel events
  [Security] Fixed method calls on EventDispatcher
  [FrameworkBundle] Removed EventSubscriber support for DI tags because it currently cannot be implemented
  [Security] Fixed calls to EventDispatcher::dispatchEvent()
  Switched from Doctrine's EventManager implementation to the EventManager clone in Symfony2 (now called EventDispatcher again)
  [EventDispatcher] Replaced EventDispatcher by Doctrine's implementation
  Renamed EventArgs classes and adapted remaining code to EventManager
  Replaced EventDispatcher by Doctrine's EventManager implementation
This commit is contained in:
Fabien Potencier 2011-03-18 07:52:05 +01:00
commit 9de0a3872b
90 changed files with 1787 additions and 1295 deletions

View File

@ -14,11 +14,12 @@ namespace Symfony\Bundle\AsseticBundle\Command;
use Assetic\Asset\AssetInterface;
use Assetic\Factory\LazyAssetManager;
use Symfony\Bundle\FrameworkBundle\Command\Command;
use Symfony\Bundle\AsseticBundle\Event\WriteEvent;
use Symfony\Bundle\AsseticBundle\Events;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\EventDispatcher\Event;
/**
* Dumps assets to the filesystem.
@ -46,7 +47,8 @@ class DumpCommand extends Command
$am = $this->container->get('assetic.asset_manager');
// notify an event so custom stream wrappers can be registered lazily
$this->container->get('event_dispatcher')->notify(new Event(null, 'assetic.write', array('path' => $basePath)));
$event = new WriteEvent($basePath);
$this->container->get('event_dispatcher')->dispatch(Events::onAsseticWrite, $writeEvent);
if ($input->getOption('watch')) {
return $this->watch($am, $basePath, $output, $this->container->getParameter('kernel.debug'));

View File

@ -0,0 +1,32 @@
<?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 Symfony\Bundle\AsseticBundle\Event;
use Symfony\Component\EventDispatcher\Event;
/**
* @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
*/
class WriteEvent extends Event
{
private $targetPath;
public function __construct($targetPath = null)
{
$this->targetPath = $targetPath;
}
public function getTargetPath()
{
return $this->targetPath;
}
}

View File

@ -0,0 +1,20 @@
<?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 Symfony\Bundle\AsseticBundle;
/**
* @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
*/
final class Events
{
const onAsseticWrite = 'onAsseticWrite';
}

View File

@ -36,7 +36,7 @@ class ConnectionFactory
/**
* Create a connection by name.
*
*
* @param string $connectionName
* @return Doctrine\DBAL\Connection
*/

View File

@ -32,7 +32,7 @@ class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface
);
foreach ($subscribers as $id => $instances) {
$definition->addMethodCall('addEventSubscriber', array(new Reference($id)));
$definition->addMethodCall('addSubscriber', array(new Reference($id)));
}
}
@ -52,7 +52,7 @@ class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface
}
if (0 < count($events)) {
$definition->addMethodCall('addEventListener', array(
$definition->addMethodCall('addListener', array(
$events,
new Reference($listenerId),
));

View File

@ -3,7 +3,7 @@
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
* (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.

View File

@ -29,7 +29,7 @@ class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface
);
foreach ($subscribers as $id => $instances) {
$definition->addMethodCall('addEventSubscriber', array(new Reference($id)));
$definition->addMethodCall('addSubscriber', array(new Reference($id)));
}
}
@ -49,7 +49,7 @@ class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface
}
if (0 < count($events)) {
$definition->addMethodCall('addEventListener', array(
$definition->addMethodCall('addListener', array(
$events,
new Reference($listenerId),
));

View File

@ -0,0 +1,87 @@
<?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\Bundle\FrameworkBundle;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
/**
* Lazily loads listeners and subscribers from the dependency injection
* container
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Bernhard Schussek <bernhard.schussek@symfony.com>
*/
class ContainerAwareEventDispatcher extends EventDispatcher
{
/**
* The container from where services are loaded
* @var ContainerInterface
*/
private $container;
/**
* The service IDs of the event listeners and subscribers
* @var array
*/
private $listenerIds;
/**
* Constructor.
*
* @param ContainerInterface $container A ContainerInterface instance
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
/**
* Adds a service as event listener
*
* @param string|array $events One or more events for which the listener
* is added
* @param string $serviceId The ID of the listener service
* @param integer $priority The higher this value, the earlier an event
* listener will be triggered in the chain.
* Defaults to 0.
*/
public function addListenerService($events, $serviceId, $priority = 0)
{
if (!is_string($serviceId)) {
throw new \InvalidArgumentException('Expected a string argument');
}
foreach ((array)$events as $event) {
// Prevent duplicate entries
$this->listenerIds[$event][$serviceId] = $priority;
}
}
/**
* {@inheritDoc}
*
* Lazily loads listeners for this event from the dependency injection
* container.
*/
public function dispatch($eventName, Event $event = null)
{
if (isset($this->listenerIds[$eventName])) {
foreach ($this->listenerIds[$eventName] as $serviceId => $priority) {
$this->addListener($eventName, $this->container->get($serviceId), $priority);
}
}
parent::dispatch($eventName, $event);
}
}

View File

@ -1,166 +0,0 @@
<?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\Bundle\FrameworkBundle\Debug;
use Symfony\Bundle\FrameworkBundle\EventDispatcher as BaseEventDispatcher;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Debug\EventDispatcherTraceableInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* EventDispatcher extends the original EventDispatcher class to add some debugging tools.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class EventDispatcher extends BaseEventDispatcher implements EventDispatcherTraceableInterface
{
protected $logger;
protected $called;
/**
* Constructor.
*
* @param ContainerInterface $container A ContainerInterface instance
* @param LoggerInterface $logger A LoggerInterface instance
*/
public function __construct(ContainerInterface $container, LoggerInterface $logger = null)
{
parent::__construct($container);
$this->logger = $logger;
$this->called = array();
}
/**
* {@inheritDoc}
*/
public function notify(EventInterface $event)
{
foreach ($this->getListeners($event->getName()) as $listener) {
$this->addCall($event, $listener, 'notify');
if (is_array($listener) && is_string($listener[0])) {
$listener[0] = $this->container->get($listener[0]);
}
call_user_func($listener, $event);
}
}
/**
* {@inheritDoc}
*/
public function notifyUntil(EventInterface $event)
{
foreach ($this->getListeners($event->getName()) as $i => $listener) {
$this->addCall($event, $listener, 'notifyUntil');
if (is_array($listener) && is_string($listener[0])) {
$listener[0] = $this->container->get($listener[0]);
}
$ret = call_user_func($listener, $event);
if ($event->isProcessed()) {
if (null !== $this->logger) {
$this->logger->debug(sprintf('Listener "%s" processed the event "%s"', $this->listenerToString($listener), $event->getName()));
$listeners = $this->getListeners($event->getName());
while (++$i < count($listeners)) {
$this->logger->debug(sprintf('Listener "%s" was not called for event "%s"', $this->listenerToString($listeners[$i]), $event->getName()));
}
}
return $ret;
}
}
}
/**
* {@inheritDoc}
*/
public function filter(EventInterface $event, $value)
{
foreach ($this->getListeners($event->getName()) as $listener) {
$this->addCall($event, $listener, 'filter');
if (is_array($listener) && is_string($listener[0])) {
$listener[0] = $this->container->get($listener[0]);
}
$value = call_user_func($listener, $event, $value);
}
return $value;
}
/**
* {@inheritDoc}
*/
public function getCalledListeners()
{
return $this->called;
}
/**
* {@inheritDoc}
*/
public function getNotCalledListeners()
{
$notCalled = array();
foreach (array_keys($this->listeners) as $name) {
foreach ($this->getListeners($name) as $listener) {
$listener = $this->listenerToString($listener);
if (!isset($this->called[$name.'.'.$listener])) {
$notCalled[] = array(
'event' => $name,
'listener' => $listener,
);
}
}
}
return $notCalled;
}
protected function listenerToString($listener)
{
if (is_object($listener) && $listener instanceof \Closure) {
return 'Closure';
}
if (is_string($listener)) {
return $listener;
}
if (is_array($listener)) {
return is_object($listener[0]) ? sprintf('%s::%s', get_class($listener[0]), $listener[1]) : implode(':', $listener);
}
}
protected function addCall(EventInterface $event, $listener, $type)
{
$listener = $this->listenerToString($listener);
if (null !== $this->logger) {
$this->logger->debug(sprintf('Notified event "%s" to listener "%s" (%s)', $event->getName(), $listener, $type));
}
$this->called[$event->getName().'.'.$listener] = array(
'event' => $event->getName(),
'caller' => null !== $event->getSubject() ? get_class($event->getSubject()) : null,
'listener' => $listener,
);
}
}

View File

@ -0,0 +1,123 @@
<?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\Bundle\FrameworkBundle\Debug;
use Symfony\Bundle\FrameworkBundle\ContainerAwareEventDispatcher;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcherInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\Event;
/**
* Extends the ContainerAwareEventDispatcher to add some debugging tools.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class TraceableEventDispatcher extends ContainerAwareEventDispatcher implements TraceableEventDispatcherInterface
{
protected $logger;
protected $called;
/**
* Constructor.
*
* @param ContainerInterface $container A ContainerInterface instance
* @param LoggerInterface $logger A LoggerInterface instance
*/
public function __construct(ContainerInterface $container, LoggerInterface $logger = null)
{
parent::__construct($container);
$this->logger = $logger;
$this->called = array();
}
/**
* {@inheritDoc}
*/
protected function triggerListener($listener, $eventName, Event $event)
{
parent::triggerListener($listener, $eventName, $event);
$listenerString = $this->listenerToString($listener);
if (null !== $this->logger) {
$this->logger->debug(sprintf('Notified event "%s" to listener "%s"', $eventName, $listenerString));
}
$this->called[$eventName.'.'.$listenerString] = array(
'class' => $listenerString,
'event' => $eventName,
);
if ($event->isPropagationStopped() && null !== $this->logger) {
$this->logger->debug(sprintf('Listener "%s" stopped propagation of the event "%s"', $this->listenerToString($listener), $eventName));
$skippedListeners = $this->getListeners($eventName);
$skipped = false;
foreach ($skippedListeners as $skippedListener) {
if ($skipped) {
$this->logger->debug(sprintf('Listener "%s" was not called for event "%s"', $this->listenerToString($skippedListener), $eventName));
}
if ($skippedListener === $listener) {
$skipped = false;
}
}
}
}
/**
* {@inheritDoc}
*/
public function getCalledListeners()
{
return $this->called;
}
/**
* {@inheritDoc}
*/
public function getNotCalledListeners()
{
$notCalled = array();
foreach (array_keys($this->getListeners()) as $name) {
foreach ($this->getListeners($name) as $listener) {
$listener = $this->listenerToString($listener);
if (!isset($this->called[$name.'.'.$listener])) {
$notCalled[] = array(
'class' => $listener,
'event' => $name,
);
}
}
}
return $notCalled;
}
protected function listenerToString($listener)
{
if (is_object($listener)) {
if ($listener instanceof \Closure) {
return 'Closure';
}
return get_class($listener);
}
if (is_array($listener)) {
return is_object($listener[0]) ? get_class($listener[0]) : implode('::', $listener);
}
}
}

View File

@ -24,30 +24,18 @@ class RegisterKernelListenersPass implements CompilerPassInterface
}
$listeners = array();
$definition = $container->getDefinition('event_dispatcher');
foreach ($container->findTaggedServiceIds('kernel.listener') as $id => $events) {
foreach ($events as $event) {
$priority = isset($event['priority']) ? $event['priority'] : 0;
if (!isset($event['event'])) {
throw new \InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "kernel.listener" tags.', $id));
}
if (!isset($event['method'])) {
throw new \InvalidArgumentException(sprintf('Service "%s" must define the "method" attribute on "kernel.listener" tags.', $id));
}
if (!isset($listeners[$event['event']][$priority])) {
if (!isset($listeners[$event['event']])) {
$listeners[$event['event']] = array();
}
$listeners[$event['event']][$priority] = array();
}
$listeners[$event['event']][$priority][] = array($id, $event['method']);
$definition->addMethodCall('addListenerService', array($event['event'], $id, $priority));
}
}
$container
->getDefinition('event_dispatcher')
->addMethodCall('registerKernelListeners', array($listeners))
;
}
}

View File

@ -140,17 +140,24 @@ class FrameworkExtension extends Extension
'Symfony\\Component\\HttpKernel\\ResponseListener',
'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver',
'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface',
'Symfony\\Component\\HttpKernel\\Event\\KernelEvent',
'Symfony\\Component\\HttpKernel\\Event\\FilterControllerEvent',
'Symfony\\Component\\HttpKernel\\Event\\FilterResponseEvent',
'Symfony\\Component\\HttpKernel\\Event\\GetResponseEvent',
'Symfony\\Component\\HttpKernel\\Event\\GetResponseForControllerResultEvent',
'Symfony\\Component\\HttpKernel\\Event\\GetResponseForExceptionEvent',
'Symfony\\Component\\HttpKernel\\Events',
'Symfony\\Component\\EventDispatcher\\EventDispatcher',
'Symfony\\Component\\EventDispatcher\\EventDispatcherInterface',
'Symfony\\Component\\EventDispatcher\\Event',
'Symfony\\Component\\EventDispatcher\\EventSubscriberInterface',
'Symfony\\Bundle\\FrameworkBundle\\RequestListener',
'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerNameParser',
'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver',
'Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller',
'Symfony\\Component\\EventDispatcher\\EventInterface',
'Symfony\\Component\\EventDispatcher\\Event',
'Symfony\\Component\\EventDispatcher\\EventDispatcherInterface',
'Symfony\\Component\\EventDispatcher\\EventDispatcher',
'Symfony\\Bundle\\FrameworkBundle\\EventDispatcher',
'Symfony\\Bundle\\FrameworkBundle\\ContainerAwareEventDispatcher',
));
}

View File

@ -1,86 +0,0 @@
<?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\Bundle\FrameworkBundle;
use Symfony\Component\EventDispatcher\EventDispatcher as BaseEventDispatcher;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventInterface;
/**
* This EventDispatcher automatically gets the kernel listeners injected
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class EventDispatcher extends BaseEventDispatcher
{
protected $container;
/**
* Constructor.
*
* @param ContainerInterface $container A ContainerInterface instance
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function registerKernelListeners(array $listeners)
{
$this->listeners = $listeners;
}
/**
* {@inheritdoc}
*/
public function notify(EventInterface $event)
{
foreach ($this->getListeners($event->getName()) as $listener) {
if (is_array($listener) && is_string($listener[0])) {
$listener[0] = $this->container->get($listener[0]);
}
call_user_func($listener, $event);
}
}
/**
* {@inheritdoc}
*/
public function notifyUntil(EventInterface $event)
{
foreach ($this->getListeners($event->getName()) as $listener) {
if (is_array($listener) && is_string($listener[0])) {
$listener[0] = $this->container->get($listener[0]);
}
$ret = call_user_func($listener, $event);
if ($event->isProcessed()) {
return $ret;
}
}
}
/**
* {@inheritdoc}
*/
public function filter(EventInterface $event, $value)
{
foreach ($this->getListeners($event->getName()) as $listener) {
if (is_array($listener) && is_string($listener[0])) {
$listener[0] = $this->container->get($listener[0]);
}
$value = call_user_func($listener, $event, $value);
}
return $value;
}
}

View File

@ -11,10 +11,10 @@
namespace Symfony\Bundle\FrameworkBundle\HttpFoundation;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
/**
* SessionListener.
@ -27,23 +27,18 @@ class SessionListener
{
/**
* Checks if session was initialized and saves if current request is master
* Runs on 'core.response' in test environment
* Runs on 'onCoreResponse' in test environment
*
* @param EventInterface $event
* @param Response $response
*
* @return Response
* @param FilterResponseEvent $event
*/
public function filter(EventInterface $event, Response $response)
public function onCoreResponse(FilterResponseEvent $event)
{
if ($request = $event->get('request')) {
if (HttpKernelInterface::MASTER_REQUEST === $event->get('request_type')) {
if ($request = $event->getRequest()) {
if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()) {
if ($session = $request->getSession()) {
$session->save();
}
}
}
return $response;
}
}

View File

@ -16,18 +16,14 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
*/
class HttpKernel extends BaseHttpKernel
{
protected $container;
protected $esiSupport;
private $container;
private $esiSupport;
public function __construct(ContainerInterface $container, ControllerResolverInterface $controllerResolver)
public function __construct(EventDispatcherInterface $dispatcher, ContainerInterface $container, ControllerResolverInterface $controllerResolver)
{
parent::__construct($dispatcher, $controllerResolver);
$this->container = $container;
$this->resolver = $controllerResolver;
}
public function setEventDispatcher(EventDispatcherInterface $dispatcher)
{
$this->dispatcher = $dispatcher;
}
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)

View File

@ -11,17 +11,16 @@
namespace Symfony\Bundle\FrameworkBundle\Profiler;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* ProfilerListener collects data for the current request by listening to the core.response event.
*
* The handleException method must be connected to the core.exception event.
* The handleResponse method must be connected to the core.response event.
* ProfilerListener collects data for the current request by listening to the onCoreResponse event.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
@ -47,49 +46,47 @@ class ProfilerListener
}
/**
* Handles the core.request event
* Handles the onCoreRequest event
*
* This method initialize the profiler to be able to get it as a scoped
* service when handleResponse() will collect the sub request
* service when onCoreResponse() will collect the sub request
*
* @param EventInterface $event An EventInterface instance
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public function handleRequest(EventInterface $event)
public function onCoreRequest(GetResponseEvent $event)
{
$this->container->get('profiler');
}
/**
* Handles the core.exception event.
* Handles the onCoreException event.
*
* @param EventInterface $event An EventInterface instance
* @param GetResponseForExceptionEvent $event A GetResponseForExceptionEvent instance
*/
public function handleException(EventInterface $event)
public function onCoreException(GetResponseForExceptionEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->get('request_type')) {
return false;
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
$this->exception = $event->get('exception');
return false;
$this->exception = $event->getException();
}
/**
* Handles the core.response event.
* Handles the onCoreResponse event.
*
* @param EventInterface $event An EventInterface instance
*
* @return Response $response A Response instance
* @param FilterResponseEvent $event A FilterResponseEvent instance
*/
public function handleResponse(EventInterface $event, Response $response)
public function onCoreResponse(FilterResponseEvent $event)
{
if (null !== $this->matcher && !$this->matcher->matches($event->get('request'))) {
$response = $event->getResponse();
if (null !== $this->matcher && !$this->matcher->matches($event->getRequest())) {
return $response;
}
if ($this->onlyException && null === $this->exception) {
return $response;
return;
}
$profiler = $this->container->get('profiler');
@ -98,9 +95,7 @@ class ProfilerListener
$profiler->setParent($parent['request']['profiler']->getToken());
}
$profiler->collect($event->get('request'), $response, $this->exception);
$profiler->collect($event->getRequest(), $event->getResponse(), $this->exception);
$this->exception = null;
return $response;
}
}

View File

@ -13,16 +13,14 @@ namespace Symfony\Bundle\FrameworkBundle;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* RequestListener.
*
* The handle method must be connected to the core.request event.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class RequestListener
@ -38,10 +36,10 @@ class RequestListener
$this->logger = $logger;
}
public function handle(EventInterface $event)
public function onCoreRequest(GetResponseEvent $event)
{
$request = $event->get('request');
$master = HttpKernelInterface::MASTER_REQUEST === $event->get('request_type');
$request = $event->getRequest();
$master = HttpKernelInterface::MASTER_REQUEST === $event->getRequestType();
$this->initializeSession($request, $master);

View File

@ -5,7 +5,7 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="debug.event_dispatcher.class">Symfony\Bundle\FrameworkBundle\Debug\EventDispatcher</parameter>
<parameter key="debug.event_dispatcher.class">Symfony\Bundle\FrameworkBundle\Debug\TraceableEventDispatcher</parameter>
</parameters>
<services>

View File

@ -13,7 +13,7 @@
<service id="esi" class="%esi.class%" public="false" />
<service id="esi_listener" class="%esi_listener.class%">
<tag name="kernel.listener" event="core.response" method="filter" />
<tag name="kernel.listener" event="onCoreResponse" />
<argument type="service" id="esi" on-invalid="ignore" />
</service>
</services>

View File

@ -23,9 +23,9 @@
</service>
<service id="profiler_listener" class="%profiler_listener.class%">
<tag name="kernel.listener" event="core.response" method="handleResponse" />
<tag name="kernel.listener" event="core.exception" method="handleException" />
<tag name="kernel.listener" event="core.request" method="handleRequest" />
<tag name="kernel.listener" event="onCoreResponse" />
<tag name="kernel.listener" event="onCoreException" />
<tag name="kernel.listener" event="onCoreRequest" />
<argument type="service" id="service_container" />
<argument type="service" id="profiler.request_matcher" on-invalid="null" />
<argument /> <!-- Only exceptions? -->

View File

@ -5,7 +5,7 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="event_dispatcher.class">Symfony\Bundle\FrameworkBundle\EventDispatcher</parameter>
<parameter key="event_dispatcher.class">Symfony\Bundle\FrameworkBundle\ContainerAwareEventDispatcher</parameter>
<parameter key="http_kernel.class">Symfony\Bundle\FrameworkBundle\HttpKernel</parameter>
<parameter key="error_handler.class">Symfony\Component\HttpKernel\Debug\ErrorHandler</parameter>
<parameter key="error_handler.level">null</parameter>
@ -25,9 +25,9 @@
</service>
<service id="http_kernel" class="%http_kernel.class%">
<argument type="service" id="event_dispatcher" />
<argument type="service" id="service_container" />
<argument type="service" id="controller_resolver" />
<call method="setEventDispatcher"><argument type="service" id="event_dispatcher" /></call>
</service>
<service id="cache_warmer" class="%cache_warmer.class%">

View File

@ -25,7 +25,7 @@
<service id="test.client.cookiejar" class="%test.client.cookiejar.class%" scope="prototype" />
<service id="test.session.listener" class="%test.session.listener.class%">
<tag name="kernel.listener" event="core.response" method="filter" priority="-128" />
<tag name="kernel.listener" event="onCoreResponse" priority="-128" />
</service>
</services>
</container>

View File

@ -26,19 +26,19 @@
</service>
<service id="request_listener" class="%request_listener.class%">
<tag name="kernel.listener" event="core.request" method="handle" />
<tag name="kernel.listener" event="onCoreRequest" />
<argument type="service" id="service_container" />
<argument type="service" id="router" />
<argument type="service" id="logger" on-invalid="ignore" />
</service>
<service id="response_listener" class="%response_listener.class%">
<tag name="kernel.listener" event="core.response" method="filter" />
<tag name="kernel.listener" event="onCoreResponse" />
<argument>%kernel.charset%</argument>
</service>
<service id="exception_listener" class="%exception_listener.class%">
<tag name="kernel.listener" event="core.exception" method="handle" priority="-128" />
<tag name="kernel.listener" event="onCoreException" priority="-128" />
<argument>%exception_listener.controller%</argument>
<argument type="service" id="logger" on-invalid="null" />
</service>

View File

@ -12,10 +12,10 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\HttpFoundation;
use Symfony\Bundle\FrameworkBundle\HttpFoundation\SessionListener;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
/**
* SessionListenerTest.
@ -53,10 +53,12 @@ class SessionListenerTest extends \PHPUnit_Framework_TestCase
{
$request->setSession($this->session);
$response = new Response();
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$event = new FilterResponseEvent($kernel, $request, $type, $response);
$this->assertSame($response, $this->listener->filter(new Event(
$this, 'core.response', array('request' => $request, 'request_type' => $type)
), $response));
$this->listener->onCoreResponse($event);
$this->assertSame($response, $event->getResponse());
}
private function sessionMustNotBeSaved()

View File

@ -5,9 +5,9 @@ namespace Symfony\Bundle\FrameworkBundle\Tests;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Bundle\FrameworkBundle\HttpKernel;
use Symfony\Component\EventDispatcher\EventDispatcher;
class HttpKernelTest extends \PHPUnit_Framework_TestCase
{
@ -38,8 +38,7 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
$dispatcher = new EventDispatcher();
$resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
$kernel = new HttpKernel($container, $resolver);
$kernel->setEventDispatcher($dispatcher);
$kernel = new HttpKernel($dispatcher, $container, $resolver);
$controller = function() use($expected)
{
@ -87,8 +86,7 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
$dispatcher = new EventDispatcher();
$resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
$kernel = new HttpKernel($container, $resolver);
$kernel->setEventDispatcher($dispatcher);
$kernel = new HttpKernel($dispatcher, $container, $resolver);
$controller = function() use ($expected)
{

View File

@ -106,7 +106,7 @@
<!-- Firewall related services -->
<service id="security.firewall" class="%security.firewall.class%">
<tag name="kernel.listener" event="core.request" method="handle" priority="-128" />
<tag name="kernel.listener" event="onCoreRequest" priority="-128" />
<argument type="service" id="security.firewall.map" />
<argument type="service" id="event_dispatcher" />
</service>

View File

@ -51,7 +51,7 @@
</service>
<service id="security.rememberme.response_listener" class="%security.rememberme.response_listener.class%">
<tag name="kernel.listener" method="handle" event="core.response"/>
<tag name="kernel.listener" event="onCoreResponse"/>
</service>
</services>

View File

@ -3,7 +3,7 @@
namespace Symfony\Bundle\SecurityBundle;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
/**
@ -13,15 +13,13 @@ use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
*/
class ResponseListener
{
public function handle(EventInterface $event, Response $response)
public function onCoreResponse(FilterResponseEvent $event)
{
$request = $event->get('request');
if (!$request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME)) {
return $response;
$request = $event->getRequest();
$response = $event->getResponse();
if ($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME)) {
$response->headers->setCookie($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME));
}
$response->headers->setCookie($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME));
return $response;
}
}

View File

@ -11,7 +11,7 @@
<services>
<service id="debug.toolbar" class="%debug.toolbar.class%">
<tag name="kernel.listener" event="core.response" method="handle" priority="-128" />
<tag name="kernel.listener" event="onCoreResponse" priority="-128" />
<argument type="service" id="http_kernel" />
<argument type="service" id="templating.engine.twig" />
<argument>%debug.toolbar.intercept_redirects%</argument>

View File

@ -12,15 +12,13 @@
<table>
<tr>
<th>Class</th>
<th>Event</th>
<th>Caller</th>
<th>Listener</th>
</tr>
{% for elements in collector.calledlisteners %}
<tr>
<td><code>{{ elements.class|abbr_class }}</code></td>
<td><code>{{ elements.event }}</code></td>
<td><code>{{ elements.caller|abbr_class }}</code></td>
<td><code>{{ elements.listener|abbr_method }}</code></td>
</tr>
{% endfor %}
</table>
@ -35,8 +33,8 @@
</tr>
{% for elements in collector.notcalledlisteners %}
<tr>
<td><code>{{ elements.class|abbr_class }}</code></td>
<td><code>{{ elements.event }}</code></td>
<td><code>{{ elements.listener|abbr_method }}</code></td>
</tr>
{% endfor %}
</table>

View File

@ -11,17 +11,17 @@
namespace Symfony\Bundle\WebProfilerBundle;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Bundle\TwigBundle\TwigEngine;
/**
* WebDebugToolbarListener injects the Web Debug Toolbar.
*
* The handle method must be connected to the core.response event.
* The handle method must be connected to the onCoreResponse event.
*
* The WDT is only injected on well-formed HTML (with a proper </body> tag).
* This means that the WDT is never included in sub-requests or ESI requests.
@ -41,13 +41,15 @@ class WebDebugToolbarListener
$this->interceptRedirects = $interceptRedirects;
}
public function handle(EventInterface $event, Response $response)
public function onCoreResponse(FilterResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->get('request_type')) {
return $response;
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
$request = $event->get('request');
$response = $event->getResponse();
$request = $event->getRequest();
if ($response->headers->has('X-Debug-Token') && $response->isRedirect() && $this->interceptRedirects) {
// keep current flashes for one more request
$request->getSession()->setFlashes($request->getSession()->getFlashes());
@ -66,12 +68,10 @@ class WebDebugToolbarListener
|| 'html' !== $request->getRequestFormat()
|| $request->isXmlHttpRequest()
) {
return $response;
return;
}
$this->injectToolbar($response);
return $response;
}
/**

View File

@ -1,136 +1,70 @@
<?php
/*
* This file is part of the Symfony package.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* (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.
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Symfony\Component\EventDispatcher;
/**
* Event.
* Event is the base class for classes containing event data.
*
* @author Fabien Potencier <fabien@symfony.com>
* This class contains no event data. It is used by events that do not pass
* state information to an event handler when an event is raised.
*
* You can call the method stopPropagation() to abort the execution of
* further listeners in your event listener.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class Event implements EventInterface
class Event
{
protected $processed = false;
protected $subject;
protected $name;
protected $parameters;
/**
* @var Boolean Whether no further event listeners should be triggered
*/
private $propagationStopped = false;
/**
* Constructs a new Event.
* Returns whether further event listeners should be triggered.
*
* @param mixed $subject The subject
* @param string $name The event name
* @param array $parameters An array of parameters
* @see Event::stopPropagation
* @return Boolean Whether propagation was already stopped for this event.
*/
public function __construct($subject, $name, $parameters = array())
public function isPropagationStopped()
{
$this->subject = $subject;
$this->name = $name;
$this->parameters = $parameters;
return $this->propagationStopped;
}
/**
* Returns the subject.
* Stops the propagation of the event to further event listeners.
*
* @return mixed The subject
* If multiple event listeners are connected to the same event, no
* further event listener will be triggered once any trigger calls
* stopPropagation().
*/
public function getSubject()
public function stopPropagation()
{
return $this->subject;
}
/**
* Returns the event name.
*
* @return string The event name
*/
public function getName()
{
return $this->name;
}
/**
* Sets the processed flag to true.
*
* This method must be called by listeners when
* it has processed the event (it is only meaningful
* when the event has been notified with the notifyUntil()
* dispatcher method.
*/
public function setProcessed()
{
$this->processed = true;
}
/**
* Returns whether the event has been processed by a listener or not.
*
* This method is only meaningful for events notified
* with notifyUntil().
*
* @return Boolean true if the event has been processed, false otherwise
*/
public function isProcessed()
{
return $this->processed;
}
/**
* Returns the event parameters.
*
* @return array The event parameters
*/
public function all()
{
return $this->parameters;
}
/**
* Returns true if the parameter exists.
*
* @param string $name The parameter name
*
* @return Boolean true if the parameter exists, false otherwise
*/
public function has($name)
{
return array_key_exists($name, $this->parameters);
}
/**
* Returns a parameter value.
*
* @param string $name The parameter name
*
* @return mixed The parameter value
*
* @throws \InvalidArgumentException When parameter doesn't exists for this event
*/
public function get($name)
{
if (!array_key_exists($name, $this->parameters)) {
throw new \InvalidArgumentException(sprintf('The event "%s" has no "%s" parameter.', $this->name, $name));
}
return $this->parameters[$name];
}
/**
* Sets a parameter.
*
* @param string $name The parameter name
* @param mixed $value The parameter value
*/
public function set($name, $value)
{
$this->parameters[$name] = $value;
$this->propagationStopped = true;
}
}

View File

@ -1,147 +1,204 @@
<?php
/*
* This file is part of the Symfony package.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* (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.
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Symfony\Component\EventDispatcher;
/**
* EventDispatcher implements a dispatcher object.
* The EventDispatcherInterface is the central point of Symfony's event listener system.
*
* @author Fabien Potencier <fabien@symfony.com>
* Listeners are registered on the manager and events are dispatched through the
* manager.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class EventDispatcher implements EventDispatcherInterface
{
protected $listeners = array();
/**
* Map of registered listeners.
* <event> => (<objecthash> => <listener>)
*
* @var array
*/
private $listeners = array();
/**
* Connects a listener to a given event name.
* Map of priorities by the object hashes of their listeners.
* <event> => (<objecthash> => <priority>)
*
* Listeners with a higher priority are executed first.
* This property is used for listener sorting.
*
* @param string $name An event name
* @param mixed $listener A PHP callable
* @param integer $priority The priority (between -10 and 10 -- defaults to 0)
* @var array
*/
public function connect($name, $listener, $priority = 0)
private $priorities = array();
/**
* Stores which event listener lists are currently sorted.
* <event> => <sorted>
*
* @var array
*/
private $sorted = array();
/**
* @see EventDispatcherInterface::dispatch
*/
public function dispatch($eventName, Event $event = null)
{
if (!isset($this->listeners[$name][$priority])) {
if (!isset($this->listeners[$name])) {
$this->listeners[$name] = array();
if (isset($this->listeners[$eventName])) {
if (null === $event) {
$event = new Event();
}
$this->listeners[$name][$priority] = array();
}
$this->listeners[$name][$priority][] = $listener;
}
$this->sortListeners($eventName);
/**
* Disconnects one, or all listeners for the given event name.
*
* @param string $name An event name
* @param mixed|null $listener The listener to remove, or null to remove all
*
* @return void
*/
public function disconnect($name, $listener = null)
{
if (!isset($this->listeners[$name])) {
return;
}
foreach ($this->listeners[$eventName] as $listener) {
$this->triggerListener($listener, $eventName, $event);
if (null === $listener) {
unset($this->listeners[$name]);
return;
}
foreach ($this->listeners[$name] as $priority => $callables) {
foreach ($callables as $i => $callable) {
if ($listener === $callable) {
unset($this->listeners[$name][$priority][$i]);
if ($event->isPropagationStopped()) {
break;
}
}
}
}
/**
* Notifies all listeners of a given event.
*
* @param EventInterface $event An EventInterface instance
* @see EventDispatcherInterface::getListeners
*/
public function notify(EventInterface $event)
public function getListeners($eventName = null)
{
foreach ($this->getListeners($event->getName()) as $listener) {
call_user_func($listener, $event);
if ($eventName) {
$this->sortListeners($eventName);
return $this->listeners[$eventName];
}
foreach ($this->listeners as $eventName => $listeners) {
$this->sortListeners($eventName);
}
return $this->listeners;
}
/**
* @see EventDispatcherInterface::hasListeners
*/
public function hasListeners($eventName)
{
return isset($this->listeners[$eventName]) && $this->listeners[$eventName];
}
/**
* @see EventDispatcherInterface::addListener
*/
public function addListener($eventNames, $listener, $priority = 0)
{
// Picks the hash code related to that listener
$hash = spl_object_hash($listener);
foreach ((array) $eventNames as $eventName) {
if (!isset($this->listeners[$eventName])) {
$this->listeners[$eventName] = array();
$this->priorities[$eventName] = array();
}
// Prevents duplicate listeners on same event (same instance only)
$this->listeners[$eventName][$hash] = $listener;
$this->priorities[$eventName][$hash] = $priority;
$this->sorted[$eventName] = false;
}
}
/**
* Notifies all listeners of a given event until one processes the event.
*
* @param EventInterface $event An EventInterface instance
*
* @return mixed The returned value of the listener that processed the event
* @see EventDispatcherInterface::removeListener
*/
public function notifyUntil(EventInterface $event)
public function removeListener($eventNames, $listener)
{
foreach ($this->getListeners($event->getName()) as $listener) {
$ret = call_user_func($listener, $event);
if ($event->isProcessed()) {
return $ret;
// Picks the hash code related to that listener
$hash = spl_object_hash($listener);
foreach ((array) $eventNames as $eventName) {
// Check if actually have this listener associated
if (isset($this->listeners[$eventName][$hash])) {
unset($this->listeners[$eventName][$hash]);
unset($this->priorities[$eventName][$hash]);
}
}
}
/**
* Filters a value by calling all listeners of a given event.
*
* @param EventInterface $event An EventInterface instance
* @param mixed $value The value to be filtered
*
* @return mixed The filtered value
* @see EventDispatcherInterface::addSubscriber
*/
public function filter(EventInterface $event, $value)
public function addSubscriber(EventSubscriberInterface $subscriber, $priority = 0)
{
foreach ($this->getListeners($event->getName()) as $listener) {
$value = call_user_func($listener, $event, $value);
}
return $value;
$this->addListener($subscriber->getSubscribedEvents(), $subscriber, $priority);
}
/**
* Returns true if the given event name has some listeners.
* Triggers the listener method for an event.
*
* @param string $name The event name
* This method can be overridden to add functionality that is executed
* for each listener.
*
* @return Boolean true if some listeners are connected, false otherwise
* @param object $listener The event listener on which to invoke the listener method.
* @param string $eventName The name of the event to dispatch. The name of the event is
* the name of the method that is invoked on listeners.
* @param Event $event The event arguments to pass to the event handlers/listeners.
*/
public function hasListeners($name)
protected function triggerListener($listener, $eventName, Event $event)
{
return (Boolean) count($this->getListeners($name));
if ($listener instanceof \Closure) {
$listener->__invoke($event);
} else {
$listener->$eventName($event);
}
}
/**
* Returns all listeners associated with a given event name.
* Sorts the internal list of listeners for the given event by priority.
*
* @param string $name The event name
* Calling this method multiple times will not cause overhead unless you
* add new listeners. As long as no listener is added, the list for an
* event name won't be sorted twice.
*
* @return array An array of listeners
* @param string $event The name of the event.
*/
public function getListeners($name)
private function sortListeners($eventName)
{
if (!isset($this->listeners[$name])) {
return array();
if (!$this->sorted[$eventName]) {
$p = $this->priorities[$eventName];
uasort($this->listeners[$eventName], function ($a, $b) use ($p) {
$order = $p[spl_object_hash($b)] - $p[spl_object_hash($a)];
// for the same priority, force the first registered one to stay first
return 0 === $order ? 1 : $order;
});
$this->sorted[$eventName] = true;
}
krsort($this->listeners[$name]);
return call_user_func_array('array_merge', $this->listeners[$name]);
}
}

View File

@ -12,81 +12,72 @@
namespace Symfony\Component\EventDispatcher;
/**
* EventDispatcherInterface describes an event dispatcher class.
* The EventDispatcherInterface is the central point of Symfony's event listener system.
* Listeners are registered on the manager and events are dispatched through the
* manager.
*
* @see http://developer.apple.com/documentation/Cocoa/Conceptual/Notifications/index.html Apple's Cocoa framework
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
interface EventDispatcherInterface
{
/**
* Connects a listener to a given event name.
* Dispatches an event to all registered listeners.
*
* Listeners with a higher priority are executed first.
*
* @param string $name An event name
* @param mixed $listener A PHP callable
* @param integer $priority The priority (between -10 and 10 -- defaults to 0)
* @param string $eventName The name of the event to dispatch. The name of
* the event is the name of the method that is
* invoked on listeners.
* @param Event $event The event to pass to the event handlers/listeners.
* If not supplied, an empty Event instance is created.
*/
function connect($name, $listener, $priority = 0);
function dispatch($eventName, Event $event = null);
/**
* Disconnects one, or all listeners for the given event name.
* Adds an event listener that listens on the specified events.
*
* @param string $name An event name
* @param mixed|null $listener The listener to remove, or null to remove all
*
* @return void
* @param string|array $eventNames The event(s) to listen on.
* @param object $listener The listener object.
* @param integer $priority The higher this value, the earlier an event
* listener will be triggered in the chain.
* Defaults to 0.
*/
function disconnect($name, $listener = null);
function addListener($eventNames, $listener, $priority = 0);
/**
* Notifies all listeners of a given event.
* Adds an event subscriber. The subscriber is asked for all the events he is
* interested in and added as a listener for these events.
*
* @param EventInterface $event An EventInterface instance
* @param EventSubscriberInterface $subscriber The subscriber.
* @param integer $priority The higher this value, the earlier an event
* listener will be triggered in the chain.
* Defaults to 0.
*/
function notify(EventInterface $event);
function addSubscriber(EventSubscriberInterface $subscriber, $priority = 0);
/**
* Notifies all listeners of a given event until one processes the event.
* Removes an event listener from the specified events.
*
* A listener tells the dispatcher that it has processed the event
* by calling the setProcessed() method on it.
*
* It can then return a value that will be forwarded to the caller.
*
* @param EventInterface $event An EventInterface instance
*
* @return mixed The returned value of the listener that processed the event
* @param string|array $eventNames The event(s) to remove a listener from.
* @param object $listener The listener object to remove.
*/
function notifyUntil(EventInterface $event);
function removeListener($eventNames, $listener);
/**
* Filters a value by calling all listeners of a given event.
* Gets the listeners of a specific event or all listeners.
*
* @param EventInterface $event An EventInterface instance
* @param mixed $value The value to be filtered
* @param string $eventName The name of the event.
*
* @return mixed The filtered value
* @return array The event listeners for the specified event, or all event
* listeners by event name.
*/
function filter(EventInterface $event, $value);
function getListeners($eventName = null);
/**
* Returns true if the given event name has some listeners.
* Checks whether an event has any registered listeners.
*
* @param string $name The event name
* @param string $eventName The name of the event.
*
* @return Boolean true if some listeners are connected, false otherwise
* @return Boolean TRUE if the specified event has any listeners, FALSE
* otherwise.
*/
function hasListeners($name);
/**
* Returns all listeners associated with a given event name.
*
* @param string $name The event name
*
* @return array An array of listeners
*/
function getListeners($name);
function hasListeners($eventName);
}

View File

@ -1,89 +0,0 @@
<?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\EventDispatcher;
/**
* EventInterface.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
interface EventInterface
{
/**
* Returns the subject.
*
* @return mixed The subject
*/
function getSubject();
/**
* Returns the event name.
*
* @return string The event name
*/
function getName();
/**
* Sets the processed flag to true.
*
* This method must be called by listeners when
* it has processed the event (it is only meaningful
* when the event has been notified with the notifyUntil()
* dispatcher method.
*/
function setProcessed();
/**
* Returns whether the event has been processed by a listener or not.
*
* This method is only meaningful for events notified
* with notifyUntil().
*
* @return Boolean true if the event has been processed, false otherwise
*/
function isProcessed();
/**
* Returns the event parameters.
*
* @return array The event parameters
*/
function all();
/**
* Returns true if the parameter exists.
*
* @param string $name The parameter name
*
* @return Boolean true if the parameter exists, false otherwise
*/
function has($name);
/**
* Returns a parameter value.
*
* @param string $name The parameter name
*
* @return mixed The parameter value
*
* @throws \InvalidArgumentException When parameter doesn't exists for this event
*/
function get($name);
/**
* Sets a parameter.
*
* @param string $name The parameter name
* @param mixed $value The parameter value
*/
function set($name, $value);
}

View File

@ -0,0 +1,45 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Symfony\Component\EventDispatcher;
/**
* An EventSubscriber knows himself what events he is interested in.
* If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes
* {@link getSubscribedEvents} and registers the subscriber as a listener for all
* returned events.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
interface EventSubscriberInterface
{
/**
* Returns an array of events this subscriber wants to listen to.
*
* @return array
*/
static function getSubscribedEvents();
}

View File

@ -11,10 +11,10 @@
namespace Symfony\Component\HttpKernel\DataCollector;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Debug\EventDispatcherTraceableInterface;
use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* EventDataCollector.
@ -27,7 +27,7 @@ class EventDataCollector extends DataCollector
public function setEventDispatcher(EventDispatcherInterface $dispatcher)
{
if ($dispatcher instanceof EventDispatcherTraceableInterface) {
if ($dispatcher instanceof TraceableEventDispatcherInterface) {
$this->dispatcher = $dispatcher;
}
}
@ -48,7 +48,7 @@ class EventDataCollector extends DataCollector
*
* @return array An array of called listeners
*
* @see EventDispatcherTraceableInterface
* @see TraceableEventDispatcherInterface
*/
public function getCalledListeners()
{
@ -60,7 +60,7 @@ class EventDataCollector extends DataCollector
*
* @return array An array of not called listeners
*
* @see EventDispatcherTraceableInterface
* @see TraceableEventDispatcherInterface
*/
public function getNotCalledListeners()
{

View File

@ -48,7 +48,7 @@ class LoggerDataCollector extends DataCollector
*
* @return array An array of called events
*
* @see EventDispatcherTraceableInterface
* @see TraceableEventDispatcherInterface
*/
public function countErrors()
{

View File

@ -11,9 +11,9 @@
namespace Symfony\Component\HttpKernel\Debug;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpFoundation\Request;
@ -21,8 +21,6 @@ use Symfony\Component\HttpFoundation\Request;
/**
* ExceptionListener.
*
* The handle method must be connected to the core.exception event.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class ExceptionListener
@ -36,7 +34,7 @@ class ExceptionListener
$this->logger = $logger;
}
public function handle(EventInterface $event)
public function onCoreException(GetResponseForExceptionEvent $event)
{
static $handling;
@ -46,8 +44,8 @@ class ExceptionListener
$handling = true;
$exception = $event->get('exception');
$request = $event->get('request');
$exception = $event->getException();
$request = $event->getRequest();
if (null !== $this->logger) {
$this->logger->err(sprintf('%s: %s (uncaught exception)', get_class($exception), $exception->getMessage()));
@ -68,7 +66,7 @@ class ExceptionListener
$request = $request->duplicate(null, null, $attributes);
try {
$response = $event->getSubject()->handle($request, HttpKernelInterface::SUB_REQUEST, true);
$response = $event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST, true);
} catch (\Exception $e) {
$message = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $e->getMessage());
if (null !== $this->logger) {
@ -79,15 +77,13 @@ class ExceptionListener
// set handling to false otherwise it wont be able to handle further more
$handling = false;
// re-throw the exception as this is a catch-all
throw $exception;
}
$event->setProcessed();
$event->setResponse($response);
$handling = false;
return $response;
}
}

View File

@ -14,7 +14,7 @@ namespace Symfony\Component\HttpKernel\Debug;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
interface EventDispatcherTraceableInterface
interface TraceableEventDispatcherInterface
{
/**
* Gets the called listeners.

View File

@ -0,0 +1,89 @@
<?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\HttpKernel\Event;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Allows to filter a controller callable
*
* You can call getController() to retrieve the current controller. With
* setController() you can set a new controller that is used in for processing
* a request.
*
* Controllers should be callables.
*
* @author Bernhard Schussek <bernhard.schussek@symfony.com>
*/
class FilterControllerEvent extends KernelEvent
{
/**
* The current controller
* @var callable
*/
private $controller;
public function __construct(HttpKernelInterface $kernel, $controller, Request $request, $requestType)
{
parent::__construct($kernel, $request, $requestType);
$this->setController($controller);
}
/**
* Returns the current controller
*
* @return callable
*/
public function getController()
{
return $this->controller;
}
/**
* Sets a new controller
*
* @param callable $controller
*/
public function setController($controller)
{
// controller must be a callable
if (!is_callable($controller)) {
throw new \LogicException(sprintf('The controller must be a callable (%s given).', $this->varToString($controller)));
}
$this->controller = $controller;
}
private function varToString($var)
{
if (is_object($var)) {
return sprintf('[object](%s)', get_class($var));
}
if (is_array($var)) {
$a = array();
foreach ($var as $k => $v) {
$a[] = sprintf('%s => %s', $k, $this->varToString($v));
}
return sprintf("[array](%s)", implode(', ', $a));
}
if (is_resource($var)) {
return '[resource]';
}
return str_replace("\n", '', var_export((string) $var, true));
}
}

View File

@ -0,0 +1,61 @@
<?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\HttpKernel\Event;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Allows to filter a Response object
*
* You can call getResponse() to retrieve the current response. With
* setResponse() you can set a new response that will be returned to the
* browser.
*
* @author Bernhard Schussek <bernhard.schussek@symfony.com>
*/
class FilterResponseEvent extends KernelEvent
{
/**
* The current response object
* @var Symfony\Component\HttpFoundation\Response
*/
private $response;
public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, Response $response)
{
parent::__construct($kernel, $request, $requestType);
$this->setResponse($response);
}
/**
* Returns the current response object
*
* @return Symfony\Component\HttpFoundation\Response
*/
public function getResponse()
{
return $this->response;
}
/**
* Sets a new response object
*
* @param Symfony\Component\HttpFoundation\Response $response
*/
public function setResponse(Response $response)
{
$this->response = $response;
}
}

View File

@ -0,0 +1,66 @@
<?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\HttpKernel\Event;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Allows to create a response for a request
*
* Call setResponse() to set the response that will be returned for the
* current request. The propagation of this event is stopped as soon as a
* response is set.
*
* @author Bernhard Schussek <bernhard.schussek@symfony.com>
*/
class GetResponseEvent extends KernelEvent
{
/**
* The response object
* @var Symfony\Component\HttpFoundation\Response
*/
private $response;
/**
* Returns the response object
*
* @return Symfony\Component\HttpFoundation\Response
*/
public function getResponse()
{
return $this->response;
}
/**
* Sets a response and stops event propagation
*
* @param Symfony\Component\HttpFoundation\Response $response
*/
public function setResponse(Response $response)
{
$this->response = $response;
$this->stopPropagation();
}
/**
* Returns whether a response was set
*
* @return Boolean Whether a response was set
*/
public function hasResponse()
{
return null !== $this->response;
}
}

View File

@ -0,0 +1,50 @@
<?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\HttpKernel\Event;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Allows to create a response for the return value of a controller
*
* Call setResponse() to set the response that will be returned for the
* current request. The propagation of this event is stopped as soon as a
* response is set.
*
* @author Bernhard Schussek <bernhard.schussek@symfony.com>
*/
class GetResponseForControllerResultEvent extends GetResponseEvent
{
/**
* The return value of the controller
* @var mixed
*/
private $controllerResult;
public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, $controllerResult)
{
parent::__construct($kernel, $request, $requestType);
$this->controllerResult = $controllerResult;
}
/**
* Returns the return value of the controller
*
* @return mixed The controller return value
*/
public function getControllerResult()
{
return $this->controllerResult;
}
}

View File

@ -0,0 +1,66 @@
<?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\HttpKernel\Event;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Allows to create a response for a thrown exception
*
* Call setResponse() to set the response that will be returned for the
* current request. The propagation of this event is stopped as soon as a
* response is set.
*
* You can also call setException() to replace the thrown exception. This
* exception will be thrown if no response is set during processing of this
* event.
*
* @author Bernhard Schussek <bernhard.schussek@symfony.com>
*/
class GetResponseForExceptionEvent extends GetResponseEvent
{
/**
* The exception object
* @var \Exception
*/
private $exception;
public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, \Exception $e)
{
parent::__construct($kernel, $request, $requestType);
$this->setException($e);
}
/**
* Returns the thrown exception
*
* @return \Exception The thrown exception
*/
public function getException()
{
return $this->exception;
}
/**
* Replaces the thrown exception
*
* This exception will be thrown if no response is set in the event.
*
* @param \Exception $exception The thrown exception
*/
public function setException(\Exception $exception)
{
$this->exception = $exception;
}
}

View File

@ -0,0 +1,81 @@
<?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\HttpKernel\Event;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\Event;
/**
* Base class for events thrown in the HttpKernel component
*
* @author Bernhard Schussek <bernhard.schussek@symfony.com>
*/
class KernelEvent extends Event
{
/**
* The kernel in which this event was thrown
* @var Symfony\Component\HttpKernel\HttpKernelInterface
*/
private $kernel;
/**
* The request the kernel is currently processing
* @var Symfony\Component\HttpFoundation\Request
*/
private $request;
/**
* The request type the kernel is currently processing. One of
* HttpKernelInterface::MASTER_REQUEST and HttpKernelInterface::SUB_REQUEST
* @var integer
*/
private $requestType;
public function __construct(HttpKernelInterface $kernel, Request $request, $requestType)
{
$this->kernel = $kernel;
$this->request = $request;
$this->requestType = $requestType;
}
/**
* Returns the kernel in which this event was thrown
*
* @return Symfony\Component\HttpKernel\HttpKernelInterface
*/
public function getKernel()
{
return $this->kernel;
}
/**
* Returns the request the kernel is currently processing
*
* @return Symfony\Component\HttpFoundation\Request
*/
public function getRequest()
{
return $this->request;
}
/**
* Returns the request type the kernel is currently processing
*
* @return integer One of HttpKernelInterface::MASTER_REQUEST and
* HttpKernelInterface::SUB_REQUEST
*/
public function getRequestType()
{
return $this->requestType;
}
}

View File

@ -0,0 +1,82 @@
<?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\HttpKernel;
/**
* Contains all events thrown in the HttpKernel component
*
* @author Bernhard Schussek <bernhard.schussek@symfony.com>
*/
final class Events
{
/**
* The onCoreRequest event occurs at the very beginning of request
* dispatching
*
* This event allows you to create a response for a request before any
* other code in the framework is executed. The event listener method
* receives a Symfony\Component\HttpKernel\Event\GetResponseEvent
* instance.
*
* @var string
*/
const onCoreRequest = 'onCoreRequest';
/**
* The onCoreException event occurs when an uncaught exception appears
*
* This event allows you to create a response for a thrown exception or
* to modify the thrown exception. The event listener method receives
* a Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent
* instance.
*
* @var string
*/
const onCoreException = 'onCoreException';
/**
* The onCoreView event occurs when the return value of a controller
* is not a Response instance
*
* This event allows you to create a response for the return value of the
* controller. The event listener method receives a
* Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent
* instance.
*
* @var string
*/
const onCoreView = 'onCoreView';
/**
* The onCoreController event occurs once a controller was found for
* handling a request
*
* This event allows you to change the controller that will handle the
* request. The event listener method receives a
* Symfony\Component\HttpKernel\Event\FilterControllerEvent instance.
*
* @var string
*/
const onCoreController = 'onCoreController';
/**
* The onCoreController event occurs once a reponse was created for
* replying to a request
*
* This event allows you to modify or replace the response that will be
* replied. The event listener method receives a
* Symfony\Component\HttpKernel\Event\FilterResponseEvent instance.
*
* @var string
*/
const onCoreResponse = 'onCoreResponse';
}

View File

@ -13,19 +13,16 @@ namespace Symfony\Component\HttpKernel\HttpCache;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
/**
* EsiListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for ESI.
*
* The filter method must be connected to the core.response event.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class EsiListener
{
protected $dispatcher;
protected $i;
protected $esi;
/**
@ -41,17 +38,14 @@ class EsiListener
/**
* Filters the Response.
*
* @param EventInterface $event An EventInterface instance
* @param Response $response A Response instance
* @param FilterResponseEvent $event A FilterResponseEvent instance
*/
public function filter(EventInterface $event, Response $response)
public function onCoreResponse(FilterResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->get('request_type') || null === $this->esi) {
return $response;
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType() || null === $this->esi) {
return;
}
$this->esi->addSurrogateControl($response);
return $response;
$this->esi->addSurrogateControl($event->getResponse());
}
}

View File

@ -11,12 +11,16 @@
namespace Symfony\Component\HttpKernel;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* HttpKernel notifies events to convert a Request object to a Response one.
@ -25,13 +29,13 @@ use Symfony\Component\HttpFoundation\Response;
*/
class HttpKernel implements HttpKernelInterface
{
protected $dispatcher;
protected $resolver;
private $dispatcher;
private $resolver;
/**
* Constructor
*
* @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
* @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
* @param ControllerResolverInterface $resolver A ControllerResolverInterface instance
*/
public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver)
@ -84,10 +88,11 @@ class HttpKernel implements HttpKernelInterface
protected function handleRaw(Request $request, $type = self::MASTER_REQUEST)
{
// request
$event = new Event($this, 'core.request', array('request_type' => $type, 'request' => $request));
$response = $this->dispatcher->notifyUntil($event);
if ($event->isProcessed()) {
return $this->filterResponse($response, $request, 'A "core.request" listener returned a non response object.', $type);
$event = new GetResponseEvent($this, $request, $type);
$this->dispatcher->dispatch(Events::onCoreRequest, $event);
if ($event->hasResponse()) {
return $this->filterResponse($event->getResponse(), $request, $type);
}
// load controller
@ -95,13 +100,9 @@ class HttpKernel implements HttpKernelInterface
throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". Maybe you forgot to add the matching route in your routing configuration?', $request->getPathInfo()));
}
$event = new Event($this, 'core.controller', array('request_type' => $type, 'request' => $request));
$controller = $this->dispatcher->filter($event, $controller);
// controller must be a callable
if (!is_callable($controller)) {
throw new \LogicException(sprintf('The controller must be a callable (%s given).', $this->varToString($controller)));
}
$event = new FilterControllerEvent($this, $controller, $request, $type);
$this->dispatcher->dispatch(Events::onCoreController, $event);
$controller = $event->getController();
// controller arguments
$arguments = $this->resolver->getArguments($request, $controller);
@ -111,14 +112,19 @@ class HttpKernel implements HttpKernelInterface
// view
if (!$response instanceof Response) {
$event = new Event($this, 'core.view', array('request_type' => $type, 'request' => $request, 'controller_value' => $response));
$retval = $this->dispatcher->notifyUntil($event);
if ($event->isProcessed()) {
$response = $retval;
$event = new GetResponseForControllerResultEvent($this, $request, $type, $response);
$this->dispatcher->dispatch(Events::onCoreView, $event);
if ($event->hasResponse()) {
$response = $event->getResponse();
}
if (!$response instanceof Response) {
throw new \LogicException(sprintf('The controller must return a response (%s given).', $this->varToString($response)));
}
}
return $this->filterResponse($response, $request, sprintf('The controller must return a response (%s given).', $this->varToString($response)), $type);
return $this->filterResponse($response, $request, $type);
}
/**
@ -132,19 +138,13 @@ class HttpKernel implements HttpKernelInterface
*
* @throws \RuntimeException if the passed object is not a Response instance
*/
protected function filterResponse($response, $request, $message, $type)
protected function filterResponse(Response $response, Request $request, $type)
{
if (!$response instanceof Response) {
throw new \RuntimeException($message);
}
$event = new FilterResponseEvent($this, $request, $type, $response);
$response = $this->dispatcher->filter(new Event($this, 'core.response', array('request_type' => $type, 'request' => $request)), $response);
$this->dispatcher->dispatch(Events::onCoreResponse, $event);
if (!$response instanceof Response) {
throw new \RuntimeException('A "core.response" listener returned a non response object.');
}
return $response;
return $event->getResponse();
}
/**
@ -158,13 +158,14 @@ class HttpKernel implements HttpKernelInterface
*/
protected function handleException(\Exception $e, $request, $type)
{
$event = new Event($this, 'core.exception', array('request_type' => $type, 'request' => $request, 'exception' => $e));
$response = $this->dispatcher->notifyUntil($event);
if (!$event->isProcessed()) {
$event = new GetResponseForExceptionEvent($this, $request, $type, $e);
$this->dispatcher->dispatch(Events::onCoreException, $event);
if (!$event->hasResponse()) {
throw $e;
}
return $this->filterResponse($response, $request, 'A "core.exception" listener returned a non response object.', $type);
return $this->filterResponse($event->getResponse(), $request, $type);
}
protected function varToString($var)

View File

@ -11,14 +11,12 @@
namespace Symfony\Component\HttpKernel;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpFoundation\Response;
/**
* ResponseListener fixes the Response Content-Type.
*
* The filter method must be connected to the core.response event.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class ResponseListener
@ -33,29 +31,28 @@ class ResponseListener
/**
* Filters the Response.
*
* @param EventInterface $event An EventInterface instance
* @param Response $response A Response instance
* @param FilterResponseEvent $event A FilterResponseEvent instance
*/
public function filter(EventInterface $event, Response $response)
public function onCoreResponse(FilterResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->get('request_type')) {
return $response;
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
$response = $event->getResponse();
if (null === $response->getCharset()) {
$response->setCharset($this->charset);
}
if ($response->headers->has('Content-Type')) {
return $response;
return;
}
$request = $event->get('request');
$request = $event->getRequest();
$format = $request->getRequestFormat();
if ((null !== $format) && $mimeType = $request->getMimeType($format)) {
$response->headers->set('Content-Type', $mimeType);
}
return $response;
}
}

View File

@ -2,8 +2,8 @@
namespace Symfony\Component\Security\Http\Authentication;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpFoundation\Request;
/**
@ -22,12 +22,12 @@ interface AuthenticationFailureHandlerInterface
* called by authentication listeners inheriting from
* AbstractAuthenticationListener.
*
* @param EventInterface $event the "core.security" event, this event always
* @param GetResponseEvent $event the "onCoreRequest" event, this event always
* has the kernel as target
* @param Request $request
* @param AuthenticationException $exception
*
* @return Response the response to return
*/
function onAuthenticationFailure(EventInterface $event, Request $request, AuthenticationException $exception);
function onAuthenticationFailure(GetResponseEvent $event, Request $request, AuthenticationException $exception);
}

View File

@ -2,7 +2,7 @@
namespace Symfony\Component\Security\Http\Authentication;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Request;
@ -22,12 +22,12 @@ interface AuthenticationSuccessHandlerInterface
* is called by authentication listeners inheriting from
* AbstractAuthenticationListener.
*
* @param EventInterface $event the "core.security" event, this event always
* @param GetResponseEvent $event the "onCoreRequest" event, this event always
* has the kernel as target
* @param Request $request
* @param TokenInterface $token
*
* @return Response the response to return
*/
function onAuthenticationSuccess(EventInterface $event, Request $request, TokenInterface $token);
function onAuthenticationSuccess(GetResponseEvent $event, Request $request, TokenInterface $token);
}

View File

@ -3,8 +3,9 @@
namespace Symfony\Component\Security\Http\Authorization;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
/**
* This is used by the ExceptionListener to translate an AccessDeniedException
@ -17,11 +18,11 @@ interface AccessDeniedHandlerInterface
/**
* Handles an access denied failure.
*
* @param EventInterface $event
* @param Request $request
* @param AccessDeniedException $accessDeniedException
* @param GetResponseForExceptionEvent $event
* @param Request $request
* @param AccessDeniedException $accessDeniedException
*
* @return Response may return null
*/
function handle(EventInterface $event, Request $request, AccessDeniedException $accessDeniedException);
}
function handle(GetResponseForExceptionEvent $event, Request $request, AccessDeniedException $accessDeniedException);
}

View File

@ -11,7 +11,7 @@
namespace Symfony\Component\Security\Http\EntryPoint;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Request;
@ -26,9 +26,9 @@ interface AuthenticationEntryPointInterface
/**
* Starts the authentication scheme.
*
* @param EventInterface $event The "core.security" event
* @param GetResponseEvent $event The "onCoreRequest" event
* @param object $request The request that resulted in an AuthenticationException
* @param AuthenticationException $authException The exception that started the authentication process
*/
function start(EventInterface $event, Request $request, AuthenticationException $authException = null);
function start(GetResponseEvent $event, Request $request, AuthenticationException $authException = null);
}

View File

@ -11,11 +11,11 @@
namespace Symfony\Component\Security\Http\EntryPoint;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
/**
* BasicAuthenticationEntryPoint starts an HTTP Basic authentication.
@ -31,7 +31,7 @@ class BasicAuthenticationEntryPoint implements AuthenticationEntryPointInterface
$this->realmName = $realmName;
}
public function start(EventInterface $event, Request $request, AuthenticationException $authException = null)
public function start(GetResponseEvent $event, Request $request, AuthenticationException $authException = null)
{
$response = new Response();
$response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realmName));

View File

@ -11,13 +11,13 @@
namespace Symfony\Component\Security\Http\EntryPoint;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\Security\Core\Exception\NonceExpiredException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
/**
* DigestAuthenticationEntryPoint starts an HTTP Digest authentication.
@ -39,7 +39,7 @@ class DigestAuthenticationEntryPoint implements AuthenticationEntryPointInterfac
$this->logger = $logger;
}
public function start(EventInterface $event, Request $request, AuthenticationException $authException = null)
public function start(GetResponseEvent $event, Request $request, AuthenticationException $authException = null)
{
$expiryTime = microtime(true) + $this->nonceValiditySeconds * 1000;
$signatureValue = md5($expiryTime.':'.$this->key);

View File

@ -11,13 +11,13 @@
namespace Symfony\Component\Security\Http\EntryPoint;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
/**
* FormAuthenticationEntryPoint starts an authentication via a login form.
@ -44,10 +44,10 @@ class FormAuthenticationEntryPoint implements AuthenticationEntryPointInterface
/**
* {@inheritdoc}
*/
public function start(EventInterface $event, Request $request, AuthenticationException $authException = null)
public function start(GetResponseEvent $event, Request $request, AuthenticationException $authException = null)
{
if ($this->useForward) {
return $event->getSubject()->handle(Request::create($this->loginPath), HttpKernelInterface::SUB_REQUEST);
return $event->getKernel()->handle(Request::create($this->loginPath), HttpKernelInterface::SUB_REQUEST);
}
return new RedirectResponse(0 !== strpos($this->loginPath, 'http') ? $request->getUriForPath($this->loginPath) : $this->loginPath, 302);

View File

@ -11,12 +11,12 @@
namespace Symfony\Component\Security\Http\EntryPoint;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
/**
* RetryAuthenticationEntryPoint redirects URL based on the configured scheme.
@ -36,7 +36,7 @@ class RetryAuthenticationEntryPoint implements AuthenticationEntryPointInterface
$this->httpsPort = $httpsPort;
}
public function start(EventInterface $event, Request $request, AuthenticationException $authException = null)
public function start(GetResponseEvent $event, Request $request, AuthenticationException $authException = null)
{
$scheme = $request->isSecure() ? 'http' : 'https';
if ('http' === $scheme && 80 != $this->httpPort) {

View File

@ -0,0 +1,38 @@
<?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\Security\Http\Event;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\Event;
class InteractiveLoginEvent extends Event
{
private $request;
private $authenticationToken;
public function __construct(Request $request, $authenticationToken)
{
$this->request = $request;
$this->authenticationToken = $authenticationToken;
}
public function getRequest()
{
return $this->request;
}
public function getAuthenticationToken()
{
return $this->authenticationToken;
}
}

View File

@ -0,0 +1,39 @@
<?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\Security\Http\Event;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\EventDispatcher\Event;
class SwitchUserEvent extends Event
{
private $request;
private $targetUser;
public function __construct(Request $request, UserInterface $targetUser)
{
$this->request = $request;
$this->targetUser = $targetUser;
}
public function getRequest()
{
return $this->request;
}
public function getTargetUser()
{
return $this->targetUser;
}
}

View File

@ -0,0 +1,19 @@
<?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\Security\Http;
final class Events
{
const onSecurityInteractiveLogin = 'onSecurityInteractiveLogin';
const onSecuritySwitchUser = 'onSecuritySwitchUser';
}

View File

@ -11,11 +11,11 @@
namespace Symfony\Component\Security\Http;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Events;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* Firewall uses a FirewallMap to register security listeners for the given
@ -25,13 +25,13 @@ use Symfony\Component\HttpFoundation\Request;
* (a Basic authentication for the /api, and a web based authentication for
* everything else for instance).
*
* The handle method must be connected to the core.request event.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Firewall
{
private $map;
private $dispatcher;
private $currentListeners;
/**
* Constructor.
@ -42,21 +42,22 @@ class Firewall
{
$this->map = $map;
$this->dispatcher = $dispatcher;
$this->currentListeners = array();
}
/**
* Handles security.
*
* @param EventInterface $event An EventInterface instance
* @param GetResponseEvent $event An GetResponseEvent instance
*/
public function handle(EventInterface $event)
public function onCoreRequest(GetResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->get('request_type')) {
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
// register listeners for this firewall
list($listeners, $exception) = $this->map->getListeners($event->get('request'));
list($listeners, $exception) = $this->map->getListeners($event->getRequest());
if (null !== $exception) {
$exception->register($this->dispatcher);
}
@ -65,8 +66,8 @@ class Firewall
foreach ($listeners as $listener) {
$response = $listener->handle($event);
if ($event->isProcessed()) {
return $response;
if ($event->hasResponse()) {
break;
}
}
}

View File

@ -11,22 +11,24 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Events as KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\Events;
/**
* The AbstractAuthenticationListener is the preferred base class for all
@ -53,7 +55,7 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
protected $providerKey;
private $securityContext;
private $sessionStrategy;
private $eventDispatcher;
private $dispatcher;
private $successHandler;
private $failureHandler;
private $rememberMeServices;
@ -66,7 +68,7 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
* @param array $options An array of options for the processing of a successful, or failed authentication attempt
* @param LoggerInterface $logger A LoggerInterface instance
*/
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, $providerKey, array $options = array(), AuthenticationSuccessHandlerInterface $successHandler = null, AuthenticationFailureHandlerInterface $failureHandler = null, LoggerInterface $logger = null, EventDispatcherInterface $eventDispatcher = null)
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, $providerKey, array $options = array(), AuthenticationSuccessHandlerInterface $successHandler = null, AuthenticationFailureHandlerInterface $failureHandler = null, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
{
if (empty($providerKey)) {
throw new \InvalidArgumentException('$providerKey must not be empty.');
@ -89,7 +91,7 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
'failure_forward' => false,
), $options);
$this->logger = $logger;
$this->eventDispatcher = $eventDispatcher;
$this->dispatcher = $dispatcher;
}
/**
@ -105,11 +107,11 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
/**
* Handles form based authentication.
*
* @param Event $event An Event instance
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public final function handle(EventInterface $event)
public final function handle(GetResponseEvent $event)
{
$request = $event->get('request');
$request = $event->getRequest();
if (!$this->requiresAuthentication($request)) {
return;
@ -129,13 +131,11 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
} else {
throw new \RuntimeException('attemptAuthentication() must either return a Response, an implementation of TokenInterface, or null.');
}
} catch (AuthenticationException $failed) {
$response = $this->onFailure($event, $request, $failed);
} catch (AuthenticationException $e) {
$response = $this->onFailure($event, $request, $e);
}
$event->setProcessed();
return $response;
$event->setResponse($response);
}
/**
@ -165,7 +165,7 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
*/
abstract protected function attemptAuthentication(Request $request);
private function onFailure($event, Request $request, AuthenticationException $failed)
private function onFailure(GetResponseEvent $event, Request $request, AuthenticationException $failed)
{
if (null !== $this->logger) {
$this->logger->debug(sprintf('Authentication request failed: %s', $failed->getMessage()));
@ -201,7 +201,7 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
return new RedirectResponse(0 !== strpos($this->options['failure_path'], 'http') ? $request->getUriForPath($this->options['failure_path']) : $this->options['failure_path'], 302);
}
private function onSuccess(EventInterface $event, Request $request, TokenInterface $token)
private function onSuccess(GetResponseEvent $event, Request $request, TokenInterface $token)
{
if (null !== $this->logger) {
$this->logger->debug('User has been authenticated successfully');
@ -213,8 +213,9 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
$session->remove(SecurityContextInterface::AUTHENTICATION_ERROR);
$session->remove(SecurityContextInterface::LAST_USERNAME);
if (null !== $this->eventDispatcher) {
$this->eventDispatcher->notify(new Event($this, 'security.interactive_login', array('request' => $request, 'token' => $token)));
if (null !== $this->dispatcher) {
$loginEvent = new InteractiveLoginEvent($request, $token);
$this->dispatcher->dispatch(Events::onSecurityInteractiveLogin, $loginEvent);
}
if (null !== $this->successHandler) {

View File

@ -11,15 +11,17 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\Events;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Events as KernelEvents;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* AbstractPreAuthenticatedListener is the base class for all listener that
@ -34,25 +36,25 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface
private $securityContext;
private $authenticationManager;
private $providerKey;
private $eventDispatcher;
private $dispatcher;
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, LoggerInterface $logger = null, EventDispatcherInterface $eventDispatcher = null)
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
{
$this->securityContext = $securityContext;
$this->authenticationManager = $authenticationManager;
$this->providerKey = $providerKey;
$this->logger = $logger;
$this->eventDispatcher = $eventDispatcher;
$this->dispatcher = $dispatcher;
}
/**
* Handles X509 authentication.
*
* @param EventInterface $event An EventInterface instance
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public final function handle(EventInterface $event)
public final function handle(GetResponseEvent $event)
{
$request = $event->get('request');
$request = $event->getRequest();
if (null !== $this->logger) {
$this->logger->debug(sprintf('Checking secure context token: %s', $this->securityContext->getToken()));
@ -78,8 +80,9 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface
}
$this->securityContext->setToken($token);
if (null !== $this->eventDispatcher) {
$this->eventDispatcher->notify(new Event($this, 'security.interactive_login', array('request' => $request, 'token' => $token)));
if (null !== $this->dispatcher) {
$loginEvent = new InteractiveLoginEvent($request, $token);
$this->dispatcher->dispatch(Events::onSecurityInteractiveLogin, $loginEvent);
}
} catch (AuthenticationException $failed) {
$this->securityContext->setToken(null);

View File

@ -16,8 +16,8 @@ use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface
use Symfony\Component\Security\Http\AccessMap;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Events;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
@ -46,15 +46,15 @@ class AccessListener implements ListenerInterface
/**
* Handles access authorization.
*
* @param EventInterface $event An EventInterface instance
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public function handle(EventInterface $event)
public function handle(GetResponseEvent $event)
{
if (null === $token = $this->context->getToken()) {
throw new AuthenticationCredentialsNotFoundException('A Token was not found in the SecurityContext.');
}
$request = $event->get('request');
$request = $event->getRequest();
list($attributes, $channel) = $this->map->getPatterns($request);

View File

@ -13,8 +13,8 @@ namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Events;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
/**
@ -39,9 +39,9 @@ class AnonymousAuthenticationListener implements ListenerInterface
/**
* Handles anonymous authentication.
*
* @param EventInterface $event An EventInterface instance
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public function handle(EventInterface $event)
public function handle(GetResponseEvent $event)
{
if (null !== $this->context->getToken()) {
return;

View File

@ -15,8 +15,8 @@ use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Events;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
@ -51,11 +51,11 @@ class BasicAuthenticationListener implements ListenerInterface
/**
* Handles basic authentication.
*
* @param EventInterface $event An EventInterface instance
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public function handle(EventInterface $event)
public function handle(GetResponseEvent $event)
{
$request = $event->get('request');
$request = $event->getRequest();
if (false === $username = $request->server->get('PHP_AUTH_USER', false)) {
return;

View File

@ -14,8 +14,8 @@ namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\Security\Http\AccessMap;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Events;
/**
* ChannelListener switches the HTTP protocol based on the access control
@ -39,11 +39,11 @@ class ChannelListener implements ListenerInterface
/**
* Handles channel management.
*
* @param EventInterface $event An EventInterface instance
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public function handle(EventInterface $event)
public function handle(GetResponseEvent $event)
{
$request = $event->get('request');
$request = $event->getRequest();
list($attributes, $channel) = $this->map->getPatterns($request);
@ -52,9 +52,11 @@ class ChannelListener implements ListenerInterface
$this->logger->debug('Redirecting to HTTPS');
}
$event->setProcessed();
$response = $this->authenticationEntryPoint->start($event, $request);
return $this->authenticationEntryPoint->start($event, $request);
$event->setResponse($response);
return;
}
if ('http' === $channel && $request->isSecure()) {
@ -62,9 +64,9 @@ class ChannelListener implements ListenerInterface
$this->logger->debug('Redirecting to HTTP');
}
$event->setProcessed();
$response = $this->authenticationEntryPoint->start($event, $request);
return $this->authenticationEntryPoint->start($event, $request);
$event->setResponse($response);
}
}
}

View File

@ -11,17 +11,19 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Events;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* ContextListener manages the SecurityContext persistence through a session.
@ -36,7 +38,7 @@ class ContextListener implements ListenerInterface
private $logger;
private $userProviders;
public function __construct(SecurityContext $context, array $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $eventDispatcher = null)
public function __construct(SecurityContext $context, array $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
{
if (empty($contextKey)) {
throw new \InvalidArgumentException('$contextKey must not be empty.');
@ -46,19 +48,19 @@ class ContextListener implements ListenerInterface
$this->userProviders = $userProviders;
$this->contextKey = $contextKey;
if (null !== $eventDispatcher) {
$eventDispatcher->connect('core.response', array($this, 'write'), 0);
if (null !== $dispatcher) {
$dispatcher->addListener(Events::onCoreResponse, $this);
}
}
/**
* Reads the SecurityContext from the session.
*
* @param EventInterface $event An EventInterface instance
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public function handle(EventInterface $event)
public function handle(GetResponseEvent $event)
{
$request = $event->get('request');
$request = $event->getRequest();
$session = $request->hasSession() ? $request->getSession() : null;
@ -82,29 +84,27 @@ class ContextListener implements ListenerInterface
/**
* Writes the SecurityContext to the session.
*
* @param EventInterface $event An EventInterface instance
* @param FilterResponseEvent $event A FilterResponseEvent instance
*/
public function write(EventInterface $event, Response $response)
public function onCoreResponse(FilterResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->get('request_type')) {
return $response;
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
if (null === $token = $this->context->getToken()) {
return $response;
return;
}
if (null === $token || $token instanceof AnonymousToken) {
return $response;
return;
}
if (null !== $this->logger) {
$this->logger->debug('Write SecurityContext in the session');
}
$event->get('request')->getSession()->set('_security_'.$this->contextKey, serialize($token));
return $response;
$event->getRequest()->getSession()->set('_security_'.$this->contextKey, serialize($token));
}
/**

View File

@ -15,8 +15,8 @@ use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Events;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
@ -54,11 +54,11 @@ class DigestAuthenticationListener implements ListenerInterface
/**
* Handles digest authentication.
*
* @param EventInterface $event An EventInterface instance
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public function handle(EventInterface $event)
public function handle(GetResponseEvent $event)
{
$request = $event->get('request');
$request = $event->getRequest();
if (!$header = $request->server->get('PHP_AUTH_DIGEST')) {
return;
@ -121,7 +121,7 @@ class DigestAuthenticationListener implements ListenerInterface
$this->securityContext->setToken(new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey));
}
private function fail(EventInterface $event, Request $request, AuthenticationException $authException)
private function fail(GetResponseEvent $event, Request $request, AuthenticationException $authException)
{
$this->securityContext->setToken(null);

View File

@ -17,14 +17,15 @@ use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Exception\InsufficientAuthenticationException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Events;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* ExceptionListener catches authentication exception and converts them to
@ -52,25 +53,24 @@ class ExceptionListener
}
/**
* Registers a core.exception listener to take care of security exceptions.
* Registers a onCoreException listener to take care of security exceptions.
*
* @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
* @param integer $priority The priority
*/
public function register(EventDispatcherInterface $dispatcher)
{
$dispatcher->connect('core.exception', array($this, 'handleException'), 0);
$dispatcher->addListener(Events::onCoreException, $this);
}
/**
* Handles security related exceptions.
*
* @param EventInterface $event An EventInterface instance
* @param GetResponseForExceptionEvent $event An GetResponseForExceptionEvent instance
*/
public function handleException(EventInterface $event)
public function onCoreException(GetResponseForExceptionEvent $event)
{
$exception = $event->get('exception');
$request = $event->get('request');
$exception = $event->getException();
$request = $event->getRequest();
if ($exception instanceof AuthenticationException) {
if (null !== $this->logger) {
@ -118,7 +118,7 @@ class ExceptionListener
$subRequest = Request::create($this->errorPage);
$subRequest->attributes->set(SecurityContextInterface::ACCESS_DENIED_ERROR, $exception);
$response = $event->getSubject()->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true);
$response = $event->getKernel()->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true);
$response->setStatusCode(403);
}
} catch (\Exception $e) {
@ -126,7 +126,7 @@ class ExceptionListener
$this->logger->err(sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $e->getMessage()));
}
$event->set('exception', new \RuntimeException('Exception thrown when handling an exception.', 0, $e));
$event->setException(new \RuntimeException('Exception thrown when handling an exception.', 0, $e));
return;
}
@ -135,12 +135,10 @@ class ExceptionListener
return;
}
$event->setProcessed();
return $response;
$event->setResponse($response);
}
private function startAuthentication(EventInterface $event, Request $request, AuthenticationException $authException)
private function startAuthentication(GetResponseForExceptionEvent $event, Request $request, AuthenticationException $authException)
{
$this->context->setToken(null);

View File

@ -11,8 +11,7 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
@ -25,7 +24,7 @@ interface ListenerInterface
/**
* This interface must be implemented by firewall listeners.
*
* @param EventInterface $dispatcher
* @param GetResponseEvent $event
*/
function handle(EventInterface $event);
function handle(GetResponseEvent $event);
}

View File

@ -15,10 +15,10 @@ use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;
use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Kernel\Event\GetResponseEvent;
use Symfony\Component\Kernel\Events;
/**
* LogoutListener logout users.
@ -63,11 +63,11 @@ class LogoutListener implements ListenerInterface
/**
* Performs the logout if requested
*
* @param EventInterface $event An EventInterface instance
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public function handle(EventInterface $event)
public function handle(GetResponseEvent $event)
{
$request = $event->get('request');
$request = $event->getRequest();
if ($this->logoutPath !== $request->getPathInfo()) {
return;
@ -92,8 +92,6 @@ class LogoutListener implements ListenerInterface
$this->securityContext->setToken(null);
$event->setProcessed();
return $response;
$event->setResponse($response);
}
}

View File

@ -2,18 +2,21 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\CookieTheftException;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Events as KernelEvents;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\CookieTheftException;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\Events;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/*
* This file is part of the Symfony framework.
@ -35,7 +38,7 @@ class RememberMeListener implements ListenerInterface
private $rememberMeServices;
private $authenticationManager;
private $logger;
private $eventDispatcher;
private $dispatcher;
/**
* Constructor
@ -45,27 +48,27 @@ class RememberMeListener implements ListenerInterface
* @param AuthenticationManagerInterface $authenticationManager
* @param LoggerInterface $logger
*/
public function __construct(SecurityContext $securityContext, RememberMeServicesInterface $rememberMeServices, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger = null, EventDispatcherInterface $eventDispatcher = null)
public function __construct(SecurityContext $securityContext, RememberMeServicesInterface $rememberMeServices, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
{
$this->securityContext = $securityContext;
$this->rememberMeServices = $rememberMeServices;
$this->authenticationManager = $authenticationManager;
$this->logger = $logger;
$this->eventDispatcher = $eventDispatcher;
$this->dispatcher = $dispatcher;
}
/**
* Handles remember-me cookie based authentication.
*
* @param Event $event An Event instance
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public function handle(EventInterface $event)
public function handle(GetResponseEvent $event)
{
if (null !== $this->securityContext->getToken()) {
return;
}
$request = $event->get('request');
$request = $event->getRequest();
if (null === $token = $this->rememberMeServices->autoLogin($request)) {
return;
}
@ -74,8 +77,9 @@ class RememberMeListener implements ListenerInterface
$token = $this->authenticationManager->authenticate($token);
$this->securityContext->setToken($token);
if (null !== $this->eventDispatcher) {
$this->eventDispatcher->notify(new Event($this, 'security.interactive_login', array('request' => $request, 'token' => $token)));
if (null !== $this->dispatcher) {
$loginEvent = new InteractiveLoginEvent($request, $token);
$this->dispatcher->dispatch(Events::onSecurityInteractiveLogin, $loginEvent);
}
if (null !== $this->logger) {

View File

@ -11,14 +11,13 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Events;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
@ -27,6 +26,9 @@ use Symfony\Component\Security\Core\Role\SwitchUserRole;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Event\SwitchUserEvent;
use Symfony\Component\Security\Http\Events;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* SwitchUserListener allows a user to impersonate another one temporarily
@ -44,12 +46,12 @@ class SwitchUserListener implements ListenerInterface
private $usernameParameter;
private $role;
private $logger;
private $eventDispatcher;
private $dispatcher;
/**
* Constructor.
*/
public function __construct(SecurityContextInterface $securityContext, UserProviderInterface $provider, UserCheckerInterface $userChecker, $providerKey, AccessDecisionManagerInterface $accessDecisionManager, LoggerInterface $logger = null, $usernameParameter = '_switch_user', $role = 'ROLE_ALLOWED_TO_SWITCH', EventDispatcherInterface $eventDispatcher = null)
public function __construct(SecurityContextInterface $securityContext, UserProviderInterface $provider, UserCheckerInterface $userChecker, $providerKey, AccessDecisionManagerInterface $accessDecisionManager, LoggerInterface $logger = null, $usernameParameter = '_switch_user', $role = 'ROLE_ALLOWED_TO_SWITCH', EventDispatcherInterface $dispatcher = null)
{
if (empty($providerKey)) {
throw new \InvalidArgumentException('$providerKey must not be empty.');
@ -63,17 +65,17 @@ class SwitchUserListener implements ListenerInterface
$this->usernameParameter = $usernameParameter;
$this->role = $role;
$this->logger = $logger;
$this->eventDispatcher = $eventDispatcher;
$this->dispatcher = $dispatcher;
}
/**
* Handles digest authentication.
*
* @param EventInterface $event An EventInterface instance
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public function handle(EventInterface $event)
public function handle(GetResponseEvent $event)
{
$request = $event->get('request');
$request = $event->getRequest();
if (!$request->get($this->usernameParameter)) {
return;
@ -94,9 +96,7 @@ class SwitchUserListener implements ListenerInterface
$request->server->set('QUERY_STRING', '');
$response = new RedirectResponse($request->getUri(), 302);
$event->setProcessed();
return $response;
$event->setResponse($response);
}
/**
@ -129,8 +129,9 @@ class SwitchUserListener implements ListenerInterface
$token = new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey, $roles);
if (null !== $this->eventDispatcher) {
$this->eventDispatcher->notify(new Event($this, 'security.switch_user', array('request' => $request, 'target_user' => $token->getUser())));
if (null !== $this->dispatcher) {
$switchEvent = new SwitchUserEvent($request, $token->getUser());
$this->dispatcher->dispatch(Events::onSecuritySwitchUser, $switchEvent);
}
return $token;
@ -149,8 +150,9 @@ class SwitchUserListener implements ListenerInterface
throw new AuthenticationCredentialsNotFoundException(sprintf('Could not find original Token object.'));
}
if (null !== $this->eventDispatcher) {
$this->eventDispatcher->notify(new Event($this, 'security.switch_user', array('request' => $request, 'target_user' => $original->getUser())));
if (null !== $this->dispatcher) {
$switchEvent = new SwitchUserEvent($request, $original->getUser());
$this->dispatcher->dispatch(Events::onSecuritySwitchUser, $switchEvent);
}
return $original;

View File

@ -11,8 +11,6 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\CsrfProvider\CsrfProviderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
@ -23,6 +21,7 @@ use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterfac
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* UsernamePasswordFormAuthenticationListener is the default implementation of
@ -37,7 +36,7 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL
/**
* {@inheritdoc}
*/
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, $providerKey, array $options = array(), AuthenticationSuccessHandlerInterface $successHandler = null, AuthenticationFailureHandlerInterface $failureHandler = null, LoggerInterface $logger = null, EventDispatcherInterface $eventDispatcher = null, CsrfProviderInterface $csrfProvider = null)
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, $providerKey, array $options = array(), AuthenticationSuccessHandlerInterface $successHandler = null, AuthenticationFailureHandlerInterface $failureHandler = null, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfProviderInterface $csrfProvider = null)
{
parent::__construct($securityContext, $authenticationManager, $sessionStrategy, $providerKey, array_merge(array(
'username_parameter' => '_username',
@ -45,7 +44,7 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL
'csrf_parameter' => '_csrf_token',
'csrf_page_id' => 'form_login',
'post_only' => true,
), $options), $successHandler, $failureHandler, $logger, $eventDispatcher);
), $options), $successHandler, $failureHandler, $logger, $dispatcher);
$this->csrfProvider = $csrfProvider;
}

View File

@ -11,12 +11,12 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* X509 authentication listener.
@ -28,9 +28,9 @@ class X509AuthenticationListener extends AbstractPreAuthenticatedListener
private $userKey;
private $credentialKey;
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, $userKey = 'SSL_CLIENT_S_DN_Email', $credentialKey = 'SSL_CLIENT_S_DN', LoggerInterface $logger = null, EventDispatcherInterface $eventDispatcher = null)
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, $userKey = 'SSL_CLIENT_S_DN_Email', $credentialKey = 'SSL_CLIENT_S_DN', LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
{
parent::__construct($securityContext, $authenticationManager, $providerKey, $logger, $eventDispatcher);
parent::__construct($securityContext, $authenticationManager, $providerKey, $logger, $dispatcher);
$this->userKey = $userKey;
$this->credentialKey = $credentialKey;

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Security\Http\Logout;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
/**
* LogoutSuccesshandlerInterface.
@ -21,9 +21,9 @@ interface LogoutSuccessHandlerInterface
/**
* Creates a Response object to send upon a successful logout.
*
* @param EventInterface $event
* @param GetResponseEvent $event
* @param Request $request
* @return Response never null
*/
function onLogoutSuccess(EventInterface $event, Request $request);
function onLogoutSuccess(GetResponseEvent $event, Request $request);
}

View File

@ -13,126 +13,187 @@ namespace Symfony\Tests\Component\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class EventDispatcherTest extends \PHPUnit_Framework_TestCase
{
public function testConnectAndDisconnect()
/* Some pseudo events */
const preFoo = 'preFoo';
const postFoo = 'postFoo';
const preBar = 'preBar';
const postBar = 'postBar';
private $dispatcher;
private $listener;
protected function setUp()
{
$dispatcher = new EventDispatcher();
$dispatcher->connect('bar', 'listenToBar');
$this->assertEquals(array('listenToBar'), $dispatcher->getListeners('bar'), '->connect() connects a listener to an event name');
$dispatcher->connect('bar', 'listenToBarBar');
$this->assertEquals(array('listenToBar', 'listenToBarBar'), $dispatcher->getListeners('bar'), '->connect() can connect several listeners for the same event name');
$dispatcher->connect('barbar', 'listenToBarBar');
$dispatcher->disconnect('bar');
$this->assertEquals(array(), $dispatcher->getListeners('bar'), '->disconnect() without a listener disconnects all listeners of for an event name');
$this->assertEquals(array('listenToBarBar'), $dispatcher->getListeners('barbar'), '->disconnect() without a listener disconnects all listeners of for an event name');
$this->dispatcher = new EventDispatcher();
$this->listener = new TestEventListener();
}
public function testGetHasListeners()
public function testInitialState()
{
$dispatcher = new EventDispatcher();
$this->assertFalse($dispatcher->hasListeners('foo'), '->hasListeners() returns false if the event has no listener');
$dispatcher->connect('foo', 'listenToFoo');
$this->assertEquals(true, $dispatcher->hasListeners('foo'), '->hasListeners() returns true if the event has some listeners');
$dispatcher->disconnect('foo', 'listenToFoo');
$this->assertFalse($dispatcher->hasListeners('foo'), '->hasListeners() returns false if the event has no listener');
$dispatcher->connect('bar', 'listenToBar');
$this->assertEquals(array('listenToBar'), $dispatcher->getListeners('bar'), '->getListeners() returns an array of listeners connected to the given event name');
$this->assertEquals(array(), $dispatcher->getListeners('foobar'), '->getListeners() returns an empty array if no listener are connected to the given event name');
$this->assertEquals(array(), $this->dispatcher->getListeners());
$this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
$this->assertFalse($this->dispatcher->hasListeners(self::postFoo));
}
public function testNotify()
public function testAddListener()
{
$listener = new Listener();
$dispatcher = new EventDispatcher();
$dispatcher->connect('foo', array($listener, 'listenToFoo'));
$dispatcher->connect('foo', array($listener, 'listenToFooBis'));
$e = $dispatcher->notify($event = new Event(new \stdClass(), 'foo'));
$this->assertEquals('listenToFoolistenToFooBis', $listener->getValue(), '->notify() notifies all registered listeners in order');
$listener->reset();
$dispatcher = new EventDispatcher();
$dispatcher->connect('foo', array($listener, 'listenToFooBis'));
$dispatcher->connect('foo', array($listener, 'listenToFoo'));
$dispatcher->notify(new Event(new \stdClass(), 'foo'));
$this->assertEquals('listenToFooBislistenToFoo', $listener->getValue(), '->notify() notifies all registered listeners in order');
$this->dispatcher->addListener(array('preFoo', 'postFoo'), $this->listener);
$this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
$this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
$this->assertEquals(1, count($this->dispatcher->getListeners(self::preFoo)));
$this->assertEquals(1, count($this->dispatcher->getListeners(self::postFoo)));
$this->assertEquals(2, count($this->dispatcher->getListeners()));
}
public function testNotifyUntil()
public function testGetListenersSortsByPriority()
{
$listener = new Listener();
$dispatcher = new EventDispatcher();
$dispatcher->connect('foo', array($listener, 'listenToFoo'));
$dispatcher->connect('foo', array($listener, 'listenToFooBis'));
$dispatcher->notifyUntil($event = new Event(new \stdClass(), 'foo'));
$this->assertEquals('listenToFoolistenToFooBis', $listener->getValue(), '->notifyUntil() notifies all registered listeners in order and stops when the event is processed');
$listener1 = new TestEventListener();
$listener2 = new TestEventListener();
$listener3 = new TestEventListener();
$listener->reset();
$dispatcher = new EventDispatcher();
$dispatcher->connect('foo', array($listener, 'listenToFooBis'));
$dispatcher->connect('foo', array($listener, 'listenToFoo'));
$dispatcher->notifyUntil($event = new Event(new \stdClass(), 'foo'));
$this->assertEquals('listenToFooBis', $listener->getValue(), '->notifyUntil() notifies all registered listeners in order and stops when the event is processed');
$this->dispatcher->addListener('preFoo', $listener1, -10);
$this->dispatcher->addListener('preFoo', $listener2);
$this->dispatcher->addListener('preFoo', $listener3, 10);
$expected = array(
spl_object_hash($listener3) => $listener3,
spl_object_hash($listener2) => $listener2,
spl_object_hash($listener1) => $listener1,
);
$this->assertSame($expected, $this->dispatcher->getListeners('preFoo'));
}
public function testFilter()
public function testGetAllListenersSortsByPriority()
{
$listener = new Listener();
$dispatcher = new EventDispatcher();
$dispatcher->connect('foo', array($listener, 'filterFoo'));
$dispatcher->connect('foo', array($listener, 'filterFooBis'));
$ret = $dispatcher->filter($event = new Event(new \stdClass(), 'foo'), 'foo');
$this->assertEquals('-*foo*-', $ret, '->filter() returns the filtered value');
$listener1 = new TestEventListener();
$listener2 = new TestEventListener();
$listener3 = new TestEventListener();
$listener4 = new TestEventListener();
$listener5 = new TestEventListener();
$listener6 = new TestEventListener();
$listener->reset();
$dispatcher = new EventDispatcher();
$dispatcher->connect('foo', array($listener, 'filterFooBis'));
$dispatcher->connect('foo', array($listener, 'filterFoo'));
$ret = $dispatcher->filter($event = new Event(new \stdClass(), 'foo'), 'foo');
$this->assertEquals('*-foo-*', $ret, '->filter() returns the filtered value');
$this->dispatcher->addListener('preFoo', $listener1, -10);
$this->dispatcher->addListener('preFoo', $listener2);
$this->dispatcher->addListener('preFoo', $listener3, 10);
$this->dispatcher->addListener('postFoo', $listener4, -10);
$this->dispatcher->addListener('postFoo', $listener5);
$this->dispatcher->addListener('postFoo', $listener6, 10);
$expected = array(
'preFoo' => array(
spl_object_hash($listener3) => $listener3,
spl_object_hash($listener2) => $listener2,
spl_object_hash($listener1) => $listener1,
),
'postFoo' => array(
spl_object_hash($listener6) => $listener6,
spl_object_hash($listener5) => $listener5,
spl_object_hash($listener4) => $listener4,
),
);
$this->assertSame($expected, $this->dispatcher->getListeners());
}
public function testDispatch()
{
$this->dispatcher->addListener(array('preFoo', 'postFoo'), $this->listener);
$this->dispatcher->dispatch(self::preFoo);
$this->assertTrue($this->listener->preFooInvoked);
$this->assertFalse($this->listener->postFooInvoked);
}
public function testDispatchForClosure()
{
$invoked = 0;
$listener = function () use (&$invoked) {
$invoked++;
};
$this->dispatcher->addListener(array('preFoo', 'postFoo'), $listener);
$this->dispatcher->dispatch(self::preFoo);
$this->assertEquals(1, $invoked);
}
public function testStopEventPropagation()
{
$otherListener = new TestEventListener;
// postFoo() stops the propagation, so only one listener should
// be executed
// Manually set priority to enforce $this->listener to be called first
$this->dispatcher->addListener('postFoo', $this->listener, 10);
$this->dispatcher->addListener('postFoo', $otherListener);
$this->dispatcher->dispatch(self::postFoo);
$this->assertTrue($this->listener->postFooInvoked);
$this->assertFalse($otherListener->postFooInvoked);
}
public function testDispatchByPriority()
{
$invoked = array();
$listener1 = function () use (&$invoked) {
$invoked[] = '1';
};
$listener2 = function () use (&$invoked) {
$invoked[] = '2';
};
$listener3 = function () use (&$invoked) {
$invoked[] = '3';
};
$this->dispatcher->addListener('preFoo', $listener1, -10);
$this->dispatcher->addListener('preFoo', $listener2);
$this->dispatcher->addListener('preFoo', $listener3, 10);
$this->dispatcher->dispatch(self::preFoo);
$this->assertEquals(array('3', '2', '1'), $invoked);
}
public function testRemoveListener()
{
$this->dispatcher->addListener(array('preBar'), $this->listener);
$this->assertTrue($this->dispatcher->hasListeners(self::preBar));
$this->dispatcher->removeListener(array('preBar'), $this->listener);
$this->assertFalse($this->dispatcher->hasListeners(self::preBar));
}
public function testAddSubscriber()
{
$eventSubscriber = new TestEventSubscriber();
$this->dispatcher->addSubscriber($eventSubscriber);
$this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
$this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
}
}
class Listener
class TestEventListener
{
protected
$value = '';
public $preFooInvoked = false;
public $postFooInvoked = false;
function filterFoo(Event $event, $foo)
/* Listener methods */
public function preFoo(Event $e)
{
return "*$foo*";
$this->preFooInvoked = true;
}
function filterFooBis(Event $event, $foo)
public function postFoo(Event $e)
{
return "-$foo-";
}
$this->postFooInvoked = true;
function listenToFoo(Event $event)
{
$this->value .= 'listenToFoo';
}
function listenToFooBis(Event $event)
{
$this->value .= 'listenToFooBis';
$event->setProcessed();
}
function getValue()
{
return $this->value;
}
function reset()
{
$this->value = '';
$e->stopPropagation();
}
}
class TestEventSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array('preFoo', 'postFoo');
}
}

View File

@ -1,68 +0,0 @@
<?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\Tests\Component\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
class EventTest extends \PHPUnit_Framework_TestCase
{
protected $subject;
protected $parameters;
public function testGetSubject()
{
$event = $this->createEvent();
$this->assertEquals($this->subject, $event->getSubject(), '->getSubject() returns the event subject');
}
public function testGetName()
{
$this->assertEquals('name', $this->createEvent()->getName(), '->getName() returns the event name');
}
public function testParameters()
{
$event = $this->createEvent();
$this->assertEquals($this->parameters, $event->all(), '->all() returns the event parameters');
$this->assertEquals('bar', $event->get('foo'), '->get() returns the value of a parameter');
$event->set('foo', 'foo');
$this->assertEquals('foo', $event->get('foo'), '->set() changes the value of a parameter');
$this->assertTrue($event->has('foo'), '->has() returns true if the parameter is defined');
$this->assertFalse($event->has('oof'), '->has() returns false if the parameter is not defined');
try {
$event->get('foobar');
$this->fail('->get() throws an \InvalidArgumentException exception when the parameter does not exist');
} catch (\Exception $e) {
$this->assertInstanceOf('\InvalidArgumentException', $e, '->get() throws an \InvalidArgumentException exception when the parameter does not exist');
$this->assertEquals('The event "name" has no "foobar" parameter.', $e->getMessage(), '->get() throws an \InvalidArgumentException exception when the parameter does not exist');
}
$event = new Event($this->subject, 'name', $this->parameters);
}
public function testSetIsProcessed()
{
$event = $this->createEvent();
$this->assertFalse($event->isProcessed(), '->isProcessed() returns false by default');
$event->setProcessed();
$this->assertTrue($event->isProcessed(), '->isProcessed() returns true if the event has been processed');
}
protected function createEvent()
{
$this->subject = new \stdClass();
$this->parameters = array('foo' => 'bar');
return new Event($this->subject, 'name', $this->parameters);
}
}

View File

@ -15,8 +15,6 @@ use Symfony\Component\HttpKernel\Client;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
require_once __DIR__.'/TestHttpKernel.php';

View File

@ -14,27 +14,26 @@ namespace Symfony\Tests\Component\HttpKernel\DataCollector;
use Symfony\Component\HttpKernel\DataCollector\EventDataCollector;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Debug\EventDispatcherTraceableInterface;
use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
class EventDataCollectorTest extends \PHPUnit_Framework_TestCase
{
public function testCollect()
{
$c = new EventDataCollector();
$c->setEventDispatcher(new TestEventDispatcher());
$c->collect(new Request(), new Response());
$this->assertSame('events',$c->getName());
$this->assertSame(array('foo'),$c->getCalledListeners());
$this->assertSame(array('bar'),$c->getNotCalledListeners());
}
}
class TestEventDispatcher extends EventDispatcher implements EventDispatcherTraceableInterface
class TestEventDispatcher extends EventDispatcher implements TraceableEventDispatcherInterface
{
function getCalledListeners()
{

View File

@ -11,11 +11,13 @@
namespace Symfony\Tests\Component\HttpKernel\Debug;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Debug\ExceptionListener;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Debug\ErrorException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Tests\Component\HttpKernel\Logger;
/**
@ -29,72 +31,74 @@ class ExceptionListenerTest extends \PHPUnit_Framework_TestCase
{
$logger = new TestLogger();
$l = new ExceptionListener('foo', $logger);
$_logger = new \ReflectionProperty(get_class($l),'logger');
$_logger = new \ReflectionProperty(get_class($l), 'logger');
$_logger->setAccessible(true);
$_controller = new \ReflectionProperty(get_class($l),'controller');
$_controller = new \ReflectionProperty(get_class($l), 'controller');
$_controller->setAccessible(true);
$this->assertSame($logger,$_logger->getValue($l));
$this->assertSame('foo',$_controller->getValue($l));
$this->assertSame($logger, $_logger->getValue($l));
$this->assertSame('foo', $_controller->getValue($l));
}
/**
* @dataProvider provider
*/
public function testHandleWithoutLogger($event,$event2)
public function testHandleWithoutLogger($event, $event2)
{
//store the current error_log, and set the new one to dev/null
$error_log = ini_get('error_log');
ini_set('error_log','/dev/null');
$l = new ExceptionListener('foo');
ini_set('error_log', '/dev/null');
$this->assertEquals('foo', $l->handle($event));
try{
$response = $l->handle($event2);
}catch(\Exception $e){
$this->assertSame('foo',$e->getMessage());
$l = new ExceptionListener('foo');
$l->onCoreException($event);
$this->assertEquals(new Response('foo'), $event->getResponse());
try {
$l->onCoreException($event2);
} catch(\Exception $e) {
$this->assertSame('foo', $e->getMessage());
}
//restore the old error_log
ini_set('error_log',$error_log);
ini_set('error_log', $error_log);
}
/**
* @dataProvider provider
*/
public function testHandleWithLogger($event, $event2)
{
$logger = new TestLogger();
$l = new ExceptionListener('foo',$logger);
$this->assertSame('foo', $l->handle($event));
try{
$response = $l->handle($event2);
}catch(\Exception $e){
$this->assertSame('foo',$e->getMessage());
$l = new ExceptionListener('foo', $logger);
$l->onCoreException($event);
$this->assertEquals(new Response('foo'), $event->getResponse());
try {
$l->onCoreException($event2);
} catch(\Exception $e) {
$this->assertSame('foo', $e->getMessage());
}
$this->assertEquals(3,$logger->countErrors());
$this->assertEquals(3,count($logger->getLogs('err')));
$this->assertEquals(3, $logger->countErrors());
$this->assertEquals(3, count($logger->getLogs('err')));
}
public function provider()
{
$args = array('exception'=>new ErrorException('foo'),'request'=>new Request());
$event = new Event(new Subject(),'bar',$args);
$event2 = new Event(new SubjectException(),'bar',$args);
$request = new Request();
$exception = new ErrorException('foo');
$event = new GetResponseForExceptionEvent(new TestKernel(), $request, 'foo', $exception);
$event2 = new GetResponseForExceptionEvent(new TestKernelThatThrowsException(), $request, 'foo', $exception);
return array(
array($event,$event2)
array($event, $event2)
);
}
}
class TestLogger extends Logger implements DebugLoggerInterface
@ -103,25 +107,25 @@ class TestLogger extends Logger implements DebugLoggerInterface
{
return count($this->logs['err']);
}
public function getDebugLogger()
{
return new static();
}
}
class Subject
class TestKernel implements HttpKernelInterface
{
public function handle()
public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
{
return 'foo';
return new Response('foo');
}
}
class SubjectException
class TestKernelThatThrowsException implements HttpKernelInterface
{
public function handle()
public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
{
throw new \Exception('bar');
}

View File

@ -13,46 +13,54 @@ namespace Symfony\Tests\Component\HttpKernel\HttpCache;
use Symfony\Component\HttpKernel\HttpCache\Esi;
use Symfony\Component\HttpKernel\HttpCache\EsiListener;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Events;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventDispatcher;
class EsiListenerTest extends \PHPUnit_Framework_TestCase
{
public function testFilterDoesNothingForSubRequests()
{
$dispatcher = new EventDispatcher();
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new Response('foo <esi:include src="" />');
$listener = new EsiListener(new Esi());
$dispatcher->connect('core.response', array($listener, 'filter'));
$event = new Event(null, 'core.response', array('request_type' => HttpKernelInterface::SUB_REQUEST));
$dispatcher->filter($event, $response = new Response('foo <esi:include src="" />'));
$dispatcher->addListener(Events::onCoreResponse, $listener);
$event = new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::SUB_REQUEST, $response);
$dispatcher->dispatch(Events::onCoreResponse, $event);
$this->assertEquals('', $response->headers->get('Surrogate-Control'));
$this->assertEquals('', $event->getResponse()->headers->get('Surrogate-Control'));
}
public function testFilterWhenThereIsSomeEsiIncludes()
{
$dispatcher = new EventDispatcher();
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new Response('foo <esi:include src="" />');
$listener = new EsiListener(new Esi());
$dispatcher->connect('core.response', array($listener, 'filter'));
$event = new Event(null, 'core.response', array('request_type' => HttpKernelInterface::MASTER_REQUEST));
$dispatcher->filter($event, $response = new Response('foo <esi:include src="" />'));
$dispatcher->addListener(Events::onCoreResponse, $listener);
$event = new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response);
$dispatcher->dispatch(Events::onCoreResponse, $event);
$this->assertEquals('content="ESI/1.0"', $response->headers->get('Surrogate-Control'));
$this->assertEquals('content="ESI/1.0"', $event->getResponse()->headers->get('Surrogate-Control'));
}
public function testFilterWhenThereIsNoEsiIncludes()
{
$dispatcher = new EventDispatcher();
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new Response('foo');
$listener = new EsiListener(new Esi());
$dispatcher->connect('core.response', array($listener, 'filter'));
$event = new Event(null, 'core.response', array('request_type' => HttpKernelInterface::MASTER_REQUEST));
$dispatcher->filter($event, $response = new Response('foo'));
$dispatcher->addListener(Events::onCoreResponse, $listener);
$event = new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response);
$dispatcher->dispatch(Events::onCoreResponse, $event);
$this->assertEquals('', $response->headers->get('Surrogate-Control'));
$this->assertEquals('', $event->getResponse()->headers->get('Surrogate-Control'));
}
}

View File

@ -15,8 +15,8 @@ use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
class TestHttpKernel extends HttpKernel implements ControllerResolverInterface
{

View File

@ -15,8 +15,8 @@ use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
class TestMultipleHttpKernel extends HttpKernel implements ControllerResolverInterface
{

View File

@ -13,6 +13,7 @@ namespace Symfony\Tests\Component\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Events;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcher;
@ -42,11 +43,9 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
public function testHandleWhenControllerThrowsAnExceptionAndRawIsFalse()
{
$dispatcher = new EventDispatcher();
$dispatcher->connect('core.exception', function ($event)
$dispatcher->addListener(Events::onCoreException, function ($event)
{
$event->setProcessed();
return new Response($event->get('exception')->getMessage());
$event->setResponse(new Response($event->getException()->getMessage()));
});
$kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new \RuntimeException('foo'); }));
@ -57,11 +56,9 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
public function testHandleWhenAListenerReturnsAResponse()
{
$dispatcher = new EventDispatcher();
$dispatcher->connect('core.request', function ($event)
$dispatcher->addListener(Events::onCoreRequest, function ($event)
{
$event->setProcessed();
return new Response('hello');
$event->setResponse(new Response('hello'));
});
$kernel = new HttpKernel($dispatcher, $this->getResolver());
@ -92,7 +89,7 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
}
/**
* @expectedException RuntimeException
* @expectedException LogicException
*/
public function testHandleWhenControllerDoesNotReturnAResponse()
{
@ -105,55 +102,21 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
public function testHandleWhenControllerDoesNotReturnAResponseButAViewIsRegistered()
{
$dispatcher = new EventDispatcher();
$dispatcher->connect('core.view', function ($event)
$dispatcher->addListener(Events::onCoreView, function ($event)
{
$event->setProcessed();
return new Response($event->get('controller_value'));
$event->setResponse(new Response($event->getControllerResult()));
});
$kernel = new HttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; }));
$this->assertEquals('foo', $kernel->handle(new Request())->getContent());
}
/**
* @expectedException RuntimeException
*/
public function testHandleWhenAViewDoesNotReturnAResponse()
{
$dispatcher = new EventDispatcher();
$dispatcher->connect('core.view', function ($event)
{
$event->setProcessed();
return $event->get('controller_value');
});
$kernel = new HttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; }));
$kernel->handle(new Request());
}
/**
* @expectedException RuntimeException
*/
public function testHandleWhenAResponseListenerDoesNotReturnAResponse()
{
$dispatcher = new EventDispatcher();
$dispatcher->connect('core.response', function ($event, $response)
{
return 'foo';
});
$kernel = new HttpKernel($dispatcher, $this->getResolver());
$kernel->handle(new Request());
}
public function testHandleWithAResponseListener()
{
$dispatcher = new EventDispatcher();
$dispatcher->connect('core.response', function ($event, $response)
$dispatcher->addListener(Events::onCoreResponse, function ($event)
{
return new Response('foo');
$event->setResponse(new Response('foo'));
});
$kernel = new HttpKernel($dispatcher, $this->getResolver());

View File

@ -12,56 +12,68 @@
namespace Symfony\Tests\Component\HttpKernel;
use Symfony\Component\HttpKernel\ResponseListener;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Events;
use Symfony\Component\EventDispatcher\EventDispatcher;
class ResponseListenerTest extends \PHPUnit_Framework_TestCase
{
private $dispatcher;
private $kernel;
protected function setUp()
{
$this->dispatcher = new EventDispatcher();
$listener = new ResponseListener('UTF-8');
$this->dispatcher->addListener(Events::onCoreResponse, $listener);
$this->kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
}
public function testFilterDoesNothingForSubRequests()
{
$event = new Event(null, 'core.response', array('request_type' => HttpKernelInterface::SUB_REQUEST));
$this->getDispatcher()->filter($event, $response = new Response('foo'));
$response = new Response('foo');
$this->assertEquals('', $response->headers->get('content-type'));
$event = new FilterResponseEvent($this->kernel, new Request(), HttpKernelInterface::SUB_REQUEST, $response);
$this->dispatcher->dispatch(Events::onCoreResponse, $event);
$this->assertEquals('', $event->getResponse()->headers->get('content-type'));
}
public function testFilterDoesNothingIfContentTypeIsSet()
{
$event = new Event(null, 'core.response', array('request_type' => HttpKernelInterface::MASTER_REQUEST));
$response = new Response('foo');
$response->headers->set('Content-Type', 'text/plain');
$this->getDispatcher()->filter($event, $response);
$this->assertEquals('text/plain', $response->headers->get('content-type'));
$event = new FilterResponseEvent($this->kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response);
$this->dispatcher->dispatch(Events::onCoreResponse, $event);
$this->assertEquals('text/plain', $event->getResponse()->headers->get('content-type'));
}
public function testFilterDoesNothingIfRequestFormatIsNotDefined()
{
$event = new Event(null, 'core.response', array('request_type' => HttpKernelInterface::MASTER_REQUEST, 'request' => Request::create('/')));
$this->getDispatcher()->filter($event, $response = new Response('foo'));
$response = new Response('foo');
$this->assertEquals('', $response->headers->get('content-type'));
$event = new FilterResponseEvent($this->kernel, Request::create('/'), HttpKernelInterface::MASTER_REQUEST, $response);
$this->dispatcher->dispatch(Events::onCoreResponse, $event);
$this->assertEquals('', $event->getResponse()->headers->get('content-type'));
}
public function testFilterSetContentType()
{
$response = new Response('foo');
$request = Request::create('/');
$request->setRequestFormat('json');
$event = new Event(null, 'core.response', array('request_type' => HttpKernelInterface::MASTER_REQUEST, 'request' => $request));
$this->getDispatcher()->filter($event, $response = new Response('foo'));
$this->assertEquals('application/json', $response->headers->get('content-type'));
}
$event = new FilterResponseEvent($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response);
$this->dispatcher->dispatch(Events::onCoreResponse, $event);
protected function getDispatcher()
{
$dispatcher = new EventDispatcher();
$listener = new ResponseListener('UTF-8');
$dispatcher->connect('core.response', array($listener, 'filter'));
return $dispatcher;
$this->assertEquals('application/json', $event->getResponse()->headers->get('content-type'));
}
}

View File

@ -14,8 +14,8 @@ namespace Symfony\Tests\Component\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
class TestHttpKernel extends HttpKernel implements ControllerResolverInterface
{

View File

@ -3,6 +3,7 @@
namespace Symfony\Tests\Component\Security\Http\Firewall;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Events;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Exception\CookieTheftException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
@ -11,7 +12,7 @@ use Symfony\Component\HttpFoundation\Request;
class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
{
public function testCheckCookiesDoesNotTryToPopulateNonEmptySecurityContext()
public function testOnCoreSecurityDoesNotTryToPopulateNonEmptySecurityContext()
{
list($listener, $context, $service,,) = $this->getListener();
@ -26,10 +27,10 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
->method('setToken')
;
$this->assertNull($listener->handle($this->getEvent()));
$this->assertNull($listener->handle($this->getGetResponseEvent()));
}
public function testCheckCookiesDoesNothingWhenNoCookieIsSet()
public function testOnCoreSecurityDoesNothingWhenNoCookieIsSet()
{
list($listener, $context, $service,,) = $this->getListener();
@ -45,18 +46,17 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue(null))
;
$event = $this->getEvent();
$event = $this->getGetResponseEvent();
$event
->expects($this->once())
->method('get')
->with('request')
->method('getRequest')
->will($this->returnValue(new Request()))
;
$this->assertNull($listener->handle($event));
}
public function testCheckCookiesIgnoresAuthenticationExceptionThrownByAuthenticationManagerImplementation()
public function testOnCoreSecurityIgnoresAuthenticationExceptionThrownByAuthenticationManagerImplementation()
{
list($listener, $context, $service, $manager,) = $this->getListener();
@ -84,18 +84,17 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
->will($this->throwException($exception))
;
$event = $this->getEvent();
$event = $this->getGetResponseEvent();
$event
->expects($this->once())
->method('get')
->with('request')
->method('getRequest')
->will($this->returnValue(new Request()))
;
$listener->handle($event);
}
public function testCheckCookies()
public function testOnCoreSecurity()
{
list($listener, $context, $service, $manager,) = $this->getListener();
@ -124,20 +123,24 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue($token))
;
$event = $this->getEvent();
$event = $this->getGetResponseEvent();
$event
->expects($this->once())
->method('get')
->with('request')
->method('getRequest')
->will($this->returnValue(new Request()))
;
$listener->handle($event);
}
protected function getEvent()
protected function getGetResponseEvent()
{
return $this->getMock('Symfony\Component\EventDispatcher\Event', array(), array(), '', false);
return $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
}
protected function getFilterResponseEvent()
{
return $this->getMock('Symfony\Component\HttpKernel\Event\FilterResponseEvent', array(), array(), '', false);
}
protected function getListener()