testify/tools/manifester.php

178 lines
5.3 KiB
PHP

<?php
/**
* Command line interface for generating autoload manifests
*
* @package Tools
* @version 1.0
* @since 1.0
*/
/**
* Command line tools
*/
require_once 'cli.php';
/**
* Prints usage
*/
function usage() {
$usage = new Usage(
'Manifest Builder 1.0',
'php ' . basename(__FIlE__),
'Builds a manifest file suitable for use by Autoloader',
'Tommy Montgomery',
'2009'
);
global $switches;
$usage->setSwitches($switches);
echo $usage;
}
if (!extension_loaded('tokenizer')) {
throw new Exception('The "tokenizer" extension must be loaded to use this script');
}
global $switches;
$switches = new CliSwitchCollection();
$switches->addSwitch(new CliSwitch('directory', 'd', true, 'dir1,dir2,...', 'Comma-delimited list of directories'))
->addSwitch(new CliSwitch('version', 'v', true, 'version_number', 'Version number for use in @version tag'))
->addSwitch(new CliSwitch('package', 'p', true, 'package_name ', 'Name of the package for use in @package tag'))
->addSwitch(new CliSwitch('output', 'o', false, 'file', 'Name of the output file, defaults to stdout if empty'))
->addSwitch(new CliSwitch('quiet', 'q', false, null, 'Do not print progress messages'))
->addSwitch(new CliSwitch('recursive', 'r', false, null, 'Recursively walk the directories'))
->addSwitch(new CliSwitch('ignore', 'i', false, 'pattern1,pattern2...', 'File patterns to ignore'))
->addSwitch(new CliSwitch('base-dir', 'b', true, 'dir', 'Base directory'));
array_shift($argv);
$args = Cli::parseArgs($argv, $switches);
$args = $args['switches']; //don't care about non-switch stuff
if (!isset($args['directory'], $args['version'], $args['package'], $args['base-dir'])) {
usage();
fwrite(STDERR, "Missing a required argument\n");
exit(1);
}
$dirs = explode(',', $args['directory']);
if (!is_dir($args['base-dir'])) {
fwrite(STDERR, $args['base-dir'] . ' is not a directory');
exit(1);
}
$args['recursive'] = array_key_exists('recursive', $args);
$args['quiet'] = array_key_exists('quiet', $args);
$date = date('Y-m-d H:i:s');
$self = basename(__FILE__);
$data = <<<ENDDATA
<?php
/**
* Autoload manifest
*
* Autogenerated by $self on $date
*
* @package $args[package]
* @version $args[version]
* @since 1.0
*/
return array(
ENDDATA;
$classes = array();
$maxClassNameLength = 0;
$ignore = array(DIRECTORY_SEPARATOR . '.');
if (isset($args['ignore']) && !empty($args['ignore'])) {
$ignore = array_merge($ignore, explode(',', $args['ignore']));
}
foreach ($dirs as $dir) {
if (!is_dir($dir)) {
fwrite(STDERR, $dir . ' is not a directory... skipping');
continue;
}
$iterator = $args['recursive'] ? new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)) : new DirectoryIterator($dir);
foreach ($iterator as $file) {
if (
$file->isFile() &&
strpos($file->getPathName(), DIRECTORY_SEPARATOR . '.') === false &&
substr($file->getFileName(), -4) === '.php' &&
array_reduce($ignore, create_function('$old, $new', 'return $old && strpos(\'' . addslashes($file->getPathName()) . '\', $new) === false;'), true)
) {
if (!$args['quiet']) {
echo 'Processing ' . $file->getPathName() . "\n";
}
$tokens = token_get_all(file_get_contents($file->getPathName()));
$count = count($tokens);
for ($i = 0; $i < $count; $i++) {
if (is_array($tokens[$i])) {
if ($tokens[$i][0] === T_CLASS || $tokens[$i][0] === T_INTERFACE) {
//get class name
if (isset($tokens[$i + 2]) && is_array($tokens[$i + 2]) && $tokens[$i + 2][0] === T_STRING) {
$className = $tokens[$i + 2][1];
if (isset($classes[$className]) && !$args['quiet']) {
fwrite(STDERR, '******WARNING: FOUND DUPLICATE CLASS (' . $className . ')******' . "\n");
}
$classes[$className] = ltrim(str_replace(array($args['base-dir'], DIRECTORY_SEPARATOR), array('', '/'), $file->getPathName()), '/');
$maxClassNameLength = max($maxClassNameLength, strlen($className));
$i += 2; //loop unroll FTW!
if (!$args['quiet']) {
echo 'Added class/interface ' . $className . "\n";
}
}
}
}
}
unset($tokens);
}
}
}
echo "\n" . '# of classes: ' . count($classes) . "\n\n";
$func = create_function(
'&$value, $key',
'$value = "\t\t\'$key\'" . str_repeat(\' \', ' . $maxClassNameLength . ' - strlen($key)) . " => \'$value\'";'
);
ksort($classes);
array_walk($classes, $func);
$data .= implode(",\n", $classes) . "\n\t);\n\n?>";
if (isset($args['output']) && !is_dir(dirname($args['output'])) && !mkdir(dirname($args['output']), 0777, true)) {
fwrite(STDERR, 'Unable to mkdir(): ' . dirname($args['output']));
exit(1);
} else if (!isset($args['output'])) {
$args['output'] = 'php://stdout';
}
if (is_dir($args['output'])) {
$args['output'] .= DIRECTORY_SEPARATOR . 'manifest.php';
}
$fp = fopen($args['output'], 'w');
if (!$fp) {
fwrite(STDERR, 'Unable to open ' . $args['output'] . ' for writing');
exit(1);
}
fwrite($fp, $data);
fclose($fp);
echo 'Wrote data to ' . $args['output'] . ' (' . strlen($data) . ' bytes)' . "\n";
exit(0);
?>