-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
ClassesInDirectories
to remove BetterReflection dependency
Replaced BetterReflection with native PHP directory and token functions for class discovery in `ClassesInDirectories.php`. This simplifies the dependency tree by removing the `roave/better-reflection` package from `composer.json`.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,51 +5,84 @@ | |
namespace Ray\MediaQuery; | ||
|
||
use Generator; | ||
use Roave\BetterReflection\BetterReflection; | ||
use Roave\BetterReflection\Reflector\DefaultReflector; | ||
use Roave\BetterReflection\SourceLocator\Type\AggregateSourceLocator; | ||
use Roave\BetterReflection\SourceLocator\Type\AutoloadSourceLocator; | ||
use Roave\BetterReflection\SourceLocator\Type\DirectoriesSourceLocator; | ||
|
||
use function assert; | ||
use function class_exists; | ||
use function interface_exists; | ||
use RecursiveDirectoryIterator; | ||
use RecursiveIteratorIterator; | ||
use SplFileInfo; | ||
|
||
final class ClassesInDirectories | ||
{ | ||
/** | ||
* get a list of all classes in the given directories. | ||
* | ||
* Based on: https://github.com/Roave/BetterReflection/blob/396a07c9d276cb9ffba581b24b2dadbb542d542e/demo/parsing-whole-directory/example2.php. | ||
* | ||
* @param list<string> $directories | ||
Check failure on line 15 in src/ClassesInDirectories.php GitHub Actions / cs / Coding Standards
|
||
* | ||
* @return Generator<int, class-string> | ||
* | ||
* This function code is taken from https://github.com/WyriHaximus/php-list-classes-in-directory/blob/master/src/functions.php | ||
* and modified for roave/better-reflection 5.x | ||
* | ||
* @see https://github.com/WyriHaximus/php-list-classes-in-directory | ||
* @psalm-suppress MixedReturnTypeCoercion | ||
* @phpstan-ignore-next-line/ | ||
*/ | ||
public static function list(string ...$directories): iterable | ||
public static function list(string ...$directories): Generator | ||
Check failure on line 18 in src/ClassesInDirectories.php GitHub Actions / sa / PHPStan
Check failure on line 18 in src/ClassesInDirectories.php GitHub Actions / sa / PHPStan
|
||
{ | ||
foreach ($directories as $directory) { | ||
$iterator = new RecursiveIteratorIterator( | ||
new RecursiveDirectoryIterator($directory) | ||
Check failure on line 22 in src/ClassesInDirectories.php GitHub Actions / cs / Coding Standards
|
||
); | ||
|
||
foreach ($iterator as $file) { | ||
Check failure on line 25 in src/ClassesInDirectories.php GitHub Actions / sa / Psalm
|
||
if (! $file instanceof SplFileInfo) { | ||
continue; | ||
} | ||
|
||
if ($file->getExtension() !== 'php') { | ||
continue; | ||
} | ||
|
||
$className = self::getClassFromFile($file->getRealPath()); | ||
if ($className === null) { | ||
continue; | ||
} | ||
|
||
if (class_exists($className) || interface_exists($className)) { | ||
Check failure on line 39 in src/ClassesInDirectories.php GitHub Actions / cs / Coding Standards
Check failure on line 39 in src/ClassesInDirectories.php GitHub Actions / cs / Coding Standards
Check failure on line 39 in src/ClassesInDirectories.php GitHub Actions / cs / Coding Standards
Check failure on line 39 in src/ClassesInDirectories.php GitHub Actions / cs / Coding Standards
Check failure on line 39 in src/ClassesInDirectories.php GitHub Actions / cs / Coding Standards
|
||
yield $className; | ||
} | ||
} | ||
} | ||
} | ||
|
||
private static function getClassFromFile(string $filePath): ?string | ||
Check failure on line 46 in src/ClassesInDirectories.php GitHub Actions / cs / Coding Standards
|
||
{ | ||
/** @var list<string> $directories */ | ||
$sourceLocator = new AggregateSourceLocator([ | ||
new DirectoriesSourceLocator( | ||
$directories, | ||
(new BetterReflection())->astLocator(), | ||
), | ||
// ↓ required to autoload parent classes/interface from another directory than /src (e.g. /vendor) | ||
new AutoloadSourceLocator((new BetterReflection())->astLocator()), | ||
]); | ||
|
||
foreach ((new DefaultReflector($sourceLocator))->reflectAllClasses() as $class) { | ||
$className = $class->getName(); | ||
assert(class_exists($className) || interface_exists($className)); | ||
|
||
yield $className; | ||
$content = file_get_contents($filePath); | ||
Check failure on line 48 in src/ClassesInDirectories.php GitHub Actions / cs / Coding Standards
|
||
if ($content === false) { | ||
return null; | ||
} | ||
|
||
$namespace = ''; | ||
$class = ''; | ||
$tokens = token_get_all($content); | ||
Check failure on line 55 in src/ClassesInDirectories.php GitHub Actions / cs / Coding Standards
|
||
$count = count($tokens); | ||
Check failure on line 56 in src/ClassesInDirectories.php GitHub Actions / cs / Coding Standards
|
||
|
||
for ($i = 0; $i < $count; $i++) { | ||
if (!isset($tokens[$i][0])) { | ||
Check failure on line 59 in src/ClassesInDirectories.php GitHub Actions / cs / Coding Standards
|
||
continue; | ||
} | ||
|
||
if ($tokens[$i][0] === T_NAMESPACE) { | ||
for ($j = $i + 1; $j < $count; $j++) { | ||
if ($tokens[$j][0] === T_NAME_QUALIFIED) { | ||
$namespace = $tokens[$j][1]; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
if ($tokens[$i][0] === T_CLASS || $tokens[$i][0] === T_INTERFACE) { | ||
for ($j = $i + 1; $j < $count; $j++) { | ||
if ($tokens[$j][0] === T_STRING) { | ||
$class = $tokens[$j][1]; | ||
break 2; | ||
} | ||
} | ||
} | ||
} | ||
|
||
if ($class === '') { | ||
return null; | ||
} | ||
|
||
return $namespace ? $namespace . '\\' . $class : $class; | ||
} | ||
} |