false, 'modules' => array(), 'quiet' => false, ); $help = "Usage: {$argv[0]} [options] file|path [file|path ...] Options: -b Set the base path for the scan. Useful if you want --base-path to scan individual files in a code base that don't live in the project's base directory. -h Display this usage information --help -m modulename Loads the requested scanning module. If this --module modulename parameter is not specified, all available modules will be loaded. -q Suppresses all progress output --quiet --svn Enables SVN integration "; class ScannerModule { var $faults; var $blame; function ScannerModule() { $this->faults = array(); $this->blame = array(); err( "Initializing " . get_class( $this ) . "...\n" ); } function fault( $object, $level, $reason = '' ) { global $config; $object['file'] = filename( $object['file'] ); $this->faults[] = array( 'object' => $object, 'level' => $level, 'reason' => $reason, 'svn' => ( $config['svn'] === true ) ? $this->blame[$object['line']] : '' ); } function parserCallback( $object ) { } function preScan( $filename ) { global $config; if( $config['svn'] === true ) { $this->blame = array(); $output = array(); exec( "svn blame '$filename' 2>/dev/null", $output, $result ); if( $result == 0 ) { foreach( $output as $line => $text ) { $matches = array(); preg_match( '/^\s*(\d+)\s+([^\s]+)/', $text, $matches ); $this->blame[$line + 1] = array( 'author' => $matches[2], 'revision' => $matches[1] ); } } } } function postScan( $filename ) { } } function _callback( $object ) { global $modules; foreach( $modules as $module ) { $module->parserCallback( $object ); } } function filename( $filename ) { global $base_path; $filename = realpath( $filename ); if( strpos( $filename, $base_path ) === 0 ) { $filename = substr( $filename, strlen( $base_path ) ); } return $filename; } function err( $string ) { global $stderr, $config; if( $config['quiet'] === false ) { fputs( $stderr, $string ); } } // Handle application arguments $files = array(); $base_path = false; for( $i = 1; $i < $argc; $i++ ) { switch( $argv[$i] ) { case '-b': case '--base-path': $new_base = $argv[++$i]; if( is_dir( $new_base ) ) { $base_path = realpath( $new_base ) . '/'; } break; case '-h': case '--help': die( $help ); break; case '-m': case '--module': $config['modules'][] = $argv[++$i]; break; case '-q': case '--quiet': $config['quiet'] = true; break; case '--svn': $config['svn'] = true; break; default: if( file_exists( $argv[$i] ) && strtolower( substr( $argv[$i], -4 ) ) == '.php' ) { $base_path = ( $base_path === false ) ? realpath( dirname( $argv[$i] ) ) . '/' : $base_path; $files[] = $argv[$i]; } else if( is_dir( $argv[$i] ) ) { $base_path = ( $base_path === false ) ? realpath( $argv[$i] ) . '/' : $base_path; exec( "find {$argv[$i]} -iname '*.php' 2>/dev/null", $output, $result ); $files = array_merge( $files, $output ); } } } if( count( $files ) == 0 ) { die( $help ); } // Dig into the modules folder and load up what we find $module_files = scandir( 'modules' ); foreach( $module_files as $module_file ) { if( strtolower( substr( $module_file, -4 ) ) == '.php' ) { $module = substr( $module_file, 0, strlen( $module_file ) - 4 ); if( count( $config['modules'] ) == 0 || ( in_array( $module, $config['modules'] ) ) ) { require_once( "modules/{$module_file}" ); } } } $parser = new PHPParser(); $parser->registerCallback( '_callback' ); err( "Parsing files...\n" ); $counter = 0; $total = count( $files ); $lastpct = 0; foreach( $files as $file ) { $counter++; if( $counter == 1 ) { err( 0 ); } else { $pct = intval( $counter / $total * 100 ); if( $pct != $lastpct && $pct % 2 == 0 ) { err( $pct % 10 == 0 ? $pct : '.' ); $lastpct = $pct; } } foreach( $modules as $module ) { $module->preScan( $file ); } $parser->parseFile( $file ); } err( "\n" ); foreach( $modules as $module ) { foreach( $module->faults as $fault ) { $svn = serialize( $fault['svn'] ); printf( "%s %s - %s\n -- %s:%d, %s r%d\n", get_class( $module ), $fault['level'], $fault['reason'], $fault['object']['file'], $fault['object']['line'], isset( $fault['svn']['author'] ) ? $fault['svn']['author'] : '?', isset( $fault['svn']['revision'] ) ? $fault['svn']['revision'] : '?' ); } } ?>