PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 3.1.0
Defender Security – Malware Scanner, Login Security & Firewall v3.1.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 3.1.0, at src/extra/php-codesniffer-php-token/Config.php

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