Passed
Push — more_multibindings ( 865fcd...0ed697 )
by Akihito
01:40
created

ConstractorParamDualReader::readAnnotation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ray\Di;
6
7
use Doctrine\Common\Annotations\AnnotationReader;
8
use Doctrine\Common\Annotations\Reader;
9
use Ray\Di\Di\Inject;
10
use Ray\Di\Di\Named;
11
use ReflectionAttribute;
12
use ReflectionClass;
13
use ReflectionParameter;
14
use ReflectionProperty;
15
16
use function assert;
17
18
use const PHP_VERSION_ID;
19
20
/**
21
 * Attribute/annotation reader for constructor parameters
22
 *
23
 * @template T of object
24
 */
25
class ConstractorParamDualReader
26
{
27
    /** @var ?Reader */
28
    private $reader;
29
30
    /**
31
     * Set optional cached reader
32
     *
33
     * @Inject(optional=true)
34
     * @Named("annotation")
35
     */
36
    #[Inject(optional: true)]
37
    #[Named('annotation')]
38
    public function setReader(Reader $reader): void
39
    {
40
        $this->reader = $reader;
41
    }
42
43
    /**
44
     * Read the parameter attribute
45
     *
46
     * Attempts to read the attribute of the parameter,
47
     * and if not successful, attempts to read the annotation of the property of the same name
48
     *
49
     * @param class-string<T> $class
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>.
Loading history...
50
     *
51
     * @return T|null
52
     */
53
    public function getParametrAnnotation(ReflectionParameter $param, string $class): ?object
54
    {
55
        if (PHP_VERSION_ID < 80000) {
56
            return $this->readAnnotation($param, $class);
57
        }
58
59
        /** @var array<ReflectionAttribute> $attributes */
60
        $attributes = $param->getAttributes($class);
61
        if ($attributes === []) {
62
            return $this->readAnnotation($param, $class);
63
        }
64
65
        $attribute = $attributes[0];
66
        /** @var T $instance */
67
        $instance = $attribute->newInstance();
68
69
        return $instance;
70
    }
71
72
    /**
73
     * @param class-string<T> $class
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>.
Loading history...
74
     *
75
     * @return T|null
76
     */
77
    private function readAnnotation(ReflectionParameter $param, string $class)
78
    {
79
        $reader = $this->reader ?? new AnnotationReader();
80
        $ref = $param->getDeclaringClass();
81
        assert($ref instanceof ReflectionClass);
82
        $prop = new ReflectionProperty($ref->getName(), $param->getName());
83
84
        return $reader->getPropertyAnnotation($prop, $class);
85
    }
86
}
87