MessageBusPass::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
c 1
b 0
f 0
nc 1
nop 8
dl 0
loc 10
rs 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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 LogicException;
16
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
17
use Symfony\Component\DependencyInjection\ContainerBuilder;
18
19
/**
20
 * A compiler pass that inspect message bus handlers and voters to create mapping parameters.
21
 *
22
 * The following parameters are created (names are customizable):
23
 *
24
 * - `message_bus.message_to_handler`: array<class-string, string> where _key_ is the class of a message and _value_
25
 *   the service identifier of a message handler.
26
 * - `message_bus.permissions_by_message`: array<class-string, string[]> where _key_ is the class of a message and
27
 *   _value_ an array of permissions.
28
 * - `message_bus.permission_to_voter`: array<string, string> where _key_ is a permission and _value_ the service
29
 *   identifier of a voter.
30
 */
31
final class MessageBusPass implements CompilerPassInterface
32
{
33
    public const DEFAULT_PARAMETER_FOR_MESSAGE_TO_HANDLER = 'message_bus.message_to_handler';
34
    public const DEFAULT_TAG_FOR_HANDLER = 'message_bus.handler';
35
    public const DEFAULT_ATTRIBUTE_FOR_MESSAGE = 'message';
36
    public const DEFAULT_PARAMETER_FOR_PERMISSIONS_BY_MESSAGE = 'message_bus.permissions_by_message';
37
    public const DEFAULT_TAG_FOR_PERMISSION = 'message_bus.permission';
38
    public const DEFAULT_ATTRIBUTE_FOR_PERMISSION = 'permission';
39
    public const DEFAULT_PARAMETER_FOR_PERMISSION_TO_VOTER = 'message_bus.permission_to_voter';
40
    public const DEFAULT_TAG_FOR_VOTER = 'message_bus.voter';
41
42
    public function __construct(
43
        private string $parameterForMessageToHandler = self::DEFAULT_PARAMETER_FOR_MESSAGE_TO_HANDLER,
44
        private string $tagForHandler = self::DEFAULT_TAG_FOR_HANDLER,
45
        private string $attributeForMessage = self::DEFAULT_ATTRIBUTE_FOR_MESSAGE,
46
        private string $parameterForPermissionsByMessage = self::DEFAULT_PARAMETER_FOR_PERMISSIONS_BY_MESSAGE,
47
        private string $tagForPermission = self::DEFAULT_TAG_FOR_PERMISSION,
48
        private string $attributeForPermission = self::DEFAULT_ATTRIBUTE_FOR_PERMISSION,
49
        private string $parameterForPermissionToVoter = self::DEFAULT_PARAMETER_FOR_PERMISSION_TO_VOTER,
50
        private string $tagForVoter = self::DEFAULT_TAG_FOR_VOTER,
51
    ) {
52
    }
53
54
    public function process(ContainerBuilder $container): void
55
    {
56
        $this->processHandlersAndPermissions($container);
57
        $this->processVoters($container);
58
    }
59
60
    /**
61
     * Builds a map of message class to handler service identifier,
62
     * and another of permissions by message class.
63
     */
64
    private function processHandlersAndPermissions(ContainerBuilder $container): void
65
    {
66
        $messageToHandler = [];
67
        $permissionsByMessage = [];
68
69
        foreach ($container->findTaggedServiceIds($this->tagForHandler) as $id => $hTags) {
70
            $message = $hTags[0][$this->attributeForMessage]
71
                ?? throw new InvalidArgumentException(
72
                    "Missing attribute '$this->attributeForMessage' for service '$id'"
73
                );
74
75
            $duplicate = $messageToHandler[$message] ?? null;
76
77
            if ($duplicate) {
78
                throw new LogicException("Unable to register handler '$id'"
79
                    . ", the handler '$duplicate' is already registered for message class '$message'");
80
            }
81
82
            $messageToHandler[$message] = $id;
83
84
            foreach ($container->findDefinition($id)->getTag($this->tagForPermission) as $pTags) {
85
                $permissionsByMessage[$message][] = $pTags[$this->attributeForPermission];
86
            }
87
        }
88
89
        $container->setParameter($this->parameterForMessageToHandler, $messageToHandler);
90
        $container->setParameter($this->parameterForPermissionsByMessage, $permissionsByMessage);
91
    }
92
93
    /**
94
     * Builds a map of permission to voter service identifier.
95
     */
96
    private function processVoters(ContainerBuilder $container): void
97
    {
98
        $permissionToVoter = [];
99
100
        foreach ($container->findTaggedServiceIds($this->tagForVoter) as $id => $tags) {
101
            $permissionToVoter[$tags[0][$this->attributeForPermission]] = $id;
102
        }
103
104
        $container->setParameter($this->parameterForPermissionToVoter, $permissionToVoter);
105
    }
106
}
107