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

LaravelLogViewer::getFiles()   A

Complexity

Conditions 6
Paths 8

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

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