Passed
Pull Request — 2.x (#264)
by Akihito
03:45 queued 02:11
created

ParameterAttributeReader::readAnnotation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 8
rs 10
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 ParameterAttributeReader
26
{
27
    /** @var ?Reader */
28
    private $reader;
29
30
    /**
31
     * @Inject(optional=true)
32
     * @Named("annotation")
33
     */
34
    #[Inject(optional: true)]
35
    #[Named('annotation')]
36
    public function setReader(Reader $reader): void
37
    {
38
        $this->reader = $reader;
39
    }
40
41
    /**
42
     * Read the parameter attribute
43
     *
44
     * Attempts to read the attribute of the parameter,
45
     * and if not successful, attempts to read the annotation of the property of the same name
46
     *
47
     * @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...
48
     *
49
     * @return T|null
50
     */
51
    public function get(ReflectionParameter $param, string $class): ?object
52
    {
53
        if (PHP_VERSION_ID < 80000) {
54
            return $this->readAnnotation($param, $class);
55
        }
56
57
        /** @var array<ReflectionAttribute> $attributes */
58
        $attributes = $param->getAttributes($class);
59
        if ($attributes === []) {
60
            return $this->readAnnotation($param, $class);
61
        }
62
63
        $attribute = $attributes[0];
64
        /** @var T $instance */
65
        $instance = $attribute->newInstance();
66
67
        return $instance;
68
    }
69
70
    /**
71
     * @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...
72
     *
73
     * @return T|null
74
     */
75
    private function readAnnotation(ReflectionParameter $param, string $class)
76
    {
77
        $reader = $this->reader ?? new AnnotationReader();
78
        $ref = $param->getDeclaringClass();
79
        assert($ref instanceof ReflectionClass);
80
        $prop = new ReflectionProperty($ref->getName(), $param->getName());
81
82
        return $reader->getPropertyAnnotation($prop, $class);
83
    }
84
}
85