AppIterator   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 131
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 46
dl 0
loc 131
rs 10
c 0
b 0
f 0
ccs 50
cts 50
cp 1
wmc 19

10 Methods

Rating   Name   Duplication   Size   Complexity  
A current() 0 4 1
A getName() 0 10 4
A next() 0 4 1
A getResourceClassName() 0 9 1
A getMetaCollection() 0 19 4
A key() 0 4 1
A __construct() 0 12 2
A valid() 0 4 1
A rewind() 0 4 1
A isNotPhp() 0 7 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Resource;
6
7
use BEAR\Resource\Exception\ResourceDirException;
8
use Iterator;
9
use Override;
10
use RecursiveDirectoryIterator;
11
use RecursiveIteratorIterator;
12
use ReflectionClass;
13
use SplFileInfo;
14
15
use function array_diff_key;
16
use function array_key_exists;
17
use function array_keys;
18
use function array_values;
19
use function assert;
20
use function class_exists;
21
use function file_exists;
22
use function get_declared_classes;
23
use function str_contains;
24
25
/** @implements Iterator<string, Meta> */
26
final class AppIterator implements Iterator
27
{
28
    private int $i = 0;
29
30
    /** @var array<string, Meta> */
31 2
    private array $metaCollection = [];
32
33 2
    /** @var list<string> */
0 ignored issues
show
Bug introduced by
The type BEAR\Resource\list was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
34 1
    private array $keys = [];
35
36 2
    /** @throws ResourceDirException */
37 2
    public function __construct(string $resourceDir)
38 2
    {
39
        if (! file_exists($resourceDir)) {
40 2
            throw new ResourceDirException($resourceDir);
41 2
        }
42 2
43
        $iterator = new RecursiveIteratorIterator(
44
            new RecursiveDirectoryIterator($resourceDir),
45
            RecursiveIteratorIterator::SELF_FIRST,
46
        );
47 1
        $this->metaCollection = $this->getMetaCollection($iterator);
48
        $this->keys = array_keys($this->metaCollection);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_keys($this->metaCollection) of type array is incompatible with the declared type BEAR\Resource\list of property $keys.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
49 1
    }
50
51
    /**
52
     * {@inheritDoc}
53
     */
54
    #[Override]
55 1
    public function current(): Meta
56
    {
57 1
        return $this->metaCollection[$this->keys[$this->i]];
58 1
    }
59
60
    /**
61
     * {@inheritDoc}
62
     */
63 1
    #[Override]
64
    public function next(): void
65 1
    {
66
        ++$this->i;
67
    }
68
69
    /**
70
     * {@inheritDoc}
71 1
     */
72
    #[Override]
73 1
    public function key(): string
74
    {
75
        return $this->keys[$this->i]; // @codeCoverageIgnore
76
    }
77
78
    /**
79 1
     * {@inheritDoc}
80
     */
81 1
    #[Override]
82 1
    public function valid(): bool
83
    {
84 2
        return array_key_exists($this->i, $this->keys);
85
    }
86 2
87 2
    /**
88
     * {@inheritDoc}
89 2
     */
90 2
    #[Override]
91
    public function rewind(): void
92 2
    {
93 2
        $this->i = 0;
94 1
    }
95
96 1
    /**
97 1
     * @param Iterator<SplFileInfo> $iterator
98
     *
99
     * @return array<string, Meta>
100 2
     */
101
    private function getMetaCollection(Iterator $iterator): array
102
    {
103 2
        $metaCollection = [];
104
        foreach ($iterator as $item) {
105 2
            if ($this->isNotPhp($item)) {
106 2
                continue;
107 2
            }
108
109 2
            $resourceClass = $this->getResourceClassName($item);
110
            if ($resourceClass === '') {
111
                continue;
112 2
            }
113
114 2
            assert(class_exists($resourceClass));
115 2
            $meta = new Meta($resourceClass);
116
            $metaCollection[$meta->uri] = $meta;
117 2
        }
118 2
119 2
        return $metaCollection;
120
    }
121 2
122
    private function isNotPhp(SplFileInfo $item): bool
123
    {
124 2
        $isPhp = $item->isFile()
125
            && $item->getExtension() === 'php'
126 2
            && (! str_contains($item->getBasename('.php'), '.'));
127 1
128 1
        return ! $isPhp;
129 1
    }
130
131
    private function getResourceClassName(SplFileInfo $file): string
132
    {
133 1
        $pathName = $file->getPathname();
134
        $declaredClasses = get_declared_classes();
135
        assert(file_exists($pathName));
136
        include_once $pathName;
137
        $newClasses = array_values(array_diff_key(get_declared_classes(), $declaredClasses));
138
139
        return $this->getName($newClasses);
140
    }
141
142
    /**
143
     * @param array<class-string> $newClasses
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...
144
     *
145
     * @return class-string|string
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string|string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string|string.
Loading history...
146
     */
147
    private function getName(array $newClasses): string
148
    {
149
        foreach ($newClasses as $newClass) {
150
            $parent = (new ReflectionClass($newClass))->getParentClass();
151
            if ($parent && $parent->name === ResourceObject::class) {
152
                return $newClass;
153
            }
154
        }
155
156
        return '';
157
    }
158
}
159