This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php declare(strict_types=1); |
||
2 | //////////////////////////////////////////////////////////////////////////////// |
||
3 | // __________ __ ________ __________ |
||
4 | // \______ \ |__ ______ / _____/ ____ _____ ______\______ \ _______ ___ |
||
5 | // | ___/ | \\____ \/ \ ____/ __ \\__ \\_ __ \ | _// _ \ \/ / |
||
6 | // | | | Y \ |_> > \_\ \ ___/ / __ \| | \/ | ( <_> > < |
||
7 | // |____| |___| / __/ \______ /\___ >____ /__| |______ /\____/__/\_ \ |
||
8 | // \/|__| \/ \/ \/ \/ \/ |
||
9 | // ----------------------------------------------------------------------------- |
||
10 | // Designed and Developed by Brad Jones <brad @="bjc.id.au" /> |
||
11 | // ----------------------------------------------------------------------------- |
||
12 | //////////////////////////////////////////////////////////////////////////////// |
||
13 | |||
14 | namespace Gears; |
||
15 | |||
16 | use Closure; |
||
17 | use Exception; |
||
18 | use Traversable; |
||
19 | use ArrayIterator; |
||
20 | use ReflectionClass; |
||
21 | use ReflectionException; |
||
22 | use Gears\String\Str; |
||
23 | use Composer\Autoload\ClassLoader; |
||
24 | use Symfony\Component\Finder\Finder; |
||
25 | use Symfony\Component\Finder\SplFileInfo; |
||
26 | |||
27 | class ClassFinder implements IClassFinder |
||
28 | { |
||
29 | /** |
||
30 | * The composer class loader as returned from `vendor/autoload.php`. |
||
31 | * |
||
32 | * @var ClassLoader |
||
33 | */ |
||
34 | protected $composer; |
||
35 | |||
36 | /** |
||
37 | * This will be filled with fully qualified class names as they are found |
||
38 | * by searching through the various class maps provided by composer. |
||
39 | * |
||
40 | * @var array|string[] |
||
41 | */ |
||
42 | protected $foundClasses = []; |
||
43 | |||
44 | /** |
||
45 | * The namespace to filter by will be stored here. |
||
46 | * |
||
47 | * > NOTE: This must be set, otherwise we could have a |
||
48 | * very large data set to search through. |
||
49 | * |
||
50 | * @var string |
||
51 | */ |
||
52 | protected $namespace; |
||
53 | |||
54 | /** |
||
55 | * The interface name to filter by will be stored here. |
||
56 | * |
||
57 | * @var string |
||
58 | */ |
||
59 | protected $implements; |
||
60 | |||
61 | /** |
||
62 | * The parent class to filter by will be stored here. |
||
63 | * |
||
64 | * @var string |
||
65 | */ |
||
66 | protected $extends; |
||
67 | |||
68 | /** |
||
69 | * An optional custom filter method can be set. |
||
70 | * Otherwise we will use the `defaultFilter` method in this class. |
||
71 | * |
||
72 | * @var Closure |
||
73 | */ |
||
74 | protected $filter; |
||
75 | |||
76 | /** |
||
77 | * Constructor. |
||
78 | * |
||
79 | * @param ClassLoader $composer We rely on the information provided by the |
||
80 | * composer class maps in order to find classes |
||
81 | * for you. |
||
82 | */ |
||
83 | public function __construct(ClassLoader $composer) |
||
84 | { |
||
85 | $this->composer = $composer; |
||
86 | } |
||
87 | |||
88 | public function namespace(string $namespace): IClassFinder |
||
0 ignored issues
–
show
Coding Style
introduced
by
![]() |
|||
89 | { |
||
90 | $this->namespace = $namespace; return $this; |
||
0 ignored issues
–
show
The visibility should be declared for property
$this .
The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using class A {
var $property;
}
the property is implicitly global. To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2. ![]() |
|||
91 | } |
||
92 | |||
93 | public function implements(string $interface): IClassFinder |
||
94 | { |
||
95 | $this->implements = $interface; return $this; |
||
96 | } |
||
97 | |||
98 | public function extends(string $parent): IClassFinder |
||
99 | { |
||
100 | $this->extends = $parent; return $this; |
||
101 | } |
||
102 | |||
103 | public function filterBy(Closure $filter): IClassFinder |
||
104 | { |
||
105 | if ($this->implements !== null || $this->extends != null) |
||
106 | { |
||
107 | throw new Exception |
||
108 | ( |
||
109 | 'Can not set a custom filter and filter '. |
||
110 | 'by `implements` or `extends`!' |
||
111 | ); |
||
112 | } |
||
113 | |||
114 | $this->filter = $filter; return $this; |
||
115 | } |
||
116 | |||
117 | public function search(): array |
||
118 | { |
||
119 | $this->foundClasses = []; |
||
120 | |||
121 | if ($this->namespace === null) |
||
122 | { |
||
123 | throw new Exception('Namespace must be set!'); |
||
124 | } |
||
125 | |||
126 | $this->searchClassMap(); |
||
127 | $this->searchPsrMaps(); |
||
128 | $this->runFilter(); |
||
129 | |||
130 | $this->namespace = null; |
||
131 | $this->implements = null; |
||
132 | $this->extends = null; |
||
133 | |||
134 | return $this->foundClasses; |
||
135 | } |
||
136 | |||
137 | public function getIterator(): Traversable |
||
138 | { |
||
139 | return new ArrayIterator($this->search()); |
||
140 | } |
||
141 | |||
142 | public function count(): int |
||
143 | { |
||
144 | return iterator_count($this->getIterator()); |
||
145 | } |
||
146 | |||
147 | /** |
||
148 | * Searches the composer class map. |
||
149 | * |
||
150 | * Results are added to the `$foundClasses` array. |
||
151 | * |
||
152 | * @return void |
||
153 | */ |
||
154 | protected function searchClassMap() |
||
155 | { |
||
156 | foreach ($this->composer->getClassMap() as $fqcn => $file) |
||
157 | { |
||
158 | View Code Duplication | if (Str::s($fqcn)->is($this->namespace.'*')) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
159 | { |
||
160 | $this->foundClasses[realpath($file)] = $fqcn; |
||
161 | } |
||
162 | } |
||
163 | } |
||
164 | |||
165 | /** |
||
166 | * Searches the composer PSR-x class maps. |
||
167 | * |
||
168 | * Results are added to the `$foundClasses` array. |
||
169 | * |
||
170 | * @return void |
||
171 | */ |
||
172 | protected function searchPsrMaps() |
||
173 | { |
||
174 | $prefixes = array_merge |
||
175 | ( |
||
176 | $this->composer->getPrefixes(), |
||
177 | $this->composer->getPrefixesPsr4() |
||
178 | ); |
||
179 | |||
180 | $trimmedNs = Str::s($this->namespace)->trimRight('\\'); |
||
181 | |||
182 | $nsSegments = $trimmedNs->split('\\'); |
||
183 | |||
184 | foreach ($prefixes as $ns => $dirs) |
||
185 | { |
||
186 | $foundSegments = Str::s($ns)->trimRight('\\') |
||
187 | ->longestCommonPrefix($trimmedNs)->split('\\'); |
||
188 | |||
189 | foreach ($foundSegments as $key => $segment) |
||
190 | { |
||
191 | if ((string) $nsSegments[$key] !== (string) $segment) |
||
192 | { |
||
193 | continue 2; |
||
194 | } |
||
195 | } |
||
196 | |||
197 | foreach ($dirs as $dir) |
||
198 | { |
||
199 | foreach ((new Finder)->in($dir)->files()->name('*.php') as $file) |
||
200 | { |
||
201 | if ($file instanceof SplFileInfo) |
||
202 | { |
||
203 | $fqcn = (string)Str::s($file->getRelativePathname()) |
||
204 | ->trimRight('.php') |
||
205 | ->replace('/', '\\') |
||
206 | ->ensureLeft($ns); |
||
207 | |||
208 | View Code Duplication | if (Str::s($fqcn)->is($this->namespace.'*')) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
209 | { |
||
210 | $this->foundClasses[$file->getRealPath()] = $fqcn; |
||
211 | } |
||
212 | } |
||
213 | } |
||
214 | } |
||
215 | } |
||
216 | } |
||
217 | |||
218 | /** |
||
219 | * Runs a filter over the array of `$foundCLasses`. |
||
220 | * |
||
221 | * Also ensures the classes are real by creating a ReflectionClass instance. |
||
222 | * By default we use the `defaultFilter` method. |
||
223 | * |
||
224 | * @return void |
||
225 | */ |
||
226 | protected function runFilter() |
||
227 | { |
||
228 | foreach ($this->foundClasses as $file => $fqcn) |
||
229 | { |
||
230 | try |
||
231 | { |
||
232 | $rClass = new ReflectionClass($fqcn); |
||
233 | } |
||
234 | catch (ReflectionException $e) |
||
235 | { |
||
236 | $result = false; |
||
0 ignored issues
–
show
$result is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
237 | } |
||
238 | |||
239 | if ($this->filter === null) |
||
240 | { |
||
241 | $result = $this->defaultFilter($rClass); |
||
242 | } |
||
243 | else |
||
244 | { |
||
245 | $result = call_user_func($this->filter, $rClass); |
||
246 | } |
||
247 | |||
248 | if ($result === false) |
||
249 | { |
||
250 | unset($this->foundClasses[$file]); |
||
251 | } |
||
252 | } |
||
253 | } |
||
254 | |||
255 | /** |
||
256 | * The default filter run by `runFilter()`. |
||
257 | * |
||
258 | * Further filters by interface or parent class and also filters |
||
259 | * out actual Interfaces, Abstract Classes and Traits. |
||
260 | * |
||
261 | * @param ReflectionClass $rClass |
||
262 | * @return bool |
||
263 | */ |
||
264 | protected function defaultFilter(ReflectionClass $rClass) |
||
265 | { |
||
266 | if ($this->implements !== null) |
||
267 | { |
||
268 | return $rClass->implementsInterface($this->implements) && !$rClass->isInterface(); |
||
269 | } |
||
270 | |||
271 | if ($this->extends !== null) |
||
272 | { |
||
273 | return $rClass->isSubclassOf($this->extends) && !$rClass->isAbstract(); |
||
274 | } |
||
275 | |||
276 | return (!$rClass->isInterface() && !$rClass->isAbstract() && !$rClass->isTrait()); |
||
277 | } |
||
278 | } |