Completed
Push — develop ( d322ef...d5777f )
by Baptiste
07:26
created

BuildCommandBusStackPass::process()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 28
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 16
nc 4
nop 1
1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\CommandBusBundle\DependencyInjection\Compiler;
5
6
use Innmind\CommandBusBundle\Exception\LogicException;
7
use Innmind\CommandBus\CommandBusInterface;
8
use Symfony\Component\DependencyInjection\{
9
    Compiler\CompilerPassInterface,
10
    ContainerBuilder,
11
    Definition,
12
    Reference
13
};
14
15
final class BuildCommandBusStackPass implements CompilerPassInterface
16
{
17
    /**
18
     * {@inheritdoc}
19
     */
20
    public function process(ContainerBuilder $container)
21
    {
22
        if (!$container->hasParameter('innmind_command_bus.stack')) {
23
            throw new LogicException;
24
        }
25
26
        $stack = $container->getParameter('innmind_command_bus.stack');
27
        $services = $this->searchServices($container);
28
29
        $container->setAlias(
30
            'innmind_command_bus',
31
            $services[$stack[0]]
32
        );
33
34
        if (count($stack) === 1) {
35
            return;
36
        }
37
38
        for ($i = 0, $count = count($stack) - 1; $i < $count; $i++) {
39
            $alias = $stack[$i];
40
            $next = $stack[$i + 1];
41
42
            $this->inject(
43
                $container->getDefinition($services[$alias]),
44
                $services[$next]
45
            );
46
        }
47
    }
48
49
    private function searchServices(ContainerBuilder $container): array
50
    {
51
        $services = $container->findTaggedServiceIds('innmind_command_bus');
52
        $map = [];
53
54
        foreach ($services as $id => $tags) {
55
            foreach ($tags as $tag => $attributes) {
56
                if (!isset($attributes['alias'])) {
57
                    throw new LogicException;
58
                }
59
60
                $map[$attributes['alias']] = $id;
61
            }
62
        }
63
64
        return $map;
65
    }
66
67
    private function inject(
68
        Definition $definition,
69
        string $next
70
    ) {
71
        $class = $definition->getClass();
72
        $refl = new \ReflectionMethod($class, '__construct');
73
74
        foreach ($refl->getParameters() as $parameter) {
75
            if ((string) $parameter->getType() !== CommandBusInterface::class) {
76
                continue;
77
            }
78
79
            $definition->replaceArgument(
80
                $parameter->getPosition(),
81
                new Reference($next)
82
            );
83
84
            return;
85
        }
86
87
        throw new LogicException(sprintf(
88
            'Missing argument type hinted with CommandBusInterface for "%s"',
89
            $class
90
        ));
91
    }
92
}
93