Completed
Push — master ( 969424...1c0e8d )
by Agel_Nash
03:49
created

DebugTrait::getLastErrorNo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php namespace AgelxNash\Modx\Evo\Database\Traits;
2
3
use AgelxNash\Modx\Evo\Database\Exceptions;
4
5
trait DebugTrait
6
{
7
    /**
8
     * @var bool
9
     */
10
    protected $debug = false;
11
12
    /**
13
     * @var array
14
     */
15
    protected $queryCollection = [];
16
17
    /**
18
     * @var int
19
     */
20
    protected $queriesTime = 0;
21
22
    /**
23
     * @var string
24
     */
25
    protected $lastQuery = '';
26
27
    /**
28
     * @var int
29
     */
30
    protected $connectionTime = 0;
31
32
    /**
33
     * @var array
34
     */
35
    protected $ignoreErrors = [
36
        '42S22', // SQLSTATE: 42S22 (ER_BAD_FIELD_ERROR) Unknown column '%s' in '%s'
37
        '42S21', // SQLSTATE: 42S21 (ER_DUP_FIELDNAME) Duplicate column name '%s'
38
        '42000', // SQLSTATE: 42000 (ER_DUP_KEYNAME) Duplicate key name '%s'
39
        '23000', // SQLSTATE: 23000 (ER_DUP_ENTRY) Duplicate entry '%s' for key %d
40
        '42000' // SQLSTATE: 42000 (ER_CANT_DROP_FIELD_OR_KEY) Can't DROP '%s'; check that column/key exists
41
    ];
42
43
    /**
44
     * @var string
45
     */
46
    protected $timeFormat = '%2.5f';
47
48
    /**
49
     * {@inheritDoc}
50
     */
51
    abstract public function getDriver();
52
53
    /**
54
     * {@inheritDoc}
55
     */
56
    abstract public function getRecordCount($result);
57
58
    /**
59
     * {@inheritDoc}
60
     */
61
    abstract public function getAffectedRows();
62
63
    /**
64
     * {@inheritDoc}
65
     */
66 51
    public function isDebug()
67
    {
68 51
        return $this->debug;
69
    }
70
71
    /**
72
     * {@inheritDoc}
73
     */
74 51
    public function setDebug($flag)
75
    {
76 51
        $this->debug = $flag;
77
78 51
        return $this;
79
    }
80
81
    /**
82
     * {@inheritDoc}
83
     */
84 4
    public function checkLastError($query = null)
85
    {
86 4
        if ($this->getDriver()->isConnected() === false || $this->getLastErrorNo() === '') {
0 ignored issues
show
Bug introduced by
It seems like getLastErrorNo() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

86
        if ($this->getDriver()->isConnected() === false || $this->/** @scrutinizer ignore-call */ getLastErrorNo() === '') {
Loading history...
87 2
            return false;
88
        }
89
90 4
        if (\in_array($this->getLastErrorNo(), $this->getIgnoreErrors(), true)) {
91 2
            return true;
92
        }
93
94 2
        throw (new Exceptions\QueryException($this->getLastError()))
0 ignored issues
show
Bug introduced by
The method getLastError() does not exist on AgelxNash\Modx\Evo\Database\Traits\DebugTrait. Did you maybe mean getLastQuery()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

94
        throw (new Exceptions\QueryException($this->/** @scrutinizer ignore-call */ getLastError()))

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
95 2
            ->setQuery($query);
96
    }
97
98
    /**
99
     * {@inheritDoc}
100
     */
101 35
    public function collectQuery($result, $sql, $time)
102
    {
103 35
        $debug = debug_backtrace();
104 35
        array_shift($debug);
105 35
        array_shift($debug);
106 35
        $path = [];
107 35
        foreach ($debug as $line) {
108 35
            $path[] = ($line['class'] ? ($line['class'] . '::') : null) . $line['function'];
109
            /*$path[] = [
110
                'method' => ($line['class'] ? ($line['class'] . '::') : null) . $line['function'],
111
                'file' => ($line['file'] ? ($line['file'] . ':') : null) . ($line['line'] ?? 0)
112
            ];*/
113
        }
114 35
        $path = implode(' > ', array_reverse($path));
115
116
        $data = [
117 35
            'sql' => $sql,
118 35
            'time' => $time,
119 35
            'rows' => (stripos($sql, 'SELECT') === 0 && $this->getDriver()->isResult($result)) ?
120 35
                $this->getRecordCount($result) : $this->getAffectedRows(),
121 35
            'path' => $path,
122
            //'event' => $modx->event->name,
123
            //'element' => [
124
            //      'name' => $modx->event->activePlugin ?? ($modx->currentSnippet ?? null),
125
            //      'type' => $modx->event->activePlugin ? 'Plugin' : ($modx->currentSnippet ? 'Snippet' : 'Source code')
126
            // ]
127
        ];
128
129 35
        $this->queryCollection[] = $data;
130
131 35
        return $data;
132
    }
133
134
    /**
135
     * {@inheritDoc}
136
     */
137 39
    public function setLastQuery($query)
138
    {
139 39
        $this->lastQuery = (string)$query;
140
141 39
        return $query;
142
    }
143
144
    /**
145
     * {@inheritDoc}
146
     */
147 38
    public function getLastQuery()
148
    {
149 38
        return (string)$this->lastQuery;
150
    }
151
152
    /**
153
     * {@inheritDoc}
154
     */
155 15
    public function getAllExecutedQuery()
156
    {
157 15
        return $this->queryCollection;
158
    }
159
160
    /**
161
     * {@inheritDoc}
162
     */
163 14
    public function flushExecutedQuery()
164
    {
165 14
        $this->queryCollection = [];
166 14
        $this->queriesTime = 0;
167 14
        $this->lastQuery = $this->setLastQuery('');
168
169 14
        return true;
170
    }
171
172
    /**
173
     * {@inheritDoc}
174
     */
175 50
    public function setConnectionTime($value)
176
    {
177 50
        $this->connectionTime = $value;
178
179 50
        return $value;
180
    }
181
182
    /**
183
     * {@inheritDoc}
184
     */
185 3
    public function getConnectionTime($format = false)
186
    {
187 3
        return $format ? sprintf($this->timeFormat, $this->connectionTime) : $this->connectionTime;
188
    }
189
190
    /**
191
     * {@inheritDoc}
192
     */
193 2
    public function getQueriesTime()
194
    {
195 2
        return $this->queriesTime;
196
    }
197
198
    /**
199
     * {@inheritDoc}
200
     */
201 35
    public function addQueriesTime($time)
202
    {
203 35
        $this->queriesTime += $time;
204
205 35
        return $time;
206
    }
207
208
    /**
209
     * @return string
210
     */
211 1
    public function renderConnectionTime()
212
    {
213
        return '<fieldset style="text-align:left">' .
214
            '<legend>Database connection</legend>' .
215 1
            'Database connection was created in ' . $this->getConnectionTime(true) . ' s.' .
216 1
            '</fieldset>' .
217 1
            '<br />';
218
    }
219
220
    /**
221
     * @return array
222
     */
223 5
    public function getIgnoreErrors()
224
    {
225 5
        return $this->ignoreErrors;
226
    }
227
228
    /**
229
     * @param string $error
230
     * @return string
231
     */
232 3
    public function addIgnoreErrors($error)
233
    {
234 3
        $this->ignoreErrors[] = $error;
235
236 3
        return $error;
237
    }
238
239
    /**
240
     * @return bool
241
     */
242 3
    public function flushIgnoreErrors()
243
    {
244 3
        $this->ignoreErrors = [];
245
246 3
        return true;
247
    }
248
249
    /**
250
     * @param array $errors
251
     * @return array
252
     */
253 3
    public function setIgnoreErrors(array $errors)
254
    {
255 3
        $this->flushIgnoreErrors();
256
257 3
        foreach ($errors as $error) {
258 3
            $this->addIgnoreErrors($error);
259
        }
260
261 3
        return $this->getIgnoreErrors();
262
    }
263
264
    /**
265
     * @return string
266
     */
267 3
    public function renderExecutedQuery()
268
    {
269 3
        $out = '';
270
271 3
        foreach ($this->getAllExecutedQuery() as $i => $query) {
272 2
            $out .= '<fieldset style="text-align:left">';
273 2
            $out .= '<legend>Query ' . $i . ' - ' . sprintf($this->timeFormat, $query['time']) . '</legend>';
274 2
            $out .= $query['sql'] . '<br><br>';
275 2
            if (! empty($query['element'])) {
276
                $out .= $query['element']['type'] . '  => ' . $query['element']['name'] . '<br>';
277
            }
278 2
            if (! empty($query['event'])) {
279
                $out .= 'Current Event  => ' . $query['event'] . '<br>';
280
            }
281 2
            $out .= 'Affected Rows => ' . $query['rows'] . '<br>';
282 2
            if (! empty($query['path'])) {
283 2
                $out .= 'Functions Path => ' . $query['path'] . '<br>';
284
            }
285
            /*$out .= 'Functions Path => ' . $query['path']['method'] . '<br>';
286
            $out .= empty($query['path']['file']) ?: $query['path']['file'] . '<br />';*/
287 2
            $out .= '</fieldset><br />';
288
        }
289
290 3
        return $out;
291
    }
292
}
293