merged branch fabpot/event-services-check (PR #9006)
This PR was merged into the 2.2 branch. Discussion ---------- Fixed registration of private event listeners/subscribers | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #6541 | License | MIT | Doc PR | n/a When registering a private event subscriber/listener, the listener was just ignored. This PR does two things to fix the problem: * the event listener pass is done earlier to get access to the private services * when a private service is identified, a proper exception is thrown Commits -------8444339
[HttpKernel] added a check for private event listeners/subscribers427ee19
[FrameworkBundle] fixed registration of the register listener pass
This commit is contained in:
commit
6c10b6966d
|
@ -25,6 +25,11 @@ class RegisterKernelListenersPass implements CompilerPassInterface
|
|||
$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 @@ class RegisterKernelListenersPass implements CompilerPassInterface
|
|||
}
|
||||
|
||||
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';
|
||||
|
|
|
@ -60,7 +60,9 @@ class FrameworkBundle extends Bundle
|
|||
|
||||
$container->addCompilerPass(new RoutingResolverPass());
|
||||
$container->addCompilerPass(new ProfilerPass());
|
||||
$container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_AFTER_REMOVING);
|
||||
// must be registered before removing private services as some might be listeners/subscribers
|
||||
// but as late as possible to get resolved parameters
|
||||
$container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_BEFORE_REMOVING);
|
||||
$container->addCompilerPass(new TemplatingPass());
|
||||
$container->addCompilerPass(new AddConstraintValidatorsPass());
|
||||
$container->addCompilerPass(new AddValidatorInitializersPass());
|
||||
|
|
|
@ -31,6 +31,9 @@ class RegisterKernelListenersPassTest extends \PHPUnit_Framework_TestCase
|
|||
);
|
||||
|
||||
$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 @@ class RegisterKernelListenersPassTest extends \PHPUnit_Framework_TestCase
|
|||
);
|
||||
|
||||
$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 @@ class RegisterKernelListenersPassTest extends \PHPUnit_Framework_TestCase
|
|||
$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
|
||||
|
|
Reference in New Issue