Issues (2)

src/AnnotationLoader.php (2 issues)

Labels
Severity
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 Spiral\Tokenizer\ClassesInterface;
11
12
final class AnnotationLoader
13
{
14
    private ClassesInterface $classLocator;
15
    private AnnotationReader $reader;
16
    private array $targets = [];
17
18 5
    public function __construct(ClassesInterface $classLocator, AnnotationReader $reader = null)
19
    {
20 5
        $this->classLocator = $classLocator;
21 5
        $this->reader = $reader ?? new AnnotationReader();
22
    }
23
24 3
    public function withTargets(array $targets): self
25
    {
26 3
        $new = clone $this;
27 3
        $new->targets = $targets;
28
29 3
        return $new;
30
    }
31
32
    /**
33
     * Find all classes with given annotation.
34
     *
35
     * @param string $annotation
36
     *
37
     * @psalm-suppress ArgumentTypeCoercion
38
     * @psalm-return Generator<AnnotatedClass>
39
     *
40
     * @return AnnotatedClass[]|Generator
41
     */
42 1
    public function findClasses(string $annotation, ?ReflectionClass $class = null): Generator
43
    {
44 1
        if ($class !== null) {
45
            $annotations = $this->reader->getClassAnnotations($class);
46
            foreach ($annotations as $classAnnotation) {
47
                if ($classAnnotation instanceof $annotation) {
48
                    yield new AnnotatedClass($class, $classAnnotation);
49
                }
50
            }
51
        }
52 1
        foreach ($this->getTargets() as $target) {
53 1
            $annotations = $this->reader->getClassAnnotations($target);
0 ignored issues
show
$target of type ReflectionClass[] is incompatible with the type ReflectionClass expected by parameter $class of Doctrine\Common\Annotati...::getClassAnnotations(). ( Ignorable by Annotation )

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

53
            $annotations = $this->reader->getClassAnnotations(/** @scrutinizer ignore-type */ $target);
Loading history...
54 1
            foreach ($annotations as $classAnnotation) {
55 1
                if ($classAnnotation instanceof $annotation) {
56 1
                    yield new AnnotatedClass($target, $classAnnotation);
0 ignored issues
show
$target of type ReflectionClass[] 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

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