Completed
Pull Request — master (#102)
by Eric
05:51
created

BusBuilder   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 111
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 94.12%

Importance

Changes 0
Metric Value
wmc 10
lcom 1
cbo 4
dl 0
loc 111
ccs 48
cts 51
cp 0.9412
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A id() 0 4 1
A serviceId() 0 4 1
A locatorServiceId() 0 4 1
A commandHandlerMiddlewareId() 0 4 1
A registerHandlerServiceLocator() 0 18 2
A registerLocatorService() 0 17 2
B registerInContainer() 0 29 1
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 111
    public function __construct(string $busId, string $methodInflector, array $middlewareIds)
34
    {
35 111
        $this->busId = $busId;
36 111
        $this->methodInflectorId = $methodInflector;
37 111
        $this->middlewareIds = $middlewareIds;
38 111
    }
39
40 108
    public function id(): string
41
    {
42 108
        return $this->busId;
43
    }
44
45 81
    public function serviceId(): string
46
    {
47 81
        return "tactician.commandbus.$this->busId";
48
    }
49
50 81
    public function locatorServiceId()
51
    {
52 81
        return "tactician.commandbus.{$this->busId}.handler.locator";
53
    }
54
55 81
    public function commandHandlerMiddlewareId(): string
56
    {
57 81
        return "tactician.commandbus.{$this->busId}.middleware.command_handler";
58
    }
59
60 75
    public function registerInContainer(ContainerBuilder $container, array $commandsToAccept)
61
    {
62 75
        $this->registerLocatorService($container, $commandsToAccept);
63
64 75
        $container->setDefinition(
65 75
            $this->commandHandlerMiddlewareId(),
66 75
            new Definition(
67 75
                CommandHandlerMiddleware::class,
68
                [
69 75
                    new Reference('tactician.handler.command_name_extractor.class_name'),
70 75
                    new Reference($this->locatorServiceId()),
71 75
                    new Reference($this->methodInflectorId),
72
                ]
73
            )
74
        );
75
76 75
        $container->setDefinition(
77 75
            $this->serviceId(),
78 75
            new Definition(
79 75
                CommandBus::class,
80
                [
81 75
                    array_map(
82
                        function (string $id) { return new Reference($id); },
83 75
                        $this->middlewareIds
84
                    )
85
                ]
86
            )
87 75
        )->setPublic(true);
88 75
    }
89
90 75
    private function registerLocatorService(ContainerBuilder $container, $commandsToAccept)
91
    {
92
        // Leverage symfony/dependency-injection:^3.3 service locators
93 75
        if (class_exists(ServiceLocator::class)) {
94 75
            $definition = new Definition(
95 75
                ContainerLocator::class,
96 75
                [new Reference($this->registerHandlerServiceLocator($container, $commandsToAccept)), $commandsToAccept]
97
            );
98
        } else {
99
            $definition = new Definition(
100
                ContainerBasedHandlerLocator::class,
101
                [new Reference('service_container'), $commandsToAccept]
102
            );
103
        }
104
105 75
        $container->setDefinition($this->locatorServiceId(), $definition);
106 75
    }
107
108 75
    private function registerHandlerServiceLocator(ContainerBuilder $container, array $commandsToAccept): string
109
    {
110 75
        $handlers = [];
111 75
        foreach ($commandsToAccept as $commandName => $handlerId) {
112 36
            $handlers[$handlerId] = new ServiceClosureArgument(new Reference($handlerId));
113
        }
114
115 75
        $handlerServiceLocator = (new Definition(ServiceLocator::class, [$handlers]))
116 75
            ->setPublic(false)
117 75
            ->addTag('container.service_locator');
118
119 75
        $container->setDefinition(
120 75
            $handlerId = "tactician.commandbus.{$this->busId}.handler.service_locator",
121 75
            $handlerServiceLocator
122
        );
123
124 75
        return $handlerId;
125
    }
126
}
127