Skip to content

Instantly share code, notes, and snippets.

@wdolek
Created February 19, 2011 00:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wdolek/834678 to your computer and use it in GitHub Desktop.
Save wdolek/834678 to your computer and use it in GitHub Desktop.
<?php
/**
* CLI script to check whether php script paths correspond to class names.
* (Name Space File Name Checker)
*
* Naming of classes and file names should meet this standard proposal:
* http://groups.google.com/group/php-standards/web/psr-0-final-proposal
*
* Usage:
* php nsfnchecker.php /path/to/libs [<vendor name>]
* php nsfnchecker.php /home/wdolek/workspace/repos/nette Nette
*
* @author Zdenek Havlin aka wdolek
* @license "THE BEER-WARE LICENSE"
*/
// check input
if (!isset ($argv[1])) {
exit (1);
}
/**
* @param string $fileName
* @return array
* @throws Exception
*/
function getTokens($fileName) {
// check whether file exists
if (!file_exists($fileName)) {
throw new Exception('File not found');
}
// tokens
$fileContent = file_get_contents($fileName);
$tokensAll = token_get_all($fileContent);
// filter for classes and interfaces
$classes = array();
$validTokens = array(
T_CLASS,
T_INTERFACE,
T_NAMESPACE,
T_NS_SEPARATOR,
);
$_lastTokenType = null;
$_tokenCounter = -1;
foreach ($tokensAll as $token) {
// not token
if (!is_array($token)) {
continue;
}
$tokenType = $token[0];
$tokenValue = $token[1];
switch ($tokenType) {
case T_CLASS:
case T_INTERFACE:
case T_NAMESPACE:
++$_tokenCounter;
$classes[$_tokenCounter] = array(
$tokenType,
token_name($tokenType),
'',
);
$_lastTokenType = $tokenType;
break;
case T_NS_SEPARATOR:
if (in_array($_lastTokenType, array(T_CLASS, T_INTERFACE, T_NAMESPACE, T_STRING))) {
$_lastTokenType = $tokenType;
}
break;
case T_STRING:
if (!in_array($_lastTokenType, $validTokens) || !isset ($classes[$_tokenCounter][0]) || is_null($_lastTokenType)) {
continue;
}
if ($_lastTokenType == T_NS_SEPARATOR) {
$classes[$_tokenCounter][2] .= '\\' . $tokenValue;
} else {
$classes[$_tokenCounter][2] .= $tokenValue;
}
$_lastTokenType = $tokenType;
break;
default:
if (in_array($_lastTokenType, array(T_CLASS, T_INTERFACE, T_NAMESPACE))) {
continue;
}
$_lastTokenType = null;
break;
}
}
return $classes;
}
/**
* @param string $basePath base path of all files (/workspace/libs)
* @param string $tokenSourcePath path of file from (/workspace/libs/Nette/Utils/Foo.php)
* @param array $tokens
* @return array
*/
function processTokens($basePath, $tokenSourcePath, array $tokens) {
// unify path
$basePath = str_replace('\\', '/', $basePath);
$tokenSourcePath = str_replace('\\', '/', $tokenSourcePath);
// trim slash
$basePath = trim($basePath, '/');
$tokenSourcePath = trim($tokenSourcePath, '/');
// remove base path
if (strpos($tokenSourcePath, $basePath) === 0) {
$tokenSourcePath = str_replace($basePath, '', $tokenSourcePath);
$tokenSourcePath = trim($tokenSourcePath, '/');
}
// class name (file path/name implies class name)
$pathParts = explode('/', $tokenSourcePath);
$fileName =& $pathParts[count($pathParts) - 1];
$fileName = str_replace('.php', '', $fileName);
$className = implode('\\', $pathParts);
// process
$result = array();
$ns = null;
foreach ($tokens as $token) {
if ($token[0] == T_NAMESPACE) {
$ns = $token[2];
continue;
}
// checked class name
$cn = empty ($ns) ? $token[2] : ($ns . '\\' . $token[2]);
if ($cn == $className) {
array_push($result, sprintf('[ok] "%s" in "%s"',
$cn,
$tokenSourcePath
));
} else {
array_push($result, sprintf('[er] "%s" does not correspond to path "%s"',
$cn,
$tokenSourcePath
));
}
}
return $result;
}
// tokenize
$basePath = $argv[1];
$vendorName = isset ($argv[2]) ? $argv[2] : null;
$dir2check = new RecursiveDirectoryIterator($basePath . '/' . $vendorName);
$rdIterator = new RecursiveIteratorIterator($dir2check);
$reIterator = new RegexIterator($rdIterator, '/^.+\.php$/i', RecursiveRegexIterator::GET_MATCH);
$result = array();
foreach ($reIterator as $i) {
$result = array_merge(
$result,
processTokens($basePath, $i[0], getTokens($i[0]))
);
}
foreach ($result as $rmsg) {
echo $rmsg, PHP_EOL;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment