Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
99.05% |
521 / 526 |
|
50.00% |
3 / 6 |
CRAP | |
0.00% |
0 / 1 |
FileScanner | |
99.05% |
521 / 526 |
|
50.00% |
3 / 6 |
17 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
findInFiles | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
find | |
100.00% |
23 / 23 |
|
100.00% |
1 / 1 |
6 | |||
addDiscoveredClassChange | |
66.67% |
4 / 6 |
|
0.00% |
0 / 1 |
3.33 | |||
addDiscoveredNamespaceChange | |
60.00% |
3 / 5 |
|
0.00% |
0 / 1 |
3.58 | |||
getBuiltIns | |
99.79% |
481 / 482 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * The purpose of this class is only to find changes that should be made. |
4 | * i.e. classes and namespaces to change. |
5 | * Those recorded are updated in a later step. |
6 | */ |
7 | |
8 | namespace BrianHenryIE\Strauss; |
9 | |
10 | use BrianHenryIE\Strauss\Composer\Extra\StraussConfig; |
11 | use BrianHenryIE\Strauss\Types\ClassSymbol; |
12 | use BrianHenryIE\Strauss\Types\ConstantSymbol; |
13 | use BrianHenryIE\Strauss\Types\NamespaceSymbol; |
14 | |
15 | class FileScanner |
16 | { |
17 | |
18 | protected string $namespacePrefix; |
19 | protected string $classmapPrefix; |
20 | |
21 | /** @var string[] */ |
22 | protected array $excludeNamespacesFromPrefixing = array(); |
23 | |
24 | /** @var string[] */ |
25 | protected array $excludeFilePatternsFromPrefixing = array(); |
26 | |
27 | /** @var string[] */ |
28 | protected array $namespaceReplacementPatterns = array(); |
29 | |
30 | protected DiscoveredSymbols $discoveredSymbols; |
31 | |
32 | /** |
33 | * @var string[] |
34 | */ |
35 | protected array $excludePackagesFromPrefixing; |
36 | |
37 | /** |
38 | * FileScanner constructor. |
39 | * @param \BrianHenryIE\Strauss\Composer\Extra\StraussConfig $config |
40 | */ |
41 | public function __construct(StraussConfig $config) |
42 | { |
43 | $this->discoveredSymbols = new DiscoveredSymbols(); |
44 | |
45 | $this->namespacePrefix = $config->getNamespacePrefix(); |
46 | $this->classmapPrefix = $config->getClassmapPrefix(); |
47 | |
48 | $this->excludePackagesFromPrefixing = $config->getExcludePackagesFromPrefixing(); |
49 | $this->excludeNamespacesFromPrefixing = $config->getExcludeNamespacesFromPrefixing(); |
50 | $this->excludeFilePatternsFromPrefixing = $config->getExcludeFilePatternsFromPrefixing(); |
51 | |
52 | $this->namespaceReplacementPatterns = $config->getNamespaceReplacementPatterns(); |
53 | } |
54 | |
55 | /** |
56 | * @param DiscoveredFiles $files |
57 | */ |
58 | public function findInFiles(DiscoveredFiles $files): DiscoveredSymbols |
59 | { |
60 | foreach ($files->getFiles() as $file) { |
61 | $this->find($file->getContents(), $file); |
62 | } |
63 | |
64 | return $this->discoveredSymbols; |
65 | } |
66 | |
67 | |
68 | /** |
69 | * TODO: Don't use preg_replace_callback! |
70 | * |
71 | * @uses self::addDiscoveredNamespaceChange() |
72 | * @uses self::addDiscoveredClassChange() |
73 | * |
74 | * @param string $contents |
75 | */ |
76 | protected function find(string $contents, File $file): void |
77 | { |
78 | // If the entire file is under one namespace, all we want is the namespace. |
79 | // If there were more than one namespace, it would appear as `namespace MyNamespace { ...`, |
80 | // a file with only a single namespace will appear as `namespace MyNamespace;`. |
81 | $singleNamespacePattern = '/ |
82 | (<?php|\r\n|\n) # A new line or the beginning of the file. |
83 | \s* # Allow whitespace before |
84 | namespace\s+(?<namespace>[0-9A-Za-z_\x7f-\xff\\\\]+)[\s\S]*; # Match a single namespace in the file. |
85 | /x'; // # x: ignore whitespace in regex. |
86 | if (1 === preg_match($singleNamespacePattern, $contents, $matches)) { |
87 | $this->addDiscoveredNamespaceChange($matches['namespace'], $file); |
88 | return; |
89 | } |
90 | |
91 | if (0 < preg_match_all('/\s*define\s*\(\s*["\']([^"\']*)["\']\s*,\s*["\'][^"\']*["\']\s*\)\s*;/', $contents, $constants)) { |
92 | foreach ($constants[1] as $constant) { |
93 | $constantObj = new ConstantSymbol($constant, $file); |
94 | $this->discoveredSymbols->add($constantObj); |
95 | } |
96 | } |
97 | |
98 | // TODO traits |
99 | |
100 | // TODO: Is the ";" in this still correct since it's being taken care of in the regex just above? |
101 | // Looks like with the preceding regex, it will never match. |
102 | |
103 | |
104 | preg_replace_callback( |
105 | ' |
106 | ~ # Start the pattern |
107 | [\r\n]+\s*namespace\s+([a-zA-Z0-9_\x7f-\xff\\\\]+)[;{\s\n]{1}[\s\S]*?(?=namespace|$) |
108 | # Look for a preceding namespace declaration, |
109 | # followed by a semicolon, open curly bracket, space or new line |
110 | # up until a |
111 | # potential second namespace declaration or end of file. |
112 | # if found, match that much before continuing the search on |
113 | | # the remainder of the string. |
114 | \/\*[\s\S]*?\*\/ | # Skip multiline comments |
115 | ^\s*\/\/.*$ | # Skip single line comments |
116 | \s* # Whitespace is allowed before |
117 | (?:abstract\sclass|class|interface)\s+ # Look behind for class, abstract class, interface |
118 | ([a-zA-Z0-9_\x7f-\xff]+) # Match the word until the first non-classname-valid character |
119 | \s? # Allow a space after |
120 | (?:{|extends|implements|\n|$) # Class declaration can be followed by {, extends, implements |
121 | # or a new line |
122 | ~x', // # x: ignore whitespace in regex. |
123 | function ($matches) use ($file) { |
124 | |
125 | // If we're inside a namespace other than the global namespace: |
126 | if (1 === preg_match('/^\s*namespace\s+[a-zA-Z0-9_\x7f-\xff\\\\]+[;{\s\n]{1}.*/', $matches[0])) { |
127 | $this->addDiscoveredNamespaceChange($matches[1], $file); |
128 | |
129 | return $matches[0]; |
130 | } |
131 | |
132 | if (count($matches) < 3) { |
133 | return $matches[0]; |
134 | } |
135 | |
136 | // TODO: Why is this [2] and not [1] (which seems to be always empty). |
137 | $this->addDiscoveredClassChange($matches[2], $file); |
138 | |
139 | return $matches[0]; |
140 | }, |
141 | $contents |
142 | ); |
143 | } |
144 | |
145 | protected function addDiscoveredClassChange(string $classname, File $file): void |
146 | { |
147 | |
148 | if ('ReturnTypeWillChange' === $classname) { |
149 | return; |
150 | } |
151 | if (in_array($classname, $this->getBuiltIns())) { |
152 | return; |
153 | } |
154 | |
155 | $classSymbol = new ClassSymbol($classname, $file); |
156 | $this->discoveredSymbols->add($classSymbol); |
157 | } |
158 | |
159 | protected function addDiscoveredNamespaceChange(string $namespace, File $file): void |
160 | { |
161 | |
162 | foreach ($this->excludeNamespacesFromPrefixing as $excludeNamespace) { |
163 | if (0 === strpos($namespace, $excludeNamespace)) { |
164 | return; |
165 | } |
166 | } |
167 | |
168 | $namespaceObj = new NamespaceSymbol($namespace, $file); |
169 | $this->discoveredSymbols->add($namespaceObj); |
170 | } |
171 | |
172 | /** |
173 | * Get a list of PHP built-in classes etc. so they are not prefixed. |
174 | * |
175 | * Polyfilled classes were being prefixed, but the polyfills are only active when the PHP version is below X, |
176 | * so calls to those prefixed polyfilled classnames would fail on newer PHP versions. |
177 | * |
178 | * NB: This list is not exhaustive. Any unloaded PHP extensions are not included. |
179 | * |
180 | * @see https://github.com/BrianHenryIE/strauss/issues/79 |
181 | * |
182 | * ``` |
183 | * array_filter( |
184 | * get_declared_classes(), |
185 | * function(string $className): bool { |
186 | * $reflector = new \ReflectionClass($className); |
187 | * return empty($reflector->getFileName()); |
188 | * } |
189 | * ); |
190 | * ``` |
191 | * |
192 | * @return string[] |
193 | */ |
194 | protected function getBuiltIns(): array |
195 | { |
196 | $builtins = [ |
197 | '7.4' => |
198 | [ |
199 | 'classes' => |
200 | [ |
201 | 'AppendIterator', |
202 | 'ArgumentCountError', |
203 | 'ArithmeticError', |
204 | 'ArrayIterator', |
205 | 'ArrayObject', |
206 | 'AssertionError', |
207 | 'BadFunctionCallException', |
208 | 'BadMethodCallException', |
209 | 'CURLFile', |
210 | 'CachingIterator', |
211 | 'CallbackFilterIterator', |
212 | 'ClosedGeneratorException', |
213 | 'Closure', |
214 | 'Collator', |
215 | 'CompileError', |
216 | 'DOMAttr', |
217 | 'DOMCdataSection', |
218 | 'DOMCharacterData', |
219 | 'DOMComment', |
220 | 'DOMConfiguration', |
221 | 'DOMDocument', |
222 | 'DOMDocumentFragment', |
223 | 'DOMDocumentType', |
224 | 'DOMDomError', |
225 | 'DOMElement', |
226 | 'DOMEntity', |
227 | 'DOMEntityReference', |
228 | 'DOMErrorHandler', |
229 | 'DOMException', |
230 | 'DOMImplementation', |
231 | 'DOMImplementationList', |
232 | 'DOMImplementationSource', |
233 | 'DOMLocator', |
234 | 'DOMNameList', |
235 | 'DOMNameSpaceNode', |
236 | 'DOMNamedNodeMap', |
237 | 'DOMNode', |
238 | 'DOMNodeList', |
239 | 'DOMNotation', |
240 | 'DOMProcessingInstruction', |
241 | 'DOMStringExtend', |
242 | 'DOMStringList', |
243 | 'DOMText', |
244 | 'DOMTypeinfo', |
245 | 'DOMUserDataHandler', |
246 | 'DOMXPath', |
247 | 'DateInterval', |
248 | 'DatePeriod', |
249 | 'DateTime', |
250 | 'DateTimeImmutable', |
251 | 'DateTimeZone', |
252 | 'Directory', |
253 | 'DirectoryIterator', |
254 | 'DivisionByZeroError', |
255 | 'DomainException', |
256 | 'EmptyIterator', |
257 | 'Error', |
258 | 'ErrorException', |
259 | 'Exception', |
260 | 'FFI', |
261 | 'FFI\\CData', |
262 | 'FFI\\CType', |
263 | 'FFI\\Exception', |
264 | 'FFI\\ParserException', |
265 | 'FilesystemIterator', |
266 | 'FilterIterator', |
267 | 'GMP', |
268 | 'Generator', |
269 | 'GlobIterator', |
270 | 'HashContext', |
271 | 'InfiniteIterator', |
272 | 'IntlBreakIterator', |
273 | 'IntlCalendar', |
274 | 'IntlChar', |
275 | 'IntlCodePointBreakIterator', |
276 | 'IntlDateFormatter', |
277 | 'IntlException', |
278 | 'IntlGregorianCalendar', |
279 | 'IntlIterator', |
280 | 'IntlPartsIterator', |
281 | 'IntlRuleBasedBreakIterator', |
282 | 'IntlTimeZone', |
283 | 'InvalidArgumentException', |
284 | 'IteratorIterator', |
285 | 'JsonException', |
286 | 'LengthException', |
287 | 'LibXMLError', |
288 | 'LimitIterator', |
289 | 'Locale', |
290 | 'LogicException', |
291 | 'MessageFormatter', |
292 | 'MultipleIterator', |
293 | 'NoRewindIterator', |
294 | 'Normalizer', |
295 | 'NumberFormatter', |
296 | 'OutOfBoundsException', |
297 | 'OutOfRangeException', |
298 | 'OverflowException', |
299 | 'PDO', |
300 | 'PDOException', |
301 | 'PDORow', |
302 | 'PDOStatement', |
303 | 'ParentIterator', |
304 | 'ParseError', |
305 | 'Phar', |
306 | 'PharData', |
307 | 'PharException', |
308 | 'PharFileInfo', |
309 | 'RangeException', |
310 | 'RecursiveArrayIterator', |
311 | 'RecursiveCachingIterator', |
312 | 'RecursiveCallbackFilterIterator', |
313 | 'RecursiveDirectoryIterator', |
314 | 'RecursiveFilterIterator', |
315 | 'RecursiveIteratorIterator', |
316 | 'RecursiveRegexIterator', |
317 | 'RecursiveTreeIterator', |
318 | 'Reflection', |
319 | 'ReflectionClass', |
320 | 'ReflectionClassConstant', |
321 | 'ReflectionException', |
322 | 'ReflectionExtension', |
323 | 'ReflectionFunction', |
324 | 'ReflectionFunctionAbstract', |
325 | 'ReflectionGenerator', |
326 | 'ReflectionMethod', |
327 | 'ReflectionNamedType', |
328 | 'ReflectionObject', |
329 | 'ReflectionParameter', |
330 | 'ReflectionProperty', |
331 | 'ReflectionReference', |
332 | 'ReflectionType', |
333 | 'ReflectionZendExtension', |
334 | 'RegexIterator', |
335 | 'ResourceBundle', |
336 | 'RuntimeException', |
337 | 'SQLite3', |
338 | 'SQLite3Result', |
339 | 'SQLite3Stmt', |
340 | 'SessionHandler', |
341 | 'SimpleXMLElement', |
342 | 'SimpleXMLIterator', |
343 | 'SoapClient', |
344 | 'SoapFault', |
345 | 'SoapHeader', |
346 | 'SoapParam', |
347 | 'SoapServer', |
348 | 'SoapVar', |
349 | 'SodiumException', |
350 | 'SplDoublyLinkedList', |
351 | 'SplFileInfo', |
352 | 'SplFileObject', |
353 | 'SplFixedArray', |
354 | 'SplHeap', |
355 | 'SplMaxHeap', |
356 | 'SplMinHeap', |
357 | 'SplObjectStorage', |
358 | 'SplPriorityQueue', |
359 | 'SplQueue', |
360 | 'SplStack', |
361 | 'SplTempFileObject', |
362 | 'Spoofchecker', |
363 | 'Transliterator', |
364 | 'TypeError', |
365 | 'UConverter', |
366 | 'UnderflowException', |
367 | 'UnexpectedValueException', |
368 | 'WeakReference', |
369 | 'XMLReader', |
370 | 'XMLWriter', |
371 | 'XSLTProcessor', |
372 | 'ZipArchive', |
373 | '__PHP_Incomplete_Class', |
374 | 'finfo', |
375 | 'mysqli', |
376 | 'mysqli_driver', |
377 | 'mysqli_result', |
378 | 'mysqli_sql_exception', |
379 | 'mysqli_stmt', |
380 | 'mysqli_warning', |
381 | 'php_user_filter', |
382 | 'stdClass', |
383 | 'tidy', |
384 | 'tidyNode', |
385 | ], |
386 | 'interfaces' => |
387 | [ |
388 | 'ArrayAccess', |
389 | 'Countable', |
390 | 'DateTimeInterface', |
391 | 'Iterator', |
392 | 'IteratorAggregate', |
393 | 'JsonSerializable', |
394 | 'OuterIterator', |
395 | 'RecursiveIterator', |
396 | 'Reflector', |
397 | 'SeekableIterator', |
398 | 'Serializable', |
399 | 'SessionHandlerInterface', |
400 | 'SessionIdInterface', |
401 | 'SessionUpdateTimestampHandlerInterface', |
402 | 'SplObserver', |
403 | 'SplSubject', |
404 | 'Throwable', |
405 | 'Traversable', |
406 | ], |
407 | 'traits' => |
408 | [ |
409 | ], |
410 | ], |
411 | '8.1' => |
412 | [ |
413 | 'classes' => |
414 | [ |
415 | 'AddressInfo', |
416 | 'Attribute', |
417 | 'CURLStringFile', |
418 | 'CurlHandle', |
419 | 'CurlMultiHandle', |
420 | 'CurlShareHandle', |
421 | 'DeflateContext', |
422 | 'FTP\\Connection', |
423 | 'Fiber', |
424 | 'FiberError', |
425 | 'GdFont', |
426 | 'GdImage', |
427 | 'InflateContext', |
428 | 'InternalIterator', |
429 | 'IntlDatePatternGenerator', |
430 | 'LDAP\\Connection', |
431 | 'LDAP\\Result', |
432 | 'LDAP\\ResultEntry', |
433 | 'OpenSSLAsymmetricKey', |
434 | 'OpenSSLCertificate', |
435 | 'OpenSSLCertificateSigningRequest', |
436 | 'PSpell\\Config', |
437 | 'PSpell\\Dictionary', |
438 | 'PgSql\\Connection', |
439 | 'PgSql\\Lob', |
440 | 'PgSql\\Result', |
441 | 'PhpToken', |
442 | 'ReflectionAttribute', |
443 | 'ReflectionEnum', |
444 | 'ReflectionEnumBackedCase', |
445 | 'ReflectionEnumUnitCase', |
446 | 'ReflectionFiber', |
447 | 'ReflectionIntersectionType', |
448 | 'ReflectionUnionType', |
449 | 'ReturnTypeWillChange', |
450 | 'Shmop', |
451 | 'Socket', |
452 | 'SysvMessageQueue', |
453 | 'SysvSemaphore', |
454 | 'SysvSharedMemory', |
455 | 'UnhandledMatchError', |
456 | 'ValueError', |
457 | 'WeakMap', |
458 | 'XMLParser', |
459 | ], |
460 | 'interfaces' => |
461 | [ |
462 | 'BackedEnum', |
463 | 'DOMChildNode', |
464 | 'DOMParentNode', |
465 | 'Stringable', |
466 | 'UnitEnum', |
467 | ], |
468 | 'traits' => |
469 | [ |
470 | ], |
471 | ], |
472 | '8.2' => |
473 | [ |
474 | 'classes' => |
475 | [ |
476 | 'AddressInfo', |
477 | 'AllowDynamicProperties', |
478 | 'Attribute', |
479 | 'CURLStringFile', |
480 | 'CurlHandle', |
481 | 'CurlMultiHandle', |
482 | 'CurlShareHandle', |
483 | 'DeflateContext', |
484 | 'FTP\\Connection', |
485 | 'Fiber', |
486 | 'FiberError', |
487 | 'GdFont', |
488 | 'GdImage', |
489 | 'InflateContext', |
490 | 'InternalIterator', |
491 | 'IntlDatePatternGenerator', |
492 | 'LDAP\\Connection', |
493 | 'LDAP\\Result', |
494 | 'LDAP\\ResultEntry', |
495 | 'OpenSSLAsymmetricKey', |
496 | 'OpenSSLCertificate', |
497 | 'OpenSSLCertificateSigningRequest', |
498 | 'PSpell\\Config', |
499 | 'PSpell\\Dictionary', |
500 | 'PgSql\\Connection', |
501 | 'PgSql\\Lob', |
502 | 'PgSql\\Result', |
503 | 'PhpToken', |
504 | 'Random\\BrokenRandomEngineError', |
505 | 'Random\\Engine\\Mt19937', |
506 | 'Random\\Engine\\PcgOneseq128XslRr64', |
507 | 'Random\\Engine\\Secure', |
508 | 'Random\\Engine\\Xoshiro256StarStar', |
509 | 'Random\\RandomError', |
510 | 'Random\\RandomException', |
511 | 'Random\\Randomizer', |
512 | 'ReflectionAttribute', |
513 | 'ReflectionEnum', |
514 | 'ReflectionEnumBackedCase', |
515 | 'ReflectionEnumUnitCase', |
516 | 'ReflectionFiber', |
517 | 'ReflectionIntersectionType', |
518 | 'ReflectionUnionType', |
519 | 'ReturnTypeWillChange', |
520 | 'SensitiveParameter', |
521 | 'SensitiveParameterValue', |
522 | 'Shmop', |
523 | 'Socket', |
524 | 'SysvMessageQueue', |
525 | 'SysvSemaphore', |
526 | 'SysvSharedMemory', |
527 | 'UnhandledMatchError', |
528 | 'ValueError', |
529 | 'WeakMap', |
530 | 'XMLParser', |
531 | ], |
532 | 'interfaces' => |
533 | [ |
534 | 'BackedEnum', |
535 | 'DOMChildNode', |
536 | 'DOMParentNode', |
537 | 'Random\\CryptoSafeEngine', |
538 | 'Random\\Engine', |
539 | 'Stringable', |
540 | 'UnitEnum', |
541 | ], |
542 | 'traits' => |
543 | [ |
544 | ], |
545 | ], |
546 | '8.3' => |
547 | [ |
548 | 'classes' => |
549 | [ |
550 | 'AddressInfo', |
551 | 'AllowDynamicProperties', |
552 | 'Attribute', |
553 | 'CURLStringFile', |
554 | 'CurlHandle', |
555 | 'CurlMultiHandle', |
556 | 'CurlShareHandle', |
557 | 'DateError', |
558 | 'DateException', |
559 | 'DateInvalidOperationException', |
560 | 'DateInvalidTimeZoneException', |
561 | 'DateMalformedIntervalStringException', |
562 | 'DateMalformedPeriodStringException', |
563 | 'DateMalformedStringException', |
564 | 'DateObjectError', |
565 | 'DateRangeError', |
566 | 'DeflateContext', |
567 | 'FTP\\Connection', |
568 | 'Fiber', |
569 | 'FiberError', |
570 | 'GdFont', |
571 | 'GdImage', |
572 | 'InflateContext', |
573 | 'InternalIterator', |
574 | 'IntlDatePatternGenerator', |
575 | 'LDAP\\Connection', |
576 | 'LDAP\\Result', |
577 | 'LDAP\\ResultEntry', |
578 | 'OpenSSLAsymmetricKey', |
579 | 'OpenSSLCertificate', |
580 | 'OpenSSLCertificateSigningRequest', |
581 | 'Override', |
582 | 'PSpell\\Config', |
583 | 'PSpell\\Dictionary', |
584 | 'PgSql\\Connection', |
585 | 'PgSql\\Lob', |
586 | 'PgSql\\Result', |
587 | 'PhpToken', |
588 | 'Random\\BrokenRandomEngineError', |
589 | 'Random\\Engine\\Mt19937', |
590 | 'Random\\Engine\\PcgOneseq128XslRr64', |
591 | 'Random\\Engine\\Secure', |
592 | 'Random\\Engine\\Xoshiro256StarStar', |
593 | 'Random\\IntervalBoundary', |
594 | 'Random\\RandomError', |
595 | 'Random\\RandomException', |
596 | 'Random\\Randomizer', |
597 | 'ReflectionAttribute', |
598 | 'ReflectionEnum', |
599 | 'ReflectionEnumBackedCase', |
600 | 'ReflectionEnumUnitCase', |
601 | 'ReflectionFiber', |
602 | 'ReflectionIntersectionType', |
603 | 'ReflectionUnionType', |
604 | 'ReturnTypeWillChange', |
605 | 'SQLite3Exception', |
606 | 'SensitiveParameter', |
607 | 'SensitiveParameterValue', |
608 | 'Shmop', |
609 | 'Socket', |
610 | 'SysvMessageQueue', |
611 | 'SysvSemaphore', |
612 | 'SysvSharedMemory', |
613 | 'UnhandledMatchError', |
614 | 'ValueError', |
615 | 'WeakMap', |
616 | 'XMLParser', |
617 | ], |
618 | 'interfaces' => |
619 | [ |
620 | 'BackedEnum', |
621 | 'DOMChildNode', |
622 | 'DOMParentNode', |
623 | 'Random\\CryptoSafeEngine', |
624 | 'Random\\Engine', |
625 | 'Stringable', |
626 | 'UnitEnum', |
627 | ], |
628 | 'traits' => |
629 | [ |
630 | ], |
631 | ], |
632 | '8.4' => |
633 | [ |
634 | 'classes' => |
635 | [ |
636 | 'DOM\\Document', |
637 | 'DOM\\HTMLDocument', |
638 | 'DOM\\XMLDocument', |
639 | 'dom\\attr', |
640 | 'dom\\cdatasection', |
641 | 'dom\\characterdata', |
642 | 'dom\\comment', |
643 | 'dom\\documentfragment', |
644 | 'dom\\documenttype', |
645 | 'dom\\domexception', |
646 | 'dom\\element', |
647 | 'dom\\entity', |
648 | 'dom\\entityreference', |
649 | 'dom\\namednodemap', |
650 | 'dom\\namespacenode', |
651 | 'dom\\node', |
652 | 'dom\\nodelist', |
653 | 'dom\\notation', |
654 | 'dom\\processinginstruction', |
655 | 'dom\\text', |
656 | 'dom\\xpath', |
657 | ], |
658 | 'interfaces' => |
659 | [ |
660 | 'dom\\childnode', |
661 | 'dom\\parentnode', |
662 | ], |
663 | 'traits' => |
664 | [ |
665 | ], |
666 | ], |
667 | ]; |
668 | |
669 | $flatArray = array(); |
670 | array_walk_recursive( |
671 | $builtins, |
672 | function ($array) use (&$flatArray) { |
673 | if (is_array($array)) { |
674 | $flatArray = array_merge($flatArray, array_values($array)); |
675 | } else { |
676 | $flatArray[] = $array; |
677 | } |
678 | } |
679 | ); |
680 | return $flatArray; |
681 | } |
682 | } |