Completed
Push — master ( fc34f9...5288c0 )
by Iman
02:03
created

ErrorPrinter   B

Complexity

Total Complexity 48

Size/Duplication

Total Lines 290
Duplicated Lines 11.72 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
dl 34
loc 290
rs 8.5599
c 0
b 0
f 0
wmc 48
lcom 1
cbo 5

29 Methods

Rating   Name   Duplication   Size   Complexity  
A end() 0 5 1
A printLink() 0 7 2
A hasErrors() 0 8 1
A logErrors() 0 16 3
A authConf() 0 4 1
A badRelation() 0 6 1
A view() 0 4 1
A printFixation() 0 7 1
A route() 0 4 1
A doesNotExist() 0 4 1
A routelessAction() 0 4 1
A simplePendError() 11 11 2
A wrongImport() 0 4 1
A compactError() 11 11 2
A routeDefinitionConflict() 0 36 4
A wrongUsedClassError() 0 4 1
A queryInBlade() 12 12 2
A wrongMethodError() 0 4 1
A yellow() 0 4 1
A badNamespace() 0 11 2
A print() 0 14 4
A printHeader() 0 12 2
A possibleFixMsg() 0 7 2
A wrongImportPossibleFixes() 0 5 1
A getCount() 0 4 1
A printTime() 0 4 2
A thanks() 0 11 1
A warnIncorrectNamespace() 0 13 3
A ask() 0 8 2

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 ErrorPrinter 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 ErrorPrinter, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Imanghafoori\LaravelMicroscope\ErrorReporters;
4
5
use Imanghafoori\LaravelMicroscope\LaravelPaths\FilePath;
6
use Imanghafoori\LaravelMicroscope\LaravelPaths\LaravelPaths;
7
8
class ErrorPrinter
9
{
10
    public $errorsList = [
11
        'total' => 0,
12
    ];
13
14
    public $printer;
15
16
    public $logErrors = true;
17
18
    public $pended = [];
19
20
    public function view($absPath, $message, $lineNumber, $fileName)
21
    {
22
        $this->simplePendError($fileName.'.blade.php', $absPath, $lineNumber, 'view', \trim($message), ' does not exist');
23
    }
24
25
    public function printFixation($absPath, $wrongClass, $lineNumber, $correct)
26
    {
27
        $header = $wrongClass.'  <===  Did not exist';
28
        $msg = 'Auto-corrected to:   '.substr($correct[0], 0, 55);
29
30
        $this->simplePendError($msg, $absPath, $lineNumber, 'ns_replacement', $header);
31
    }
32
33
    public function route($path, $errorIt, $errorTxt, $absPath = null, $lineNumber = 0)
34
    {
35
        $this->simplePendError($path, $absPath, $lineNumber, 'route', $errorIt, '', $errorTxt);
36
    }
37
38
    public function authConf()
39
    {
40
        $this->print('The model in the "config/auth.php" is not a valid class');
41
    }
42
43
    public function badRelation($absPath, $lineNumber, $relatedModel)
44
    {
45
        $header = 'Wrong model is passed in relation:';
46
47
        $this->doesNotExist($relatedModel, $absPath, $lineNumber, 'badRelation', $header);
48
    }
49
50
    public function doesNotExist($yellowText, $absPath, $lineNumber, $key, $header)
51
    {
52
        $this->simplePendError($yellowText, $absPath, $lineNumber, $key, $header, '   <==== does not exist');
53
    }
54
55
    public function routelessAction($absPath, $lineNumber, $msg)
56
    {
57
        $this->simplePendError($msg, $absPath, $lineNumber, 'routelessCtrl', 'No route is defined for controller action:');
58
    }
59
60 View Code Duplication
    public function simplePendError($yellowText, $absPath, $lineNumber, $key, $header, $rest = '', $pre = '')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
61
    {
62
        if (LaravelPaths::isIgnored($absPath)) {
63
            return;
64
        }
65
66
        ($this->errorsList[$key][] = (new PendingError($key))
67
            ->header($header)
68
            ->errorData($pre.$this->yellow($yellowText). $rest)
69
            ->link($absPath, $lineNumber));
70
    }
71
72
    public function wrongImport($absPath, $class, $lineNumber)
73
    {
74
        $this->doesNotExist("use $class;", $absPath, $lineNumber, 'wrongImport', 'Wrong import:');
75
    }
76
77 View Code Duplication
    public function compactError($path, $lineNumber, $absent, $key, $header)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
78
    {
79
        if (LaravelPaths::isIgnored($path)) {
80
            return;
81
        }
82
83
        ($this->errorsList[$key][] = (new PendingError($key))
84
            ->header($header)
85
            ->errorData($this->yellow(\implode(', ', array_keys($absent))).' does not exist')
86
            ->link($path, $lineNumber));
87
    }
88
89
    public function routeDefinitionConflict($route1, $route2, $info)
90
    {
91
        if (LaravelPaths::isIgnored($info[0]['file'] ?? 'unknown')) {
92
            return;
93
        }
94
95
        $key = 'routeDefinitionConflict';
96
        $routeName = $route1->getName();
97
        if ($routeName) {
98
            $routeName = $this->yellow($routeName);
99
            $msg = 'Route name: '.$routeName;
100
        } else {
101
            $routeUri = $route1->uri();
102
            $routeUri = $this->yellow($routeUri);
103
            $msg = 'Route uri: '.$routeUri;
104
        }
105
106
        $msg .= "\n".' at '.($info[0]['file'] ?? 'unknown').':'.($info[0]['line'] ?? 2);
107
        $msg .= "\n".' is overridden by ';
108
109
        $routeName = $route2->getName();
110
        if ($routeName) {
111
            $routeName = $this->yellow($routeName);
112
            $msg .= 'route name: '.$routeName;
113
        } else {
114
            $msg .= 'an other route with same uri.';
115
        }
116
117
        $msg .= "\n".' at '.($info[1]['file'] ?? ' ').':'.$info[1]['line']."\n";
118
119
        $methods = \implode(',', $route1->methods());
120
121
        $this->errorsList[$key][$methods] = (new PendingError($key))
122
            ->header('Route with uri: '.$this->yellow($methods.': /'.$route1->uri()).' is overridden.')
123
            ->errorData($msg);
124
    }
125
126
    public function wrongUsedClassError($absPath, $class, $lineNumber)
127
    {
128
        $this->doesNotExist($class, $absPath, $lineNumber, 'wrongUsedClassError', 'Class does not exist:');
129
    }
130
131 View Code Duplication
    public function queryInBlade($absPath, $class, $lineNumber)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
132
    {
133
        if (LaravelPaths::isIgnored($absPath)) {
134
            return;
135
        }
136
137
        $key = 'queryInBlade';
138
        ($this->errorsList[$key][] = (new PendingError($key))
139
            ->header('Query in blade file: ')
140
            ->errorData($this->yellow($class).'  <=== DB query in blade file')
141
            ->link($absPath, $lineNumber));
142
    }
143
144
    public function wrongMethodError($absPath, $class, $lineNumber)
145
    {
146
        $this->doesNotExist($class, $absPath, $lineNumber, 'wrongMethodError', 'Method does not exist:');
147
    }
148
149
    public function yellow($msg)
150
    {
151
        return "<fg=yellow>$msg</>";
152
    }
153
154
    public function badNamespace($absPath, $correctNamespace, $incorrectNamespace, $lineNumber = 4)
155
    {
156
        if (LaravelPaths::isIgnored($absPath)) {
157
            return;
158
        }
159
160
        ($this->errorsList['badNamespace'][] = (new PendingError('badNamespace'))
161
            ->header('Incorrect namespace: '.$this->yellow("namespace $incorrectNamespace;"))
162
            ->errorData('  namespace fixed to:  '.$this->yellow("namespace $correctNamespace;"))
163
            ->link($absPath, $lineNumber));
164
    }
165
166
    public function print($msg, $path = '|  ', $len = null)
167
    {
168
        ! $len && $len = PendingError::$maxLength + 1;
169
        $msgLen = strlen($msg);
170
        if (strpos($msg, 'yellow')) {
171
            $msgLen = $msgLen - 14;
172
        }
173
        $len = $len - $msgLen;
174
        if ($len < 0) {
175
            $len = 0;
176
        }
177
178
        $this->printer->writeln($path.$msg.str_repeat(' ', $len).'|');
179
    }
180
181
    public function printHeader($msg)
182
    {
183
        $number = ++$this->errorsList['total'];
184
        ($number < 10) && $number = " $number";
185
186
        $number = '<fg=yellow>'.$number.' </>';
187
        $path = "| $number";
188
189
        PendingError::$maxLength = max(PendingError::$maxLength, strlen($msg));
190
        $this->print('');
191
        $this->print($msg, $path, PendingError::$maxLength - 1);
192
    }
193
194
    public function end()
195
    {
196
        $this->print('');
197
        $this->printer->writeln('|'.str_repeat('*', 3 + PendingError::$maxLength).'|  ');
198
    }
199
200
    public function printLink($path, $lineNumber = 4)
201
    {
202
        if ($path) {
203
            $relativePath = FilePath::normalize(\trim(\str_replace(base_path(), '', $path), '\\/'));
204
            $this->print('at <fg=green>'.$relativePath.'</>'.':<fg=green>'.$lineNumber.'</>', '', PendingError::$maxLength + 30);
205
        }
206
    }
207
208
    /**
209
     * Checks for errors for the run command.
210
     *
211
     * @return int
212
     */
213
    public function hasErrors()
214
    {
215
        $errorsCollection = collect($this->errorsList);
216
217
        return $errorsCollection->flatten()->filter(function ($action) {
218
            return $action instanceof PendingError;
219
        })->count();
220
    }
221
222
    public function logErrors()
223
    {
224
        collect($this->errorsList)->except('total')->flatten()->each(function ($error) {
225
            if ($error instanceof PendingError) {
226
                $this->printHeader($error->getHeader());
227
                $this->print($error->getErrorData());
228
                $this->printLink($error->getLinkPath(), $error->getLinkLineNumber());
229
                $this->end();
230
            }
231
        });
232
233
        foreach ($this->pended as $pend) {
234
            $this->print($pend);
235
            $this->end();
236
        }
237
    }
238
239
    private static function possibleFixMsg($pieces)
240
    {
241
        $fixes = \implode("\n - ", $pieces);
242
        $fixes && $fixes = "\n Possible fixes:\n - ".$fixes;
243
244
        return $fixes;
245
    }
246
247
    public function wrongImportPossibleFixes($absPath, $class, $line, $fixes)
248
    {
249
        $fixes = self::possibleFixMsg($fixes);
250
        $this->wrongUsedClassError($absPath, $class.'   <===  \(-_-)/  '.$fixes, $line);
251
    }
252
253
    public function getCount($key)
254
    {
255
        return \count($this->errorsList[$key] ?? []);
256
    }
257
258
    public function printTime()
259
    {
260
        $this->logErrors && $this->printer->writeln('time: '.round(microtime(true) - microscope_start, 3).' (sec)', 2);
261
    }
262
263
    public static function thanks($command)
264
    {
265
        $command->line(PHP_EOL.'<fg=blue>|-------------------------------------------------|</>');
266
        $command->line('<fg=blue>|-----------     Star Me On Github     -----------|</>');
267
        $command->line('<fg=blue>|-------------------------------------------------|</>');
268
        $command->line('<fg=blue>|  Hey man, if you have found microscope useful   |</>');
269
        $command->line('<fg=blue>|  Please consider giving it an star on github.   |</>');
270
        $command->line('<fg=blue>|  \(^_^)/    Regards, Iman Ghafoori    \(^_^)/   |</>');
271
        $command->line('<fg=blue>|-------------------------------------------------|</>');
272
        $command->line('https://github.com/imanghafoori1/microscope');
273
    }
274
275
    public static function warnIncorrectNamespace($currentNamespace, $relativePath, $class)
276
    {
277
        /**
278
         * @var $p ErrorPrinter
279
         */
280
        $p = app(ErrorPrinter::class);
281
        $msg = 'Incorrect namespace: '.$p->yellow("namespace $currentNamespace;");
282
        PendingError::$maxLength = max(PendingError::$maxLength, strlen($msg));
283
        $p->end();
284
        $currentNamespace && $p->printHeader('Incorrect namespace: '.$p->yellow("namespace $currentNamespace;"));
285
        ! $currentNamespace && $p->printHeader('Namespace Not Found: '.$class);
286
        $p->printLink($relativePath, 3);
287
    }
288
289
    public static function ask($command, $correctNamespace)
290
    {
291
        if ($command->option('force')) {
292
            return true;
293
        }
294
295
        return $command->getOutput()->confirm('Do you want to change it to: '.$correctNamespace, true);
296
    }
297
}
298