Completed
Push — master ( 9eb157...ff31c5 )
by Iman
01:37
created

ErrorPrinter   B

Complexity

Total Complexity 49

Size/Duplication

Total Lines 297
Duplicated Lines 15.15 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
dl 45
loc 297
rs 8.48
c 0
b 0
f 0
wmc 49
lcom 1
cbo 5

29 Methods

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