Passed
Branch master (8bcaf5)
by Glynn
07:33
created
src/QueryBuilder/Raw.php 1 patch
Indentation   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -5,41 +5,41 @@
 block discarded – undo
5 5
 class Raw
6 6
 {
7 7
 
8
-    /**
9
-     * @var string
10
-     */
11
-    protected $value;
8
+	/**
9
+	 * @var string
10
+	 */
11
+	protected $value;
12 12
 
13
-    /**
14
-     * @var mixed[]
15
-     */
16
-    protected $bindings;
13
+	/**
14
+	 * @var mixed[]
15
+	 */
16
+	protected $bindings;
17 17
 
18
-    /**
19
-     * @param string|\Stringable|int|float|bool $value
20
-     * @param mixed|mixed[] $bindings
21
-     */
22
-    public function __construct($value, $bindings = array())
23
-    {
24
-        $this->value = (string)$value;
25
-        $this->bindings = (array)$bindings;
26
-    }
18
+	/**
19
+	 * @param string|\Stringable|int|float|bool $value
20
+	 * @param mixed|mixed[] $bindings
21
+	 */
22
+	public function __construct($value, $bindings = array())
23
+	{
24
+		$this->value = (string)$value;
25
+		$this->bindings = (array)$bindings;
26
+	}
27 27
 
28
-    /**
29
-     * Returns the current bindings
30
-     *
31
-     * @return mixed[]
32
-     */
33
-    public function getBindings(): array
34
-    {
35
-        return $this->bindings;
36
-    }
28
+	/**
29
+	 * Returns the current bindings
30
+	 *
31
+	 * @return mixed[]
32
+	 */
33
+	public function getBindings(): array
34
+	{
35
+		return $this->bindings;
36
+	}
37 37
 
38
-    /**
39
-     * @return string
40
-     */
41
-    public function __toString()
42
-    {
43
-        return (string)$this->value;
44
-    }
38
+	/**
39
+	 * @return string
40
+	 */
41
+	public function __toString()
42
+	{
43
+		return (string)$this->value;
44
+	}
45 45
 }
Please login to merge, or discard this patch.
src/QueryBuilder/JoinBuilder.php 1 patch
Indentation   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -2,43 +2,43 @@
 block discarded – undo
2 2
 
3 3
 class JoinBuilder extends QueryBuilderHandler
4 4
 {
5
-    /**
6
-     * @param $key
7
-     * @param $operator
8
-     * @param $value
9
-     *
10
-     * @return $this
11
-     */
12
-    public function on($key, $operator, $value)
13
-    {
14
-        return $this->joinHandler($key, $operator, $value, 'AND');
15
-    }
5
+	/**
6
+	 * @param $key
7
+	 * @param $operator
8
+	 * @param $value
9
+	 *
10
+	 * @return $this
11
+	 */
12
+	public function on($key, $operator, $value)
13
+	{
14
+		return $this->joinHandler($key, $operator, $value, 'AND');
15
+	}
16 16
 
17
-    /**
18
-     * @param $key
19
-     * @param $operator
20
-     * @param $value
21
-     *
22
-     * @return $this
23
-     */
24
-    public function orOn($key, $operator, $value)
25
-    {
26
-        return $this->joinHandler($key, $operator, $value, 'OR');
27
-    }
17
+	/**
18
+	 * @param $key
19
+	 * @param $operator
20
+	 * @param $value
21
+	 *
22
+	 * @return $this
23
+	 */
24
+	public function orOn($key, $operator, $value)
25
+	{
26
+		return $this->joinHandler($key, $operator, $value, 'OR');
27
+	}
28 28
 
29
-    /**
30
-     * @param        $key
31
-     * @param null   $operator
32
-     * @param null   $value
33
-     * @param string $joiner
34
-     *
35
-     * @return $this
36
-     */
37
-    protected function joinHandler($key, $operator = null, $value = null, $joiner = 'AND')
38
-    {
39
-        $key = $this->addTablePrefix($key);
40
-        $value = $this->addTablePrefix($value);
41
-        $this->statements['criteria'][] = compact('key', 'operator', 'value', 'joiner');
42
-        return $this;
43
-    }
29
+	/**
30
+	 * @param        $key
31
+	 * @param null   $operator
32
+	 * @param null   $value
33
+	 * @param string $joiner
34
+	 *
35
+	 * @return $this
36
+	 */
37
+	protected function joinHandler($key, $operator = null, $value = null, $joiner = 'AND')
38
+	{
39
+		$key = $this->addTablePrefix($key);
40
+		$value = $this->addTablePrefix($value);
41
+		$this->statements['criteria'][] = compact('key', 'operator', 'value', 'joiner');
42
+		return $this;
43
+	}
44 44
 }
Please login to merge, or discard this patch.
src/QueryBuilder/Transaction.php 1 patch
Indentation   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -5,25 +5,25 @@
 block discarded – undo
5 5
 class Transaction extends QueryBuilderHandler
6 6
 {
7 7
 
8
-    /**
9
-     * Commit the database changes
10
-     *
11
-     * @throws TransactionHaltException
12
-     */
13
-    public function commit()
14
-    {
15
-        $this->dbInstance->query('COMMIT');
16
-        throw new TransactionHaltException();
17
-    }
8
+	/**
9
+	 * Commit the database changes
10
+	 *
11
+	 * @throws TransactionHaltException
12
+	 */
13
+	public function commit()
14
+	{
15
+		$this->dbInstance->query('COMMIT');
16
+		throw new TransactionHaltException();
17
+	}
18 18
 
19
-    /**
20
-     * Rollback the database changes
21
-     *
22
-     * @throws TransactionHaltException
23
-     */
24
-    public function rollback()
25
-    {
26
-        $this->dbInstance->query('ROLLBACK');
27
-        throw new TransactionHaltException();
28
-    }
19
+	/**
20
+	 * Rollback the database changes
21
+	 *
22
+	 * @throws TransactionHaltException
23
+	 */
24
+	public function rollback()
25
+	{
26
+		$this->dbInstance->query('ROLLBACK');
27
+		throw new TransactionHaltException();
28
+	}
29 29
 }
Please login to merge, or discard this patch.
src/QueryBuilder/WPDBAdapter.php 1 patch
Indentation   +555 added lines, -555 removed lines patch added patch discarded remove patch
@@ -9,559 +9,559 @@
 block discarded – undo
9 9
 
10 10
 class WPDBAdapter
11 11
 {
12
-    /**
13
-     * @var string
14
-     */
15
-    protected $sanitizer = '';
16
-
17
-    /**
18
-     * @var \Pixie\Connection
19
-     */
20
-    protected $connection;
21
-
22
-    /**
23
-     * @var \Viocon\Container
24
-     */
25
-    protected $container;
26
-
27
-    public function __construct(Connection $connection)
28
-    {
29
-        $this->connection = $connection;
30
-        $this->container = $this->connection->getContainer();
31
-    }
32
-
33
-    /**
34
-     * Build select query string and bindings
35
-     *
36
-     * @param $statements
37
-     *
38
-     * @throws Exception
39
-     * @return array
40
-     */
41
-    public function select($statements)
42
-    {
43
-        if (!array_key_exists('tables', $statements)) {
44
-            throw new Exception('No table specified.', 3);
45
-        } elseif (!array_key_exists('selects', $statements)) {
46
-            $statements['selects'][] = '*';
47
-        }
48
-
49
-        // From
50
-        $tables = $this->arrayStr($statements['tables'], ', ');
51
-        // Select
52
-        $selects = $this->arrayStr($statements['selects'], ', ');
53
-
54
-
55
-        // Wheres
56
-        list($whereCriteria, $whereBindings) = $this->buildCriteriaWithType($statements, 'wheres', 'WHERE');
57
-        // Group bys
58
-        $groupBys = '';
59
-        if (isset($statements['groupBys']) && $groupBys = $this->arrayStr($statements['groupBys'], ', ')) {
60
-            $groupBys = 'GROUP BY ' . $groupBys;
61
-        }
62
-
63
-        // Order bys
64
-        $orderBys = '';
65
-        if (isset($statements['orderBys']) && is_array($statements['orderBys'])) {
66
-            foreach ($statements['orderBys'] as $orderBy) {
67
-                $orderBys .= $this->wrapSanitizer($orderBy['field']) . ' ' . $orderBy['type'] . ', ';
68
-            }
69
-
70
-            if ($orderBys = trim($orderBys, ', ')) {
71
-                $orderBys = 'ORDER BY ' . $orderBys;
72
-            }
73
-        }
74
-
75
-        // Limit and offset
76
-        $limit = isset($statements['limit']) ? 'LIMIT ' . (int) $statements['limit'] : '';
77
-        $offset = isset($statements['offset']) ? 'OFFSET ' . (int) $statements['offset'] : '';
78
-
79
-        // Having
80
-        list($havingCriteria, $havingBindings) = $this->buildCriteriaWithType($statements, 'havings', 'HAVING');
81
-
82
-        // Joins
83
-        $joinString = $this->buildJoin($statements);
84
-
85
-        $sqlArray = array(
86
-            'SELECT' . (isset($statements['distinct']) ? ' DISTINCT' : ''),
87
-            $selects,
88
-            'FROM',
89
-            $tables,
90
-            $joinString,
91
-            $whereCriteria,
92
-            $groupBys,
93
-            $havingCriteria,
94
-            $orderBys,
95
-            $limit,
96
-            $offset
97
-        );
98
-
99
-        $sql = $this->concatenateQuery($sqlArray);
100
-
101
-        $bindings = array_merge(
102
-            $whereBindings,
103
-            $havingBindings
104
-        );
105
-
106
-        return compact('sql', 'bindings');
107
-    }
108
-
109
-    /**
110
-     * Build just criteria part of the query
111
-     *
112
-     * @param      $statements
113
-     * @param bool $bindValues
114
-     *
115
-     * @return array
116
-     */
117
-    public function criteriaOnly($statements, $bindValues = true)
118
-    {
119
-        $sql = $bindings = array();
120
-        if (!isset($statements['criteria'])) {
121
-            return compact('sql', 'bindings');
122
-        }
123
-
124
-        list($sql, $bindings) = $this->buildCriteria($statements['criteria'], $bindValues);
125
-
126
-        return compact('sql', 'bindings');
127
-    }
128
-
129
-    /**
130
-     * Build a generic insert/ignore/replace query
131
-     *
132
-     * @param       $statements
133
-     * @param array $data
134
-     *
135
-     * @return array
136
-     * @throws Exception
137
-     */
138
-    private function doInsert($statements, array $data, $type)
139
-    {
140
-        if (!isset($statements['tables'])) {
141
-            throw new Exception('No table specified', 3);
142
-        }
143
-
144
-        $table = end($statements['tables']);
145
-
146
-        $bindings = $keys = $values = array();
147
-
148
-        foreach ($data as $key => $value) {
149
-            $keys[] = $key;
150
-            if ($value instanceof Raw) {
151
-                $values[] = (string) $value;
152
-            } else {
153
-                $values[] =  $this->inferType($value);
154
-                $bindings[] = $value;
155
-            }
156
-        }
157
-
158
-        $sqlArray = array(
159
-            $type . ' INTO',
160
-            $this->wrapSanitizer($table),
161
-            '(' . $this->arrayStr($keys, ',') . ')',
162
-            'VALUES',
163
-            '(' . $this->arrayStr($values, ',', false) . ')',
164
-        );
165
-
166
-        if (isset($statements['onduplicate'])) {
167
-            if (count($statements['onduplicate']) < 1) {
168
-                throw new Exception('No data given.', 4);
169
-            }
170
-            list($updateStatement, $updateBindings) = $this->getUpdateStatement($statements['onduplicate']);
171
-            $sqlArray[] = 'ON DUPLICATE KEY UPDATE ' . $updateStatement;
172
-            $bindings = array_merge($bindings, $updateBindings);
173
-        }
174
-
175
-        $sql = $this->concatenateQuery($sqlArray);
176
-
177
-        return compact('sql', 'bindings');
178
-    }
179
-
180
-    /**
181
-     * Build Insert query
182
-     *
183
-     * @param       $statements
184
-     * @param array $data
185
-     *
186
-     * @return array
187
-     * @throws Exception
188
-     */
189
-    public function insert($statements, array $data)
190
-    {
191
-        return $this->doInsert($statements, $data, 'INSERT');
192
-    }
193
-
194
-    /**
195
-     * Build Insert Ignore query
196
-     *
197
-     * @param       $statements
198
-     * @param array $data
199
-     *
200
-     * @return array
201
-     * @throws Exception
202
-     */
203
-    public function insertIgnore($statements, array $data)
204
-    {
205
-        return $this->doInsert($statements, $data, 'INSERT IGNORE');
206
-    }
207
-
208
-    /**
209
-     * Build Insert Ignore query
210
-     *
211
-     * @param       $statements
212
-     * @param array $data
213
-     *
214
-     * @return array
215
-     * @throws Exception
216
-     */
217
-    public function replace($statements, array $data)
218
-    {
219
-        return $this->doInsert($statements, $data, 'REPLACE');
220
-    }
221
-
222
-    /**
223
-     * Build fields assignment part of SET ... or ON DUBLICATE KEY UPDATE ... statements
224
-     *
225
-     * @param array $data
226
-     *
227
-     * @return array
228
-     */
229
-    private function getUpdateStatement($data)
230
-    {
231
-        $bindings = array();
232
-        $statement = '';
233
-
234
-        foreach ($data as $key => $value) {
235
-            if ($value instanceof Raw) {
236
-                $statement .= $this->wrapSanitizer($key) . '=' . $value . ',';
237
-            } else {
238
-                $statement .= $this->wrapSanitizer($key) . sprintf('=%s,', $this->inferType($value));
239
-                $bindings[] = $value;
240
-            }
241
-        }
242
-
243
-        $statement = trim($statement, ',');
244
-        return array($statement, $bindings);
245
-    }
246
-
247
-    /**
248
-     * Build update query
249
-     *
250
-     * @param       $statements
251
-     * @param array $data
252
-     *
253
-     * @return array
254
-     * @throws Exception
255
-     */
256
-    public function update($statements, array $data)
257
-    {
258
-        if (!isset($statements['tables'])) {
259
-            throw new Exception('No table specified', 3);
260
-        } elseif (count($data) < 1) {
261
-            throw new Exception('No data given.', 4);
262
-        }
263
-
264
-        $table = end($statements['tables']);
265
-
266
-        // Update statement
267
-        list($updateStatement, $bindings) = $this->getUpdateStatement($data);
268
-
269
-        // Wheres
270
-        list($whereCriteria, $whereBindings) = $this->buildCriteriaWithType($statements, 'wheres', 'WHERE');
271
-
272
-        // Limit
273
-        $limit = isset($statements['limit']) ? 'LIMIT ' . $statements['limit'] : '';
274
-
275
-        $sqlArray = array(
276
-            'UPDATE',
277
-            $this->wrapSanitizer($table),
278
-            'SET ' . $updateStatement,
279
-            $whereCriteria,
280
-            $limit
281
-        );
282
-
283
-        $sql = $this->concatenateQuery($sqlArray);
284
-
285
-        $bindings = array_merge($bindings, $whereBindings);
286
-        return compact('sql', 'bindings');
287
-    }
288
-
289
-    /**
290
-     * Build delete query
291
-     *
292
-     * @param $statements
293
-     *
294
-     * @return array
295
-     * @throws Exception
296
-     */
297
-    public function delete($statements)
298
-    {
299
-        if (!isset($statements['tables'])) {
300
-            throw new Exception('No table specified', 3);
301
-        }
302
-
303
-        $table = end($statements['tables']);
304
-
305
-        // Wheres
306
-        list($whereCriteria, $whereBindings) = $this->buildCriteriaWithType($statements, 'wheres', 'WHERE');
307
-
308
-        // Limit
309
-        $limit = isset($statements['limit']) ? 'LIMIT ' . $statements['limit'] : '';
310
-
311
-        $sqlArray = array('DELETE FROM', $this->wrapSanitizer($table), $whereCriteria);
312
-        $sql = $this->concatenateQuery($sqlArray);
313
-        $bindings = $whereBindings;
314
-
315
-        return compact('sql', 'bindings');
316
-    }
317
-
318
-    /**
319
-     * Array concatenating method, like implode.
320
-     * But it does wrap sanitizer and trims last glue
321
-     *
322
-     * @param array $pieces
323
-     * @param       $glue
324
-     * @param bool  $wrapSanitizer
325
-     *
326
-     * @return string
327
-     */
328
-    protected function arrayStr(array $pieces, $glue, $wrapSanitizer = true)
329
-    {
330
-        $str = '';
331
-        foreach ($pieces as $key => $piece) {
332
-            if ($wrapSanitizer) {
333
-                $piece = $this->wrapSanitizer($piece);
334
-            }
335
-
336
-            if (!is_int($key)) {
337
-                $piece = ($wrapSanitizer ? $this->wrapSanitizer($key) : $key) . ' AS ' . $piece;
338
-            }
339
-
340
-            $str .= $piece . $glue;
341
-        }
342
-
343
-        return trim($str, $glue);
344
-    }
345
-
346
-    /**
347
-     * Join different part of queries with a space.
348
-     *
349
-     * @param array $pieces
350
-     *
351
-     * @return string
352
-     */
353
-    protected function concatenateQuery(array $pieces)
354
-    {
355
-        $str = '';
356
-        foreach ($pieces as $piece) {
357
-            $str = trim($str) . ' ' . trim($piece);
358
-        }
359
-        return trim($str);
360
-    }
361
-
362
-    /**
363
-     * Build generic criteria string and bindings from statements, like "a = b and c = ?"
364
-     *
365
-     * @param      $statements
366
-     * @param bool $bindValues
367
-     *
368
-     * @return array
369
-     */
370
-    protected function buildCriteria($statements, $bindValues = true)
371
-    {
372
-        $criteria = '';
373
-        $bindings = array();
374
-        foreach ($statements as $statement) {
375
-            $key = $this->wrapSanitizer($statement['key']);
376
-            $value = $statement['value'];
377
-
378
-            if (is_null($value) && $key instanceof \Closure) {
379
-                // We have a closure, a nested criteria
380
-
381
-                // Build a new NestedCriteria class, keep it by reference so any changes made
382
-                // in the closure should reflect here
383
-                $nestedCriteria = $this->container->build(NestedCriteria::class, array($this->connection));
384
-
385
-                $nestedCriteria = & $nestedCriteria;
386
-                // Call the closure with our new nestedCriteria object
387
-                $key($nestedCriteria);
388
-                // Get the criteria only query from the nestedCriteria object
389
-                $queryObject = $nestedCriteria->getQuery('criteriaOnly', true);
390
-                // Merge the bindings we get from nestedCriteria object
391
-                $bindings = array_merge($bindings, $queryObject->getBindings());
392
-                // Append the sql we get from the nestedCriteria object
393
-                $criteria .= $statement['joiner'] . ' (' . $queryObject->getSql() . ') ';
394
-            } elseif (is_array($value)) {
395
-                // where_in or between like query
396
-                $criteria .= $statement['joiner'] . ' ' . $key . ' ' . $statement['operator'];
397
-
398
-                switch ($statement['operator']) {
399
-                    case 'BETWEEN':
400
-                        $bindings = array_merge($bindings, $statement['value']);
401
-                        $criteria .= sprintf(
402
-                            ' %s AND %s ',
403
-                            $this->inferType($statement['value'][0]),
404
-                            $this->inferType($statement['value'][1])
405
-                        );
406
-                        break;
407
-                    default:
408
-                        $valuePlaceholder = '';
409
-                        foreach ($statement['value'] as $subValue) {
410
-                            // Add in format placeholders.
411
-                            $valuePlaceholder .= sprintf('%s, ', $this->inferType($subValue)); // glynn
412
-                            $bindings[] = $subValue;
413
-                        }
414
-
415
-                        $valuePlaceholder = trim($valuePlaceholder, ', ');
416
-                        $criteria .= ' (' . $valuePlaceholder . ') ';
417
-                        break;
418
-                }
419
-            } elseif ($value instanceof Raw) {
420
-                $criteria .= "{$statement['joiner']} {$key} {$statement['operator']} $value ";
421
-            } else {
422
-                // Usual where like criteria
423
-
424
-                if (!$bindValues) {
425
-                    // Specially for joins
426
-
427
-                    // We are not binding values, lets sanitize then
428
-                    $value = $this->wrapSanitizer($value);
429
-                    $criteria .= $statement['joiner'] . ' ' . $key . ' ' . $statement['operator'] . ' ' . $value . ' ';
430
-                } elseif ($statement['key'] instanceof Raw) {
431
-                    $criteria .= $statement['joiner'] . ' ' . $key . ' ';
432
-                    $bindings = array_merge($bindings, $statement['key']->getBindings());
433
-                } else {
434
-                    // For wheres
435
-                    $valuePlaceholder = $this->inferType($value);
436
-                    $bindings[] = $value;
437
-                    $criteria .= $statement['joiner'] . ' ' . $key . ' ' . $statement['operator'] . ' '
438
-                        . $valuePlaceholder . ' ';
439
-                }
440
-            }
441
-        }
442
-
443
-        // Clear all white spaces, and, or from beginning and white spaces from ending
444
-        $criteria = preg_replace('/^(\s?AND ?|\s?OR ?)|\s$/i', '', $criteria);
445
-
446
-        return array($criteria, $bindings);
447
-    }
448
-
449
-    /**
450
-     * Asserts the types place holder based on its value
451
-     *
452
-     * @param mixed $value
453
-     * @return string
454
-     */
455
-    public function inferType($value): string
456
-    {
457
-        switch (true) {
458
-            case is_string($value):
459
-                return '%s';
460
-            case \is_int($value):
461
-            case \is_bool($value):
462
-                return '%d';
463
-            case \is_float($value):
464
-                return '%f';
465
-            default:
466
-                return '';
467
-        }
468
-    }
469
-
470
-    /**
471
-     * Wrap values with adapter's sanitizer like, '`'
472
-     *
473
-     * @param $value
474
-     *
475
-     * @return string
476
-     */
477
-    public function wrapSanitizer($value)
478
-    {
479
-        // Its a raw query, just cast as string, object has __toString()
480
-        if ($value instanceof Raw) {
481
-            return (string)$value;
482
-        } elseif ($value instanceof \Closure) {
483
-            return $value;
484
-        }
485
-
486
-        // Separate our table and fields which are joined with a ".",
487
-        // like my_table.id
488
-        $valueArr = explode('.', $value, 2);
489
-
490
-        foreach ($valueArr as $key => $subValue) {
491
-            // Don't wrap if we have *, which is not a usual field
492
-            $valueArr[$key] = trim($subValue) == '*' ? $subValue : $this->sanitizer . $subValue . $this->sanitizer;
493
-        }
494
-
495
-        // Join these back with "." and return
496
-        return implode('.', $valueArr);
497
-    }
498
-
499
-    /**
500
-     * Build criteria string and binding with various types added, like WHERE and Having
501
-     *
502
-     * @param      $statements
503
-     * @param      $key
504
-     * @param      $type
505
-     * @param bool $bindValues
506
-     *
507
-     * @return array
508
-     */
509
-    protected function buildCriteriaWithType($statements, $key, $type, $bindValues = true)
510
-    {
511
-        $criteria = '';
512
-        $bindings = array();
513
-
514
-        if (isset($statements[$key])) {
515
-            // Get the generic/adapter agnostic criteria string from parent
516
-            list($criteria, $bindings) = $this->buildCriteria($statements[$key], $bindValues);
517
-
518
-            if ($criteria) {
519
-                $criteria = $type . ' ' . $criteria;
520
-            }
521
-        }
522
-
523
-        return array($criteria, $bindings);
524
-    }
525
-
526
-    /**
527
-     * Build join string
528
-     *
529
-     * @param $statements
530
-     *
531
-     * @return array
532
-     */
533
-    protected function buildJoin($statements)
534
-    {
535
-        $sql = '';
536
-
537
-        if (!array_key_exists('joins', $statements) || !is_array($statements['joins'])) {
538
-            return $sql;
539
-        }
540
-
541
-        foreach ($statements['joins'] as $joinArr) {
542
-            if (is_array($joinArr['table'])) {
543
-                $mainTable = $joinArr['table'][0];
544
-                $aliasTable = $joinArr['table'][1];
545
-                $table = $this->wrapSanitizer($mainTable) . ' AS ' . $this->wrapSanitizer($aliasTable);
546
-            } else {
547
-                $table = $joinArr['table'] instanceof Raw ?
548
-                    (string) $joinArr['table'] :
549
-                    $this->wrapSanitizer($joinArr['table']);
550
-            }
551
-            $joinBuilder = $joinArr['joinBuilder'];
552
-
553
-            $sqlArr = array(
554
-                $sql,
555
-                strtoupper($joinArr['type']),
556
-                'JOIN',
557
-                $table,
558
-                'ON',
559
-                $joinBuilder->getQuery('criteriaOnly', false)->getSql()
560
-            );
561
-
562
-            $sql = $this->concatenateQuery($sqlArr);
563
-        }
564
-
565
-        return $sql;
566
-    }
12
+	/**
13
+	 * @var string
14
+	 */
15
+	protected $sanitizer = '';
16
+
17
+	/**
18
+	 * @var \Pixie\Connection
19
+	 */
20
+	protected $connection;
21
+
22
+	/**
23
+	 * @var \Viocon\Container
24
+	 */
25
+	protected $container;
26
+
27
+	public function __construct(Connection $connection)
28
+	{
29
+		$this->connection = $connection;
30
+		$this->container = $this->connection->getContainer();
31
+	}
32
+
33
+	/**
34
+	 * Build select query string and bindings
35
+	 *
36
+	 * @param $statements
37
+	 *
38
+	 * @throws Exception
39
+	 * @return array
40
+	 */
41
+	public function select($statements)
42
+	{
43
+		if (!array_key_exists('tables', $statements)) {
44
+			throw new Exception('No table specified.', 3);
45
+		} elseif (!array_key_exists('selects', $statements)) {
46
+			$statements['selects'][] = '*';
47
+		}
48
+
49
+		// From
50
+		$tables = $this->arrayStr($statements['tables'], ', ');
51
+		// Select
52
+		$selects = $this->arrayStr($statements['selects'], ', ');
53
+
54
+
55
+		// Wheres
56
+		list($whereCriteria, $whereBindings) = $this->buildCriteriaWithType($statements, 'wheres', 'WHERE');
57
+		// Group bys
58
+		$groupBys = '';
59
+		if (isset($statements['groupBys']) && $groupBys = $this->arrayStr($statements['groupBys'], ', ')) {
60
+			$groupBys = 'GROUP BY ' . $groupBys;
61
+		}
62
+
63
+		// Order bys
64
+		$orderBys = '';
65
+		if (isset($statements['orderBys']) && is_array($statements['orderBys'])) {
66
+			foreach ($statements['orderBys'] as $orderBy) {
67
+				$orderBys .= $this->wrapSanitizer($orderBy['field']) . ' ' . $orderBy['type'] . ', ';
68
+			}
69
+
70
+			if ($orderBys = trim($orderBys, ', ')) {
71
+				$orderBys = 'ORDER BY ' . $orderBys;
72
+			}
73
+		}
74
+
75
+		// Limit and offset
76
+		$limit = isset($statements['limit']) ? 'LIMIT ' . (int) $statements['limit'] : '';
77
+		$offset = isset($statements['offset']) ? 'OFFSET ' . (int) $statements['offset'] : '';
78
+
79
+		// Having
80
+		list($havingCriteria, $havingBindings) = $this->buildCriteriaWithType($statements, 'havings', 'HAVING');
81
+
82
+		// Joins
83
+		$joinString = $this->buildJoin($statements);
84
+
85
+		$sqlArray = array(
86
+			'SELECT' . (isset($statements['distinct']) ? ' DISTINCT' : ''),
87
+			$selects,
88
+			'FROM',
89
+			$tables,
90
+			$joinString,
91
+			$whereCriteria,
92
+			$groupBys,
93
+			$havingCriteria,
94
+			$orderBys,
95
+			$limit,
96
+			$offset
97
+		);
98
+
99
+		$sql = $this->concatenateQuery($sqlArray);
100
+
101
+		$bindings = array_merge(
102
+			$whereBindings,
103
+			$havingBindings
104
+		);
105
+
106
+		return compact('sql', 'bindings');
107
+	}
108
+
109
+	/**
110
+	 * Build just criteria part of the query
111
+	 *
112
+	 * @param      $statements
113
+	 * @param bool $bindValues
114
+	 *
115
+	 * @return array
116
+	 */
117
+	public function criteriaOnly($statements, $bindValues = true)
118
+	{
119
+		$sql = $bindings = array();
120
+		if (!isset($statements['criteria'])) {
121
+			return compact('sql', 'bindings');
122
+		}
123
+
124
+		list($sql, $bindings) = $this->buildCriteria($statements['criteria'], $bindValues);
125
+
126
+		return compact('sql', 'bindings');
127
+	}
128
+
129
+	/**
130
+	 * Build a generic insert/ignore/replace query
131
+	 *
132
+	 * @param       $statements
133
+	 * @param array $data
134
+	 *
135
+	 * @return array
136
+	 * @throws Exception
137
+	 */
138
+	private function doInsert($statements, array $data, $type)
139
+	{
140
+		if (!isset($statements['tables'])) {
141
+			throw new Exception('No table specified', 3);
142
+		}
143
+
144
+		$table = end($statements['tables']);
145
+
146
+		$bindings = $keys = $values = array();
147
+
148
+		foreach ($data as $key => $value) {
149
+			$keys[] = $key;
150
+			if ($value instanceof Raw) {
151
+				$values[] = (string) $value;
152
+			} else {
153
+				$values[] =  $this->inferType($value);
154
+				$bindings[] = $value;
155
+			}
156
+		}
157
+
158
+		$sqlArray = array(
159
+			$type . ' INTO',
160
+			$this->wrapSanitizer($table),
161
+			'(' . $this->arrayStr($keys, ',') . ')',
162
+			'VALUES',
163
+			'(' . $this->arrayStr($values, ',', false) . ')',
164
+		);
165
+
166
+		if (isset($statements['onduplicate'])) {
167
+			if (count($statements['onduplicate']) < 1) {
168
+				throw new Exception('No data given.', 4);
169
+			}
170
+			list($updateStatement, $updateBindings) = $this->getUpdateStatement($statements['onduplicate']);
171
+			$sqlArray[] = 'ON DUPLICATE KEY UPDATE ' . $updateStatement;
172
+			$bindings = array_merge($bindings, $updateBindings);
173
+		}
174
+
175
+		$sql = $this->concatenateQuery($sqlArray);
176
+
177
+		return compact('sql', 'bindings');
178
+	}
179
+
180
+	/**
181
+	 * Build Insert query
182
+	 *
183
+	 * @param       $statements
184
+	 * @param array $data
185
+	 *
186
+	 * @return array
187
+	 * @throws Exception
188
+	 */
189
+	public function insert($statements, array $data)
190
+	{
191
+		return $this->doInsert($statements, $data, 'INSERT');
192
+	}
193
+
194
+	/**
195
+	 * Build Insert Ignore query
196
+	 *
197
+	 * @param       $statements
198
+	 * @param array $data
199
+	 *
200
+	 * @return array
201
+	 * @throws Exception
202
+	 */
203
+	public function insertIgnore($statements, array $data)
204
+	{
205
+		return $this->doInsert($statements, $data, 'INSERT IGNORE');
206
+	}
207
+
208
+	/**
209
+	 * Build Insert Ignore query
210
+	 *
211
+	 * @param       $statements
212
+	 * @param array $data
213
+	 *
214
+	 * @return array
215
+	 * @throws Exception
216
+	 */
217
+	public function replace($statements, array $data)
218
+	{
219
+		return $this->doInsert($statements, $data, 'REPLACE');
220
+	}
221
+
222
+	/**
223
+	 * Build fields assignment part of SET ... or ON DUBLICATE KEY UPDATE ... statements
224
+	 *
225
+	 * @param array $data
226
+	 *
227
+	 * @return array
228
+	 */
229
+	private function getUpdateStatement($data)
230
+	{
231
+		$bindings = array();
232
+		$statement = '';
233
+
234
+		foreach ($data as $key => $value) {
235
+			if ($value instanceof Raw) {
236
+				$statement .= $this->wrapSanitizer($key) . '=' . $value . ',';
237
+			} else {
238
+				$statement .= $this->wrapSanitizer($key) . sprintf('=%s,', $this->inferType($value));
239
+				$bindings[] = $value;
240
+			}
241
+		}
242
+
243
+		$statement = trim($statement, ',');
244
+		return array($statement, $bindings);
245
+	}
246
+
247
+	/**
248
+	 * Build update query
249
+	 *
250
+	 * @param       $statements
251
+	 * @param array $data
252
+	 *
253
+	 * @return array
254
+	 * @throws Exception
255
+	 */
256
+	public function update($statements, array $data)
257
+	{
258
+		if (!isset($statements['tables'])) {
259
+			throw new Exception('No table specified', 3);
260
+		} elseif (count($data) < 1) {
261
+			throw new Exception('No data given.', 4);
262
+		}
263
+
264
+		$table = end($statements['tables']);
265
+
266
+		// Update statement
267
+		list($updateStatement, $bindings) = $this->getUpdateStatement($data);
268
+
269
+		// Wheres
270
+		list($whereCriteria, $whereBindings) = $this->buildCriteriaWithType($statements, 'wheres', 'WHERE');
271
+
272
+		// Limit
273
+		$limit = isset($statements['limit']) ? 'LIMIT ' . $statements['limit'] : '';
274
+
275
+		$sqlArray = array(
276
+			'UPDATE',
277
+			$this->wrapSanitizer($table),
278
+			'SET ' . $updateStatement,
279
+			$whereCriteria,
280
+			$limit
281
+		);
282
+
283
+		$sql = $this->concatenateQuery($sqlArray);
284
+
285
+		$bindings = array_merge($bindings, $whereBindings);
286
+		return compact('sql', 'bindings');
287
+	}
288
+
289
+	/**
290
+	 * Build delete query
291
+	 *
292
+	 * @param $statements
293
+	 *
294
+	 * @return array
295
+	 * @throws Exception
296
+	 */
297
+	public function delete($statements)
298
+	{
299
+		if (!isset($statements['tables'])) {
300
+			throw new Exception('No table specified', 3);
301
+		}
302
+
303
+		$table = end($statements['tables']);
304
+
305
+		// Wheres
306
+		list($whereCriteria, $whereBindings) = $this->buildCriteriaWithType($statements, 'wheres', 'WHERE');
307
+
308
+		// Limit
309
+		$limit = isset($statements['limit']) ? 'LIMIT ' . $statements['limit'] : '';
310
+
311
+		$sqlArray = array('DELETE FROM', $this->wrapSanitizer($table), $whereCriteria);
312
+		$sql = $this->concatenateQuery($sqlArray);
313
+		$bindings = $whereBindings;
314
+
315
+		return compact('sql', 'bindings');
316
+	}
317
+
318
+	/**
319
+	 * Array concatenating method, like implode.
320
+	 * But it does wrap sanitizer and trims last glue
321
+	 *
322
+	 * @param array $pieces
323
+	 * @param       $glue
324
+	 * @param bool  $wrapSanitizer
325
+	 *
326
+	 * @return string
327
+	 */
328
+	protected function arrayStr(array $pieces, $glue, $wrapSanitizer = true)
329
+	{
330
+		$str = '';
331
+		foreach ($pieces as $key => $piece) {
332
+			if ($wrapSanitizer) {
333
+				$piece = $this->wrapSanitizer($piece);
334
+			}
335
+
336
+			if (!is_int($key)) {
337
+				$piece = ($wrapSanitizer ? $this->wrapSanitizer($key) : $key) . ' AS ' . $piece;
338
+			}
339
+
340
+			$str .= $piece . $glue;
341
+		}
342
+
343
+		return trim($str, $glue);
344
+	}
345
+
346
+	/**
347
+	 * Join different part of queries with a space.
348
+	 *
349
+	 * @param array $pieces
350
+	 *
351
+	 * @return string
352
+	 */
353
+	protected function concatenateQuery(array $pieces)
354
+	{
355
+		$str = '';
356
+		foreach ($pieces as $piece) {
357
+			$str = trim($str) . ' ' . trim($piece);
358
+		}
359
+		return trim($str);
360
+	}
361
+
362
+	/**
363
+	 * Build generic criteria string and bindings from statements, like "a = b and c = ?"
364
+	 *
365
+	 * @param      $statements
366
+	 * @param bool $bindValues
367
+	 *
368
+	 * @return array
369
+	 */
370
+	protected function buildCriteria($statements, $bindValues = true)
371
+	{
372
+		$criteria = '';
373
+		$bindings = array();
374
+		foreach ($statements as $statement) {
375
+			$key = $this->wrapSanitizer($statement['key']);
376
+			$value = $statement['value'];
377
+
378
+			if (is_null($value) && $key instanceof \Closure) {
379
+				// We have a closure, a nested criteria
380
+
381
+				// Build a new NestedCriteria class, keep it by reference so any changes made
382
+				// in the closure should reflect here
383
+				$nestedCriteria = $this->container->build(NestedCriteria::class, array($this->connection));
384
+
385
+				$nestedCriteria = & $nestedCriteria;
386
+				// Call the closure with our new nestedCriteria object
387
+				$key($nestedCriteria);
388
+				// Get the criteria only query from the nestedCriteria object
389
+				$queryObject = $nestedCriteria->getQuery('criteriaOnly', true);
390
+				// Merge the bindings we get from nestedCriteria object
391
+				$bindings = array_merge($bindings, $queryObject->getBindings());
392
+				// Append the sql we get from the nestedCriteria object
393
+				$criteria .= $statement['joiner'] . ' (' . $queryObject->getSql() . ') ';
394
+			} elseif (is_array($value)) {
395
+				// where_in or between like query
396
+				$criteria .= $statement['joiner'] . ' ' . $key . ' ' . $statement['operator'];
397
+
398
+				switch ($statement['operator']) {
399
+					case 'BETWEEN':
400
+						$bindings = array_merge($bindings, $statement['value']);
401
+						$criteria .= sprintf(
402
+							' %s AND %s ',
403
+							$this->inferType($statement['value'][0]),
404
+							$this->inferType($statement['value'][1])
405
+						);
406
+						break;
407
+					default:
408
+						$valuePlaceholder = '';
409
+						foreach ($statement['value'] as $subValue) {
410
+							// Add in format placeholders.
411
+							$valuePlaceholder .= sprintf('%s, ', $this->inferType($subValue)); // glynn
412
+							$bindings[] = $subValue;
413
+						}
414
+
415
+						$valuePlaceholder = trim($valuePlaceholder, ', ');
416
+						$criteria .= ' (' . $valuePlaceholder . ') ';
417
+						break;
418
+				}
419
+			} elseif ($value instanceof Raw) {
420
+				$criteria .= "{$statement['joiner']} {$key} {$statement['operator']} $value ";
421
+			} else {
422
+				// Usual where like criteria
423
+
424
+				if (!$bindValues) {
425
+					// Specially for joins
426
+
427
+					// We are not binding values, lets sanitize then
428
+					$value = $this->wrapSanitizer($value);
429
+					$criteria .= $statement['joiner'] . ' ' . $key . ' ' . $statement['operator'] . ' ' . $value . ' ';
430
+				} elseif ($statement['key'] instanceof Raw) {
431
+					$criteria .= $statement['joiner'] . ' ' . $key . ' ';
432
+					$bindings = array_merge($bindings, $statement['key']->getBindings());
433
+				} else {
434
+					// For wheres
435
+					$valuePlaceholder = $this->inferType($value);
436
+					$bindings[] = $value;
437
+					$criteria .= $statement['joiner'] . ' ' . $key . ' ' . $statement['operator'] . ' '
438
+						. $valuePlaceholder . ' ';
439
+				}
440
+			}
441
+		}
442
+
443
+		// Clear all white spaces, and, or from beginning and white spaces from ending
444
+		$criteria = preg_replace('/^(\s?AND ?|\s?OR ?)|\s$/i', '', $criteria);
445
+
446
+		return array($criteria, $bindings);
447
+	}
448
+
449
+	/**
450
+	 * Asserts the types place holder based on its value
451
+	 *
452
+	 * @param mixed $value
453
+	 * @return string
454
+	 */
455
+	public function inferType($value): string
456
+	{
457
+		switch (true) {
458
+			case is_string($value):
459
+				return '%s';
460
+			case \is_int($value):
461
+			case \is_bool($value):
462
+				return '%d';
463
+			case \is_float($value):
464
+				return '%f';
465
+			default:
466
+				return '';
467
+		}
468
+	}
469
+
470
+	/**
471
+	 * Wrap values with adapter's sanitizer like, '`'
472
+	 *
473
+	 * @param $value
474
+	 *
475
+	 * @return string
476
+	 */
477
+	public function wrapSanitizer($value)
478
+	{
479
+		// Its a raw query, just cast as string, object has __toString()
480
+		if ($value instanceof Raw) {
481
+			return (string)$value;
482
+		} elseif ($value instanceof \Closure) {
483
+			return $value;
484
+		}
485
+
486
+		// Separate our table and fields which are joined with a ".",
487
+		// like my_table.id
488
+		$valueArr = explode('.', $value, 2);
489
+
490
+		foreach ($valueArr as $key => $subValue) {
491
+			// Don't wrap if we have *, which is not a usual field
492
+			$valueArr[$key] = trim($subValue) == '*' ? $subValue : $this->sanitizer . $subValue . $this->sanitizer;
493
+		}
494
+
495
+		// Join these back with "." and return
496
+		return implode('.', $valueArr);
497
+	}
498
+
499
+	/**
500
+	 * Build criteria string and binding with various types added, like WHERE and Having
501
+	 *
502
+	 * @param      $statements
503
+	 * @param      $key
504
+	 * @param      $type
505
+	 * @param bool $bindValues
506
+	 *
507
+	 * @return array
508
+	 */
509
+	protected function buildCriteriaWithType($statements, $key, $type, $bindValues = true)
510
+	{
511
+		$criteria = '';
512
+		$bindings = array();
513
+
514
+		if (isset($statements[$key])) {
515
+			// Get the generic/adapter agnostic criteria string from parent
516
+			list($criteria, $bindings) = $this->buildCriteria($statements[$key], $bindValues);
517
+
518
+			if ($criteria) {
519
+				$criteria = $type . ' ' . $criteria;
520
+			}
521
+		}
522
+
523
+		return array($criteria, $bindings);
524
+	}
525
+
526
+	/**
527
+	 * Build join string
528
+	 *
529
+	 * @param $statements
530
+	 *
531
+	 * @return array
532
+	 */
533
+	protected function buildJoin($statements)
534
+	{
535
+		$sql = '';
536
+
537
+		if (!array_key_exists('joins', $statements) || !is_array($statements['joins'])) {
538
+			return $sql;
539
+		}
540
+
541
+		foreach ($statements['joins'] as $joinArr) {
542
+			if (is_array($joinArr['table'])) {
543
+				$mainTable = $joinArr['table'][0];
544
+				$aliasTable = $joinArr['table'][1];
545
+				$table = $this->wrapSanitizer($mainTable) . ' AS ' . $this->wrapSanitizer($aliasTable);
546
+			} else {
547
+				$table = $joinArr['table'] instanceof Raw ?
548
+					(string) $joinArr['table'] :
549
+					$this->wrapSanitizer($joinArr['table']);
550
+			}
551
+			$joinBuilder = $joinArr['joinBuilder'];
552
+
553
+			$sqlArr = array(
554
+				$sql,
555
+				strtoupper($joinArr['type']),
556
+				'JOIN',
557
+				$table,
558
+				'ON',
559
+				$joinBuilder->getQuery('criteriaOnly', false)->getSql()
560
+			);
561
+
562
+			$sql = $this->concatenateQuery($sqlArr);
563
+		}
564
+
565
+		return $sql;
566
+	}
567 567
 }
Please login to merge, or discard this patch.
src/QueryBuilder/NestedCriteria.php 1 patch
Indentation   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -2,18 +2,18 @@
 block discarded – undo
2 2
 
3 3
 class NestedCriteria extends QueryBuilderHandler
4 4
 {
5
-    /**
6
-     * @param        $key
7
-     * @param null   $operator
8
-     * @param null   $value
9
-     * @param string $joiner
10
-     *
11
-     * @return $this
12
-     */
13
-    protected function whereHandler($key, $operator = null, $value = null, $joiner = 'AND')
14
-    {
15
-        $key = $this->addTablePrefix($key);
16
-        $this->statements['criteria'][] = compact('key', 'operator', 'value', 'joiner');
17
-        return $this;
18
-    }
5
+	/**
6
+	 * @param        $key
7
+	 * @param null   $operator
8
+	 * @param null   $value
9
+	 * @param string $joiner
10
+	 *
11
+	 * @return $this
12
+	 */
13
+	protected function whereHandler($key, $operator = null, $value = null, $joiner = 'AND')
14
+	{
15
+		$key = $this->addTablePrefix($key);
16
+		$this->statements['criteria'][] = compact('key', 'operator', 'value', 'joiner');
17
+		return $this;
18
+	}
19 19
 }
Please login to merge, or discard this patch.
src/QueryBuilder/QueryObject.php 1 patch
Indentation   +58 added lines, -58 removed lines patch added patch discarded remove patch
@@ -5,69 +5,69 @@
 block discarded – undo
5 5
 class QueryObject
6 6
 {
7 7
 
8
-    /**
9
-     * @var string
10
-     */
11
-    protected $sql;
8
+	/**
9
+	 * @var string
10
+	 */
11
+	protected $sql;
12 12
 
13
-    /**
14
-     * @var mixed[]
15
-     */
16
-    protected $bindings = array();
13
+	/**
14
+	 * @var mixed[]
15
+	 */
16
+	protected $bindings = array();
17 17
 
18
-    /**
19
-     * @var \wpdb
20
-     */
21
-    protected $dbInstance;
18
+	/**
19
+	 * @var \wpdb
20
+	 */
21
+	protected $dbInstance;
22 22
 
23
-    public function __construct($sql, array $bindings, $dbInstance)
24
-    {
25
-        $this->sql = (string)$sql;
26
-        $this->bindings = $bindings;
27
-        $this->dbInstance = $dbInstance;
28
-    }
23
+	public function __construct($sql, array $bindings, $dbInstance)
24
+	{
25
+		$this->sql = (string)$sql;
26
+		$this->bindings = $bindings;
27
+		$this->dbInstance = $dbInstance;
28
+	}
29 29
 
30
-    /**
31
-     * @return string
32
-     */
33
-    public function getSql()
34
-    {
35
-        return $this->sql;
36
-    }
30
+	/**
31
+	 * @return string
32
+	 */
33
+	public function getSql()
34
+	{
35
+		return $this->sql;
36
+	}
37 37
 
38
-    /**
39
-     * @return mixed[]
40
-     */
41
-    public function getBindings()
42
-    {
43
-        return $this->bindings;
44
-    }
38
+	/**
39
+	 * @return mixed[]
40
+	 */
41
+	public function getBindings()
42
+	{
43
+		return $this->bindings;
44
+	}
45 45
 
46
-    /**
47
-     * Get the raw/bound sql
48
-     *
49
-     * @return string
50
-     */
51
-    public function getRawSql()
52
-    {
53
-        return $this->interpolateQuery($this->sql, $this->bindings);
54
-    }
46
+	/**
47
+	 * Get the raw/bound sql
48
+	 *
49
+	 * @return string
50
+	 */
51
+	public function getRawSql()
52
+	{
53
+		return $this->interpolateQuery($this->sql, $this->bindings);
54
+	}
55 55
 
56
-    /**
57
-     * Replaces any parameter placeholders in a query with the value of that
58
-     * parameter. Useful for debugging. Assumes anonymous parameters from
59
-     * $params are are in the same order as specified in $query
60
-     *
61
-     * Reference: http://stackoverflow.com/a/1376838/656489
62
-     *
63
-     * @param string $query  The sql query with parameter placeholders
64
-     * @param array  $params The array of substitution parameters
65
-     *
66
-     * @return string The interpolated query
67
-     */
68
-    protected function interpolateQuery($query, $params)
69
-    {
70
-        // Only call this when we have valid params (avoids wpdb::prepare() incorrectly called error)
71
-        return empty($params) ? $query : $this->dbInstance->prepare($query, $params);
72
-    }
56
+	/**
57
+	 * Replaces any parameter placeholders in a query with the value of that
58
+	 * parameter. Useful for debugging. Assumes anonymous parameters from
59
+	 * $params are are in the same order as specified in $query
60
+	 *
61
+	 * Reference: http://stackoverflow.com/a/1376838/656489
62
+	 *
63
+	 * @param string $query  The sql query with parameter placeholders
64
+	 * @param array  $params The array of substitution parameters
65
+	 *
66
+	 * @return string The interpolated query
67
+	 */
68
+	protected function interpolateQuery($query, $params)
69
+	{
70
+		// Only call this when we have valid params (avoids wpdb::prepare() incorrectly called error)
71
+		return empty($params) ? $query : $this->dbInstance->prepare($query, $params);
72
+	}
73 73
 }
Please login to merge, or discard this patch.
src/QueryBuilder/QueryBuilderHandler.php 1 patch
Indentation   +1194 added lines, -1194 removed lines patch added patch discarded remove patch
@@ -16,1198 +16,1198 @@
 block discarded – undo
16 16
 class QueryBuilderHandler
17 17
 {
18 18
 
19
-    /**
20
-     * @var \Viocon\Container
21
-     */
22
-    protected $container;
23
-
24
-    /**
25
-     * @var Connection
26
-     */
27
-    protected $connection;
28
-
29
-    /**
30
-     * @var array
31
-     */
32
-    protected $statements = array();
33
-
34
-    /**
35
-     * @var \wpdb
36
-     */
37
-    protected $dbInstance;
38
-
39
-    /**
40
-     * @var null|string[]
41
-     */
42
-    protected $sqlStatement = null;
43
-
44
-    /**
45
-     * @var null|string
46
-     */
47
-    protected $tablePrefix = null;
48
-
49
-    /**
50
-     * @var \Pixie\QueryBuilder\Adapters\BaseAdapter
51
-     */
52
-    protected $adapterInstance;
53
-
54
-    /**
55
-     * The mode to return results as.
56
-     * Accepts WPDB constants or class names.
57
-     *
58
-     * @var string
59
-     */
60
-    protected $fetchMode;
61
-
62
-    /**
63
-     * Custom args used to construct models for hydrator
64
-     *
65
-     * @var array<int, mixed>|null
66
-     */
67
-    protected $hydratorConstructorArgs;
68
-
69
-    /**
70
-     * @param null|\Pixie\Connection $connection
71
-     * @param string $fetchMode
72
-     * @throws Exception If no connection passed and not previously established.
73
-     */
74
-    public function __construct(
75
-        Connection $connection = null,
76
-        string $fetchMode = \OBJECT,
77
-        ?array $hydratorConstructorArgs = null
78
-    ) {
79
-        if (is_null($connection)) {
80
-            // throws if connection not already established.
81
-            $connection = Connection::getStoredConnection();
82
-        }
83
-
84
-        $this->connection = $connection;
85
-        $this->container = $this->connection->getContainer();
86
-        $this->dbInstance = $this->connection->getDbInstance();
87
-        $this->adapter = 'wpdb';
88
-        $this->adapterConfig = $this->connection->getAdapterConfig();
89
-
90
-        if (isset($this->adapterConfig['prefix'])) {
91
-            $this->tablePrefix = $this->adapterConfig['prefix'];
92
-        }
93
-
94
-        // Set up optional hydration details.
95
-        $this->setFetchMode($fetchMode);
96
-        $this->hydratorConstructorArgs = $hydratorConstructorArgs;
97
-
98
-
99
-        // Query builder adapter instance
100
-        $this->adapterInstance = $this->container->build(
101
-            WPDBAdapter::class,
102
-            array($this->connection)
103
-        );
104
-    }
105
-
106
-    /**
107
-     * Set the fetch mode
108
-     *
109
-     * @param string $mode
110
-     * @param null|array<int, mixed> $constructorArgs
111
-     * @return $this
112
-     */
113
-    public function setFetchMode(string $mode, ?array $constructorArgs = null): self
114
-    {
115
-        $this->fetchMode = $mode;
116
-        $this->hydratorConstructorArgs = $constructorArgs;
117
-        return $this;
118
-    }
119
-
120
-    /**
121
-     * @param null|Connection $connection
122
-     * @return QueryBuilderHandler
123
-     * @throws Exception
124
-     */
125
-    public function newQuery(Connection $connection = null)
126
-    {
127
-        if (is_null($connection)) {
128
-            $connection = $this->connection;
129
-        }
130
-
131
-        $new = new static($connection);
132
-        $new->setFetchMode($this->getFetchMode(), $this->hydratorConstructorArgs);
133
-        return $new;
134
-    }
135
-
136
-    /**
137
-     * @param       $sql
138
-     * @param array $bindings
139
-     *
140
-     * @return $this
141
-     */
142
-    public function query($sql, $bindings = array())
143
-    {
144
-        list($this->sqlStatement) = $this->statement($sql, $bindings);
145
-
146
-        return $this;
147
-    }
148
-
149
-    /**
150
-     * @param       $sql
151
-     * @param array $bindings
152
-     *
153
-     * @return array sqlStatement and execution time as float
154
-     */
155
-    public function statement($sql, $bindings = array())
156
-    {
157
-        $start = microtime(true);
158
-        $sqlStatement = empty($bindings) ? $sql : $this->dbInstance->prepare($sql, $bindings);
159
-
160
-        return array($sqlStatement, microtime(true) - $start);
161
-    }
162
-
163
-    /**
164
-     * Get all rows
165
-     *
166
-     * @return object|object[]
167
-     * @throws Exception
168
-     */
169
-    public function get()
170
-    {
171
-        $eventResult = $this->fireEvents('before-select');
172
-        if (!is_null($eventResult)) {
173
-            return $eventResult;
174
-        };
175
-        $executionTime = 0;
176
-        if (is_null($this->sqlStatement)) {
177
-            $queryObject = $this->getQuery('select');
178
-
179
-            list($this->sqlStatement, $executionTime) = $this->statement(
180
-                $queryObject->getSql(),
181
-                $queryObject->getBindings()
182
-            );
183
-        }
184
-
185
-        $start = microtime(true);
186
-        $result = $this->dbInstance()->get_results(
187
-            $this->sqlStatement,
188
-            $this->useHydrator() ? OBJECT : $this->getFetchMode()
189
-        );
190
-        $executionTime += microtime(true) - $start;
191
-        $this->sqlStatement = null;
192
-
193
-        // Maybe hydrate the results.
194
-        if (is_array($result) && $this->useHydrator()) {
195
-            $result = $this->getHydrator()->fromMany($result);
196
-        }
197
-
198
-        $this->fireEvents('after-select', $result, $executionTime);
199
-        return $result;
200
-    }
201
-
202
-    /**
203
-     * Returns a populated instance of the Hydrator.
204
-     *
205
-     * @return Hydrator
206
-     */
207
-    protected function getHydrator(): Hydrator
208
-    {
209
-        return new Hydrator($this->getFetchMode(), $this->hydratorConstructorArgs ?? []);
210
-    }
211
-
212
-    /**
213
-     * Checks if the results should be mapped via the hydrator
214
-     *
215
-     * @return bool
216
-     */
217
-    protected function useHydrator(): bool
218
-    {
219
-        return ! in_array($this->getFetchMode(), [\ARRAY_A, \ARRAY_N, \OBJECT, \OBJECT_K]);
220
-    }
221
-
222
-    /**
223
-     * Get first row
224
-     *
225
-     * @return \stdClass|array|null
226
-     */
227
-    public function first()
228
-    {
229
-        $this->limit(1);
230
-        $result = $this->get();
231
-        return empty($result) ? null : $result[0];
232
-    }
233
-
234
-    /**
235
-     * @param        $value
236
-     * @param string $fieldName
237
-     *
238
-     * @return null|\stdClass
239
-     */
240
-    public function findAll($fieldName, $value)
241
-    {
242
-        $this->where($fieldName, '=', $value);
243
-        return $this->get();
244
-    }
245
-
246
-    /**
247
-     * @param        $value
248
-     * @param string $fieldName
249
-     *
250
-     * @return null|\stdClass
251
-     */
252
-    public function find($value, $fieldName = 'id')
253
-    {
254
-        $this->where($fieldName, '=', $value);
255
-        return $this->first();
256
-    }
257
-
258
-    /**
259
-     * Used to handle all aggregation method.
260
-     *
261
-     * @see Taken from the pecee-pixie library - https://github.com/skipperbent/pecee-pixie/
262
-     *
263
-     * @param string $type
264
-     * @param string $field
265
-     * @return float
266
-     */
267
-    protected function aggregate(string $type, string $field = '*'): float
268
-    {
269
-        // Verify that field exists
270
-        if ($field !== '*' && isset($this->statements['selects']) === true && \in_array($field, $this->statements['selects'], true) === false) {
271
-            throw new \Exception(sprintf('Failed %s query - the column %s hasn\'t been selected in the query.', $type, $field));
272
-        }
273
-
274
-        if (isset($this->statements['tables']) === false) {
275
-            throw new Exception('No table selected');
276
-        }
277
-
278
-        $count = $this
279
-            ->table($this->subQuery($this, 'count'))
280
-            ->select([$this->raw(sprintf('%s(%s) AS field', strtoupper($type), $field))])
281
-            ->first();
282
-
283
-        return isset($count->field) === true ? (float)$count->field : 0;
284
-    }
285
-
286
-    /**
287
-     * Get count of all the rows for the current query
288
-     * @see Taken from the pecee-pixie library - https://github.com/skipperbent/pecee-pixie/
289
-     *
290
-     * @param string $field
291
-     *
292
-     * @return integer
293
-     * @throws Exception
294
-     */
295
-    public function count(string $field = '*'): int
296
-    {
297
-        return (int)$this->aggregate('count', $field);
298
-    }
299
-
300
-    /**
301
-     * Get the sum for a field in the current query
302
-     * @see Taken from the pecee-pixie library - https://github.com/skipperbent/pecee-pixie/
303
-     *
304
-     * @param string $field
305
-     * @return float
306
-     * @throws Exception
307
-     */
308
-    public function sum(string $field): float
309
-    {
310
-        return $this->aggregate('sum', $field);
311
-    }
312
-
313
-    /**
314
-     * Get the average for a field in the current query
315
-     * @see Taken from the pecee-pixie library - https://github.com/skipperbent/pecee-pixie/
316
-     *
317
-     * @param string $field
318
-     * @return float
319
-     * @throws Exception
320
-     */
321
-    public function average(string $field): float
322
-    {
323
-        return $this->aggregate('avg', $field);
324
-    }
325
-
326
-    /**
327
-     * Get the minimum for a field in the current query
328
-     * @see Taken from the pecee-pixie library - https://github.com/skipperbent/pecee-pixie/
329
-     *
330
-     * @param string $field
331
-     * @return float
332
-     * @throws Exception
333
-     */
334
-    public function min(string $field): float
335
-    {
336
-        return $this->aggregate('min', $field);
337
-    }
338
-
339
-    /**
340
-     * Get the maximum for a field in the current query
341
-     * @see Taken from the pecee-pixie library - https://github.com/skipperbent/pecee-pixie/
342
-     *
343
-     * @param string $field
344
-     * @return float
345
-     * @throws Exception
346
-     */
347
-    public function max(string $field): float
348
-    {
349
-        return $this->aggregate('max', $field);
350
-    }
351
-
352
-    /**
353
-     * @param string $type
354
-     * @param array $dataToBePassed
355
-     *
356
-     * @return mixed
357
-     * @throws Exception
358
-     */
359
-    public function getQuery($type = 'select', $dataToBePassed = array())
360
-    {
361
-        $allowedTypes = array('select', 'insert', 'insertignore', 'replace', 'delete', 'update', 'criteriaonly');
362
-        if (!in_array(strtolower($type), $allowedTypes)) {
363
-            throw new Exception($type . ' is not a known type.', 2);
364
-        }
365
-
366
-        $queryArr = $this->adapterInstance->$type($this->statements, $dataToBePassed);
367
-
368
-        return $this->container->build(
369
-            QueryObject::class,
370
-            array($queryArr['sql'], $queryArr['bindings'], $this->dbInstance)
371
-        );
372
-    }
373
-
374
-    /**
375
-     * @param QueryBuilderHandler $queryBuilder
376
-     * @param null $alias
377
-     *
378
-     * @return Raw
379
-     */
380
-    public function subQuery(QueryBuilderHandler $queryBuilder, $alias = null)
381
-    {
382
-        $sql = '(' . $queryBuilder->getQuery()->getRawSql() . ')';
383
-        if ($alias) {
384
-            $sql = $sql . ' as ' . $alias;
385
-        }
386
-
387
-        return $queryBuilder->raw($sql);
388
-    }
389
-
390
-    /**
391
-     * @param $data
392
-     *
393
-     * @return array|string
394
-     */
395
-    private function doInsert($data, $type)
396
-    {
397
-        $eventResult = $this->fireEvents('before-insert');
398
-        if (!is_null($eventResult)) {
399
-            return $eventResult;
400
-        }
401
-
402
-        // If first value is not an array () not a batch insert)
403
-        if (!is_array(current($data))) {
404
-            $queryObject = $this->getQuery($type, $data);
405
-
406
-            list($preparedQuery, $executionTime) = $this->statement($queryObject->getSql(), $queryObject->getBindings());
407
-            $this->dbInstance->get_results($preparedQuery);
408
-
409
-            // Check we have a result.
410
-            $return = $this->dbInstance->rows_affected === 1 ? $this->dbInstance->insert_id : null;
411
-        } else {
412
-            // Its a batch insert
413
-            $return = array();
414
-            $executionTime = 0;
415
-            foreach ($data as $subData) {
416
-                $queryObject = $this->getQuery($type, $subData);
417
-
418
-                list($preparedQuery, $time) = $this->statement($queryObject->getSql(), $queryObject->getBindings());
419
-                $this->dbInstance->get_results($preparedQuery);
420
-                $executionTime += $time;
421
-
422
-                if ($this->dbInstance->rows_affected === 1) {
423
-                    $return[] = $this->dbInstance->insert_id;
424
-                }
425
-            }
426
-        }
427
-
428
-        $this->fireEvents('after-insert', $return, $executionTime);
429
-
430
-        return $return;
431
-    }
432
-
433
-    /**
434
-     * @param $data
435
-     *
436
-     * @return array|string
437
-     */
438
-    public function insert($data)
439
-    {
440
-        return $this->doInsert($data, 'insert');
441
-    }
442
-
443
-    /**
444
-     * @param $data
445
-     *
446
-     * @return array|string
447
-     */
448
-    public function insertIgnore($data)
449
-    {
450
-        return $this->doInsert($data, 'insertignore');
451
-    }
452
-
453
-    /**
454
-     * @param $data
455
-     *
456
-     * @return array|string
457
-     */
458
-    public function replace($data)
459
-    {
460
-        return $this->doInsert($data, 'replace');
461
-    }
462
-
463
-    /**
464
-     * @param $data
465
-     *
466
-     * @return bool
467
-     */
468
-    public function update($data)
469
-    {
470
-        $eventResult = $this->fireEvents('before-update');
471
-        if (!is_null($eventResult)) {
472
-            return $eventResult;
473
-        }
474
-
475
-        $queryObject = $this->getQuery('update', $data);
476
-        list($preparedQuery, $executionTime) = $this->statement($queryObject->getSql(), $queryObject->getBindings());
477
-
478
-        $this->dbInstance()->get_results($preparedQuery);
479
-        $this->fireEvents('after-update', $queryObject, $executionTime);
480
-
481
-        return $this->dbInstance()->rows_affected !== 0
482
-            ? $this->dbInstance()->rows_affected
483
-            : null;
484
-    }
485
-
486
-    /**
487
-     * @param $data
488
-     *
489
-     * @return array|string
490
-     */
491
-    public function updateOrInsert($data)
492
-    {
493
-        if ($this->first()) {
494
-            return $this->update($data);
495
-        } else {
496
-            return $this->insert($data);
497
-        }
498
-    }
499
-
500
-    /**
501
-     * @param $data
502
-     *
503
-     * @return $this
504
-     */
505
-    public function onDuplicateKeyUpdate($data)
506
-    {
507
-        $this->addStatement('onduplicate', $data);
508
-        return $this;
509
-    }
510
-
511
-    /**
512
-     *
513
-     */
514
-    public function delete()
515
-    {
516
-        $eventResult = $this->fireEvents('before-delete');
517
-        if (!is_null($eventResult)) {
518
-            return $eventResult;
519
-        }
520
-
521
-        $queryObject = $this->getQuery('delete');
522
-
523
-        list($preparedQuery, $executionTime) = $this->statement($queryObject->getSql(), $queryObject->getBindings());
524
-        $response = $this->dbInstance()->get_results($preparedQuery);
525
-        $this->fireEvents('after-delete', $queryObject, $executionTime);
526
-
527
-        return $response;
528
-    }
529
-
530
-    /**
531
-     * @param string|array $tables Single table or array of tables
532
-     *
533
-     * @return QueryBuilderHandler
534
-     * @throws Exception
535
-     */
536
-    public function table($tables)
537
-    {
538
-        if (!is_array($tables)) {
539
-            // because a single table is converted to an array anyways,
540
-            // this makes sense.
541
-            $tables = func_get_args();
542
-        }
543
-
544
-        $instance = new static($this->connection);
545
-        $this->setFetchMode($this->getFetchMode(), $this->hydratorConstructorArgs);
546
-        $tables = $this->addTablePrefix($tables, false);
547
-        $instance->addStatement('tables', $tables);
548
-        return $instance;
549
-    }
550
-
551
-    /**
552
-     * @param $tables
553
-     *
554
-     * @return $this
555
-     */
556
-    public function from($tables)
557
-    {
558
-        if (!is_array($tables)) {
559
-            $tables = func_get_args();
560
-        }
561
-
562
-        $tables = $this->addTablePrefix($tables, false);
563
-        $this->addStatement('tables', $tables);
564
-        return $this;
565
-    }
566
-
567
-    /**
568
-     * @param $fields
569
-     *
570
-     * @return $this
571
-     */
572
-    public function select($fields)
573
-    {
574
-        if (!is_array($fields)) {
575
-            $fields = func_get_args();
576
-        }
577
-
578
-        $fields = $this->addTablePrefix($fields);
579
-        $this->addStatement('selects', $fields);
580
-        return $this;
581
-    }
582
-
583
-    /**
584
-     * @param $fields
585
-     *
586
-     * @return $this
587
-     */
588
-    public function selectDistinct($fields)
589
-    {
590
-        $this->select($fields);
591
-        $this->addStatement('distinct', true);
592
-        return $this;
593
-    }
594
-
595
-    /**
596
-     * @param string|string[] $field Either the single field or an array of fields.
597
-     *
598
-     * @return $this
599
-     */
600
-    public function groupBy($field)
601
-    {
602
-        $field = $this->addTablePrefix($field);
603
-        $this->addStatement('groupBys', $field);
604
-        return $this;
605
-    }
606
-
607
-    /**
608
-     * @param string|string[] $fields
609
-     * @param string          $defaultDirection
610
-     *
611
-     * @return $this
612
-     */
613
-    public function orderBy($fields, $defaultDirection = 'ASC')
614
-    {
615
-        if (!is_array($fields)) {
616
-            $fields = array($fields);
617
-        }
618
-
619
-        foreach ($fields as $key => $value) {
620
-            $field = $key;
621
-            $type = $value;
622
-            if (is_int($key)) {
623
-                $field = $value;
624
-                $type = $defaultDirection;
625
-            }
626
-            if (!$field instanceof Raw) {
627
-                $field = $this->addTablePrefix($field);
628
-            }
629
-            $this->statements['orderBys'][] = compact('field', 'type');
630
-        }
631
-
632
-        return $this;
633
-    }
634
-
635
-    /**
636
-     * @param $limit
637
-     *
638
-     * @return $this
639
-     */
640
-    public function limit($limit)
641
-    {
642
-        $this->statements['limit'] = $limit;
643
-        return $this;
644
-    }
645
-
646
-    /**
647
-     * @param $offset
648
-     *
649
-     * @return $this
650
-     */
651
-    public function offset($offset)
652
-    {
653
-        $this->statements['offset'] = $offset;
654
-        return $this;
655
-    }
656
-
657
-    /**
658
-     * @param        $key
659
-     * @param        $operator
660
-     * @param        $value
661
-     * @param string $joiner
662
-     *
663
-     * @return $this
664
-     */
665
-    public function having($key, $operator, $value, $joiner = 'AND')
666
-    {
667
-        $key = $this->addTablePrefix($key);
668
-        $this->statements['havings'][] = compact('key', 'operator', 'value', 'joiner');
669
-        return $this;
670
-    }
671
-
672
-    /**
673
-     * @param        $key
674
-     * @param        $operator
675
-     * @param        $value
676
-     *
677
-     * @return $this
678
-     */
679
-    public function orHaving($key, $operator, $value)
680
-    {
681
-        return $this->having($key, $operator, $value, 'OR');
682
-    }
683
-
684
-    /**
685
-     * @param $key
686
-     * @param $operator
687
-     * @param $value
688
-     *
689
-     * @return $this
690
-     */
691
-    public function where($key, $operator = null, $value = null)
692
-    {
693
-        // If two params are given then assume operator is =
694
-        if (func_num_args() == 2) {
695
-            $value = $operator;
696
-            $operator = '=';
697
-        }
698
-        return $this->whereHandler($key, $operator, $value);
699
-    }
700
-
701
-    /**
702
-     * @param $key
703
-     * @param $operator
704
-     * @param $value
705
-     *
706
-     * @return $this
707
-     */
708
-    public function orWhere($key, $operator = null, $value = null)
709
-    {
710
-        // If two params are given then assume operator is =
711
-        if (func_num_args() == 2) {
712
-            $value = $operator;
713
-            $operator = '=';
714
-        }
715
-
716
-        return $this->whereHandler($key, $operator, $value, 'OR');
717
-    }
718
-
719
-    /**
720
-     * @param $key
721
-     * @param $operator
722
-     * @param $value
723
-     *
724
-     * @return $this
725
-     */
726
-    public function whereNot($key, $operator = null, $value = null)
727
-    {
728
-        // If two params are given then assume operator is =
729
-        if (func_num_args() == 2) {
730
-            $value = $operator;
731
-            $operator = '=';
732
-        }
733
-        return $this->whereHandler($key, $operator, $value, 'AND NOT');
734
-    }
735
-
736
-    /**
737
-     * @param $key
738
-     * @param $operator
739
-     * @param $value
740
-     *
741
-     * @return $this
742
-     */
743
-    public function orWhereNot($key, $operator = null, $value = null)
744
-    {
745
-        // If two params are given then assume operator is =
746
-        if (func_num_args() == 2) {
747
-            $value = $operator;
748
-            $operator = '=';
749
-        }
750
-        return $this->whereHandler($key, $operator, $value, 'OR NOT');
751
-    }
752
-
753
-    /**
754
-     * @param       $key
755
-     * @param array $values
756
-     *
757
-     * @return $this
758
-     */
759
-    public function whereIn($key, $values)
760
-    {
761
-        return $this->whereHandler($key, 'IN', $values, 'AND');
762
-    }
763
-
764
-    /**
765
-     * @param       $key
766
-     * @param array $values
767
-     *
768
-     * @return $this
769
-     */
770
-    public function whereNotIn($key, $values)
771
-    {
772
-        return $this->whereHandler($key, 'NOT IN', $values, 'AND');
773
-    }
774
-
775
-    /**
776
-     * @param       $key
777
-     * @param array $values
778
-     *
779
-     * @return $this
780
-     */
781
-    public function orWhereIn($key, $values)
782
-    {
783
-        return $this->whereHandler($key, 'IN', $values, 'OR');
784
-    }
785
-
786
-    /**
787
-     * @param       $key
788
-     * @param array $values
789
-     *
790
-     * @return $this
791
-     */
792
-    public function orWhereNotIn($key, $values)
793
-    {
794
-        return $this->whereHandler($key, 'NOT IN', $values, 'OR');
795
-    }
796
-
797
-    /**
798
-     * @param $key
799
-     * @param $valueFrom
800
-     * @param $valueTo
801
-     *
802
-     * @return $this
803
-     */
804
-    public function whereBetween($key, $valueFrom, $valueTo)
805
-    {
806
-        return $this->whereHandler($key, 'BETWEEN', array($valueFrom, $valueTo), 'AND');
807
-    }
808
-
809
-    /**
810
-     * @param $key
811
-     * @param $valueFrom
812
-     * @param $valueTo
813
-     *
814
-     * @return $this
815
-     */
816
-    public function orWhereBetween($key, $valueFrom, $valueTo)
817
-    {
818
-        return $this->whereHandler($key, 'BETWEEN', array($valueFrom, $valueTo), 'OR');
819
-    }
820
-
821
-    /**
822
-     * @param $key
823
-     * @return QueryBuilderHandler
824
-     */
825
-    public function whereNull($key)
826
-    {
827
-        return $this->whereNullHandler($key);
828
-    }
829
-
830
-    /**
831
-     * @param $key
832
-     * @return QueryBuilderHandler
833
-     */
834
-    public function whereNotNull($key)
835
-    {
836
-        return $this->whereNullHandler($key, 'NOT');
837
-    }
838
-
839
-    /**
840
-     * @param $key
841
-     * @return QueryBuilderHandler
842
-     */
843
-    public function orWhereNull($key)
844
-    {
845
-        return $this->whereNullHandler($key, '', 'or');
846
-    }
847
-
848
-    /**
849
-     * @param $key
850
-     * @return QueryBuilderHandler
851
-     */
852
-    public function orWhereNotNull($key)
853
-    {
854
-        return $this->whereNullHandler($key, 'NOT', 'or');
855
-    }
856
-
857
-    protected function whereNullHandler($key, string $prefix = '', $operator = '')
858
-    {
859
-        $prefix = \strlen($prefix) === 0 ? '' : " {$prefix}";
860
-
861
-        $key = $this->adapterInstance->wrapSanitizer($this->addTablePrefix($key));
862
-        return $this->{$operator . 'Where'}($this->raw("{$key} IS{$prefix} NULL"));
863
-    }
864
-
865
-    /**
866
-     * @param        $table
867
-     * @param        $key
868
-     * @param        $operator
869
-     * @param        $value
870
-     * @param string $type
871
-     *
872
-     * @return $this
873
-     */
874
-    public function join($table, $key, $operator = null, $value = null, $type = 'inner')
875
-    {
876
-        if (!$key instanceof \Closure) {
877
-            $key = function ($joinBuilder) use ($key, $operator, $value) {
878
-                $joinBuilder->on($key, $operator, $value);
879
-            };
880
-        }
881
-
882
-        // Build a new JoinBuilder class, keep it by reference so any changes made
883
-        // in the closure should reflect here
884
-        $joinBuilder = $this->container->build(JoinBuilder::class, array($this->connection));
885
-        $joinBuilder = &$joinBuilder;
886
-        // Call the closure with our new joinBuilder object
887
-        $key($joinBuilder);
888
-        $table = $this->addTablePrefix($table, false);
889
-        // Get the criteria only query from the joinBuilder object
890
-        $this->statements['joins'][] = compact('type', 'table', 'joinBuilder');
891
-
892
-        return $this;
893
-    }
894
-
895
-    /**
896
-     * Runs a transaction
897
-     *
898
-     * @param $callback
899
-     *
900
-     * @return $this
901
-     */
902
-    public function transaction(\Closure $callback)
903
-    {
904
-        try {
905
-            // Begin the transaction
906
-            $this->dbInstance->query('START TRANSACTION');
907
-
908
-            // Get the Transaction class
909
-            $transaction = $this->container->build(Transaction::class, array($this->connection));
910
-
911
-            $this->handleTransactionCall($callback, $transaction);
912
-
913
-            // If no errors have been thrown or the transaction wasn't completed within
914
-            $this->dbInstance->query('COMMIT');
915
-
916
-            return $this;
917
-        } catch (TransactionHaltException $e) {
918
-            // Commit or rollback behavior has been handled in the closure, so exit
919
-            return $this;
920
-        } catch (\Exception $e) {
921
-            // something happened, rollback changes
922
-            $this->dbInstance->query('ROLLBACK');
923
-            return $this;
924
-        }
925
-    }
926
-
927
-    /**
928
-     * Handles the transaction call.
929
-     *
930
-     * Catches any WP Errors (printed)
931
-     *
932
-     * @param callable    $callback
933
-     * @param Transaction $transaction
934
-     * @return void
935
-     */
936
-    protected function handleTransactionCall(callable $callback, Transaction $transaction): void
937
-    {
938
-        try {
939
-            ob_start();
940
-            $callback($transaction);
941
-            $output = ob_get_clean();
942
-        } catch (\Throwable $th) {
943
-            ob_end_clean();
944
-            throw $th;
945
-        }
946
-
947
-        // If we caught an error, throw an exception.
948
-        if (\mb_strlen($output) !== 0) {
949
-            throw new Exception($output);
950
-        }
951
-    }
952
-
953
-    /**
954
-     * @param      $table
955
-     * @param      $key
956
-     * @param null $operator
957
-     * @param null $value
958
-     *
959
-     * @return $this
960
-     */
961
-    public function leftJoin($table, $key, $operator = null, $value = null)
962
-    {
963
-        return $this->join($table, $key, $operator, $value, 'left');
964
-    }
965
-
966
-    /**
967
-     * @param      $table
968
-     * @param      $key
969
-     * @param null $operator
970
-     * @param null $value
971
-     *
972
-     * @return $this
973
-     */
974
-    public function rightJoin($table, $key, $operator = null, $value = null)
975
-    {
976
-        return $this->join($table, $key, $operator, $value, 'right');
977
-    }
978
-
979
-    /**
980
-     * @param      $table
981
-     * @param      $key
982
-     * @param null $operator
983
-     * @param null $value
984
-     *
985
-     * @return $this
986
-     */
987
-    public function innerJoin($table, $key, $operator = null, $value = null)
988
-    {
989
-        return $this->join($table, $key, $operator, $value, 'inner');
990
-    }
991
-
992
-    /**
993
-     * @param string           $table
994
-     * @param callable|string  $key
995
-     * @param null|string      $operator
996
-     * @param null|mixed       $value
997
-     * @return this
998
-     */
999
-    public function crossJoin($table, $key, $operator = null, $value = null)
1000
-    {
1001
-        return $this->join($table, $key, $operator, $value, 'cross');
1002
-    }
1003
-
1004
-    /**
1005
-     * @param string           $table
1006
-     * @param callable|string  $key
1007
-     * @param null|string      $operator
1008
-     * @param null|mixed       $value
1009
-     * @return this
1010
-     */
1011
-    public function outerJoin($table, $key, $operator = null, $value = null)
1012
-    {
1013
-        return $this->join($table, $key, $operator, $value, 'outer');
1014
-    }
1015
-
1016
-    /**
1017
-     * Add a raw query
1018
-     *
1019
-     * @param $value
1020
-     * @param $bindings
1021
-     *
1022
-     * @return mixed
1023
-     */
1024
-    public function raw($value, $bindings = array())
1025
-    {
1026
-        return $this->container->build(Raw::class, array($value, $bindings));
1027
-    }
1028
-
1029
-    /**
1030
-     * Return wpdb instance
1031
-     *
1032
-     * @return wpdb
1033
-     */
1034
-    public function dbInstance(): \wpdb
1035
-    {
1036
-        return $this->dbInstance;
1037
-    }
1038
-
1039
-    /**
1040
-     * @param Connection $connection
1041
-     *
1042
-     * @return $this
1043
-     */
1044
-    public function setConnection(Connection $connection)
1045
-    {
1046
-        $this->connection = $connection;
1047
-        return $this;
1048
-    }
1049
-
1050
-    /**
1051
-     * @return Connection
1052
-     */
1053
-    public function getConnection()
1054
-    {
1055
-        return $this->connection;
1056
-    }
1057
-
1058
-    /**
1059
-     * @param        $key
1060
-     * @param        $operator
1061
-     * @param        $value
1062
-     * @param string $joiner
1063
-     *
1064
-     * @return $this
1065
-     */
1066
-    protected function whereHandler($key, $operator = null, $value = null, $joiner = 'AND')
1067
-    {
1068
-        $key = $this->addTablePrefix($key);
1069
-        $this->statements['wheres'][] = compact('key', 'operator', 'value', 'joiner');
1070
-        return $this;
1071
-    }
1072
-
1073
-    /**
1074
-     * Add table prefix (if given) on given string.
1075
-     *
1076
-     * @param string|string[]     $values
1077
-     * @param bool $tableFieldMix If we have mixes of field and table names with a "."
1078
-     *
1079
-     * @return array|mixed
1080
-     */
1081
-    public function addTablePrefix($values, $tableFieldMix = true)
1082
-    {
1083
-        if (is_null($this->tablePrefix)) {
1084
-            return $values;
1085
-        }
1086
-
1087
-        // $value will be an array and we will add prefix to all table names
1088
-
1089
-        // If supplied value is not an array then make it one
1090
-        $single = false;
1091
-        if (!is_array($values)) {
1092
-            $values = array($values);
1093
-            // We had single value, so should return a single value
1094
-            $single = true;
1095
-        }
1096
-
1097
-        $return = array();
1098
-
1099
-        foreach ($values as $key => $value) {
1100
-            // It's a raw query, just add it to our return array and continue next
1101
-            if ($value instanceof Raw || $value instanceof \Closure) {
1102
-                $return[$key] = $value;
1103
-                continue;
1104
-            }
1105
-
1106
-            // If key is not integer, it is likely a alias mapping,
1107
-            // so we need to change prefix target
1108
-            $target = &$value;
1109
-            if (!is_int($key)) {
1110
-                $target = &$key;
1111
-            }
1112
-
1113
-            if (!$tableFieldMix || ($tableFieldMix && strpos($target, '.') !== false)) {
1114
-                $target = $this->tablePrefix . $target;
1115
-            }
1116
-
1117
-            $return[$key] = $value;
1118
-        }
1119
-
1120
-        // If we had single value then we should return a single value (end value of the array)
1121
-        return $single ? end($return) : $return;
1122
-    }
1123
-
1124
-    /**
1125
-     * @param $key
1126
-     * @param $value
1127
-     */
1128
-    protected function addStatement($key, $value)
1129
-    {
1130
-        if (!is_array($value)) {
1131
-            $value = array($value);
1132
-        }
1133
-
1134
-        if (!array_key_exists($key, $this->statements)) {
1135
-            $this->statements[$key] = $value;
1136
-        } else {
1137
-            $this->statements[$key] = array_merge($this->statements[$key], $value);
1138
-        }
1139
-    }
1140
-
1141
-    /**
1142
-     * @param $event
1143
-     * @param $table
1144
-     *
1145
-     * @return callable|null
1146
-     */
1147
-    public function getEvent($event, $table = ':any')
1148
-    {
1149
-        return $this->connection->getEventHandler()->getEvent($event, $table);
1150
-    }
1151
-
1152
-    /**
1153
-     * @param          $event
1154
-     * @param string $table
1155
-     * @param callable $action
1156
-     *
1157
-     * @return void
1158
-     */
1159
-    public function registerEvent($event, $table, \Closure $action)
1160
-    {
1161
-        $table = $table ?: ':any';
1162
-
1163
-        if ($table != ':any') {
1164
-            $table = $this->addTablePrefix($table, false);
1165
-        }
1166
-
1167
-        return $this->connection->getEventHandler()->registerEvent($event, $table, $action);
1168
-    }
1169
-
1170
-    /**
1171
-     * @param          $event
1172
-     * @param string $table
1173
-     *
1174
-     * @return void
1175
-     */
1176
-    public function removeEvent($event, $table = ':any')
1177
-    {
1178
-        if ($table != ':any') {
1179
-            $table = $this->addTablePrefix($table, false);
1180
-        }
1181
-
1182
-        return $this->connection->getEventHandler()->removeEvent($event, $table);
1183
-    }
1184
-
1185
-    /**
1186
-     * @param      $event
1187
-     * @return mixed
1188
-     */
1189
-    public function fireEvents($event)
1190
-    {
1191
-        $params = func_get_args();
1192
-        array_unshift($params, $this);
1193
-        return call_user_func_array(array($this->connection->getEventHandler(), 'fireEvents'), $params);
1194
-    }
1195
-
1196
-    /**
1197
-     * @return array
1198
-     */
1199
-    public function getStatements()
1200
-    {
1201
-        return $this->statements;
1202
-    }
1203
-
1204
-    /**
1205
-     * @return string will return WPDB Fetch mode
1206
-     */
1207
-    public function getFetchMode()
1208
-    {
1209
-        return null !== $this->fetchMode
1210
-            ? $this->fetchMode
1211
-            : \OBJECT;
1212
-    }
19
+	/**
20
+	 * @var \Viocon\Container
21
+	 */
22
+	protected $container;
23
+
24
+	/**
25
+	 * @var Connection
26
+	 */
27
+	protected $connection;
28
+
29
+	/**
30
+	 * @var array
31
+	 */
32
+	protected $statements = array();
33
+
34
+	/**
35
+	 * @var \wpdb
36
+	 */
37
+	protected $dbInstance;
38
+
39
+	/**
40
+	 * @var null|string[]
41
+	 */
42
+	protected $sqlStatement = null;
43
+
44
+	/**
45
+	 * @var null|string
46
+	 */
47
+	protected $tablePrefix = null;
48
+
49
+	/**
50
+	 * @var \Pixie\QueryBuilder\Adapters\BaseAdapter
51
+	 */
52
+	protected $adapterInstance;
53
+
54
+	/**
55
+	 * The mode to return results as.
56
+	 * Accepts WPDB constants or class names.
57
+	 *
58
+	 * @var string
59
+	 */
60
+	protected $fetchMode;
61
+
62
+	/**
63
+	 * Custom args used to construct models for hydrator
64
+	 *
65
+	 * @var array<int, mixed>|null
66
+	 */
67
+	protected $hydratorConstructorArgs;
68
+
69
+	/**
70
+	 * @param null|\Pixie\Connection $connection
71
+	 * @param string $fetchMode
72
+	 * @throws Exception If no connection passed and not previously established.
73
+	 */
74
+	public function __construct(
75
+		Connection $connection = null,
76
+		string $fetchMode = \OBJECT,
77
+		?array $hydratorConstructorArgs = null
78
+	) {
79
+		if (is_null($connection)) {
80
+			// throws if connection not already established.
81
+			$connection = Connection::getStoredConnection();
82
+		}
83
+
84
+		$this->connection = $connection;
85
+		$this->container = $this->connection->getContainer();
86
+		$this->dbInstance = $this->connection->getDbInstance();
87
+		$this->adapter = 'wpdb';
88
+		$this->adapterConfig = $this->connection->getAdapterConfig();
89
+
90
+		if (isset($this->adapterConfig['prefix'])) {
91
+			$this->tablePrefix = $this->adapterConfig['prefix'];
92
+		}
93
+
94
+		// Set up optional hydration details.
95
+		$this->setFetchMode($fetchMode);
96
+		$this->hydratorConstructorArgs = $hydratorConstructorArgs;
97
+
98
+
99
+		// Query builder adapter instance
100
+		$this->adapterInstance = $this->container->build(
101
+			WPDBAdapter::class,
102
+			array($this->connection)
103
+		);
104
+	}
105
+
106
+	/**
107
+	 * Set the fetch mode
108
+	 *
109
+	 * @param string $mode
110
+	 * @param null|array<int, mixed> $constructorArgs
111
+	 * @return $this
112
+	 */
113
+	public function setFetchMode(string $mode, ?array $constructorArgs = null): self
114
+	{
115
+		$this->fetchMode = $mode;
116
+		$this->hydratorConstructorArgs = $constructorArgs;
117
+		return $this;
118
+	}
119
+
120
+	/**
121
+	 * @param null|Connection $connection
122
+	 * @return QueryBuilderHandler
123
+	 * @throws Exception
124
+	 */
125
+	public function newQuery(Connection $connection = null)
126
+	{
127
+		if (is_null($connection)) {
128
+			$connection = $this->connection;
129
+		}
130
+
131
+		$new = new static($connection);
132
+		$new->setFetchMode($this->getFetchMode(), $this->hydratorConstructorArgs);
133
+		return $new;
134
+	}
135
+
136
+	/**
137
+	 * @param       $sql
138
+	 * @param array $bindings
139
+	 *
140
+	 * @return $this
141
+	 */
142
+	public function query($sql, $bindings = array())
143
+	{
144
+		list($this->sqlStatement) = $this->statement($sql, $bindings);
145
+
146
+		return $this;
147
+	}
148
+
149
+	/**
150
+	 * @param       $sql
151
+	 * @param array $bindings
152
+	 *
153
+	 * @return array sqlStatement and execution time as float
154
+	 */
155
+	public function statement($sql, $bindings = array())
156
+	{
157
+		$start = microtime(true);
158
+		$sqlStatement = empty($bindings) ? $sql : $this->dbInstance->prepare($sql, $bindings);
159
+
160
+		return array($sqlStatement, microtime(true) - $start);
161
+	}
162
+
163
+	/**
164
+	 * Get all rows
165
+	 *
166
+	 * @return object|object[]
167
+	 * @throws Exception
168
+	 */
169
+	public function get()
170
+	{
171
+		$eventResult = $this->fireEvents('before-select');
172
+		if (!is_null($eventResult)) {
173
+			return $eventResult;
174
+		};
175
+		$executionTime = 0;
176
+		if (is_null($this->sqlStatement)) {
177
+			$queryObject = $this->getQuery('select');
178
+
179
+			list($this->sqlStatement, $executionTime) = $this->statement(
180
+				$queryObject->getSql(),
181
+				$queryObject->getBindings()
182
+			);
183
+		}
184
+
185
+		$start = microtime(true);
186
+		$result = $this->dbInstance()->get_results(
187
+			$this->sqlStatement,
188
+			$this->useHydrator() ? OBJECT : $this->getFetchMode()
189
+		);
190
+		$executionTime += microtime(true) - $start;
191
+		$this->sqlStatement = null;
192
+
193
+		// Maybe hydrate the results.
194
+		if (is_array($result) && $this->useHydrator()) {
195
+			$result = $this->getHydrator()->fromMany($result);
196
+		}
197
+
198
+		$this->fireEvents('after-select', $result, $executionTime);
199
+		return $result;
200
+	}
201
+
202
+	/**
203
+	 * Returns a populated instance of the Hydrator.
204
+	 *
205
+	 * @return Hydrator
206
+	 */
207
+	protected function getHydrator(): Hydrator
208
+	{
209
+		return new Hydrator($this->getFetchMode(), $this->hydratorConstructorArgs ?? []);
210
+	}
211
+
212
+	/**
213
+	 * Checks if the results should be mapped via the hydrator
214
+	 *
215
+	 * @return bool
216
+	 */
217
+	protected function useHydrator(): bool
218
+	{
219
+		return ! in_array($this->getFetchMode(), [\ARRAY_A, \ARRAY_N, \OBJECT, \OBJECT_K]);
220
+	}
221
+
222
+	/**
223
+	 * Get first row
224
+	 *
225
+	 * @return \stdClass|array|null
226
+	 */
227
+	public function first()
228
+	{
229
+		$this->limit(1);
230
+		$result = $this->get();
231
+		return empty($result) ? null : $result[0];
232
+	}
233
+
234
+	/**
235
+	 * @param        $value
236
+	 * @param string $fieldName
237
+	 *
238
+	 * @return null|\stdClass
239
+	 */
240
+	public function findAll($fieldName, $value)
241
+	{
242
+		$this->where($fieldName, '=', $value);
243
+		return $this->get();
244
+	}
245
+
246
+	/**
247
+	 * @param        $value
248
+	 * @param string $fieldName
249
+	 *
250
+	 * @return null|\stdClass
251
+	 */
252
+	public function find($value, $fieldName = 'id')
253
+	{
254
+		$this->where($fieldName, '=', $value);
255
+		return $this->first();
256
+	}
257
+
258
+	/**
259
+	 * Used to handle all aggregation method.
260
+	 *
261
+	 * @see Taken from the pecee-pixie library - https://github.com/skipperbent/pecee-pixie/
262
+	 *
263
+	 * @param string $type
264
+	 * @param string $field
265
+	 * @return float
266
+	 */
267
+	protected function aggregate(string $type, string $field = '*'): float
268
+	{
269
+		// Verify that field exists
270
+		if ($field !== '*' && isset($this->statements['selects']) === true && \in_array($field, $this->statements['selects'], true) === false) {
271
+			throw new \Exception(sprintf('Failed %s query - the column %s hasn\'t been selected in the query.', $type, $field));
272
+		}
273
+
274
+		if (isset($this->statements['tables']) === false) {
275
+			throw new Exception('No table selected');
276
+		}
277
+
278
+		$count = $this
279
+			->table($this->subQuery($this, 'count'))
280
+			->select([$this->raw(sprintf('%s(%s) AS field', strtoupper($type), $field))])
281
+			->first();
282
+
283
+		return isset($count->field) === true ? (float)$count->field : 0;
284
+	}
285
+
286
+	/**
287
+	 * Get count of all the rows for the current query
288
+	 * @see Taken from the pecee-pixie library - https://github.com/skipperbent/pecee-pixie/
289
+	 *
290
+	 * @param string $field
291
+	 *
292
+	 * @return integer
293
+	 * @throws Exception
294
+	 */
295
+	public function count(string $field = '*'): int
296
+	{
297
+		return (int)$this->aggregate('count', $field);
298
+	}
299
+
300
+	/**
301
+	 * Get the sum for a field in the current query
302
+	 * @see Taken from the pecee-pixie library - https://github.com/skipperbent/pecee-pixie/
303
+	 *
304
+	 * @param string $field
305
+	 * @return float
306
+	 * @throws Exception
307
+	 */
308
+	public function sum(string $field): float
309
+	{
310
+		return $this->aggregate('sum', $field);
311
+	}
312
+
313
+	/**
314
+	 * Get the average for a field in the current query
315
+	 * @see Taken from the pecee-pixie library - https://github.com/skipperbent/pecee-pixie/
316
+	 *
317
+	 * @param string $field
318
+	 * @return float
319
+	 * @throws Exception
320
+	 */
321
+	public function average(string $field): float
322
+	{
323
+		return $this->aggregate('avg', $field);
324
+	}
325
+
326
+	/**
327
+	 * Get the minimum for a field in the current query
328
+	 * @see Taken from the pecee-pixie library - https://github.com/skipperbent/pecee-pixie/
329
+	 *
330
+	 * @param string $field
331
+	 * @return float
332
+	 * @throws Exception
333
+	 */
334
+	public function min(string $field): float
335
+	{
336
+		return $this->aggregate('min', $field);
337
+	}
338
+
339
+	/**
340
+	 * Get the maximum for a field in the current query
341
+	 * @see Taken from the pecee-pixie library - https://github.com/skipperbent/pecee-pixie/
342
+	 *
343
+	 * @param string $field
344
+	 * @return float
345
+	 * @throws Exception
346
+	 */
347
+	public function max(string $field): float
348
+	{
349
+		return $this->aggregate('max', $field);
350
+	}
351
+
352
+	/**
353
+	 * @param string $type
354
+	 * @param array $dataToBePassed
355
+	 *
356
+	 * @return mixed
357
+	 * @throws Exception
358
+	 */
359
+	public function getQuery($type = 'select', $dataToBePassed = array())
360
+	{
361
+		$allowedTypes = array('select', 'insert', 'insertignore', 'replace', 'delete', 'update', 'criteriaonly');
362
+		if (!in_array(strtolower($type), $allowedTypes)) {
363
+			throw new Exception($type . ' is not a known type.', 2);
364
+		}
365
+
366
+		$queryArr = $this->adapterInstance->$type($this->statements, $dataToBePassed);
367
+
368
+		return $this->container->build(
369
+			QueryObject::class,
370
+			array($queryArr['sql'], $queryArr['bindings'], $this->dbInstance)
371
+		);
372
+	}
373
+
374
+	/**
375
+	 * @param QueryBuilderHandler $queryBuilder
376
+	 * @param null $alias
377
+	 *
378
+	 * @return Raw
379
+	 */
380
+	public function subQuery(QueryBuilderHandler $queryBuilder, $alias = null)
381
+	{
382
+		$sql = '(' . $queryBuilder->getQuery()->getRawSql() . ')';
383
+		if ($alias) {
384
+			$sql = $sql . ' as ' . $alias;
385
+		}
386
+
387
+		return $queryBuilder->raw($sql);
388
+	}
389
+
390
+	/**
391
+	 * @param $data
392
+	 *
393
+	 * @return array|string
394
+	 */
395
+	private function doInsert($data, $type)
396
+	{
397
+		$eventResult = $this->fireEvents('before-insert');
398
+		if (!is_null($eventResult)) {
399
+			return $eventResult;
400
+		}
401
+
402
+		// If first value is not an array () not a batch insert)
403
+		if (!is_array(current($data))) {
404
+			$queryObject = $this->getQuery($type, $data);
405
+
406
+			list($preparedQuery, $executionTime) = $this->statement($queryObject->getSql(), $queryObject->getBindings());
407
+			$this->dbInstance->get_results($preparedQuery);
408
+
409
+			// Check we have a result.
410
+			$return = $this->dbInstance->rows_affected === 1 ? $this->dbInstance->insert_id : null;
411
+		} else {
412
+			// Its a batch insert
413
+			$return = array();
414
+			$executionTime = 0;
415
+			foreach ($data as $subData) {
416
+				$queryObject = $this->getQuery($type, $subData);
417
+
418
+				list($preparedQuery, $time) = $this->statement($queryObject->getSql(), $queryObject->getBindings());
419
+				$this->dbInstance->get_results($preparedQuery);
420
+				$executionTime += $time;
421
+
422
+				if ($this->dbInstance->rows_affected === 1) {
423
+					$return[] = $this->dbInstance->insert_id;
424
+				}
425
+			}
426
+		}
427
+
428
+		$this->fireEvents('after-insert', $return, $executionTime);
429
+
430
+		return $return;
431
+	}
432
+
433
+	/**
434
+	 * @param $data
435
+	 *
436
+	 * @return array|string
437
+	 */
438
+	public function insert($data)
439
+	{
440
+		return $this->doInsert($data, 'insert');
441
+	}
442
+
443
+	/**
444
+	 * @param $data
445
+	 *
446
+	 * @return array|string
447
+	 */
448
+	public function insertIgnore($data)
449
+	{
450
+		return $this->doInsert($data, 'insertignore');
451
+	}
452
+
453
+	/**
454
+	 * @param $data
455
+	 *
456
+	 * @return array|string
457
+	 */
458
+	public function replace($data)
459
+	{
460
+		return $this->doInsert($data, 'replace');
461
+	}
462
+
463
+	/**
464
+	 * @param $data
465
+	 *
466
+	 * @return bool
467
+	 */
468
+	public function update($data)
469
+	{
470
+		$eventResult = $this->fireEvents('before-update');
471
+		if (!is_null($eventResult)) {
472
+			return $eventResult;
473
+		}
474
+
475
+		$queryObject = $this->getQuery('update', $data);
476
+		list($preparedQuery, $executionTime) = $this->statement($queryObject->getSql(), $queryObject->getBindings());
477
+
478
+		$this->dbInstance()->get_results($preparedQuery);
479
+		$this->fireEvents('after-update', $queryObject, $executionTime);
480
+
481
+		return $this->dbInstance()->rows_affected !== 0
482
+			? $this->dbInstance()->rows_affected
483
+			: null;
484
+	}
485
+
486
+	/**
487
+	 * @param $data
488
+	 *
489
+	 * @return array|string
490
+	 */
491
+	public function updateOrInsert($data)
492
+	{
493
+		if ($this->first()) {
494
+			return $this->update($data);
495
+		} else {
496
+			return $this->insert($data);
497
+		}
498
+	}
499
+
500
+	/**
501
+	 * @param $data
502
+	 *
503
+	 * @return $this
504
+	 */
505
+	public function onDuplicateKeyUpdate($data)
506
+	{
507
+		$this->addStatement('onduplicate', $data);
508
+		return $this;
509
+	}
510
+
511
+	/**
512
+	 *
513
+	 */
514
+	public function delete()
515
+	{
516
+		$eventResult = $this->fireEvents('before-delete');
517
+		if (!is_null($eventResult)) {
518
+			return $eventResult;
519
+		}
520
+
521
+		$queryObject = $this->getQuery('delete');
522
+
523
+		list($preparedQuery, $executionTime) = $this->statement($queryObject->getSql(), $queryObject->getBindings());
524
+		$response = $this->dbInstance()->get_results($preparedQuery);
525
+		$this->fireEvents('after-delete', $queryObject, $executionTime);
526
+
527
+		return $response;
528
+	}
529
+
530
+	/**
531
+	 * @param string|array $tables Single table or array of tables
532
+	 *
533
+	 * @return QueryBuilderHandler
534
+	 * @throws Exception
535
+	 */
536
+	public function table($tables)
537
+	{
538
+		if (!is_array($tables)) {
539
+			// because a single table is converted to an array anyways,
540
+			// this makes sense.
541
+			$tables = func_get_args();
542
+		}
543
+
544
+		$instance = new static($this->connection);
545
+		$this->setFetchMode($this->getFetchMode(), $this->hydratorConstructorArgs);
546
+		$tables = $this->addTablePrefix($tables, false);
547
+		$instance->addStatement('tables', $tables);
548
+		return $instance;
549
+	}
550
+
551
+	/**
552
+	 * @param $tables
553
+	 *
554
+	 * @return $this
555
+	 */
556
+	public function from($tables)
557
+	{
558
+		if (!is_array($tables)) {
559
+			$tables = func_get_args();
560
+		}
561
+
562
+		$tables = $this->addTablePrefix($tables, false);
563
+		$this->addStatement('tables', $tables);
564
+		return $this;
565
+	}
566
+
567
+	/**
568
+	 * @param $fields
569
+	 *
570
+	 * @return $this
571
+	 */
572
+	public function select($fields)
573
+	{
574
+		if (!is_array($fields)) {
575
+			$fields = func_get_args();
576
+		}
577
+
578
+		$fields = $this->addTablePrefix($fields);
579
+		$this->addStatement('selects', $fields);
580
+		return $this;
581
+	}
582
+
583
+	/**
584
+	 * @param $fields
585
+	 *
586
+	 * @return $this
587
+	 */
588
+	public function selectDistinct($fields)
589
+	{
590
+		$this->select($fields);
591
+		$this->addStatement('distinct', true);
592
+		return $this;
593
+	}
594
+
595
+	/**
596
+	 * @param string|string[] $field Either the single field or an array of fields.
597
+	 *
598
+	 * @return $this
599
+	 */
600
+	public function groupBy($field)
601
+	{
602
+		$field = $this->addTablePrefix($field);
603
+		$this->addStatement('groupBys', $field);
604
+		return $this;
605
+	}
606
+
607
+	/**
608
+	 * @param string|string[] $fields
609
+	 * @param string          $defaultDirection
610
+	 *
611
+	 * @return $this
612
+	 */
613
+	public function orderBy($fields, $defaultDirection = 'ASC')
614
+	{
615
+		if (!is_array($fields)) {
616
+			$fields = array($fields);
617
+		}
618
+
619
+		foreach ($fields as $key => $value) {
620
+			$field = $key;
621
+			$type = $value;
622
+			if (is_int($key)) {
623
+				$field = $value;
624
+				$type = $defaultDirection;
625
+			}
626
+			if (!$field instanceof Raw) {
627
+				$field = $this->addTablePrefix($field);
628
+			}
629
+			$this->statements['orderBys'][] = compact('field', 'type');
630
+		}
631
+
632
+		return $this;
633
+	}
634
+
635
+	/**
636
+	 * @param $limit
637
+	 *
638
+	 * @return $this
639
+	 */
640
+	public function limit($limit)
641
+	{
642
+		$this->statements['limit'] = $limit;
643
+		return $this;
644
+	}
645
+
646
+	/**
647
+	 * @param $offset
648
+	 *
649
+	 * @return $this
650
+	 */
651
+	public function offset($offset)
652
+	{
653
+		$this->statements['offset'] = $offset;
654
+		return $this;
655
+	}
656
+
657
+	/**
658
+	 * @param        $key
659
+	 * @param        $operator
660
+	 * @param        $value
661
+	 * @param string $joiner
662
+	 *
663
+	 * @return $this
664
+	 */
665
+	public function having($key, $operator, $value, $joiner = 'AND')
666
+	{
667
+		$key = $this->addTablePrefix($key);
668
+		$this->statements['havings'][] = compact('key', 'operator', 'value', 'joiner');
669
+		return $this;
670
+	}
671
+
672
+	/**
673
+	 * @param        $key
674
+	 * @param        $operator
675
+	 * @param        $value
676
+	 *
677
+	 * @return $this
678
+	 */
679
+	public function orHaving($key, $operator, $value)
680
+	{
681
+		return $this->having($key, $operator, $value, 'OR');
682
+	}
683
+
684
+	/**
685
+	 * @param $key
686
+	 * @param $operator
687
+	 * @param $value
688
+	 *
689
+	 * @return $this
690
+	 */
691
+	public function where($key, $operator = null, $value = null)
692
+	{
693
+		// If two params are given then assume operator is =
694
+		if (func_num_args() == 2) {
695
+			$value = $operator;
696
+			$operator = '=';
697
+		}
698
+		return $this->whereHandler($key, $operator, $value);
699
+	}
700
+
701
+	/**
702
+	 * @param $key
703
+	 * @param $operator
704
+	 * @param $value
705
+	 *
706
+	 * @return $this
707
+	 */
708
+	public function orWhere($key, $operator = null, $value = null)
709
+	{
710
+		// If two params are given then assume operator is =
711
+		if (func_num_args() == 2) {
712
+			$value = $operator;
713
+			$operator = '=';
714
+		}
715
+
716
+		return $this->whereHandler($key, $operator, $value, 'OR');
717
+	}
718
+
719
+	/**
720
+	 * @param $key
721
+	 * @param $operator
722
+	 * @param $value
723
+	 *
724
+	 * @return $this
725
+	 */
726
+	public function whereNot($key, $operator = null, $value = null)
727
+	{
728
+		// If two params are given then assume operator is =
729
+		if (func_num_args() == 2) {
730
+			$value = $operator;
731
+			$operator = '=';
732
+		}
733
+		return $this->whereHandler($key, $operator, $value, 'AND NOT');
734
+	}
735
+
736
+	/**
737
+	 * @param $key
738
+	 * @param $operator
739
+	 * @param $value
740
+	 *
741
+	 * @return $this
742
+	 */
743
+	public function orWhereNot($key, $operator = null, $value = null)
744
+	{
745
+		// If two params are given then assume operator is =
746
+		if (func_num_args() == 2) {
747
+			$value = $operator;
748
+			$operator = '=';
749
+		}
750
+		return $this->whereHandler($key, $operator, $value, 'OR NOT');
751
+	}
752
+
753
+	/**
754
+	 * @param       $key
755
+	 * @param array $values
756
+	 *
757
+	 * @return $this
758
+	 */
759
+	public function whereIn($key, $values)
760
+	{
761
+		return $this->whereHandler($key, 'IN', $values, 'AND');
762
+	}
763
+
764
+	/**
765
+	 * @param       $key
766
+	 * @param array $values
767
+	 *
768
+	 * @return $this
769
+	 */
770
+	public function whereNotIn($key, $values)
771
+	{
772
+		return $this->whereHandler($key, 'NOT IN', $values, 'AND');
773
+	}
774
+
775
+	/**
776
+	 * @param       $key
777
+	 * @param array $values
778
+	 *
779
+	 * @return $this
780
+	 */
781
+	public function orWhereIn($key, $values)
782
+	{
783
+		return $this->whereHandler($key, 'IN', $values, 'OR');
784
+	}
785
+
786
+	/**
787
+	 * @param       $key
788
+	 * @param array $values
789
+	 *
790
+	 * @return $this
791
+	 */
792
+	public function orWhereNotIn($key, $values)
793
+	{
794
+		return $this->whereHandler($key, 'NOT IN', $values, 'OR');
795
+	}
796
+
797
+	/**
798
+	 * @param $key
799
+	 * @param $valueFrom
800
+	 * @param $valueTo
801
+	 *
802
+	 * @return $this
803
+	 */
804
+	public function whereBetween($key, $valueFrom, $valueTo)
805
+	{
806
+		return $this->whereHandler($key, 'BETWEEN', array($valueFrom, $valueTo), 'AND');
807
+	}
808
+
809
+	/**
810
+	 * @param $key
811
+	 * @param $valueFrom
812
+	 * @param $valueTo
813
+	 *
814
+	 * @return $this
815
+	 */
816
+	public function orWhereBetween($key, $valueFrom, $valueTo)
817
+	{
818
+		return $this->whereHandler($key, 'BETWEEN', array($valueFrom, $valueTo), 'OR');
819
+	}
820
+
821
+	/**
822
+	 * @param $key
823
+	 * @return QueryBuilderHandler
824
+	 */
825
+	public function whereNull($key)
826
+	{
827
+		return $this->whereNullHandler($key);
828
+	}
829
+
830
+	/**
831
+	 * @param $key
832
+	 * @return QueryBuilderHandler
833
+	 */
834
+	public function whereNotNull($key)
835
+	{
836
+		return $this->whereNullHandler($key, 'NOT');
837
+	}
838
+
839
+	/**
840
+	 * @param $key
841
+	 * @return QueryBuilderHandler
842
+	 */
843
+	public function orWhereNull($key)
844
+	{
845
+		return $this->whereNullHandler($key, '', 'or');
846
+	}
847
+
848
+	/**
849
+	 * @param $key
850
+	 * @return QueryBuilderHandler
851
+	 */
852
+	public function orWhereNotNull($key)
853
+	{
854
+		return $this->whereNullHandler($key, 'NOT', 'or');
855
+	}
856
+
857
+	protected function whereNullHandler($key, string $prefix = '', $operator = '')
858
+	{
859
+		$prefix = \strlen($prefix) === 0 ? '' : " {$prefix}";
860
+
861
+		$key = $this->adapterInstance->wrapSanitizer($this->addTablePrefix($key));
862
+		return $this->{$operator . 'Where'}($this->raw("{$key} IS{$prefix} NULL"));
863
+	}
864
+
865
+	/**
866
+	 * @param        $table
867
+	 * @param        $key
868
+	 * @param        $operator
869
+	 * @param        $value
870
+	 * @param string $type
871
+	 *
872
+	 * @return $this
873
+	 */
874
+	public function join($table, $key, $operator = null, $value = null, $type = 'inner')
875
+	{
876
+		if (!$key instanceof \Closure) {
877
+			$key = function ($joinBuilder) use ($key, $operator, $value) {
878
+				$joinBuilder->on($key, $operator, $value);
879
+			};
880
+		}
881
+
882
+		// Build a new JoinBuilder class, keep it by reference so any changes made
883
+		// in the closure should reflect here
884
+		$joinBuilder = $this->container->build(JoinBuilder::class, array($this->connection));
885
+		$joinBuilder = &$joinBuilder;
886
+		// Call the closure with our new joinBuilder object
887
+		$key($joinBuilder);
888
+		$table = $this->addTablePrefix($table, false);
889
+		// Get the criteria only query from the joinBuilder object
890
+		$this->statements['joins'][] = compact('type', 'table', 'joinBuilder');
891
+
892
+		return $this;
893
+	}
894
+
895
+	/**
896
+	 * Runs a transaction
897
+	 *
898
+	 * @param $callback
899
+	 *
900
+	 * @return $this
901
+	 */
902
+	public function transaction(\Closure $callback)
903
+	{
904
+		try {
905
+			// Begin the transaction
906
+			$this->dbInstance->query('START TRANSACTION');
907
+
908
+			// Get the Transaction class
909
+			$transaction = $this->container->build(Transaction::class, array($this->connection));
910
+
911
+			$this->handleTransactionCall($callback, $transaction);
912
+
913
+			// If no errors have been thrown or the transaction wasn't completed within
914
+			$this->dbInstance->query('COMMIT');
915
+
916
+			return $this;
917
+		} catch (TransactionHaltException $e) {
918
+			// Commit or rollback behavior has been handled in the closure, so exit
919
+			return $this;
920
+		} catch (\Exception $e) {
921
+			// something happened, rollback changes
922
+			$this->dbInstance->query('ROLLBACK');
923
+			return $this;
924
+		}
925
+	}
926
+
927
+	/**
928
+	 * Handles the transaction call.
929
+	 *
930
+	 * Catches any WP Errors (printed)
931
+	 *
932
+	 * @param callable    $callback
933
+	 * @param Transaction $transaction
934
+	 * @return void
935
+	 */
936
+	protected function handleTransactionCall(callable $callback, Transaction $transaction): void
937
+	{
938
+		try {
939
+			ob_start();
940
+			$callback($transaction);
941
+			$output = ob_get_clean();
942
+		} catch (\Throwable $th) {
943
+			ob_end_clean();
944
+			throw $th;
945
+		}
946
+
947
+		// If we caught an error, throw an exception.
948
+		if (\mb_strlen($output) !== 0) {
949
+			throw new Exception($output);
950
+		}
951
+	}
952
+
953
+	/**
954
+	 * @param      $table
955
+	 * @param      $key
956
+	 * @param null $operator
957
+	 * @param null $value
958
+	 *
959
+	 * @return $this
960
+	 */
961
+	public function leftJoin($table, $key, $operator = null, $value = null)
962
+	{
963
+		return $this->join($table, $key, $operator, $value, 'left');
964
+	}
965
+
966
+	/**
967
+	 * @param      $table
968
+	 * @param      $key
969
+	 * @param null $operator
970
+	 * @param null $value
971
+	 *
972
+	 * @return $this
973
+	 */
974
+	public function rightJoin($table, $key, $operator = null, $value = null)
975
+	{
976
+		return $this->join($table, $key, $operator, $value, 'right');
977
+	}
978
+
979
+	/**
980
+	 * @param      $table
981
+	 * @param      $key
982
+	 * @param null $operator
983
+	 * @param null $value
984
+	 *
985
+	 * @return $this
986
+	 */
987
+	public function innerJoin($table, $key, $operator = null, $value = null)
988
+	{
989
+		return $this->join($table, $key, $operator, $value, 'inner');
990
+	}
991
+
992
+	/**
993
+	 * @param string           $table
994
+	 * @param callable|string  $key
995
+	 * @param null|string      $operator
996
+	 * @param null|mixed       $value
997
+	 * @return this
998
+	 */
999
+	public function crossJoin($table, $key, $operator = null, $value = null)
1000
+	{
1001
+		return $this->join($table, $key, $operator, $value, 'cross');
1002
+	}
1003
+
1004
+	/**
1005
+	 * @param string           $table
1006
+	 * @param callable|string  $key
1007
+	 * @param null|string      $operator
1008
+	 * @param null|mixed       $value
1009
+	 * @return this
1010
+	 */
1011
+	public function outerJoin($table, $key, $operator = null, $value = null)
1012
+	{
1013
+		return $this->join($table, $key, $operator, $value, 'outer');
1014
+	}
1015
+
1016
+	/**
1017
+	 * Add a raw query
1018
+	 *
1019
+	 * @param $value
1020
+	 * @param $bindings
1021
+	 *
1022
+	 * @return mixed
1023
+	 */
1024
+	public function raw($value, $bindings = array())
1025
+	{
1026
+		return $this->container->build(Raw::class, array($value, $bindings));
1027
+	}
1028
+
1029
+	/**
1030
+	 * Return wpdb instance
1031
+	 *
1032
+	 * @return wpdb
1033
+	 */
1034
+	public function dbInstance(): \wpdb
1035
+	{
1036
+		return $this->dbInstance;
1037
+	}
1038
+
1039
+	/**
1040
+	 * @param Connection $connection
1041
+	 *
1042
+	 * @return $this
1043
+	 */
1044
+	public function setConnection(Connection $connection)
1045
+	{
1046
+		$this->connection = $connection;
1047
+		return $this;
1048
+	}
1049
+
1050
+	/**
1051
+	 * @return Connection
1052
+	 */
1053
+	public function getConnection()
1054
+	{
1055
+		return $this->connection;
1056
+	}
1057
+
1058
+	/**
1059
+	 * @param        $key
1060
+	 * @param        $operator
1061
+	 * @param        $value
1062
+	 * @param string $joiner
1063
+	 *
1064
+	 * @return $this
1065
+	 */
1066
+	protected function whereHandler($key, $operator = null, $value = null, $joiner = 'AND')
1067
+	{
1068
+		$key = $this->addTablePrefix($key);
1069
+		$this->statements['wheres'][] = compact('key', 'operator', 'value', 'joiner');
1070
+		return $this;
1071
+	}
1072
+
1073
+	/**
1074
+	 * Add table prefix (if given) on given string.
1075
+	 *
1076
+	 * @param string|string[]     $values
1077
+	 * @param bool $tableFieldMix If we have mixes of field and table names with a "."
1078
+	 *
1079
+	 * @return array|mixed
1080
+	 */
1081
+	public function addTablePrefix($values, $tableFieldMix = true)
1082
+	{
1083
+		if (is_null($this->tablePrefix)) {
1084
+			return $values;
1085
+		}
1086
+
1087
+		// $value will be an array and we will add prefix to all table names
1088
+
1089
+		// If supplied value is not an array then make it one
1090
+		$single = false;
1091
+		if (!is_array($values)) {
1092
+			$values = array($values);
1093
+			// We had single value, so should return a single value
1094
+			$single = true;
1095
+		}
1096
+
1097
+		$return = array();
1098
+
1099
+		foreach ($values as $key => $value) {
1100
+			// It's a raw query, just add it to our return array and continue next
1101
+			if ($value instanceof Raw || $value instanceof \Closure) {
1102
+				$return[$key] = $value;
1103
+				continue;
1104
+			}
1105
+
1106
+			// If key is not integer, it is likely a alias mapping,
1107
+			// so we need to change prefix target
1108
+			$target = &$value;
1109
+			if (!is_int($key)) {
1110
+				$target = &$key;
1111
+			}
1112
+
1113
+			if (!$tableFieldMix || ($tableFieldMix && strpos($target, '.') !== false)) {
1114
+				$target = $this->tablePrefix . $target;
1115
+			}
1116
+
1117
+			$return[$key] = $value;
1118
+		}
1119
+
1120
+		// If we had single value then we should return a single value (end value of the array)
1121
+		return $single ? end($return) : $return;
1122
+	}
1123
+
1124
+	/**
1125
+	 * @param $key
1126
+	 * @param $value
1127
+	 */
1128
+	protected function addStatement($key, $value)
1129
+	{
1130
+		if (!is_array($value)) {
1131
+			$value = array($value);
1132
+		}
1133
+
1134
+		if (!array_key_exists($key, $this->statements)) {
1135
+			$this->statements[$key] = $value;
1136
+		} else {
1137
+			$this->statements[$key] = array_merge($this->statements[$key], $value);
1138
+		}
1139
+	}
1140
+
1141
+	/**
1142
+	 * @param $event
1143
+	 * @param $table
1144
+	 *
1145
+	 * @return callable|null
1146
+	 */
1147
+	public function getEvent($event, $table = ':any')
1148
+	{
1149
+		return $this->connection->getEventHandler()->getEvent($event, $table);
1150
+	}
1151
+
1152
+	/**
1153
+	 * @param          $event
1154
+	 * @param string $table
1155
+	 * @param callable $action
1156
+	 *
1157
+	 * @return void
1158
+	 */
1159
+	public function registerEvent($event, $table, \Closure $action)
1160
+	{
1161
+		$table = $table ?: ':any';
1162
+
1163
+		if ($table != ':any') {
1164
+			$table = $this->addTablePrefix($table, false);
1165
+		}
1166
+
1167
+		return $this->connection->getEventHandler()->registerEvent($event, $table, $action);
1168
+	}
1169
+
1170
+	/**
1171
+	 * @param          $event
1172
+	 * @param string $table
1173
+	 *
1174
+	 * @return void
1175
+	 */
1176
+	public function removeEvent($event, $table = ':any')
1177
+	{
1178
+		if ($table != ':any') {
1179
+			$table = $this->addTablePrefix($table, false);
1180
+		}
1181
+
1182
+		return $this->connection->getEventHandler()->removeEvent($event, $table);
1183
+	}
1184
+
1185
+	/**
1186
+	 * @param      $event
1187
+	 * @return mixed
1188
+	 */
1189
+	public function fireEvents($event)
1190
+	{
1191
+		$params = func_get_args();
1192
+		array_unshift($params, $this);
1193
+		return call_user_func_array(array($this->connection->getEventHandler(), 'fireEvents'), $params);
1194
+	}
1195
+
1196
+	/**
1197
+	 * @return array
1198
+	 */
1199
+	public function getStatements()
1200
+	{
1201
+		return $this->statements;
1202
+	}
1203
+
1204
+	/**
1205
+	 * @return string will return WPDB Fetch mode
1206
+	 */
1207
+	public function getFetchMode()
1208
+	{
1209
+		return null !== $this->fetchMode
1210
+			? $this->fetchMode
1211
+			: \OBJECT;
1212
+	}
1213 1213
 }
Please login to merge, or discard this patch.
src/EventHandler.php 1 patch
Indentation   +80 added lines, -80 removed lines patch added patch discarded remove patch
@@ -5,94 +5,94 @@
 block discarded – undo
5 5
 
6 6
 class EventHandler
7 7
 {
8
-    /**
9
-     * @var array
10
-     */
11
-    protected $events = array();
8
+	/**
9
+	 * @var array
10
+	 */
11
+	protected $events = array();
12 12
 
13
-    /**
14
-     * @var array
15
-     */
16
-    protected $firedEvents = array();
13
+	/**
14
+	 * @var array
15
+	 */
16
+	protected $firedEvents = array();
17 17
 
18
-    /**
19
-     * @return array
20
-     */
21
-    public function getEvents()
22
-    {
23
-        return $this->events;
24
-    }
18
+	/**
19
+	 * @return array
20
+	 */
21
+	public function getEvents()
22
+	{
23
+		return $this->events;
24
+	}
25 25
 
26
-    /**
27
-     * @param $event
28
-     * @param $table
29
-     *
30
-     * @return callable|null
31
-     */
32
-    public function getEvent($event, $table = ':any')
33
-    {
34
-        if ($table instanceof Raw) {
35
-            return null;
36
-        }
37
-        return isset($this->events[$table][$event]) ? $this->events[$table][$event] : null;
38
-    }
26
+	/**
27
+	 * @param $event
28
+	 * @param $table
29
+	 *
30
+	 * @return callable|null
31
+	 */
32
+	public function getEvent($event, $table = ':any')
33
+	{
34
+		if ($table instanceof Raw) {
35
+			return null;
36
+		}
37
+		return isset($this->events[$table][$event]) ? $this->events[$table][$event] : null;
38
+	}
39 39
 
40
-    /**
41
-     * @param          $event
42
-     * @param string   $table
43
-     * @param callable $action
44
-     *
45
-     * @return void
46
-     */
47
-    public function registerEvent($event, $table, \Closure $action)
48
-    {
49
-        $table = $table ?: ':any';
40
+	/**
41
+	 * @param          $event
42
+	 * @param string   $table
43
+	 * @param callable $action
44
+	 *
45
+	 * @return void
46
+	 */
47
+	public function registerEvent($event, $table, \Closure $action)
48
+	{
49
+		$table = $table ?: ':any';
50 50
 
51
-        $this->events[$table][$event] = $action;
52
-    }
51
+		$this->events[$table][$event] = $action;
52
+	}
53 53
 
54
-    /**
55
-     * @param          $event
56
-     * @param string   $table
57
-     *
58
-     * @return void
59
-     */
60
-    public function removeEvent($event, $table = ':any')
61
-    {
62
-        unset($this->events[$table][$event]);
63
-    }
54
+	/**
55
+	 * @param          $event
56
+	 * @param string   $table
57
+	 *
58
+	 * @return void
59
+	 */
60
+	public function removeEvent($event, $table = ':any')
61
+	{
62
+		unset($this->events[$table][$event]);
63
+	}
64 64
 
65
-    /**
66
-     * @param QueryBuilderHandler $queryBuilder
67
-     * @param                     $event
68
-     * @return mixed
69
-     */
70
-    public function fireEvents($queryBuilder, $event)
71
-    {
72
-        $statements = $queryBuilder->getStatements();
73
-        $tables = isset($statements['tables']) ? $statements['tables'] : array();
65
+	/**
66
+	 * @param QueryBuilderHandler $queryBuilder
67
+	 * @param                     $event
68
+	 * @return mixed
69
+	 */
70
+	public function fireEvents($queryBuilder, $event)
71
+	{
72
+		$statements = $queryBuilder->getStatements();
73
+		$tables = isset($statements['tables']) ? $statements['tables'] : array();
74 74
 
75
-        // Events added with :any will be fired in case of any table,
76
-        // we are adding :any as a fake table at the beginning.
77
-        array_unshift($tables, ':any');
75
+		// Events added with :any will be fired in case of any table,
76
+		// we are adding :any as a fake table at the beginning.
77
+		array_unshift($tables, ':any');
78 78
 
79
-        // Fire all events
80
-        foreach ($tables as $table) {
81
-            // Fire before events for :any table
82
-            if ($action = $this->getEvent($event, $table)) {
83
-                // Make an event id, with event type and table
84
-                $eventId = $event . $table;
79
+		// Fire all events
80
+		foreach ($tables as $table) {
81
+			// Fire before events for :any table
82
+			if ($action = $this->getEvent($event, $table)) {
83
+				// Make an event id, with event type and table
84
+				$eventId = $event . $table;
85 85
 
86
-                // Fire event
87
-                $handlerParams = func_get_args();
88
-                unset($handlerParams[1]); // we do not need $event
89
-                // Add to fired list
90
-                $this->firedEvents[] = $eventId;
91
-                $result = call_user_func_array($action, $handlerParams);
92
-                if (!is_null($result)) {
93
-                    return $result;
94
-                };
95
-            }
96
-        }
97
-    }
86
+				// Fire event
87
+				$handlerParams = func_get_args();
88
+				unset($handlerParams[1]); // we do not need $event
89
+				// Add to fired list
90
+				$this->firedEvents[] = $eventId;
91
+				$result = call_user_func_array($action, $handlerParams);
92
+				if (!is_null($result)) {
93
+					return $result;
94
+				};
95
+			}
96
+		}
97
+	}
98 98
 }
Please login to merge, or discard this patch.
src/AliasFacade.php 1 patch
Indentation   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -12,32 +12,32 @@
 block discarded – undo
12 12
 class AliasFacade
13 13
 {
14 14
 
15
-    /**
16
-     * @var QueryBuilderHandler
17
-     */
18
-    protected static $queryBuilderInstance;
15
+	/**
16
+	 * @var QueryBuilderHandler
17
+	 */
18
+	protected static $queryBuilderInstance;
19 19
 
20
-    /**
21
-     * @param $method
22
-     * @param $args
23
-     *
24
-     * @return mixed
25
-     */
26
-    public static function __callStatic($method, $args)
27
-    {
28
-        if (!static::$queryBuilderInstance) {
29
-            static::$queryBuilderInstance = new QueryBuilderHandler();
30
-        }
20
+	/**
21
+	 * @param $method
22
+	 * @param $args
23
+	 *
24
+	 * @return mixed
25
+	 */
26
+	public static function __callStatic($method, $args)
27
+	{
28
+		if (!static::$queryBuilderInstance) {
29
+			static::$queryBuilderInstance = new QueryBuilderHandler();
30
+		}
31 31
 
32
-        // Call the non-static method from the class instance
33
-        return call_user_func_array(array(static::$queryBuilderInstance, $method), $args);
34
-    }
32
+		// Call the non-static method from the class instance
33
+		return call_user_func_array(array(static::$queryBuilderInstance, $method), $args);
34
+	}
35 35
 
36
-    /**
37
-     * @param QueryBuilderHandler $queryBuilderInstance
38
-     */
39
-    public static function setQueryBuilderInstance($queryBuilderInstance)
40
-    {
41
-        static::$queryBuilderInstance = $queryBuilderInstance;
42
-    }
36
+	/**
37
+	 * @param QueryBuilderHandler $queryBuilderInstance
38
+	 */
39
+	public static function setQueryBuilderInstance($queryBuilderInstance)
40
+	{
41
+		static::$queryBuilderInstance = $queryBuilderInstance;
42
+	}
43 43
 }
Please login to merge, or discard this patch.