Completed
Push — master ( 9c0fcf...cbcb64 )
by Tobias
05:38
created

CompilerPasses::replaceSimpleBusPublisher()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 33
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4.944

Importance

Changes 0
Metric Value
dl 0
loc 33
ccs 10
cts 25
cp 0.4
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 25
nc 3
nop 1
crap 4.944
1
<?php
2
3
namespace Happyr\SimpleBusBundle\DependencyInjection\CompilerPass;
4
5
use Happyr\SimpleBusBundle\Message\Publisher\DirectPublisher;
6
use Happyr\SimpleBusBundle\Message\Publisher\RabbitMQPublisher;
7
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
8
use Symfony\Component\DependencyInjection\ContainerBuilder;
9
use Symfony\Component\DependencyInjection\ContainerInterface;
10
use Symfony\Component\DependencyInjection\Reference;
11
12
/**
13
 * @author Tobias Nyholm
14
 */
15
class CompilerPasses implements CompilerPassInterface
16
{
17 1
    public function process(ContainerBuilder $container)
18
    {
19 1
        $this->removeCommandHandlerDuplicates($container);
20 1
        $this->handleEventSubscriberDuplicates($container);
21 1
        $this->processMessageHandlers($container);
22 1
        $this->replaceSimpleBusPublisher($container);
23 1
    }
24
25
    /**
26
     * If we find to command handler services that are registered on the same command, make sure we remove the one with '.auto' on the end.
27
     *
28
     * @param ContainerBuilder $container
29
     */
30 1
    private function removeCommandHandlerDuplicates(ContainerBuilder $container)
31
    {
32 1
        $taggedServices = array_merge($container->findTaggedServiceIds('command_handler'), $container->findTaggedServiceIds('asynchronous_command_handler'));
33
34 1
        $commands = [];
35
36 1
        foreach ($taggedServices as $id => $tags) {
37 1
            foreach ($tags as $tag) {
38 1
                if (isset($commands[$tag['handles']])) {
39
                    // Find the one that ends with '.auto'
40
                    $removeServiceId = null;
41
42
                    if (substr($id, -5) === '.auto') {
43
                        $removeServiceId = $id;
44
                    }
45
46
                    if (substr($commands[$tag['handles']], -5) === '.auto') {
47
                        $removeServiceId = $commands[$tag['handles']];
48
                        $commands[$tag['handles']] = $id;
49
                    }
50
51
                    if ($removeServiceId !== null) {
52
                        // Remove the definition
53
                        $container->removeDefinition($removeServiceId);
54
                        continue;
55
                    }
56
                }
57 1
                $commands[$tag['handles']] = $id;
58
            }
59
        }
60 1
    }
61
62
    /**
63
     * @param ContainerBuilder $container
64
     */
65 1
    private function handleEventSubscriberDuplicates(ContainerBuilder $container)
66
    {
67 1
        $taggedServices = array_merge($container->findTaggedServiceIds('event_subscriber'), $container->findTaggedServiceIds('asynchronous_event_subscriber'));
68
69
        // Keys are event class names
70 1
        $events = [];
71
72 1
        foreach ($taggedServices as $id => $tags) {
73 1
            foreach ($tags as $tag) {
74 1
                if (isset($tag['subscribes_to'])) {
75 1
                    $events[$tag['subscribes_to']][] = $id;
76
                }
77
            }
78
        }
79
80 1
        foreach ($events as $eventClass => $subscribersIds) {
81 1
            if (count($subscribersIds) <= 1) {
82 1
                continue;
83
            }
84
85
            // Get services
86
            $subscriberClassNames = [];
87
            foreach ($subscribersIds as $subscribersId) {
88
                $service = $container->getDefinition($subscribersId);
89
                $subscriberClassNames[$service->getClass()][] = $subscribersId;
90
            }
91
92
            foreach ($subscriberClassNames as $className => $services) {
93
                if (count($services) <= 1) {
94
                    continue;
95
                }
96
97
                // IF we have multiple services registed to the same event subscriber, remove the auto added ones.
98
                foreach ($services as $serviceId) {
99
                    if (substr($serviceId, -5) === '.auto') {
100
                        $container->removeDefinition($serviceId);
101
                    }
102
                }
103
            }
104
        }
105 1
    }
106
107
    /**
108
     * @param ContainerBuilder $container
109
     */
110 1
    private function processMessageHandlers(ContainerBuilder $container)
111
    {
112 1
        $taggedServices = array_merge(
113 1
            $container->findTaggedServiceIds('command_handler'),
114 1
            $container->findTaggedServiceIds('event_subscriber'),
115 1
            $container->findTaggedServiceIds('asynchronous_command_handler'),
116 1
            $container->findTaggedServiceIds('asynchronous_event_subscriber')
117
        );
118 1
        $doctrine = $this->hasDoctrine($container);
119
120 1
        foreach ($taggedServices as $id => $tags) {
121 1
            $def = $container->findDefinition($id);
122 1
            $class = $def->getClass();
123
124 1
            if (method_exists($class, 'setEventRecorder')) {
125
                $def->addMethodCall('setEventRecorder', [new Reference('event_recorder')]);
126
            }
127
128 1
            if (method_exists($class, 'setCommandBus')) {
129
                $def->addMethodCall('setCommandBus', [new Reference('command_bus')]);
130
            }
131
132 1
            if (method_exists($class, 'setEventBus')) {
133
                $def->addMethodCall('setEventBus', [new Reference('event_bus')]);
134
            }
135
136 1
            if ($doctrine && method_exists($class, 'setEntityManager')) {
137
                $def->addMethodCall('setEntityManager', [new Reference('doctrine.orm.entity_manager')]);
138
            }
139
140 1
            if (in_array('Psr\Log\LoggerAwareInterface', class_implements($class))) {
141 1
                $def->addMethodCall('setLogger', [new Reference('logger', ContainerInterface::NULL_ON_INVALID_REFERENCE)]);
142
            }
143
        }
144 1
    }
145
146
    /**
147
     * @param ContainerBuilder $container
148
     */
149 1
    private function replaceSimpleBusPublisher(ContainerBuilder $container)
150
    {
151 1
        if (!$container->has('simple_bus.rabbit_mq_bundle_bridge.event_publisher')) {
152
            return;
153
        }
154
155 1
        if (!$container->getParameter('happyr.simplebus.direct_publisher')) {
156 1
            $container->getDefinition('simple_bus.rabbit_mq_bundle_bridge.event_publisher')
157 1
                ->setClass(RabbitMQPublisher::class)
158 1
                ->setLazy(true);
159 1
            $container->getDefinition('simple_bus.rabbit_mq_bundle_bridge.command_publisher')
160 1
                ->setClass(RabbitMQPublisher::class)
161 1
                ->setLazy(true);
162
        } else {
163
            $container->getDefinition('simple_bus.rabbit_mq_bundle_bridge.event_publisher')
164
                ->setClass(DirectPublisher::class)
165
                ->setLazy(true)
166
                ->setArguments([
167
                    new Reference('happyr.mq2php.consumer_wrapper'),
168
                    new Reference('happyr.mq2php.message_serializer'),
169
                    $container->getParameter('happyr.mq2php.event_queue_name'),
170
                ]);
171
172
            $container->getDefinition('simple_bus.rabbit_mq_bundle_bridge.command_publisher')
173
                ->setClass(DirectPublisher::class)
174
                ->setLazy(true)
175
                ->setArguments([
176
                    new Reference('happyr.mq2php.consumer_wrapper'),
177
                    new Reference('happyr.mq2php.message_serializer'),
178
                    $container->getParameter('happyr.mq2php.command_queue_name'),
179
                ]);
180
        }
181 1
    }
182
183
    /**
184
     * @param ContainerBuilder $container
185
     *
186
     * @return bool
187
     */
188 1
    private function hasDoctrine(ContainerBuilder $container)
189
    {
190 1
        return $container->hasDefinition('doctrine.orm.entity_manager') ||
191 1
            $container->hasAlias('doctrine.orm.entity_manager');
192
    }
193
}
194