CommandLineOptions::baselineFile()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php
2
/**
3
 * This file is part of PHP Mess Detector.
4
 *
5
 * Copyright (c) Manuel Pichler <[email protected]>.
6
 * All rights reserved.
7
 *
8
 * Licensed under BSD License
9
 * For full copyright and license information, please see the LICENSE file.
10
 * Redistributions of files must retain the above copyright notice.
11
 *
12
 * @author    Manuel Pichler <[email protected]>
13
 * @copyright Manuel Pichler. All rights reserved.
14
 * @license   https://opensource.org/licenses/bsd-license.php BSD License
15
 * @link      http://phpmd.org/
16
 */
17
18
namespace PHPMD\TextUI;
19
20
use InvalidArgumentException;
21
use PHPMD\Baseline\BaselineMode;
22
use PHPMD\Cache\Model\ResultCacheStrategy;
23
use PHPMD\Console\OutputInterface;
24
use PHPMD\Renderer\AnsiRenderer;
25
use PHPMD\Renderer\CheckStyleRenderer;
26
use PHPMD\Renderer\GitHubRenderer;
27
use PHPMD\Renderer\GitLabRenderer;
28
use PHPMD\Renderer\HTMLRenderer;
29
use PHPMD\Renderer\JSONRenderer;
30
use PHPMD\Renderer\Option\Color;
31
use PHPMD\Renderer\Option\Verbose;
32
use PHPMD\Renderer\SARIFRenderer;
33
use PHPMD\Renderer\TextRenderer;
34
use PHPMD\Renderer\XMLRenderer;
35
use PHPMD\Rule;
36
use PHPMD\Utility\ArgumentsValidator;
37
38
/**
39
 * This is a helper class that collects the specified cli arguments and puts them
40
 * into accessible properties.
41
 *
42
 * @SuppressWarnings(PHPMD.LongVariable)
43
 */
44
class CommandLineOptions
45
{
46
    /**
47
     * Error code for invalid input
48
     */
49
    const INPUT_ERROR = 23;
50
51
    /**
52
     * The minimum rule priority.
53
     *
54
     * @var integer
55
     */
56
    protected $minimumPriority = Rule::LOWEST_PRIORITY;
57
58
    /**
59
     * The maximum rule priority.
60
     *
61
     * @var integer
62
     */
63
    protected $maximumPriority = Rule::HIGHEST_PRIORITY;
64
65
    /**
66
     * A php source code filename or directory.
67
     *
68
     * @var string
69
     */
70
    protected $inputPath;
71
72
    /**
73
     * The specified report format.
74
     *
75
     * @var string
76
     */
77
    protected $reportFormat;
78
79
    /**
80
     * An optional filename for the generated report.
81
     *
82
     * @var string
83
     */
84
    protected $reportFile;
85
86
    /**
87
     * An optional filename to collect errors.
88
     *
89
     * @var string
90
     */
91
    protected $errorFile;
92
93
    /**
94
     * Additional report files.
95
     *
96
     * @var array
97
     */
98
    protected $reportFiles = array();
99
100
    /**
101
     * List of deprecations.
102
     *
103
     * @var array
104
     */
105
    protected $deprecations = array();
106
107
    /**
108
     * A ruleset filename or a comma-separated string of ruleset filenames.
109
     *
110
     * @var string
111
     */
112
    protected $ruleSets;
113
114
    /**
115
     * File name of a PHPUnit code coverage report.
116
     *
117
     * @var string
118
     */
119
    protected $coverageReport;
120
121
    /**
122
     * A string of comma-separated extensions for valid php source code filenames.
123
     *
124
     * @var string
125
     */
126
    protected $extensions;
127
128
    /**
129
     * A string of comma-separated pattern that is used to exclude directories.
130
     *
131
     * Use asterisks to exclude by pattern. For example *src/foo/*.php or *src/foo/*
132
     *
133
     * @var string
134
     */
135
    protected $ignore;
136
137
    /**
138
     * Should the shell show the current phpmd version?
139
     *
140
     * @var boolean
141
     */
142
    protected $version = false;
143
144
    /**
145
     * Should PHPMD run in strict mode?
146
     *
147
     * @var boolean
148
     * @since 1.2.0
149
     */
150
    protected $strict = false;
151
152
    /** @var int */
153
    protected $verbosity = OutputInterface::VERBOSITY_NORMAL;
154
155
    /**
156
     * Should PHPMD exit without error code even if error is found?
157
     *
158
     * @var boolean
159
     * @since 2.10.0
160
     */
161
    protected $ignoreErrorsOnExit = false;
162
163
    /**
164
     * Should PHPMD exit without error code even if violation is found?
165
     *
166
     * @var boolean
167
     */
168
    protected $ignoreViolationsOnExit = false;
169
170
    /**
171
     * List of available rule-sets.
172
     *
173
     * @var array(string)
174
     */
175
    protected $availableRuleSets = array();
176
177
    /**
178
     * Should PHPMD baseline the existing violations and write them to the $baselineFile
179
     * @var string allowed modes: NONE, GENERATE or UPDATE
180
     */
181
    protected $generateBaseline = BaselineMode::NONE;
182
183
    /**
184
     * The baseline source file to read the baseline violations from.
185
     * Defaults to the path of the (first) ruleset file as phpmd.baseline.xml
186
     * @var string|null
187
     */
188
    protected $baselineFile;
189
190
    /**
191
     * Should PHPMD read or write the result cache state from the cache file
192
     * @var bool
193
     */
194
    protected $cacheEnabled = false;
195
196
    /**
197
     * If set the path to read and write the result cache state from and to.
198
     * @var string|null
199
     */
200
    protected $cacheFile;
201
202
    /**
203
     * If set determine the cache strategy. Either `content` or `timestamp`. Defaults to `content`.
204
     * @var string|null
205
     */
206
    protected $cacheStrategy;
207
208
    /**
209
     * Either the output should be colored.
210
     *
211
     * @var bool
212
     */
213
    protected $colored = false;
214
215
    /**
216
     * Specify how many extra lines are added to a code snippet
217
     * @var int|null
218
     */
219
    protected $extraLineInExcerpt;
220
221
    /**
222
     * Constructs a new command line options instance.
223
     *
224
     * @param string[] $args
225
     * @param string[] $availableRuleSets
226
     * @throws InvalidArgumentException
227
     */
228 73
    public function __construct(array $args, array $availableRuleSets = array())
229
    {
230
        // Remove current file name
231 73
        array_shift($args);
232
233 73
        $originalArguments = $args;
234 73
        $this->availableRuleSets = $availableRuleSets;
235
236 73
        $arguments = array();
237 73
        $listenOptions = true;
238 73
        $hasImplicitArguments = false;
239
240 73
        while (($arg = array_shift($args)) !== null) {
241 73
            if (!$listenOptions) {
242 2
                $arguments[] = $arg;
243
244 2
                continue;
245
            }
246
247 73
            $equalChunk = explode('=', $arg, 2);
248
249 73
            switch ($equalChunk[0]) {
250 73
                case '--':
251 2
                    $this->refuseValue($equalChunk);
252 2
                    $listenOptions = false;
253 2
                    break;
254 72
                case '--verbose':
255 72
                case '-v':
256 1
                    $this->refuseValue($equalChunk);
257 1
                    $this->verbosity = OutputInterface::VERBOSITY_VERBOSE;
258 1
                    break;
259 72
                case '-vv':
260 1
                    $this->refuseValue($equalChunk);
261 1
                    $this->verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE;
262 1
                    break;
263 72
                case '-vvv':
264 2
                    $this->refuseValue($equalChunk);
265 2
                    $this->verbosity = OutputInterface::VERBOSITY_DEBUG;
266 2
                    break;
267 72
                case '--min-priority':
268 72
                case '--minimum-priority':
269 72
                case '--minimumpriority':
270 1
                    $this->minimumPriority = (int)$this->readValue($equalChunk, $args);
271 1
                    break;
272 72
                case '--max-priority':
273 72
                case '--maximum-priority':
274 72
                case '--maximumpriority':
275 1
                    $this->maximumPriority = (int)$this->readValue($equalChunk, $args);
276 1
                    break;
277 72
                case '--report-file':
278 72
                case '--reportfile':
279 4
                    $this->reportFile = $this->readValue($equalChunk, $args);
280 4
                    break;
281 72
                case '--error-file':
282 72
                case '--errorfile':
283 1
                    $this->errorFile = $this->readValue($equalChunk, $args);
284 1
                    break;
285 72
                case '--input-file':
286 72
                case '--inputfile':
287 6
                    array_unshift($arguments, $this->readInputFile($this->readValue($equalChunk, $args)));
288 5
                    break;
289 72
                case '--coverage':
290 1
                    $this->coverageReport = $this->readValue($equalChunk, $args);
291 1
                    break;
292 72
                case '--extensions':
293 1
                    $this->logDeprecated('extensions', 'suffixes');
294
                    /* Deprecated: We use the suffixes option now */
295 1
                    $this->extensions = $this->readValue($equalChunk, $args);
296 1
                    break;
297 72
                case '--suffixes':
298 1
                    $this->extensions = $this->readValue($equalChunk, $args);
299 1
                    break;
300 72
                case '--ignore':
301 2
                    $this->logDeprecated('ignore', 'exclude');
302
                    /* Deprecated: We use the exclude option now */
303 2
                    $this->ignore = $this->readValue($equalChunk, $args);
304 2
                    break;
305 72
                case '--exclude':
306 3
                    $this->ignore = $this->readValue($equalChunk, $args);
307 3
                    break;
308 72
                case '--color':
309 2
                    $this->refuseValue($equalChunk);
310 1
                    $this->colored = true;
311 1
                    break;
312 71
                case '--version':
313 1
                    $this->refuseValue($equalChunk);
314 1
                    $this->version = true;
315
316 1
                    return;
317 70
                case '--strict':
318 1
                    $this->refuseValue($equalChunk);
319 1
                    $this->strict = true;
320 1
                    break;
321 70
                case '--not-strict':
322 1
                    $this->refuseValue($equalChunk);
323 1
                    $this->strict = false;
324 1
                    break;
325 70
                case '--generate-baseline':
326 1
                    $this->refuseValue($equalChunk);
327 1
                    $this->generateBaseline = BaselineMode::GENERATE;
328 1
                    break;
329 70
                case '--update-baseline':
330 1
                    $this->refuseValue($equalChunk);
331 1
                    $this->generateBaseline = BaselineMode::UPDATE;
332 1
                    break;
333 70
                case '--baseline-file':
334 1
                    $this->baselineFile = $this->readValue($equalChunk, $args);
335 1
                    break;
336 70
                case '--cache':
337 1
                    $this->refuseValue($equalChunk);
338 1
                    $this->cacheEnabled = true;
339 1
                    break;
340 70
                case '--cache-file':
341 1
                    $this->cacheFile = $this->readValue($equalChunk, $args);
342 1
                    break;
343 70
                case '--cache-strategy':
344 1
                    $this->cacheStrategy = $this->readValue($equalChunk, $args);
345 1
                    break;
346 70
                case '--ignore-errors-on-exit':
347 1
                    $this->refuseValue($equalChunk);
348 1
                    $this->ignoreErrorsOnExit = true;
349 1
                    break;
350 70
                case '--ignore-violations-on-exit':
351 1
                    $this->refuseValue($equalChunk);
352 1
                    $this->ignoreViolationsOnExit = true;
353 1
                    break;
354 70
                case '--reportfile-checkstyle':
355 70
                case '--reportfile-github':
356 70
                case '--reportfile-gitlab':
357 70
                case '--reportfile-html':
358 70
                case '--reportfile-json':
359 70
                case '--reportfile-sarif':
360 70
                case '--reportfile-text':
361 70
                case '--reportfile-xml':
362 6
                    preg_match('(^\-\-reportfile\-(checkstyle|github|gitlab|html|json|sarif|text|xml)$)', $arg, $match);
363 6
                    $this->reportFiles[$match[1]] = $this->readValue($equalChunk, $args);
364 6
                    break;
365 70
                case '--extra-line-in-excerpt':
366 1
                    $this->extraLineInExcerpt = (int)$this->readValue($equalChunk, $args);
367 1
                    break;
368
                default:
369 70
                    $hasImplicitArguments = true;
370 70
                    $arguments[] = $arg;
371 70
                    break;
372
            }
373
        }
374
375 70
        if (count($arguments) < 3) {
376 1
            throw new InvalidArgumentException($this->usage(), self::INPUT_ERROR);
377
        }
378
379 69
        $validator = new ArgumentsValidator($hasImplicitArguments, $originalArguments, $arguments);
380
381 69
        $this->ruleSets = (string)array_pop($arguments);
382 69
        $validator->validate('ruleset', $this->ruleSets);
383
384 68
        $this->reportFormat = (string)array_pop($arguments);
385 68
        $validator->validate('report format', $this->reportFormat);
386
387 68
        $this->inputPath = implode(',', $arguments);
388
389 68
        if ($this->inputPath === '-') {
390 2
            $this->inputPath = 'php://stdin';
391
392 2
            return;
393
        }
394
395 66
        foreach ($arguments as $arg) {
396 66
            $validator->validate('input path', $arg);
397
        }
398 64
    }
399
400
    /**
401
     * Returns a php source code filename or directory.
402
     *
403
     * @return string
404
     */
405 9
    public function getInputPath()
406
    {
407 9
        return $this->inputPath;
408
    }
409
410
    /**
411
     * Returns the specified report format.
412
     *
413
     * @return string
414
     */
415 3
    public function getReportFormat()
416
    {
417 3
        return $this->reportFormat;
418
    }
419
420
    /**
421
     * Returns the output filename for a generated report or <b>null</b> when
422
     * the report should be displayed in STDOUT.
423
     *
424
     * @return string|null
425
     */
426 4
    public function getReportFile()
427
    {
428 4
        return $this->reportFile;
429
    }
430
431
    /**
432
     * Returns the output filename for the errors or <b>null</b> when
433
     * the report should be displayed in STDERR.
434
     *
435
     * @return string|null
436
     */
437 5
    public function getErrorFile()
438
    {
439 5
        return $this->errorFile;
440
    }
441
442
    /**
443
     * Return the list of deprecations raised when parsing options.
444
     *
445
     * @return list<string>
0 ignored issues
show
Bug introduced by
The type PHPMD\TextUI\list was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
446
     */
447 7
    public function getDeprecations()
448
    {
449 7
        return $this->deprecations;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->deprecations returns the type array which is incompatible with the documented return type PHPMD\TextUI\list.
Loading history...
450
    }
451
452
    /**
453
     * Returns a hash with report files specified for different renderers. The
454
     * key represents the report format and the value the report file location.
455
     *
456
     * @return array
457
     */
458 10
    public function getReportFiles()
459
    {
460 10
        return $this->reportFiles;
461
    }
462
463
    /**
464
     * Returns a ruleset filename or a comma-separated string of ruleset
465
     *
466
     * @return string
467
     */
468 7
    public function getRuleSets()
469
    {
470 7
        return $this->ruleSets;
471
    }
472
473
    /**
474
     * Returns the minimum rule priority.
475
     *
476
     * @return integer
477
     */
478 6
    public function getMinimumPriority()
479
    {
480 6
        return $this->minimumPriority;
481
    }
482
483
    /**
484
     * Returns the maximum rule priority.
485
     *
486
     * @return integer
487
     */
488 5
    public function getMaximumPriority()
489
    {
490 5
        return $this->maximumPriority;
491
    }
492
493
    /**
494
     * Returns the file name of a supplied code coverage report or <b>NULL</b>
495
     * if the user has not supplied the --coverage option.
496
     *
497
     * @return string|null
498
     */
499 6
    public function getCoverageReport()
500
    {
501 6
        return $this->coverageReport;
502
    }
503
504
    /**
505
     * Returns a string of comma-separated extensions for valid php source code
506
     * filenames or <b>null</b> when this argument was not set.
507
     *
508
     * @return string|null
509
     */
510 5
    public function getExtensions()
511
    {
512 5
        return $this->extensions;
513
    }
514
515
    /**
516
     * Returns string of comma-separated pattern that is used to exclude
517
     * directories or <b>null</b> when this argument was not set.
518
     *
519
     * @return string|null
520
     */
521 7
    public function getIgnore()
522
    {
523 7
        return $this->ignore;
524
    }
525
526
    /**
527
     * Was the <b>--version</b> passed to PHPMD's command line interface?
528
     *
529
     * @return boolean
530
     */
531 6
    public function hasVersion()
532
    {
533 6
        return $this->version;
534
    }
535
536
    /**
537
     * Was the <b>--strict</b> option passed to PHPMD's command line interface?
538
     *
539
     * @return boolean
540
     * @since 1.2.0
541
     */
542 6
    public function hasStrict()
543
    {
544 6
        return $this->strict;
545
    }
546
547
    /**
548
     * @return int
549
     */
550 8
    public function getVerbosity()
551
    {
552 8
        return $this->verbosity;
553
    }
554
555
    /**
556
     * Should the current violations be baselined
557
     *
558
     * @return string
559
     */
560 7
    public function generateBaseline()
561
    {
562 7
        return $this->generateBaseline;
563
    }
564
565
    /**
566
     * The filepath of the baseline violations xml
567
     *
568
     * @return string|null
569
     */
570 6
    public function baselineFile()
571
    {
572 6
        return $this->baselineFile;
573
    }
574
575
    /**
576
     * @return bool
577
     */
578 5
    public function isCacheEnabled()
579
    {
580 5
        return $this->cacheEnabled;
581
    }
582
583
    /**
584
     * The filepath to the result cache state file
585
     *
586
     * @return string
587
     */
588 1
    public function cacheFile()
589
    {
590 1
        return $this->cacheFile === null ? '.phpmd.result-cache.php' : $this->cacheFile;
591
    }
592
593
    /**
594
     * The caching strategy to determine if a file should be (re)inspected. Either
595
     * `content` or last modified `timestamp` based.
596
     *
597
     * @return string
598
     */
599 1
    public function cacheStrategy()
600
    {
601 1
        switch ($this->cacheStrategy) {
602 1
            case ResultCacheStrategy::CONTENT:
603 1
            case ResultCacheStrategy::TIMESTAMP:
604 1
                return $this->cacheStrategy;
605
            default:
606 1
                return ResultCacheStrategy::CONTENT;
607
        }
608
    }
609
610
    /**
611
     * Was the <b>--ignore-errors-on-exit</b> passed to PHPMD's command line interface?
612
     *
613
     * @return boolean
614
     * @since 2.10.0
615
     */
616 2
    public function ignoreErrorsOnExit()
617
    {
618 2
        return $this->ignoreErrorsOnExit;
619
    }
620
621
    /**
622
     * Was the <b>--ignore-violations-on-exit</b> passed to PHPMD's command line interface?
623
     *
624
     * @return boolean
625
     */
626 6
    public function ignoreViolationsOnExit()
627
    {
628 6
        return $this->ignoreViolationsOnExit;
629
    }
630
631
    /**
632
     * Specify how many extra lines are added to a code snippet
633
     *
634
     * @return int|null
635
     */
636 1
    public function extraLineInExcerpt()
637
    {
638 1
        return $this->extraLineInExcerpt;
639
    }
640
    /**
641
     * Creates a report renderer instance based on the user's command line
642
     * argument.
643
     *
644
     * Valid renderers are:
645
     * <ul>
646
     *   <li>xml</li>
647
     *   <li>html</li>
648
     *   <li>text</li>
649
     *   <li>json</li>
650
     * </ul>
651
     *
652
     * @param string $reportFormat
653
     * @return \PHPMD\AbstractRenderer
654
     * @throws InvalidArgumentException When the specified renderer does not exist.
655
     */
656 20
    public function createRenderer($reportFormat = null)
657
    {
658 20
        $renderer = $this->createRendererWithoutOptions($reportFormat);
659
660 18
        if ($renderer instanceof Verbose) {
661 7
            $renderer->setVerbosityLevel($this->verbosity);
662
        }
663
664 18
        if ($renderer instanceof Color) {
665 7
            $renderer->setColored($this->colored);
666
        }
667
668 18
        return $renderer;
669
    }
670
671
    /**
672
     * @param string $reportFormat
673
     * @return \PHPMD\AbstractRenderer
674
     * @throws InvalidArgumentException When the specified renderer does not exist.
675
     */
676 20
    protected function createRendererWithoutOptions($reportFormat = null)
677
    {
678 20
        $reportFormat = $reportFormat ?: $this->reportFormat;
679
680 20
        switch ($reportFormat) {
681 20
            case 'ansi':
682 1
                return $this->createAnsiRenderer();
683 19
            case 'checkstyle':
684 1
                return $this->createCheckStyleRenderer();
685 18
            case 'gitlab':
686 1
                return $this->createGitLabRenderer();
687 17
            case 'github':
688 1
                return $this->createGitHubRenderer();
689 16
            case 'html':
690 1
                return $this->createHtmlRenderer();
691 15
            case 'json':
692 1
                return $this->createJsonRenderer();
693 14
            case 'sarif':
694 1
                return $this->createSarifRenderer();
695 13
            case 'text':
696 7
                return $this->createTextRenderer();
697 6
            case 'xml':
698 1
                return $this->createXmlRenderer();
699
            default:
700 5
                return $this->createCustomRenderer();
701
        }
702
    }
703
704
    /**
705
     * @return \PHPMD\Renderer\XMLRenderer
706
     */
707 1
    protected function createXmlRenderer()
708
    {
709 1
        return new XMLRenderer();
710
    }
711
712
    /**
713
     * @return \PHPMD\Renderer\TextRenderer
714
     */
715 7
    protected function createTextRenderer()
716
    {
717 7
        return new TextRenderer();
718
    }
719
720
    /**
721
     * @return \PHPMD\Renderer\AnsiRenderer
722
     */
723 1
    protected function createAnsiRenderer()
724
    {
725 1
        return new AnsiRenderer();
726
    }
727
728
    /**
729
     * @return \PHPMD\Renderer\GitLabRenderer
730
     */
731 1
    protected function createGitLabRenderer()
732
    {
733 1
        return new GitLabRenderer();
734
    }
735
736
    /**
737
     * @return \PHPMD\Renderer\GitHubRenderer
738
     */
739 1
    protected function createGitHubRenderer()
740
    {
741 1
        return new GitHubRenderer();
742
    }
743
744
    /**
745
     * @return \PHPMD\Renderer\HTMLRenderer
746
     */
747 1
    protected function createHtmlRenderer()
748
    {
749 1
        return new HTMLRenderer($this->extraLineInExcerpt);
750
    }
751
752
    /**
753
     * @return \PHPMD\Renderer\JSONRenderer
754
     */
755 1
    protected function createJsonRenderer()
756
    {
757 1
        return new JSONRenderer();
758
    }
759
760
    /**
761
     * @return \PHPMD\Renderer\CheckStyleRenderer
762
     */
763 1
    protected function createCheckStyleRenderer()
764
    {
765 1
        return new CheckStyleRenderer();
766
    }
767
768
    /**
769
     * @return \PHPMD\Renderer\SARIFRenderer
770
     */
771 1
    protected function createSarifRenderer()
772
    {
773 1
        return new SARIFRenderer();
774
    }
775
776
    /**
777
     * @return \PHPMD\AbstractRenderer
778
     * @throws InvalidArgumentException
779
     */
780 5
    protected function createCustomRenderer()
781
    {
782 5
        if ('' === $this->reportFormat) {
783 1
            throw new InvalidArgumentException(
784 1
                'Can\'t create report with empty format.',
785 1
                self::INPUT_ERROR
786
            );
787
        }
788
789 4
        if (class_exists($this->reportFormat)) {
790 1
            return new $this->reportFormat();
791
        }
792
793
        // Try to load a custom renderer
794 3
        $fileName = strtr($this->reportFormat, '_\\', '//') . '.php';
795
796 3
        $fileHandle = @fopen($fileName, 'r', true);
797 3
        if (is_resource($fileHandle) === false) {
798 1
            throw new InvalidArgumentException(
799 1
                sprintf(
800 1
                    'Can\'t find the custom report class: %s',
801 1
                    $this->reportFormat
802
                ),
803 1
                self::INPUT_ERROR
804
            );
805
        }
806 2
        @fclose($fileHandle);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for fclose(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

806
        /** @scrutinizer ignore-unhandled */ @fclose($fileHandle);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
Bug introduced by
$fileHandle of type false is incompatible with the type resource expected by parameter $stream of fclose(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

806
        @fclose(/** @scrutinizer ignore-type */ $fileHandle);
Loading history...
807
808 2
        include_once $fileName;
809
810 2
        return new $this->reportFormat();
811
    }
812
813
    /**
814
     * Returns usage information for the PHPMD command line interface.
815
     *
816
     * @return string
817
     */
818 5
    public function usage()
819
    {
820 5
        $availableRenderers = $this->getListOfAvailableRenderers();
821 5
        $noRenderers = ($availableRenderers === null);
822
823
        return 'Mandatory arguments:' . \PHP_EOL .
824
            '1) A php source code filename or directory. Can be a comma-' .
825
            'separated string, glob pattern, or "-" to scan stdin' . \PHP_EOL .
826
            '2) A report format' . \PHP_EOL .
827
            '3) A ruleset filename or a comma-separated string of ruleset' .
828
            'filenames' . \PHP_EOL . \PHP_EOL .
829
            'Example: phpmd /path/to/source format ruleset' . \PHP_EOL . \PHP_EOL .
830 5
            ($noRenderers ? 'No available formats' : 'Available formats: ' . $availableRenderers) . '.' . \PHP_EOL .
831 5
            'Available rulesets: ' . implode(', ', $this->availableRuleSets) . '.' . \PHP_EOL . \PHP_EOL .
832 5
            'Optional arguments that may be put after the mandatory arguments:' .
833 5
            \PHP_EOL .
834 5
            '--verbose, -v, -vv, -vvv: Show debug information.' . \PHP_EOL .
835 5
            '--minimum-priority: rule priority threshold; rules with lower ' .
836 5
            'priority than this will not be used' . \PHP_EOL .
837 5
            '--report-file: send report output to a file; default to STDOUT' .
838 5
            \PHP_EOL .
839 5
            '--error-file: send errors (other than reported violations) ' .
840 5
            'output to a file; default to STDERR' .
841 5
            \PHP_EOL .
842 5
            '--suffixes: comma-separated string of valid source code ' .
843 5
            'filename extensions, e.g. php,phtml' . \PHP_EOL .
844 5
            '--exclude: comma-separated string of patterns that are used to ' .
845 5
            'ignore directories. Use asterisks to exclude by pattern. ' .
846 5
            'For example *src/foo/*.php or *src/foo/*' . \PHP_EOL .
847 5
            '--strict: also report those nodes with a @SuppressWarnings ' .
848 5
            'annotation' . \PHP_EOL .
849 5
            '--ignore-errors-on-exit: will exit with a zero code, ' .
850 5
            'even on error' . \PHP_EOL .
851 5
            '--ignore-violations-on-exit: will exit with a zero code, ' .
852 5
            'even if any violations are found' . \PHP_EOL .
853 5
            '--cache: will enable the result cache.' . \PHP_EOL .
854 5
            '--cache-file: instead of the default .phpmd.result-cache.php' .
855 5
            ' will use this file as result cache file path.' . \PHP_EOL .
856 5
            '--cache-strategy: sets the caching strategy to determine if' .
857 5
            ' a file is still fresh. Either `content` to base it on the ' .
858 5
            'file contents, or `timestamp` to base it on the file modified ' .
859 5
            'timestamp' . \PHP_EOL .
860 5
            '--generate-baseline: will generate a phpmd.baseline.xml next ' .
861 5
            'to the first ruleset file location' . \PHP_EOL .
862 5
            '--update-baseline: will remove any non-existing violations from the phpmd.baseline.xml' . \PHP_EOL .
863 5
            '--baseline-file: a custom location of the baseline file' . \PHP_EOL .
864 5
            '--color: enable color in output' . \PHP_EOL .
865 5
            '--extra-line-in-excerpt: Specify how many extra lines are added ' .
866 5
            'to a code snippet in html format' . \PHP_EOL .
867 5
            '--: Explicit argument separator: Anything after "--" will be read as an argument even if' .
868 5
            'it starts with "-" or matches the name of an option' . \PHP_EOL;
869
    }
870
871
    /**
872
     * Get a list of available renderers
873
     *
874
     * @return string|null The list of renderers found separated by comma, or null if none.
875
     */
876 5
    protected function getListOfAvailableRenderers()
877
    {
878 5
        $renderersDirPathName = __DIR__ . '/../Renderer';
879 5
        $renderers            = array();
880
881 5
        foreach (scandir($renderersDirPathName) as $rendererFileName) {
882 5
            $rendererName = array();
883 5
            if (preg_match('/^(\w+)Renderer.php$/i', $rendererFileName, $rendererName)) {
884 5
                $renderers[] = strtolower($rendererName[1]);
885
            }
886
        }
887
888 5
        sort($renderers);
889
890 5
        return implode(', ', $renderers) ?: null;
891
    }
892
893
    /**
894
     * Logs a deprecated option to the current user interface.
895
     *
896
     * @param string $deprecatedName
897
     * @param string $newName
898
     * @return void
899
     */
900 3
    protected function logDeprecated($deprecatedName, $newName)
901
    {
902 3
        $this->deprecations[] = sprintf(
903 3
            'The --%s option is deprecated, please use --%s instead.',
904
            $deprecatedName,
905
            $newName
906
        );
907 3
    }
908
909
    /**
910
     * This method takes the given input file, reads the newline separated paths
911
     * from that file and creates a comma separated string of the file paths. If
912
     * the given <b>$inputFile</b> not exists, this method will throw an
913
     * exception.
914
     *
915
     * @param string $inputFile Specified input file name.
916
     * @return string
917
     * @throws InvalidArgumentException If the specified input file does not exist.
918
     * @since 1.1.0
919
     */
920 6
    protected function readInputFile($inputFile)
921
    {
922 6
        if (file_exists($inputFile)) {
923 5
            return implode(',', array_map('trim', file($inputFile)));
924
        }
925 1
        throw new InvalidArgumentException("Input file '{$inputFile}' not exists.");
926
    }
927
928
    /**
929
     * Throw an exception if a boolean option has a value (is followed by equal).
930
     *
931
     * @param string[] $equalChunk The CLI parameter split in 2 by "=" sign
932
     *
933
     * @throws InvalidArgumentException if a boolean option has a value (is followed by equal)
934
     */
935 15
    private function refuseValue(array $equalChunk)
936
    {
937 15
        if (count($equalChunk) > 1) {
938 1
            throw new InvalidArgumentException($equalChunk[0] . ' option does not accept a value');
939
        }
940 14
    }
941
942
    /**
943
     * Return value for an option either what is after "=" sign if present, else take the next CLI parameter.
944
     *
945
     * @param string[] $equalChunk The CLI parameter split in 2 by "=" sign
946
     * @param string[] &$args      The remaining CLI parameters not yet parsed
947
     *
948
     * @return string|null
949
     */
950 24
    private function readValue(array $equalChunk, array &$args)
951
    {
952 24
        if (count($equalChunk) > 1) {
953 1
            return $equalChunk[1];
954
        }
955
956 23
        return array_shift($args);
957
    }
958
}
959