Completed
Pull Request — master (#76)
by amir
01:25
created

ErrorPrinter   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 267
Duplicated Lines 25.47 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 68
loc 267
rs 8.96
c 0
b 0
f 0
wmc 43
lcom 1
cbo 4

24 Methods

Rating   Name   Duplication   Size   Complexity  
A bladeImport() 0 4 1
A authConf() 0 4 1
A badRelation() 0 6 1
A view() 0 11 2
A route() 11 11 2
A pendError() 11 11 2
A routelessAction() 12 12 2
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 getCount() 0 4 1
A printTime() 0 4 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\LaravelPaths;
6
7
class ErrorPrinter
8
{
9
    public $errorsList = [
10
        'total' => 0,
11
    ];
12
13
    public $printer;
14
15
    public $logErrors = true;
16
17
    public $pended = [];
18
19
    public function view($absPath, $lineContent, $lineNumber, $fileName)
20
    {
21
        if (LaravelPaths::isIgnored($absPath)) {
22
            return;
23
        }
24
25
        ($this->errorsList['view'][] = (new PendingError('view'))
26
            ->header(\trim($lineContent))
27
            ->errorData($this->yellow($fileName.'.blade.php').' does not exist')
28
            ->link($absPath, $lineNumber));
29
    }
30
31 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...
32
    {
33
        if (LaravelPaths::isIgnored($absPath)) {
34
            return;
35
        }
36
37
        ($this->errorsList['route'][] = (new PendingError('route'))
38
            ->header($errorIt)
39
            ->errorData($errorTxt.$this->yellow($path))
40
            ->link($absPath, $lineNumber));
41
    }
42
43
    public function bladeImport($class, $absPath, $lineNumber)
44
    {
45
        $this->pendError($absPath, $lineNumber, $class, 'bladeImport', 'Class does not exist:');
46
    }
47
48
    public function authConf()
49
    {
50
        $this->print('The model in the "config/auth.php" is not a valid class');
51
    }
52
53
    public function badRelation($absPath, $lineNumber, $relatedModel)
54
    {
55
        $header = 'Wrong model is passed in relation:';
56
57
        $this->pendError($absPath, $lineNumber, $relatedModel, 'badRelation', $header);
58
    }
59
60 View Code Duplication
    public function pendError($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...
61
    {
62
        if (LaravelPaths::isIgnored($path)) {
63
            return;
64
        }
65
66
        ($this->errorsList[$key][] = (new PendingError($key))
67
            ->header($header)
68
            ->errorData($this->yellow($absent).'   <==== does not exist')
69
            ->link($path, $lineNumber));
70
    }
71
72 View Code Duplication
    public function routelessAction($absPath, $lineNumber, $action)
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...
73
    {
74
        if (LaravelPaths::isIgnored($absPath)) {
75
            return;
76
        }
77
78
        $key = 'routelessCtrl';
79
        ($this->errorsList[$key][] = (new PendingError($key))
80
            ->header('No route is defined for controller action:')
81
            ->errorData($this->yellow($action))
82
            ->link($absPath, $lineNumber));
83
    }
84
85 View Code Duplication
    public function simplePendError($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...
86
    {
87
        if (LaravelPaths::isIgnored($path)) {
88
            return;
89
        }
90
91
        ($this->errorsList[$key][] = (new PendingError($key))
92
            ->header($header)
93
            ->errorData($this->yellow($absent))
94
            ->link($path, $lineNumber));
95
    }
96
97
    public function wrongImport($absPath, $class, $lineNumber)
98
    {
99
        $this->pendError($absPath, $lineNumber, "use $class;", 'wrongImport', 'Wrong import:');
100
    }
101
102 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...
103
    {
104
        if (LaravelPaths::isIgnored($path)) {
105
            return;
106
        }
107
108
        ($this->errorsList[$key][] = (new PendingError($key))
109
            ->header($header)
110
            ->errorData($this->yellow(\implode(', ', array_keys($absent))).' does not exist')
111
            ->link($path, $lineNumber));
112
    }
113
114
    public function routeDefinitionConflict($route1, $route2, $info)
115
    {
116
        if (LaravelPaths::isIgnored($info[0]['file'])) {
117
            return;
118
        }
119
120
        $key = 'routeDefinitionConflict';
121
        $routeName = $route1->getName();
122
        if ($routeName) {
123
            $routeName = $this->yellow($routeName);
124
            $msg = 'Route name: '.$routeName;
125
        } else {
126
            $routeUri = $route1->uri();
127
            $routeUri = $this->yellow($routeUri);
128
            $msg = 'Route uri: '.$routeUri;
129
        }
130
131
        $msg .= "\n".' at '.($info[0]['file'] ?? 'unknown').':'.($info[0]['line'] ?? 2);
132
        $msg .= "\n".' is overridden by ';
133
134
        $routeName = $route2->getName();
135
        if ($routeName) {
136
            $routeName = $this->yellow($routeName);
137
            $msg .= 'route name: '.$routeName;
138
        } else {
139
            $msg .= 'an other route with same uri.';
140
        }
141
142
        $msg .= "\n".' at '.$info[1]['file'].':'.$info[1]['line']."\n";
143
144
        $methods = \implode(',', $route1->methods());
145
146
        $this->errorsList[$key][$methods] = (new PendingError($key))
147
            ->header('Route with uri: '.$this->yellow($methods.': /'.$route1->uri()).' is overridden.')
148
            ->errorData($msg);
149
    }
150
151
    public function wrongUsedClassError($absPath, $class, $lineNumber)
152
    {
153
        $this->pendError($absPath, $lineNumber, $class, 'wrongUsedClassError', 'Class does not exist:');
154
    }
155
156 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...
157
    {
158
        if (LaravelPaths::isIgnored($absPath)) {
159
            return;
160
        }
161
162
        $key = 'queryInBlade';
163
        ($this->errorsList[$key][] = (new PendingError($key))
164
            ->header('Query in blade file: ')
165
            ->errorData($this->yellow($class).'  <=== DB query in blade file')
166
            ->link($absPath, $lineNumber));
167
    }
168
169
    public function wrongMethodError($absPath, $class, $lineNumber)
170
    {
171
        $this->pendError($absPath, $lineNumber, $class, 'wrongMethodError', 'Method does not exist:');
172
    }
173
174
    public function yellow($msg)
175
    {
176
        return "<fg=yellow>$msg</>";
177
    }
178
179
    public function badNamespace($absPath, $correctNamespace, $incorrectNamespace, $lineNumber = 4)
180
    {
181
        if (LaravelPaths::isIgnored($absPath)) {
182
            return;
183
        }
184
185
        ($this->errorsList['badNamespace'][] = (new PendingError('badNamespace'))
186
            ->header('Incorrect namespace: '.$this->yellow("namespace $incorrectNamespace;"))
187
            ->errorData('  namespace fixed to:  '.$this->yellow("namespace $correctNamespace;"))
188
            ->link($absPath, $lineNumber));
189
    }
190
191
    public function print($msg, $path = '|  ', $len = null)
192
    {
193
        ! $len && $len = PendingError::$maxLength + 1;
194
        $msgLen = strlen($msg);
195
        if (strpos($msg, 'yellow')) {
196
            $msgLen = $msgLen - 14;
197
        }
198
        $len = $len - $msgLen;
199
        if ($len < 0) {
200
            $len = 0;
201
        }
202
203
        $this->printer->writeln($path.$msg.str_repeat(' ', $len).'|');
204
    }
205
206
    public function printHeader($msg)
207
    {
208
        $number = ++$this->errorsList['total'];
209
        ($number < 10) && $number = " $number";
210
211
        $number = '<fg=yellow>'.$number.' </>';
212
        $path = "| $number";
213
214
        PendingError::$maxLength = max(PendingError::$maxLength, strlen($msg));
215
        $this->print('');
216
        $this->print($msg, $path, PendingError::$maxLength - 1);
217
    }
218
219
    public function end()
220
    {
221
        $this->print('');
222
        $this->printer->writeln('|'.str_repeat('*', 3 + PendingError::$maxLength).'|  ');
223
    }
224
225
    public function printLink($path, $lineNumber = 4)
226
    {
227
        if ($path) {
228
            $filePath = \trim(\str_replace(base_path(), '', $path), '\\/');
229
            $this->print('at <fg=green>'.$filePath.'</>'.':<fg=green>'.$lineNumber.'</>', '', PendingError::$maxLength + 30);
230
        }
231
    }
232
233
    /**
234
     * Checks for errors for the run command.
235
     *
236
     * @return int
237
     */
238
    public function hasErrors()
239
    {
240
        $errorsCollection = collect($this->errorsList);
241
242
        return $errorsCollection->flatten()->filter(function ($action) {
243
            return $action instanceof PendingError;
244
        })->count();
245
    }
246
247
    public function logErrors()
248
    {
249
        collect($this->errorsList)->except('total')->flatten()->each(function ($error) {
250
            if ($error instanceof PendingError) {
251
                $this->printHeader($error->getHeader());
252
                $this->print($error->getErrorData());
253
                $this->printLink($error->getLinkPath(), $error->getLinkLineNumber());
254
                $this->end();
255
            }
256
        });
257
258
        foreach ($this->pended as $pend) {
259
            $this->print($pend);
260
            $this->end();
261
        }
262
    }
263
264
    public function getCount($key)
265
    {
266
        return \count($this->errorsList[$key] ?? []);
267
    }
268
269
    public function printTime()
270
    {
271
        $this->logErrors && $this->printer->writeln('Total elapsed time: '.round(microtime(true) - microscope_start, 2).' sec', 2);
272
    }
273
}
274