Completed
Push — master ( 27392d...1a11c7 )
by raphael
01:06
created

LaravelLogViewer   C

Complexity

Total Complexity 53

Size/Duplication

Total Lines 288
Duplicated Lines 4.86 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 53
lcom 1
cbo 2
dl 14
loc 288
rs 6.96
c 0
b 0
f 0

10 Methods

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