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