Passed
Push — master ( f68793...1e735e )
by Olivier
10:02
created

MessageBusPass::process()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 2
b 0
f 0
nc 1
nop 1
dl 0
loc 4
rs 10
1
<?php
2
3
/*
4
 * This file is part of the ICanBoogie package.
5
 *
6
 * (c) Olivier Laviale <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace ICanBoogie\MessageBus\Symfony;
13
14
use InvalidArgumentException;
15
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
16
use Symfony\Component\DependencyInjection\ContainerBuilder;
17
18
/**
19
 * A compiler pass that inspect message bus handlers and voters to create mapping parameters.
20
 *
21
 * The following parameters are created (names are customizable):
22
 *
23
 * - `message_bus.message_to_handler`: array<class-string, string> where _key_ is the class of a message and _value_
24
 *   the service identifier of a message handler.
25
 * - `message_bus.permissions_by_message`: array<class-string, string[]> where _key_ is the class of a message and
26
 *   _value_ an array of permissions.
27
 * - `message_bus.permission_to_voter`: array<string, string> where _key_ is a permission and _value_ the service
28
 *   identifier of a voter.
29
 */
30
final class MessageBusPass implements CompilerPassInterface
31
{
32
    public const DEFAULT_PARAMETER_FOR_MESSAGE_TO_HANDLER = 'message_bus.message_to_handler';
33
    public const DEFAULT_TAG_FOR_HANDLER = 'message_bus.handler';
34
    public const DEFAULT_ATTRIBUTE_FOR_MESSAGE = 'message';
35
    public const DEFAULT_PARAMETER_FOR_PERMISSIONS_BY_MESSAGE = 'message_bus.permissions_by_message';
36
    public const DEFAULT_TAG_FOR_PERMISSION = 'message_bus.permission';
37
    public const DEFAULT_ATTRIBUTE_FOR_PERMISSION = 'permission';
38
    public const DEFAULT_PARAMETER_FOR_PERMISSION_TO_VOTER = 'message_bus.permission_to_voter';
39
    public const DEFAULT_TAG_FOR_VOTER = 'message_bus.voter';
40
41
    public function __construct(
42
        private string $parameterForMessageToHandler = self::DEFAULT_PARAMETER_FOR_MESSAGE_TO_HANDLER,
43
        private string $tagForHandler = self::DEFAULT_TAG_FOR_HANDLER,
44
        private string $attributeForMessage = self::DEFAULT_ATTRIBUTE_FOR_MESSAGE,
45
        private string $parameterForPermissionsByMessage = self::DEFAULT_PARAMETER_FOR_PERMISSIONS_BY_MESSAGE,
46
        private string $tagForPermission = self::DEFAULT_TAG_FOR_PERMISSION,
47
        private string $attributeForPermission = self::DEFAULT_ATTRIBUTE_FOR_PERMISSION,
48
        private string $parameterForPermissionToVoter = self::DEFAULT_PARAMETER_FOR_PERMISSION_TO_VOTER,
49
        private string $tagForVoter = self::DEFAULT_TAG_FOR_VOTER,
50
    ) {
51
    }
52
53
    public function process(ContainerBuilder $container): void
54
    {
55
        $this->processHandlersAndPermissions($container);
56
        $this->processVoters($container);
57
    }
58
59
    /**
60
     * Builds a map of message class to handler service identifier,
61
     * and another of permissions by message class.
62
     */
63
    private function processHandlersAndPermissions(ContainerBuilder $container): void
64
    {
65
        $messageToHandler = [];
66
        $permissionsByMessage = [];
67
68
        foreach ($container->findTaggedServiceIds($this->tagForHandler) as $id => $hTags) {
69
            $message = $hTags[0][$this->attributeForMessage]
70
                ?? throw new InvalidArgumentException(
71
                    "Missing attribute `$this->attributeForMessage` for service `$id`"
72
                );
73
74
            $messageToHandler[$message] = $id;
75
76
            foreach ($container->findDefinition($id)->getTag($this->tagForPermission) as $pTags) {
77
                $permissionsByMessage[$message][] = $pTags[$this->attributeForPermission];
78
            }
79
        }
80
81
        $container->setParameter($this->parameterForMessageToHandler, $messageToHandler);
82
        $container->setParameter($this->parameterForPermissionsByMessage, $permissionsByMessage);
83
    }
84
85
    /**
86
     * Builds a map of permission to voter service identifier.
87
     */
88
    private function processVoters(ContainerBuilder $container): void
89
    {
90
        $permissionToVoter = [];
91
92
        foreach ($container->findTaggedServiceIds($this->tagForVoter) as $id => $tags) {
93
            $permissionToVoter[$tags[0][$this->attributeForPermission]] = $id;
94
        }
95
96
        $container->setParameter($this->parameterForPermissionToVoter, $permissionToVoter);
97
    }
98
}
99