Completed
Pull Request — master (#175)
by Elminson
01:17
created

LaravelLogViewer   B

Complexity

Total Complexity 49

Size/Duplication

Total Lines 276
Duplicated Lines 5.07 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 49
lcom 1
cbo 2
dl 14
loc 276
rs 8.48
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 2
A setFolder() 8 18 5
A setFile() 0 8 2
B pathToLogFile() 6 24 7
A getFolderName() 0 4 1
A getFileName() 0 4 1
D all() 0 78 16
A getFolders() 0 21 5
A getFolderFiles() 0 4 1
B getFiles() 0 30 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 LaravelLogViewer 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 LaravelLogViewer, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Rap2hpoutre\LaravelLogViewer;
4
5
/**
6
 * Class LaravelLogViewer
7
 * @package Rap2hpoutre\LaravelLogViewer
8
 */
9
class LaravelLogViewer
10
{
11
    /**
12
     * @var string file
13
     */
14
    private $file;
15
16
    /**
17
     * @var string folder
18
     */
19
    private $folder;
20
21
    /**
22
     * @var string storage_path
23
     */
24
    private $storage_path;
25
26
    /**
27
     * Why? Uh... Sorry
28
     */
29
    const MAX_FILE_SIZE = 52428800;
30
31
    /**
32
     * @var Level level
33
     */
34
    private $level;
35
36
    /**
37
     * @var Pattern pattern
38
     */
39
    private $pattern;
40
41
    /**
42
     * LaravelLogViewer constructor.
43
     */
44
    public function __construct()
45
    {
46
        $this->level = new Level();
47
        $this->pattern = new Pattern();
48
        $this->storage_path = function_exists('config') ? config('logviewer.storage_path', storage_path('logs')) : storage_path('logs');
49
50
    }
51
52
    /**
53
     * @param string $folder
54
     */
55
    public function setFolder($folder)
56
    {
57
        //fix multi level folder
58
        if(is_array($this->storage_path)){
59 View Code Duplication
            foreach ($this->storage_path as $value) {
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...
60
                $logsPath = $value . '/' . $folder;
61
                if (app('files')->exists($logsPath)) {
62
63
                    $this->folder = $folder;
64
                    break;
65
                }
66
            }
67
        } else {
68
            if (app('files')->exists($folder)) {
69
                $this->folder = $folder;
70
            }
71
        }
72
    }
73
74
    /**
75
     * @param string $file
76
     * @throws \Exception
77
     */
78
    public function setFile($file)
79
    {
80
        $file = $this->pathToLogFile($file);
81
82
        if (app('files')->exists($file)) {
83
            $this->file = $file;
84
        }
85
    }
86
87
    /**
88
     * @param string $file
89
     * @return string
90
     * @throws \Exception
91
     */
92
    public function pathToLogFile($file)
93
    {
94
        if (app('files')->exists($file)) { // try the absolute path
95
            return $file;
96
        }
97
        if (is_array($this->storage_path)) {
98 View Code Duplication
            foreach ($this->storage_path as $folder) {
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...
99
                if (app('files')->exists($folder . '/' . $file)) { // try the absolute path
100
                    $file = $folder . '/' . $file;
101
                    break;
102
                }
103
            }
104
            return $file;
105
        }
106
107
        $logsPath = $this->storage_path;
108
        $logsPath .= ($this->folder) ? '/' . $this->folder : '';
109
        $file = $logsPath . '/' . $file;
110
        // check if requested file is really in the logs directory
111
        if (dirname($file) !== $logsPath) {
112
            throw new \Exception('No such log file');
113
        }
114
        return $file;
115
    }
116
117
    /**
118
     * @return string
119
     */
120
    public function getFolderName()
121
    {
122
        return $this->folder;
123
    }
124
125
    /**
126
     * @return string
127
     */
128
    public function getFileName()
129
    {
130
        return basename($this->file);
131
    }
132
133
    /**
134
     * @return array
135
     */
136
    public function all()
137
    {
138
        $log = array();
139
140
        if (!$this->file) {
141
            $log_file = (!$this->folder) ? $this->getFiles() : $this->getFolderFiles();
142
            if (!count($log_file)) {
143
                return [];
144
            }
145
            $this->file = $log_file[0];
146
        }
147
148
        if (app('files')->size($this->file) > self::MAX_FILE_SIZE) {
149
            return null;
150
        }
151
152
        $file = app('files')->get($this->file);
153
154
        preg_match_all($this->pattern->getPattern('logs'), $file, $headings);
155
156
        if (!is_array($headings)) {
157
            return $log;
158
        }
159
160
        $log_data = preg_split($this->pattern->getPattern('logs'), $file);
161
162
        if ($log_data[0] < 1) {
163
            array_shift($log_data);
164
        }
165
166
        foreach ($headings as $h) {
167
            for ($i = 0, $j = count($h); $i < $j; $i++) {
168
                foreach ($this->level->all() as $level) {
169
                    if (strpos(strtolower($h[$i]), '.' . $level) || strpos(strtolower($h[$i]), $level . ':')) {
170
171
                        preg_match($this->pattern->getPattern('current_log', 0) . $level . $this->pattern->getPattern('current_log', 1), $h[$i], $current);
172
                        if (!isset($current[4])) {
173
                            continue;
174
                        }
175
176
                        $log[] = array(
177
                            'context' => $current[3],
178
                            'level' => $level,
179
                            'folder' => $this->folder,
180
                            'level_class' => $this->level->cssClass($level),
181
                            'level_img' => $this->level->img($level),
182
                            'date' => $current[1],
183
                            'text' => $current[4],
184
                            'in_file' => isset($current[5]) ? $current[5] : null,
185
                            'stack' => preg_replace("/^\n*/", '', $log_data[$i])
186
                        );
187
                    }
188
                }
189
            }
190
        }
191
192
        if (empty($log)) {
193
194
            $lines = explode(PHP_EOL, $file);
195
            $log = [];
196
197
            foreach ($lines as $key => $line) {
198
                $log[] = [
199
                    'context' => '',
200
                    'level' => '',
201
                    'folder' => '',
202
                    'level_class' => '',
203
                    'level_img' => '',
204
                    'date' => $key + 1,
205
                    'text' => $line,
206
                    'in_file' => null,
207
                    'stack' => '',
208
                ];
209
            }
210
        }
211
212
        return array_reverse($log);
213
    }
214
215
    /**
216
     * @return array
217
     */
218
    public function getFolders()
219
    {
220
        $folders = [];
221
        if (is_array($this->storage_path)) {
222
            foreach ($this->storage_path as $value) {
223
                $folders = array_merge(
224
                  $folders,
225
                  glob($value . '/*', GLOB_ONLYDIR)
226
                );
227
            }
228
        } else {
229
            $folders = glob($this->storage_path . '/*', GLOB_ONLYDIR);
230
        }
231
232
        if (is_array($folders)) {
233
            foreach ($folders as $k => $folder) {
234
                $folders[$k] = basename($folder);
235
            }
236
        }
237
        return array_values($folders);
238
    }
239
240
    /**
241
     * @param bool $basename
242
     * @return array
243
     */
244
    public function getFolderFiles($basename = false)
245
    {
246
        return $this->getFiles($basename, $this->folder);
247
    }
248
249
    /**
250
     * @param bool $basename
251
     * @param string $folder
252
     * @return array
253
     */
254
    public function getFiles($basename = false, $folder = '')
255
    {
256
        $files = [];
257
        $pattern = function_exists('config') ? config('logviewer.pattern', '*.log') : '*.log';
258
        if (is_array($this->storage_path)) {
259
            foreach ($this->storage_path as $value) {
260
                $files = array_merge(
261
                  $files,
262
                  glob(
263
                    $value . '/' . $folder . '/' . $pattern,
264
                    preg_match($this->pattern->getPattern('files'), $pattern) ? GLOB_BRACE : 0
265
                  )
266
                );
267
            }
268
        } else {
269
            $files = glob(
270
              $this->storage_path . '/' . $folder . '/' . $pattern,
271
              preg_match($this->pattern->getPattern('files'), $pattern) ? GLOB_BRACE : 0
272
            );
273
        }
274
275
        $files = array_reverse($files);
276
        $files = array_filter($files, 'is_file');
277
        if ($basename && is_array($files)) {
278
            foreach ($files as $k => $file) {
279
                $files[$k] = basename($file);
280
            }
281
        }
282
        return array_values($files);
283
    }
284
}
285