Completed
Pull Request — master (#209)
by Zacchaeus
13:40
created

LaravelLogViewer::foldersAndFiles()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

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