Completed
Push — master ( d652fb...43bb25 )
by Ross
03:19
created

BusBuilder::registerHandlerServiceLocator()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 0
cts 11
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 11
nc 2
nop 2
crap 6
1
<?php
2
declare(strict_types=1);
3
4
namespace League\Tactician\Bundle\DependencyInjection\Compiler\BusBuilder;
5
6
use League\Tactician\Bundle\Handler\ContainerBasedHandlerLocator;
7
use League\Tactician\CommandBus;
8
use League\Tactician\Container\ContainerLocator;
9
use League\Tactician\Handler\CommandHandlerMiddleware;
10
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
11
use Symfony\Component\DependencyInjection\ContainerBuilder;
12
use Symfony\Component\DependencyInjection\Definition;
13
use Symfony\Component\DependencyInjection\Reference;
14
use Symfony\Component\DependencyInjection\ServiceLocator;
15
16
final class BusBuilder
17
{
18
    /**
19
     * @var string
20
     */
21
    private $busId;
22
23
    /**
24
     * @var string[]
25
     */
26
    private $middlewareIds = [];
27
28
    /**
29
     * @var string
30
     */
31
    private $methodInflectorId;
32
33 105
    public function __construct(string $busId, string $methodInflector, array $middlewareIds)
34
    {
35 105
        $this->busId = $busId;
36 105
        $this->methodInflectorId = $methodInflector;
37 105
        $this->middlewareIds = $middlewareIds;
38 105
    }
39
40 102
    public function id(): string
41
    {
42 102
        return $this->busId;
43
    }
44
45 75
    public function serviceId(): string
46
    {
47 75
        return "tactician.commandbus.$this->busId";
48
    }
49
50 75
    public function locatorServiceId()
51
    {
52 75
        return "tactician.commandbus.{$this->busId}.handler.locator";
53
    }
54
55 75
    public function commandHandlerMiddlewareId(): string
56
    {
57 75
        return "tactician.commandbus.{$this->busId}.middleware.command_handler";
58
    }
59
60 69
    public function registerInContainer(ContainerBuilder $container, array $commandsToAccept)
61
    {
62 69
        $this->registerLocatorService($container, $commandsToAccept);
63
64 69
        $container->setDefinition(
65 69
            $this->commandHandlerMiddlewareId(),
66 69
            new Definition(
67 69
                CommandHandlerMiddleware::class,
68
                [
69 69
                    new Reference('tactician.handler.command_name_extractor.class_name'),
70 69
                    new Reference($this->locatorServiceId()),
71 69
                    new Reference($this->methodInflectorId),
72
                ]
73
            )
74
        );
75
76 69
        $container->setDefinition(
77 69
            $this->serviceId(),
78 69
            new Definition(
79 69
                CommandBus::class,
80
                [
81 69
                    array_map(
82
                        function (string $id) { return new Reference($id); },
83 69
                        $this->middlewareIds
84
                    )
85
                ]
86
            )
87
        );
88 69
    }
89
90 69
    private function registerLocatorService(ContainerBuilder $container, $commandsToAccept)
91
    {
92
        // Leverage symfony/dependency-injection:^3.3 service locators
93 69
        if (class_exists(ServiceLocator::class)) {
94
            $definition = new Definition(
95
                ContainerLocator::class,
96
                [new Reference($this->registerHandlerServiceLocator($container, $commandsToAccept)), $commandsToAccept]
97
            );
98
        } else {
99 69
            $definition = new Definition(
100 69
                ContainerBasedHandlerLocator::class,
101 69
                [new Reference('service_container'), $commandsToAccept]
102
            );
103
        }
104
105 69
        $container->setDefinition($this->locatorServiceId(), $definition);
106 69
    }
107
108
    private function registerHandlerServiceLocator(ContainerBuilder $container, array $commandsToAccept): string
109
    {
110
        $handlers = [];
111
        foreach ($commandsToAccept as $commandName => $handlerId) {
112
            $handlers[$handlerId] = new ServiceClosureArgument(new Reference($handlerId));
113
        }
114
115
        $handlerServiceLocator = (new Definition(ServiceLocator::class, [$handlers]))
116
            ->setPublic(false)
117
            ->addTag('container.service_locator');
118
119
        $container->setDefinition(
120
            $handlerId = "tactician.commandbus.{$this->busId}.handler.service_locator",
121
            $handlerServiceLocator
122
        );
123
124
        return $handlerId;
125
    }
126
}
127