AppIterator::getMetaCollection()   A
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 10
c 0
b 0
f 0
nc 4
nop 1
dl 0
loc 18
rs 9.6111
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
/**
26
 * @psalm-import-type ResourceClassName from Types
27
 * @psalm-import-type MetaMap from Types
28
 * @psalm-import-type ClassNameList from Types
29
 * @implements Iterator<string, Meta>
30
 */
31
final class AppIterator implements Iterator
32
{
33
    private int $i = 0;
34
35
    /** @var MetaMap */
0 ignored issues
show
Bug introduced by
The type BEAR\Resource\MetaMap 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...
36
    private array $metaCollection = [];
37
38
    /** @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...
39
    private array $keys = [];
40
41
    /** @throws ResourceDirException */
42
    public function __construct(string $resourceDir)
43
    {
44
        if (! file_exists($resourceDir)) {
45
            throw new ResourceDirException($resourceDir);
46
        }
47
48
        $iterator = new RecursiveIteratorIterator(
49
            new RecursiveDirectoryIterator($resourceDir),
50
            RecursiveIteratorIterator::SELF_FIRST,
51
        );
52
        $this->metaCollection = $this->getMetaCollection($iterator);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getMetaCollection($iterator) of type array or array is incompatible with the declared type BEAR\Resource\MetaMap of property $metaCollection.

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