comparison vendor/squizlabs/php_codesniffer/CodeSniffer/CLI.php @ 0:c75dbcec494b

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