Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * A class to process command line phpcs scripts.
4
 *
5
 * PHP version 5
6
 *
7
 * @category  PHP
8
 * @package   PHP_CodeSniffer
9
 * @author    Greg Sherwood <gsherwood@squiz.net>
10
 * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
11
 * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
12
 * @version   CVS: $Id: CLI.php 287726 2009-08-26 05:13:12Z squiz $
13
 * @link      http://pear.php.net/package/PHP_CodeSniffer
14
 */
15
 
16
if (is_file(dirname(__FILE__).'/../CodeSniffer.php') === true) {
17
    include_once dirname(__FILE__).'/../CodeSniffer.php';
18
} else {
19
    include_once 'PHP/CodeSniffer.php';
20
}
21
 
22
/**
23
 * A class to process command line phpcs scripts.
24
 *
25
 * @category  PHP
26
 * @package   PHP_CodeSniffer
27
 * @author    Greg Sherwood <gsherwood@squiz.net>
28
 * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
29
 * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
30
 * @version   Release: 1.2.1
31
 * @link      http://pear.php.net/package/PHP_CodeSniffer
32
 */
33
class PHP_CodeSniffer_CLI
34
{
35
 
36
 
37
    /**
38
     * Exits if the minimum requirements of PHP_CodSniffer are not met.
39
     *
40
     * @return array
41
     */
42
    public function checkRequirements()
43
    {
44
        // Check the PHP version.
45
        if (version_compare(PHP_VERSION, '5.1.2') === -1) {
46
            echo 'ERROR: PHP_CodeSniffer requires PHP version 5.1.2 or greater.'.PHP_EOL;
47
            exit(2);
48
        }
49
 
50
        if (extension_loaded('tokenizer') === false) {
51
            echo 'ERROR: PHP_CodeSniffer requires the tokenizer extension to be enabled.'.PHP_EOL;
52
            exit(2);
53
        }
54
 
55
    }//end checkRequirements()
56
 
57
 
58
    /**
59
     * Get a list of default values for all possible command line arguments.
60
     *
61
     * @return array
62
     */
63
    public function getDefaults()
64
    {
65
        // The default values for config settings.
66
        $defaults['files']       = array();
67
        $defaults['standard']    = null;
68
        $defaults['verbosity']   = 0;
69
        $defaults['local']       = false;
70
        $defaults['showSources'] = false;
71
        $defaults['extensions']  = array();
72
        $defaults['sniffs']      = array();
73
        $defaults['ignored']     = array();
74
        $defaults['reportFile']  = '';
75
        $defaults['generator']   = '';
76
 
77
        $defaults['report'] = PHP_CodeSniffer::getConfigData('report_format');
78
        if ($defaults['report'] === null) {
79
            $defaults['report'] = 'full';
80
        }
81
 
82
        $showWarnings = PHP_CodeSniffer::getConfigData('show_warnings');
83
        if ($showWarnings === null) {
84
            $defaults['showWarnings'] = true;
85
        } else {
86
            $defaults['showWarnings'] = (bool) $showWarnings;
87
        }
88
 
89
        $tabWidth = PHP_CodeSniffer::getConfigData('tab_width');
90
        if ($tabWidth === null) {
91
            $defaults['tabWidth'] = 0;
92
        } else {
93
            $defaults['tabWidth'] = (int) $tabWidth;
94
        }
95
 
96
        $reportWidth = PHP_CodeSniffer::getConfigData('report_width');
97
        if ($reportWidth === null) {
98
            $defaults['reportWidth'] = 80;
99
        } else {
100
            $defaults['reportWidth'] = (int) $reportWidth;
101
        }
102
 
103
        return $defaults;
104
 
105
    }//end getDefaults()
106
 
107
 
108
    /**
109
     * Process the command line arguments and returns the values.
110
     *
111
     * @return array
112
     */
113
    public function getCommandLineValues()
114
    {
115
        $values = $this->getDefaults();
116
 
117
        for ($i = 1; $i < $_SERVER['argc']; $i++) {
118
            $arg = $_SERVER['argv'][$i];
119
            if ($arg{0} === '-') {
120
                if ($arg === '-' || $arg === '--') {
121
                    // Empty argument, ignore it.
122
                    continue;
123
                }
124
 
125
                if ($arg{1} === '-') {
126
                    $values
127
                        = $this->processLongArgument(substr($arg, 2), $i, $values);
128
                } else {
129
                    $switches = str_split($arg);
130
                    foreach ($switches as $switch) {
131
                        if ($switch === '-') {
132
                            continue;
133
                        }
134
 
135
                        $values = $this->processShortArgument($switch, $i, $values);
136
                    }
137
                }
138
            } else {
139
                $values = $this->processUnknownArgument($arg, $i, $values);
140
            }
141
        }//end for
142
 
143
        return $values;
144
 
145
    }//end getCommandLineValues()
146
 
147
 
148
    /**
149
     * Processes a sort (-e) command line argument.
150
     *
151
     * @param string $arg    The command line argument.
152
     * @param int    $pos    The position of the argument on the command line.
153
     * @param array  $values An array of values determined from CLI args.
154
     *
155
     * @return array The updated CLI values.
156
     * @see getCommandLineValues()
157
     */
158
    public function processShortArgument($arg, $pos, $values)
159
    {
160
        switch ($arg) {
161
        case 'h':
162
        case '?':
163
            $this->printUsage();
164
            exit(0);
165
            break;
166
        case 'i' :
167
            $this->printInstalledStandards();
168
            exit(0);
169
            break;
170
        case 'v' :
171
            $values['verbosity']++;
172
            break;
173
        case 'l' :
174
            $values['local'] = true;
175
            break;
176
        case 's' :
177
            $values['showSources'] = true;
178
            break;
179
        case 'n' :
180
            $values['showWarnings'] = false;
181
            break;
182
        case 'w' :
183
            $values['showWarnings'] = true;
184
            break;
185
        default:
186
            $values = $this->processUnknownArgument('-'.$arg, $pos, $values);
187
        }//end switch
188
 
189
        return $values;
190
 
191
    }//end processShortArgument()
192
 
193
 
194
    /**
195
     * Processes a long (--example) command line argument.
196
     *
197
     * @param string $arg    The command line argument.
198
     * @param int    $pos    The position of the argument on the command line.
199
     * @param array  $values An array of values determined from CLI args.
200
     *
201
     * @return array The updated CLI values.
202
     * @see getCommandLineValues()
203
     */
204
    public function processLongArgument($arg, $pos, $values)
205
    {
206
        switch ($arg) {
207
        case 'help':
208
            $this->printUsage();
209
            exit(0);
210
            break;
211
        case 'version':
212
            echo 'PHP_CodeSniffer version 1.2.1 (stable) ';
213
            echo 'by Squiz Pty Ltd. (http://www.squiz.net)'.PHP_EOL;
214
            exit(0);
215
            break;
216
        case 'config-set':
217
            $key   = $_SERVER['argv'][($pos + 1)];
218
            $value = $_SERVER['argv'][($pos + 2)];
219
            PHP_CodeSniffer::setConfigData($key, $value);
220
            exit(0);
221
            break;
222
        case 'config-delete':
223
            $key = $_SERVER['argv'][($pos + 1)];
224
            PHP_CodeSniffer::setConfigData($key, null);
225
            exit(0);
226
            break;
227
        case 'config-show':
228
            $data = PHP_CodeSniffer::getAllConfigData();
229
            print_r($data);
230
            exit(0);
231
            break;
232
        default:
233
            if (substr($arg, 0, 7) === 'sniffs=') {
234
                $values['sniffs'] = array();
235
 
236
                $sniffs = substr($arg, 7);
237
                $sniffs = explode(',', $sniffs);
238
 
239
                // Convert the sniffs to class names.
240
                foreach ($sniffs as $sniff) {
241
                    $parts = explode('.', $sniff);
242
                    $values['sniffs'][] = $parts[0].'_Sniffs_'.$parts[1].'_'.$parts[2].'Sniff';
243
                }
244
            } else if (substr($arg, 0, 7) === 'report=') {
245
                $values['report'] = substr($arg, 7);
246
                $validReports     = array(
247
                                     'full',
248
                                     'xml',
249
                                     'checkstyle',
250
                                     'csv',
251
                                     'emacs',
252
                                     'source',
253
                                     'summary',
254
                                     'svnblame',
255
                                    );
256
 
257
                if (in_array($values['report'], $validReports) === false) {
258
                    echo 'ERROR: Report type "'.$values['report'].'" not known.'.PHP_EOL;
259
                    exit(2);
260
                }
261
            } else if (substr($arg, 0, 12) === 'report-file=') {
262
                $values['reportFile'] = realpath(substr($arg, 12));
263
 
264
                // It may not exist and return false instead.
265
                if ($values['reportFile'] === false) {
266
                    $values['reportFile'] = substr($arg, 12);
267
                }
268
 
269
                if (is_dir($values['reportFile']) === true) {
270
                    echo 'ERROR: The specified report file path "'.$values['reportFile'].'" is a directory.'.PHP_EOL.PHP_EOL;
271
                    $this->printUsage();
272
                    exit(2);
273
                }
274
 
275
                $dir = dirname($values['reportFile']);
276
                if (is_dir($dir) === false) {
277
                    echo 'ERROR: The specified report file path "'.$values['reportFile'].'" points to a non-existent directory.'.PHP_EOL.PHP_EOL;
278
                    $this->printUsage();
279
                    exit(2);
280
                }
281
            } else if (substr($arg, 0, 9) === 'standard=') {
282
                $values['standard'] = substr($arg, 9);
283
            } else if (substr($arg, 0, 11) === 'extensions=') {
284
                $values['extensions'] = explode(',', substr($arg, 11));
285
            } else if (substr($arg, 0, 7) === 'ignore=') {
286
                // Split the ignore string on commas, unless the comma is escaped
287
                // using 1 or 3 slashes (\, or \\\,).
288
                $values['ignored']= preg_split(
289
                    '/(?<=(?<!\\\\)\\\\\\\\),|(?<!\\\\),/',
290
                    substr($arg, 7)
291
                );
292
            } else if (substr($arg, 0, 10) === 'generator=') {
293
                $values['generator'] = substr($arg, 10);
294
            } else if (substr($arg, 0, 10) === 'tab-width=') {
295
                $values['tabWidth'] = (int) substr($arg, 10);
296
            } else if (substr($arg, 0, 13) === 'report-width=') {
297
                $values['reportWidth'] = (int) substr($arg, 13);
298
            } else {
299
                $values = $this->processUnknownArgument('--'.$arg, $pos, $values);
300
            }//end if
301
 
302
            break;
303
        }//end switch
304
 
305
        return $values;
306
 
307
    }//end processLongArgument()
308
 
309
 
310
    /**
311
     * Processes an unknown command line argument.
312
     *
313
     * Assumes all unknown arguments are files and folders to check.
314
     *
315
     * @param string $arg    The command line argument.
316
     * @param int    $pos    The position of the argument on the command line.
317
     * @param array  $values An array of values determined from CLI args.
318
     *
319
     * @return array The updated CLI values.
320
     * @see getCommandLineValues()
321
     */
322
    public function processUnknownArgument($arg, $pos, $values)
323
    {
324
        // We don't know about any additional switches; just files.
325
        if ($arg{0} === '-') {
326
            echo 'ERROR: option "'.$arg.'" not known.'.PHP_EOL.PHP_EOL;
327
            $this->printUsage();
328
            exit(2);
329
        }
330
 
331
        $file = realpath($arg);
332
        if (file_exists($file) === false) {
333
            echo 'ERROR: The file "'.$arg.'" does not exist.'.PHP_EOL.PHP_EOL;
334
            $this->printUsage();
335
            exit(2);
336
        } else {
337
            $values['files'][] = $file;
338
        }
339
 
340
        return $values;
341
 
342
    }//end processUnknownArgument()
343
 
344
 
345
    /**
346
     * Runs PHP_CodeSniffer over files are directories.
347
     *
348
     * @param array $values An array of values determined from CLI args.
349
     *
350
     * @return int The number of error and warning messages shown.
351
     * @see getCommandLineValues()
352
     */
353
    public function process($values=array())
354
    {
355
        if (empty($values) === true) {
356
            $values = $this->getCommandLineValues();
357
        }
358
 
359
        if ($values['generator'] !== '') {
360
            $phpcs = new PHP_CodeSniffer($values['verbosity']);
361
            $phpcs->generateDocs(
362
                $values['standard'],
363
                $values['files'],
364
                $values['generator']
365
            );
366
            exit(0);
367
        }
368
 
369
        if (empty($values['files']) === true) {
370
            echo 'ERROR: You must supply at least one file or directory to process.'.PHP_EOL.PHP_EOL;
371
            $this->printUsage();
372
            exit(2);
373
        }
374
 
375
        $values['standard'] = $this->validateStandard($values['standard']);
376
        if (PHP_CodeSniffer::isInstalledStandard($values['standard']) === false) {
377
            // They didn't select a valid coding standard, so help them
378
            // out by letting them know which standards are installed.
379
            echo 'ERROR: the "'.$values['standard'].'" coding standard is not installed. ';
380
            $this->printInstalledStandards();
381
            exit(2);
382
        }
383
 
384
        $phpcs = new PHP_CodeSniffer($values['verbosity'], $values['tabWidth']);
385
 
386
        // Set file extensions if they were specified. Otherwise,
387
        // let PHP_CodeSniffer decide on the defaults.
388
        if (empty($values['extensions']) === false) {
389
            $phpcs->setAllowedFileExtensions($values['extensions']);
390
        }
391
 
392
        // Set ignore patterns if they were specified.
393
        if (empty($values['ignored']) === false) {
394
            $phpcs->setIgnorePatterns($values['ignored']);
395
        }
396
 
397
        $phpcs->process(
398
            $values['files'],
399
            $values['standard'],
400
            $values['sniffs'],
401
            $values['local']
402
        );
403
 
404
        return $this->printErrorReport(
405
            $phpcs,
406
            $values['report'],
407
            $values['showWarnings'],
408
            $values['showSources'],
409
            $values['reportFile'],
410
            $values['reportWidth']
411
        );
412
 
413
    }//end process()
414
 
415
 
416
    /**
417
     * Prints the error report.
418
     *
419
     * @param PHP_CodeSniffer $phpcs        The PHP_CodeSniffer object containing
420
     *                                      the errors.
421
     * @param string          $report       The type of report to print.
422
     * @param bool            $showWarnings TRUE if warnings should also be printed.
423
     * @param bool            $showSources  TRUE if report should show error sources
424
     *                                      (not used by all reports).
425
     * @param string          $reportFile   A file to log the report out to.
426
     * @param int             $reportWidth  How wide the screen reports should be.
427
     *
428
     * @return int The number of error and warning messages shown.
429
     */
430
    public function printErrorReport(
431
        $phpcs,
432
        $report,
433
        $showWarnings,
434
        $showSources,
435
        $reportFile='',
436
        $reportWidth=80
437
    ) {
438
        if ($reportFile !== '') {
439
            ob_start();
440
        }
441
 
442
        switch ($report) {
443
        case 'xml':
444
            $numErrors = $phpcs->printXMLErrorReport($showWarnings);
445
            break;
446
        case 'checkstyle':
447
            $numErrors = $phpcs->printCheckstyleErrorReport($showWarnings);
448
            break;
449
        case 'csv':
450
            $numErrors = $phpcs->printCSVErrorReport($showWarnings);
451
            break;
452
        case 'emacs':
453
            $numErrors = $phpcs->printEmacsErrorReport($showWarnings);
454
            break;
455
        case 'summary':
456
            $numErrors = $phpcs->printErrorReportSummary(
457
                $showWarnings,
458
                $showSources,
459
                $reportWidth
460
            );
461
            break;
462
        case 'source':
463
            $numErrors = $phpcs->printSourceReport(
464
                $showWarnings,
465
                $showSources,
466
                $reportWidth
467
            );
468
            break;
469
        case 'svnblame':
470
            $numErrors = $phpcs->printSvnBlameReport(
471
                $showWarnings,
472
                $showSources,
473
                $reportWidth
474
            );
475
            break;
476
        default:
477
            $numErrors = $phpcs->printErrorReport(
478
                $showWarnings,
479
                $showSources,
480
                $reportWidth
481
            );
482
            break;
483
        }
484
 
485
        if ($reportFile !== '') {
486
            $report = ob_get_contents();
487
            ob_end_flush();
488
 
489
            $report = trim($report);
490
            file_put_contents($reportFile, "$report\n");
491
        }
492
 
493
        return $numErrors;
494
 
495
    }//end printErrorReport()
496
 
497
 
498
    /**
499
     * Convert the passed standard into a valid standard.
500
     *
501
     * Checks things like default values and case.
502
     *
503
     * @param string $standard The standard to validate.
504
     *
505
     * @return string
506
     */
507
    public function validateStandard($standard)
508
    {
509
        if ($standard === null) {
510
            // They did not supply a standard to use.
511
            // Try to get the default from the config system.
512
            $standard = PHP_CodeSniffer::getConfigData('default_standard');
513
            if ($standard === null) {
514
                $standard = 'PEAR';
515
            }
516
        }
517
 
518
        // Check if the standard name is valid. If not, check that the case
519
        // was not entered incorrectly.
520
        if (PHP_CodeSniffer::isInstalledStandard($standard) === false) {
521
            $installedStandards = PHP_CodeSniffer::getInstalledStandards();
522
            foreach ($installedStandards as $validStandard) {
523
                if (strtolower($standard) === strtolower($validStandard)) {
524
                    $standard = $validStandard;
525
                    break;
526
                }
527
            }
528
        }
529
 
530
        return $standard;
531
 
532
    }//end validateStandard()
533
 
534
 
535
    /**
536
     * Prints out the usage information for this script.
537
     *
538
     * @return void
539
     */
540
    public function printUsage()
541
    {
542
        echo 'Usage: phpcs [-nwlsvi] [--extensions=<extensions>] [--ignore=<patterns>]'.PHP_EOL;
543
        echo '    [--report=<report>] [--report-width=<reportWidth>] [--report-file=<reportfile>]'.PHP_EOL;
544
        echo '    [--config-set key value] [--config-delete key] [--config-show]'.PHP_EOL;
545
        echo '    [--standard=<standard>] [--sniffs=<sniffs>]'.PHP_EOL;
546
        echo '    [--generator=<generator>] [--tab-width=<tabWidth>] <file> ...'.PHP_EOL;
547
        echo '        -n            Do not print warnings'.PHP_EOL;
548
        echo '        -w            Print both warnings and errors (on by default)'.PHP_EOL;
549
        echo '        -l            Local directory only, no recursion'.PHP_EOL;
550
        echo '        -s            Show sniff codes in all reports'.PHP_EOL;
551
        echo '        -v[v][v]      Print verbose output'.PHP_EOL;
552
        echo '        -i            Show a list of installed coding standards'.PHP_EOL;
553
        echo '        --help        Print this help message'.PHP_EOL;
554
        echo '        --version     Print version information'.PHP_EOL;
555
        echo '        <file>        One or more files and/or directories to check'.PHP_EOL;
556
        echo '        <extensions>  A comma separated list of file extensions to check'.PHP_EOL;
557
        echo '                      (only valid if checking a directory)'.PHP_EOL;
558
        echo '        <patterns>    A comma separated list of patterns that are used'.PHP_EOL;
559
        echo '                      to ignore directories and files'.PHP_EOL;
560
        echo '        <sniffs>      A comma separated list of sniff codes to limit the check to'.PHP_EOL;
561
        echo '                      (all sniffs must be part of the specified standard)'.PHP_EOL;
562
        echo '        <standard>    The name of the coding standard to use'.PHP_EOL;
563
        echo '        <tabWidth>    The number of spaces each tab represents'.PHP_EOL;
564
        echo '        <generator>   The name of a doc generator to use'.PHP_EOL;
565
        echo '                      (forces doc generation instead of checking)'.PHP_EOL;
566
        echo '        <report>      Print either the "full", "xml", "checkstyle",'.PHP_EOL;
567
        echo '                      "csv", "emacs", "source", "summary" or "svnblame" report'.PHP_EOL;
568
        echo '                      (the "full" report is printed by default)'.PHP_EOL;
569
        echo '        <reportWidth> How many columns wide screen reports should be printed'.PHP_EOL;
570
        echo '        <reportfile>  Write the report to the specified file path'.PHP_EOL;
571
        echo '                      (report is also written to screen)'.PHP_EOL;
572
 
573
    }//end printUsage()
574
 
575
 
576
    /**
577
     * Prints out a list of installed coding standards.
578
     *
579
     * @return void
580
     */
581
    public function printInstalledStandards()
582
    {
583
        $installedStandards = PHP_CodeSniffer::getInstalledStandards();
584
        $numStandards       = count($installedStandards);
585
 
586
        if ($numStandards === 0) {
587
            echo 'No coding standards are installed.'.PHP_EOL;
588
        } else {
589
            $lastStandard = array_pop($installedStandards);
590
            if ($numStandards === 1) {
591
                echo 'The only coding standard installed is $lastStandard'.PHP_EOL;
592
            } else {
593
                $standardList  = implode(', ', $installedStandards);
594
                $standardList .= ' and '.$lastStandard;
595
                echo 'The installed coding standards are '.$standardList.PHP_EOL;
596
            }
597
        }
598
 
599
    }//end printInstalledStandards()
600
 
601
 
602
}//end class
603
 
604
?>