Passed
Push — master ( e43c9f...31f1c1 )
by Rustam
02:14
created

Attributes::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
nc 1
nop 2
dl 0
loc 8
ccs 4
cts 4
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace RustamWin\Attributes;
6
7
use JetBrains\PhpStorm\Pure;
8
use ReflectionClass;
9
use ReflectionException;
10
use RustamWin\Attributes\Presenter\AttributePresenterInterface;
11
use RustamWin\Attributes\Reader\AttributeReader;
12
use RustamWin\Attributes\Reader\AttributeReaderInterface;
13
use Spiral\Tokenizer\ClassLocator;
14
use SplObjectStorage;
15
use Symfony\Component\Finder\Finder;
16
17
final class Attributes
18
{
19
    private AttributeReaderInterface $attributeReader;
20
    private SplObjectStorage $attributes;
21
    private AttributePresenterInterface $attributePresenter;
22
    /**
23
     * @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...
24
     */
25
    private array $directories = [];
26
    /**
27
     * @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...
28
     */
29
    private array $classes = [];
30
31 1
    #[Pure]
32
    public function __construct(
33
        AttributePresenterInterface $attributePresenter,
34
        ?AttributeReaderInterface $attributeReader = null,
35
    ) {
36 1
        $this->attributeReader = $attributeReader ?? new AttributeReader(new Instantiator\Instantiator());
37 1
        $this->attributePresenter = $attributePresenter;
38 1
        $this->attributes = new SplObjectStorage();
39 1
    }
40
41
    /**
42
     * @throws ReflectionException
43
     */
44 1
    public function handle(): void
45
    {
46 1
        $classes = array_unique(array_merge($this->getClasses(), $this->loadClasses()));
47 1
        foreach ($classes as $reflectionClass) {
48 1
            $resolvedAttributes = $this->attributeReader->read($reflectionClass);
49 1
            $this->attributes->attach($reflectionClass);
50 1
            $this->attributePresenter->present($reflectionClass, $resolvedAttributes);
51
        }
52 1
    }
53
54
    /**
55
     * @psalm-param array<class-string> $classes
56
     *
57
     * @return $this
58
     */
59 1
    public function setClasses(array $classes): self
60
    {
61 1
        $this->classes = $classes;
62
63 1
        return $this;
64
    }
65
66
    /**
67
     * @psalm-param array<array-key, string> $directories
68
     *
69
     * @return $this
70
     */
71 1
    public function setDirectories(array $directories): self
72
    {
73 1
        $this->directories = $directories;
74
75 1
        return $this;
76
    }
77
78
    /**
79
     * @throws ReflectionException
80
     *
81
     * @psalm-return array<array-key, ReflectionClass<object>>
82
     */
83 1
    private function getClasses(): array
84
    {
85 1
        return array_map(
86 1
            static fn (string $className) => new ReflectionClass($className),
87 1
            $this->classes
88
        );
89
    }
90
91
    /**
92
     * @return ReflectionClass[]
93
     *
94
     * @psalm-return list<ReflectionClass<object>>
95
     */
96 1
    private function loadClasses(): array
97
    {
98 1
        if ($this->directories === []) {
99
            return [];
100
        }
101 1
        $finder = Finder::create()->name('*.php')->in($this->directories);
102 1
        $classes = (new ClassLocator($finder))->getClasses();
103
104 1
        return array_values($classes);
105
    }
106
}
107