1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file is part of the miBadger package. |
5
|
|
|
* |
6
|
|
|
* @author Michael Webbers <[email protected]> |
7
|
|
|
* @license http://opensource.org/licenses/Apache-2.0 Apache v2 License |
8
|
|
|
* @version 1.0.0 |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace miBadger\Query; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* The query builder class. |
15
|
|
|
* |
16
|
|
|
* @since 1.0.0 |
17
|
|
|
*/ |
18
|
|
|
class QueryBuilder implements QueryInterface |
19
|
|
|
{ |
20
|
|
|
/* @var string The modifier. SELECT, INSERT INTO, UPDATE or DELETE */ |
21
|
|
|
private $modifier; |
22
|
|
|
|
23
|
|
|
/* @var string The table name. */ |
24
|
|
|
private $table; |
25
|
|
|
|
26
|
|
|
/* @var array The columns. */ |
27
|
|
|
private $columns; |
28
|
|
|
|
29
|
|
|
/* @var array The values. */ |
30
|
|
|
private $values; |
31
|
|
|
|
32
|
|
|
/* @var array The join conditions. */ |
33
|
|
|
private $join; |
34
|
|
|
|
35
|
|
|
/* @var array The where conditions. */ |
36
|
|
|
private $where; |
37
|
|
|
|
38
|
|
|
/* @var array The group by conditions. */ |
39
|
|
|
private $groupBy; |
40
|
|
|
|
41
|
|
|
/* @var array The order by conditions. */ |
42
|
|
|
private $orderBy; |
43
|
|
|
|
44
|
|
|
/* @var string The limit. */ |
45
|
|
|
private $limit; |
46
|
|
|
|
47
|
|
|
/* @var string The offset. */ |
48
|
|
|
private $offset; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Construct a query builder object with the given table. |
52
|
|
|
* |
53
|
|
|
* @param string $table |
54
|
|
|
*/ |
55
|
45 |
|
public function __construct($table) |
56
|
|
|
{ |
57
|
45 |
|
$this->table = $table; |
58
|
45 |
|
$this->join = []; |
59
|
45 |
|
$this->where = []; |
60
|
45 |
|
$this->groupBy = []; |
61
|
45 |
|
$this->orderBy = []; |
62
|
45 |
|
} |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* Returns a string representation of the query object. |
66
|
|
|
* |
67
|
|
|
* @return string a string representation of the query object. |
68
|
|
|
*/ |
69
|
45 |
|
public function __toString() |
70
|
|
|
{ |
71
|
45 |
|
switch ($this->modifier) { |
72
|
45 |
|
case self::SELECT: |
73
|
33 |
|
return $this->getSelectQuery(); |
74
|
|
|
|
75
|
12 |
|
case self::INSERT: |
76
|
3 |
|
return $this->getInsertQuery(); |
77
|
|
|
|
78
|
9 |
|
case self::UPDATE: |
79
|
4 |
|
return $this->getUpdateQuery(); |
80
|
|
|
|
81
|
5 |
|
case self::DELETE: |
82
|
3 |
|
return $this->getDeleteQuery(); |
83
|
|
|
|
84
|
2 |
|
default: |
85
|
2 |
|
return ''; |
86
|
2 |
|
} |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* {@inheritdoc} |
91
|
|
|
*/ |
92
|
33 |
|
public function select($columns = ['*']) |
93
|
|
|
{ |
94
|
33 |
|
$this->columns = is_array($columns) ? $columns : func_get_args(); |
95
|
33 |
|
$this->modifier = self::SELECT; |
96
|
|
|
|
97
|
33 |
|
return $this; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Returns the select clause. |
102
|
|
|
* |
103
|
|
|
* @return string the select clause. |
104
|
|
|
*/ |
105
|
33 |
|
private function getSelectClause() |
106
|
|
|
{ |
107
|
33 |
|
return sprintf('SELECT %s FROM %s', implode(', ', $this->columns), $this->table); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* Returns the select query. |
112
|
|
|
* |
113
|
|
|
* @return string the select query. |
114
|
|
|
*/ |
115
|
33 |
|
private function getSelectQuery() |
116
|
|
|
{ |
117
|
33 |
|
$result = $this->getSelectClause(); |
118
|
|
|
|
119
|
33 |
|
if ($join = $this->getJoinClause()) { |
120
|
8 |
|
$result .= ' ' . $join; |
121
|
8 |
|
} |
122
|
|
|
|
123
|
33 |
|
if ($where = $this->getWhereClause()) { |
124
|
9 |
|
$result .= ' ' . $where; |
125
|
9 |
|
} |
126
|
|
|
|
127
|
33 |
|
if ($groupBy = $this->getGroupByClause()) { |
128
|
2 |
|
$result .= ' ' . $groupBy; |
129
|
2 |
|
} |
130
|
|
|
|
131
|
33 |
|
if ($orderBy = $this->getOrderByClause()) { |
132
|
4 |
|
$result .= ' ' . $orderBy; |
133
|
4 |
|
} |
134
|
|
|
|
135
|
33 |
|
if ($limit = $this->getLimitClause()) { |
136
|
4 |
|
$result .= ' ' . $limit; |
137
|
4 |
|
} |
138
|
|
|
|
139
|
33 |
|
if ($offset = $this->getOffsetClause()) { |
140
|
2 |
|
$result .= ' ' . $offset; |
141
|
2 |
|
} |
142
|
|
|
|
143
|
33 |
|
return $result; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* {@inheritdoc} |
148
|
|
|
*/ |
149
|
3 |
|
public function insert(array $values) |
150
|
|
|
{ |
151
|
3 |
|
$this->values = $values; |
152
|
3 |
|
$this->modifier = self::INSERT; |
153
|
|
|
|
154
|
3 |
|
return $this; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
/** |
158
|
|
|
* Returns the insert clause. |
159
|
|
|
* |
160
|
|
|
* @return string the insert clause. |
161
|
|
|
*/ |
162
|
3 |
|
private function getInsertClause() |
163
|
|
|
{ |
164
|
3 |
|
$columns = []; |
165
|
3 |
|
$values = []; |
166
|
|
|
|
167
|
3 |
|
foreach ($this->values as $key => $value) { |
168
|
3 |
|
$columns[] = $key; |
169
|
3 |
|
$values[] = sprintf('%s', $value); |
170
|
3 |
|
} |
171
|
|
|
|
172
|
3 |
|
return sprintf('INSERT INTO %s (%s) VALUES (%s)', $this->table, implode(', ', $columns), implode(', ', $values)); |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Returns the insert query. |
177
|
|
|
* |
178
|
|
|
* @return string the insert query. |
179
|
|
|
*/ |
180
|
3 |
|
private function getInsertQuery() |
181
|
|
|
{ |
182
|
3 |
|
return $this->getInsertClause(); |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
/** |
186
|
|
|
* {@inheritdoc} |
187
|
|
|
*/ |
188
|
4 |
|
public function update(array $values) |
189
|
|
|
{ |
190
|
4 |
|
$this->values = $values; |
191
|
4 |
|
$this->modifier = self::UPDATE; |
192
|
|
|
|
193
|
4 |
|
return $this; |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* Returns the update clause. |
198
|
|
|
* |
199
|
|
|
* @return string the update clause. |
200
|
|
|
*/ |
201
|
4 |
|
private function getUpdateClause() |
202
|
|
|
{ |
203
|
4 |
|
$placeholders = []; |
204
|
|
|
|
205
|
4 |
|
foreach ($this->values as $key => $value) { |
206
|
4 |
|
$placeholders[] = sprintf('%s = %s', $key, $value); |
207
|
4 |
|
} |
208
|
|
|
|
209
|
4 |
|
return sprintf('UPDATE %s SET %s', $this->table, implode(', ', $placeholders)); |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* Returns the update query. |
214
|
|
|
* |
215
|
|
|
* @return string the update query. |
216
|
|
|
*/ |
217
|
4 |
View Code Duplication |
private function getUpdateQuery() |
|
|
|
|
218
|
|
|
{ |
219
|
4 |
|
$result = $this->getUpdateClause(); |
220
|
|
|
|
221
|
4 |
|
if ($where = $this->getWhereClause()) { |
222
|
4 |
|
$result .= ' ' . $where; |
223
|
4 |
|
} |
224
|
|
|
|
225
|
4 |
|
if ($limit = $this->getLimitClause()) { |
226
|
1 |
|
$result .= ' ' . $limit; |
227
|
1 |
|
} |
228
|
|
|
|
229
|
4 |
|
return $result; |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* {@inheritdoc} |
234
|
|
|
*/ |
235
|
3 |
|
public function delete() |
236
|
|
|
{ |
237
|
3 |
|
$this->modifier = self::DELETE; |
238
|
|
|
|
239
|
3 |
|
return $this; |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
/** |
243
|
|
|
* Returns the delete clause. |
244
|
|
|
* |
245
|
|
|
* @return string the delete clause. |
246
|
|
|
*/ |
247
|
3 |
|
private function getDeleteClause() |
248
|
|
|
{ |
249
|
3 |
|
return sprintf('DELETE FROM %s', $this->table); |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* Returns the delete query. |
254
|
|
|
* |
255
|
|
|
* @return string the delete query. |
256
|
|
|
*/ |
257
|
3 |
View Code Duplication |
private function getDeleteQuery() |
|
|
|
|
258
|
|
|
{ |
259
|
|
|
|
260
|
3 |
|
$result = $this->getDeleteClause(); |
261
|
|
|
|
262
|
3 |
|
if ($where = $this->getWhereClause()) { |
263
|
2 |
|
$result .= ' ' . $where; |
264
|
2 |
|
} |
265
|
|
|
|
266
|
3 |
|
if ($limit = $this->getLimitClause()) { |
267
|
1 |
|
$result .= ' ' . $limit; |
268
|
1 |
|
} |
269
|
|
|
|
270
|
3 |
|
return $result; |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
/** |
274
|
|
|
* {@inheritdoc} |
275
|
|
|
*/ |
276
|
2 |
|
public function join($table, $primary, $operator, $secondary) |
277
|
|
|
{ |
278
|
2 |
|
$this->join[] = ['INNER JOIN', $table, $primary, $operator, $secondary]; |
279
|
|
|
|
280
|
2 |
|
return $this; |
281
|
|
|
} |
282
|
|
|
|
283
|
|
|
/** |
284
|
|
|
* {@inheritdoc} |
285
|
|
|
*/ |
286
|
2 |
|
public function leftJoin($table, $primary, $operator, $secondary) |
287
|
|
|
{ |
288
|
2 |
|
$this->join[] = ['LEFT JOIN', $table, $primary, $operator, $secondary]; |
289
|
|
|
|
290
|
2 |
|
return $this; |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
/** |
294
|
|
|
* {@inheritdoc} |
295
|
|
|
*/ |
296
|
2 |
|
public function rightJoin($table, $primary, $operator, $secondary) |
297
|
|
|
{ |
298
|
2 |
|
$this->join[] = ['RIGHT JOIN', $table, $primary, $operator, $secondary]; |
299
|
|
|
|
300
|
2 |
|
return $this; |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
/** |
304
|
|
|
* {@inheritdoc} |
305
|
|
|
*/ |
306
|
2 |
|
public function crossJoin($table, $primary, $operator, $secondary) |
307
|
|
|
{ |
308
|
2 |
|
$this->join[] = ['CROSS JOIN', $table, $primary, $operator, $secondary]; |
309
|
|
|
|
310
|
2 |
|
return $this; |
311
|
|
|
} |
312
|
|
|
|
313
|
33 |
|
private function getJoinClause() |
314
|
|
|
{ |
315
|
33 |
|
$result = []; |
316
|
|
|
|
317
|
33 |
|
foreach ($this->join as $key => $value) { |
318
|
8 |
|
$result[] = sprintf('%s %s ON %s %s %s', $value[0], $value[1], $value[2], $value[3], $value[4]); |
319
|
33 |
|
} |
320
|
|
|
|
321
|
33 |
|
return implode(' ', $result); |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
/** |
325
|
|
|
* {@inheritdoc} |
326
|
|
|
*/ |
327
|
15 |
|
public function where($column, $operator, $value) |
328
|
|
|
{ |
329
|
15 |
|
$this->where[] = [$column, $operator, $value]; |
330
|
|
|
|
331
|
15 |
|
return $this; |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
/** |
335
|
|
|
* Returns the where clause. |
336
|
|
|
* |
337
|
|
|
* @return string the where clause. |
338
|
|
|
*/ |
339
|
40 |
|
private function getWhereClause() |
340
|
|
|
{ |
341
|
40 |
|
if (empty($this->where)) { |
342
|
25 |
|
return ''; |
343
|
|
|
} |
344
|
|
|
|
345
|
15 |
|
$result = []; |
346
|
|
|
|
347
|
15 |
|
foreach ($this->where as $key => $value) { |
348
|
15 |
|
$result[] = $this->getWhereCondition($value[0], $value[1], $value[2]); |
349
|
15 |
|
} |
350
|
|
|
|
351
|
15 |
|
return sprintf('WHERE %s', implode(' AND ', $result)); |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
/** |
355
|
|
|
* Returns the where condition. |
356
|
|
|
* |
357
|
|
|
* @param string $column |
358
|
|
|
* @param string $operator |
359
|
|
|
* @param mixed $value |
360
|
|
|
* @return string the where condition. |
361
|
|
|
*/ |
362
|
15 |
|
private function getWhereCondition($column, $operator, $value) |
363
|
|
|
{ |
364
|
15 |
|
if ($operator == 'IN') { |
365
|
3 |
|
return sprintf('%s IN (%s)', $column, is_array($value) ? implode(', ', $value) : $value); |
366
|
|
|
} else { |
367
|
12 |
|
return sprintf('%s %s %s', $column, $operator, $value); |
368
|
|
|
} |
369
|
|
|
} |
370
|
|
|
|
371
|
|
|
/** |
372
|
|
|
* {@inheritdoc} |
373
|
|
|
*/ |
374
|
2 |
|
public function groupBy($column) |
375
|
|
|
{ |
376
|
2 |
|
$this->groupBy[] = $column; |
377
|
|
|
|
378
|
2 |
|
return $this; |
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
/** |
382
|
|
|
* Returns the group by clause. |
383
|
|
|
* |
384
|
|
|
* @return string the group by clause. |
385
|
|
|
*/ |
386
|
33 |
|
private function getGroupByClause() |
387
|
|
|
{ |
388
|
33 |
|
if (empty($this->groupBy)) { |
389
|
31 |
|
return ''; |
390
|
|
|
} |
391
|
|
|
|
392
|
2 |
|
return sprintf('GROUP BY %s', implode(', ', $this->groupBy)); |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
/** |
396
|
|
|
* {@inheritdoc} |
397
|
|
|
*/ |
398
|
4 |
|
public function orderBy($column, $order = null) |
399
|
|
|
{ |
400
|
4 |
|
if (strcasecmp($order, 'asc') == 0) { |
401
|
1 |
|
$column .= ' ASC'; |
402
|
4 |
|
} elseif(strcasecmp($order, 'desc') == 0) { |
403
|
2 |
|
$column .= ' DESC'; |
404
|
2 |
|
} |
405
|
|
|
|
406
|
4 |
|
$this->orderBy[] = $column; |
407
|
|
|
|
408
|
4 |
|
return $this; |
409
|
|
|
} |
410
|
|
|
|
411
|
|
|
/** |
412
|
|
|
* Returns the order by clause. |
413
|
|
|
* |
414
|
|
|
* @return string the order by clause. |
415
|
|
|
*/ |
416
|
33 |
|
private function getOrderByClause() |
417
|
|
|
{ |
418
|
33 |
|
if (empty($this->orderBy)) { |
419
|
29 |
|
return ''; |
420
|
|
|
} |
421
|
|
|
|
422
|
4 |
|
return sprintf('ORDER BY %s', implode(', ', $this->orderBy)); |
423
|
|
|
} |
424
|
|
|
|
425
|
|
|
/** |
426
|
|
|
* {@inheritdoc} |
427
|
|
|
*/ |
428
|
6 |
|
public function limit($limit) |
429
|
|
|
{ |
430
|
6 |
|
$this->limit = $limit; |
431
|
|
|
|
432
|
6 |
|
return $this; |
433
|
|
|
} |
434
|
|
|
|
435
|
|
|
/** |
436
|
|
|
* Returns the limit clause. |
437
|
|
|
* |
438
|
|
|
* @return string the limit clause. |
439
|
|
|
*/ |
440
|
40 |
|
private function getLimitClause() |
441
|
|
|
{ |
442
|
40 |
|
if (!$this->limit) { |
443
|
34 |
|
return ''; |
444
|
|
|
} |
445
|
|
|
|
446
|
6 |
|
return sprintf('LIMIT %s', $this->limit); |
447
|
|
|
} |
448
|
|
|
|
449
|
|
|
/** |
450
|
|
|
* {@inheritdoc} |
451
|
|
|
*/ |
452
|
2 |
|
public function offset($offset) |
453
|
|
|
{ |
454
|
2 |
|
$this->offset = $offset; |
455
|
|
|
|
456
|
2 |
|
return $this; |
457
|
|
|
} |
458
|
|
|
|
459
|
|
|
/** |
460
|
|
|
* Returns the offset clause. |
461
|
|
|
* |
462
|
|
|
* @return string the offset clause. |
463
|
|
|
*/ |
464
|
33 |
|
private function getOffsetClause() |
465
|
|
|
{ |
466
|
33 |
|
if (!$this->limit || !$this->offset) { |
467
|
31 |
|
return ''; |
468
|
|
|
} |
469
|
|
|
|
470
|
2 |
|
return sprintf('OFFSET %s', $this->offset); |
471
|
|
|
} |
472
|
|
|
} |
473
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.