diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RegisterKernelListenersPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RegisterKernelListenersPass.php index ad406eb6a3d9..4a152f575e62 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RegisterKernelListenersPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RegisterKernelListenersPass.php @@ -25,6 +25,11 @@ public function process(ContainerBuilder $container) $definition = $container->getDefinition('event_dispatcher'); foreach ($container->findTaggedServiceIds('kernel.event_listener') as $id => $events) { + $def = $container->getDefinition($id); + if (!$def->isPublic()) { + throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event listeners are lazy-loaded.', $id)); + } + foreach ($events as $event) { $priority = isset($event['priority']) ? $event['priority'] : 0; @@ -45,8 +50,13 @@ public function process(ContainerBuilder $container) } foreach ($container->findTaggedServiceIds('kernel.event_subscriber') as $id => $attributes) { + $def = $container->getDefinition($id); + if (!$def->isPublic()) { + throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event subscribers are lazy-loaded.', $id)); + } + // We must assume that the class value has been correctly filled, even if the service is created by a factory - $class = $container->getDefinition($id)->getClass(); + $class = $def->getClass(); $refClass = new \ReflectionClass($class); $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface'; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/RegisterKernelListenersPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/RegisterKernelListenersPassTest.php index 670052fe1b3a..a0bbcdc3d86b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/RegisterKernelListenersPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/RegisterKernelListenersPassTest.php @@ -31,6 +31,9 @@ public function testEventSubscriberWithoutInterface() ); $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition'); + $definition->expects($this->atLeastOnce()) + ->method('isPublic') + ->will($this->returnValue(true)); $definition->expects($this->atLeastOnce()) ->method('getClass') ->will($this->returnValue('stdClass')); @@ -60,6 +63,9 @@ public function testValidEventSubscriber() ); $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition'); + $definition->expects($this->atLeastOnce()) + ->method('isPublic') + ->will($this->returnValue(true)); $definition->expects($this->atLeastOnce()) ->method('getClass') ->will($this->returnValue('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\SubscriberService')); @@ -81,6 +87,34 @@ public function testValidEventSubscriber() $registerListenersPass = new RegisterKernelListenersPass(); $registerListenersPass->process($builder); } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The service "foo" must be public as event listeners are lazy-loaded. + */ + public function testPrivateEventListener() + { + $container = new ContainerBuilder(); + $container->register('foo', 'stdClass')->setPublic(false)->addTag('kernel.event_listener', array()); + $container->register('event_dispatcher', 'stdClass'); + + $registerListenersPass = new RegisterKernelListenersPass(); + $registerListenersPass->process($container); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The service "foo" must be public as event subscribers are lazy-loaded. + */ + public function testPrivateEventSubscriber() + { + $container = new ContainerBuilder(); + $container->register('foo', 'stdClass')->setPublic(false)->addTag('kernel.event_subscriber', array()); + $container->register('event_dispatcher', 'stdClass'); + + $registerListenersPass = new RegisterKernelListenersPass(); + $registerListenersPass->process($container); + } } class SubscriberService implements \Symfony\Component\EventDispatcher\EventSubscriberInterface