Skip to content

Instantly share code, notes, and snippets.

@asuth
Created January 11, 2011 04:34
Show Gist options
  • Save asuth/774026 to your computer and use it in GitHub Desktop.
Save asuth/774026 to your computer and use it in GitHub Desktop.
improvement to https://www.firehed.net/lint-check-all-php-files-syntax-validation so that it doesn't re-lint all your files
#!/opt/local/bin/php
<?php
// https://www.firehed.net/lint-check-all-php-files-syntax-validation
// with some modifications
// ===========
// = Globals =
// ===========
$count = 0; // total files checked
$changed = array();
$errors = array();
$options = setOptions(array(
'quiet' => false,
'recurse' => false,
));
$start = microtime(true);
// include the md5 of this file so
// a new cache is used when we change the file
$cache_path = __DIR__.'/php-lint-cache.'.md5_file(__FILE__).'.cache';
// this cache file saves md5-checksums of files
// so we don't have to re-lint already verified files
if (file_exists($cache_path))
require $cache_path;
else
$md5_cache_old = array();
if ($options['quiet']) {
ob_start();
}
// =============
// = Scan path =
// =============
$files = getPipedFiles();
$path = $_SERVER['PWD']; // Default to execution directory
echo "Running PHP Lint:\n";
// Piped files present
if ($files) {
foreach ($files as $file) {
checkFile("$path/$file");
}
}
// Use arguments
else {
if ($_SERVER['argc'] > 1) {
$last = end($_SERVER['argv']);
if (substr($last, 0, 1) != '-') {
$path = $last; // snag last argument, if it wasn't an option switch
}
}
if (is_dir($path)) {
checkDirectoryContents($path);
}
elseif (is_file($path)) {
checkFile($path);
}
else {
echo "$path is not a file or directory.\n";
showHelp() AND exit(1);
}
}
if ($options['quiet']) {
ob_end_clean();
}
$time = microtime(true) - $start;
echo "\n$count total files checked, ".count($changed)." changed files, ".count($errors).' errors; took '.number_format($time, 3).' seconds';
if ($changed)
echo "\nChanged php files:\n\t", implode($changed, "\n\t");
if ($errors)
echo "\n*********************\nFiles with ERRORS:\n\t", implode($errors, "\n\t")."\n*********************";
else
echo "\nNO ERRORS";
echo "\n";
file_put_contents($cache_path, "<?php \$md5_cache_old = ".var_export($md5_cache_new, true)." ?>");
if (empty($errors))
exit(0); // exit successfully
else
exit(1); // exit unsuccessfully
function checkDirectoryContents($dir) {
global $options, $i, $errors, $count;
$contents = scandir($dir);
foreach($contents as $content) {
if ( $content == '.' ||
$content == '..') {
continue;
}
$path = "$dir/$content";
// Recurse into directories
if (is_dir($path) && $options['recurse']) {
checkDirectoryContents($path);
} // if is_dir
else {
// Skip non-php files
if (substr($path, -4) != '.php') {
continue;
}
checkFile($path);
} // !is_dir
} // foreach
} // function checkDirectoryContents
function checkFile($path) {
global $count, $errors, $md5_cache_old, $md5_cache_new, $changed;
if (($count % 80 == 0)) {
echo "\n";
}
$md5 = md5_file($path);
// check md5_cache to see if we've already linted this file
if (isset($md5_cache_old[$md5])) :
$error = $md5_cache_old[$md5];
else :
exec('php -l ' . escapeshellarg( $path ) . ' 2> /dev/null', $output, $return);
if ($return === 0) : // php -l gives a 0 error code if everything went well
$error = false;
else :
array_shift($output); // first line is always blank
array_pop($output); // the last line is always "Errors parsing httpdocs/test.php"
$error = implode("\n", $output);
endif;
$changed[] = $path;
endif;
$md5_cache_new[$md5] = $error;
if ($error) {
$errors[] = $error;
echo 'E';
} else {
echo ".";
}
$count++;
}
function getPipedFiles() {
$files = array();
stream_set_blocking(STDIN,FALSE);
while ($line = trim(fgets(STDIN))) {
$files[] = $line;
}
return $files;
}
function setOptions($options) {
$args = array_keys(getopt('qRh', array('quiet', 'recursive', 'help')));
foreach ($args as $arg) {
switch ($arg) {
case 'q':
case 'quiet':
$options['quiet'] = true;
break;
case 'R':
case 'recursive':
$options['recurse'] = true;
break;
case 'h':
case 'help':
default:
showHelp() AND exit(0);
} // Switch
} // Foreach args
return $options;
} // function setOptions
function showHelp() {
echo <<<HELP
usage: lint [-qR] [path]
options:
-q, --quiet: disable verbose output
-R, --recursive: recurse into subdirectories
-h, --help: display this help screen
HELP;
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment