Passed
Push — master ( 19e66f...6bc648 )
by Rustam
11:52
created

Attributes   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 112
Duplicated Lines 0 %

Test Coverage

Coverage 73.52%

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 34
c 2
b 0
f 1
dl 0
loc 112
ccs 25
cts 34
cp 0.7352
rs 10
wmc 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getClasses() 0 5 1
A loadClasses() 0 9 2
A __construct() 0 9 1
A getClassMetadata() 0 12 2
A handle() 0 8 2
A setDirectories() 0 5 1
A setClasses() 0 5 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace RustamWin\Attributes;
6
7
use JetBrains\PhpStorm\Pure;
8
use Psr\SimpleCache\CacheInterface;
9
use ReflectionClass;
10
use ReflectionException;
11
use RustamWin\Attributes\Dto\ResolvedAttribute;
12
use RustamWin\Attributes\Handler\AttributeHandlerInterface;
13
use RustamWin\Attributes\Reader\AttributeReader;
14
use RustamWin\Attributes\Reader\AttributeReaderInterface;
15
use Spiral\Tokenizer\ClassLocator;
16
use Symfony\Component\Finder\Finder;
17
18
final class Attributes
19
{
20
    private AttributeReaderInterface $attributeReader;
21
    private AttributeHandlerInterface $attributeHandler;
22
    private ?CacheInterface $cache;
23
    /**
24
     * @var array<array-key, string>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, string> at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, string>.
Loading history...
25
     */
26
    private array $directories = [];
27
    /**
28
     * @var array<class-string>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string>.
Loading history...
29
     */
30
    private array $classes = [];
31
32 1
    #[Pure]
33
    public function __construct(
34
        AttributeHandlerInterface $attributeHandler,
35
        ?AttributeReaderInterface $attributeReader = null,
36
        ?CacheInterface $cache = null
37
    ) {
38 1
        $this->attributeHandler = $attributeHandler;
39 1
        $this->attributeReader = $attributeReader ?? new AttributeReader(new Instantiator\Instantiator());
40 1
        $this->cache = $cache;
41
    }
42
43
    /**
44
     * @throws ReflectionException
45
     */
46 1
    public function handle(): void
47
    {
48
        /** @var ReflectionClass[] $classes */
49 1
        $classes = array_unique(array_merge($this->getClasses(), $this->loadClasses()));
50 1
        foreach ($classes as $reflectionClass) {
51 1
            $resolvedAttributes = $this->attributeReader->read($reflectionClass);
52 1
            $this->cache?->set($reflectionClass->getName(), $resolvedAttributes);
53 1
            $this->attributeHandler->handle($reflectionClass, $resolvedAttributes);
54
        }
55
    }
56
57
    /**
58
     * @param class-string $class
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
59
     *
60
     * @throws ReflectionException
61
     * @throws \Psr\SimpleCache\InvalidArgumentException
62
     *
63
     * @return array
64
     */
65
    public function getClassMetadata(string $class): array
66
    {
67
        /** @var ResolvedAttribute[]|null $resolvedAttributes */
68
        $resolvedAttributes = $this->cache?->get($class);
69
        if ($resolvedAttributes !== null) {
70
            return $resolvedAttributes;
71
        }
72
        $ref = new ReflectionClass($class);
73
        $resolvedAttributes = $this->attributeReader->read($ref);
74
        $this->cache?->set($class, $resolvedAttributes);
75
76
        return $resolvedAttributes;
77
    }
78
79
    /**
80
     * @psalm-param array<class-string> $classes
81
     *
82
     * @return $this
83
     */
84 1
    public function setClasses(array $classes): self
85
    {
86 1
        $this->classes = $classes;
87
88 1
        return $this;
89
    }
90
91
    /**
92
     * @psalm-param array<array-key, string> $directories
93
     *
94
     * @return $this
95
     */
96 1
    public function setDirectories(array $directories): self
97
    {
98 1
        $this->directories = $directories;
99
100 1
        return $this;
101
    }
102
103
    /**
104
     * @throws ReflectionException
105
     *
106
     * @psalm-return array<array-key, ReflectionClass<object>>
107
     */
108 1
    private function getClasses(): array
109
    {
110 1
        return array_map(
111 1
            static fn (string $className) => new ReflectionClass($className),
112 1
            $this->classes
113
        );
114
    }
115
116
    /**
117
     * @return ReflectionClass[]
118
     *
119
     * @psalm-return list<ReflectionClass<object>>
120
     */
121 1
    private function loadClasses(): array
122
    {
123 1
        if ($this->directories === []) {
124
            return [];
125
        }
126 1
        $finder = Finder::create()->name('*.php')->in($this->directories);
127 1
        $classes = (new ClassLocator($finder))->getClasses();
128
129 1
        return array_values($classes);
130
    }
131
}
132