GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( 490b6c...dd0459 )
by SignpostMarv
03:01
created

StaticMethodCollector::__construct()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 42
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 15
nc 2
nop 3
dl 0
loc 42
ccs 14
cts 14
cp 1
crap 2
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
/**
5
* @author SignpostMarv
6
*/
7
8
namespace SignpostMarv\DaftInterfaceCollector;
9
10
use Generator;
11
use ReflectionClass;
12
use ReflectionMethod;
13
use Traversable;
14
15
class StaticMethodCollector
16
{
17
    /**
18
    * @var array<string, array<int, string>>
19
    */
20
    private $staticMethods;
21
22
    /**
23
    * @var string[]
24
    */
25
    private $interfaces = [];
26
27
    /**
28
    * @var array<int, string>
29
    */
30
    private $processedSources = [];
31
32
    /**
33
    * @var string[]
34
    */
35
    private $alreadyYielded = [];
36
37
    /**
38
    * @var bool
39
    */
40
    private $autoResetProcessedSources;
41
42 4
    public function __construct(
43
        array $staticMethods,
44
        array $interfaces,
45
        bool $autoResetProcessedSources = true
46
    ) {
47
        /**
48
        * @var array<string, array<int, string>> $filtered
49
        */
50 4
        $filtered = [];
51
52
        /**
53
        * @var string $interface
54
        * @var array<string, array<int, string>> $methods
55
        */
56
        foreach (
57 4
            array_filter(
58 4
                $staticMethods,
59 4
                [$this, 'shouldContainInterfaces'],
60 4
                ARRAY_FILTER_USE_KEY
61
            ) as $interface => $methods
62
        ) {
63 4
            $ref = new ReflectionClass($interface);
64
65 4
            $filtered[$interface] = $this->FilterMethods($ref, $methods);
66
        }
67
68
        /**
69
        * @var array<string, array<int, string>> $filtered
70
        */
71
        $filtered = array_filter($filtered, function (array $methods) : bool {
72 4
            return count($methods) > 0;
73 4
        });
74
75
        /**
76
        * @var string[] $filteredInterfaces
77
        */
78 4
        $filteredInterfaces = array_filter($interfaces, [$this, 'shouldContainInterfaces']);
79
80 4
        $this->interfaces = $filteredInterfaces;
81
82 4
        $this->staticMethods = $filtered;
83 4
        $this->autoResetProcessedSources = $autoResetProcessedSources;
84 4
    }
85
86 4
    public function Collect(string ...$implementations) : Generator
87
    {
88 4
        if ($this->autoResetProcessedSources) {
89 2
            $this->processedSources = [];
90 2
            $this->alreadyYielded = [];
91
        }
92
93 4
        yield from $this->CollectInterfaces(...$implementations);
94 4
    }
95
96 4
    protected function CollectInterfaces(string ...$implementations) : Generator
97
    {
98
        /**
99
        * @var string[] $interfaces
100
        */
101 4
        $interfaces = array_keys($this->staticMethods);
102 4
        foreach (array_filter($implementations, 'class_exists') as $implementation) {
103
            if (
104 4
                in_array($implementation, $this->processedSources, true) ||
105 4
                in_array($implementation, $this->alreadyYielded, true)
106
            ) {
107 2
                continue;
108
            }
109 4
            $this->processedSources[] = $implementation;
110
111
            /**
112
            * @var string $interface
113
            */
114 4
            foreach ($this->interfaces as $interface) {
115 4
                if (is_a($implementation, $interface, true)) {
116
                    yield $implementation;
117
                    $this->alreadyYielded[] = $implementation;
118 4
                    break;
119
                }
120
            }
121
122 4
            foreach ($interfaces as $interface) {
123 4
                if (is_a($implementation, $interface, true)) {
124
                    /**
125
                    * @var array<int, string> $types
126
                    */
127 4
                    foreach ($this->staticMethods[$interface] as $method => $types) {
128
                        /**
129
                        * @var iterable<string> $methodResult
130
                        */
131 4
                        $methodResult = $implementation::$method();
132
133
                        /**
134
                        * @var string $result
135
                        */
136 4
                        foreach ($methodResult as $result) {
137 4
                            if (in_array($result, $this->alreadyYielded, true)) {
138
                                continue;
139
                            }
140 4
                            foreach ($types as $type) {
0 ignored issues
show
Bug introduced by
The expression $types of type string is not traversable.
Loading history...
141 4
                                if (is_a($result, $type, true)) {
142 4
                                    yield $result;
143 4
                                    $this->alreadyYielded[] = $result;
144 4
                                    continue;
145
                                }
146
                            }
147 4
                            foreach ($interfaces as $checkResultWithInterface) {
148 4
                                if (is_a($result, $checkResultWithInterface, true)) {
149 4
                                    yield from $this->CollectInterfaces($result);
150
                                }
151
                            }
152
                        }
153
                    }
154
                }
155
            }
156
        }
157 4
    }
158
159
    /**
160
    * @param mixed $maybe
161
    */
162 4
    protected function shouldContainInterfaces($maybe) : bool
163
    {
164 4
        return is_string($maybe) && interface_exists($maybe);
165
    }
166
167
    /**
168
    * @param array<string, array<int, string>> $methods
169
    */
170 4
    private function FilterMethods(ReflectionClass $ref, array $methods) : array
171
    {
172 4
        $methods = array_filter(
173 4
            $methods,
174
            /**
175
            * @param mixed $maybe
176
            */
177
            function ($maybe) use ($ref) : bool {
178 4
                if (is_string($maybe) && $ref->hasMethod($maybe)) {
179
                    /**
180
                    * @var ReflectionMethod $refMethod
181
                    */
182 4
                    $refMethod = $ref->getMethod($maybe);
183
184
                    if (
185 4
                        $refMethod->isStatic() &&
186 4
                        $refMethod->isPublic() &&
187 4
                        0 === $refMethod->getNumberOfRequiredParameters() &&
188 4
                        $refMethod->hasReturnType()
189
                    ) {
190
                        /**
191
                        * @var \ReflectionType $refReturn
192
                        */
193 4
                        $refReturn = $refMethod->getReturnType();
194 4
                        $refReturnName = $refReturn->__toString();
0 ignored issues
show
Deprecated Code introduced by
The function ReflectionType::__toString() has been deprecated: 7.1.0:8.0.0 Please use getName() ( Ignorable by Annotation )

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

194
                        $refReturnName = /** @scrutinizer ignore-deprecated */ $refReturn->__toString();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
195
196
                        return
197 4
                            'array' === $refReturnName ||
198 4
                            is_a($refReturnName, Traversable::class, true);
199
                    }
200
                }
201
202
                return false;
203 4
            },
204 4
            ARRAY_FILTER_USE_KEY
205
        );
206
207 4
        return array_map(
208
            function (array $methodInterfaces) : array {
209 4
                return array_filter($methodInterfaces, [$this, 'shouldContainInterfaces']);
210 4
            },
211 4
            $methods
212
        );
213
    }
214
}
215