I've been reading through the following somewhat similar questions:
But those are specific to class names only. I'm wondering if there is an efficient way (using token_get_all()
or otherwise) to retrieve all the methods contained in all the classes within a specific folder?
My initial thoughts are that I could traverse the directory using the FilesystemIterator
, then use the ReflectionClass
to create instances of each one. Alternatively I could include
each class if it hasn't been declared already, then use a combination of get_declared_classes
and get_class_methods
... But both of these seem like bad ideas as they would consume a lot of memory. Is there a more efficient way?
EDIT: My attempt using token_get_all()
function getDirectoryList($dir) {
$dirList = $fileList = [];
$iter = new FilesystemIterator($dir, FilesystemIterator::SKIP_DOTS);
foreach ($iter as $file) {
if ($file->isDir()) {
$dirList[$file->getFilename()] = getDirectoryList($file->getPathname());
} else {
$fileList[$file->getFilename()] = $file->getFilename();
}
}
uksort($dirList, 'strnatcmp');
natsort($fileList);
return $dirList + $fileList;
}
$path = '/var/www/html/dev/lib/framework/controllers';
$classes = getDirectoryList($path);
foreach ($classes as $class) {
$file = $path . '/' . $class;
echo $file . '<br />';
$fp = fopen($file, 'r');
$method = $namespace = $buffer = '';
$i = 0;
while (!feof($fp)) {
$buffer .= fread($fp, 512);
$tokens = token_get_all($buffer);
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_FUNCTION) {
for ($j=$i+1;$j<count($tokens);$j++) {
if ($tokens[$j] === '{') {
$method = $tokens[$i+2][1];
}
}
}
}
echo '<pre>';
var_dump($method);
echo '</pre>';
}
}
This gives me output as follows:
/var/www/html/dev/lib/framework/controllers/AuthController.php
string(8) "register"
string(14) "registerSubmit"
string(14) "registerSubmit"
string(14) "registerSubmit"
string(14) "registerSubmit"
string(14) "registerSubmit"
string(14) "registerSubmit"
string(14) "registerSubmit"
string(14) "registerSubmit"
string(5) "login"
string(5) "login"
string(5) "login"
string(5) "login"
string(5) "login"
string(5) "login"
string(6) "logout"
string(6) "verify"
string(6) "verify"
string(6) "verify"
string(6) "verify"
string(12) "verifySubmit"
string(12) "verifySubmit"
string(12) "verifySubmit"
string(12) "verifySubmit"
string(12) "verifySubmit"
string(12) "verifySubmit"
string(12) "verifySubmit"
Several of the methods are repeated. Also, it doesn't seem to catch all of the methods, for example loginSubmit
should be listed. Here is a pastebin of the whole class as a reference. And I'm still not sure if this is even the most efficient way to do it?