Completed
Push — master ( 11d4d7...5c8a4b )
by raphael
05:32
created

LaravelLogViewer::setFolder()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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