Drupal investigation

CLI.php 52KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445
  1. <?php
  2. /**
  3. * A class to process command line phpcs scripts.
  4. *
  5. * PHP version 5
  6. *
  7. * @category PHP
  8. * @package PHP_CodeSniffer
  9. * @author Greg Sherwood <gsherwood@squiz.net>
  10. * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
  11. * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
  12. * @link http://pear.php.net/package/PHP_CodeSniffer
  13. */
  14. error_reporting(E_ALL | E_STRICT);
  15. // Make sure version id constant is available.
  16. if (defined('PHP_VERSION_ID') === false) {
  17. $version = explode('.', PHP_VERSION);
  18. define('PHP_VERSION_ID', (int) (($version[0] * 10000) + ($version[1] * 100) + $version[2]));
  19. unset($version);
  20. }
  21. // Make sure that we autoload all dependencies if running via Composer.
  22. if (PHP_VERSION_ID >= 50302) {
  23. if (file_exists($a = dirname(__FILE__).'/../../../autoload.php') === true) {
  24. include_once $a;
  25. } else if (file_exists($a = dirname(__FILE__).'/../vendor/autoload.php') === true) {
  26. include_once $a;
  27. }
  28. }
  29. if (file_exists($a = dirname(__FILE__).'/../CodeSniffer.php') === true) {
  30. // Running from a git clone.
  31. include_once $a;
  32. } else {
  33. // PEAR installed.
  34. include_once 'PHP/CodeSniffer.php';
  35. }
  36. /**
  37. * A class to process command line phpcs scripts.
  38. *
  39. * @category PHP
  40. * @package PHP_CodeSniffer
  41. * @author Greg Sherwood <gsherwood@squiz.net>
  42. * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
  43. * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
  44. * @version Release: @package_version@
  45. * @link http://pear.php.net/package/PHP_CodeSniffer
  46. */
  47. class PHP_CodeSniffer_CLI
  48. {
  49. /**
  50. * An array of all values specified on the command line.
  51. *
  52. * @var array
  53. */
  54. protected $values = array();
  55. /**
  56. * The minimum severity level errors must have to be displayed.
  57. *
  58. * @var bool
  59. */
  60. public $errorSeverity = 0;
  61. /**
  62. * The minimum severity level warnings must have to be displayed.
  63. *
  64. * @var bool
  65. */
  66. public $warningSeverity = 0;
  67. /**
  68. * Whether or not to kill the process when an unknown command line arg is found.
  69. *
  70. * If FALSE, arguments that are not command line options or file/directory paths
  71. * will be ignored and execution will continue.
  72. *
  73. * @var bool
  74. */
  75. public $dieOnUnknownArg = true;
  76. /**
  77. * An array of the current command line arguments we are processing.
  78. *
  79. * @var array
  80. */
  81. private $_cliArgs = array();
  82. /**
  83. * Run the PHPCS script.
  84. *
  85. * @return array
  86. */
  87. public function runphpcs()
  88. {
  89. if (defined('PHP_CODESNIFFER_CBF') === false) {
  90. define('PHP_CODESNIFFER_CBF', false);
  91. }
  92. if (is_file(dirname(__FILE__).'/../CodeSniffer/Reporting.php') === true) {
  93. include_once dirname(__FILE__).'/../CodeSniffer/Reporting.php';
  94. } else {
  95. include_once 'PHP/CodeSniffer/Reporting.php';
  96. }
  97. PHP_CodeSniffer_Reporting::startTiming();
  98. $this->checkRequirements();
  99. $numErrors = $this->process();
  100. if ($numErrors === 0) {
  101. exit(0);
  102. } else {
  103. exit(1);
  104. }
  105. }//end runphpcs()
  106. /**
  107. * Run the PHPCBF script.
  108. *
  109. * @return array
  110. */
  111. public function runphpcbf()
  112. {
  113. if (defined('PHP_CODESNIFFER_CBF') === false) {
  114. define('PHP_CODESNIFFER_CBF', true);
  115. }
  116. if (is_file(dirname(__FILE__).'/../CodeSniffer/Reporting.php') === true) {
  117. include_once dirname(__FILE__).'/../CodeSniffer/Reporting.php';
  118. } else {
  119. include_once 'PHP/CodeSniffer/Reporting.php';
  120. }
  121. PHP_CodeSniffer_Reporting::startTiming();
  122. $this->checkRequirements();
  123. $this->dieOnUnknownArg = false;
  124. // Override some of the command line settings that might break the fixes.
  125. $cliValues = $this->getCommandLineValues();
  126. $cliValues['verbosity'] = 0;
  127. $cliValues['showProgress'] = false;
  128. $cliValues['generator'] = '';
  129. $cliValues['explain'] = false;
  130. $cliValues['interactive'] = false;
  131. $cliValues['showSources'] = false;
  132. $cliValues['reportFile'] = null;
  133. $cliValues['reports'] = array();
  134. $suffix = '';
  135. if (isset($cliValues['suffix']) === true) {
  136. $suffix = $cliValues['suffix'];
  137. }
  138. $allowPatch = true;
  139. if (isset($cliValues['no-patch']) === true || empty($cliValues['files']) === true) {
  140. // They either asked for this,
  141. // or they are using STDIN, which can't use diff.
  142. $allowPatch = false;
  143. }
  144. if ($suffix === '' && $allowPatch === true) {
  145. // Using the diff/patch tools.
  146. $diffFile = getcwd().'/phpcbf-fixed.diff';
  147. $cliValues['reports'] = array('diff' => $diffFile);
  148. if (file_exists($diffFile) === true) {
  149. unlink($diffFile);
  150. }
  151. } else {
  152. // Replace the file without the patch command
  153. // or writing to a file with a new suffix.
  154. $cliValues['reports'] = array('cbf' => null);
  155. $cliValues['phpcbf-suffix'] = $suffix;
  156. }
  157. $numErrors = $this->process($cliValues);
  158. if ($suffix === '' && $allowPatch === true) {
  159. if (file_exists($diffFile) === false) {
  160. // Nothing to fix.
  161. if ($numErrors === 0) {
  162. // And no errors reported.
  163. $exit = 0;
  164. } else {
  165. // Errors we can't fix.
  166. $exit = 2;
  167. }
  168. } else {
  169. if (filesize($diffFile) < 10) {
  170. // Empty or bad diff file.
  171. if ($numErrors === 0) {
  172. // And no errors reported.
  173. $exit = 0;
  174. } else {
  175. // Errors we can't fix.
  176. $exit = 2;
  177. }
  178. } else {
  179. $cmd = "patch -p0 -ui \"$diffFile\"";
  180. $output = array();
  181. $retVal = null;
  182. exec($cmd, $output, $retVal);
  183. if ($retVal === 0) {
  184. // Everything went well.
  185. $filesPatched = count($output);
  186. echo "Patched $filesPatched file";
  187. if ($filesPatched > 1) {
  188. echo 's';
  189. }
  190. echo PHP_EOL;
  191. $exit = 1;
  192. } else {
  193. print_r($output);
  194. echo "Returned: $retVal".PHP_EOL;
  195. $exit = 3;
  196. }
  197. }//end if
  198. unlink($diffFile);
  199. }//end if
  200. } else {
  201. // File are being patched manually, so we can't tell
  202. // how many errors were fixed.
  203. $exit = 1;
  204. }//end if
  205. if ($exit === 0) {
  206. echo 'No fixable errors were found'.PHP_EOL;
  207. } else if ($exit === 2) {
  208. echo 'PHPCBF could not fix all the errors found'.PHP_EOL;
  209. }
  210. PHP_CodeSniffer_Reporting::printRunTime();
  211. exit($exit);
  212. }//end runphpcbf()
  213. /**
  214. * Exits if the minimum requirements of PHP_CodSniffer are not met.
  215. *
  216. * @return array
  217. */
  218. public function checkRequirements()
  219. {
  220. // Check the PHP version.
  221. if (PHP_VERSION_ID < 50102) {
  222. echo 'ERROR: PHP_CodeSniffer requires PHP version 5.1.2 or greater.'.PHP_EOL;
  223. exit(2);
  224. }
  225. if (extension_loaded('tokenizer') === false) {
  226. echo 'ERROR: PHP_CodeSniffer requires the tokenizer extension to be enabled.'.PHP_EOL;
  227. exit(2);
  228. }
  229. }//end checkRequirements()
  230. /**
  231. * Get a list of default values for all possible command line arguments.
  232. *
  233. * @return array
  234. */
  235. public function getDefaults()
  236. {
  237. if (defined('PHP_CODESNIFFER_IN_TESTS') === true) {
  238. return array();
  239. }
  240. // The default values for config settings.
  241. $defaults['files'] = array();
  242. $defaults['standard'] = null;
  243. $defaults['verbosity'] = 0;
  244. $defaults['interactive'] = false;
  245. $defaults['colors'] = false;
  246. $defaults['explain'] = false;
  247. $defaults['local'] = false;
  248. $defaults['showSources'] = false;
  249. $defaults['extensions'] = array();
  250. $defaults['sniffs'] = array();
  251. $defaults['exclude'] = array();
  252. $defaults['ignored'] = array();
  253. $defaults['reportFile'] = null;
  254. $defaults['generator'] = '';
  255. $defaults['reports'] = array();
  256. $defaults['bootstrap'] = array();
  257. $defaults['errorSeverity'] = null;
  258. $defaults['warningSeverity'] = null;
  259. $defaults['stdin'] = null;
  260. $defaults['stdinPath'] = '';
  261. $reportFormat = PHP_CodeSniffer::getConfigData('report_format');
  262. if ($reportFormat !== null) {
  263. $defaults['reports'][$reportFormat] = null;
  264. }
  265. $tabWidth = PHP_CodeSniffer::getConfigData('tab_width');
  266. if ($tabWidth === null) {
  267. $defaults['tabWidth'] = 0;
  268. } else {
  269. $defaults['tabWidth'] = (int) $tabWidth;
  270. }
  271. $encoding = PHP_CodeSniffer::getConfigData('encoding');
  272. if ($encoding === null) {
  273. $defaults['encoding'] = 'iso-8859-1';
  274. } else {
  275. $defaults['encoding'] = strtolower($encoding);
  276. }
  277. $severity = PHP_CodeSniffer::getConfigData('severity');
  278. if ($severity !== null) {
  279. $defaults['errorSeverity'] = (int) $severity;
  280. $defaults['warningSeverity'] = (int) $severity;
  281. }
  282. $severity = PHP_CodeSniffer::getConfigData('error_severity');
  283. if ($severity !== null) {
  284. $defaults['errorSeverity'] = (int) $severity;
  285. }
  286. $severity = PHP_CodeSniffer::getConfigData('warning_severity');
  287. if ($severity !== null) {
  288. $defaults['warningSeverity'] = (int) $severity;
  289. }
  290. $showWarnings = PHP_CodeSniffer::getConfigData('show_warnings');
  291. if ($showWarnings !== null) {
  292. $showWarnings = (bool) $showWarnings;
  293. if ($showWarnings === false) {
  294. $defaults['warningSeverity'] = 0;
  295. }
  296. }
  297. $reportWidth = PHP_CodeSniffer::getConfigData('report_width');
  298. if ($reportWidth !== null) {
  299. $defaults['reportWidth'] = $this->_validateReportWidth($reportWidth);
  300. } else {
  301. // Use function defaults.
  302. $defaults['reportWidth'] = null;
  303. }
  304. $showProgress = PHP_CodeSniffer::getConfigData('show_progress');
  305. if ($showProgress === null) {
  306. $defaults['showProgress'] = false;
  307. } else {
  308. $defaults['showProgress'] = (bool) $showProgress;
  309. }
  310. $quiet = PHP_CodeSniffer::getConfigData('quiet');
  311. if ($quiet === null) {
  312. $defaults['quiet'] = false;
  313. } else {
  314. $defaults['quiet'] = (bool) $quiet;
  315. }
  316. $colors = PHP_CodeSniffer::getConfigData('colors');
  317. if ($colors === null) {
  318. $defaults['colors'] = false;
  319. } else {
  320. $defaults['colors'] = (bool) $colors;
  321. }
  322. if (PHP_CodeSniffer::isPharFile(dirname(dirname(__FILE__))) === true) {
  323. // If this is a phar file, check for the standard in the config.
  324. $standard = PHP_CodeSniffer::getConfigData('standard');
  325. if ($standard !== null) {
  326. $defaults['standard'] = $standard;
  327. }
  328. }
  329. return $defaults;
  330. }//end getDefaults()
  331. /**
  332. * Gets the processed command line values.
  333. *
  334. * If the values have not yet been set, the values will be sourced
  335. * from the command line arguments.
  336. *
  337. * @return array
  338. */
  339. public function getCommandLineValues()
  340. {
  341. if (empty($this->values) === false) {
  342. return $this->values;
  343. }
  344. $args = $_SERVER['argv'];
  345. array_shift($args);
  346. $this->setCommandLineValues($args);
  347. // Check for content on STDIN.
  348. $handle = fopen('php://stdin', 'r');
  349. if (stream_set_blocking($handle, false) === true) {
  350. $fileContents = '';
  351. while (($line = fgets($handle)) !== false) {
  352. $fileContents .= $line;
  353. usleep(10);
  354. }
  355. stream_set_blocking($handle, true);
  356. fclose($handle);
  357. if (trim($fileContents) !== '') {
  358. $this->values['stdin'] = $fileContents;
  359. }
  360. }
  361. return $this->values;
  362. }//end getCommandLineValues()
  363. /**
  364. * Set the command line values.
  365. *
  366. * @param array $args An array of command line arguments to process.
  367. *
  368. * @return void
  369. */
  370. public function setCommandLineValues($args)
  371. {
  372. if (defined('PHP_CODESNIFFER_IN_TESTS') === true) {
  373. $this->values = array(
  374. 'stdin' => null,
  375. 'quiet' => true,
  376. );
  377. } else if (empty($this->values) === true) {
  378. $this->values = $this->getDefaults();
  379. }
  380. $this->_cliArgs = $args;
  381. $numArgs = count($args);
  382. for ($i = 0; $i < $numArgs; $i++) {
  383. $arg = $this->_cliArgs[$i];
  384. if ($arg === '') {
  385. continue;
  386. }
  387. if ($arg{0} === '-') {
  388. if ($arg === '-' || $arg === '--') {
  389. // Empty argument, ignore it.
  390. continue;
  391. }
  392. if ($arg{1} === '-') {
  393. $this->processLongArgument(substr($arg, 2), $i);
  394. } else {
  395. $switches = str_split($arg);
  396. foreach ($switches as $switch) {
  397. if ($switch === '-') {
  398. continue;
  399. }
  400. $this->processShortArgument($switch, $i);
  401. }
  402. }
  403. } else {
  404. $this->processUnknownArgument($arg, $i);
  405. }//end if
  406. }//end for
  407. }//end setCommandLineValues()
  408. /**
  409. * Processes a short (-e) command line argument.
  410. *
  411. * @param string $arg The command line argument.
  412. * @param int $pos The position of the argument on the command line.
  413. *
  414. * @return void
  415. */
  416. public function processShortArgument($arg, $pos)
  417. {
  418. switch ($arg) {
  419. case 'h':
  420. case '?':
  421. $this->printUsage();
  422. exit(0);
  423. case 'i' :
  424. $this->printInstalledStandards();
  425. exit(0);
  426. case 'v' :
  427. if ($this->values['quiet'] === true) {
  428. // Ignore when quiet mode is enabled.
  429. break;
  430. }
  431. if (isset($this->values['verbosity']) === false) {
  432. $this->values['verbosity'] = 1;
  433. } else {
  434. $this->values['verbosity']++;
  435. }
  436. break;
  437. case 'l' :
  438. $this->values['local'] = true;
  439. break;
  440. case 's' :
  441. $this->values['showSources'] = true;
  442. break;
  443. case 'a' :
  444. $this->values['interactive'] = true;
  445. break;
  446. case 'e':
  447. $this->values['explain'] = true;
  448. break;
  449. case 'p' :
  450. if ($this->values['quiet'] === true) {
  451. // Ignore when quiet mode is enabled.
  452. break;
  453. }
  454. $this->values['showProgress'] = true;
  455. break;
  456. case 'q' :
  457. // Quiet mode disables a few other settings as well.
  458. $this->values['quiet'] = true;
  459. $this->values['showProgress'] = false;
  460. $this->values['verbosity'] = 0;
  461. break;
  462. case 'd' :
  463. $ini = explode('=', $this->_cliArgs[($pos + 1)]);
  464. $this->_cliArgs[($pos + 1)] = '';
  465. if (isset($ini[1]) === true) {
  466. ini_set($ini[0], $ini[1]);
  467. } else {
  468. ini_set($ini[0], true);
  469. }
  470. break;
  471. case 'n' :
  472. $this->values['warningSeverity'] = 0;
  473. break;
  474. case 'w' :
  475. $this->values['warningSeverity'] = null;
  476. break;
  477. default:
  478. if ($this->dieOnUnknownArg === false) {
  479. $this->values[$arg] = $arg;
  480. } else {
  481. $this->processUnknownArgument('-'.$arg, $pos);
  482. }
  483. }//end switch
  484. }//end processShortArgument()
  485. /**
  486. * Processes a long (--example) command line argument.
  487. *
  488. * @param string $arg The command line argument.
  489. * @param int $pos The position of the argument on the command line.
  490. *
  491. * @return void
  492. */
  493. public function processLongArgument($arg, $pos)
  494. {
  495. switch ($arg) {
  496. case 'help':
  497. $this->printUsage();
  498. exit(0);
  499. case 'version':
  500. echo 'PHP_CodeSniffer version '.PHP_CodeSniffer::VERSION.' ('.PHP_CodeSniffer::STABILITY.') ';
  501. echo 'by Squiz (http://www.squiz.net)'.PHP_EOL;
  502. exit(0);
  503. case 'colors':
  504. $this->values['colors'] = true;
  505. break;
  506. case 'no-colors':
  507. $this->values['colors'] = false;
  508. break;
  509. case 'config-set':
  510. if (isset($this->_cliArgs[($pos + 1)]) === false
  511. || isset($this->_cliArgs[($pos + 2)]) === false
  512. ) {
  513. echo 'ERROR: Setting a config option requires a name and value'.PHP_EOL.PHP_EOL;
  514. $this->printUsage();
  515. exit(0);
  516. }
  517. $key = $this->_cliArgs[($pos + 1)];
  518. $value = $this->_cliArgs[($pos + 2)];
  519. $current = PHP_CodeSniffer::getConfigData($key);
  520. try {
  521. PHP_CodeSniffer::setConfigData($key, $value);
  522. } catch (Exception $e) {
  523. echo $e->getMessage().PHP_EOL;
  524. exit(2);
  525. }
  526. if ($current === null) {
  527. echo "Config value \"$key\" added successfully".PHP_EOL;
  528. } else {
  529. echo "Config value \"$key\" updated successfully; old value was \"$current\"".PHP_EOL;
  530. }
  531. exit(0);
  532. case 'config-delete':
  533. if (isset($this->_cliArgs[($pos + 1)]) === false) {
  534. echo 'ERROR: Deleting a config option requires the name of the option'.PHP_EOL.PHP_EOL;
  535. $this->printUsage();
  536. exit(0);
  537. }
  538. $key = $this->_cliArgs[($pos + 1)];
  539. $current = PHP_CodeSniffer::getConfigData($key);
  540. if ($current === null) {
  541. echo "Config value \"$key\" has not been set".PHP_EOL;
  542. } else {
  543. try {
  544. PHP_CodeSniffer::setConfigData($key, null);
  545. } catch (Exception $e) {
  546. echo $e->getMessage().PHP_EOL;
  547. exit(2);
  548. }
  549. echo "Config value \"$key\" removed successfully; old value was \"$current\"".PHP_EOL;
  550. }
  551. exit(0);
  552. case 'config-show':
  553. $data = PHP_CodeSniffer::getAllConfigData();
  554. $this->printConfigData($data);
  555. exit(0);
  556. case 'runtime-set':
  557. if (isset($this->_cliArgs[($pos + 1)]) === false
  558. || isset($this->_cliArgs[($pos + 2)]) === false
  559. ) {
  560. echo 'ERROR: Setting a runtime config option requires a name and value'.PHP_EOL.PHP_EOL;
  561. $this->printUsage();
  562. exit(0);
  563. }
  564. $key = $this->_cliArgs[($pos + 1)];
  565. $value = $this->_cliArgs[($pos + 2)];
  566. $this->_cliArgs[($pos + 1)] = '';
  567. $this->_cliArgs[($pos + 2)] = '';
  568. PHP_CodeSniffer::setConfigData($key, $value, true);
  569. break;
  570. default:
  571. if (substr($arg, 0, 7) === 'sniffs=') {
  572. $sniffs = explode(',', substr($arg, 7));
  573. foreach ($sniffs as $sniff) {
  574. if (substr_count($sniff, '.') !== 2) {
  575. echo 'ERROR: The specified sniff code "'.$sniff.'" is invalid'.PHP_EOL.PHP_EOL;
  576. $this->printUsage();
  577. exit(2);
  578. }
  579. }
  580. $this->values['sniffs'] = $sniffs;
  581. } else if (substr($arg, 0, 8) === 'exclude=') {
  582. $sniffs = explode(',', substr($arg, 8));
  583. foreach ($sniffs as $sniff) {
  584. if (substr_count($sniff, '.') !== 2) {
  585. echo 'ERROR: The specified sniff code "'.$sniff.'" is invalid'.PHP_EOL.PHP_EOL;
  586. $this->printUsage();
  587. exit(2);
  588. }
  589. }
  590. $this->values['exclude'] = $sniffs;
  591. } else if (substr($arg, 0, 10) === 'bootstrap=') {
  592. $files = explode(',', substr($arg, 10));
  593. foreach ($files as $file) {
  594. $path = PHP_CodeSniffer::realpath($file);
  595. if ($path === false) {
  596. echo 'ERROR: The specified bootstrap file "'.$file.'" does not exist'.PHP_EOL.PHP_EOL;
  597. $this->printUsage();
  598. exit(2);
  599. }
  600. $this->values['bootstrap'][] = $path;
  601. }
  602. } else if (substr($arg, 0, 10) === 'file-list=') {
  603. $fileList = substr($arg, 10);
  604. $path = PHP_CodeSniffer::realpath($fileList);
  605. if ($path === false) {
  606. echo 'ERROR: The specified file list "'.$file.'" does not exist'.PHP_EOL.PHP_EOL;
  607. $this->printUsage();
  608. exit(2);
  609. }
  610. $files = file($path);
  611. foreach ($files as $inputFile) {
  612. $inputFile = trim($inputFile);
  613. // Skip empty lines.
  614. if ($inputFile === '') {
  615. continue;
  616. }
  617. $realFile = PHP_CodeSniffer::realpath($inputFile);
  618. if ($realFile === false) {
  619. echo 'ERROR: The specified file "'.$inputFile.'" does not exist'.PHP_EOL.PHP_EOL;
  620. $this->printUsage();
  621. exit(2);
  622. }
  623. $this->values['files'][] = $realFile;
  624. }
  625. } else if (substr($arg, 0, 11) === 'stdin-path=') {
  626. $this->values['stdinPath'] = PHP_CodeSniffer::realpath(substr($arg, 11));
  627. // It may not exist and return false instead, so just use whatever they gave us.
  628. if ($this->values['stdinPath'] === false) {
  629. $this->values['stdinPath'] = trim(substr($arg, 11));
  630. }
  631. } else if (substr($arg, 0, 12) === 'report-file=') {
  632. $this->values['reportFile'] = PHP_CodeSniffer::realpath(substr($arg, 12));
  633. // It may not exist and return false instead.
  634. if ($this->values['reportFile'] === false) {
  635. $this->values['reportFile'] = substr($arg, 12);
  636. $dir = dirname($this->values['reportFile']);
  637. if (is_dir($dir) === false) {
  638. echo 'ERROR: The specified report file path "'.$this->values['reportFile'].'" points to a non-existent directory'.PHP_EOL.PHP_EOL;
  639. $this->printUsage();
  640. exit(2);
  641. }
  642. if ($dir === '.') {
  643. // Passed report file is a file in the current directory.
  644. $this->values['reportFile'] = getcwd().'/'.basename($this->values['reportFile']);
  645. } else {
  646. if ($dir{0} === '/') {
  647. // An absolute path.
  648. $dir = PHP_CodeSniffer::realpath($dir);
  649. } else {
  650. $dir = PHP_CodeSniffer::realpath(getcwd().'/'.$dir);
  651. }
  652. if ($dir !== false) {
  653. // Report file path is relative.
  654. $this->values['reportFile'] = $dir.'/'.basename($this->values['reportFile']);
  655. }
  656. }
  657. }//end if
  658. if (is_dir($this->values['reportFile']) === true) {
  659. echo 'ERROR: The specified report file path "'.$this->values['reportFile'].'" is a directory'.PHP_EOL.PHP_EOL;
  660. $this->printUsage();
  661. exit(2);
  662. }
  663. } else if (substr($arg, 0, 13) === 'report-width=') {
  664. $this->values['reportWidth'] = $this->_validateReportWidth(substr($arg, 13));
  665. } else if (substr($arg, 0, 7) === 'report='
  666. || substr($arg, 0, 7) === 'report-'
  667. ) {
  668. if ($arg[6] === '-') {
  669. // This is a report with file output.
  670. $split = strpos($arg, '=');
  671. if ($split === false) {
  672. $report = substr($arg, 7);
  673. $output = null;
  674. } else {
  675. $report = substr($arg, 7, ($split - 7));
  676. $output = substr($arg, ($split + 1));
  677. if ($output === false) {
  678. $output = null;
  679. } else {
  680. $dir = dirname($output);
  681. if ($dir === '.') {
  682. // Passed report file is a filename in the current directory.
  683. $output = getcwd().'/'.basename($output);
  684. } else {
  685. if ($dir{0} === '/') {
  686. // An absolute path.
  687. $dir = PHP_CodeSniffer::realpath($dir);
  688. } else {
  689. $dir = PHP_CodeSniffer::realpath(getcwd().'/'.$dir);
  690. }
  691. if ($dir !== false) {
  692. // Report file path is relative.
  693. $output = $dir.'/'.basename($output);
  694. }
  695. }
  696. }//end if
  697. }//end if
  698. } else {
  699. // This is a single report.
  700. $report = substr($arg, 7);
  701. $output = null;
  702. }//end if
  703. $this->values['reports'][$report] = $output;
  704. } else if (substr($arg, 0, 9) === 'standard=') {
  705. $standards = trim(substr($arg, 9));
  706. if ($standards !== '') {
  707. $this->values['standard'] = explode(',', $standards);
  708. }
  709. } else if (substr($arg, 0, 11) === 'extensions=') {
  710. if (isset($this->values['extensions']) === false) {
  711. $this->values['extensions'] = array();
  712. }
  713. $this->values['extensions'] = array_merge($this->values['extensions'], explode(',', substr($arg, 11)));
  714. } else if (substr($arg, 0, 9) === 'severity=') {
  715. $this->values['errorSeverity'] = (int) substr($arg, 9);
  716. $this->values['warningSeverity'] = $this->values['errorSeverity'];
  717. } else if (substr($arg, 0, 15) === 'error-severity=') {
  718. $this->values['errorSeverity'] = (int) substr($arg, 15);
  719. } else if (substr($arg, 0, 17) === 'warning-severity=') {
  720. $this->values['warningSeverity'] = (int) substr($arg, 17);
  721. } else if (substr($arg, 0, 7) === 'ignore=') {
  722. // Split the ignore string on commas, unless the comma is escaped
  723. // using 1 or 3 slashes (\, or \\\,).
  724. $ignored = preg_split(
  725. '/(?<=(?<!\\\\)\\\\\\\\),|(?<!\\\\),/',
  726. substr($arg, 7)
  727. );
  728. foreach ($ignored as $pattern) {
  729. $pattern = trim($pattern);
  730. if ($pattern === '') {
  731. continue;
  732. }
  733. $this->values['ignored'][$pattern] = 'absolute';
  734. }
  735. } else if (substr($arg, 0, 10) === 'generator=') {
  736. $this->values['generator'] = substr($arg, 10);
  737. } else if (substr($arg, 0, 9) === 'encoding=') {
  738. $this->values['encoding'] = strtolower(substr($arg, 9));
  739. } else if (substr($arg, 0, 10) === 'tab-width=') {
  740. $this->values['tabWidth'] = (int) substr($arg, 10);
  741. } else {
  742. if ($this->dieOnUnknownArg === false) {
  743. $eqPos = strpos($arg, '=');
  744. if ($eqPos === false) {
  745. $this->values[$arg] = $arg;
  746. } else {
  747. $value = substr($arg, ($eqPos + 1));
  748. $arg = substr($arg, 0, $eqPos);
  749. $this->values[$arg] = $value;
  750. }
  751. } else {
  752. $this->processUnknownArgument('--'.$arg, $pos);
  753. }
  754. }//end if
  755. break;
  756. }//end switch
  757. }//end processLongArgument()
  758. /**
  759. * Processes an unknown command line argument.
  760. *
  761. * Assumes all unknown arguments are files and folders to check.
  762. *
  763. * @param string $arg The command line argument.
  764. * @param int $pos The position of the argument on the command line.
  765. *
  766. * @return void
  767. */
  768. public function processUnknownArgument($arg, $pos)
  769. {
  770. // We don't know about any additional switches; just files.
  771. if ($arg{0} === '-') {
  772. if ($this->dieOnUnknownArg === false) {
  773. return;
  774. }
  775. echo 'ERROR: option "'.$arg.'" not known.'.PHP_EOL.PHP_EOL;
  776. $this->printUsage();
  777. exit(2);
  778. }
  779. $file = PHP_CodeSniffer::realpath($arg);
  780. if (file_exists($file) === false) {
  781. if ($this->dieOnUnknownArg === false) {
  782. return;
  783. }
  784. echo 'ERROR: The file "'.$arg.'" does not exist.'.PHP_EOL.PHP_EOL;
  785. $this->printUsage();
  786. exit(2);
  787. } else {
  788. $this->values['files'][] = $file;
  789. }
  790. }//end processUnknownArgument()
  791. /**
  792. * Runs PHP_CodeSniffer over files and directories.
  793. *
  794. * @param array $values An array of values determined from CLI args.
  795. *
  796. * @return int The number of error and warning messages shown.
  797. * @see getCommandLineValues()
  798. */
  799. public function process($values=array())
  800. {
  801. if (empty($values) === true) {
  802. $values = $this->getCommandLineValues();
  803. } else {
  804. $values = array_merge($this->getDefaults(), $values);
  805. $this->values = $values;
  806. }
  807. if ($values['generator'] !== '') {
  808. $phpcs = new PHP_CodeSniffer($values['verbosity']);
  809. if ($values['standard'] === null) {
  810. $values['standard'] = $this->validateStandard(null);
  811. }
  812. foreach ($values['standard'] as $standard) {
  813. $phpcs->generateDocs(
  814. $standard,
  815. $values['sniffs'],
  816. $values['generator']
  817. );
  818. }
  819. exit(0);
  820. }
  821. // If no standard is supplied, get the default.
  822. $values['standard'] = $this->validateStandard($values['standard']);
  823. foreach ($values['standard'] as $standard) {
  824. if (PHP_CodeSniffer::isInstalledStandard($standard) === false) {
  825. // They didn't select a valid coding standard, so help them
  826. // out by letting them know which standards are installed.
  827. echo 'ERROR: the "'.$standard.'" coding standard is not installed. ';
  828. $this->printInstalledStandards();
  829. exit(2);
  830. }
  831. }
  832. if ($values['explain'] === true) {
  833. foreach ($values['standard'] as $standard) {
  834. $this->explainStandard($standard);
  835. }
  836. exit(0);
  837. }
  838. $phpcs = new PHP_CodeSniffer($values['verbosity'], null, null, null);
  839. $phpcs->setCli($this);
  840. $phpcs->initStandard($values['standard'], $values['sniffs'], $values['exclude']);
  841. $values = $this->values;
  842. $phpcs->setTabWidth($values['tabWidth']);
  843. $phpcs->setEncoding($values['encoding']);
  844. $phpcs->setInteractive($values['interactive']);
  845. // Set file extensions if they were specified. Otherwise,
  846. // let PHP_CodeSniffer decide on the defaults.
  847. if (empty($values['extensions']) === false) {
  848. $phpcs->setAllowedFileExtensions($values['extensions']);
  849. }
  850. // Set ignore patterns if they were specified.
  851. if (empty($values['ignored']) === false) {
  852. $ignorePatterns = array_merge($phpcs->getIgnorePatterns(), $values['ignored']);
  853. $phpcs->setIgnorePatterns($ignorePatterns);
  854. }
  855. // Set some convenience member vars.
  856. if ($values['errorSeverity'] === null) {
  857. $this->errorSeverity = PHPCS_DEFAULT_ERROR_SEV;
  858. } else {
  859. $this->errorSeverity = $values['errorSeverity'];
  860. }
  861. if ($values['warningSeverity'] === null) {
  862. $this->warningSeverity = PHPCS_DEFAULT_WARN_SEV;
  863. } else {
  864. $this->warningSeverity = $values['warningSeverity'];
  865. }
  866. if (empty($values['reports']) === true) {
  867. $values['reports']['full'] = $values['reportFile'];
  868. $this->values['reports'] = $values['reports'];
  869. }
  870. // Include bootstrap files.
  871. foreach ($values['bootstrap'] as $bootstrap) {
  872. include $bootstrap;
  873. }
  874. $phpcs->processFiles($values['files'], $values['local']);
  875. if (empty($values['files']) === true || $values['stdin'] !== null) {
  876. $fileContents = $values['stdin'];
  877. if ($fileContents === null) {
  878. // Check if they are passing in the file contents.
  879. $handle = fopen('php://stdin', 'r');
  880. stream_set_blocking($handle, true);
  881. $fileContents = stream_get_contents($handle);
  882. fclose($handle);
  883. }
  884. if ($fileContents === '') {
  885. // No files and no content passed in.
  886. echo 'ERROR: You must supply at least one file or directory to process.'.PHP_EOL.PHP_EOL;
  887. $this->printUsage();
  888. exit(2);
  889. } else {
  890. $this->values['stdin'] = $fileContents;
  891. $phpcs->processFile('STDIN', $fileContents);
  892. }
  893. }
  894. // Interactive runs don't require a final report and it doesn't really
  895. // matter what the retun value is because we know it isn't being read
  896. // by a script.
  897. if ($values['interactive'] === true) {
  898. return 0;
  899. }
  900. return $this->printErrorReport(
  901. $phpcs,
  902. $values['reports'],
  903. $values['showSources'],
  904. $values['reportFile'],
  905. $values['reportWidth']
  906. );
  907. }//end process()
  908. /**
  909. * Prints the error report for the run.
  910. *
  911. * Note that this function may actually print multiple reports
  912. * as the user may have specified a number of output formats.
  913. *
  914. * @param PHP_CodeSniffer $phpcs The PHP_CodeSniffer object containing
  915. * the errors.
  916. * @param array $reports A list of reports to print.
  917. * @param bool $showSources TRUE if report should show error sources
  918. * (not used by all reports).
  919. * @param string $reportFile A default file to log report output to.
  920. * @param int $reportWidth How wide the screen reports should be.
  921. *
  922. * @return int The number of error and warning messages shown.
  923. */
  924. public function printErrorReport(
  925. PHP_CodeSniffer $phpcs,
  926. $reports,
  927. $showSources,
  928. $reportFile,
  929. $reportWidth
  930. ) {
  931. if (empty($reports) === true) {
  932. $reports['full'] = $reportFile;
  933. }
  934. $errors = 0;
  935. $warnings = 0;
  936. $toScreen = false;
  937. foreach ($reports as $report => $output) {
  938. if ($output === null) {
  939. $output = $reportFile;
  940. }
  941. if ($reportFile === null) {
  942. $toScreen = true;
  943. }
  944. // We don't add errors here because the number of
  945. // errors reported by each report type will always be the
  946. // same, so we really just need 1 number.
  947. $result = $phpcs->reporting->printReport(
  948. $report,
  949. $showSources,
  950. $this->values,
  951. $output,
  952. $reportWidth
  953. );
  954. $errors = $result['errors'];
  955. $warnings = $result['warnings'];
  956. }//end foreach
  957. // Only print timer output if no reports were
  958. // printed to the screen so we don't put additional output
  959. // in something like an XML report. If we are printing to screen,
  960. // the report types would have already worked out who should
  961. // print the timer info.
  962. if (PHP_CODESNIFFER_INTERACTIVE === false
  963. && ($toScreen === false
  964. || (($errors + $warnings) === 0 && $this->values['showProgress'] === true))
  965. ) {
  966. PHP_CodeSniffer_Reporting::printRunTime();
  967. }
  968. // They should all return the same value, so it
  969. // doesn't matter which return value we end up using.
  970. $ignoreWarnings = PHP_CodeSniffer::getConfigData('ignore_warnings_on_exit');
  971. $ignoreErrors = PHP_CodeSniffer::getConfigData('ignore_errors_on_exit');
  972. $return = ($errors + $warnings);
  973. if ($ignoreErrors !== null) {
  974. $ignoreErrors = (bool) $ignoreErrors;
  975. if ($ignoreErrors === true) {
  976. $return -= $errors;
  977. }
  978. }
  979. if ($ignoreWarnings !== null) {
  980. $ignoreWarnings = (bool) $ignoreWarnings;
  981. if ($ignoreWarnings === true) {
  982. $return -= $warnings;
  983. }
  984. }
  985. return $return;
  986. }//end printErrorReport()
  987. /**
  988. * Convert the passed standards into valid standards.
  989. *
  990. * Checks things like default values and case.
  991. *
  992. * @param array $standards The standards to validate.
  993. *
  994. * @return array
  995. */
  996. public function validateStandard($standards)
  997. {
  998. if ($standards === null) {
  999. // They did not supply a standard to use.
  1000. // Look for a default ruleset in the current directory or higher.
  1001. $currentDir = getcwd();
  1002. do {
  1003. $default = $currentDir.DIRECTORY_SEPARATOR.'phpcs.xml';
  1004. if (is_file($default) === true) {
  1005. return array($default);
  1006. }
  1007. $default = $currentDir.DIRECTORY_SEPARATOR.'phpcs.xml.dist';
  1008. if (is_file($default) === true) {
  1009. return array($default);
  1010. }
  1011. $lastDir = $currentDir;
  1012. $currentDir = dirname($currentDir);
  1013. } while ($currentDir !== '.' && $currentDir !== $lastDir);
  1014. // Try to get the default from the config system.
  1015. $standard = PHP_CodeSniffer::getConfigData('default_standard');
  1016. if ($standard === null) {
  1017. // Product default standard.
  1018. $standard = 'PEAR';
  1019. }
  1020. return explode(',', $standard);
  1021. }//end if
  1022. $cleaned = array();
  1023. $standards = (array) $standards;
  1024. // Check if the standard name is valid, or if the case is invalid.
  1025. $installedStandards = PHP_CodeSniffer::getInstalledStandards();
  1026. foreach ($standards as $standard) {
  1027. foreach ($installedStandards as $validStandard) {
  1028. if (strtolower($standard) === strtolower($validStandard)) {
  1029. $standard = $validStandard;
  1030. break;
  1031. }
  1032. }
  1033. $cleaned[] = $standard;
  1034. }
  1035. return $cleaned;
  1036. }//end validateStandard()
  1037. /**
  1038. * Prints a report showing the sniffs contained in a standard.
  1039. *
  1040. * @param string $standard The standard to validate.
  1041. *
  1042. * @return void
  1043. */
  1044. public function explainStandard($standard)
  1045. {
  1046. $phpcs = new PHP_CodeSniffer();
  1047. $phpcs->process(array(), $standard);
  1048. $sniffs = $phpcs->getSniffs();
  1049. $sniffs = array_keys($sniffs);
  1050. sort($sniffs);
  1051. ob_start();
  1052. $lastStandard = '';
  1053. $lastCount = '';
  1054. $sniffCount = count($sniffs);
  1055. $sniffs[] = '___';
  1056. echo PHP_EOL."The $standard standard contains $sniffCount sniffs".PHP_EOL;
  1057. ob_start();
  1058. foreach ($sniffs as $sniff) {
  1059. $parts = explode('_', str_replace('\\', '_', $sniff));
  1060. if ($lastStandard === '') {
  1061. $lastStandard = $parts[0];
  1062. }
  1063. if ($parts[0] !== $lastStandard) {
  1064. $sniffList = ob_get_contents();
  1065. ob_end_clean();
  1066. echo PHP_EOL.$lastStandard.' ('.$lastCount.' sniffs)'.PHP_EOL;
  1067. echo str_repeat('-', (strlen($lastStandard.$lastCount) + 10));
  1068. echo PHP_EOL;
  1069. echo $sniffList;
  1070. $lastStandard = $parts[0];
  1071. $lastCount = 0;
  1072. ob_start();
  1073. }
  1074. echo ' '.$parts[0].'.'.$parts[2].'.'.substr($parts[3], 0, -5).PHP_EOL;
  1075. $lastCount++;
  1076. }//end foreach
  1077. ob_end_clean();
  1078. }//end explainStandard()
  1079. /**
  1080. * Prints out the gathered config data.
  1081. *
  1082. * @param array $data The config data to print.
  1083. *
  1084. * @return void
  1085. */
  1086. public function printConfigData($data)
  1087. {
  1088. $max = 0;
  1089. $keys = array_keys($data);
  1090. foreach ($keys as $key) {
  1091. $len = strlen($key);
  1092. if (strlen($key) > $max) {
  1093. $max = $len;
  1094. }
  1095. }
  1096. if ($max === 0) {
  1097. return;
  1098. }
  1099. $max += 2;
  1100. ksort($data);
  1101. foreach ($data as $name => $value) {
  1102. echo str_pad($name.': ', $max).$value.PHP_EOL;
  1103. }
  1104. }//end printConfigData()
  1105. /**
  1106. * Prints out the usage information for this script.
  1107. *
  1108. * @return void
  1109. */
  1110. public function printUsage()
  1111. {
  1112. if (PHP_CODESNIFFER_CBF === true) {
  1113. $this->printPHPCBFUsage();
  1114. } else {
  1115. $this->printPHPCSUsage();
  1116. }
  1117. }//end printUsage()
  1118. /**
  1119. * Prints out the usage information for PHPCS.
  1120. *
  1121. * @return void
  1122. */
  1123. public function printPHPCSUsage()
  1124. {
  1125. echo 'Usage: phpcs [-nwlsaepqvi] [-d key[=value]] [--colors] [--no-colors] [--stdin-path=<stdinPath>]'.PHP_EOL;
  1126. echo ' [--report=<report>] [--report-file=<reportFile>] [--report-<report>=<reportFile>] ...'.PHP_EOL;
  1127. echo ' [--report-width=<reportWidth>] [--generator=<generator>] [--tab-width=<tabWidth>]'.PHP_EOL;
  1128. echo ' [--severity=<severity>] [--error-severity=<severity>] [--warning-severity=<severity>]'.PHP_EOL;
  1129. echo ' [--runtime-set key value] [--config-set key value] [--config-delete key] [--config-show]'.PHP_EOL;
  1130. echo ' [--standard=<standard>] [--sniffs=<sniffs>] [--exclude=<sniffs>] [--encoding=<encoding>]'.PHP_EOL;
  1131. echo ' [--extensions=<extensions>] [--ignore=<patterns>] [--bootstrap=<bootstrap>]'.PHP_EOL;
  1132. echo ' [--file-list=<fileList>] <file> ...'.PHP_EOL;
  1133. echo ' Set runtime value (see --config-set) '.PHP_EOL;
  1134. echo ' -n Do not print warnings (shortcut for --warning-severity=0)'.PHP_EOL;
  1135. echo ' -w Print both warnings and errors (this is the default)'.PHP_EOL;
  1136. echo ' -l Local directory only, no recursion'.PHP_EOL;
  1137. echo ' -s Show sniff codes in all reports'.PHP_EOL;
  1138. echo ' -a Run interactively'.PHP_EOL;
  1139. echo ' -e Explain a standard by showing the sniffs it includes'.PHP_EOL;
  1140. echo ' -p Show progress of the run'.PHP_EOL;
  1141. echo ' -q Quiet mode; disables progress and verbose output'.PHP_EOL;
  1142. echo ' -v[v][v] Print verbose output'.PHP_EOL;
  1143. echo ' -i Show a list of installed coding standards'.PHP_EOL;
  1144. echo ' -d Set the [key] php.ini value to [value] or [true] if value is omitted'.PHP_EOL;
  1145. echo ' --help Print this help message'.PHP_EOL;
  1146. echo ' --version Print version information'.PHP_EOL;
  1147. echo ' --colors Use colors in output'.PHP_EOL;
  1148. echo ' --no-colors Do not use colors in output (this is the default)'.PHP_EOL;
  1149. echo ' <file> One or more files and/or directories to check'.PHP_EOL;
  1150. echo ' <fileList> A file containing a list of files and/or directories to check (one per line)'.PHP_EOL;
  1151. echo ' <stdinPath> If processing STDIN, the file path that STDIN will be processed as '.PHP_EOL;
  1152. echo ' <bootstrap> A comma separated list of files to run before processing starts'.PHP_EOL;
  1153. echo ' <encoding> The encoding of the files being checked (default is iso-8859-1)'.PHP_EOL;
  1154. echo ' <extensions> A comma separated list of file extensions to check'.PHP_EOL;
  1155. echo ' (extension filtering only valid when checking a directory)'.PHP_EOL;
  1156. echo ' The type of the file can be specified using: ext/type'.PHP_EOL;
  1157. echo ' e.g., module/php,es/js'.PHP_EOL;
  1158. echo ' <generator> Uses either the "HTML", "Markdown" or "Text" generator'.PHP_EOL;
  1159. echo ' (forces documentation generation instead of checking)'.PHP_EOL;
  1160. echo ' <patterns> A comma separated list of patterns to ignore files and directories'.PHP_EOL;
  1161. echo ' <report> Print either the "full", "xml", "checkstyle", "csv"'.PHP_EOL;
  1162. echo ' "json", "emacs", "source", "summary", "diff", "junit"'.PHP_EOL;
  1163. echo ' "svnblame", "gitblame", "hgblame" or "notifysend" report'.PHP_EOL;
  1164. echo ' (the "full" report is printed by default)'.PHP_EOL;
  1165. echo ' <reportFile> Write the report to the specified file path'.PHP_EOL;
  1166. echo ' <reportWidth> How many columns wide screen reports should be printed'.PHP_EOL;
  1167. echo ' or set to "auto" to use current screen width, where supported'.PHP_EOL;
  1168. echo ' <sniffs> A comma separated list of sniff codes to include or exclude during checking'.PHP_EOL;
  1169. echo ' (all sniffs must be part of the specified standard)'.PHP_EOL;
  1170. echo ' <severity> The minimum severity required to display an error or warning'.PHP_EOL;
  1171. echo ' <standard> The name or path of the coding standard to use'.PHP_EOL;
  1172. echo ' <tabWidth> The number of spaces each tab represents'.PHP_EOL;
  1173. }//end printPHPCSUsage()
  1174. /**
  1175. * Prints out the usage information for PHPCBF.
  1176. *
  1177. * @return void
  1178. */
  1179. public function printPHPCBFUsage()
  1180. {
  1181. echo 'Usage: phpcbf [-nwli] [-d key[=value]] [--stdin-path=<stdinPath>]'.PHP_EOL;
  1182. echo ' [--standard=<standard>] [--sniffs=<sniffs>] [--exclude=<sniffs>] [--suffix=<suffix>]'.PHP_EOL;
  1183. echo ' [--severity=<severity>] [--error-severity=<severity>] [--warning-severity=<severity>]'.PHP_EOL;
  1184. echo ' [--tab-width=<tabWidth>] [--encoding=<encoding>]'.PHP_EOL;
  1185. echo ' [--extensions=<extensions>] [--ignore=<patterns>] [--bootstrap=<bootstrap>]'.PHP_EOL;
  1186. echo ' [--file-list=<fileList>] <file> ...'.PHP_EOL;
  1187. echo ' -n Do not fix warnings (shortcut for --warning-severity=0)'.PHP_EOL;
  1188. echo ' -w Fix both warnings and errors (on by default)'.PHP_EOL;
  1189. echo ' -l Local directory only, no recursion'.PHP_EOL;
  1190. echo ' -i Show a list of installed coding standards'.PHP_EOL;
  1191. echo ' -d Set the [key] php.ini value to [value] or [true] if value is omitted'.PHP_EOL;
  1192. echo ' --help Print this help message'.PHP_EOL;
  1193. echo ' --version Print version information'.PHP_EOL;
  1194. echo ' --no-patch Do not make use of the "diff" or "patch" programs'.PHP_EOL;
  1195. echo ' <file> One or more files and/or directories to fix'.PHP_EOL;
  1196. echo ' <fileList> A file containing a list of files and/or directories to fix (one per line)'.PHP_EOL;
  1197. echo ' <stdinPath> If processing STDIN, the file path that STDIN will be processed as '.PHP_EOL;
  1198. echo ' <bootstrap> A comma separated list of files to run before processing starts'.PHP_EOL;
  1199. echo ' <encoding> The encoding of the files being fixed (default is iso-8859-1)'.PHP_EOL;
  1200. echo ' <extensions> A comma separated list of file extensions to fix'.PHP_EOL;
  1201. echo ' (extension filtering only valid when checking a directory)'.PHP_EOL;
  1202. echo ' The type of the file can be specified using: ext/type'.PHP_EOL;
  1203. echo ' e.g., module/php,es/js'.PHP_EOL;
  1204. echo ' <patterns> A comma separated list of patterns to ignore files and directories'.PHP_EOL;
  1205. echo ' <sniffs> A comma separated list of sniff codes to include or exclude during fixing'.PHP_EOL;
  1206. echo ' (all sniffs must be part of the specified standard)'.PHP_EOL;
  1207. echo ' <severity> The minimum severity required to fix an error or warning'.PHP_EOL;
  1208. echo ' <standard> The name or path of the coding standard to use'.PHP_EOL;
  1209. echo ' <suffix> Write modified files to a filename using this suffix'.PHP_EOL;
  1210. echo ' ("diff" and "patch" are not used in this mode)'.PHP_EOL;
  1211. echo ' <tabWidth> The number of spaces each tab represents'.PHP_EOL;
  1212. }//end printPHPCBFUsage()
  1213. /**
  1214. * Prints out a list of installed coding standards.
  1215. *
  1216. * @return void
  1217. */
  1218. public function printInstalledStandards()
  1219. {
  1220. $installedStandards = PHP_CodeSniffer::getInstalledStandards();
  1221. $numStandards = count($installedStandards);
  1222. if ($numStandards === 0) {
  1223. echo 'No coding standards are installed.'.PHP_EOL;
  1224. } else {
  1225. $lastStandard = array_pop($installedStandards);
  1226. if ($numStandards === 1) {
  1227. echo "The only coding standard installed is $lastStandard".PHP_EOL;
  1228. } else {
  1229. $standardList = implode(', ', $installedStandards);
  1230. $standardList .= ' and '.$lastStandard;
  1231. echo 'The installed coding standards are '.$standardList.PHP_EOL;
  1232. }
  1233. }
  1234. }//end printInstalledStandards()
  1235. /**
  1236. * Set report width based on terminal width.
  1237. *
  1238. * @param int $width The width of the report. If "auto" then will
  1239. * be replaced by the terminal width.
  1240. *
  1241. * @return int
  1242. */
  1243. private function _validateReportWidth($width)
  1244. {
  1245. if ($width === 'auto'
  1246. && preg_match('|\d+ (\d+)|', shell_exec('stty size 2>&1'), $matches) === 1
  1247. ) {
  1248. return (int) $matches[1];
  1249. }
  1250. return (int) $width;
  1251. }//end _validateReportWidth()
  1252. }//end class