Passed
Push — master ( b336ac...2b1ebd )
by Rustam
01:58
created

AnnotationLoader::__construct()   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 2
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 Yiistack\Annotated;
6
7
use Doctrine\Common\Annotations\AnnotationReader;
8
use Generator;
9
use ReflectionClass;
10
use ReflectionMethod;
11
use ReflectionProperty;
12
use Spiral\Tokenizer\ClassesInterface;
13
14
final class AnnotationLoader
15
{
16
    private ClassesInterface $classLocator;
17
    private AnnotationReader $reader;
18
    private array $targets = [];
19
20 5
    public function __construct(ClassesInterface $classLocator, AnnotationReader $reader = null)
21
    {
22 5
        $this->classLocator = $classLocator;
23 5
        $this->reader = $reader ?? new AnnotationReader();
24 5
    }
25
26 3
    public function withTargets(array $targets): self
27
    {
28 3
        $new = clone $this;
29 3
        $new->targets = $targets;
30
31 3
        return $new;
32
    }
33
34
    /**
35
     * Find all classes with given annotation.
36
     *
37
     * @param string $annotation
38
     *
39
     * @psalm-suppress ArgumentTypeCoercion
40
     * @psalm-return Generator
41
     *
42
     * @return ReflectionClass[]|Generator
43
     */
44 1
    public function findClasses(string $annotation): Generator
45
    {
46 1
        foreach ($this->getTargets() as $target) {
47 1
            $found = $this->reader->getClassAnnotation($target, $annotation);
0 ignored issues
show
Bug introduced by
$target of type array is incompatible with the type ReflectionClass expected by parameter $class of Doctrine\Common\Annotati...r::getClassAnnotation(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

47
            $found = $this->reader->getClassAnnotation(/** @scrutinizer ignore-type */ $target, $annotation);
Loading history...
48 1
            if ($found !== null) {
49 1
                yield new AnnotatedClass($target, $found);
0 ignored issues
show
Bug introduced by
$target of type array is incompatible with the type ReflectionClass expected by parameter $class of Yiistack\Annotated\AnnotatedClass::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

49
                yield new AnnotatedClass(/** @scrutinizer ignore-type */ $target, $found);
Loading history...
50
            }
51
        }
52 1
    }
53
54
    /**
55
     * Find all methods with given annotation.
56
     *
57
     * @param string $annotation
58
     * @param ReflectionClass|null $class
59
     *
60
     * @psalm-suppress ArgumentTypeCoercion
61
     * @psalm-return Generator
62
     *
63
     * @return ReflectionMethod[]|Generator
64
     */
65 2
    public function findMethods(string $annotation, ?ReflectionClass $class = null): Generator
66
    {
67 2
        if ($class !== null) {
68 1
            foreach ($class->getMethods() as $method) {
69 1
                $found = $this->reader->getMethodAnnotation($method, $annotation);
70 1
                if ($found !== null) {
71 1
                    yield new AnnotatedMethod($method, $found);
72
                }
73
            }
74 1
            return;
75
        }
76 1
        foreach ($this->getTargets() as $target) {
77 1
            foreach ($target->getMethods() as $method) {
78 1
                $found = $this->reader->getMethodAnnotation($method, $annotation);
79 1
                if ($found !== null) {
80 1
                    yield new AnnotatedMethod($method, $found);
81
                }
82
            }
83
        }
84 1
    }
85
86
    /**
87
     * Find all properties with given annotation.
88
     *
89
     * @param string $annotation
90
     * @param ReflectionClass|null $class
91
     *
92
     * @psalm-suppress ArgumentTypeCoercion
93
     * @psalm-return Generator
94
     *
95
     * @return ReflectionProperty[]|Generator
96
     */
97 2
    public function findProperties(string $annotation, ?ReflectionClass $class = null): Generator
98
    {
99 2
        if ($class !== null) {
100 1
            foreach ($class->getProperties() as $property) {
101 1
                $found = $this->reader->getPropertyAnnotation($property, $annotation);
102 1
                if ($found !== null) {
103 1
                    yield new AnnotatedProperty($property, $found);
104
                }
105
            }
106 1
            return;
107
        }
108 1
        foreach ($this->getTargets() as $target) {
109 1
            foreach ($target->getProperties() as $property) {
110 1
                $found = $this->reader->getPropertyAnnotation($property, $annotation);
111 1
                if ($found !== null) {
112 1
                    yield new AnnotatedProperty($property, $found);
113
                }
114
            }
115
        }
116 1
    }
117
118 3
    private function getTargets(): Generator
119
    {
120 3
        if ($this->targets === []) {
121
            yield from $this->classLocator->getClasses();
122
            return;
123
        }
124
125 3
        foreach ($this->targets as $target) {
126 3
            yield from $this->classLocator->getClasses($target);
127
        }
128 3
    }
129
}
130