Passed
Push — main ( dae7cc...12f243 )
by Breno
01:47
created

AttributesMapper::getHandlers()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 18
rs 9.9332
c 0
b 0
f 0
cc 4
nc 4
nop 1
1
<?php
2
declare(strict_types=1);
3
4
namespace OniBus\Handler\Attributes;
5
6
use OniBus\Handler\ClassMethod\ClassMethod;
7
use ReflectionAttribute;
8
use ReflectionClass;
9
use ReflectionException;
10
use ReflectionMethod;
11
use OniBus\Attributes\Handler;
12
use RuntimeException;
13
14
class AttributesMapper implements AttributesMapperInterface
15
{
16
    /**
17
     * @var string
18
     */
19
    protected $attribute;
20
21
    /**
22
     * @var array
23
     */
24
    protected $handlersFQCN;
25
26
    public function __construct(string $attribute, array $handlersFQCN = [])
27
    {
28
        $this->attribute = $attribute;
29
        $this->handlersFQCN = $handlersFQCN;
30
    }
31
32
    /**
33
     * @inheritDoc
34
     */
35
    public function mapHandlers(): array
36
    {
37
        $mapped = [];
38
        foreach ($this->handlersFQCN as $class) {
39
            $mapped = array_merge($mapped, $this->getHandlers($class));
40
        }
41
42
        return $mapped;
43
    }
44
45
    /**
46
     * @param  string $class
47
     * @return ClassMethod[]
48
     * @throws ReflectionException
49
     */
50
    protected function getHandlers(string $class): array
51
    {
52
        $handlers = [];
53
        if (!class_exists($class)) {
54
            return $handlers;
55
        }
56
57
        $reflectionClass = new ReflectionClass($class);
58
        foreach ($reflectionClass->getMethods() as $method) {
59
            $attribute = $this->extractHandlerAttribute($method);
60
            if (empty($attribute)) {
61
                continue;
62
            }
63
64
            $handlers[] = new ClassMethod($this->extractMessage($method, $attribute), $class, $method->getName());
65
        }
66
67
        return $handlers;
68
    }
69
70
    protected function extractHandlerAttribute(ReflectionMethod $method): ?Handler
71
    {
72
        $attribute = $method->getAttributes($this->attribute, ReflectionAttribute::IS_INSTANCEOF)[0] ?? null;
73
        if ($attribute instanceof ReflectionAttribute) {
74
            $attr =  $attribute->newInstance();
75
            assert($attr instanceof Handler);
76
            return $attr;
77
        }
78
79
        return null;
80
    }
81
82
    protected function extractMessage(ReflectionMethod $method, Handler $attribute): string
83
    {
84
        $hasParameters = (bool) $method->getNumberOfParameters();
85
        if (empty($attribute->getMessage()) && !$hasParameters) {
86
            throw new RuntimeException(
87
                sprintf(
88
                    "Invalid Handler: No 'Message' has been set in %s::%s",
89
                    $method->getDeclaringClass()->getName(),
90
                    $method->getName()
91
                )
92
            );
93
        }
94
95
        return $attribute->getMessage() ?? (string) $method->getParameters()[0]->getType();
96
    }
97
}
98