Passed
Push — more_multibindings ( 09a370...ac9d35 )
by Akihito
01:40
created

ParameterReader   A

Complexity

Total Complexity 5

Size/Duplication

Total Lines 56
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 5
eloc 16
dl 0
loc 56
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A getParametrAnnotation() 0 17 3
A __construct() 0 4 1
A readAnnotation() 0 8 1
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\Named;
10
use ReflectionAttribute;
11
use ReflectionClass;
12
use ReflectionParameter;
13
use ReflectionProperty;
14
15
use function assert;
16
17
use const PHP_VERSION_ID;
18
19
/**
20
 * An attribute/annotation reader for method parameters
21
 *
22
 * @template T of object
23
 */
24
class ParameterReader
25
{
26
    /** @var ?Reader */
27
    private $reader;
28
29
    /**
30
     * @Named("annotation")
31
     */
32
    #[Named('annotation')]
33
    public function __construct(?Reader $reader = null)
34
    {
35
        $this->reader = $reader;
36
    }
37
38
    /**
39
     * Read the parameter attribute or annotation
40
     *
41
     * Attempts to read the attribute of the parameter,
42
     * and if not successful, attempts to read the annotation of the property of the same variable name.
43
     *
44
     * @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...
45
     *
46
     * @return T|null
47
     */
48
    public function getParametrAnnotation(ReflectionParameter $param, string $class): ?object
49
    {
50
        if (PHP_VERSION_ID < 80000) {
51
            return $this->readAnnotation($param, $class);
52
        }
53
54
        /** @var array<ReflectionAttribute> $attributes */
55
        $attributes = $param->getAttributes($class);
56
        if ($attributes === []) {
57
            return $this->readAnnotation($param, $class);
58
        }
59
60
        $attribute = $attributes[0];
61
        /** @var T $instance */
62
        $instance = $attribute->newInstance();
63
64
        return $instance;
65
    }
66
67
    /**
68
     * @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...
69
     *
70
     * @return T|null
71
     */
72
    private function readAnnotation(ReflectionParameter $param, string $class)
73
    {
74
        $reader = $this->reader ?? new AnnotationReader();
75
        $ref = $param->getDeclaringClass();
76
        assert($ref instanceof ReflectionClass);
77
        $prop = new ReflectionProperty($ref->getName(), $param->getName());
78
79
        return $reader->getPropertyAnnotation($prop, $class);
80
    }
81
}
82