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\Asset\AssetInterface;
use Assetic\Factory\LazyAssetManager; use Assetic\Factory\LazyAssetManager;
use Symfony\Bundle\FrameworkBundle\Command\Command; 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\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\EventDispatcher\Event;
/** /**
* Dumps assets to the filesystem. * Dumps assets to the filesystem.
@ -46,7 +47,8 @@ class DumpCommand extends Command
$am = $this->container->get('assetic.asset_manager'); $am = $this->container->get('assetic.asset_manager');
// notify an event so custom stream wrappers can be registered lazily // 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')) { if ($input->getOption('watch')) {
return $this->watch($am, $basePath, $output, $this->container->getParameter('kernel.debug')); 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

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

View File

@ -3,7 +3,7 @@
/* /*
* This file is part of the Symfony package. * 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 * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.

View File

@ -29,7 +29,7 @@ class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface
); );
foreach ($subscribers as $id => $instances) { 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)) { if (0 < count($events)) {
$definition->addMethodCall('addEventListener', array( $definition->addMethodCall('addListener', array(
$events, $events,
new Reference($listenerId), 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(); $listeners = array();
$definition = $container->getDefinition('event_dispatcher');
foreach ($container->findTaggedServiceIds('kernel.listener') as $id => $events) { foreach ($container->findTaggedServiceIds('kernel.listener') as $id => $events) {
foreach ($events as $event) { foreach ($events as $event) {
$priority = isset($event['priority']) ? $event['priority'] : 0; $priority = isset($event['priority']) ? $event['priority'] : 0;
if (!isset($event['event'])) { if (!isset($event['event'])) {
throw new \InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "kernel.listener" tags.', $id)); 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])) { $definition->addMethodCall('addListenerService', array($event['event'], $id, $priority));
if (!isset($listeners[$event['event']])) {
$listeners[$event['event']] = array();
}
$listeners[$event['event']][$priority] = array();
}
$listeners[$event['event']][$priority][] = array($id, $event['method']);
} }
} }
$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\\ResponseListener',
'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver', 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver',
'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface', '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\\RequestListener',
'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerNameParser', 'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerNameParser',
'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver', 'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver',
'Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller', 'Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller',
'Symfony\\Bundle\\FrameworkBundle\\ContainerAwareEventDispatcher',
'Symfony\\Component\\EventDispatcher\\EventInterface',
'Symfony\\Component\\EventDispatcher\\Event',
'Symfony\\Component\\EventDispatcher\\EventDispatcherInterface',
'Symfony\\Component\\EventDispatcher\\EventDispatcher',
'Symfony\\Bundle\\FrameworkBundle\\EventDispatcher',
)); ));
} }

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

View File

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

View File

@ -11,17 +11,16 @@
namespace Symfony\Bundle\FrameworkBundle\Profiler; namespace Symfony\Bundle\FrameworkBundle\Profiler;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface; 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\HttpFoundation\RequestMatcherInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
* ProfilerListener collects data for the current request by listening to the core.response event. * ProfilerListener collects data for the current request by listening to the onCoreResponse event.
*
* The handleException method must be connected to the core.exception event.
* The handleResponse method must be connected to the core.response event.
* *
* @author Fabien Potencier <fabien@symfony.com> * @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 * 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'); $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')) { if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return false; return;
} }
$this->exception = $event->get('exception'); $this->exception = $event->getException();
return false;
} }
/** /**
* Handles the core.response event. * Handles the onCoreResponse event.
* *
* @param EventInterface $event An EventInterface instance * @param FilterResponseEvent $event A FilterResponseEvent instance
*
* @return Response $response A Response 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; return $response;
} }
if ($this->onlyException && null === $this->exception) { if ($this->onlyException && null === $this->exception) {
return $response; return;
} }
$profiler = $this->container->get('profiler'); $profiler = $this->container->get('profiler');
@ -98,9 +95,7 @@ class ProfilerListener
$profiler->setParent($parent['request']['profiler']->getToken()); $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; $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\Log\LoggerInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
* RequestListener. * RequestListener.
* *
* The handle method must be connected to the core.request event.
*
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
*/ */
class RequestListener class RequestListener
@ -38,10 +36,10 @@ class RequestListener
$this->logger = $logger; $this->logger = $logger;
} }
public function handle(EventInterface $event) public function onCoreRequest(GetResponseEvent $event)
{ {
$request = $event->get('request'); $request = $event->getRequest();
$master = HttpKernelInterface::MASTER_REQUEST === $event->get('request_type'); $master = HttpKernelInterface::MASTER_REQUEST === $event->getRequestType();
$this->initializeSession($request, $master); $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"> xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters> <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> </parameters>
<services> <services>

View File

@ -13,7 +13,7 @@
<service id="esi" class="%esi.class%" public="false" /> <service id="esi" class="%esi.class%" public="false" />
<service id="esi_listener" class="%esi_listener.class%"> <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" /> <argument type="service" id="esi" on-invalid="ignore" />
</service> </service>
</services> </services>

View File

@ -23,9 +23,9 @@
</service> </service>
<service id="profiler_listener" class="%profiler_listener.class%"> <service id="profiler_listener" class="%profiler_listener.class%">
<tag name="kernel.listener" event="core.response" method="handleResponse" /> <tag name="kernel.listener" event="onCoreResponse" />
<tag name="kernel.listener" event="core.exception" method="handleException" /> <tag name="kernel.listener" event="onCoreException" />
<tag name="kernel.listener" event="core.request" method="handleRequest" /> <tag name="kernel.listener" event="onCoreRequest" />
<argument type="service" id="service_container" /> <argument type="service" id="service_container" />
<argument type="service" id="profiler.request_matcher" on-invalid="null" /> <argument type="service" id="profiler.request_matcher" on-invalid="null" />
<argument /> <!-- Only exceptions? --> <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"> xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters> <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="http_kernel.class">Symfony\Bundle\FrameworkBundle\HttpKernel</parameter>
<parameter key="error_handler.class">Symfony\Component\HttpKernel\Debug\ErrorHandler</parameter> <parameter key="error_handler.class">Symfony\Component\HttpKernel\Debug\ErrorHandler</parameter>
<parameter key="error_handler.level">null</parameter> <parameter key="error_handler.level">null</parameter>
@ -25,9 +25,9 @@
</service> </service>
<service id="http_kernel" class="%http_kernel.class%"> <service id="http_kernel" class="%http_kernel.class%">
<argument type="service" id="event_dispatcher" />
<argument type="service" id="service_container" /> <argument type="service" id="service_container" />
<argument type="service" id="controller_resolver" /> <argument type="service" id="controller_resolver" />
<call method="setEventDispatcher"><argument type="service" id="event_dispatcher" /></call>
</service> </service>
<service id="cache_warmer" class="%cache_warmer.class%"> <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.client.cookiejar" class="%test.client.cookiejar.class%" scope="prototype" />
<service id="test.session.listener" class="%test.session.listener.class%"> <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> </service>
</services> </services>
</container> </container>

View File

@ -26,19 +26,19 @@
</service> </service>
<service id="request_listener" class="%request_listener.class%"> <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="service_container" />
<argument type="service" id="router" /> <argument type="service" id="router" />
<argument type="service" id="logger" on-invalid="ignore" /> <argument type="service" id="logger" on-invalid="ignore" />
</service> </service>
<service id="response_listener" class="%response_listener.class%"> <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> <argument>%kernel.charset%</argument>
</service> </service>
<service id="exception_listener" class="%exception_listener.class%"> <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>%exception_listener.controller%</argument>
<argument type="service" id="logger" on-invalid="null" /> <argument type="service" id="logger" on-invalid="null" />
</service> </service>

View File

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

View File

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

View File

@ -106,7 +106,7 @@
<!-- Firewall related services --> <!-- Firewall related services -->
<service id="security.firewall" class="%security.firewall.class%"> <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="security.firewall.map" />
<argument type="service" id="event_dispatcher" /> <argument type="service" id="event_dispatcher" />
</service> </service>

View File

@ -51,7 +51,7 @@
</service> </service>
<service id="security.rememberme.response_listener" class="%security.rememberme.response_listener.class%"> <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> </service>
</services> </services>

View File

@ -3,7 +3,7 @@
namespace Symfony\Bundle\SecurityBundle; namespace Symfony\Bundle\SecurityBundle;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventInterface; use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface; use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
/** /**
@ -13,15 +13,13 @@ use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
*/ */
class ResponseListener class ResponseListener
{ {
public function handle(EventInterface $event, Response $response) public function onCoreResponse(FilterResponseEvent $event)
{ {
$request = $event->get('request'); $request = $event->getRequest();
if (!$request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME)) { $response = $event->getResponse();
return $response;
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> <services>
<service id="debug.toolbar" class="%debug.toolbar.class%"> <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="http_kernel" />
<argument type="service" id="templating.engine.twig" /> <argument type="service" id="templating.engine.twig" />
<argument>%debug.toolbar.intercept_redirects%</argument> <argument>%debug.toolbar.intercept_redirects%</argument>

View File

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

View File

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

View File

@ -1,136 +1,70 @@
<?php <?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> * This software consists of voluntary contributions made by many individuals
* * and is licensed under the LGPL. For more information, see
* For the full copyright and license information, please view the LICENSE * <http://www.doctrine-project.org>.
* file that was distributed with this source code.
*/ */
namespace Symfony\Component\EventDispatcher; 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; * @var Boolean Whether no further event listeners should be triggered
protected $name; */
protected $parameters; private $propagationStopped = false;
/** /**
* Constructs a new Event. * Returns whether further event listeners should be triggered.
* *
* @param mixed $subject The subject * @see Event::stopPropagation
* @param string $name The event name * @return Boolean Whether propagation was already stopped for this event.
* @param array $parameters An array of parameters
*/ */
public function __construct($subject, $name, $parameters = array()) public function isPropagationStopped()
{ {
$this->subject = $subject; return $this->propagationStopped;
$this->name = $name;
$this->parameters = $parameters;
} }
/** /**
* 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; $this->propagationStopped = true;
}
/**
* 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;
} }
} }

View File

@ -1,147 +1,204 @@
<?php <?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> * This software consists of voluntary contributions made by many individuals
* * and is licensed under the LGPL. For more information, see
* For the full copyright and license information, please view the LICENSE * <http://www.doctrine-project.org>.
* file that was distributed with this source code.
*/ */
namespace Symfony\Component\EventDispatcher; 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 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 * @var array
* @param mixed $listener A PHP callable
* @param integer $priority The priority (between -10 and 10 -- defaults to 0)
*/ */
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[$eventName])) {
if (!isset($this->listeners[$name])) { if (null === $event) {
$this->listeners[$name] = array(); $event = new Event();
} }
$this->listeners[$name][$priority] = array();
}
$this->listeners[$name][$priority][] = $listener; $this->sortListeners($eventName);
}
/** foreach ($this->listeners[$eventName] as $listener) {
* Disconnects one, or all listeners for the given event name. $this->triggerListener($listener, $eventName, $event);
*
* @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;
}
if (null === $listener) { if ($event->isPropagationStopped()) {
unset($this->listeners[$name]); break;
return;
}
foreach ($this->listeners[$name] as $priority => $callables) {
foreach ($callables as $i => $callable) {
if ($listener === $callable) {
unset($this->listeners[$name][$priority][$i]);
} }
} }
} }
} }
/** /**
* Notifies all listeners of a given event. * @see EventDispatcherInterface::getListeners
*
* @param EventInterface $event An EventInterface instance
*/ */
public function notify(EventInterface $event) public function getListeners($eventName = null)
{ {
foreach ($this->getListeners($event->getName()) as $listener) { if ($eventName) {
call_user_func($listener, $event); $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. * @see EventDispatcherInterface::removeListener
*
* @param EventInterface $event An EventInterface instance
*
* @return mixed The returned value of the listener that processed the event
*/ */
public function notifyUntil(EventInterface $event) public function removeListener($eventNames, $listener)
{ {
foreach ($this->getListeners($event->getName()) as $listener) { // Picks the hash code related to that listener
$ret = call_user_func($listener, $event); $hash = spl_object_hash($listener);
if ($event->isProcessed()) {
return $ret; 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. * @see EventDispatcherInterface::addSubscriber
*
* @param EventInterface $event An EventInterface instance
* @param mixed $value The value to be filtered
*
* @return mixed The filtered value
*/ */
public function filter(EventInterface $event, $value) public function addSubscriber(EventSubscriberInterface $subscriber, $priority = 0)
{ {
foreach ($this->getListeners($event->getName()) as $listener) { $this->addListener($subscriber->getSubscribedEvents(), $subscriber, $priority);
$value = call_user_func($listener, $event, $value);
}
return $value;
} }
/** /**
* 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])) { if (!$this->sorted[$eventName]) {
return array(); $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; 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 Bernhard Schussek <bschussek@gmail.com>
*
* @author Fabien Potencier <fabien@symfony.com>
*/ */
interface EventDispatcherInterface 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 $eventName The name of the event to dispatch. The name of
* * the event is the name of the method that is
* @param string $name An event name * invoked on listeners.
* @param mixed $listener A PHP callable * @param Event $event The event to pass to the event handlers/listeners.
* @param integer $priority The priority (between -10 and 10 -- defaults to 0) * 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 string|array $eventNames The event(s) to listen on.
* @param mixed|null $listener The listener to remove, or null to remove all * @param object $listener The listener object.
* * @param integer $priority The higher this value, the earlier an event
* @return void * 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 * @param string|array $eventNames The event(s) to remove a listener from.
* by calling the setProcessed() method on it. * @param object $listener The listener object to remove.
*
* 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
*/ */
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 string $eventName The name of the event.
* @param mixed $value The value to be filtered
* *
* @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); function hasListeners($eventName);
/**
* Returns all listeners associated with a given event name.
*
* @param string $name The event name
*
* @return array An array of listeners
*/
function getListeners($name);
} }

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

View File

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

View File

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

View File

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

View File

@ -11,12 +11,16 @@
namespace Symfony\Component\HttpKernel; namespace Symfony\Component\HttpKernel;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; 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\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/** /**
* HttpKernel notifies events to convert a Request object to a Response one. * 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 class HttpKernel implements HttpKernelInterface
{ {
protected $dispatcher; private $dispatcher;
protected $resolver; private $resolver;
/** /**
* Constructor * Constructor
* *
* @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
* @param ControllerResolverInterface $resolver A ControllerResolverInterface instance * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance
*/ */
public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver) public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver)
@ -84,10 +88,11 @@ class HttpKernel implements HttpKernelInterface
protected function handleRaw(Request $request, $type = self::MASTER_REQUEST) protected function handleRaw(Request $request, $type = self::MASTER_REQUEST)
{ {
// request // request
$event = new Event($this, 'core.request', array('request_type' => $type, 'request' => $request)); $event = new GetResponseEvent($this, $request, $type);
$response = $this->dispatcher->notifyUntil($event); $this->dispatcher->dispatch(Events::onCoreRequest, $event);
if ($event->isProcessed()) {
return $this->filterResponse($response, $request, 'A "core.request" listener returned a non response object.', $type); if ($event->hasResponse()) {
return $this->filterResponse($event->getResponse(), $request, $type);
} }
// load controller // 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())); 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)); $event = new FilterControllerEvent($this, $controller, $request, $type);
$controller = $this->dispatcher->filter($event, $controller); $this->dispatcher->dispatch(Events::onCoreController, $event);
$controller = $event->getController();
// controller must be a callable
if (!is_callable($controller)) {
throw new \LogicException(sprintf('The controller must be a callable (%s given).', $this->varToString($controller)));
}
// controller arguments // controller arguments
$arguments = $this->resolver->getArguments($request, $controller); $arguments = $this->resolver->getArguments($request, $controller);
@ -111,14 +112,19 @@ class HttpKernel implements HttpKernelInterface
// view // view
if (!$response instanceof Response) { if (!$response instanceof Response) {
$event = new Event($this, 'core.view', array('request_type' => $type, 'request' => $request, 'controller_value' => $response)); $event = new GetResponseForControllerResultEvent($this, $request, $type, $response);
$retval = $this->dispatcher->notifyUntil($event); $this->dispatcher->dispatch(Events::onCoreView, $event);
if ($event->isProcessed()) {
$response = $retval; 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 * @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) { $event = new FilterResponseEvent($this, $request, $type, $response);
throw new \RuntimeException($message);
}
$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) { return $event->getResponse();
throw new \RuntimeException('A "core.response" listener returned a non response object.');
}
return $response;
} }
/** /**
@ -158,13 +158,14 @@ class HttpKernel implements HttpKernelInterface
*/ */
protected function handleException(\Exception $e, $request, $type) protected function handleException(\Exception $e, $request, $type)
{ {
$event = new Event($this, 'core.exception', array('request_type' => $type, 'request' => $request, 'exception' => $e)); $event = new GetResponseForExceptionEvent($this, $request, $type, $e);
$response = $this->dispatcher->notifyUntil($event); $this->dispatcher->dispatch(Events::onCoreException, $event);
if (!$event->isProcessed()) {
if (!$event->hasResponse()) {
throw $e; 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) protected function varToString($var)

View File

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

View File

@ -2,8 +2,8 @@
namespace Symfony\Component\Security\Http\Authentication; namespace Symfony\Component\Security\Http\Authentication;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
/** /**
@ -22,12 +22,12 @@ interface AuthenticationFailureHandlerInterface
* called by authentication listeners inheriting from * called by authentication listeners inheriting from
* AbstractAuthenticationListener. * 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 * has the kernel as target
* @param Request $request * @param Request $request
* @param AuthenticationException $exception * @param AuthenticationException $exception
* *
* @return Response the response to return * @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; 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\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
@ -22,12 +22,12 @@ interface AuthenticationSuccessHandlerInterface
* is called by authentication listeners inheriting from * is called by authentication listeners inheriting from
* AbstractAuthenticationListener. * 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 * has the kernel as target
* @param Request $request * @param Request $request
* @param TokenInterface $token * @param TokenInterface $token
* *
* @return Response the response to return * @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; namespace Symfony\Component\Security\Http\Authorization;
use Symfony\Component\HttpFoundation\Request; 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\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
/** /**
* This is used by the ExceptionListener to translate an AccessDeniedException * This is used by the ExceptionListener to translate an AccessDeniedException
@ -17,11 +18,11 @@ interface AccessDeniedHandlerInterface
/** /**
* Handles an access denied failure. * Handles an access denied failure.
* *
* @param EventInterface $event * @param GetResponseForExceptionEvent $event
* @param Request $request * @param Request $request
* @param AccessDeniedException $accessDeniedException * @param AccessDeniedException $accessDeniedException
* *
* @return Response may return null * @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; 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\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
@ -26,9 +26,9 @@ interface AuthenticationEntryPointInterface
/** /**
* Starts the authentication scheme. * 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 object $request The request that resulted in an AuthenticationException
* @param AuthenticationException $authException The exception that started the authentication process * @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; namespace Symfony\Component\Security\Http\EntryPoint;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
/** /**
* BasicAuthenticationEntryPoint starts an HTTP Basic authentication. * BasicAuthenticationEntryPoint starts an HTTP Basic authentication.
@ -31,7 +31,7 @@ class BasicAuthenticationEntryPoint implements AuthenticationEntryPointInterface
$this->realmName = $realmName; $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 = new Response();
$response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realmName)); $response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realmName));

View File

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

View File

@ -11,13 +11,13 @@
namespace Symfony\Component\Security\Http\EntryPoint; namespace Symfony\Component\Security\Http\EntryPoint;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
/** /**
* FormAuthenticationEntryPoint starts an authentication via a login form. * FormAuthenticationEntryPoint starts an authentication via a login form.
@ -44,10 +44,10 @@ class FormAuthenticationEntryPoint implements AuthenticationEntryPointInterface
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function start(EventInterface $event, Request $request, AuthenticationException $authException = null) public function start(GetResponseEvent $event, Request $request, AuthenticationException $authException = null)
{ {
if ($this->useForward) { 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); 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; namespace Symfony\Component\Security\Http\EntryPoint;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
/** /**
* RetryAuthenticationEntryPoint redirects URL based on the configured scheme. * RetryAuthenticationEntryPoint redirects URL based on the configured scheme.
@ -36,7 +36,7 @@ class RetryAuthenticationEntryPoint implements AuthenticationEntryPointInterface
$this->httpsPort = $httpsPort; $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'; $scheme = $request->isSecure() ? 'http' : 'https';
if ('http' === $scheme && 80 != $this->httpPort) { 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; 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\HttpKernelInterface;
use Symfony\Component\HttpKernel\Events;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/** /**
* Firewall uses a FirewallMap to register security listeners for the given * 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 * (a Basic authentication for the /api, and a web based authentication for
* everything else for instance). * everything else for instance).
* *
* The handle method must be connected to the core.request event.
*
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
*/ */
class Firewall class Firewall
{ {
private $map; private $map;
private $dispatcher;
private $currentListeners;
/** /**
* Constructor. * Constructor.
@ -42,21 +42,22 @@ class Firewall
{ {
$this->map = $map; $this->map = $map;
$this->dispatcher = $dispatcher; $this->dispatcher = $dispatcher;
$this->currentListeners = array();
} }
/** /**
* Handles security. * 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; return;
} }
// register listeners for this firewall // 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) { if (null !== $exception) {
$exception->register($this->dispatcher); $exception->register($this->dispatcher);
} }
@ -65,8 +66,8 @@ class Firewall
foreach ($listeners as $listener) { foreach ($listeners as $listener) {
$response = $listener->handle($event); $response = $listener->handle($event);
if ($event->isProcessed()) { if ($event->hasResponse()) {
return $response; break;
} }
} }
} }

View File

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

View File

@ -11,15 +11,17 @@
namespace Symfony\Component\Security\Http\Firewall; namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; 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\Authentication\Token\PreAuthenticatedToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException; 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\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/** /**
* AbstractPreAuthenticatedListener is the base class for all listener that * AbstractPreAuthenticatedListener is the base class for all listener that
@ -34,25 +36,25 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface
private $securityContext; private $securityContext;
private $authenticationManager; private $authenticationManager;
private $providerKey; 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->securityContext = $securityContext;
$this->authenticationManager = $authenticationManager; $this->authenticationManager = $authenticationManager;
$this->providerKey = $providerKey; $this->providerKey = $providerKey;
$this->logger = $logger; $this->logger = $logger;
$this->eventDispatcher = $eventDispatcher; $this->dispatcher = $dispatcher;
} }
/** /**
* Handles X509 authentication. * 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) { if (null !== $this->logger) {
$this->logger->debug(sprintf('Checking secure context token: %s', $this->securityContext->getToken())); $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); $this->securityContext->setToken($token);
if (null !== $this->eventDispatcher) { if (null !== $this->dispatcher) {
$this->eventDispatcher->notify(new Event($this, 'security.interactive_login', array('request' => $request, 'token' => $token))); $loginEvent = new InteractiveLoginEvent($request, $token);
$this->dispatcher->dispatch(Events::onSecurityInteractiveLogin, $loginEvent);
} }
} catch (AuthenticationException $failed) { } catch (AuthenticationException $failed) {
$this->securityContext->setToken(null); $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\Http\AccessMap;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface; use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventInterface; use Symfony\Component\HttpKernel\Events;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException; use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\Exception\AccessDeniedException;
@ -46,15 +46,15 @@ class AccessListener implements ListenerInterface
/** /**
* Handles access authorization. * 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()) { if (null === $token = $this->context->getToken()) {
throw new AuthenticationCredentialsNotFoundException('A Token was not found in the SecurityContext.'); 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); 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\Security\Core\SecurityContextInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface; use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventInterface; use Symfony\Component\HttpKernel\Events;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
/** /**
@ -39,9 +39,9 @@ class AnonymousAuthenticationListener implements ListenerInterface
/** /**
* Handles anonymous authentication. * 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()) { if (null !== $this->context->getToken()) {
return; return;

View File

@ -15,8 +15,8 @@ use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface; use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventInterface; use Symfony\Component\HttpKernel\Events;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\AuthenticationException;
@ -51,11 +51,11 @@ class BasicAuthenticationListener implements ListenerInterface
/** /**
* Handles basic authentication. * 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)) { if (false === $username = $request->server->get('PHP_AUTH_USER', false)) {
return; return;

View File

@ -14,8 +14,8 @@ namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\Security\Http\AccessMap; use Symfony\Component\Security\Http\AccessMap;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface; use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventInterface; use Symfony\Component\HttpKernel\Events;
/** /**
* ChannelListener switches the HTTP protocol based on the access control * ChannelListener switches the HTTP protocol based on the access control
@ -39,11 +39,11 @@ class ChannelListener implements ListenerInterface
/** /**
* Handles channel management. * 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); list($attributes, $channel) = $this->map->getPatterns($request);
@ -52,9 +52,11 @@ class ChannelListener implements ListenerInterface
$this->logger->debug('Redirecting to HTTPS'); $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()) { if ('http' === $channel && $request->isSecure()) {
@ -62,9 +64,9 @@ class ChannelListener implements ListenerInterface
$this->logger->debug('Redirecting to HTTP'); $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; namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface; 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\AnonymousToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\SecurityContext; use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/** /**
* ContextListener manages the SecurityContext persistence through a session. * ContextListener manages the SecurityContext persistence through a session.
@ -36,7 +38,7 @@ class ContextListener implements ListenerInterface
private $logger; private $logger;
private $userProviders; 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)) { if (empty($contextKey)) {
throw new \InvalidArgumentException('$contextKey must not be empty.'); throw new \InvalidArgumentException('$contextKey must not be empty.');
@ -46,19 +48,19 @@ class ContextListener implements ListenerInterface
$this->userProviders = $userProviders; $this->userProviders = $userProviders;
$this->contextKey = $contextKey; $this->contextKey = $contextKey;
if (null !== $eventDispatcher) { if (null !== $dispatcher) {
$eventDispatcher->connect('core.response', array($this, 'write'), 0); $dispatcher->addListener(Events::onCoreResponse, $this);
} }
} }
/** /**
* Reads the SecurityContext from the session. * 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; $session = $request->hasSession() ? $request->getSession() : null;
@ -82,29 +84,27 @@ class ContextListener implements ListenerInterface
/** /**
* Writes the SecurityContext to the session. * 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')) { if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return $response; return;
} }
if (null === $token = $this->context->getToken()) { if (null === $token = $this->context->getToken()) {
return $response; return;
} }
if (null === $token || $token instanceof AnonymousToken) { if (null === $token || $token instanceof AnonymousToken) {
return $response; return;
} }
if (null !== $this->logger) { if (null !== $this->logger) {
$this->logger->debug('Write SecurityContext in the session'); $this->logger->debug('Write SecurityContext in the session');
} }
$event->get('request')->getSession()->set('_security_'.$this->contextKey, serialize($token)); $event->getRequest()->getSession()->set('_security_'.$this->contextKey, serialize($token));
return $response;
} }
/** /**

View File

@ -15,8 +15,8 @@ use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint; use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint;
use Symfony\Component\HttpKernel\Log\LoggerInterface; use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventInterface; use Symfony\Component\HttpKernel\Events;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException; use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
@ -54,11 +54,11 @@ class DigestAuthenticationListener implements ListenerInterface
/** /**
* Handles digest authentication. * 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')) { if (!$header = $request->server->get('PHP_AUTH_DIGEST')) {
return; return;
@ -121,7 +121,7 @@ class DigestAuthenticationListener implements ListenerInterface
$this->securityContext->setToken(new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey)); $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); $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\Core\Authentication\AuthenticationTrustResolverInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface; 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\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Exception\InsufficientAuthenticationException; use Symfony\Component\Security\Core\Exception\InsufficientAuthenticationException;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface; 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 * 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 EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
* @param integer $priority The priority
*/ */
public function register(EventDispatcherInterface $dispatcher) public function register(EventDispatcherInterface $dispatcher)
{ {
$dispatcher->connect('core.exception', array($this, 'handleException'), 0); $dispatcher->addListener(Events::onCoreException, $this);
} }
/** /**
* Handles security related exceptions. * 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'); $exception = $event->getException();
$request = $event->get('request'); $request = $event->getRequest();
if ($exception instanceof AuthenticationException) { if ($exception instanceof AuthenticationException) {
if (null !== $this->logger) { if (null !== $this->logger) {
@ -118,7 +118,7 @@ class ExceptionListener
$subRequest = Request::create($this->errorPage); $subRequest = Request::create($this->errorPage);
$subRequest->attributes->set(SecurityContextInterface::ACCESS_DENIED_ERROR, $exception); $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); $response->setStatusCode(403);
} }
} catch (\Exception $e) { } 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())); $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; return;
} }
@ -135,12 +135,10 @@ class ExceptionListener
return; return;
} }
$event->setProcessed(); $event->setResponse($response);
return $response;
} }
private function startAuthentication(EventInterface $event, Request $request, AuthenticationException $authException) private function startAuthentication(GetResponseForExceptionEvent $event, Request $request, AuthenticationException $authException)
{ {
$this->context->setToken(null); $this->context->setToken(null);

View File

@ -11,8 +11,7 @@
namespace Symfony\Component\Security\Http\Firewall; namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\EventDispatcher\EventInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/** /**
@ -25,7 +24,7 @@ interface ListenerInterface
/** /**
* This interface must be implemented by firewall listeners. * 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\Http\Logout\LogoutHandlerInterface;
use Symfony\Component\Security\Core\SecurityContextInterface; 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\Response;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Kernel\Event\GetResponseEvent;
use Symfony\Component\Kernel\Events;
/** /**
* LogoutListener logout users. * LogoutListener logout users.
@ -63,11 +63,11 @@ class LogoutListener implements ListenerInterface
/** /**
* Performs the logout if requested * 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()) { if ($this->logoutPath !== $request->getPathInfo()) {
return; return;
@ -92,8 +92,6 @@ class LogoutListener implements ListenerInterface
$this->securityContext->setToken(null); $this->securityContext->setToken(null);
$event->setProcessed(); $event->setResponse($response);
return $response;
} }
} }

View File

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

View File

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

View File

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

View File

@ -11,12 +11,12 @@
namespace Symfony\Component\Security\Http\Firewall; namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface; use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/** /**
* X509 authentication listener. * X509 authentication listener.
@ -28,9 +28,9 @@ class X509AuthenticationListener extends AbstractPreAuthenticatedListener
private $userKey; private $userKey;
private $credentialKey; 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->userKey = $userKey;
$this->credentialKey = $credentialKey; $this->credentialKey = $credentialKey;

View File

@ -3,7 +3,7 @@
namespace Symfony\Component\Security\Http\Logout; namespace Symfony\Component\Security\Http\Logout;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent;
/** /**
* LogoutSuccesshandlerInterface. * LogoutSuccesshandlerInterface.
@ -21,9 +21,9 @@ interface LogoutSuccessHandlerInterface
/** /**
* Creates a Response object to send upon a successful logout. * Creates a Response object to send upon a successful logout.
* *
* @param EventInterface $event * @param GetResponseEvent $event
* @param Request $request * @param Request $request
* @return Response never null * @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\Event;
use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class EventDispatcherTest extends \PHPUnit_Framework_TestCase 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(); $this->dispatcher = new EventDispatcher();
$this->listener = new TestEventListener();
$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');
} }
public function testGetHasListeners() public function testInitialState()
{ {
$dispatcher = new EventDispatcher(); $this->assertEquals(array(), $this->dispatcher->getListeners());
$this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
$this->assertFalse($dispatcher->hasListeners('foo'), '->hasListeners() returns false if the event has no listener'); $this->assertFalse($this->dispatcher->hasListeners(self::postFoo));
$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');
} }
public function testNotify() public function testAddListener()
{ {
$listener = new Listener(); $this->dispatcher->addListener(array('preFoo', 'postFoo'), $this->listener);
$dispatcher = new EventDispatcher(); $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
$dispatcher->connect('foo', array($listener, 'listenToFoo')); $this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
$dispatcher->connect('foo', array($listener, 'listenToFooBis')); $this->assertEquals(1, count($this->dispatcher->getListeners(self::preFoo)));
$e = $dispatcher->notify($event = new Event(new \stdClass(), 'foo')); $this->assertEquals(1, count($this->dispatcher->getListeners(self::postFoo)));
$this->assertEquals('listenToFoolistenToFooBis', $listener->getValue(), '->notify() notifies all registered listeners in order'); $this->assertEquals(2, count($this->dispatcher->getListeners()));
$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');
} }
public function testNotifyUntil() public function testGetListenersSortsByPriority()
{ {
$listener = new Listener(); $listener1 = new TestEventListener();
$dispatcher = new EventDispatcher(); $listener2 = new TestEventListener();
$dispatcher->connect('foo', array($listener, 'listenToFoo')); $listener3 = new TestEventListener();
$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');
$listener->reset(); $this->dispatcher->addListener('preFoo', $listener1, -10);
$dispatcher = new EventDispatcher(); $this->dispatcher->addListener('preFoo', $listener2);
$dispatcher->connect('foo', array($listener, 'listenToFooBis')); $this->dispatcher->addListener('preFoo', $listener3, 10);
$dispatcher->connect('foo', array($listener, 'listenToFoo'));
$dispatcher->notifyUntil($event = new Event(new \stdClass(), 'foo')); $expected = array(
$this->assertEquals('listenToFooBis', $listener->getValue(), '->notifyUntil() notifies all registered listeners in order and stops when the event is processed'); 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(); $listener1 = new TestEventListener();
$dispatcher = new EventDispatcher(); $listener2 = new TestEventListener();
$dispatcher->connect('foo', array($listener, 'filterFoo')); $listener3 = new TestEventListener();
$dispatcher->connect('foo', array($listener, 'filterFooBis')); $listener4 = new TestEventListener();
$ret = $dispatcher->filter($event = new Event(new \stdClass(), 'foo'), 'foo'); $listener5 = new TestEventListener();
$this->assertEquals('-*foo*-', $ret, '->filter() returns the filtered value'); $listener6 = new TestEventListener();
$listener->reset(); $this->dispatcher->addListener('preFoo', $listener1, -10);
$dispatcher = new EventDispatcher(); $this->dispatcher->addListener('preFoo', $listener2);
$dispatcher->connect('foo', array($listener, 'filterFooBis')); $this->dispatcher->addListener('preFoo', $listener3, 10);
$dispatcher->connect('foo', array($listener, 'filterFoo')); $this->dispatcher->addListener('postFoo', $listener4, -10);
$ret = $dispatcher->filter($event = new Event(new \stdClass(), 'foo'), 'foo'); $this->dispatcher->addListener('postFoo', $listener5);
$this->assertEquals('*-foo-*', $ret, '->filter() returns the filtered value'); $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 public $preFooInvoked = false;
$value = ''; 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) $e->stopPropagation();
{ }
$this->value .= 'listenToFoo'; }
}
class TestEventSubscriber implements EventSubscriberInterface
function listenToFooBis(Event $event) {
{ public static function getSubscribedEvents()
$this->value .= 'listenToFooBis'; {
return array('preFoo', 'postFoo');
$event->setProcessed();
}
function getValue()
{
return $this->value;
}
function reset()
{
$this->value = '';
} }
} }

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\HttpKernel\HttpKernel;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
require_once __DIR__.'/TestHttpKernel.php'; require_once __DIR__.'/TestHttpKernel.php';

View File

@ -14,10 +14,9 @@ namespace Symfony\Tests\Component\HttpKernel\DataCollector;
use Symfony\Component\HttpKernel\DataCollector\EventDataCollector; use Symfony\Component\HttpKernel\DataCollector\EventDataCollector;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Debug\EventDispatcherTraceableInterface; use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcher;
class EventDataCollectorTest extends \PHPUnit_Framework_TestCase class EventDataCollectorTest extends \PHPUnit_Framework_TestCase
{ {
public function testCollect() public function testCollect()
@ -34,7 +33,7 @@ class EventDataCollectorTest extends \PHPUnit_Framework_TestCase
} }
class TestEventDispatcher extends EventDispatcher implements EventDispatcherTraceableInterface class TestEventDispatcher extends EventDispatcher implements TraceableEventDispatcherInterface
{ {
function getCalledListeners() function getCalledListeners()
{ {

View File

@ -11,11 +11,13 @@
namespace Symfony\Tests\Component\HttpKernel\Debug; namespace Symfony\Tests\Component\HttpKernel\Debug;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Debug\ExceptionListener; 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\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; use Symfony\Tests\Component\HttpKernel\Logger;
/** /**
@ -30,36 +32,37 @@ class ExceptionListenerTest extends \PHPUnit_Framework_TestCase
$logger = new TestLogger(); $logger = new TestLogger();
$l = new ExceptionListener('foo', $logger); $l = new ExceptionListener('foo', $logger);
$_logger = new \ReflectionProperty(get_class($l),'logger'); $_logger = new \ReflectionProperty(get_class($l), 'logger');
$_logger->setAccessible(true); $_logger->setAccessible(true);
$_controller = new \ReflectionProperty(get_class($l),'controller'); $_controller = new \ReflectionProperty(get_class($l), 'controller');
$_controller->setAccessible(true); $_controller->setAccessible(true);
$this->assertSame($logger,$_logger->getValue($l)); $this->assertSame($logger, $_logger->getValue($l));
$this->assertSame('foo',$_controller->getValue($l)); $this->assertSame('foo', $_controller->getValue($l));
} }
/** /**
* @dataProvider provider * @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 //store the current error_log, and set the new one to dev/null
$error_log = ini_get('error_log'); $error_log = ini_get('error_log');
ini_set('error_log','/dev/null'); ini_set('error_log', '/dev/null');
$l = new ExceptionListener('foo'); $l = new ExceptionListener('foo');
$l->onCoreException($event);
$this->assertEquals('foo', $l->handle($event)); $this->assertEquals(new Response('foo'), $event->getResponse());
try{ try {
$response = $l->handle($event2); $l->onCoreException($event2);
}catch(\Exception $e){ } catch(\Exception $e) {
$this->assertSame('foo',$e->getMessage()); $this->assertSame('foo', $e->getMessage());
} }
//restore the old error_log //restore the old error_log
ini_set('error_log',$error_log); ini_set('error_log', $error_log);
} }
/** /**
@ -69,29 +72,30 @@ class ExceptionListenerTest extends \PHPUnit_Framework_TestCase
{ {
$logger = new TestLogger(); $logger = new TestLogger();
$l = new ExceptionListener('foo',$logger); $l = new ExceptionListener('foo', $logger);
$l->onCoreException($event);
$this->assertSame('foo', $l->handle($event)); $this->assertEquals(new Response('foo'), $event->getResponse());
try{ try {
$response = $l->handle($event2); $l->onCoreException($event2);
}catch(\Exception $e){ } catch(\Exception $e) {
$this->assertSame('foo',$e->getMessage()); $this->assertSame('foo', $e->getMessage());
} }
$this->assertEquals(3,$logger->countErrors()); $this->assertEquals(3, $logger->countErrors());
$this->assertEquals(3,count($logger->getLogs('err'))); $this->assertEquals(3, count($logger->getLogs('err')));
} }
public function provider() public function provider()
{ {
$args = array('exception'=>new ErrorException('foo'),'request'=>new Request()); $request = new Request();
$exception = new ErrorException('foo');
$event = new Event(new Subject(),'bar',$args); $event = new GetResponseForExceptionEvent(new TestKernel(), $request, 'foo', $exception);
$event2 = new Event(new SubjectException(),'bar',$args); $event2 = new GetResponseForExceptionEvent(new TestKernelThatThrowsException(), $request, 'foo', $exception);
return array( return array(
array($event,$event2) array($event, $event2)
); );
} }
@ -110,18 +114,18 @@ class TestLogger extends Logger implements DebugLoggerInterface
} }
} }
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'); 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\Esi;
use Symfony\Component\HttpKernel\HttpCache\EsiListener; use Symfony\Component\HttpKernel\HttpCache\EsiListener;
use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\EventDispatcher\Event; use Symfony\Component\HttpKernel\Events;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface; 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 class EsiListenerTest extends \PHPUnit_Framework_TestCase
{ {
public function testFilterDoesNothingForSubRequests() public function testFilterDoesNothingForSubRequests()
{ {
$dispatcher = new EventDispatcher(); $dispatcher = new EventDispatcher();
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new Response('foo <esi:include src="" />');
$listener = new EsiListener(new Esi()); $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->addListener(Events::onCoreResponse, $listener);
$dispatcher->filter($event, $response = new Response('foo <esi:include src="" />')); $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() public function testFilterWhenThereIsSomeEsiIncludes()
{ {
$dispatcher = new EventDispatcher(); $dispatcher = new EventDispatcher();
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new Response('foo <esi:include src="" />');
$listener = new EsiListener(new Esi()); $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->addListener(Events::onCoreResponse, $listener);
$dispatcher->filter($event, $response = new Response('foo <esi:include src="" />')); $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() public function testFilterWhenThereIsNoEsiIncludes()
{ {
$dispatcher = new EventDispatcher(); $dispatcher = new EventDispatcher();
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new Response('foo');
$listener = new EsiListener(new Esi()); $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->addListener(Events::onCoreResponse, $listener);
$dispatcher->filter($event, $response = new Response('foo')); $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\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
class TestHttpKernel extends HttpKernel implements ControllerResolverInterface 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\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
class TestMultipleHttpKernel extends HttpKernel implements ControllerResolverInterface 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\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Events;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcher;
@ -42,11 +43,9 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
public function testHandleWhenControllerThrowsAnExceptionAndRawIsFalse() public function testHandleWhenControllerThrowsAnExceptionAndRawIsFalse()
{ {
$dispatcher = new EventDispatcher(); $dispatcher = new EventDispatcher();
$dispatcher->connect('core.exception', function ($event) $dispatcher->addListener(Events::onCoreException, function ($event)
{ {
$event->setProcessed(); $event->setResponse(new Response($event->getException()->getMessage()));
return new Response($event->get('exception')->getMessage());
}); });
$kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new \RuntimeException('foo'); })); $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new \RuntimeException('foo'); }));
@ -57,11 +56,9 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
public function testHandleWhenAListenerReturnsAResponse() public function testHandleWhenAListenerReturnsAResponse()
{ {
$dispatcher = new EventDispatcher(); $dispatcher = new EventDispatcher();
$dispatcher->connect('core.request', function ($event) $dispatcher->addListener(Events::onCoreRequest, function ($event)
{ {
$event->setProcessed(); $event->setResponse(new Response('hello'));
return new Response('hello');
}); });
$kernel = new HttpKernel($dispatcher, $this->getResolver()); $kernel = new HttpKernel($dispatcher, $this->getResolver());
@ -92,7 +89,7 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* @expectedException RuntimeException * @expectedException LogicException
*/ */
public function testHandleWhenControllerDoesNotReturnAResponse() public function testHandleWhenControllerDoesNotReturnAResponse()
{ {
@ -105,55 +102,21 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
public function testHandleWhenControllerDoesNotReturnAResponseButAViewIsRegistered() public function testHandleWhenControllerDoesNotReturnAResponseButAViewIsRegistered()
{ {
$dispatcher = new EventDispatcher(); $dispatcher = new EventDispatcher();
$dispatcher->connect('core.view', function ($event) $dispatcher->addListener(Events::onCoreView, function ($event)
{ {
$event->setProcessed(); $event->setResponse(new Response($event->getControllerResult()));
return new Response($event->get('controller_value'));
}); });
$kernel = new HttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; })); $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; }));
$this->assertEquals('foo', $kernel->handle(new Request())->getContent()); $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() public function testHandleWithAResponseListener()
{ {
$dispatcher = new EventDispatcher(); $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()); $kernel = new HttpKernel($dispatcher, $this->getResolver());

View File

@ -12,56 +12,68 @@
namespace Symfony\Tests\Component\HttpKernel; namespace Symfony\Tests\Component\HttpKernel;
use Symfony\Component\HttpKernel\ResponseListener; use Symfony\Component\HttpKernel\ResponseListener;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface; 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 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() public function testFilterDoesNothingForSubRequests()
{ {
$event = new Event(null, 'core.response', array('request_type' => HttpKernelInterface::SUB_REQUEST)); $response = new Response('foo');
$this->getDispatcher()->filter($event, $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() public function testFilterDoesNothingIfContentTypeIsSet()
{ {
$event = new Event(null, 'core.response', array('request_type' => HttpKernelInterface::MASTER_REQUEST));
$response = new Response('foo'); $response = new Response('foo');
$response->headers->set('Content-Type', 'text/plain'); $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() public function testFilterDoesNothingIfRequestFormatIsNotDefined()
{ {
$event = new Event(null, 'core.response', array('request_type' => HttpKernelInterface::MASTER_REQUEST, 'request' => Request::create('/'))); $response = new Response('foo');
$this->getDispatcher()->filter($event, $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() public function testFilterSetContentType()
{ {
$response = new Response('foo');
$request = Request::create('/'); $request = Request::create('/');
$request->setRequestFormat('json'); $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() $this->assertEquals('application/json', $event->getResponse()->headers->get('content-type'));
{
$dispatcher = new EventDispatcher();
$listener = new ResponseListener('UTF-8');
$dispatcher->connect('core.response', array($listener, 'filter'));
return $dispatcher;
} }
} }

View File

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

View File

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