PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.3.0
Defender Security – Malware Scanner, Login Security & Firewall v6.3.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / src / extra / php-codesniffer-php-token / Config.php

Config.php in Defender Security – Malware Scanner, Login Security & Firewall 6.3.0, at src/extra/php-codesniffer-php-token/Config.php

1,579 lines 52.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Stores the configuration used to run PHPCS and PHPCBF.
4 *
5 * Parses the command line to determine user supplied values
6 * and provides functions to access data stored in config files.
7 *
8 * @author Greg Sherwood <[email protected]>
9 * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
10 * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
11 */
12
13 namespace PHP_CodeSniffer;
14
15 use PHP_CodeSniffer\Exceptions\DeepExitException;
16 use PHP_CodeSniffer\Exceptions\RuntimeException;
17
18 class Config {
19
20 /**
21 * The current version.
22 *
23 * @var string
24 */
25 const VERSION = '3.5.4';
26
27 /**
28 * Package stability; either stable, beta or alpha.
29 *
30 * @var string
31 */
32 const STABILITY = 'stable';
33
34 /**
35 * An array of settings that PHPCS and PHPCBF accept.
36 *
37 * This array is not meant to be accessed directly. Instead, use the settings
38 * as if they are class member vars so the __get() and __set() magic methods
39 * can be used to validate the values. For example, to set the verbosity level to
40 * level 2, use $this->verbosity = 2; instead of accessing this property directly.
41 *
42 * The list of settings are:
43 *
44 * string[] files The files and directories to check.
45 * string[] standards The standards being used for checking.
46 * int verbosity How verbose the output should be.
47 * 0: no unnecessary output
48 * 1: basic output for files being checked
49 * 2: ruleset and file parsing output
50 * 3: sniff execution output
51 * bool interactive Enable interactive checking mode.
52 * bool parallel Check files in parallel.
53 * bool cache Enable the use of the file cache.
54 * bool cacheFile A file where the cache data should be written
55 * bool colors Display colours in output.
56 * bool explain Explain the coding standards.
57 * bool local Process local files in directories only (no recursion).
58 * bool showSources Show sniff source codes in report output.
59 * bool showProgress Show basic progress information while running.
60 * bool quiet Quiet mode; disables progress and verbose output.
61 * bool annotations Process phpcs: annotations.
62 * int tabWidth How many spaces each tab is worth.
63 * string encoding The encoding of the files being checked.
64 * string[] sniffs The sniffs that should be used for checking.
65 * If empty, all sniffs in the supplied standards will be used.
66 * string[] exclude The sniffs that should be excluded from checking.
67 * If empty, all sniffs in the supplied standards will be used.
68 * string[] ignored Regular expressions used to ignore files and folders during checking.
69 * string reportFile A file where the report output should be written.
70 * string generator The documentation generator to use.
71 * string filter The filter to use for the run.
72 * string[] bootstrap One of more files to include before the run begins.
73 * int reportWidth The maximum number of columns that reports should use for output.
74 * Set to "auto" for have this value changed to the width of the terminal.
75 * int errorSeverity The minimum severity an error must have to be displayed.
76 * int warningSeverity The minimum severity a warning must have to be displayed.
77 * bool recordErrors Record the content of error messages as well as error counts.
78 * string suffix A suffix to add to fixed files.
79 * string basepath A file system location to strip from the paths of files shown in reports.
80 * bool stdin Read content from STDIN instead of supplied files.
81 * string stdinContent Content passed directly to PHPCS on STDIN.
82 * string stdinPath The path to use for content passed on STDIN.
83 *
84 * array<string, string> extensions File extensions that should be checked, and what tokenizer to use.
85 * E.g., array('inc' => 'PHP');
86 * array<string, string|null> reports The reports to use for printing output after the run.
87 * The format of the array is:
88 * array(
89 * 'reportName1' => 'outputFile',
90 * 'reportName2' => null,
91 * );
92 * If the array value is NULL, the report will be written to the screen.
93 *
94 * string[] unknown Any arguments gathered on the command line that are unknown to us.
95 * E.g., using `phpcs -c` will give array('c');
96 *
97 * @var array<string, mixed>
98 */
99 private $settings = [
100 'files' => null,
101 'standards' => null,
102 'verbosity' => null,
103 'interactive' => null,
104 'parallel' => null,
105 'cache' => null,
106 'cacheFile' => null,
107 'colors' => null,
108 'explain' => null,
109 'local' => null,
110 'showSources' => null,
111 'showProgress' => null,
112 'quiet' => null,
113 'annotations' => null,
114 'tabWidth' => null,
115 'encoding' => null,
116 'extensions' => null,
117 'sniffs' => null,
118 'exclude' => null,
119 'ignored' => null,
120 'reportFile' => null,
121 'generator' => null,
122 'filter' => null,
123 'bootstrap' => null,
124 'reports' => null,
125 'basepath' => null,
126 'reportWidth' => null,
127 'errorSeverity' => null,
128 'warningSeverity' => null,
129 'recordErrors' => null,
130 'suffix' => null,
131 'stdin' => null,
132 'stdinContent' => null,
133 'stdinPath' => null,
134 'unknown' => null,
135 ];
136
137 /**
138 * Whether or not to kill the process when an unknown command line arg is found.
139 *
140 * If FALSE, arguments that are not command line options or file/directory paths
141 * will be ignored and execution will continue. These values will be stored in
142 * $this->unknown.
143 *
144 * @var boolean
145 */
146 public $dieOnUnknownArg;
147
148 /**
149 * The current command line arguments we are processing.
150 *
151 * @var string[]
152 */
153 private $cliArgs = [];
154
155 /**
156 * Command line values that the user has supplied directly.
157 *
158 * @var array<string, TRUE>
159 */
160 private static $overriddenDefaults = [];
161
162 /**
163 * Config file data that has been loaded for the run.
164 *
165 * @var array<string, string>
166 */
167 private static $configData = null;
168
169 /**
170 * The full path to the config data file that has been loaded.
171 *
172 * @var string
173 */
174 private static $configDataFile = null;
175
176 /**
177 * Automatically discovered executable utility paths.
178 *
179 * @var array<string, string>
180 */
181 private static $executablePaths = [];
182
183
184 /**
185 * Get the value of an inaccessible property.
186 *
187 * @param string $name The name of the property.
188 *
189 * @return mixed
190 * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the setting name is invalid.
191 */
192 public function __get( $name ) {
193 if ( array_key_exists( $name, $this->settings ) === false ) {
194 throw new RuntimeException( "ERROR: unable to get value of property \"$name\"" );
195 }
196
197 return $this->settings[ $name ];
198
199 }//end __get()
200
201
202 /**
203 * Set the value of an inaccessible property.
204 *
205 * @param string $name The name of the property.
206 * @param mixed $value The value of the property.
207 *
208 * @return void
209 * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the setting name is invalid.
210 */
211 public function __set( $name, $value ) {
212 if ( array_key_exists( $name, $this->settings ) === false ) {
213 throw new RuntimeException( "Can't __set() $name; setting doesn't exist" );
214 }
215
216 $this->settings[ $name ] = $value;
217
218 }//end __set()
219
220
221 /**
222 * Check if the value of an inaccessible property is set.
223 *
224 * @param string $name The name of the property.
225 *
226 * @return bool
227 */
228 public function __isset( $name ) {
229 return isset( $this->settings[ $name ] );
230
231 }//end __isset()
232
233
234 /**
235 * Unset the value of an inaccessible property.
236 *
237 * @param string $name The name of the property.
238 *
239 * @return void
240 */
241 public function __unset( $name ) {
242 $this->settings[ $name ] = null;
243
244 }//end __unset()
245
246
247 /**
248 * Get the array of all config settings.
249 *
250 * @return array<string, mixed>
251 */
252 public function getSettings() {
253 return $this->settings;
254
255 }//end getSettings()
256
257
258 /**
259 * Set the array of all config settings.
260 *
261 * @param array<string, mixed> $settings The array of config settings.
262 *
263 * @return void
264 */
265 public function setSettings( $settings ) {
266 return $this->settings = $settings;
267
268 }//end setSettings()
269
270
271 /**
272 * Creates a Config object and populates it with command line values.
273 *
274 * @param array $cliArgs An array of values gathered from CLI args.
275 * @param bool $dieOnUnknownArg Whether or not to kill the process when an
276 * unknown command line arg is found.
277 *
278 * @return void
279 */
280 public function __construct( array $cliArgs = [], $dieOnUnknownArg = true ) {
281 if ( defined( 'PHP_CODESNIFFER_IN_TESTS' ) === true ) {
282 // Let everything through during testing so that we can
283 // make use of PHPUnit command line arguments as well.
284 $this->dieOnUnknownArg = false;
285 } else {
286 $this->dieOnUnknownArg = $dieOnUnknownArg;
287 }
288
289 if ( empty( $cliArgs ) === true ) {
290 $cliArgs = $_SERVER['argv'];
291 array_shift( $cliArgs );
292 }
293
294 $this->restoreDefaults();
295 $this->setCommandLineValues( $cliArgs );
296
297 if ( isset( self::$overriddenDefaults['standards'] ) === false ) {
298 // They did not supply a standard to use.
299 // Look for a default ruleset in the current directory or higher.
300 $currentDir = getcwd();
301
302 $defaultFiles = [
303 '.phpcs.xml',
304 'phpcs.xml',
305 '.phpcs.xml.dist',
306 'phpcs.xml.dist',
307 ];
308
309 do {
310 foreach ( $defaultFiles as $defaultFilename ) {
311 $default = $currentDir . DIRECTORY_SEPARATOR . $defaultFilename;
312 if ( is_file( $default ) === true ) {
313 $this->standards = [ $default ];
314 break( 2 );
315 }
316 }
317
318 $lastDir = $currentDir;
319 $currentDir = dirname( $currentDir );
320 } while ( $currentDir !== '.' && $currentDir !== $lastDir && @is_readable( $currentDir ) === true );
321 }//end if
322
323 if ( defined( 'STDIN' ) === false
324 || strtoupper( substr( PHP_OS, 0, 3 ) ) === 'WIN'
325 ) {
326 return;
327 }
328
329 $handle = fopen( 'php://stdin', 'r' );
330
331 fclose( $handle );
332
333 }//end __construct()
334
335
336 /**
337 * Set the command line values.
338 *
339 * @param array $args An array of command line arguments to set.
340 *
341 * @return void
342 */
343 public function setCommandLineValues( $args ) {
344 $this->cliArgs = $args;
345 $numArgs = count( $args );
346
347 for ( $i = 0; $i < $numArgs; $i ++ ) {
348 $arg = $this->cliArgs[ $i ];
349 if ( $arg === '' ) {
350 continue;
351 }
352
353 if ( $arg[0] === '-' ) {
354 if ( $arg === '-' ) {
355 // Asking to read from STDIN.
356 $this->stdin = true;
357 self::$overriddenDefaults['stdin'] = true;
358 continue;
359 }
360
361 if ( $arg === '--' ) {
362 // Empty argument, ignore it.
363 continue;
364 }
365
366 if ( $arg[1] === '-' ) {
367 $this->processLongArgument( substr( $arg, 2 ), $i );
368 } else {
369 $switches = str_split( $arg );
370 foreach ( $switches as $switch ) {
371 if ( $switch === '-' ) {
372 continue;
373 }
374
375 $this->processShortArgument( $switch, $i );
376 }
377 }
378 } else {
379 $this->processUnknownArgument( $arg, $i );
380 }//end if
381 }//end for
382
383 }//end setCommandLineValues()
384
385
386 /**
387 * Restore default values for all possible command line arguments.
388 *
389 * @return array
390 */
391 public function restoreDefaults() {
392 $this->files = [];
393 $this->standards = [ 'PEAR' ];
394 $this->verbosity = 0;
395 $this->interactive = false;
396 $this->cache = false;
397 $this->cacheFile = null;
398 $this->colors = false;
399 $this->explain = false;
400 $this->local = false;
401 $this->showSources = false;
402 $this->showProgress = false;
403 $this->quiet = false;
404 $this->annotations = true;
405 $this->parallel = 1;
406 $this->tabWidth = 0;
407 $this->encoding = 'utf-8';
408 $this->extensions = [
409 'php' => 'PHP',
410 'inc' => 'PHP',
411 'js' => 'JS',
412 'css' => 'CSS',
413 ];
414 $this->sniffs = [];
415 $this->exclude = [];
416 $this->ignored = [];
417 $this->reportFile = null;
418 $this->generator = null;
419 $this->filter = null;
420 $this->bootstrap = [];
421 $this->basepath = null;
422 $this->reports = [ 'full' => null ];
423 $this->reportWidth = 'auto';
424 $this->errorSeverity = 5;
425 $this->warningSeverity = 5;
426 $this->recordErrors = true;
427 $this->suffix = '';
428 $this->stdin = false;
429 $this->stdinContent = null;
430 $this->stdinPath = null;
431 $this->unknown = [];
432
433 $standard = self::getConfigData( 'default_standard' );
434 if ( $standard !== null ) {
435 $this->standards = explode( ',', $standard );
436 }
437
438 $reportFormat = self::getConfigData( 'report_format' );
439 if ( $reportFormat !== null ) {
440 $this->reports = [ $reportFormat => null ];
441 }
442
443 $tabWidth = self::getConfigData( 'tab_width' );
444 if ( $tabWidth !== null ) {
445 $this->tabWidth = (int) $tabWidth;
446 }
447
448 $encoding = self::getConfigData( 'encoding' );
449 if ( $encoding !== null ) {
450 $this->encoding = strtolower( $encoding );
451 }
452
453 $severity = self::getConfigData( 'severity' );
454 if ( $severity !== null ) {
455 $this->errorSeverity = (int) $severity;
456 $this->warningSeverity = (int) $severity;
457 }
458
459 $severity = self::getConfigData( 'error_severity' );
460 if ( $severity !== null ) {
461 $this->errorSeverity = (int) $severity;
462 }
463
464 $severity = self::getConfigData( 'warning_severity' );
465 if ( $severity !== null ) {
466 $this->warningSeverity = (int) $severity;
467 }
468
469 $showWarnings = self::getConfigData( 'show_warnings' );
470 if ( $showWarnings !== null ) {
471 $showWarnings = (bool) $showWarnings;
472 if ( $showWarnings === false ) {
473 $this->warningSeverity = 0;
474 }
475 }
476
477 $reportWidth = self::getConfigData( 'report_width' );
478 if ( $reportWidth !== null ) {
479 $this->reportWidth = $reportWidth;
480 }
481
482 $showProgress = self::getConfigData( 'show_progress' );
483 if ( $showProgress !== null ) {
484 $this->showProgress = (bool) $showProgress;
485 }
486
487 $quiet = self::getConfigData( 'quiet' );
488 if ( $quiet !== null ) {
489 $this->quiet = (bool) $quiet;
490 }
491
492 $colors = self::getConfigData( 'colors' );
493 if ( $colors !== null ) {
494 $this->colors = (bool) $colors;
495 }
496
497 if ( defined( 'PHP_CODESNIFFER_IN_TESTS' ) === false ) {
498 $cache = self::getConfigData( 'cache' );
499 if ( $cache !== null ) {
500 $this->cache = (bool) $cache;
501 }
502
503 $parallel = self::getConfigData( 'parallel' );
504 if ( $parallel !== null ) {
505 $this->parallel = max( (int) $parallel, 1 );
506 }
507 }
508
509 }//end restoreDefaults()
510
511
512 /**
513 * Processes a short (-e) command line argument.
514 *
515 * @param string $arg The command line argument.
516 * @param int $pos The position of the argument on the command line.
517 *
518 * @return void
519 * @throws \PHP_CodeSniffer\Exceptions\DeepExitException
520 */
521 public function processShortArgument( $arg, $pos ) {
522 switch ( $arg ) {
523 case 'h':
524 case '?':
525 ob_start();
526 $this->printUsage();
527 $output = ob_get_contents();
528 ob_end_clean();
529 throw new DeepExitException( $output, 0 );
530 case 'i' :
531 ob_start();
532 Util\Standards::printInstalledStandards();
533 $output = ob_get_contents();
534 ob_end_clean();
535 throw new DeepExitException( $output, 0 );
536 case 'v' :
537 if ( $this->quiet === true ) {
538 // Ignore when quiet mode is enabled.
539 break;
540 }
541
542 $this->verbosity ++;
543 self::$overriddenDefaults['verbosity'] = true;
544 break;
545 case 'l' :
546 $this->local = true;
547 self::$overriddenDefaults['local'] = true;
548 break;
549 case 's' :
550 $this->showSources = true;
551 self::$overriddenDefaults['showSources'] = true;
552 break;
553 case 'a' :
554 $this->interactive = true;
555 self::$overriddenDefaults['interactive'] = true;
556 break;
557 case 'e':
558 $this->explain = true;
559 self::$overriddenDefaults['explain'] = true;
560 break;
561 case 'p' :
562 if ( $this->quiet === true ) {
563 // Ignore when quiet mode is enabled.
564 break;
565 }
566
567 $this->showProgress = true;
568 self::$overriddenDefaults['showProgress'] = true;
569 break;
570 case 'q' :
571 // Quiet mode disables a few other settings as well.
572 $this->quiet = true;
573 $this->showProgress = false;
574 $this->verbosity = 0;
575
576 self::$overriddenDefaults['quiet'] = true;
577 break;
578 case 'm' :
579 $this->recordErrors = false;
580 self::$overriddenDefaults['recordErrors'] = true;
581 break;
582 case 'd' :
583 $ini = explode( '=', $this->cliArgs[ ( $pos + 1 ) ] );
584 $this->cliArgs[ ( $pos + 1 ) ] = '';
585 if ( isset( $ini[1] ) === true ) {
586 ini_set( $ini[0], $ini[1] );
587 } else {
588 ini_set( $ini[0], true );
589 }
590 break;
591 case 'n' :
592 if ( isset( self::$overriddenDefaults['warningSeverity'] ) === false ) {
593 $this->warningSeverity = 0;
594 self::$overriddenDefaults['warningSeverity'] = true;
595 }
596 break;
597 case 'w' :
598 if ( isset( self::$overriddenDefaults['warningSeverity'] ) === false ) {
599 $this->warningSeverity = $this->errorSeverity;
600 self::$overriddenDefaults['warningSeverity'] = true;
601 }
602 break;
603 default:
604 if ( $this->dieOnUnknownArg === false ) {
605 $unknown = $this->unknown;
606 $unknown[] = $arg;
607 $this->unknown = $unknown;
608 } else {
609 $this->processUnknownArgument( '-' . $arg, $pos );
610 }
611 }//end switch
612
613 }//end processShortArgument()
614
615
616 /**
617 * Processes a long (--example) command line argument.
618 *
619 * @param string $arg The command line argument.
620 * @param int $pos The position of the argument on the command line.
621 *
622 * @return void
623 * @throws \PHP_CodeSniffer\Exceptions\DeepExitException
624 */
625 public function processLongArgument( $arg, $pos ) {
626 switch ( $arg ) {
627 case 'help':
628 ob_start();
629 $this->printUsage();
630 $output = ob_get_contents();
631 ob_end_clean();
632 throw new DeepExitException( $output, 0 );
633 case 'version':
634 $output = 'PHP_CodeSniffer version ' . self::VERSION . ' (' . self::STABILITY . ') ';
635 $output .= 'by Squiz (http://www.squiz.net)' . PHP_EOL;
636 throw new DeepExitException( $output, 0 );
637 case 'colors':
638 if ( isset( self::$overriddenDefaults['colors'] ) === true ) {
639 break;
640 }
641
642 $this->colors = true;
643 self::$overriddenDefaults['colors'] = true;
644 break;
645 case 'no-colors':
646 if ( isset( self::$overriddenDefaults['colors'] ) === true ) {
647 break;
648 }
649
650 $this->colors = false;
651 self::$overriddenDefaults['colors'] = true;
652 break;
653 case 'cache':
654 if ( isset( self::$overriddenDefaults['cache'] ) === true ) {
655 break;
656 }
657
658 if ( defined( 'PHP_CODESNIFFER_IN_TESTS' ) === false ) {
659 $this->cache = true;
660 self::$overriddenDefaults['cache'] = true;
661 }
662 break;
663 case 'no-cache':
664 if ( isset( self::$overriddenDefaults['cache'] ) === true ) {
665 break;
666 }
667
668 $this->cache = false;
669 self::$overriddenDefaults['cache'] = true;
670 break;
671 case 'ignore-annotations':
672 if ( isset( self::$overriddenDefaults['annotations'] ) === true ) {
673 break;
674 }
675
676 $this->annotations = false;
677 self::$overriddenDefaults['annotations'] = true;
678 break;
679 case 'config-set':
680 if ( isset( $this->cliArgs[ ( $pos + 1 ) ] ) === false
681 || isset( $this->cliArgs[ ( $pos + 2 ) ] ) === false
682 ) {
683 $error = 'ERROR: Setting a config option requires a name and value' . PHP_EOL . PHP_EOL;
684 $error .= $this->printShortUsage( true );
685 throw new DeepExitException( $error, 3 );
686 }
687
688 $key = $this->cliArgs[ ( $pos + 1 ) ];
689 $value = $this->cliArgs[ ( $pos + 2 ) ];
690 $current = self::getConfigData( $key );
691
692 try {
693 $this->setConfigData( $key, $value );
694 } catch ( \Exception $e ) {
695 throw new DeepExitException( $e->getMessage() . PHP_EOL, 3 );
696 }
697
698 $output = 'Using config file: ' . self::$configDataFile . PHP_EOL . PHP_EOL;
699
700 if ( $current === null ) {
701 $output .= "Config value \"$key\" added successfully" . PHP_EOL;
702 } else {
703 $output .= "Config value \"$key\" updated successfully; old value was \"$current\"" . PHP_EOL;
704 }
705 throw new DeepExitException( $output, 0 );
706 case 'config-delete':
707 if ( isset( $this->cliArgs[ ( $pos + 1 ) ] ) === false ) {
708 $error = 'ERROR: Deleting a config option requires the name of the option' . PHP_EOL . PHP_EOL;
709 $error .= $this->printShortUsage( true );
710 throw new DeepExitException( $error, 3 );
711 }
712
713 $output = 'Using config file: ' . self::$configDataFile . PHP_EOL . PHP_EOL;
714
715 $key = $this->cliArgs[ ( $pos + 1 ) ];
716 $current = self::getConfigData( $key );
717 if ( $current === null ) {
718 $output .= "Config value \"$key\" has not been set" . PHP_EOL;
719 } else {
720 try {
721 $this->setConfigData( $key, null );
722 } catch ( \Exception $e ) {
723 throw new DeepExitException( $e->getMessage() . PHP_EOL, 3 );
724 }
725
726 $output .= "Config value \"$key\" removed successfully; old value was \"$current\"" . PHP_EOL;
727 }
728 throw new DeepExitException( $output, 0 );
729 case 'config-show':
730 ob_start();
731 $data = self::getAllConfigData();
732 echo 'Using config file: ' . self::$configDataFile . PHP_EOL . PHP_EOL;
733 $this->printConfigData( $data );
734 $output = ob_get_contents();
735 ob_end_clean();
736 throw new DeepExitException( $output, 0 );
737 case 'runtime-set':
738 if ( isset( $this->cliArgs[ ( $pos + 1 ) ] ) === false
739 || isset( $this->cliArgs[ ( $pos + 2 ) ] ) === false
740 ) {
741 $error = 'ERROR: Setting a runtime config option requires a name and value' . PHP_EOL . PHP_EOL;
742 $error .= $this->printShortUsage( true );
743 throw new DeepExitException( $error, 3 );
744 }
745
746 $key = $this->cliArgs[ ( $pos + 1 ) ];
747 $value = $this->cliArgs[ ( $pos + 2 ) ];
748 $this->cliArgs[ ( $pos + 1 ) ] = '';
749 $this->cliArgs[ ( $pos + 2 ) ] = '';
750 self::setConfigData( $key, $value, true );
751 if ( isset( self::$overriddenDefaults['runtime-set'] ) === false ) {
752 self::$overriddenDefaults['runtime-set'] = [];
753 }
754
755 self::$overriddenDefaults['runtime-set'][ $key ] = true;
756 break;
757 default:
758 if ( substr( $arg, 0, 7 ) === 'sniffs=' ) {
759 if ( isset( self::$overriddenDefaults['sniffs'] ) === true ) {
760 break;
761 }
762
763 $sniffs = explode( ',', substr( $arg, 7 ) );
764 foreach ( $sniffs as $sniff ) {
765 if ( substr_count( $sniff, '.' ) !== 2 ) {
766 $error = 'ERROR: The specified sniff code "' . $sniff . '" is invalid' . PHP_EOL . PHP_EOL;
767 $error .= $this->printShortUsage( true );
768 throw new DeepExitException( $error, 3 );
769 }
770 }
771
772 $this->sniffs = $sniffs;
773 self::$overriddenDefaults['sniffs'] = true;
774 } else if ( substr( $arg, 0, 8 ) === 'exclude=' ) {
775 if ( isset( self::$overriddenDefaults['exclude'] ) === true ) {
776 break;
777 }
778
779 $sniffs = explode( ',', substr( $arg, 8 ) );
780 foreach ( $sniffs as $sniff ) {
781 if ( substr_count( $sniff, '.' ) !== 2 ) {
782 $error = 'ERROR: The specified sniff code "' . $sniff . '" is invalid' . PHP_EOL . PHP_EOL;
783 $error .= $this->printShortUsage( true );
784 throw new DeepExitException( $error, 3 );
785 }
786 }
787
788 $this->exclude = $sniffs;
789 self::$overriddenDefaults['exclude'] = true;
790 } else if ( defined( 'PHP_CODESNIFFER_IN_TESTS' ) === false
791 && substr( $arg, 0, 6 ) === 'cache='
792 ) {
793 if ( ( isset( self::$overriddenDefaults['cache'] ) === true
794 && $this->cache === false )
795 || isset( self::$overriddenDefaults['cacheFile'] ) === true
796 ) {
797 break;
798 }
799
800 // Turn caching on.
801 $this->cache = true;
802 self::$overriddenDefaults['cache'] = true;
803
804 $this->cacheFile = Util\Common::realpath( substr( $arg, 6 ) );
805
806 // It may not exist and return false instead.
807 if ( $this->cacheFile === false ) {
808 $this->cacheFile = substr( $arg, 6 );
809
810 $dir = dirname( $this->cacheFile );
811 if ( is_dir( $dir ) === false ) {
812 $error = 'ERROR: The specified cache file path "' . $this->cacheFile . '" points to a non-existent directory' . PHP_EOL . PHP_EOL;
813 $error .= $this->printShortUsage( true );
814 throw new DeepExitException( $error, 3 );
815 }
816
817 if ( $dir === '.' ) {
818 // Passed cache file is a file in the current directory.
819 $this->cacheFile = getcwd() . '/' . basename( $this->cacheFile );
820 } else {
821 if ( $dir[0] === '/' ) {
822 // An absolute path.
823 $dir = Util\Common::realpath( $dir );
824 } else {
825 $dir = Util\Common::realpath( getcwd() . '/' . $dir );
826 }
827
828 if ( $dir !== false ) {
829 // Cache file path is relative.
830 $this->cacheFile = $dir . '/' . basename( $this->cacheFile );
831 }
832 }
833 }//end if
834
835 self::$overriddenDefaults['cacheFile'] = true;
836
837 if ( is_dir( $this->cacheFile ) === true ) {
838 $error = 'ERROR: The specified cache file path "' . $this->cacheFile . '" is a directory' . PHP_EOL . PHP_EOL;
839 $error .= $this->printShortUsage( true );
840 throw new DeepExitException( $error, 3 );
841 }
842 } else if ( substr( $arg, 0, 10 ) === 'bootstrap=' ) {
843 $files = explode( ',', substr( $arg, 10 ) );
844 $bootstrap = [];
845 foreach ( $files as $file ) {
846 $path = Util\Common::realpath( $file );
847 if ( $path === false ) {
848 $error = 'ERROR: The specified bootstrap file "' . $file . '" does not exist' . PHP_EOL . PHP_EOL;
849 $error .= $this->printShortUsage( true );
850 throw new DeepExitException( $error, 3 );
851 }
852
853 $bootstrap[] = $path;
854 }
855
856 $this->bootstrap = array_merge( $this->bootstrap, $bootstrap );
857 self::$overriddenDefaults['bootstrap'] = true;
858 } else if ( substr( $arg, 0, 10 ) === 'file-list=' ) {
859 $fileList = substr( $arg, 10 );
860 $path = Util\Common::realpath( $fileList );
861 if ( $path === false ) {
862 $error = 'ERROR: The specified file list "' . $fileList . '" does not exist' . PHP_EOL . PHP_EOL;
863 $error .= $this->printShortUsage( true );
864 throw new DeepExitException( $error, 3 );
865 }
866
867 $files = file( $path );
868 foreach ( $files as $inputFile ) {
869 $inputFile = trim( $inputFile );
870
871 // Skip empty lines.
872 if ( $inputFile === '' ) {
873 continue;
874 }
875
876 $this->processFilePath( $inputFile );
877 }
878 } else if ( substr( $arg, 0, 11 ) === 'stdin-path=' ) {
879 if ( isset( self::$overriddenDefaults['stdinPath'] ) === true ) {
880 break;
881 }
882
883 $this->stdinPath = Util\Common::realpath( substr( $arg, 11 ) );
884
885 // It may not exist and return false instead, so use whatever they gave us.
886 if ( $this->stdinPath === false ) {
887 $this->stdinPath = trim( substr( $arg, 11 ) );
888 }
889
890 self::$overriddenDefaults['stdinPath'] = true;
891 } else if ( PHP_CODESNIFFER_CBF === false && substr( $arg, 0, 12 ) === 'report-file=' ) {
892 if ( isset( self::$overriddenDefaults['reportFile'] ) === true ) {
893 break;
894 }
895
896 $this->reportFile = Util\Common::realpath( substr( $arg, 12 ) );
897
898 // It may not exist and return false instead.
899 if ( $this->reportFile === false ) {
900 $this->reportFile = substr( $arg, 12 );
901
902 $dir = Util\Common::realpath( dirname( $this->reportFile ) );
903 if ( is_dir( $dir ) === false ) {
904 $error = 'ERROR: The specified report file path "' . $this->reportFile . '" points to a non-existent directory' . PHP_EOL . PHP_EOL;
905 $error .= $this->printShortUsage( true );
906 throw new DeepExitException( $error, 3 );
907 }
908
909 $this->reportFile = $dir . '/' . basename( $this->reportFile );
910 }//end if
911
912 self::$overriddenDefaults['reportFile'] = true;
913
914 if ( is_dir( $this->reportFile ) === true ) {
915 $error = 'ERROR: The specified report file path "' . $this->reportFile . '" is a directory' . PHP_EOL . PHP_EOL;
916 $error .= $this->printShortUsage( true );
917 throw new DeepExitException( $error, 3 );
918 }
919 } else if ( substr( $arg, 0, 13 ) === 'report-width=' ) {
920 if ( isset( self::$overriddenDefaults['reportWidth'] ) === true ) {
921 break;
922 }
923
924 $this->reportWidth = substr( $arg, 13 );
925 self::$overriddenDefaults['reportWidth'] = true;
926 } else if ( substr( $arg, 0, 9 ) === 'basepath=' ) {
927 if ( isset( self::$overriddenDefaults['basepath'] ) === true ) {
928 break;
929 }
930
931 self::$overriddenDefaults['basepath'] = true;
932
933 if ( substr( $arg, 9 ) === '' ) {
934 $this->basepath = null;
935 break;
936 }
937
938 $this->basepath = Util\Common::realpath( substr( $arg, 9 ) );
939
940 // It may not exist and return false instead.
941 if ( $this->basepath === false ) {
942 $this->basepath = substr( $arg, 9 );
943 }
944
945 if ( is_dir( $this->basepath ) === false ) {
946 $error = 'ERROR: The specified basepath "' . $this->basepath . '" points to a non-existent directory' . PHP_EOL . PHP_EOL;
947 $error .= $this->printShortUsage( true );
948 throw new DeepExitException( $error, 3 );
949 }
950 } else if ( ( substr( $arg, 0, 7 ) === 'report=' || substr( $arg, 0, 7 ) === 'report-' ) ) {
951 $reports = [];
952
953 if ( $arg[6] === '-' ) {
954 // This is a report with file output.
955 $split = strpos( $arg, '=' );
956 if ( $split === false ) {
957 $report = substr( $arg, 7 );
958 $output = null;
959 } else {
960 $report = substr( $arg, 7, ( $split - 7 ) );
961 $output = substr( $arg, ( $split + 1 ) );
962 if ( $output === false ) {
963 $output = null;
964 } else {
965 $dir = Util\Common::realpath( dirname( $output ) );
966 if ( is_dir( $dir ) === false ) {
967 $error = 'ERROR: The specified ' . $report . ' report file path "' . $output . '" points to a non-existent directory' . PHP_EOL . PHP_EOL;
968 $error .= $this->printShortUsage( true );
969 throw new DeepExitException( $error, 3 );
970 }
971
972 $output = $dir . '/' . basename( $output );
973
974 if ( is_dir( $output ) === true ) {
975 $error = 'ERROR: The specified ' . $report . ' report file path "' . $output . '" is a directory' . PHP_EOL . PHP_EOL;
976 $error .= $this->printShortUsage( true );
977 throw new DeepExitException( $error, 3 );
978 }
979 }//end if
980 }//end if
981
982 $reports[ $report ] = $output;
983 } else {
984 // This is a single report.
985 if ( isset( self::$overriddenDefaults['reports'] ) === true ) {
986 break;
987 }
988
989 $reportNames = explode( ',', substr( $arg, 7 ) );
990 foreach ( $reportNames as $report ) {
991 $reports[ $report ] = null;
992 }
993 }//end if
994
995 // Remove the default value so the CLI value overrides it.
996 if ( isset( self::$overriddenDefaults['reports'] ) === false ) {
997 $this->reports = $reports;
998 } else {
999 $this->reports = array_merge( $this->reports, $reports );
1000 }
1001
1002 self::$overriddenDefaults['reports'] = true;
1003 } else if ( substr( $arg, 0, 7 ) === 'filter=' ) {
1004 if ( isset( self::$overriddenDefaults['filter'] ) === true ) {
1005 break;
1006 }
1007
1008 $this->filter = substr( $arg, 7 );
1009 self::$overriddenDefaults['filter'] = true;
1010 } else if ( substr( $arg, 0, 9 ) === 'standard=' ) {
1011 $standards = trim( substr( $arg, 9 ) );
1012 if ( $standards !== '' ) {
1013 $this->standards = explode( ',', $standards );
1014 }
1015
1016 self::$overriddenDefaults['standards'] = true;
1017 } else if ( substr( $arg, 0, 11 ) === 'extensions=' ) {
1018 if ( isset( self::$overriddenDefaults['extensions'] ) === true ) {
1019 break;
1020 }
1021
1022 $extensions = explode( ',', substr( $arg, 11 ) );
1023 $newExtensions = [];
1024 foreach ( $extensions as $ext ) {
1025 $slash = strpos( $ext, '/' );
1026 if ( $slash !== false ) {
1027 // They specified the tokenizer too.
1028 list( $ext, $tokenizer ) = explode( '/', $ext );
1029 $newExtensions[ $ext ] = strtoupper( $tokenizer );
1030 continue;
1031 }
1032
1033 if ( isset( $this->extensions[ $ext ] ) === true ) {
1034 $newExtensions[ $ext ] = $this->extensions[ $ext ];
1035 } else {
1036 $newExtensions[ $ext ] = 'PHP';
1037 }
1038 }
1039
1040 $this->extensions = $newExtensions;
1041 self::$overriddenDefaults['extensions'] = true;
1042 } else if ( substr( $arg, 0, 7 ) === 'suffix=' ) {
1043 if ( isset( self::$overriddenDefaults['suffix'] ) === true ) {
1044 break;
1045 }
1046
1047 $this->suffix = substr( $arg, 7 );
1048 self::$overriddenDefaults['suffix'] = true;
1049 } else if ( substr( $arg, 0, 9 ) === 'parallel=' ) {
1050 if ( isset( self::$overriddenDefaults['parallel'] ) === true ) {
1051 break;
1052 }
1053
1054 $this->parallel = max( (int) substr( $arg, 9 ), 1 );
1055 self::$overriddenDefaults['parallel'] = true;
1056 } else if ( substr( $arg, 0, 9 ) === 'severity=' ) {
1057 $this->errorSeverity = (int) substr( $arg, 9 );
1058 $this->warningSeverity = $this->errorSeverity;
1059 if ( isset( self::$overriddenDefaults['errorSeverity'] ) === false ) {
1060 self::$overriddenDefaults['errorSeverity'] = true;
1061 }
1062
1063 if ( isset( self::$overriddenDefaults['warningSeverity'] ) === false ) {
1064 self::$overriddenDefaults['warningSeverity'] = true;
1065 }
1066 } else if ( substr( $arg, 0, 15 ) === 'error-severity=' ) {
1067 if ( isset( self::$overriddenDefaults['errorSeverity'] ) === true ) {
1068 break;
1069 }
1070
1071 $this->errorSeverity = (int) substr( $arg, 15 );
1072 self::$overriddenDefaults['errorSeverity'] = true;
1073 } else if ( substr( $arg, 0, 17 ) === 'warning-severity=' ) {
1074 if ( isset( self::$overriddenDefaults['warningSeverity'] ) === true ) {
1075 break;
1076 }
1077
1078 $this->warningSeverity = (int) substr( $arg, 17 );
1079 self::$overriddenDefaults['warningSeverity'] = true;
1080 } else if ( substr( $arg, 0, 7 ) === 'ignore=' ) {
1081 if ( isset( self::$overriddenDefaults['ignored'] ) === true ) {
1082 break;
1083 }
1084
1085 // Split the ignore string on commas, unless the comma is escaped
1086 // using 1 or 3 slashes (\, or \\\,).
1087 $patterns = preg_split(
1088 '/(?<=(?<!\\\\)\\\\\\\\),|(?<!\\\\),/',
1089 substr( $arg, 7 )
1090 );
1091
1092 $ignored = [];
1093 foreach ( $patterns as $pattern ) {
1094 $pattern = trim( $pattern );
1095 if ( $pattern === '' ) {
1096 continue;
1097 }
1098
1099 $ignored[ $pattern ] = 'absolute';
1100 }
1101
1102 $this->ignored = $ignored;
1103 self::$overriddenDefaults['ignored'] = true;
1104 } else if ( substr( $arg, 0, 10 ) === 'generator='
1105 && PHP_CODESNIFFER_CBF === false
1106 ) {
1107 if ( isset( self::$overriddenDefaults['generator'] ) === true ) {
1108 break;
1109 }
1110
1111 $this->generator = substr( $arg, 10 );
1112 self::$overriddenDefaults['generator'] = true;
1113 } else if ( substr( $arg, 0, 9 ) === 'encoding=' ) {
1114 if ( isset( self::$overriddenDefaults['encoding'] ) === true ) {
1115 break;
1116 }
1117
1118 $this->encoding = strtolower( substr( $arg, 9 ) );
1119 self::$overriddenDefaults['encoding'] = true;
1120 } else if ( substr( $arg, 0, 10 ) === 'tab-width=' ) {
1121 if ( isset( self::$overriddenDefaults['tabWidth'] ) === true ) {
1122 break;
1123 }
1124
1125 $this->tabWidth = (int) substr( $arg, 10 );
1126 self::$overriddenDefaults['tabWidth'] = true;
1127 } else {
1128 if ( $this->dieOnUnknownArg === false ) {
1129 $eqPos = strpos( $arg, '=' );
1130 try {
1131 if ( $eqPos === false ) {
1132 $this->values[ $arg ] = $arg;
1133 } else {
1134 $value = substr( $arg, ( $eqPos + 1 ) );
1135 $arg = substr( $arg, 0, $eqPos );
1136 $this->values[ $arg ] = $value;
1137 }
1138 } catch ( RuntimeException $e ) {
1139 // Value is not valid, so just ignore it.
1140 }
1141 } else {
1142 $this->processUnknownArgument( '--' . $arg, $pos );
1143 }
1144 }//end if
1145 break;
1146 }//end switch
1147
1148 }//end processLongArgument()
1149
1150
1151 /**
1152 * Processes an unknown command line argument.
1153 *
1154 * Assumes all unknown arguments are files and folders to check.
1155 *
1156 * @param string $arg The command line argument.
1157 * @param int $pos The position of the argument on the command line.
1158 *
1159 * @return void
1160 * @throws \PHP_CodeSniffer\Exceptions\DeepExitException
1161 */
1162 public function processUnknownArgument( $arg, $pos ) {
1163 // We don't know about any additional switches; just files.
1164 if ( $arg[0] === '-' ) {
1165 if ( $this->dieOnUnknownArg === false ) {
1166 return;
1167 }
1168
1169 $error = "ERROR: option \"$arg\" not known" . PHP_EOL . PHP_EOL;
1170 $error .= $this->printShortUsage( true );
1171 throw new DeepExitException( $error, 3 );
1172 }
1173
1174 $this->processFilePath( $arg );
1175
1176 }//end processUnknownArgument()
1177
1178
1179 /**
1180 * Processes a file path and add it to the file list.
1181 *
1182 * @param string $path The path to the file to add.
1183 *
1184 * @return void
1185 * @throws \PHP_CodeSniffer\Exceptions\DeepExitException
1186 */
1187 public function processFilePath( $path ) {
1188 // If we are processing STDIN, don't record any files to check.
1189 if ( $this->stdin === true ) {
1190 return;
1191 }
1192
1193 $file = Util\Common::realpath( $path );
1194 if ( file_exists( $file ) === false ) {
1195 if ( $this->dieOnUnknownArg === false ) {
1196 return;
1197 }
1198
1199 $error = 'ERROR: The file "' . $path . '" does not exist.' . PHP_EOL . PHP_EOL;
1200 $error .= $this->printShortUsage( true );
1201 throw new DeepExitException( $error, 3 );
1202 } else {
1203 // Can't modify the files array directly because it's not a real
1204 // class member, so need to use this little get/modify/set trick.
1205 $files = $this->files;
1206 $files[] = $file;
1207 $this->files = $files;
1208 self::$overriddenDefaults['files'] = true;
1209 }
1210
1211 }//end processFilePath()
1212
1213
1214 /**
1215 * Prints out the usage information for this script.
1216 *
1217 * @return void
1218 */
1219 public function printUsage() {
1220 echo PHP_EOL;
1221
1222 if ( PHP_CODESNIFFER_CBF === true ) {
1223 $this->printPHPCBFUsage();
1224 } else {
1225 $this->printPHPCSUsage();
1226 }
1227
1228 echo PHP_EOL;
1229
1230 }//end printUsage()
1231
1232
1233 /**
1234 * Prints out the short usage information for this script.
1235 *
1236 * @param bool $return If TRUE, the usage string is returned
1237 * instead of output to screen.
1238 *
1239 * @return string|void
1240 */
1241 public function printShortUsage( $return = false ) {
1242 if ( PHP_CODESNIFFER_CBF === true ) {
1243 $usage = 'Run "phpcbf --help" for usage information';
1244 } else {
1245 $usage = 'Run "phpcs --help" for usage information';
1246 }
1247
1248 $usage .= PHP_EOL . PHP_EOL;
1249
1250 if ( $return === true ) {
1251 return $usage;
1252 }
1253
1254 echo $usage;
1255
1256 }//end printShortUsage()
1257
1258
1259 /**
1260 * Prints out the usage information for PHPCS.
1261 *
1262 * @return void
1263 */
1264 public function printPHPCSUsage() {
1265 echo 'Usage: phpcs [-nwlsaepqvi] [-d key[=value]] [--colors] [--no-colors]' . PHP_EOL;
1266 echo ' [--cache[=<cacheFile>]] [--no-cache] [--tab-width=<tabWidth>]' . PHP_EOL;
1267 echo ' [--report=<report>] [--report-file=<reportFile>] [--report-<report>=<reportFile>]' . PHP_EOL;
1268 echo ' [--report-width=<reportWidth>] [--basepath=<basepath>] [--bootstrap=<bootstrap>]' . PHP_EOL;
1269 echo ' [--severity=<severity>] [--error-severity=<severity>] [--warning-severity=<severity>]' . PHP_EOL;
1270 echo ' [--runtime-set key value] [--config-set key value] [--config-delete key] [--config-show]' . PHP_EOL;
1271 echo ' [--standard=<standard>] [--sniffs=<sniffs>] [--exclude=<sniffs>]' . PHP_EOL;
1272 echo ' [--encoding=<encoding>] [--parallel=<processes>] [--generator=<generator>]' . PHP_EOL;
1273 echo ' [--extensions=<extensions>] [--ignore=<patterns>] [--ignore-annotations]' . PHP_EOL;
1274 echo ' [--stdin-path=<stdinPath>] [--file-list=<fileList>] [--filter=<filter>] <file> - ...' . PHP_EOL;
1275 echo PHP_EOL;
1276 echo ' - Check STDIN instead of local files and directories' . PHP_EOL;
1277 echo ' -n Do not print warnings (shortcut for --warning-severity=0)' . PHP_EOL;
1278 echo ' -w Print both warnings and errors (this is the default)' . PHP_EOL;
1279 echo ' -l Local directory only, no recursion' . PHP_EOL;
1280 echo ' -s Show sniff codes in all reports' . PHP_EOL;
1281 echo ' -a Run interactively' . PHP_EOL;
1282 echo ' -e Explain a standard by showing the sniffs it includes' . PHP_EOL;
1283 echo ' -p Show progress of the run' . PHP_EOL;
1284 echo ' -q Quiet mode; disables progress and verbose output' . PHP_EOL;
1285 echo ' -m Stop error messages from being recorded' . PHP_EOL;
1286 echo ' (saves a lot of memory, but stops many reports from being used)' . PHP_EOL;
1287 echo ' -v Print processed files' . PHP_EOL;
1288 echo ' -vv Print ruleset and token output' . PHP_EOL;
1289 echo ' -vvv Print sniff processing information' . PHP_EOL;
1290 echo ' -i Show a list of installed coding standards' . PHP_EOL;
1291 echo ' -d Set the [key] php.ini value to [value] or [true] if value is omitted' . PHP_EOL;
1292 echo PHP_EOL;
1293 echo ' --help Print this help message' . PHP_EOL;
1294 echo ' --version Print version information' . PHP_EOL;
1295 echo ' --colors Use colors in output' . PHP_EOL;
1296 echo ' --no-colors Do not use colors in output (this is the default)' . PHP_EOL;
1297 echo ' --cache Cache results between runs' . PHP_EOL;
1298 echo ' --no-cache Do not cache results between runs (this is the default)' . PHP_EOL;
1299 echo ' --ignore-annotations Ignore all phpcs: annotations in code comments' . PHP_EOL;
1300 echo PHP_EOL;
1301 echo ' <cacheFile> Use a specific file for caching (uses a temporary file by default)' . PHP_EOL;
1302 echo ' <basepath> A path to strip from the front of file paths inside reports' . PHP_EOL;
1303 echo ' <bootstrap> A comma separated list of files to run before processing begins' . PHP_EOL;
1304 echo ' <encoding> The encoding of the files being checked (default is utf-8)' . PHP_EOL;
1305 echo ' <extensions> A comma separated list of file extensions to check' . PHP_EOL;
1306 echo ' The type of the file can be specified using: ext/type' . PHP_EOL;
1307 echo ' e.g., module/php,es/js' . PHP_EOL;
1308 echo ' <file> One or more files and/or directories to check' . PHP_EOL;
1309 echo ' <fileList> A file containing a list of files and/or directories to check (one per line)' . PHP_EOL;
1310 echo ' <filter> Use either the "gitmodified" or "gitstaged" filter,' . PHP_EOL;
1311 echo ' or specify the path to a custom filter class' . PHP_EOL;
1312 echo ' <generator> Use either the "HTML", "Markdown" or "Text" generator' . PHP_EOL;
1313 echo ' (forces documentation generation instead of checking)' . PHP_EOL;
1314 echo ' <patterns> A comma separated list of patterns to ignore files and directories' . PHP_EOL;
1315 echo ' <processes> How many files should be checked simultaneously (default is 1)' . PHP_EOL;
1316 echo ' <report> Print either the "full", "xml", "checkstyle", "csv"' . PHP_EOL;
1317 echo ' "json", "junit", "emacs", "source", "summary", "diff"' . PHP_EOL;
1318 echo ' "svnblame", "gitblame", "hgblame" or "notifysend" report,' . PHP_EOL;
1319 echo ' or specify the path to a custom report class' . PHP_EOL;
1320 echo ' (the "full" report is printed by default)' . PHP_EOL;
1321 echo ' <reportFile> Write the report to the specified file path' . PHP_EOL;
1322 echo ' <reportWidth> How many columns wide screen reports should be printed' . PHP_EOL;
1323 echo ' or set to "auto" to use current screen width, where supported' . PHP_EOL;
1324 echo ' <severity> The minimum severity required to display an error or warning' . PHP_EOL;
1325 echo ' <sniffs> A comma separated list of sniff codes to include or exclude from checking' . PHP_EOL;
1326 echo ' (all sniffs must be part of the specified standard)' . PHP_EOL;
1327 echo ' <standard> The name or path of the coding standard to use' . PHP_EOL;
1328 echo ' <stdinPath> If processing STDIN, the file path that STDIN will be processed as' . PHP_EOL;
1329 echo ' <tabWidth> The number of spaces each tab represents' . PHP_EOL;
1330
1331 }//end printPHPCSUsage()
1332
1333
1334 /**
1335 * Prints out the usage information for PHPCBF.
1336 *
1337 * @return void
1338 */
1339 public function printPHPCBFUsage() {
1340 echo 'Usage: phpcbf [-nwli] [-d key[=value]] [--ignore-annotations] [--bootstrap=<bootstrap>]' . PHP_EOL;
1341 echo ' [--standard=<standard>] [--sniffs=<sniffs>] [--exclude=<sniffs>] [--suffix=<suffix>]' . PHP_EOL;
1342 echo ' [--severity=<severity>] [--error-severity=<severity>] [--warning-severity=<severity>]' . PHP_EOL;
1343 echo ' [--tab-width=<tabWidth>] [--encoding=<encoding>] [--parallel=<processes>]' . PHP_EOL;
1344 echo ' [--basepath=<basepath>] [--extensions=<extensions>] [--ignore=<patterns>]' . PHP_EOL;
1345 echo ' [--stdin-path=<stdinPath>] [--file-list=<fileList>] [--filter=<filter>] <file> - ...' . PHP_EOL;
1346 echo PHP_EOL;
1347 echo ' - Fix STDIN instead of local files and directories' . PHP_EOL;
1348 echo ' -n Do not fix warnings (shortcut for --warning-severity=0)' . PHP_EOL;
1349 echo ' -w Fix both warnings and errors (on by default)' . PHP_EOL;
1350 echo ' -l Local directory only, no recursion' . PHP_EOL;
1351 echo ' -p Show progress of the run' . PHP_EOL;
1352 echo ' -q Quiet mode; disables progress and verbose output' . PHP_EOL;
1353 echo ' -v Print processed files' . PHP_EOL;
1354 echo ' -vv Print ruleset and token output' . PHP_EOL;
1355 echo ' -vvv Print sniff processing information' . PHP_EOL;
1356 echo ' -i Show a list of installed coding standards' . PHP_EOL;
1357 echo ' -d Set the [key] php.ini value to [value] or [true] if value is omitted' . PHP_EOL;
1358 echo PHP_EOL;
1359 echo ' --help Print this help message' . PHP_EOL;
1360 echo ' --version Print version information' . PHP_EOL;
1361 echo ' --ignore-annotations Ignore all phpcs: annotations in code comments' . PHP_EOL;
1362 echo PHP_EOL;
1363 echo ' <basepath> A path to strip from the front of file paths inside reports' . PHP_EOL;
1364 echo ' <bootstrap> A comma separated list of files to run before processing begins' . PHP_EOL;
1365 echo ' <encoding> The encoding of the files being fixed (default is utf-8)' . PHP_EOL;
1366 echo ' <extensions> A comma separated list of file extensions to fix' . PHP_EOL;
1367 echo ' The type of the file can be specified using: ext/type' . PHP_EOL;
1368 echo ' e.g., module/php,es/js' . PHP_EOL;
1369 echo ' <file> One or more files and/or directories to fix' . PHP_EOL;
1370 echo ' <fileList> A file containing a list of files and/or directories to fix (one per line)' . PHP_EOL;
1371 echo ' <filter> Use either the "gitmodified" or "gitstaged" filter,' . PHP_EOL;
1372 echo ' or specify the path to a custom filter class' . PHP_EOL;
1373 echo ' <patterns> A comma separated list of patterns to ignore files and directories' . PHP_EOL;
1374 echo ' <processes> How many files should be fixed simultaneously (default is 1)' . PHP_EOL;
1375 echo ' <severity> The minimum severity required to fix an error or warning' . PHP_EOL;
1376 echo ' <sniffs> A comma separated list of sniff codes to include or exclude from fixing' . PHP_EOL;
1377 echo ' (all sniffs must be part of the specified standard)' . PHP_EOL;
1378 echo ' <standard> The name or path of the coding standard to use' . PHP_EOL;
1379 echo ' <stdinPath> If processing STDIN, the file path that STDIN will be processed as' . PHP_EOL;
1380 echo ' <suffix> Write modified files to a filename using this suffix' . PHP_EOL;
1381 echo ' ("diff" and "patch" are not used in this mode)' . PHP_EOL;
1382 echo ' <tabWidth> The number of spaces each tab represents' . PHP_EOL;
1383
1384 }//end printPHPCBFUsage()
1385
1386
1387 /**
1388 * Get a single config value.
1389 *
1390 * @param string $key The name of the config value.
1391 *
1392 * @return string|null
1393 * @see setConfigData()
1394 * @see getAllConfigData()
1395 */
1396 public static function getConfigData( $key ) {
1397 $phpCodeSnifferConfig = self::getAllConfigData();
1398
1399 if ( $phpCodeSnifferConfig === null ) {
1400 return null;
1401 }
1402
1403 if ( isset( $phpCodeSnifferConfig[ $key ] ) === false ) {
1404 return null;
1405 }
1406
1407 return $phpCodeSnifferConfig[ $key ];
1408
1409 }//end getConfigData()
1410
1411
1412 /**
1413 * Set a single config value.
1414 *
1415 * @param string $key The name of the config value.
1416 * @param string|null $value The value to set. If null, the config
1417 * entry is deleted, reverting it to the
1418 * default value.
1419 * @param boolean $temp Set this config data temporarily for this
1420 * script run. This will not write the config
1421 * data to the config file.
1422 *
1423 * @return bool
1424 * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If the config file can not be written.
1425 * @see getConfigData()
1426 */
1427 public static function setConfigData( $key, $value, $temp = false ) {
1428 if ( isset( self::$overriddenDefaults['runtime-set'] ) === true
1429 && isset( self::$overriddenDefaults['runtime-set'][ $key ] ) === true
1430 ) {
1431 return false;
1432 }
1433
1434 if ( $temp === false ) {
1435 $path = '';
1436 if ( is_callable( '\Phar::running' ) === true ) {
1437 $path = \Phar::running( false );
1438 }
1439
1440 if ( $path !== '' ) {
1441 $configFile = dirname( $path ) . DIRECTORY_SEPARATOR . 'CodeSniffer.conf';
1442 } else {
1443 $configFile = dirname( __DIR__ ) . DIRECTORY_SEPARATOR . 'CodeSniffer.conf';
1444 if ( is_file( $configFile ) === false
1445 && strpos( '@data_dir@', '@data_dir' ) === false
1446 ) {
1447 // If data_dir was replaced, this is a PEAR install and we can
1448 // use the PEAR data dir to store the conf file.
1449 $configFile = '@data_dir@/PHP_CodeSniffer/CodeSniffer.conf';
1450 }
1451 }
1452
1453 if ( is_file( $configFile ) === true
1454 && is_writable( $configFile ) === false
1455 ) {
1456 $error = 'ERROR: Config file ' . $configFile . ' is not writable' . PHP_EOL . PHP_EOL;
1457 throw new DeepExitException( $error, 3 );
1458 }
1459 }//end if
1460
1461 $phpCodeSnifferConfig = self::getAllConfigData();
1462
1463 if ( $value === null ) {
1464 if ( isset( $phpCodeSnifferConfig[ $key ] ) === true ) {
1465 unset( $phpCodeSnifferConfig[ $key ] );
1466 }
1467 } else {
1468 $phpCodeSnifferConfig[ $key ] = $value;
1469 }
1470
1471 if ( $temp === false ) {
1472 $output = '<' . '?php' . "\n" . ' $phpCodeSnifferConfig = ';
1473 $output .= var_export( $phpCodeSnifferConfig, true );
1474 $output .= "\n?" . '>';
1475
1476 if ( file_put_contents( $configFile, $output ) === false ) {
1477 $error = 'ERROR: Config file ' . $configFile . ' could not be written' . PHP_EOL . PHP_EOL;
1478 throw new DeepExitException( $error, 3 );
1479 }
1480
1481 self::$configDataFile = $configFile;
1482 }
1483
1484 self::$configData = $phpCodeSnifferConfig;
1485
1486 // If the installed paths are being set, make sure all known
1487 // standards paths are added to the autoloader.
1488 if ( $key === 'installed_paths' ) {
1489 $installedStandards = Util\Standards::getInstalledStandardDetails();
1490 foreach ( $installedStandards as $name => $details ) {
1491 Autoload::addSearchPath( $details['path'], $details['namespace'] );
1492 }
1493 }
1494
1495 return true;
1496
1497 }//end setConfigData()
1498
1499
1500 /**
1501 * Get all config data.
1502 *
1503 * @return array<string, string>
1504 * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If the config file could not be read.
1505 * @see getConfigData()
1506 */
1507 public static function getAllConfigData() {
1508 if ( self::$configData !== null ) {
1509 return self::$configData;
1510 }
1511
1512 $path = '';
1513 if ( is_callable( '\Phar::running' ) === true ) {
1514 $path = \Phar::running( false );
1515 }
1516
1517 if ( $path !== '' ) {
1518 $configFile = dirname( $path ) . DIRECTORY_SEPARATOR . 'CodeSniffer.conf';
1519 } else {
1520 $configFile = dirname( __DIR__ ) . DIRECTORY_SEPARATOR . 'CodeSniffer.conf';
1521 if ( is_file( $configFile ) === false
1522 && strpos( '@data_dir@', '@data_dir' ) === false
1523 ) {
1524 $configFile = '@data_dir@/PHP_CodeSniffer/CodeSniffer.conf';
1525 }
1526 }
1527
1528 if ( is_file( $configFile ) === false ) {
1529 self::$configData = [];
1530
1531 return [];
1532 }
1533
1534 if ( is_readable( $configFile ) === false ) {
1535 $error = 'ERROR: Config file ' . $configFile . ' is not readable' . PHP_EOL . PHP_EOL;
1536 throw new DeepExitException( $error, 3 );
1537 }
1538
1539 include $configFile;
1540 self::$configDataFile = $configFile;
1541 self::$configData = $phpCodeSnifferConfig;
1542
1543 return self::$configData;
1544
1545 }//end getAllConfigData()
1546
1547
1548 /**
1549 * Prints out the gathered config data.
1550 *
1551 * @param array $data The config data to print.
1552 *
1553 * @return void
1554 */
1555 public function printConfigData( $data ) {
1556 $max = 0;
1557 $keys = array_keys( $data );
1558 foreach ( $keys as $key ) {
1559 $len = strlen( $key );
1560 if ( strlen( $key ) > $max ) {
1561 $max = $len;
1562 }
1563 }
1564
1565 if ( $max === 0 ) {
1566 return;
1567 }
1568
1569 $max += 2;
1570 ksort( $data );
1571 foreach ( $data as $name => $value ) {
1572 echo str_pad( $name . ': ', $max ) . $value . PHP_EOL;
1573 }
1574
1575 }//end printConfigData()
1576
1577
1578 }//end class
1579