Passed
Push — main ( 12f243...150a56 )
by Breno
01:53
created

ExtractorUsingAttribute::extractClassMethods()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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