• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PHPCSStandards / PHP_CodeSniffer / 9756688221

02 Jul 2024 07:22AM UTC coverage: 75.507%. Remained the same
9756688221

push

github

web-flow
Merge pull request #523 from PHPCSStandards/feature/docs-improve-reports-array-format-info

Documentation: improve information about Report data format + remove unused foreach keys

0 of 9 new or added lines in 4 files covered. (0.0%)

1 existing line in 1 file now uncovered.

23275 of 30825 relevant lines covered (75.51%)

61.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Reports/VersionControl.php
1
<?php
2
/**
3
 * Version control report base class for PHP_CodeSniffer.
4
 *
5
 * @author    Ben Selby <benmatselby@gmail.com>
6
 * @author    Greg Sherwood <gsherwood@squiz.net>
7
 * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
8
 * @license   https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
9
 */
10

11
namespace PHP_CodeSniffer\Reports;
12

13
use PHP_CodeSniffer\Files\File;
14
use PHP_CodeSniffer\Util\Timing;
15

16
abstract class VersionControl implements Report
17
{
18

19
    /**
20
     * The name of the report we want in the output.
21
     *
22
     * @var string
23
     */
24
    protected $reportName = 'VERSION CONTROL';
25

26

27
    /**
28
     * Generate a partial report for a single processed file.
29
     *
30
     * Function should return TRUE if it printed or stored data about the file
31
     * and FALSE if it ignored the file. Returning TRUE indicates that the file and
32
     * its data should be counted in the grand totals.
33
     *
34
     * @param array<string, string|int|array> $report      Prepared report data.
35
     *                                                     See the {@see Report} interface for a detailed specification.
36
     * @param \PHP_CodeSniffer\Files\File     $phpcsFile   The file being reported on.
37
     * @param bool                            $showSources Show sources?
38
     * @param int                             $width       Maximum allowed line width.
39
     *
40
     * @return bool
41
     */
42
    public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80)
×
43
    {
44
        $blames = $this->getBlameContent($phpcsFile->getFilename());
×
45

46
        $authorCache = [];
×
47
        $praiseCache = [];
×
48
        $sourceCache = [];
×
49

50
        foreach ($report['messages'] as $line => $lineErrors) {
×
51
            $author = 'Unknown';
×
52
            if (isset($blames[($line - 1)]) === true) {
×
53
                $blameAuthor = $this->getAuthor($blames[($line - 1)]);
×
54
                if ($blameAuthor !== false) {
×
55
                    $author = $blameAuthor;
×
56
                }
57
            }
58

59
            if (isset($authorCache[$author]) === false) {
×
60
                $authorCache[$author] = 0;
×
61
                $praiseCache[$author] = [
×
62
                    'good' => 0,
×
63
                    'bad'  => 0,
×
64
                ];
×
65
            }
66

67
            $praiseCache[$author]['bad']++;
×
68

NEW
69
            foreach ($lineErrors as $colErrors) {
×
70
                foreach ($colErrors as $error) {
×
71
                    $authorCache[$author]++;
×
72

73
                    if ($showSources === true) {
×
74
                        $source = $error['source'];
×
75
                        if (isset($sourceCache[$author][$source]) === false) {
×
76
                            $sourceCache[$author][$source] = [
×
77
                                'count'   => 1,
×
78
                                'fixable' => $error['fixable'],
×
79
                            ];
×
80
                        } else {
81
                            $sourceCache[$author][$source]['count']++;
×
82
                        }
83
                    }
84
                }
85
            }
86

87
            unset($blames[($line - 1)]);
×
88
        }//end foreach
89

90
        // Now go through and give the authors some credit for
91
        // all the lines that do not have errors.
92
        foreach ($blames as $line) {
×
93
            $author = $this->getAuthor($line);
×
94
            if ($author === false) {
×
95
                $author = 'Unknown';
×
96
            }
97

98
            if (isset($authorCache[$author]) === false) {
×
99
                // This author doesn't have any errors.
100
                if (PHP_CODESNIFFER_VERBOSITY === 0) {
×
101
                    continue;
×
102
                }
103

104
                $authorCache[$author] = 0;
×
105
                $praiseCache[$author] = [
×
106
                    'good' => 0,
×
107
                    'bad'  => 0,
×
108
                ];
×
109
            }
110

111
            $praiseCache[$author]['good']++;
×
112
        }//end foreach
113

114
        foreach ($authorCache as $author => $errors) {
×
115
            echo "AUTHOR>>$author>>$errors".PHP_EOL;
×
116
        }
117

118
        foreach ($praiseCache as $author => $praise) {
×
119
            echo "PRAISE>>$author>>".$praise['good'].'>>'.$praise['bad'].PHP_EOL;
×
120
        }
121

122
        foreach ($sourceCache as $author => $sources) {
×
123
            foreach ($sources as $source => $sourceData) {
×
124
                $count   = $sourceData['count'];
×
125
                $fixable = (int) $sourceData['fixable'];
×
126
                echo "SOURCE>>$author>>$source>>$count>>$fixable".PHP_EOL;
×
127
            }
128
        }
129

130
        return true;
×
131

132
    }//end generateFileReport()
133

134

135
    /**
136
     * Prints the author of all errors and warnings, as given by "version control blame".
137
     *
138
     * @param string $cachedData    Any partial report data that was returned from
139
     *                              generateFileReport during the run.
140
     * @param int    $totalFiles    Total number of files processed during the run.
141
     * @param int    $totalErrors   Total number of errors found during the run.
142
     * @param int    $totalWarnings Total number of warnings found during the run.
143
     * @param int    $totalFixable  Total number of problems that can be fixed.
144
     * @param bool   $showSources   Show sources?
145
     * @param int    $width         Maximum allowed line width.
146
     * @param bool   $interactive   Are we running in interactive mode?
147
     * @param bool   $toScreen      Is the report being printed to screen?
148
     *
149
     * @return void
150
     */
151
    public function generate(
×
152
        $cachedData,
153
        $totalFiles,
154
        $totalErrors,
155
        $totalWarnings,
156
        $totalFixable,
157
        $showSources=false,
158
        $width=80,
159
        $interactive=false,
160
        $toScreen=true
161
    ) {
162
        $errorsShown = ($totalErrors + $totalWarnings);
×
163
        if ($errorsShown === 0) {
×
164
            // Nothing to show.
165
            return;
×
166
        }
167

168
        $lines = explode(PHP_EOL, $cachedData);
×
169
        array_pop($lines);
×
170

171
        if (empty($lines) === true) {
×
172
            return;
×
173
        }
174

175
        $authorCache = [];
×
176
        $praiseCache = [];
×
177
        $sourceCache = [];
×
178

179
        foreach ($lines as $line) {
×
180
            $parts = explode('>>', $line);
×
181
            switch ($parts[0]) {
×
182
            case 'AUTHOR':
×
183
                if (isset($authorCache[$parts[1]]) === false) {
×
184
                    $authorCache[$parts[1]] = $parts[2];
×
185
                } else {
186
                    $authorCache[$parts[1]] += $parts[2];
×
187
                }
188
                break;
×
189
            case 'PRAISE':
×
190
                if (isset($praiseCache[$parts[1]]) === false) {
×
191
                    $praiseCache[$parts[1]] = [
×
192
                        'good' => $parts[2],
×
193
                        'bad'  => $parts[3],
×
194
                    ];
×
195
                } else {
196
                    $praiseCache[$parts[1]]['good'] += $parts[2];
×
197
                    $praiseCache[$parts[1]]['bad']  += $parts[3];
×
198
                }
199
                break;
×
200
            case 'SOURCE':
×
201
                if (isset($praiseCache[$parts[1]]) === false) {
×
202
                    $praiseCache[$parts[1]] = [];
×
203
                }
204

205
                if (isset($sourceCache[$parts[1]][$parts[2]]) === false) {
×
206
                    $sourceCache[$parts[1]][$parts[2]] = [
×
207
                        'count'   => $parts[3],
×
208
                        'fixable' => (bool) $parts[4],
×
209
                    ];
×
210
                } else {
211
                    $sourceCache[$parts[1]][$parts[2]]['count'] += $parts[3];
×
212
                }
213
                break;
×
214
            default:
215
                break;
×
216
            }//end switch
217
        }//end foreach
218

219
        // Make sure the report width isn't too big.
220
        $maxLength = 0;
×
221
        foreach ($authorCache as $author => $count) {
×
222
            $maxLength = max($maxLength, strlen($author));
×
223
            if ($showSources === true && isset($sourceCache[$author]) === true) {
×
224
                foreach ($sourceCache[$author] as $source => $sourceData) {
×
225
                    if ($source === 'count') {
×
226
                        continue;
×
227
                    }
228

229
                    $maxLength = max($maxLength, (strlen($source) + 9));
×
230
                }
231
            }
232
        }
233

234
        $width = min($width, ($maxLength + 30));
×
235
        $width = max($width, 70);
×
236
        arsort($authorCache);
×
237

238
        echo PHP_EOL."\033[1m".'PHP CODE SNIFFER '.$this->reportName.' BLAME SUMMARY'."\033[0m".PHP_EOL;
×
239
        echo str_repeat('-', $width).PHP_EOL."\033[1m";
×
240
        if ($showSources === true) {
×
241
            echo 'AUTHOR   SOURCE'.str_repeat(' ', ($width - 43)).'(Author %) (Overall %) COUNT'.PHP_EOL;
×
242
            echo str_repeat('-', $width).PHP_EOL;
×
243
        } else {
244
            echo 'AUTHOR'.str_repeat(' ', ($width - 34)).'(Author %) (Overall %) COUNT'.PHP_EOL;
×
245
            echo str_repeat('-', $width).PHP_EOL;
×
246
        }
247

248
        echo "\033[0m";
×
249

250
        if ($showSources === true) {
×
251
            $maxSniffWidth = ($width - 15);
×
252

253
            if ($totalFixable > 0) {
×
254
                $maxSniffWidth -= 4;
×
255
            }
256
        }
257

258
        $fixableSources = 0;
×
259

260
        foreach ($authorCache as $author => $count) {
×
261
            if ($praiseCache[$author]['good'] === 0) {
×
262
                $percent = 0;
×
263
            } else {
264
                $total   = ($praiseCache[$author]['bad'] + $praiseCache[$author]['good']);
×
265
                $percent = round(($praiseCache[$author]['bad'] / $total * 100), 2);
×
266
            }
267

268
            $overallPercent = '('.round((($count / $errorsShown) * 100), 2).')';
×
269
            $authorPercent  = '('.$percent.')';
×
270
            $line           = str_repeat(' ', (6 - strlen($count))).$count;
×
271
            $line           = str_repeat(' ', (12 - strlen($overallPercent))).$overallPercent.$line;
×
272
            $line           = str_repeat(' ', (11 - strlen($authorPercent))).$authorPercent.$line;
×
273
            $line           = $author.str_repeat(' ', ($width - strlen($author) - strlen($line))).$line;
×
274

275
            if ($showSources === true) {
×
276
                $line = "\033[1m$line\033[0m";
×
277
            }
278

279
            echo $line.PHP_EOL;
×
280

281
            if ($showSources === true && isset($sourceCache[$author]) === true) {
×
282
                $errors = $sourceCache[$author];
×
283
                asort($errors);
×
284
                $errors = array_reverse($errors);
×
285

286
                foreach ($errors as $source => $sourceData) {
×
287
                    if ($source === 'count') {
×
288
                        continue;
×
289
                    }
290

291
                    $count = $sourceData['count'];
×
292

293
                    $srcLength = strlen($source);
×
294
                    if ($srcLength > $maxSniffWidth) {
×
295
                        $source = substr($source, 0, $maxSniffWidth);
×
296
                    }
297

298
                    $line = str_repeat(' ', (5 - strlen($count))).$count;
×
299

300
                    echo '         ';
×
301
                    if ($totalFixable > 0) {
×
302
                        echo '[';
×
303
                        if ($sourceData['fixable'] === true) {
×
304
                            echo 'x';
×
305
                            $fixableSources++;
×
306
                        } else {
307
                            echo ' ';
×
308
                        }
309

310
                        echo '] ';
×
311
                    }
312

313
                    echo $source;
×
314
                    if ($totalFixable > 0) {
×
315
                        echo str_repeat(' ', ($width - 18 - strlen($source)));
×
316
                    } else {
317
                        echo str_repeat(' ', ($width - 14 - strlen($source)));
×
318
                    }
319

320
                    echo $line.PHP_EOL;
×
321
                }//end foreach
322
            }//end if
323
        }//end foreach
324

325
        echo str_repeat('-', $width).PHP_EOL;
×
326
        echo "\033[1m".'A TOTAL OF '.$errorsShown.' SNIFF VIOLATION';
×
327
        if ($errorsShown !== 1) {
×
328
            echo 'S';
×
329
        }
330

331
        echo ' WERE COMMITTED BY '.count($authorCache).' AUTHOR';
×
332
        if (count($authorCache) !== 1) {
×
333
            echo 'S';
×
334
        }
335

336
        echo "\033[0m";
×
337

338
        if ($totalFixable > 0) {
×
339
            if ($showSources === true) {
×
340
                echo PHP_EOL.str_repeat('-', $width).PHP_EOL;
×
341
                echo "\033[1mPHPCBF CAN FIX THE $fixableSources MARKED SOURCES AUTOMATICALLY ($totalFixable VIOLATIONS IN TOTAL)\033[0m";
×
342
            } else {
343
                echo PHP_EOL.str_repeat('-', $width).PHP_EOL;
×
344
                echo "\033[1mPHPCBF CAN FIX $totalFixable OF THESE SNIFF VIOLATIONS AUTOMATICALLY\033[0m";
×
345
            }
346
        }
347

348
        echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL;
×
349

350
        if ($toScreen === true && $interactive === false) {
×
351
            Timing::printRunTime();
×
352
        }
353

354
    }//end generate()
355

356

357
    /**
358
     * Extract the author from a blame line.
359
     *
360
     * @param string $line Line to parse.
361
     *
362
     * @return mixed string or false if impossible to recover.
363
     */
364
    abstract protected function getAuthor($line);
365

366

367
    /**
368
     * Gets the blame output.
369
     *
370
     * @param string $filename File to blame.
371
     *
372
     * @return array
373
     */
374
    abstract protected function getBlameContent($filename);
375

376

377
}//end class
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc