Completed
Push — master ( 1c3eca...176ce4 )
by Mark
02:10 queued 01:03
created

QueryListener::listen()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
3
namespace Socialblue\LaravelQueryAdviser\DataListener;
4
5
use Illuminate\Database\Events\QueryExecuted;
6
use Illuminate\Support\Facades\Cache;
7
use Socialblue\LaravelQueryAdviser\Helper\QueryBuilderHelper;
8
9
class QueryListener {
10
11
    public static function listen(QueryExecuted $query) {
12
        if (config('laravel-query-adviser.enable_query_logging') === false) {
13
            return;
14
        }
15
16
        $url = url()->current();
17
        if (strpos($url, '/query-adviser') !== false) {
18
            return;
19
        }
20
        $time = time();
21
        $referer = request()->headers->get('referer');
22
23
        $data = self::getFromCache($time);
24
25
        $possibleTraces = self::formatPossibleTraces(self::getPossibleTraces());
26
27
        self::putToCache(
28
            self::formatData($query, $data, $time, $possibleTraces, $url, $referer)
29
        );
30
    }
31
32
    /**
33
     * @return array
34
     */
35
    protected static function getPossibleTraces(): array
36
    {
37
        $possibleTraces = array_filter(debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT, 25),
38
            static function ($trace) {
39
                return isset($trace['file']) &&
40
                    strpos($trace['file'], '/var/www/app/') !== false &&
41
                    isset($trace['object']);
42
43
            }
44
        );
45
        return $possibleTraces;
46
    }
47
48
    /**
49
     * @param possibleTraces
50
     * @return mixed
51
     */
52
    protected static function formatPossibleTraces($possibleTraces)
53
    {
54
        array_walk($possibleTraces, static function (&$trace) {
55
            if (method_exists($trace['object'], 'getModel')) {
56
                $a = $trace['object']->getModel();
57
                if (is_string($a)) {
58
                    $trace['model'] = $a;
59
                } else {
60
                    $trace['model'] = get_class($a);
61
                }
62
            }
63
            unset($trace['object']);
64
            unset($trace['args']);
65
        });
66
        return $possibleTraces;
67
    }
68
69
    /**
70
     * @param QueryExecuted $query
71
     * @param array $data
72
     * @param int $time
73
     * @param $possibleTraces
74
     * @param string $url
75
     * @param string|null $referer
76
     * @return array
77
     */
78
    protected static function formatData(QueryExecuted $query, array $data, int $time, $possibleTraces, string $url, ?string $referer): array
79
    {
80
        if (empty($url)) {
81
            $url = '';
82
        }
83
84
        $key = count($data[$time]);
85
86
        $data[$time][$key] = [
87
            'time'      => $time,
88
            'timeKey'   => $key,
89
            'backtrace' => $possibleTraces,
90
            'sql'       => QueryBuilderHelper::combineQueryAndBindings($query->sql, $query->bindings),
91
            'rawSql'    => $query->sql,
92
            'bindings'  => $query->bindings,
93
            'queryTime' => $query->time,
94
            'url'       => $url,
95
            'referer'   => $referer,
96
        ];
97
        return $data;
98
    }
99
100
    /**
101
     * @param array $data
102
     * @return array
103
     */
104
    protected static function putToCache(array $data): array
105
    {
106
        if (count($data) > config('laravel-query-adviser.cache.max_entries')) {
107
            array_shift($data);
108
        }
109
110
        Cache::put(config('laravel-query-adviser.cache.key'), $data, config('laravel-query-adviser.cache.ttl'));
111
        return $data;
112
    }
113
114
    /**
115
     * @param int $time
116
     * @return array|mixed
117
     */
118
    protected static function getFromCache(int $time)
119
    {
120
        $data = Cache::get(config('laravel-query-adviser.cache.key'), []);
121
        if (!is_array($data)) {
122
            $data = [];
123
        }
124
125
        if (!isset($data[$time])) {
126
            $data[$time] = [];
127
        }
128
        return $data;
129
    }
130
}
131