1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Symfony\Component\EventDispatcher\DependencyInjection;
13:
14: use Symfony\Component\DependencyInjection\ContainerBuilder;
15: use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
16:
17: 18: 19:
20: class RegisterListenersPass implements CompilerPassInterface
21: {
22: 23: 24:
25: protected $dispatcherService;
26:
27: 28: 29:
30: protected $listenerTag;
31:
32: 33: 34:
35: protected $subscriberTag;
36:
37: 38: 39: 40: 41: 42: 43:
44: public function __construct($dispatcherService = 'event_dispatcher', $listenerTag = 'kernel.event_listener', $subscriberTag = 'kernel.event_subscriber')
45: {
46: $this->dispatcherService = $dispatcherService;
47: $this->listenerTag = $listenerTag;
48: $this->subscriberTag = $subscriberTag;
49: }
50:
51: public function process(ContainerBuilder $container)
52: {
53: if (!$container->hasDefinition($this->dispatcherService) && !$container->hasAlias($this->dispatcherService)) {
54: return;
55: }
56:
57: $definition = $container->findDefinition($this->dispatcherService);
58:
59: foreach ($container->findTaggedServiceIds($this->listenerTag) as $id => $events) {
60: $def = $container->getDefinition($id);
61: if (!$def->isPublic()) {
62: throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event listeners are lazy-loaded.', $id));
63: }
64:
65: if ($def->isAbstract()) {
66: throw new \InvalidArgumentException(sprintf('The service "%s" must not be abstract as event listeners are lazy-loaded.', $id));
67: }
68:
69: foreach ($events as $event) {
70: $priority = isset($event['priority']) ? $event['priority'] : 0;
71:
72: if (!isset($event['event'])) {
73: throw new \InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag));
74: }
75:
76: if (!isset($event['method'])) {
77: $event['method'] = 'on'.preg_replace_callback(array(
78: '/(?<=\b)[a-z]/i',
79: '/[^a-z0-9]/i',
80: ), function ($matches) { return strtoupper($matches[0]); }, $event['event']);
81: $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']);
82: }
83:
84: $definition->addMethodCall('addListenerService', array($event['event'], array($id, $event['method']), $priority));
85: }
86: }
87:
88: foreach ($container->findTaggedServiceIds($this->subscriberTag) as $id => $attributes) {
89: $def = $container->getDefinition($id);
90: if (!$def->isPublic()) {
91: throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event subscribers are lazy-loaded.', $id));
92: }
93:
94: if ($def->isAbstract()) {
95: throw new \InvalidArgumentException(sprintf('The service "%s" must not be abstract as event subscribers are lazy-loaded.', $id));
96: }
97:
98:
99: $class = $container->getParameterBag()->resolveValue($def->getClass());
100:
101: $refClass = new \ReflectionClass($class);
102: $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface';
103: if (!$refClass->implementsInterface($interface)) {
104: throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
105: }
106:
107: $definition->addMethodCall('addSubscriberService', array($id, $class));
108: }
109: }
110: }
111: