1<?php 2 3namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler; 4 5use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 6use Symfony\Component\DependencyInjection\ContainerBuilder; 7use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; 8use Symfony\Component\DependencyInjection\Reference; 9 10/** 11 * Class for Symfony bundles to register entity listeners 12 */ 13class EntityListenerPass implements CompilerPassInterface 14{ 15 /** 16 * {@inheritDoc} 17 */ 18 public function process(ContainerBuilder $container) 19 { 20 $resolvers = $container->findTaggedServiceIds('doctrine.orm.entity_listener'); 21 22 foreach ($resolvers as $id => $tagAttributes) { 23 foreach ($tagAttributes as $attributes) { 24 $name = isset($attributes['entity_manager']) ? $attributes['entity_manager'] : $container->getParameter('doctrine.default_entity_manager'); 25 $entityManager = sprintf('doctrine.orm.%s_entity_manager', $name); 26 27 if (! $container->hasDefinition($entityManager)) { 28 continue; 29 } 30 31 $resolverId = sprintf('doctrine.orm.%s_entity_listener_resolver', $name); 32 33 if (! $container->has($resolverId)) { 34 continue; 35 } 36 37 $resolver = $container->findDefinition($resolverId); 38 $resolver->setPublic(true); 39 40 if (isset($attributes['entity']) && isset($attributes['event'])) { 41 $this->attachToListener($container, $name, $id, $attributes); 42 } 43 44 if (isset($attributes['lazy']) && $attributes['lazy']) { 45 $listener = $container->findDefinition($id); 46 47 if ($listener->isAbstract()) { 48 throw new InvalidArgumentException(sprintf('The service "%s" must not be abstract as this entity listener is lazy-loaded.', $id)); 49 } 50 51 $interface = 'Doctrine\\Bundle\\DoctrineBundle\\Mapping\\EntityListenerServiceResolver'; 52 $class = $resolver->getClass(); 53 54 if (substr($class, 0, 1) === '%') { 55 // resolve container parameter first 56 $class = $container->getParameterBag()->resolveValue($resolver->getClass()); 57 } 58 59 if (! is_a($class, $interface, true)) { 60 throw new InvalidArgumentException( 61 sprintf('Lazy-loaded entity listeners can only be resolved by a resolver implementing %s.', $interface) 62 ); 63 } 64 65 $listener->setPublic(true); 66 67 $resolver->addMethodCall('registerService', [$listener->getClass(), $id]); 68 } else { 69 $resolver->addMethodCall('register', [new Reference($id)]); 70 } 71 } 72 } 73 } 74 75 private function attachToListener(ContainerBuilder $container, $name, $id, array $attributes) 76 { 77 $listenerId = sprintf('doctrine.orm.%s_listeners.attach_entity_listeners', $name); 78 79 if (! $container->has($listenerId)) { 80 return; 81 } 82 83 $serviceDef = $container->getDefinition($id); 84 85 $args = [ 86 $attributes['entity'], 87 $serviceDef->getClass(), 88 $attributes['event'], 89 ]; 90 91 if (isset($attributes['method'])) { 92 $args[] = $attributes['method']; 93 } 94 95 $container->findDefinition($listenerId)->addMethodCall('addEntityListener', $args); 96 } 97} 98