MessageBusPassWithAttributes   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 73
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 24
dl 0
loc 73
rs 10
c 1
b 0
f 0
wmc 7

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A process() 0 40 5
A resolveMessage() 0 10 1
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 ICanBoogie\MessageBus\Attribute;
15
use LogicException;
16
use olvlvl\ComposerAttributeCollector\Attributes;
17
use ReflectionException;
18
use ReflectionMethod;
19
use ReflectionNamedType;
20
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
21
use Symfony\Component\DependencyInjection\ContainerBuilder;
22
use Symfony\Component\DependencyInjection\Definition;
23
24
use function assert;
25
26
/**
27
 * Creates handler and voter services according to their attributes.
28
 *
29
 * This compiler pass is meant to run before {@link MessageBusPass}.
30
 */
31
final class MessageBusPassWithAttributes implements CompilerPassInterface
32
{
33
    public function __construct(
34
        private string $tagForHandler = MessageBusPass::DEFAULT_TAG_FOR_HANDLER,
35
        private string $attributeForMessage = MessageBusPass::DEFAULT_ATTRIBUTE_FOR_MESSAGE,
36
        private string $tagForPermission = MessageBusPass::DEFAULT_TAG_FOR_PERMISSION,
37
        private string $attributeForPermission = MessageBusPass::DEFAULT_ATTRIBUTE_FOR_PERMISSION,
38
        private string $tagForVoter = MessageBusPass::DEFAULT_TAG_FOR_VOTER,
39
    ) {
40
    }
41
42
    /**
43
     * @throws ReflectionException
44
     */
45
    public function process(ContainerBuilder $container): void
46
    {
47
        /** @var array<class-string, Definition> $definitions */
48
        $definitions = [];
49
50
        /**
51
         * @var array<class-string, string[]> $permissions
52
         *     Where _key_ is a command and _value_ its associated permissions.
53
         */
54
        $permissions = [];
55
56
        foreach (Attributes::findTargetClasses(Attribute\Permission::class) as $targetClass) {
57
            $permissions[$targetClass->name][] = $targetClass->attribute->permission;
58
        }
59
60
        foreach (Attributes::findTargetClasses(Attribute\Handler::class) as $targetClass) {
61
            $handler = $targetClass->name;
62
            $message = self::resolveMessage($handler);
63
64
            $definition = new Definition($handler);
65
            $definition->addTag($this->tagForHandler, [ $this->attributeForMessage => $message ]);
66
67
            foreach ($permissions[$message] ?? [] as $permission) {
68
                $definition->addTag($this->tagForPermission, [ $this->attributeForPermission => $permission ]);
69
            }
70
71
            $definitions[$handler] = $definition;
72
        }
73
74
        foreach (Attributes::findTargetClasses(Attribute\Vote::class) as $targetClass) {
75
            $voter = $targetClass->name;
76
            $permission = $targetClass->attribute->permission;
77
78
            $definition = new Definition($voter);
79
            $definition->addTag($this->tagForVoter, [ $this->attributeForPermission => $permission ]);
80
81
            $definitions[$voter] = $definition;
82
        }
83
84
        $container->addDefinitions($definitions);
85
    }
86
87
    /**
88
     * @param class-string $handler
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
89
     *
90
     * @return class-string
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
91
     *
92
     * @throws ReflectionException
93
     */
94
    private static function resolveMessage(string $handler): string
95
    {
96
        $type = (new ReflectionMethod($handler, '__invoke'))
97
            ->getParameters()[0]
98
            ->getType() ?? throw new LogicException("Expected a type for the first argument");
99
100
        assert($type instanceof ReflectionNamedType);
101
102
        // @phpstan-ignore-next-line
103
        return $type->getName();
104
    }
105
}
106