Last active
April 19, 2024 18:25
-
-
Save cwhite92/f0aaf008e1679b27768fbb8c884df6f7 to your computer and use it in GitHub Desktop.
Get the FQCN from a PHP file specified by file path
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
public static function fqcnFromPath(string $path): string | |
{ | |
$namespace = $class = $buffer = ''; | |
$handle = fopen($path, 'r'); | |
while (!feof($handle)) { | |
$buffer .= fread($handle, 512); | |
// Suppress warnings for cases where `$buffer` ends in the middle of a PHP comment. | |
$tokens = @token_get_all($buffer); | |
// Filter out whitespace and comments from the tokens, as they are irrelevant. | |
$tokens = array_filter($tokens, fn($token) => $token[0] !== T_WHITESPACE && $token[0] !== T_COMMENT); | |
// Reset array indexes after filtering. | |
$tokens = array_values($tokens); | |
foreach ($tokens as $index => $token) { | |
// The namespace is a `T_NAME_QUALIFIED` that is immediately preceded by a `T_NAMESPACE`. | |
if ($token[0] === T_NAMESPACE && isset($tokens[$index + 1]) && $tokens[$index + 1][0] === T_NAME_QUALIFIED) { | |
$namespace = $tokens[$index + 1][1]; | |
continue; | |
} | |
// The class name is a `T_STRING` which makes it unreliable to match against, so check if we have a | |
// `T_CLASS` token with a `T_STRING` token ahead of it. | |
if ($token[0] === T_CLASS && isset($tokens[$index + 1]) && $tokens[$index + 1][0] === T_STRING) { | |
$class = $tokens[$index + 1][1]; | |
} | |
} | |
if ($namespace && $class) { | |
// We've found both the namespace and the class, we can now stop reading and parsing the file. | |
break; | |
} | |
} | |
fclose($handle); | |
return $namespace.'\\'.$class; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Based on my testing this works for the following examples:
and even some wonky whitespace or comments: