Chris@0: Chris@0: * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) Chris@0: * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence Chris@0: * @link http://pear.php.net/package/PHP_CodeSniffer Chris@0: */ Chris@0: Chris@0: error_reporting(E_ALL | E_STRICT); Chris@0: Chris@0: // Make sure version id constant is available. Chris@0: if (defined('PHP_VERSION_ID') === false) { Chris@0: $version = explode('.', PHP_VERSION); Chris@0: define('PHP_VERSION_ID', (int) (($version[0] * 10000) + ($version[1] * 100) + $version[2])); Chris@0: unset($version); Chris@0: } Chris@0: Chris@0: // Make sure that we autoload all dependencies if running via Composer. Chris@0: if (PHP_VERSION_ID >= 50302) { Chris@0: if (file_exists($a = dirname(__FILE__).'/../../../autoload.php') === true) { Chris@0: include_once $a; Chris@0: } else if (file_exists($a = dirname(__FILE__).'/../vendor/autoload.php') === true) { Chris@0: include_once $a; Chris@0: } Chris@0: } Chris@0: Chris@0: if (file_exists($a = dirname(__FILE__).'/../CodeSniffer.php') === true) { Chris@0: // Running from a git clone. Chris@0: include_once $a; Chris@0: } else { Chris@0: // PEAR installed. Chris@0: include_once 'PHP/CodeSniffer.php'; Chris@0: } Chris@0: Chris@0: /** Chris@0: * A class to process command line phpcs scripts. Chris@0: * Chris@0: * @category PHP Chris@0: * @package PHP_CodeSniffer Chris@0: * @author Greg Sherwood Chris@0: * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) Chris@0: * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence Chris@0: * @version Release: @package_version@ Chris@0: * @link http://pear.php.net/package/PHP_CodeSniffer Chris@0: */ Chris@0: class PHP_CodeSniffer_CLI Chris@0: { Chris@0: Chris@0: /** Chris@0: * An array of all values specified on the command line. Chris@0: * Chris@0: * @var array Chris@0: */ Chris@0: protected $values = array(); Chris@0: Chris@0: /** Chris@0: * The minimum severity level errors must have to be displayed. Chris@0: * Chris@0: * @var bool Chris@0: */ Chris@0: public $errorSeverity = 0; Chris@0: Chris@0: /** Chris@0: * The minimum severity level warnings must have to be displayed. Chris@0: * Chris@0: * @var bool Chris@0: */ Chris@0: public $warningSeverity = 0; Chris@0: Chris@0: /** Chris@0: * Whether or not to kill the process when an unknown command line arg is found. Chris@0: * Chris@0: * If FALSE, arguments that are not command line options or file/directory paths Chris@0: * will be ignored and execution will continue. Chris@0: * Chris@0: * @var bool Chris@0: */ Chris@0: public $dieOnUnknownArg = true; Chris@0: Chris@0: /** Chris@0: * An array of the current command line arguments we are processing. Chris@0: * Chris@0: * @var array Chris@0: */ Chris@0: private $_cliArgs = array(); Chris@0: Chris@0: Chris@0: /** Chris@0: * Run the PHPCS script. Chris@0: * Chris@0: * @return array Chris@0: */ Chris@0: public function runphpcs() Chris@0: { Chris@0: if (defined('PHP_CODESNIFFER_CBF') === false) { Chris@0: define('PHP_CODESNIFFER_CBF', false); Chris@0: } Chris@0: Chris@0: if (is_file(dirname(__FILE__).'/../CodeSniffer/Reporting.php') === true) { Chris@0: include_once dirname(__FILE__).'/../CodeSniffer/Reporting.php'; Chris@0: } else { Chris@0: include_once 'PHP/CodeSniffer/Reporting.php'; Chris@0: } Chris@0: Chris@0: PHP_CodeSniffer_Reporting::startTiming(); Chris@0: $this->checkRequirements(); Chris@0: $numErrors = $this->process(); Chris@0: if ($numErrors === 0) { Chris@0: exit(0); Chris@0: } else { Chris@0: exit(1); Chris@0: } Chris@0: Chris@0: }//end runphpcs() Chris@0: Chris@0: Chris@0: /** Chris@0: * Run the PHPCBF script. Chris@0: * Chris@0: * @return array Chris@0: */ Chris@0: public function runphpcbf() Chris@0: { Chris@0: if (defined('PHP_CODESNIFFER_CBF') === false) { Chris@0: define('PHP_CODESNIFFER_CBF', true); Chris@0: } Chris@0: Chris@0: if (is_file(dirname(__FILE__).'/../CodeSniffer/Reporting.php') === true) { Chris@0: include_once dirname(__FILE__).'/../CodeSniffer/Reporting.php'; Chris@0: } else { Chris@0: include_once 'PHP/CodeSniffer/Reporting.php'; Chris@0: } Chris@0: Chris@0: PHP_CodeSniffer_Reporting::startTiming(); Chris@0: $this->checkRequirements(); Chris@0: Chris@0: $this->dieOnUnknownArg = false; Chris@0: Chris@0: // Override some of the command line settings that might break the fixes. Chris@0: $cliValues = $this->getCommandLineValues(); Chris@0: $cliValues['verbosity'] = 0; Chris@0: $cliValues['showProgress'] = false; Chris@0: $cliValues['generator'] = ''; Chris@0: $cliValues['explain'] = false; Chris@0: $cliValues['interactive'] = false; Chris@0: $cliValues['showSources'] = false; Chris@0: $cliValues['reportFile'] = null; Chris@0: $cliValues['reports'] = array(); Chris@0: Chris@0: $suffix = ''; Chris@0: if (isset($cliValues['suffix']) === true) { Chris@0: $suffix = $cliValues['suffix']; Chris@0: } Chris@0: Chris@0: $allowPatch = true; Chris@0: if (isset($cliValues['no-patch']) === true || empty($cliValues['files']) === true) { Chris@0: // They either asked for this, Chris@0: // or they are using STDIN, which can't use diff. Chris@0: $allowPatch = false; Chris@0: } Chris@0: Chris@0: if ($suffix === '' && $allowPatch === true) { Chris@0: // Using the diff/patch tools. Chris@0: $diffFile = getcwd().'/phpcbf-fixed.diff'; Chris@0: $cliValues['reports'] = array('diff' => $diffFile); Chris@0: if (file_exists($diffFile) === true) { Chris@0: unlink($diffFile); Chris@0: } Chris@0: } else { Chris@0: // Replace the file without the patch command Chris@0: // or writing to a file with a new suffix. Chris@0: $cliValues['reports'] = array('cbf' => null); Chris@0: $cliValues['phpcbf-suffix'] = $suffix; Chris@0: } Chris@0: Chris@0: $numErrors = $this->process($cliValues); Chris@0: Chris@0: if ($suffix === '' && $allowPatch === true) { Chris@0: if (file_exists($diffFile) === false) { Chris@0: // Nothing to fix. Chris@0: if ($numErrors === 0) { Chris@0: // And no errors reported. Chris@0: $exit = 0; Chris@0: } else { Chris@0: // Errors we can't fix. Chris@0: $exit = 2; Chris@0: } Chris@0: } else { Chris@0: if (filesize($diffFile) < 10) { Chris@0: // Empty or bad diff file. Chris@0: if ($numErrors === 0) { Chris@0: // And no errors reported. Chris@0: $exit = 0; Chris@0: } else { Chris@0: // Errors we can't fix. Chris@0: $exit = 2; Chris@0: } Chris@0: } else { Chris@0: $cmd = "patch -p0 -ui \"$diffFile\""; Chris@0: $output = array(); Chris@0: $retVal = null; Chris@0: exec($cmd, $output, $retVal); Chris@0: Chris@0: if ($retVal === 0) { Chris@0: // Everything went well. Chris@0: $filesPatched = count($output); Chris@0: echo "Patched $filesPatched file"; Chris@0: if ($filesPatched > 1) { Chris@0: echo 's'; Chris@0: } Chris@0: Chris@0: echo PHP_EOL; Chris@0: $exit = 1; Chris@0: } else { Chris@0: print_r($output); Chris@0: echo "Returned: $retVal".PHP_EOL; Chris@0: $exit = 3; Chris@0: } Chris@0: }//end if Chris@0: Chris@0: unlink($diffFile); Chris@0: }//end if Chris@0: } else { Chris@0: // File are being patched manually, so we can't tell Chris@0: // how many errors were fixed. Chris@0: $exit = 1; Chris@0: }//end if Chris@0: Chris@0: if ($exit === 0) { Chris@0: echo 'No fixable errors were found'.PHP_EOL; Chris@0: } else if ($exit === 2) { Chris@0: echo 'PHPCBF could not fix all the errors found'.PHP_EOL; Chris@0: } Chris@0: Chris@0: PHP_CodeSniffer_Reporting::printRunTime(); Chris@0: exit($exit); Chris@0: Chris@0: }//end runphpcbf() Chris@0: Chris@0: Chris@0: /** Chris@0: * Exits if the minimum requirements of PHP_CodSniffer are not met. Chris@0: * Chris@0: * @return array Chris@0: */ Chris@0: public function checkRequirements() Chris@0: { Chris@0: // Check the PHP version. Chris@0: if (PHP_VERSION_ID < 50102) { Chris@0: echo 'ERROR: PHP_CodeSniffer requires PHP version 5.1.2 or greater.'.PHP_EOL; Chris@0: exit(2); Chris@0: } Chris@0: Chris@0: if (extension_loaded('tokenizer') === false) { Chris@0: echo 'ERROR: PHP_CodeSniffer requires the tokenizer extension to be enabled.'.PHP_EOL; Chris@0: exit(2); Chris@0: } Chris@0: Chris@0: }//end checkRequirements() Chris@0: Chris@0: Chris@0: /** Chris@0: * Get a list of default values for all possible command line arguments. Chris@0: * Chris@0: * @return array Chris@0: */ Chris@0: public function getDefaults() Chris@0: { Chris@0: if (defined('PHP_CODESNIFFER_IN_TESTS') === true) { Chris@0: return array(); Chris@0: } Chris@0: Chris@0: // The default values for config settings. Chris@0: $defaults['files'] = array(); Chris@0: $defaults['standard'] = null; Chris@0: $defaults['verbosity'] = 0; Chris@0: $defaults['interactive'] = false; Chris@0: $defaults['colors'] = false; Chris@0: $defaults['explain'] = false; Chris@0: $defaults['local'] = false; Chris@0: $defaults['showSources'] = false; Chris@0: $defaults['extensions'] = array(); Chris@0: $defaults['sniffs'] = array(); Chris@0: $defaults['exclude'] = array(); Chris@0: $defaults['ignored'] = array(); Chris@0: $defaults['reportFile'] = null; Chris@0: $defaults['generator'] = ''; Chris@0: $defaults['reports'] = array(); Chris@0: $defaults['bootstrap'] = array(); Chris@0: $defaults['errorSeverity'] = null; Chris@0: $defaults['warningSeverity'] = null; Chris@0: $defaults['stdin'] = null; Chris@0: $defaults['stdinPath'] = ''; Chris@0: Chris@0: $reportFormat = PHP_CodeSniffer::getConfigData('report_format'); Chris@0: if ($reportFormat !== null) { Chris@0: $defaults['reports'][$reportFormat] = null; Chris@0: } Chris@0: Chris@0: $tabWidth = PHP_CodeSniffer::getConfigData('tab_width'); Chris@0: if ($tabWidth === null) { Chris@0: $defaults['tabWidth'] = 0; Chris@0: } else { Chris@0: $defaults['tabWidth'] = (int) $tabWidth; Chris@0: } Chris@0: Chris@0: $encoding = PHP_CodeSniffer::getConfigData('encoding'); Chris@0: if ($encoding === null) { Chris@0: $defaults['encoding'] = 'iso-8859-1'; Chris@0: } else { Chris@0: $defaults['encoding'] = strtolower($encoding); Chris@0: } Chris@0: Chris@0: $severity = PHP_CodeSniffer::getConfigData('severity'); Chris@0: if ($severity !== null) { Chris@0: $defaults['errorSeverity'] = (int) $severity; Chris@0: $defaults['warningSeverity'] = (int) $severity; Chris@0: } Chris@0: Chris@0: $severity = PHP_CodeSniffer::getConfigData('error_severity'); Chris@0: if ($severity !== null) { Chris@0: $defaults['errorSeverity'] = (int) $severity; Chris@0: } Chris@0: Chris@0: $severity = PHP_CodeSniffer::getConfigData('warning_severity'); Chris@0: if ($severity !== null) { Chris@0: $defaults['warningSeverity'] = (int) $severity; Chris@0: } Chris@0: Chris@0: $showWarnings = PHP_CodeSniffer::getConfigData('show_warnings'); Chris@0: if ($showWarnings !== null) { Chris@0: $showWarnings = (bool) $showWarnings; Chris@0: if ($showWarnings === false) { Chris@0: $defaults['warningSeverity'] = 0; Chris@0: } Chris@0: } Chris@0: Chris@0: $reportWidth = PHP_CodeSniffer::getConfigData('report_width'); Chris@0: if ($reportWidth !== null) { Chris@0: $defaults['reportWidth'] = $this->_validateReportWidth($reportWidth); Chris@0: } else { Chris@0: // Use function defaults. Chris@0: $defaults['reportWidth'] = null; Chris@0: } Chris@0: Chris@0: $showProgress = PHP_CodeSniffer::getConfigData('show_progress'); Chris@0: if ($showProgress === null) { Chris@0: $defaults['showProgress'] = false; Chris@0: } else { Chris@0: $defaults['showProgress'] = (bool) $showProgress; Chris@0: } Chris@0: Chris@0: $quiet = PHP_CodeSniffer::getConfigData('quiet'); Chris@0: if ($quiet === null) { Chris@0: $defaults['quiet'] = false; Chris@0: } else { Chris@0: $defaults['quiet'] = (bool) $quiet; Chris@0: } Chris@0: Chris@0: $colors = PHP_CodeSniffer::getConfigData('colors'); Chris@0: if ($colors === null) { Chris@0: $defaults['colors'] = false; Chris@0: } else { Chris@0: $defaults['colors'] = (bool) $colors; Chris@0: } Chris@0: Chris@0: if (PHP_CodeSniffer::isPharFile(dirname(dirname(__FILE__))) === true) { Chris@0: // If this is a phar file, check for the standard in the config. Chris@0: $standard = PHP_CodeSniffer::getConfigData('standard'); Chris@0: if ($standard !== null) { Chris@0: $defaults['standard'] = $standard; Chris@0: } Chris@0: } Chris@0: Chris@0: return $defaults; Chris@0: Chris@0: }//end getDefaults() Chris@0: Chris@0: Chris@0: /** Chris@0: * Gets the processed command line values. Chris@0: * Chris@0: * If the values have not yet been set, the values will be sourced Chris@0: * from the command line arguments. Chris@0: * Chris@0: * @return array Chris@0: */ Chris@0: public function getCommandLineValues() Chris@0: { Chris@0: if (empty($this->values) === false) { Chris@0: return $this->values; Chris@0: } Chris@0: Chris@0: $args = $_SERVER['argv']; Chris@0: array_shift($args); Chris@0: Chris@0: $this->setCommandLineValues($args); Chris@0: Chris@0: // Check for content on STDIN. Chris@0: $handle = fopen('php://stdin', 'r'); Chris@0: if (stream_set_blocking($handle, false) === true) { Chris@0: $fileContents = ''; Chris@0: while (($line = fgets($handle)) !== false) { Chris@0: $fileContents .= $line; Chris@0: usleep(10); Chris@0: } Chris@0: Chris@0: stream_set_blocking($handle, true); Chris@0: fclose($handle); Chris@0: if (trim($fileContents) !== '') { Chris@0: $this->values['stdin'] = $fileContents; Chris@0: } Chris@0: } Chris@0: Chris@0: return $this->values; Chris@0: Chris@0: }//end getCommandLineValues() Chris@0: Chris@0: Chris@0: /** Chris@0: * Set the command line values. Chris@0: * Chris@0: * @param array $args An array of command line arguments to process. Chris@0: * Chris@0: * @return void Chris@0: */ Chris@0: public function setCommandLineValues($args) Chris@0: { Chris@0: if (defined('PHP_CODESNIFFER_IN_TESTS') === true) { Chris@0: $this->values = array( Chris@0: 'stdin' => null, Chris@0: 'quiet' => true, Chris@0: ); Chris@0: } else if (empty($this->values) === true) { Chris@0: $this->values = $this->getDefaults(); Chris@0: } Chris@0: Chris@0: $this->_cliArgs = $args; Chris@0: $numArgs = count($args); Chris@0: Chris@0: for ($i = 0; $i < $numArgs; $i++) { Chris@0: $arg = $this->_cliArgs[$i]; Chris@0: if ($arg === '') { Chris@0: continue; Chris@0: } Chris@0: Chris@0: if ($arg{0} === '-') { Chris@0: if ($arg === '-' || $arg === '--') { Chris@0: // Empty argument, ignore it. Chris@0: continue; Chris@0: } Chris@0: Chris@0: if ($arg{1} === '-') { Chris@0: $this->processLongArgument(substr($arg, 2), $i); Chris@0: } else { Chris@0: $switches = str_split($arg); Chris@0: foreach ($switches as $switch) { Chris@0: if ($switch === '-') { Chris@0: continue; Chris@0: } Chris@0: Chris@0: $this->processShortArgument($switch, $i); Chris@0: } Chris@0: } Chris@0: } else { Chris@0: $this->processUnknownArgument($arg, $i); Chris@0: }//end if Chris@0: }//end for Chris@0: Chris@0: }//end setCommandLineValues() Chris@0: Chris@0: Chris@0: /** Chris@0: * Processes a short (-e) command line argument. Chris@0: * Chris@0: * @param string $arg The command line argument. Chris@0: * @param int $pos The position of the argument on the command line. Chris@0: * Chris@0: * @return void Chris@0: */ Chris@0: public function processShortArgument($arg, $pos) Chris@0: { Chris@0: switch ($arg) { Chris@0: case 'h': Chris@0: case '?': Chris@0: $this->printUsage(); Chris@0: exit(0); Chris@0: case 'i' : Chris@0: $this->printInstalledStandards(); Chris@0: exit(0); Chris@0: case 'v' : Chris@0: if ($this->values['quiet'] === true) { Chris@0: // Ignore when quiet mode is enabled. Chris@0: break; Chris@0: } Chris@0: Chris@0: if (isset($this->values['verbosity']) === false) { Chris@0: $this->values['verbosity'] = 1; Chris@0: } else { Chris@0: $this->values['verbosity']++; Chris@0: } Chris@0: break; Chris@0: case 'l' : Chris@0: $this->values['local'] = true; Chris@0: break; Chris@0: case 's' : Chris@0: $this->values['showSources'] = true; Chris@0: break; Chris@0: case 'a' : Chris@0: $this->values['interactive'] = true; Chris@0: break; Chris@0: case 'e': Chris@0: $this->values['explain'] = true; Chris@0: break; Chris@0: case 'p' : Chris@0: if ($this->values['quiet'] === true) { Chris@0: // Ignore when quiet mode is enabled. Chris@0: break; Chris@0: } Chris@0: Chris@0: $this->values['showProgress'] = true; Chris@0: break; Chris@0: case 'q' : Chris@0: // Quiet mode disables a few other settings as well. Chris@0: $this->values['quiet'] = true; Chris@0: $this->values['showProgress'] = false; Chris@0: $this->values['verbosity'] = 0; Chris@0: break; Chris@0: case 'd' : Chris@0: $ini = explode('=', $this->_cliArgs[($pos + 1)]); Chris@0: $this->_cliArgs[($pos + 1)] = ''; Chris@0: if (isset($ini[1]) === true) { Chris@0: ini_set($ini[0], $ini[1]); Chris@0: } else { Chris@0: ini_set($ini[0], true); Chris@0: } Chris@0: break; Chris@0: case 'n' : Chris@0: $this->values['warningSeverity'] = 0; Chris@0: break; Chris@0: case 'w' : Chris@0: $this->values['warningSeverity'] = null; Chris@0: break; Chris@0: default: Chris@0: if ($this->dieOnUnknownArg === false) { Chris@0: $this->values[$arg] = $arg; Chris@0: } else { Chris@0: $this->processUnknownArgument('-'.$arg, $pos); Chris@0: } Chris@0: }//end switch Chris@0: Chris@0: }//end processShortArgument() Chris@0: Chris@0: Chris@0: /** Chris@0: * Processes a long (--example) command line argument. Chris@0: * Chris@0: * @param string $arg The command line argument. Chris@0: * @param int $pos The position of the argument on the command line. Chris@0: * Chris@0: * @return void Chris@0: */ Chris@0: public function processLongArgument($arg, $pos) Chris@0: { Chris@0: switch ($arg) { Chris@0: case 'help': Chris@0: $this->printUsage(); Chris@0: exit(0); Chris@0: case 'version': Chris@0: echo 'PHP_CodeSniffer version '.PHP_CodeSniffer::VERSION.' ('.PHP_CodeSniffer::STABILITY.') '; Chris@0: echo 'by Squiz (http://www.squiz.net)'.PHP_EOL; Chris@0: exit(0); Chris@0: case 'colors': Chris@0: $this->values['colors'] = true; Chris@0: break; Chris@0: case 'no-colors': Chris@0: $this->values['colors'] = false; Chris@0: break; Chris@0: case 'config-set': Chris@0: if (isset($this->_cliArgs[($pos + 1)]) === false Chris@0: || isset($this->_cliArgs[($pos + 2)]) === false Chris@0: ) { Chris@0: echo 'ERROR: Setting a config option requires a name and value'.PHP_EOL.PHP_EOL; Chris@0: $this->printUsage(); Chris@0: exit(0); Chris@0: } Chris@0: Chris@0: $key = $this->_cliArgs[($pos + 1)]; Chris@0: $value = $this->_cliArgs[($pos + 2)]; Chris@0: $current = PHP_CodeSniffer::getConfigData($key); Chris@0: Chris@0: try { Chris@0: PHP_CodeSniffer::setConfigData($key, $value); Chris@0: } catch (Exception $e) { Chris@0: echo $e->getMessage().PHP_EOL; Chris@0: exit(2); Chris@0: } Chris@0: Chris@0: if ($current === null) { Chris@0: echo "Config value \"$key\" added successfully".PHP_EOL; Chris@0: } else { Chris@0: echo "Config value \"$key\" updated successfully; old value was \"$current\"".PHP_EOL; Chris@0: } Chris@0: exit(0); Chris@0: case 'config-delete': Chris@0: if (isset($this->_cliArgs[($pos + 1)]) === false) { Chris@0: echo 'ERROR: Deleting a config option requires the name of the option'.PHP_EOL.PHP_EOL; Chris@0: $this->printUsage(); Chris@0: exit(0); Chris@0: } Chris@0: Chris@0: $key = $this->_cliArgs[($pos + 1)]; Chris@0: $current = PHP_CodeSniffer::getConfigData($key); Chris@0: if ($current === null) { Chris@0: echo "Config value \"$key\" has not been set".PHP_EOL; Chris@0: } else { Chris@0: try { Chris@0: PHP_CodeSniffer::setConfigData($key, null); Chris@0: } catch (Exception $e) { Chris@0: echo $e->getMessage().PHP_EOL; Chris@0: exit(2); Chris@0: } Chris@0: Chris@0: echo "Config value \"$key\" removed successfully; old value was \"$current\"".PHP_EOL; Chris@0: } Chris@0: exit(0); Chris@0: case 'config-show': Chris@0: $data = PHP_CodeSniffer::getAllConfigData(); Chris@0: $this->printConfigData($data); Chris@0: exit(0); Chris@0: case 'runtime-set': Chris@0: if (isset($this->_cliArgs[($pos + 1)]) === false Chris@0: || isset($this->_cliArgs[($pos + 2)]) === false Chris@0: ) { Chris@0: echo 'ERROR: Setting a runtime config option requires a name and value'.PHP_EOL.PHP_EOL; Chris@0: $this->printUsage(); Chris@0: exit(0); Chris@0: } Chris@0: Chris@0: $key = $this->_cliArgs[($pos + 1)]; Chris@0: $value = $this->_cliArgs[($pos + 2)]; Chris@0: $this->_cliArgs[($pos + 1)] = ''; Chris@0: $this->_cliArgs[($pos + 2)] = ''; Chris@0: PHP_CodeSniffer::setConfigData($key, $value, true); Chris@0: break; Chris@0: default: Chris@0: if (substr($arg, 0, 7) === 'sniffs=') { Chris@0: $sniffs = explode(',', substr($arg, 7)); Chris@0: foreach ($sniffs as $sniff) { Chris@0: if (substr_count($sniff, '.') !== 2) { Chris@0: echo 'ERROR: The specified sniff code "'.$sniff.'" is invalid'.PHP_EOL.PHP_EOL; Chris@0: $this->printUsage(); Chris@0: exit(2); Chris@0: } Chris@0: } Chris@0: Chris@0: $this->values['sniffs'] = $sniffs; Chris@0: } else if (substr($arg, 0, 8) === 'exclude=') { Chris@0: $sniffs = explode(',', substr($arg, 8)); Chris@0: foreach ($sniffs as $sniff) { Chris@0: if (substr_count($sniff, '.') !== 2) { Chris@0: echo 'ERROR: The specified sniff code "'.$sniff.'" is invalid'.PHP_EOL.PHP_EOL; Chris@0: $this->printUsage(); Chris@0: exit(2); Chris@0: } Chris@0: } Chris@0: Chris@0: $this->values['exclude'] = $sniffs; Chris@0: } else if (substr($arg, 0, 10) === 'bootstrap=') { Chris@0: $files = explode(',', substr($arg, 10)); Chris@0: foreach ($files as $file) { Chris@0: $path = PHP_CodeSniffer::realpath($file); Chris@0: if ($path === false) { Chris@0: echo 'ERROR: The specified bootstrap file "'.$file.'" does not exist'.PHP_EOL.PHP_EOL; Chris@0: $this->printUsage(); Chris@0: exit(2); Chris@0: } Chris@0: Chris@0: $this->values['bootstrap'][] = $path; Chris@0: } Chris@0: } else if (substr($arg, 0, 10) === 'file-list=') { Chris@0: $fileList = substr($arg, 10); Chris@0: $path = PHP_CodeSniffer::realpath($fileList); Chris@0: if ($path === false) { Chris@0: echo 'ERROR: The specified file list "'.$file.'" does not exist'.PHP_EOL.PHP_EOL; Chris@0: $this->printUsage(); Chris@0: exit(2); Chris@0: } Chris@0: Chris@0: $files = file($path); Chris@0: foreach ($files as $inputFile) { Chris@0: $inputFile = trim($inputFile); Chris@0: Chris@0: // Skip empty lines. Chris@0: if ($inputFile === '') { Chris@0: continue; Chris@0: } Chris@0: Chris@0: $realFile = PHP_CodeSniffer::realpath($inputFile); Chris@0: if ($realFile === false) { Chris@0: echo 'ERROR: The specified file "'.$inputFile.'" does not exist'.PHP_EOL.PHP_EOL; Chris@0: $this->printUsage(); Chris@0: exit(2); Chris@0: } Chris@0: Chris@0: $this->values['files'][] = $realFile; Chris@0: } Chris@0: } else if (substr($arg, 0, 11) === 'stdin-path=') { Chris@0: $this->values['stdinPath'] = PHP_CodeSniffer::realpath(substr($arg, 11)); Chris@0: Chris@0: // It may not exist and return false instead, so just use whatever they gave us. Chris@0: if ($this->values['stdinPath'] === false) { Chris@0: $this->values['stdinPath'] = trim(substr($arg, 11)); Chris@0: } Chris@0: } else if (substr($arg, 0, 12) === 'report-file=') { Chris@0: $this->values['reportFile'] = PHP_CodeSniffer::realpath(substr($arg, 12)); Chris@0: Chris@0: // It may not exist and return false instead. Chris@0: if ($this->values['reportFile'] === false) { Chris@0: $this->values['reportFile'] = substr($arg, 12); Chris@0: Chris@0: $dir = dirname($this->values['reportFile']); Chris@0: if (is_dir($dir) === false) { Chris@0: echo 'ERROR: The specified report file path "'.$this->values['reportFile'].'" points to a non-existent directory'.PHP_EOL.PHP_EOL; Chris@0: $this->printUsage(); Chris@0: exit(2); Chris@0: } Chris@0: Chris@0: if ($dir === '.') { Chris@0: // Passed report file is a file in the current directory. Chris@0: $this->values['reportFile'] = getcwd().'/'.basename($this->values['reportFile']); Chris@0: } else { Chris@0: if ($dir{0} === '/') { Chris@0: // An absolute path. Chris@0: $dir = PHP_CodeSniffer::realpath($dir); Chris@0: } else { Chris@0: $dir = PHP_CodeSniffer::realpath(getcwd().'/'.$dir); Chris@0: } Chris@0: Chris@0: if ($dir !== false) { Chris@0: // Report file path is relative. Chris@0: $this->values['reportFile'] = $dir.'/'.basename($this->values['reportFile']); Chris@0: } Chris@0: } Chris@0: }//end if Chris@0: Chris@0: if (is_dir($this->values['reportFile']) === true) { Chris@0: echo 'ERROR: The specified report file path "'.$this->values['reportFile'].'" is a directory'.PHP_EOL.PHP_EOL; Chris@0: $this->printUsage(); Chris@0: exit(2); Chris@0: } Chris@0: } else if (substr($arg, 0, 13) === 'report-width=') { Chris@0: $this->values['reportWidth'] = $this->_validateReportWidth(substr($arg, 13)); Chris@0: } else if (substr($arg, 0, 7) === 'report=' Chris@0: || substr($arg, 0, 7) === 'report-' Chris@0: ) { Chris@0: if ($arg[6] === '-') { Chris@0: // This is a report with file output. Chris@0: $split = strpos($arg, '='); Chris@0: if ($split === false) { Chris@0: $report = substr($arg, 7); Chris@0: $output = null; Chris@0: } else { Chris@0: $report = substr($arg, 7, ($split - 7)); Chris@0: $output = substr($arg, ($split + 1)); Chris@0: if ($output === false) { Chris@0: $output = null; Chris@0: } else { Chris@0: $dir = dirname($output); Chris@0: if ($dir === '.') { Chris@0: // Passed report file is a filename in the current directory. Chris@0: $output = getcwd().'/'.basename($output); Chris@0: } else { Chris@0: if ($dir{0} === '/') { Chris@0: // An absolute path. Chris@0: $dir = PHP_CodeSniffer::realpath($dir); Chris@0: } else { Chris@0: $dir = PHP_CodeSniffer::realpath(getcwd().'/'.$dir); Chris@0: } Chris@0: Chris@0: if ($dir !== false) { Chris@0: // Report file path is relative. Chris@0: $output = $dir.'/'.basename($output); Chris@0: } Chris@0: } Chris@0: }//end if Chris@0: }//end if Chris@0: } else { Chris@0: // This is a single report. Chris@0: $report = substr($arg, 7); Chris@0: $output = null; Chris@0: }//end if Chris@0: Chris@0: $this->values['reports'][$report] = $output; Chris@0: } else if (substr($arg, 0, 9) === 'standard=') { Chris@0: $standards = trim(substr($arg, 9)); Chris@0: if ($standards !== '') { Chris@0: $this->values['standard'] = explode(',', $standards); Chris@0: } Chris@0: } else if (substr($arg, 0, 11) === 'extensions=') { Chris@0: if (isset($this->values['extensions']) === false) { Chris@0: $this->values['extensions'] = array(); Chris@0: } Chris@0: Chris@0: $this->values['extensions'] = array_merge($this->values['extensions'], explode(',', substr($arg, 11))); Chris@0: } else if (substr($arg, 0, 9) === 'severity=') { Chris@0: $this->values['errorSeverity'] = (int) substr($arg, 9); Chris@0: $this->values['warningSeverity'] = $this->values['errorSeverity']; Chris@0: } else if (substr($arg, 0, 15) === 'error-severity=') { Chris@0: $this->values['errorSeverity'] = (int) substr($arg, 15); Chris@0: } else if (substr($arg, 0, 17) === 'warning-severity=') { Chris@0: $this->values['warningSeverity'] = (int) substr($arg, 17); Chris@0: } else if (substr($arg, 0, 7) === 'ignore=') { Chris@0: // Split the ignore string on commas, unless the comma is escaped Chris@0: // using 1 or 3 slashes (\, or \\\,). Chris@0: $ignored = preg_split( Chris@0: '/(?<=(?values['ignored'][$pattern] = 'absolute'; Chris@0: } Chris@0: } else if (substr($arg, 0, 10) === 'generator=') { Chris@0: $this->values['generator'] = substr($arg, 10); Chris@0: } else if (substr($arg, 0, 9) === 'encoding=') { Chris@0: $this->values['encoding'] = strtolower(substr($arg, 9)); Chris@0: } else if (substr($arg, 0, 10) === 'tab-width=') { Chris@0: $this->values['tabWidth'] = (int) substr($arg, 10); Chris@0: } else { Chris@0: if ($this->dieOnUnknownArg === false) { Chris@0: $eqPos = strpos($arg, '='); Chris@0: if ($eqPos === false) { Chris@0: $this->values[$arg] = $arg; Chris@0: } else { Chris@0: $value = substr($arg, ($eqPos + 1)); Chris@0: $arg = substr($arg, 0, $eqPos); Chris@0: $this->values[$arg] = $value; Chris@0: } Chris@0: } else { Chris@0: $this->processUnknownArgument('--'.$arg, $pos); Chris@0: } Chris@0: }//end if Chris@0: Chris@0: break; Chris@0: }//end switch Chris@0: Chris@0: }//end processLongArgument() Chris@0: Chris@0: Chris@0: /** Chris@0: * Processes an unknown command line argument. Chris@0: * Chris@0: * Assumes all unknown arguments are files and folders to check. Chris@0: * Chris@0: * @param string $arg The command line argument. Chris@0: * @param int $pos The position of the argument on the command line. Chris@0: * Chris@0: * @return void Chris@0: */ Chris@0: public function processUnknownArgument($arg, $pos) Chris@0: { Chris@0: // We don't know about any additional switches; just files. Chris@0: if ($arg{0} === '-') { Chris@0: if ($this->dieOnUnknownArg === false) { Chris@0: return; Chris@0: } Chris@0: Chris@0: echo 'ERROR: option "'.$arg.'" not known.'.PHP_EOL.PHP_EOL; Chris@0: $this->printUsage(); Chris@0: exit(2); Chris@0: } Chris@0: Chris@0: $file = PHP_CodeSniffer::realpath($arg); Chris@0: if (file_exists($file) === false) { Chris@0: if ($this->dieOnUnknownArg === false) { Chris@0: return; Chris@0: } Chris@0: Chris@0: echo 'ERROR: The file "'.$arg.'" does not exist.'.PHP_EOL.PHP_EOL; Chris@0: $this->printUsage(); Chris@0: exit(2); Chris@0: } else { Chris@0: $this->values['files'][] = $file; Chris@0: } Chris@0: Chris@0: }//end processUnknownArgument() Chris@0: Chris@0: Chris@0: /** Chris@0: * Runs PHP_CodeSniffer over files and directories. Chris@0: * Chris@0: * @param array $values An array of values determined from CLI args. Chris@0: * Chris@0: * @return int The number of error and warning messages shown. Chris@0: * @see getCommandLineValues() Chris@0: */ Chris@0: public function process($values=array()) Chris@0: { Chris@0: if (empty($values) === true) { Chris@0: $values = $this->getCommandLineValues(); Chris@0: } else { Chris@0: $values = array_merge($this->getDefaults(), $values); Chris@0: $this->values = $values; Chris@0: } Chris@0: Chris@0: if ($values['generator'] !== '') { Chris@0: $phpcs = new PHP_CodeSniffer($values['verbosity']); Chris@0: if ($values['standard'] === null) { Chris@0: $values['standard'] = $this->validateStandard(null); Chris@0: } Chris@0: Chris@0: foreach ($values['standard'] as $standard) { Chris@0: $phpcs->generateDocs( Chris@0: $standard, Chris@0: $values['sniffs'], Chris@0: $values['generator'] Chris@0: ); Chris@0: } Chris@0: Chris@0: exit(0); Chris@0: } Chris@0: Chris@0: // If no standard is supplied, get the default. Chris@0: $values['standard'] = $this->validateStandard($values['standard']); Chris@0: foreach ($values['standard'] as $standard) { Chris@0: if (PHP_CodeSniffer::isInstalledStandard($standard) === false) { Chris@0: // They didn't select a valid coding standard, so help them Chris@0: // out by letting them know which standards are installed. Chris@0: echo 'ERROR: the "'.$standard.'" coding standard is not installed. '; Chris@0: $this->printInstalledStandards(); Chris@0: exit(2); Chris@0: } Chris@0: } Chris@0: Chris@0: if ($values['explain'] === true) { Chris@0: foreach ($values['standard'] as $standard) { Chris@0: $this->explainStandard($standard); Chris@0: } Chris@0: Chris@0: exit(0); Chris@0: } Chris@0: Chris@0: $phpcs = new PHP_CodeSniffer($values['verbosity'], null, null, null); Chris@0: $phpcs->setCli($this); Chris@0: $phpcs->initStandard($values['standard'], $values['sniffs'], $values['exclude']); Chris@0: $values = $this->values; Chris@0: Chris@0: $phpcs->setTabWidth($values['tabWidth']); Chris@0: $phpcs->setEncoding($values['encoding']); Chris@0: $phpcs->setInteractive($values['interactive']); Chris@0: Chris@0: // Set file extensions if they were specified. Otherwise, Chris@0: // let PHP_CodeSniffer decide on the defaults. Chris@0: if (empty($values['extensions']) === false) { Chris@0: $phpcs->setAllowedFileExtensions($values['extensions']); Chris@0: } Chris@0: Chris@0: // Set ignore patterns if they were specified. Chris@0: if (empty($values['ignored']) === false) { Chris@0: $ignorePatterns = array_merge($phpcs->getIgnorePatterns(), $values['ignored']); Chris@0: $phpcs->setIgnorePatterns($ignorePatterns); Chris@0: } Chris@0: Chris@0: // Set some convenience member vars. Chris@0: if ($values['errorSeverity'] === null) { Chris@0: $this->errorSeverity = PHPCS_DEFAULT_ERROR_SEV; Chris@0: } else { Chris@0: $this->errorSeverity = $values['errorSeverity']; Chris@0: } Chris@0: Chris@0: if ($values['warningSeverity'] === null) { Chris@0: $this->warningSeverity = PHPCS_DEFAULT_WARN_SEV; Chris@0: } else { Chris@0: $this->warningSeverity = $values['warningSeverity']; Chris@0: } Chris@0: Chris@0: if (empty($values['reports']) === true) { Chris@0: $values['reports']['full'] = $values['reportFile']; Chris@0: $this->values['reports'] = $values['reports']; Chris@0: } Chris@0: Chris@0: // Include bootstrap files. Chris@0: foreach ($values['bootstrap'] as $bootstrap) { Chris@0: include $bootstrap; Chris@0: } Chris@0: Chris@0: $phpcs->processFiles($values['files'], $values['local']); Chris@0: Chris@0: if (empty($values['files']) === true || $values['stdin'] !== null) { Chris@0: $fileContents = $values['stdin']; Chris@0: if ($fileContents === null) { Chris@0: // Check if they are passing in the file contents. Chris@0: $handle = fopen('php://stdin', 'r'); Chris@0: stream_set_blocking($handle, true); Chris@0: $fileContents = stream_get_contents($handle); Chris@0: fclose($handle); Chris@0: } Chris@0: Chris@0: if ($fileContents === '') { Chris@0: // No files and no content passed in. Chris@0: echo 'ERROR: You must supply at least one file or directory to process.'.PHP_EOL.PHP_EOL; Chris@0: $this->printUsage(); Chris@0: exit(2); Chris@0: } else { Chris@0: $this->values['stdin'] = $fileContents; Chris@0: $phpcs->processFile('STDIN', $fileContents); Chris@0: } Chris@0: } Chris@0: Chris@0: // Interactive runs don't require a final report and it doesn't really Chris@0: // matter what the retun value is because we know it isn't being read Chris@0: // by a script. Chris@0: if ($values['interactive'] === true) { Chris@0: return 0; Chris@0: } Chris@0: Chris@0: return $this->printErrorReport( Chris@0: $phpcs, Chris@0: $values['reports'], Chris@0: $values['showSources'], Chris@0: $values['reportFile'], Chris@0: $values['reportWidth'] Chris@0: ); Chris@0: Chris@0: }//end process() Chris@0: Chris@0: Chris@0: /** Chris@0: * Prints the error report for the run. Chris@0: * Chris@0: * Note that this function may actually print multiple reports Chris@0: * as the user may have specified a number of output formats. Chris@0: * Chris@0: * @param PHP_CodeSniffer $phpcs The PHP_CodeSniffer object containing Chris@0: * the errors. Chris@0: * @param array $reports A list of reports to print. Chris@0: * @param bool $showSources TRUE if report should show error sources Chris@0: * (not used by all reports). Chris@0: * @param string $reportFile A default file to log report output to. Chris@0: * @param int $reportWidth How wide the screen reports should be. Chris@0: * Chris@0: * @return int The number of error and warning messages shown. Chris@0: */ Chris@0: public function printErrorReport( Chris@0: PHP_CodeSniffer $phpcs, Chris@0: $reports, Chris@0: $showSources, Chris@0: $reportFile, Chris@0: $reportWidth Chris@0: ) { Chris@0: if (empty($reports) === true) { Chris@0: $reports['full'] = $reportFile; Chris@0: } Chris@0: Chris@0: $errors = 0; Chris@0: $warnings = 0; Chris@0: $toScreen = false; Chris@0: Chris@0: foreach ($reports as $report => $output) { Chris@0: if ($output === null) { Chris@0: $output = $reportFile; Chris@0: } Chris@0: Chris@0: if ($reportFile === null) { Chris@0: $toScreen = true; Chris@0: } Chris@0: Chris@0: // We don't add errors here because the number of Chris@0: // errors reported by each report type will always be the Chris@0: // same, so we really just need 1 number. Chris@0: $result = $phpcs->reporting->printReport( Chris@0: $report, Chris@0: $showSources, Chris@0: $this->values, Chris@0: $output, Chris@0: $reportWidth Chris@0: ); Chris@0: Chris@0: $errors = $result['errors']; Chris@0: $warnings = $result['warnings']; Chris@0: }//end foreach Chris@0: Chris@0: // Only print timer output if no reports were Chris@0: // printed to the screen so we don't put additional output Chris@0: // in something like an XML report. If we are printing to screen, Chris@0: // the report types would have already worked out who should Chris@0: // print the timer info. Chris@0: if (PHP_CODESNIFFER_INTERACTIVE === false Chris@0: && ($toScreen === false Chris@0: || (($errors + $warnings) === 0 && $this->values['showProgress'] === true)) Chris@0: ) { Chris@0: PHP_CodeSniffer_Reporting::printRunTime(); Chris@0: } Chris@0: Chris@0: // They should all return the same value, so it Chris@0: // doesn't matter which return value we end up using. Chris@0: $ignoreWarnings = PHP_CodeSniffer::getConfigData('ignore_warnings_on_exit'); Chris@0: $ignoreErrors = PHP_CodeSniffer::getConfigData('ignore_errors_on_exit'); Chris@0: Chris@0: $return = ($errors + $warnings); Chris@0: if ($ignoreErrors !== null) { Chris@0: $ignoreErrors = (bool) $ignoreErrors; Chris@0: if ($ignoreErrors === true) { Chris@0: $return -= $errors; Chris@0: } Chris@0: } Chris@0: Chris@0: if ($ignoreWarnings !== null) { Chris@0: $ignoreWarnings = (bool) $ignoreWarnings; Chris@0: if ($ignoreWarnings === true) { Chris@0: $return -= $warnings; Chris@0: } Chris@0: } Chris@0: Chris@0: return $return; Chris@0: Chris@0: }//end printErrorReport() Chris@0: Chris@0: Chris@0: /** Chris@0: * Convert the passed standards into valid standards. Chris@0: * Chris@0: * Checks things like default values and case. Chris@0: * Chris@0: * @param array $standards The standards to validate. Chris@0: * Chris@0: * @return array Chris@0: */ Chris@0: public function validateStandard($standards) Chris@0: { Chris@0: if ($standards === null) { Chris@0: // They did not supply a standard to use. Chris@0: // Look for a default ruleset in the current directory or higher. Chris@0: $currentDir = getcwd(); Chris@0: Chris@0: do { Chris@0: $default = $currentDir.DIRECTORY_SEPARATOR.'phpcs.xml'; Chris@0: if (is_file($default) === true) { Chris@0: return array($default); Chris@0: } Chris@0: Chris@0: $default = $currentDir.DIRECTORY_SEPARATOR.'phpcs.xml.dist'; Chris@0: if (is_file($default) === true) { Chris@0: return array($default); Chris@0: } Chris@0: Chris@0: $lastDir = $currentDir; Chris@0: $currentDir = dirname($currentDir); Chris@0: } while ($currentDir !== '.' && $currentDir !== $lastDir); Chris@0: Chris@0: // Try to get the default from the config system. Chris@0: $standard = PHP_CodeSniffer::getConfigData('default_standard'); Chris@0: if ($standard === null) { Chris@0: // Product default standard. Chris@0: $standard = 'PEAR'; Chris@0: } Chris@0: Chris@0: return explode(',', $standard); Chris@0: }//end if Chris@0: Chris@0: $cleaned = array(); Chris@0: $standards = (array) $standards; Chris@0: Chris@0: // Check if the standard name is valid, or if the case is invalid. Chris@0: $installedStandards = PHP_CodeSniffer::getInstalledStandards(); Chris@0: foreach ($standards as $standard) { Chris@0: foreach ($installedStandards as $validStandard) { Chris@0: if (strtolower($standard) === strtolower($validStandard)) { Chris@0: $standard = $validStandard; Chris@0: break; Chris@0: } Chris@0: } Chris@0: Chris@0: $cleaned[] = $standard; Chris@0: } Chris@0: Chris@0: return $cleaned; Chris@0: Chris@0: }//end validateStandard() Chris@0: Chris@0: Chris@0: /** Chris@0: * Prints a report showing the sniffs contained in a standard. Chris@0: * Chris@0: * @param string $standard The standard to validate. Chris@0: * Chris@0: * @return void Chris@0: */ Chris@0: public function explainStandard($standard) Chris@0: { Chris@0: $phpcs = new PHP_CodeSniffer(); Chris@0: $phpcs->process(array(), $standard); Chris@0: $sniffs = $phpcs->getSniffs(); Chris@0: $sniffs = array_keys($sniffs); Chris@0: sort($sniffs); Chris@0: Chris@0: ob_start(); Chris@0: Chris@0: $lastStandard = ''; Chris@0: $lastCount = ''; Chris@0: $sniffCount = count($sniffs); Chris@0: $sniffs[] = '___'; Chris@0: Chris@0: echo PHP_EOL."The $standard standard contains $sniffCount sniffs".PHP_EOL; Chris@0: Chris@0: ob_start(); Chris@0: Chris@0: foreach ($sniffs as $sniff) { Chris@0: $parts = explode('_', str_replace('\\', '_', $sniff)); Chris@0: if ($lastStandard === '') { Chris@0: $lastStandard = $parts[0]; Chris@0: } Chris@0: Chris@0: if ($parts[0] !== $lastStandard) { Chris@0: $sniffList = ob_get_contents(); Chris@0: ob_end_clean(); Chris@0: Chris@0: echo PHP_EOL.$lastStandard.' ('.$lastCount.' sniffs)'.PHP_EOL; Chris@0: echo str_repeat('-', (strlen($lastStandard.$lastCount) + 10)); Chris@0: echo PHP_EOL; Chris@0: echo $sniffList; Chris@0: Chris@0: $lastStandard = $parts[0]; Chris@0: $lastCount = 0; Chris@0: Chris@0: ob_start(); Chris@0: } Chris@0: Chris@0: echo ' '.$parts[0].'.'.$parts[2].'.'.substr($parts[3], 0, -5).PHP_EOL; Chris@0: $lastCount++; Chris@0: }//end foreach Chris@0: Chris@0: ob_end_clean(); Chris@0: Chris@0: }//end explainStandard() Chris@0: Chris@0: Chris@0: /** Chris@0: * Prints out the gathered config data. Chris@0: * Chris@0: * @param array $data The config data to print. Chris@0: * Chris@0: * @return void Chris@0: */ Chris@0: public function printConfigData($data) Chris@0: { Chris@0: $max = 0; Chris@0: $keys = array_keys($data); Chris@0: foreach ($keys as $key) { Chris@0: $len = strlen($key); Chris@0: if (strlen($key) > $max) { Chris@0: $max = $len; Chris@0: } Chris@0: } Chris@0: Chris@0: if ($max === 0) { Chris@0: return; Chris@0: } Chris@0: Chris@0: $max += 2; Chris@0: ksort($data); Chris@0: foreach ($data as $name => $value) { Chris@0: echo str_pad($name.': ', $max).$value.PHP_EOL; Chris@0: } Chris@0: Chris@0: }//end printConfigData() Chris@0: Chris@0: Chris@0: /** Chris@0: * Prints out the usage information for this script. Chris@0: * Chris@0: * @return void Chris@0: */ Chris@0: public function printUsage() Chris@0: { Chris@0: if (PHP_CODESNIFFER_CBF === true) { Chris@0: $this->printPHPCBFUsage(); Chris@0: } else { Chris@0: $this->printPHPCSUsage(); Chris@0: } Chris@0: Chris@0: }//end printUsage() Chris@0: Chris@0: Chris@0: /** Chris@0: * Prints out the usage information for PHPCS. Chris@0: * Chris@0: * @return void Chris@0: */ Chris@0: public function printPHPCSUsage() Chris@0: { Chris@0: echo 'Usage: phpcs [-nwlsaepqvi] [-d key[=value]] [--colors] [--no-colors] [--stdin-path=]'.PHP_EOL; Chris@0: echo ' [--report=] [--report-file=] [--report-=] ...'.PHP_EOL; Chris@0: echo ' [--report-width=] [--generator=] [--tab-width=]'.PHP_EOL; Chris@0: echo ' [--severity=] [--error-severity=] [--warning-severity=]'.PHP_EOL; Chris@0: echo ' [--runtime-set key value] [--config-set key value] [--config-delete key] [--config-show]'.PHP_EOL; Chris@0: echo ' [--standard=] [--sniffs=] [--exclude=] [--encoding=]'.PHP_EOL; Chris@0: echo ' [--extensions=] [--ignore=] [--bootstrap=]'.PHP_EOL; Chris@0: echo ' [--file-list=] ...'.PHP_EOL; Chris@0: echo ' Set runtime value (see --config-set) '.PHP_EOL; Chris@0: echo ' -n Do not print warnings (shortcut for --warning-severity=0)'.PHP_EOL; Chris@0: echo ' -w Print both warnings and errors (this is the default)'.PHP_EOL; Chris@0: echo ' -l Local directory only, no recursion'.PHP_EOL; Chris@0: echo ' -s Show sniff codes in all reports'.PHP_EOL; Chris@0: echo ' -a Run interactively'.PHP_EOL; Chris@0: echo ' -e Explain a standard by showing the sniffs it includes'.PHP_EOL; Chris@0: echo ' -p Show progress of the run'.PHP_EOL; Chris@0: echo ' -q Quiet mode; disables progress and verbose output'.PHP_EOL; Chris@0: echo ' -v[v][v] Print verbose output'.PHP_EOL; Chris@0: echo ' -i Show a list of installed coding standards'.PHP_EOL; Chris@0: echo ' -d Set the [key] php.ini value to [value] or [true] if value is omitted'.PHP_EOL; Chris@0: echo ' --help Print this help message'.PHP_EOL; Chris@0: echo ' --version Print version information'.PHP_EOL; Chris@0: echo ' --colors Use colors in output'.PHP_EOL; Chris@0: echo ' --no-colors Do not use colors in output (this is the default)'.PHP_EOL; Chris@0: echo ' One or more files and/or directories to check'.PHP_EOL; Chris@0: echo ' A file containing a list of files and/or directories to check (one per line)'.PHP_EOL; Chris@0: echo ' If processing STDIN, the file path that STDIN will be processed as '.PHP_EOL; Chris@0: echo ' A comma separated list of files to run before processing starts'.PHP_EOL; Chris@0: echo ' The encoding of the files being checked (default is iso-8859-1)'.PHP_EOL; Chris@0: echo ' A comma separated list of file extensions to check'.PHP_EOL; Chris@0: echo ' (extension filtering only valid when checking a directory)'.PHP_EOL; Chris@0: echo ' The type of the file can be specified using: ext/type'.PHP_EOL; Chris@0: echo ' e.g., module/php,es/js'.PHP_EOL; Chris@0: echo ' Uses either the "HTML", "Markdown" or "Text" generator'.PHP_EOL; Chris@0: echo ' (forces documentation generation instead of checking)'.PHP_EOL; Chris@0: echo ' A comma separated list of patterns to ignore files and directories'.PHP_EOL; Chris@0: echo ' Print either the "full", "xml", "checkstyle", "csv"'.PHP_EOL; Chris@0: echo ' "json", "emacs", "source", "summary", "diff", "junit"'.PHP_EOL; Chris@0: echo ' "svnblame", "gitblame", "hgblame" or "notifysend" report'.PHP_EOL; Chris@0: echo ' (the "full" report is printed by default)'.PHP_EOL; Chris@0: echo ' Write the report to the specified file path'.PHP_EOL; Chris@0: echo ' How many columns wide screen reports should be printed'.PHP_EOL; Chris@0: echo ' or set to "auto" to use current screen width, where supported'.PHP_EOL; Chris@0: echo ' A comma separated list of sniff codes to include or exclude during checking'.PHP_EOL; Chris@0: echo ' (all sniffs must be part of the specified standard)'.PHP_EOL; Chris@0: echo ' The minimum severity required to display an error or warning'.PHP_EOL; Chris@0: echo ' The name or path of the coding standard to use'.PHP_EOL; Chris@0: echo ' The number of spaces each tab represents'.PHP_EOL; Chris@0: Chris@0: }//end printPHPCSUsage() Chris@0: Chris@0: Chris@0: /** Chris@0: * Prints out the usage information for PHPCBF. Chris@0: * Chris@0: * @return void Chris@0: */ Chris@0: public function printPHPCBFUsage() Chris@0: { Chris@0: echo 'Usage: phpcbf [-nwli] [-d key[=value]] [--stdin-path=]'.PHP_EOL; Chris@0: echo ' [--standard=] [--sniffs=] [--exclude=] [--suffix=]'.PHP_EOL; Chris@0: echo ' [--severity=] [--error-severity=] [--warning-severity=]'.PHP_EOL; Chris@0: echo ' [--tab-width=] [--encoding=]'.PHP_EOL; Chris@0: echo ' [--extensions=] [--ignore=] [--bootstrap=]'.PHP_EOL; Chris@0: echo ' [--file-list=] ...'.PHP_EOL; Chris@0: echo ' -n Do not fix warnings (shortcut for --warning-severity=0)'.PHP_EOL; Chris@0: echo ' -w Fix both warnings and errors (on by default)'.PHP_EOL; Chris@0: echo ' -l Local directory only, no recursion'.PHP_EOL; Chris@0: echo ' -i Show a list of installed coding standards'.PHP_EOL; Chris@0: echo ' -d Set the [key] php.ini value to [value] or [true] if value is omitted'.PHP_EOL; Chris@0: echo ' --help Print this help message'.PHP_EOL; Chris@0: echo ' --version Print version information'.PHP_EOL; Chris@0: echo ' --no-patch Do not make use of the "diff" or "patch" programs'.PHP_EOL; Chris@0: echo ' One or more files and/or directories to fix'.PHP_EOL; Chris@0: echo ' A file containing a list of files and/or directories to fix (one per line)'.PHP_EOL; Chris@0: echo ' If processing STDIN, the file path that STDIN will be processed as '.PHP_EOL; Chris@0: echo ' A comma separated list of files to run before processing starts'.PHP_EOL; Chris@0: echo ' The encoding of the files being fixed (default is iso-8859-1)'.PHP_EOL; Chris@0: echo ' A comma separated list of file extensions to fix'.PHP_EOL; Chris@0: echo ' (extension filtering only valid when checking a directory)'.PHP_EOL; Chris@0: echo ' The type of the file can be specified using: ext/type'.PHP_EOL; Chris@0: echo ' e.g., module/php,es/js'.PHP_EOL; Chris@0: echo ' A comma separated list of patterns to ignore files and directories'.PHP_EOL; Chris@0: echo ' A comma separated list of sniff codes to include or exclude during fixing'.PHP_EOL; Chris@0: echo ' (all sniffs must be part of the specified standard)'.PHP_EOL; Chris@0: echo ' The minimum severity required to fix an error or warning'.PHP_EOL; Chris@0: echo ' The name or path of the coding standard to use'.PHP_EOL; Chris@0: echo ' Write modified files to a filename using this suffix'.PHP_EOL; Chris@0: echo ' ("diff" and "patch" are not used in this mode)'.PHP_EOL; Chris@0: echo ' The number of spaces each tab represents'.PHP_EOL; Chris@0: Chris@0: }//end printPHPCBFUsage() Chris@0: Chris@0: Chris@0: /** Chris@0: * Prints out a list of installed coding standards. Chris@0: * Chris@0: * @return void Chris@0: */ Chris@0: public function printInstalledStandards() Chris@0: { Chris@0: $installedStandards = PHP_CodeSniffer::getInstalledStandards(); Chris@0: $numStandards = count($installedStandards); Chris@0: Chris@0: if ($numStandards === 0) { Chris@0: echo 'No coding standards are installed.'.PHP_EOL; Chris@0: } else { Chris@0: $lastStandard = array_pop($installedStandards); Chris@0: if ($numStandards === 1) { Chris@0: echo "The only coding standard installed is $lastStandard".PHP_EOL; Chris@0: } else { Chris@0: $standardList = implode(', ', $installedStandards); Chris@0: $standardList .= ' and '.$lastStandard; Chris@0: echo 'The installed coding standards are '.$standardList.PHP_EOL; Chris@0: } Chris@0: } Chris@0: Chris@0: }//end printInstalledStandards() Chris@0: Chris@0: Chris@0: /** Chris@0: * Set report width based on terminal width. Chris@0: * Chris@0: * @param int $width The width of the report. If "auto" then will Chris@0: * be replaced by the terminal width. Chris@0: * Chris@0: * @return int Chris@0: */ Chris@0: private function _validateReportWidth($width) Chris@0: { Chris@0: if ($width === 'auto' Chris@0: && preg_match('|\d+ (\d+)|', shell_exec('stty size 2>&1'), $matches) === 1 Chris@0: ) { Chris@0: return (int) $matches[1]; Chris@0: } Chris@0: Chris@0: return (int) $width; Chris@0: Chris@0: }//end _validateReportWidth() Chris@0: Chris@0: Chris@0: }//end class