Implementation of kernel.event_subscriber tag for services.
This commit is contained in:
parent
02b30d929b
commit
8b240d4c22
@ -21,6 +21,7 @@ use Symfony\Component\EventDispatcher\Event;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Bernhard Schussek <bernhard.schussek@symfony.com>
|
||||
* @author Jordan Alliot <jordan.alliot@gmail.com>
|
||||
*/
|
||||
class ContainerAwareEventDispatcher extends EventDispatcher
|
||||
{
|
||||
@ -103,6 +104,32 @@ class ContainerAwareEventDispatcher extends EventDispatcher
|
||||
return parent::getListeners($eventName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a service as event subscriber
|
||||
*
|
||||
* If this service is created by a factory, its class value must be correctly filled.
|
||||
* The service's class must implement Symfony\Component\EventDispatcher\EventSubscriberInterface.
|
||||
*
|
||||
* @param string $serviceId The service ID of the subscriber service
|
||||
* @param string $class The service's class name
|
||||
*/
|
||||
public function addSubscriberService($serviceId, $class)
|
||||
{
|
||||
$refClass = new \ReflectionClass($class);
|
||||
$interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface';
|
||||
if (!$refClass->implementsInterface($interface)) {
|
||||
throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $serviceId, $interface));
|
||||
}
|
||||
|
||||
foreach ($class::getSubscribedEvents() as $eventName => $params) {
|
||||
if (is_string($params)) {
|
||||
$this->listenerIds[$eventName][] = array($serviceId, $params, 0);
|
||||
} else {
|
||||
$this->listenerIds[$eventName][] = array($serviceId, $params[0], $params[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -43,5 +43,18 @@ class RegisterKernelListenersPass implements CompilerPassInterface
|
||||
$definition->addMethodCall('addListenerService', array($event['event'], array($id, $event['method']), $priority));
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($container->findTaggedServiceIds('kernel.event_subscriber') as $id => $attributes) {
|
||||
// We must assume that the class value has been correcly filled, even if the service is created by a factory
|
||||
$class = $container->getDefinition($id)->getClass();
|
||||
|
||||
$refClass = new \ReflectionClass($class);
|
||||
$interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface';
|
||||
if (!$refClass->implementsInterface($interface)) {
|
||||
throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
|
||||
}
|
||||
|
||||
$definition->addMethodCall('addSubscriberService', array($id, $class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
use Symfony\Bundle\FrameworkBundle\ContainerAwareEventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\DependencyInjection\Scope;
|
||||
|
||||
class ContainerAwareEventDispatcherTest extends \PHPUnit_Framework_TestCase
|
||||
@ -39,6 +40,36 @@ class ContainerAwareEventDispatcherTest extends \PHPUnit_Framework_TestCase
|
||||
$dispatcher->dispatch('onEvent', $event);
|
||||
}
|
||||
|
||||
public function testAddASubscriberService()
|
||||
{
|
||||
$event = new Event();
|
||||
|
||||
$service = $this->getMock('Symfony\Bundle\FrameworkBundle\Tests\SubscriberService');
|
||||
|
||||
$service
|
||||
->expects($this->once())
|
||||
->method('onEvent')
|
||||
->with($event)
|
||||
;
|
||||
|
||||
$container = new Container();
|
||||
$container->set('service.subscriber', $service);
|
||||
|
||||
$dispatcher = new ContainerAwareEventDispatcher($container);
|
||||
$dispatcher->addSubscriberService('service.subscriber', 'Symfony\Bundle\FrameworkBundle\Tests\SubscriberService');
|
||||
|
||||
$dispatcher->dispatch('onEvent', $event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testTriggerASubscriberDoesntImplementInterface()
|
||||
{
|
||||
$dispatcher = new ContainerAwareEventDispatcher(new Container());
|
||||
$dispatcher->addSubscriberService('service.subscriber', 'Symfony\Bundle\FrameworkBundle\Tests\Service');
|
||||
}
|
||||
|
||||
public function testPreventDuplicateListenerService()
|
||||
{
|
||||
$event = new Event();
|
||||
@ -174,3 +205,16 @@ class Service
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class SubscriberService implements EventSubscriberInterface
|
||||
{
|
||||
static function getSubscribedEvents() {
|
||||
return array(
|
||||
'onEvent' => 'onEvent',
|
||||
);
|
||||
}
|
||||
|
||||
function onEvent(Event $e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -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\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RegisterKernelListenersPass;
|
||||
|
||||
class RegisterKernelListenersPassTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* Tests that event subscribers not implementing EventSubscriberInterface
|
||||
* trigger an exception.
|
||||
*
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testEventSubscriberWithoutInterface()
|
||||
{
|
||||
// one service, not implementing any interface
|
||||
$services = array(
|
||||
'my_event_subscriber' => array(0 => array()),
|
||||
);
|
||||
|
||||
$definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
|
||||
$definition->expects($this->atLeastOnce())
|
||||
->method('getClass')
|
||||
->will($this->returnValue('stdClass'));
|
||||
|
||||
$builder = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
|
||||
$builder->expects($this->any())
|
||||
->method('hasDefinition')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
// We don't test kernel.event_listener here
|
||||
$builder->expects($this->atLeastOnce())
|
||||
->method('findTaggedServiceIds')
|
||||
->will($this->onConsecutiveCalls(array(), $services));
|
||||
|
||||
$builder->expects($this->atLeastOnce())
|
||||
->method('getDefinition')
|
||||
->will($this->returnValue($definition));
|
||||
|
||||
$registerListenersPass = new RegisterKernelListenersPass();
|
||||
$registerListenersPass->process($builder);
|
||||
}
|
||||
|
||||
public function testValidEventSubscriber()
|
||||
{
|
||||
$services = array(
|
||||
'my_event_subscriber' => array(0 => array()),
|
||||
);
|
||||
|
||||
$definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
|
||||
$definition->expects($this->atLeastOnce())
|
||||
->method('getClass')
|
||||
->will($this->returnValue('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\SubscriberService'));
|
||||
|
||||
$builder = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
|
||||
$builder->expects($this->any())
|
||||
->method('hasDefinition')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
// We don't test kernel.event_listener here
|
||||
$builder->expects($this->atLeastOnce())
|
||||
->method('findTaggedServiceIds')
|
||||
->will($this->onConsecutiveCalls(array(), $services));
|
||||
|
||||
$builder->expects($this->atLeastOnce())
|
||||
->method('getDefinition')
|
||||
->will($this->returnValue($definition));
|
||||
|
||||
$registerListenersPass = new RegisterKernelListenersPass();
|
||||
$registerListenersPass->process($builder);
|
||||
}
|
||||
}
|
||||
|
||||
class SubscriberService implements \Symfony\Component\EventDispatcher\EventSubscriberInterface
|
||||
{
|
||||
static function getSubscribedEvents() {}
|
||||
}
|
Reference in New Issue
Block a user