Skip to content

Instantly share code, notes, and snippets.

@soyuka
Created January 17, 2024 21:30
Show Gist options
  • Save soyuka/2c0310a43ff0b82d0ec40236f0d7490b to your computer and use it in GitHub Desktop.
Save soyuka/2c0310a43ff0b82d0ec40236f0d7490b to your computer and use it in GitHub Desktop.
components dependencies php
<?php
namespace Components;
use Symfony\Component\Finder\Finder;
$loader = require './vendor/autoload.php';
$namespace = 'ApiPlatform';
$prefix = 'api-platform';
$lnamespace = strlen($namespace);
$ignoreList = ['ApiPlatform\\Api', 'ApiPlatform\\Exception', 'ApiPlatform\\Util'];
$class_uses_namespaces = function(\ReflectionClass $r) use ($namespace, $lnamespace): \Generator {
$fp = fopen($r->getFileName(), 'r');
$u = 'use';
$c = false;
while (($buffer = fgets($fp, 4096)) !== false) {
if ($c && $buffer === PHP_EOL) {
break;
}
if (strncmp($buffer, $u, 3) !== 0) {
continue;
}
$c = true;
$buffer = substr($buffer, 4, -2);
if (strncmp($buffer, $namespace, $lnamespace) === 0) {
yield $buffer;
}
}
fclose($fp);
};
$directories = [];
$map = [];
foreach (Finder::create()->in('src')->notPath('vendor')->name('composer.json') as $f) {
if (null === ($component = json_decode($f->getContents(), true))) {
continue;
}
$filter = fn ($v) => 0 === strncmp($v, $prefix, 12);
$dependencies = (
array_filter(array_keys((array) $component['require']), $filter) +
array_filter(array_keys((array) $component['require-dev'] ?? []), $filter)
);
$map[$component['name']] = ['namespace' => substr(key($component['autoload']['psr-4']), 0, -1), 'dependencies' => $dependencies];
$directories[] = substr($f->getRealPath(), 0, -14);
foreach (Finder::create()->in($f->getPath())->name('*.php')->notName('*.tpl.php') as $f) {
require_once $f->getRealPath();
}
}
// create a PSR map of dependencies
$psrMap = [];
foreach ($map as $component) {
$depsPsr = [];
foreach ($component['dependencies'] as $d) {
$depsPsr[] = $map[$d]['namespace'];
}
$psrMap[$component['namespace']] = $depsPsr;
}
$exitCode = 0;
foreach (array_merge(get_declared_classes(), get_declared_interfaces(), get_declared_traits()) as $className) {
if (strncmp($className, $namespace, $lnamespace) !== 0) {
continue;
}
$r = new \ReflectionClass($className);
$ns = $r->getNamespaceName();
if (!isset($psrMap[$ns])) {
$ns = substr($ns, 0, strpos($ns, '\\', $lnamespace + 1));
if (!isset($psrMap[$ns])) {
continue;
}
}
foreach ($class_uses_namespaces($r) as $u) {
if (0 === strncmp($u, $ns, strlen($ns))) {
continue;
}
$useNs = substr($u, 0, strpos($u, '\\', $lnamespace + 1));
if (in_array($useNs, $ignoreList)) {
continue;
}
if (!in_array($useNs, $psrMap[$ns])) {
echo sprintf('"%s" uses "%s" although "%s" is not one of its dependencies', $className, $u, $useNs) . PHP_EOL;
$exitCode = 1;
}
}
}
exit($exitCode);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment