Completed
Pull Request — master (#33)
by Timothée
02:14
created

CommandHandlerPass::methodInflectorOfBus()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 2
crap 2
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
     *
21
     * @throws \Exception
22
     * @api
23
     */
24 15
    public function process(ContainerBuilder $container)
25
    {
26 15
        $defaultBusId = $container->getParameter('tactician.commandbus.default');
27 15
        $busIds = $container->getParameter('tactician.commandbus.ids');
28 15
        $busIdToHandlerMapping = [];
29
30 15
        foreach ($container->findTaggedServiceIds('tactician.handler') as $id => $tags) {
31
32 15
            foreach ($tags as $attributes) {
33 15
                if (!isset($attributes['command'])) {
34 3
                    throw new \Exception('The tactician.handler tag must always have a command attribute');
35
                }
36
37 12
                if (array_key_exists('bus', $attributes)) {
38 9
                    $this->abortIfInvalidBusId($attributes['bus'], $busIds);
39 6
                }
40
41 9
                $busIdsDefined = array_key_exists('bus', $attributes) ? [$attributes['bus']] : $busIds;
42 9
                foreach ($busIdsDefined as $busId) {
43 9
                    $busIdToHandlerMapping[$busId][$attributes['command']] = $id;
44 9
                }
45 9
            }
46 9
        }
47
48 9
        foreach ($busIdToHandlerMapping as $busId => $handlerMapping) {
49 9
            $locatorServiceId = 'tactician.commandbus.'.$busId.'.handler.locator';
50 9
            $methodInflectorId = $container->getParameter(sprintf('tactician.method_inflector.%s', $busId));
51 9
            $container->setDefinition(
52 9
                $locatorServiceId,
53 9
                $this->buildLocatorDefinition($handlerMapping)
54 9
            );
55
56 9
            $container->setDefinition(
57 9
                'tactician.commandbus.'.$busId.'.middleware.command_handler',
58 9
                new Definition(
59 9
                    CommandHandlerMiddleware::class,
60
                    [
61 9
                        new Reference('tactician.handler.command_name_extractor.class_name'),
62 9
                        new Reference($locatorServiceId),
63 9
                        new Reference($methodInflectorId)
64 9
                    ]
65 9
                )
66 9
            );
67 9
        }
68
69 9
        $container->setAlias(
70 9
            'tactician.handler.locator.symfony',
71 9
            'tactician.commandbus.'.$defaultBusId.'.handler.locator'
72 9
        );
73
74 9
        $container->setAlias(
75 9
            'tactician.middleware.command_handler',
76 9
            'tactician.commandbus.'.$defaultBusId.'.middleware.command_handler'
77 9
        );
78 9
    }
79
80
    /**
81
     * @param string $id
82
     * @param array $busIds
83
     * @throws Exception
84
     */
85 9
    protected function abortIfInvalidBusId($id, array $busIds)
86
    {
87 9
        if (!in_array($id, $busIds)) {
88 3
            throw new \Exception('Invalid bus id "'.$id.'". Valid buses are: '.implode(', ', $busIds));
89
        }
90 6
    }
91
92
    /**
93
     * @param array $handlerMapping
94
     * @return Definition
95
     */
96 9
    protected function buildLocatorDefinition(array $handlerMapping)
97
    {
98 9
        return new Definition(
99 9
            ContainerBasedHandlerLocator::class,
100
            [
101 9
                new Reference('service_container'),
102 9
                $handlerMapping,
103
            ]
104 9
        );
105
    }
106
}
107