Completed
Pull Request — master (#29)
by Timothée
05:48
created

CommandHandlerPass::methodInflectorOfBus()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 0
cts 0
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 2
crap 6
1
<?php
2
namespace League\Tactician\Bundle\DependencyInjection\Compiler;
3
4
use League\Tactician\Bundle\Handler\ContainerBasedHandlerLocator;
5
use League\Tactician\Handler\CommandHandlerMiddleware;
6
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
7
use Symfony\Component\DependencyInjection\ContainerBuilder;
8
use Symfony\Component\DependencyInjection\Definition;
9
use Symfony\Component\DependencyInjection\Reference;
10
11
/**
12
 * This compiler pass maps Handler DI tags to specific commands
13
 */
14
class CommandHandlerPass implements CompilerPassInterface
15
{
16
    /**
17
     * You can modify the container here before it is dumped to PHP code.
18
     *
19
     * @param ContainerBuilder $container
20 9
     *
21
     * @throws \Exception
22 9
     * @api
23 3
     */
24
    public function process(ContainerBuilder $container)
25
    {
26 6
        $tacticianConfig = $container->getExtensionConfig('tactician');
27
        $defaultBusId = $tacticianConfig['default_bus'];
28 6
        $busIds = array_keys($tacticianConfig['commandbus']);
29
        $busIdToHandlerMapping = [];
30 6
31 6
        foreach ($container->findTaggedServiceIds('tactician.handler') as $id => $tags) {
32 6
33 3
            foreach ($tags as $attributes) {
34
                if (!isset($attributes['command'])) {
35
                    throw new \Exception('The tactician.handler tag must always have a command attribute');
36 3
                }
37 3
38 3
                if (array_key_exists('bus', $attributes)) {
39
                    $this->abortIfInvalidBusId($attributes['bus'], $busIds);
40 3
                }
41 3
42
                $busIdsDefined = array_key_exists('bus', $attributes) ? [$attributes['bus']] : $busIds;
43
                foreach ($busIdsDefined as $busId) {
44
                    $busIdToHandlerMapping[$busId][$attributes['command']] = $id;
45
                }
46
            }
47
        }
48
49
        foreach ($busIdToHandlerMapping as $busId => $handlerMapping) {
50
            $locatorServiceId = 'tactician.commandbus.'.$busId.'.handler.locator';
51
            $container->setDefinition(
52
                $locatorServiceId,
53
                $this->buildLocatorDefinition($handlerMapping)
54
            );
55
56
            $container->setDefinition(
57
                'tactician.commandbus.'.$busId.'.middleware.command_handler',
58
                $this->buildCommandHandlerDefinition($busId, $locatorServiceId, $tacticianConfig)
59
            );
60
        }
61
62
        $container->setAlias(
63
            'tactician.handler.locator.symfony',
64
            'tactician.commandbus.'.$defaultBusId.'.handler.locator'
65
        );
66
67
        $container->setAlias(
68
            'tactician.middleware.command_handler',
69
            'tactician.commandbus.'.$defaultBusId.'.middleware.command_handler'
70
        );
71
    }
72
73
    /**
74
     * @param string $id
75
     * @param array $busIds
76
     * @throws Exception
77
     */
78
    protected function abortIfInvalidBusId($id, array $busIds)
79
    {
80
        if (!in_array($id, $busIds)) {
81
            throw new \Exception('Invalid bus id "'.$id.'". Valid buses are: '.implode(', ', $busIds));
82
        }
83
    }
84
85
    /**
86
     * @param array $handlerMapping
87
     * @return Definition
88
     */
89
    protected function buildLocatorDefinition(array $handlerMapping)
90
    {
91
        return new Definition(
92
            ContainerBasedHandlerLocator::class,
93
            [
94
                new Reference('service_container'),
95
                $handlerMapping,
96
            ]
97
        );
98
    }
99
100
    /**
101
     * @param string $busId
102
     * @param string $locatorServiceId
103
     * @param array $config
104
     * @return Definition
105
     */
106
    protected function buildCommandHandlerDefinition($busId, $locatorServiceId, array $config)
107
    {
108
        return new Definition(
109
            CommandHandlerMiddleware::class,
110
            [
111
                new Reference('tactician.handler.command_name_extractor.class_name'),
112
                new Reference($locatorServiceId),
113
                new Reference($this->methodInflectorOfBus($busId, $config))
114
            ]
115
        );
116
    }
117
118
    private function methodInflectorOfBus($busId, array $config)
119
    {
120
        if (array_key_exists('method_inflector', $config['commandbus'][$busId])) {
121
            return $config['commandbus'][$busId]['method_inflector'];
122
        }
123
124
        return $config['method_inflector'];
125
    }
126
}
127