Passed
Push — master ( 205488...e43c9f )
by Rustam
01:47
created

AttributeReader::readConstantAttributes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace RustamWin\Attributes\Reader;
6
7
use JetBrains\PhpStorm\Pure;
8
use ReflectionAttribute;
9
use ReflectionClass;
10
use ReflectionClassConstant;
11
use ReflectionMethod;
12
use ReflectionParameter;
13
use ReflectionProperty;
14
use RustamWin\Attributes\Dto\ResolvedAttribute;
15
use RustamWin\Attributes\Instantiator\Instantiator;
16
use RustamWin\Attributes\Instantiator\InstantiatorInterface;
17
18
final class AttributeReader implements AttributeReaderInterface
19
{
20
    private InstantiatorInterface $instantiator;
21
22 1
    #[Pure]
23
    public function __construct(?InstantiatorInterface $instantiator = null)
24
    {
25 1
        $this->instantiator = $instantiator ?? new Instantiator();
26 1
    }
27
28
    /**
29
     * @inheritDoc
30
     */
31 1
    public function read(ReflectionClass $ref): array
32
    {
33 1
        return array_merge(
34 1
            $this->readClassAttributes($ref),
35 1
            $this->readConstantAttributes($ref),
36 1
            $this->readPropertyAttributes($ref),
37 1
            $this->readMethodAttributes($ref)
38
        );
39
    }
40
41
    /**
42
     * @return ResolvedAttribute[]
43
     *
44
     * @psalm-return array<ResolvedAttribute>
45
     */
46 1
    private function readClassAttributes(ReflectionClass $class): array
47
    {
48 1
        return $this->readAttributes($class);
49
    }
50
51 1
    private function readConstantAttributes(ReflectionClass $class): array
52
    {
53 1
        $constants = $class->getReflectionConstants();
54 1
        return $this->mapAttributes($constants);
55
    }
56
57 1
    private function readPropertyAttributes(ReflectionClass $class): array
58
    {
59 1
        $properties = $class->getProperties();
60 1
        return $this->mapAttributes($properties);
61
    }
62
63
    /**
64
     * @psalm-return array<array-key, ResolvedAttribute>
65
     */
66 1
    private function readMethodAttributes(ReflectionClass $class): array
67
    {
68 1
        $methods = $class->getMethods();
69 1
        $mappedMethods = $this->mapAttributes($methods);
70
71 1
        $mappedParameters = array_map(
72 1
            fn (ReflectionMethod $method) => $this->readParameterAttributes($method),
73
            $methods
74
        );
75
76 1
        return array_merge($mappedMethods, ...$mappedParameters);
77
    }
78
79 1
    private function readParameterAttributes(ReflectionMethod $method): array
80
    {
81 1
        $parameters = $method->getParameters();
82 1
        return $this->mapAttributes($parameters);
83
    }
84
85
    /**
86
     * @return ResolvedAttribute[]
87
     */
88 1
    private function readAttributes(
89
        ReflectionClass|ReflectionClassConstant|ReflectionProperty|ReflectionMethod|ReflectionParameter $ref
90
    ): array {
91 1
        return array_map(
92 1
            fn (ReflectionAttribute $attribute) => new ResolvedAttribute(
93 1
                attribute: $this->instantiator->instantiate($attribute),
94
                reflectionTarget: $ref
95 1
            ),
96 1
            $this->filterAttributes($ref->getAttributes())
97
        );
98
    }
99
100
    /**
101
     * @param array $attributes
102
     *
103
     * @return array
104
     */
105 1
    private function filterAttributes(array $attributes): array
106
    {
107 1
        return array_filter(
108 1
            $attributes,
109 1
            static fn (ReflectionAttribute $attribute) => class_exists($attribute->getName())
110 1
        );
111
    }
112
113
    /**
114
     * @psalm-param list<ReflectionClass|ReflectionClassConstant|ReflectionProperty|ReflectionMethod|ReflectionParameter> $targets
115
     *
116
     * @return ResolvedAttribute[]
117
     *
118
     * @psalm-return array<ResolvedAttribute>
119
     */
120 1
    private function mapAttributes(array $targets): array
121
    {
122 1
        $resolvedAttributes = array_map(
123 1
            fn ($targetRef) => $this->readAttributes($targetRef),
124
            $targets
125
        );
126
127 1
        return array_merge(...$resolvedAttributes);
128
    }
129
}
130