Completed
Push — master ( 7e6b92...936a45 )
by Anton
08:09
created

AnnotationLocator::findMethods()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 5
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 7
rs 10
1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
declare(strict_types=1);
9
10
namespace Spiral\Annotations;
11
12
use Doctrine\Common\Annotations\AnnotationReader;
13
use Spiral\Core\Container\SingletonInterface;
14
use Spiral\Tokenizer\ClassesInterface;
15
16
/**
17
 * Locate all available annotations for methods, classes and properties across all the codebase.
18
 */
19
final class AnnotationLocator implements SingletonInterface
20
{
21
    /** @var ClassesInterface */
22
    private $classLocator;
23
24
    /** @var AnnotationReader */
25
    private $reader;
26
27
    /** @var array */
28
    private $targets = [];
29
30
    /**
31
     * AnnotationLocator constructor.
32
     *
33
     * @param ClassesInterface      $classLocator
34
     * @param AnnotationReader|null $reader
35
     *
36
     * @throws \Doctrine\Common\Annotations\AnnotationException
37
     */
38
    public function __construct(ClassesInterface $classLocator, AnnotationReader $reader = null)
39
    {
40
        $this->classLocator = $classLocator;
41
        $this->reader = $reader ?? new AnnotationReader();
42
    }
43
44
    /**
45
     * Limit locator to only specific class types.
46
     *
47
     * @param array $targets
48
     * @return AnnotationLocator
49
     */
50
    public function withTargets(array $targets): self
51
    {
52
        $locator = clone $this;
53
        $locator->targets = $targets;
54
55
        return $locator;
56
    }
57
58
    /**
59
     * Find all classes with given annotation.
60
     *
61
     * @param string $annotation
62
     * @return iterable|AnnotatedClass[]
63
     */
64
    public function findClasses(string $annotation): iterable
65
    {
66
        foreach ($this->getTargets() as $target) {
67
            $found = $this->reader->getClassAnnotation($target, $annotation);
68
            if ($found !== null) {
69
                yield new AnnotatedClass($target, $found);
0 ignored issues
show
Bug Best Practice introduced by
The expression yield new Spiral\Annotat...dClass($target, $found) returns the type Generator which is incompatible with the documented return type Spiral\Annotations\AnnotatedClass[]|iterable.
Loading history...
70
            }
71
        }
72
    }
73
74
    /**
75
     * Find all methods with given annotation.
76
     *
77
     * @param array $annotation
78
     * @return iterable|AnnotatedMethod[]
79
     */
80
    public function findMethods(array $annotation): iterable
81
    {
82
        foreach ($this->getTargets() as $target) {
83
            foreach ($target->getMethods() as $method) {
84
                $found = $this->reader->getMethodAnnotation($method, $annotation);
85
                if ($found !== null) {
86
                    yield new AnnotatedMethod($method, $found);
0 ignored issues
show
Bug Best Practice introduced by
The expression yield new Spiral\Annotat...Method($method, $found) returns the type Generator which is incompatible with the documented return type Spiral\Annotations\AnnotatedMethod[]|iterable.
Loading history...
87
                }
88
            }
89
        }
90
    }
91
92
    /**
93
     * Find all properties with given annotation.
94
     *
95
     * @param string $annotation
96
     * @return iterable|AnnotatedProperty[]
97
     */
98
    public function findProperties(string $annotation): iterable
99
    {
100
        foreach ($this->getTargets() as $target) {
101
            foreach ($target->getProperties() as $property) {
102
                $found = $this->reader->getPropertyAnnotation($property, $annotation);
103
                if ($found !== null) {
104
                    yield new AnnotatedProperty($property, $found);
0 ignored issues
show
Bug Best Practice introduced by
The expression yield new Spiral\Annotat...erty($property, $found) returns the type Generator which is incompatible with the documented return type Spiral\Annotations\AnnotatedProperty[]|iterable.
Loading history...
105
                }
106
            }
107
        }
108
109
    }
110
111
    /**
112
     * @return iterable|\ReflectionClass[]
113
     */
114
    private function getTargets(): iterable
115
    {
116
        if ($this->targets === []) {
117
            yield from $this->classLocator->getClasses();
0 ignored issues
show
Bug Best Practice introduced by
The expression YieldFromNode returns the type Generator which is incompatible with the documented return type ReflectionClass[]|iterable.
Loading history...
118
            return;
119
        }
120
121
        foreach ($this->targets as $target) {
122
            yield from $this->classLocator->getClasses($target);
123
        }
124
    }
125
}