DependencyBuilder.php
<?php
class DependencyBuilder {
protected $dirs = [];
protected $excludeDirs = [];
protected $baseDir='';
public function __construct($baseDir=''){
$this->setBaseDir($baseDir);
}
public function setBaseDir($baseDir){
$this->baseDir = $baseDir;
}
public function addExcludeDir($dir){
$this->excludeDirs[] = $this->baseDir.'/'.$dir;
}
/**
* Add a directory inside the base dir
*/
public function addScanDir($dir){
$dir = $this->baseDir.'/'.$dir;
if (!is_dir($dir)){
trigger_error("Path '{$dir}' is not a directory.");
return;
}
$this->dirs[] = $dir;
}
public function build(){
$excludes = ['class'=>[],'file'=>[]];
$classmap = dirname(__DIR__).'/.cache/classmap.php';
$list = $this->getAllFiles();
// var_dump($list);
// exit;
$classes = $this->getAllClasses($list);
$classes = $this->sortClasses($classes);
$export = var_export($classes,true);
$php = "<?php return \n{$export}\n ?>";
file_put_contents($classmap,$php);
}
protected function sortClasses($classes){
uasort($classes,
function($a,$b){
$c1 = count($a);
$c2 = count($b);
return ($c2>$c1) ?? ($c2<$c1);
}
);
return $classes;
}
protected function getAllClasses($allFiles){
$lens = [];
$final = [];
foreach ($allFiles as $file){
if (strpos($file,'old')!==false)continue;
$class = $this->classFromFile($file);
if ($class=='')continue;
if (isset($excludes['class'][$class])
||isset($excludes['file'][$file]))continue;
$l = $lens[$class] ?? 0;
if ($l==false)$final[$class] = [];
if (($newL=strlen($file))<$l||$l==0){
$final[$class] = [];
array_unshift($final[$class],$file);
$lens[$class] = $newL;
} else {
// $final[$class][] = $file;
}
}
return $final;
}
protected function getAllFiles(){
// var_dump($this->dirs);exit;
$list=[];
foreach ($this->dirs as $resourceDir){
if (is_dir($resourceDir)){
$rii = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($resourceDir));
$files = array();
foreach ($rii as $file) {
// if ($file->isDir()){
// continue;
// }
if ($file->getExtension()=='php'){
$list[] = $file->getPathName();
}
}
}
}
return $list;
}
protected function classFromFile($file){
$expect = pathinfo($file,PATHINFO_FILENAME);
$fp = fopen($file, 'r');
$class = $namespace = $buffer = '';
$i = 0;
while (!$class||$expect!=$class) {
if (feof($fp)) break;
$buffer .= fread($fp, 512);
ob_start();
//suppress the token-message, since I'm not reading the full file
$tokens = @token_get_all($buffer);
$err = ob_get_clean();
// if (true&&strlen($err)>0){
// echo $buffer;
// echo $err."\n";
// echo $class."\n";
// echo "\n".$file;
// print_r($tokens);
// }
if (strpos($buffer, '{') === false) continue;
for (;$i<count($tokens);$i++) {
if ($tokens[$i][0] === T_NAMESPACE) {
for ($j=$i+1;$j<count($tokens); $j++) {
if ($tokens[$j][0] === T_STRING) {
$namespace .= '\\'.$tokens[$j][1];
} else if ($tokens[$j] === '{' || $tokens[$j] === ';') {
break;
}
}
}
if ($tokens[$i][0] === T_CLASS
|| $tokens[$i][0] === T_TRAIT
|| $tokens[$i][0] === T_INTERFACE
) {
for ($j=$i+1;$j<count($tokens);$j++) {
if ($tokens[$j] === '{') {
$class = @$tokens[$i+2][1];
}
}
}
}
}
if ($class=='')return '';
return $namespace.'\\'.$class;
}
}