Completed
Push — master ( da65dc...5751ed )
by Tomáš
20:43 queued 16:49
created

Source   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 322
Duplicated Lines 8.07 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 45
c 0
b 0
f 0
lcom 1
cbo 1
dl 26
loc 322
rs 8.3673

3 Methods

Rating   Name   Duplication   Size   Complexity  
C generateFileReport() 0 31 8
F generate() 26 191 28
C makeFriendlyName() 0 52 9

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Source often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Source, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Source report for Symplify\PHP7_CodeSniffer.
4
 *
5
 * @author    Greg Sherwood <[email protected]>
6
 * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
7
 * @license   https://github.com/squizlabs/Symplify\PHP7_CodeSniffer/blob/master/licence.txt BSD Licence
8
 */
9
10
namespace Symplify\PHP7_CodeSniffer\Reports;
11
12
use Symplify\PHP7_CodeSniffer\Files\File;
13
use Symplify\PHP7_CodeSniffer\Util\Timing;
14
15
class Source implements Report
16
{
17
18
19
    /**
20
     * Generate a partial report for a single processed file.
21
     *
22
     * Function should return TRUE if it printed or stored data about the file
23
     * and FALSE if it ignored the file. Returning TRUE indicates that the file and
24
     * its data should be counted in the grand totals.
25
     *
26
     * @param array                 $report      Prepared report data.
27
     * @param \Symplify\PHP7_CodeSniffer\File $phpcsFile   The file being reported on.
28
     * @param bool                  $showSources Show sources?
29
     * @param int                   $width       Maximum allowed line width.
30
     *
31
     * @return bool
32
     */
33
    public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80)
34
    {
35
        if ($report['errors'] === 0 && $report['warnings'] === 0) {
36
            // Nothing to print.
37
            return false;
38
        }
39
40
        $sources = array();
41
42
        foreach ($report['messages'] as $line => $lineErrors) {
43
            foreach ($lineErrors as $column => $colErrors) {
44
                foreach ($colErrors as $error) {
45
                    if (isset($sources[$error['source']]) === false) {
46
                        $sources[$error['source']] = array(
47
                                                      'fixable' => (int) $error['fixable'],
48
                                                      'count'   => 1,
49
                                                     );
50
                    } else {
51
                        $sources[$error['source']]['count']++;
52
                    }
53
                }
54
            }
55
        }
56
57
        foreach ($sources as $source => $data) {
58
            echo $source.'>>'.$data['fixable'].'>>'.$data['count'].PHP_EOL;
59
        }
60
61
        return true;
62
63
    }//end generateFileReport()
64
65
66
    /**
67
     * Prints the source of all errors and warnings.
68
     *
69
     * @param string $cachedData    Any partial report data that was returned from
70
     *                              generateFileReport during the run.
71
     * @param int    $totalFiles    Total number of files processed during the run.
72
     * @param int    $totalErrors   Total number of errors found during the run.
73
     * @param int    $totalWarnings Total number of warnings found during the run.
74
     * @param int    $totalFixable  Total number of problems that can be fixed.
75
     * @param bool   $showSources   Show sources?
76
     * @param int    $width         Maximum allowed line width.
77
     * @param bool   $interactive   Are we running in interactive mode?
78
     * @param bool   $toScreen      Is the report being printed to screen?
79
     *
80
     * @return void
81
     */
82
    public function generate(
83
        $cachedData,
84
        $totalFiles,
85
        $totalErrors,
86
        $totalWarnings,
87
        $totalFixable,
88
        $showSources=false,
89
        $width=80,
90
        $interactive=false,
91
        $toScreen=true
92
    ) {
93
        $lines = explode(PHP_EOL, $cachedData);
94
        array_pop($lines);
95
96
        if (empty($lines) === true) {
97
            return;
98
        }
99
100
        $sources   = array();
101
        $maxLength = 0;
102
103
        foreach ($lines as $line) {
104
            $parts   = explode('>>', $line);
105
            $source  = $parts[0];
106
            $fixable = (bool) $parts[1];
107
            $count   = $parts[2];
0 ignored issues
show
Unused Code introduced by
$count is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
108
109
            if (isset($sources[$source]) === false) {
110
                if ($showSources === true) {
111
                    $parts = null;
112
                    $sniff = $source;
113
                } else {
114
                    $parts = explode('.', $source);
115
                    if ($parts[0] === 'Internal') {
116
                        $parts[2] = $parts[1];
117
                        $parts[1] = '';
118
                    }
119
120
                    $parts[1] = $this->makeFriendlyName($parts[1]);
121
122
                    $sniff = $this->makeFriendlyName($parts[2]);
123
                    if (isset($parts[3]) === true) {
124
                        $name    = $this->makeFriendlyName($parts[3]);
125
                        $name[0] = strtolower($name[0]);
126
                        $sniff  .= ' '.$name;
127
                        unset($parts[3]);
128
                    }
129
130
                    $parts[2] = $sniff;
131
                }//end if
132
133
                $maxLength = max($maxLength, $sniff);
134
135
                $sources[$source] = array(
136
                                     'count'   => 1,
137
                                     'fixable' => $fixable,
138
                                     'parts'   => $parts,
139
                                    );
140
            } else {
141
                $sources[$source]['count']++;
142
            }//end if
143
144
            $fileLen = strlen($parts[0]);
145
            $reportFiles[$parts[0]] = array(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$reportFiles was never initialized. Although not strictly required by PHP, it is generally a good practice to add $reportFiles = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
146
                                       'errors'   => $parts[1],
147
                                       'warnings' => $parts[2],
148
                                       'strlen'   => $fileLen,
149
                                      );
150
        }//end foreach
151
152
        if ($showSources === true) {
153
            $width = min($width, ($maxLength + 11));
154
        } else {
155
            $width = min($width, ($maxLength + 41));
156
        }
157
158
        $width = max($width, 70);
159
160
        asort($sources);
161
        $sources = array_reverse($sources);
162
163
        echo PHP_EOL."\033[1mPHP CODE SNIFFER VIOLATION SOURCE SUMMARY\033[0m".PHP_EOL;
164
        echo str_repeat('-', $width).PHP_EOL."\033[1m";
165
        if ($showSources === true) {
166 View Code Duplication
            if ($totalFixable > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
167
                echo '    SOURCE'.str_repeat(' ', ($width - 15)).'COUNT'.PHP_EOL;
168
            } else {
169
                echo 'SOURCE'.str_repeat(' ', ($width - 11)).'COUNT'.PHP_EOL;
170
            }
171 View Code Duplication
        } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
172
            if ($totalFixable > 0) {
173
                echo '    STANDARD  CATEGORY            SNIFF'.str_repeat(' ', ($width - 44)).'COUNT'.PHP_EOL;
174
            } else {
175
                echo 'STANDARD  CATEGORY            SNIFF'.str_repeat(' ', ($width - 40)).'COUNT'.PHP_EOL;
176
            }
177
        }
178
179
        echo "\033[0m".str_repeat('-', $width).PHP_EOL;
180
181
        $fixableSources = 0;
182
183
        if ($showSources === true) {
184
            $maxSniffWidth = ($width - 7);
185
        } else {
186
            $maxSniffWidth = ($width - 37);
187
        }
188
189
        if ($totalFixable > 0) {
190
            $maxSniffWidth -= 4;
191
        }
192
193
        foreach ($sources as $source => $sourceData) {
194
            if ($totalFixable > 0) {
195
                echo '[';
196
                if ($sourceData['fixable'] === true) {
197
                    echo 'x';
198
                    $fixableSources++;
199
                } else {
200
                    echo ' ';
201
                }
202
203
                echo '] ';
204
            }
205
206
            if ($showSources === true) {
207
                if ($sourceData['strlen'] > $maxSniffWidth) {
208
                    $source = substr($source, 0, $maxSniffWidth);
209
                }
210
211
                echo $source;
212 View Code Duplication
                if ($totalFixable > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
213
                    echo str_repeat(' ', ($width - 9 - strlen($source)));
214
                } else {
215
                    echo str_repeat(' ', ($width - 5 - strlen($source)));
216
                }
217
            } else {
218
                $parts = $sourceData['parts'];
219
220
                if (strlen($parts[0]) > 8) {
221
                    $parts[0] = substr($parts[0], 0, ((strlen($parts[0]) - 8) * -1));
222
                }
223
224
                echo $parts[0].str_repeat(' ', (10 - strlen($parts[0])));
225
226
                $category = $parts[1];
227
                if (strlen($category) > 18) {
228
                    $category = substr($category, 0, ((strlen($category) - 18) * -1));
229
                }
230
231
                echo $category.str_repeat(' ', (20 - strlen($category)));
232
233
                $sniff = $parts[2];
234
                if (strlen($sniff) > $maxSniffWidth) {
235
                    $sniff = substr($sniff, 0, $maxSniffWidth);
236
                }
237
238 View Code Duplication
                if ($totalFixable > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
239
                    echo $sniff.str_repeat(' ', ($width - 39 - strlen($sniff)));
240
                } else {
241
                    echo $sniff.str_repeat(' ', ($width - 35 - strlen($sniff)));
242
                }
243
            }//end if
244
245
            echo $sourceData['count'].PHP_EOL;
246
        }//end foreach
247
248
        echo str_repeat('-', $width).PHP_EOL;
249
        echo "\033[1m".'A TOTAL OF '.($totalErrors + $totalWarnings).' SNIFF VIOLATION';
250
        if (($totalErrors + $totalWarnings) > 1) {
251
            echo 'S';
252
        }
253
254
        echo ' WERE FOUND IN '.count($this->sourceCache).' SOURCE';
0 ignored issues
show
Bug introduced by
The property sourceCache does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
255
        if (count($this->sourceCache) !== 1) {
256
            echo 'S';
257
        }
258
259
        echo "\033[0m";
260
261 View Code Duplication
        if ($totalFixable > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
262
            echo PHP_EOL.str_repeat('-', $width).PHP_EOL;
263
            echo "\033[1mPHPCBF CAN FIX THE $fixableSources MARKED SOURCES AUTOMATICALLY ($totalFixable VIOLATIONS IN TOTAL)\033[0m";
264
        }
265
266
        echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL;
267
268
        if ($toScreen === true && $interactive === false) {
269
            Timing::printRunTime();
270
        }
271
272
    }//end generate()
273
274
275
    /**
276
     * Converts a camel caps name into a readable string.
277
     *
278
     * @param string $name The camel caps name to convert.
279
     *
280
     * @return string
281
     */
282
    public function makeFriendlyName($name)
283
    {
284
        if (trim($name) === '') {
285
            return '';
286
        }
287
288
        $friendlyName = '';
289
        $length       = strlen($name);
290
291
        $lastWasUpper   = false;
292
        $lastWasNumeric = false;
293
        for ($i = 0; $i < $length; $i++) {
294
            if (is_numeric($name[$i]) === true) {
295
                if ($lastWasNumeric === false) {
296
                    $friendlyName .= ' ';
297
                }
298
299
                $lastWasUpper   = false;
300
                $lastWasNumeric = true;
301
            } else {
302
                $lastWasNumeric = false;
303
304
                $char = strtolower($name[$i]);
305
                if ($char === $name[$i]) {
306
                    // Lowercase.
307
                    $lastWasUpper = false;
308
                } else {
309
                    // Uppercase.
310
                    if ($lastWasUpper === false) {
311
                        $friendlyName .= ' ';
312
                        if ($i < ($length - 1)) {
313
                            $next = $name[($i + 1)];
314
                            if (strtolower($next) === $next) {
315
                                // Next char is lowercase so it is a word boundary.
316
                                $name[$i] = strtolower($name[$i]);
317
                            }
318
                        }
319
                    }
320
321
                    $lastWasUpper = true;
322
                }
323
            }//end if
324
325
            $friendlyName .= $name[$i];
326
        }//end for
327
328
        $friendlyName    = trim($friendlyName);
329
        $friendlyName[0] = strtoupper($friendlyName[0]);
330
331
        return $friendlyName;
332
333
    }//end makeFriendlyName()
334
335
336
}//end class
337