Completed
Pull Request — master (#209)
by Zacchaeus
01:10
created

LaravelLogViewer::getFiles()   A

Complexity

Conditions 6
Paths 8

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.0777
c 0
b 0
f 0
cc 6
nc 8
nop 2
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
85
        $file = $this->pathToLogFile($file);
86
87
        if (app('files')->exists($file)) {
88
            $this->file = $file;
89
        }
90
    }
91
92
    /**
93
     * @param string $file
94
     * @return string
95
     * @throws \Exception
96
     */
97
    public function pathToLogFile($file)
98
    {
99
100
        if (app('files')->exists($file)) { // try the absolute path
101
            return $file;
102
        }
103
        if (is_array($this->storage_path)) {
104 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...
105
                if (app('files')->exists($folder . '/' . $file)) { // try the absolute path
106
                    $file = $folder . '/' . $file;
107
                    break;
108
                }
109
            }
110
            return $file;
111
        }
112
113
        $logsPath = $this->storage_path;
114
        $logsPath .= ($this->folder) ? '/' . $this->folder : '';
115
        $file = $logsPath . '/' . $file;
116
        // check if requested file is really in the logs directory
117
        if (dirname($file) !== $logsPath) {
118
            throw new \Exception('No such log file: '.$file);
119
        }
120
        return $file;
121
    }
122
123
    /**
124
     * @return string
125
     */
126
    public function getFolderName()
127
    {
128
        return $this->folder;
129
    }
130
131
    /**
132
     * @return string
133
     */
134
    public function getFileName()
135
    {
136
        return basename($this->file);
137
    }
138
139
    /**
140
     * @return array
141
     */
142
    public function all()
143
    {
144
        $log = array();
145
146
        if (!$this->file) {
147
            $log_file = (!$this->folder) ? $this->getFiles() : $this->getFolderFiles();
148
            if (!count($log_file)) {
149
                return [];
150
            }
151
            $this->file = $log_file[0];
152
        }
153
154
        $max_file_size = function_exists('config') ? config('logviewer.max_file_size', self::MAX_FILE_SIZE) : self::MAX_FILE_SIZE;
155
        if (app('files')->size($this->file) > $max_file_size) {
156
            return null;
157
        }
158
159
        $file = app('files')->get($this->file);
160
161
        preg_match_all($this->pattern->getPattern('logs'), $file, $headings);
162
163
        if (!is_array($headings)) {
164
            return $log;
165
        }
166
167
        $log_data = preg_split($this->pattern->getPattern('logs'), $file);
168
169
        if ($log_data[0] < 1) {
170
            array_shift($log_data);
171
        }
172
173
        foreach ($headings as $h) {
174
            for ($i = 0, $j = count($h); $i < $j; $i++) {
175
                foreach ($this->level->all() as $level) {
176
                    if (strpos(strtolower($h[$i]), '.' . $level) || strpos(strtolower($h[$i]), $level . ':')) {
177
178
                        preg_match($this->pattern->getPattern('current_log', 0) . $level . $this->pattern->getPattern('current_log', 1), $h[$i], $current);
179
                        if (!isset($current[4])) {
180
                            continue;
181
                        }
182
183
                        $log[] = array(
184
                            'context' => $current[3],
185
                            'level' => $level,
186
                            'folder' => $this->folder,
187
                            'level_class' => $this->level->cssClass($level),
188
                            'level_img' => $this->level->img($level),
189
                            'date' => $current[1],
190
                            'text' => $current[4],
191
                            'in_file' => isset($current[5]) ? $current[5] : null,
192
                            'stack' => preg_replace("/^\n*/", '', $log_data[$i])
193
                        );
194
                    }
195
                }
196
            }
197
        }
198
199
        if (empty($log)) {
200
201
            $lines = explode(PHP_EOL, $file);
202
            $log = [];
203
204
            foreach ($lines as $key => $line) {
205
                $log[] = [
206
                    'context' => '',
207
                    'level' => '',
208
                    'folder' => '',
209
                    'level_class' => '',
210
                    'level_img' => '',
211
                    'date' => $key + 1,
212
                    'text' => $line,
213
                    'in_file' => null,
214
                    'stack' => '',
215
                ];
216
            }
217
        }
218
219
        return array_reverse($log);
220
    }
221
222
	/**Creates a multidimensional array
223
	 * of subdirectories and files
224
	 *
225
	 * @param null $path
226
	 *
227
	 * @return array
228
	 */
229
    public function foldersAndFiles($path = null)
230
    {
231
	    $contents = array();
232
	    $dir = $path ? $path : $this->storage_path;
233
	    foreach (scandir($dir) as $node) {
234
		    if ($node == '.' || $node == '..') continue;
235
		    $path = $dir . '\\' . $node;
236
		    if (is_dir($path)) {
237
			    $contents[$path] = $this->foldersAndFiles($path);
238
		    } else {
239
			    $contents[] = $path;
240
		    }
241
	    }
242
243
	    return $contents;
244
    }
245
246
	/**Returns an array of
247
	 * all subdirectories of specified directory
248
	 *
249
	 * @param string $folder
250
	 *
251
	 * @return array
252
	 */
253
    public function getFolders($folder = '')
254
    {
255
	    $folders = [];
256
	    $listObject = new \RecursiveIteratorIterator(
257
		    new \RecursiveDirectoryIterator($this->storage_path.'/'.$folder, \RecursiveDirectoryIterator::SKIP_DOTS),
258
		    \RecursiveIteratorIterator::CHILD_FIRST
259
	    );
260
	    foreach ($listObject as $fileinfo) {
261
		    if($fileinfo->isDir()) $folders[] = $fileinfo->getRealPath();
262
	    }
263
	    return $folders;
264
    }
265
266
    /**
267
     * @param bool $basename
268
     * @return array
269
     */
270
    public function getFolderFiles($basename = false)
271
    {
272
        return $this->getFiles($basename, $this->folder);
273
    }
274
275
    /**
276
     * @param bool $basename
277
     * @param string $folder
278
     * @return array
279
     */
280
    public function getFiles($basename = false, $folder = '')
281
    {
282
	    $files = [];
283
	    $pattern = function_exists('config') ? config('logviewer.pattern', '*.log') : '*.log';
284
	    $fullPath = $this->storage_path.'/'.$folder;
285
286
	    $listObject = new \RecursiveIteratorIterator(
287
		    new \RecursiveDirectoryIterator($fullPath, \RecursiveDirectoryIterator::SKIP_DOTS),
288
		    \RecursiveIteratorIterator::CHILD_FIRST
289
	    );
290
291
	    foreach ($listObject as $fileinfo) {
292
		    if(!$fileinfo->isDir() && strtolower(pathinfo($fileinfo->getRealPath(), PATHINFO_EXTENSION)) == explode('.', $pattern)[1])
293
			    $files[] = $basename ? basename($fileinfo->getRealPath()) : $fileinfo->getRealPath();
294
	    }
295
	    return $files;
296
    }
297
298
	/**
299
	 * @return string
300
	 */
301
    public function getStoragePath()
302
    {
303
    	return $this->storage_path;
304
    }
305
306
	/**
307
	 * @param $path
308
	 *
309
	 * @return void
310
	 */
311
	public function setStoragePath($path)
312
	{
313
		$this->storage_path = $path;
314
	}
315
316
    public static function directoryTreeStructure($storage_path, array $array)
317
    {
318
	    foreach ($array as $k => $v) {
319
		    if(is_dir( $k )) {
320
321
			    $exploded = explode( "\\", $k );
322
			    $show = last( $exploded );
323
324
			    echo '<div class="list-group folder">
325
				    <a href="?f='. \Illuminate\Support\Facades\Crypt::encrypt($k).'">
326
					    <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
327
						    class="fa fa-folder"></span> '.$show.'
328
				    </a>
329
			    </div>';
330
331
			    if ( is_array( $v ) ) {
332
				    self::directoryTreeStructure( $storage_path, $v );
333
			    }
334
335
		    }
336
		    else {
337
338
			    $exploded = explode( "\\", $v );
339
			    $show2 = last( $exploded );
340
			    $folder = str_replace( $storage_path, "", rtrim( str_replace( $show2, "", $v ), "\\" ) );
341
			    $file = $v;
342
343
344
			   echo '<div class="list-group">
345
				    <a href="?l='.\Illuminate\Support\Facades\Crypt::encrypt($file).'&f='.\Illuminate\Support\Facades\Crypt::encrypt($folder).'">
346
					    <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span
347
						    class="fa fa-file"></span> '.$show2.'
348
				    </a>
349
			    </div>';
350
351
		    }
352
	    }
353
    }
354
}
355