Passed
Push — 1.0.0-dev ( 29a38b...3f14f3 )
by nguereza
02:39
created

getWhereStrIfOperatorIsArray()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 1
Metric Value
cc 4
eloc 9
nc 4
nop 4
dl 0
loc 13
rs 9.9666
c 1
b 1
f 1
1
<?php
2
    defined('ROOT_PATH') || exit('Access denied');
3
    /**
4
     * TNH Framework
5
     *
6
     * A simple PHP framework using HMVC architecture
7
     *
8
     * This content is released under the MIT License (MIT)
9
     *
10
     * Copyright (c) 2017 TNH Framework
11
     *
12
     * Permission is hereby granted, free of charge, to any person obtaining a copy
13
     * of this software and associated documentation files (the "Software"), to deal
14
     * in the Software without restriction, including without limitation the rights
15
     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
     * copies of the Software, and to permit persons to whom the Software is
17
     * furnished to do so, subject to the following conditions:
18
     *
19
     * The above copyright notice and this permission notice shall be included in all
20
     * copies or substantial portions of the Software.
21
     *
22
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
     * SOFTWARE.
29
     */
30
    
31
    class DatabaseQueryBuilder {
32
33
         /**
34
         * The DatabaseConnection instance
35
         * @var object
36
         */
37
        private $connection = null;
38
39
        /**
40
         * The SQL SELECT statment
41
         * @var string
42
         */
43
        private $select = '*';
44
  	
45
        /**
46
         * The SQL FROM statment
47
         * @var string
48
         */
49
        private $from = null;
50
  	
51
        /**
52
         * The SQL WHERE statment
53
         * @var string
54
         */
55
        private $where = null;
56
  	
57
        /**
58
         * The SQL LIMIT statment
59
         * @var string
60
         */
61
        private $limit = null;
62
  	
63
        /**
64
         * The SQL JOIN statment
65
         * @var string
66
         */
67
        private $join = null;
68
  	
69
        /**
70
         * The SQL ORDER BY statment
71
         * @var string
72
         */
73
        private $orderBy = null;
74
  	
75
        /**
76
         * The SQL GROUP BY statment
77
         * @var string
78
         */
79
        private $groupBy = null;
80
  	
81
        /**
82
         * The SQL HAVING statment
83
         * @var string
84
         */
85
        private $having = null;
86
  	
87
        /**
88
         * The full SQL query statment after build for each command
89
         * @var string
90
         */
91
        private $query = null;
92
  	
93
        /**
94
         * The list of SQL valid operators
95
         * @var array
96
         */
97
        private $operatorList = array('=', '!=', '<', '>', '<=', '>=', '<>');
98
  	
99
        /**
100
         * Construct new DatabaseQueryBuilder
101
         * @param object $connection the DatabaseConnection object
102
         */
103
        public function __construct(DatabaseConnection $connection = null) {
104
            if ($connection !== null) {
105
                $this->connection = $connection;
106
            }
107
        }
108
109
        /**
110
         * Set the SQL FROM statment
111
         * @param  string|array $table the table name or array of table list
112
         * @return object        the current DatabaseQueryBuilder instance
113
         */
114
        public function from($table) {
115
            $prefix = $this->connection->getPrefix();
116
            if (is_array($table)) {
117
                $froms = '';
118
                foreach ($table as $key) {
119
                    $froms .= $prefix . $key . ', ';
120
                }
121
                $this->from = rtrim($froms, ', ');
122
            } else {
123
                $this->from = $prefix . $table;
124
            }
125
            return $this;
126
        }
127
128
        /**
129
         * Set the SQL SELECT statment
130
         * @param  string|array $fields the field name or array of field list
131
         * @return object        the current DatabaseQueryBuilder instance
132
         */
133
        public function select($fields) {
134
            $select = $fields;
135
            if (is_array($fields)) {
136
                $select = implode(', ', $fields);
137
            }
138
            return $this->setSelectStr($select);
0 ignored issues
show
Bug introduced by
It seems like $select can also be of type array; however, parameter $newSelect of DatabaseQueryBuilder::setSelectStr() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

138
            return $this->setSelectStr(/** @scrutinizer ignore-type */ $select);
Loading history...
139
        }
140
141
        /**
142
         * Set the SQL SELECT DISTINCT statment
143
         * @param  string $field the field name to distinct
144
         * @return object        the current DatabaseQueryBuilder instance
145
         */
146
        public function distinct($field) {
147
            return $this->setSelectStr('DISTINCT ' . $field);
148
        }
149
150
        /**
151
         * Set the SQL function COUNT in SELECT statment
152
         * @param  string $field the field name
153
         * @param  string $name  if is not null represent the alias used for this field in the result
154
         * @return object        the current DatabaseQueryBuilder instance
155
         */
156
        public function count($field = '*', $name = null) {
157
            return $this->select_min_max_sum_count_avg('COUNT', $field, $name);
158
        }
159
    
160
        /**
161
         * Set the SQL function MIN in SELECT statment
162
         * @param  string $field the field name
163
         * @param  string $name  if is not null represent the alias used for this field in the result
164
         * @return object        the current DatabaseQueryBuilder instance
165
         */
166
        public function min($field, $name = null) {
167
            return $this->select_min_max_sum_count_avg('MIN', $field, $name);
168
        }
169
170
        /**
171
         * Set the SQL function MAX in SELECT statment
172
         * @param  string $field the field name
173
         * @param  string $name  if is not null represent the alias used for this field in the result
174
         * @return object        the current DatabaseQueryBuilder instance
175
         */
176
        public function max($field, $name = null) {
177
            return $this->select_min_max_sum_count_avg('MAX', $field, $name);
178
        }
179
180
        /**
181
         * Set the SQL function SUM in SELECT statment
182
         * @param  string $field the field name
183
         * @param  string $name  if is not null represent the alias used for this field in the result
184
         * @return object        the current DatabaseQueryBuilder instance
185
         */
186
        public function sum($field, $name = null) {
187
            return $this->select_min_max_sum_count_avg('SUM', $field, $name);
188
        }
189
190
        /**
191
         * Set the SQL function AVG in SELECT statment
192
         * @param  string $field the field name
193
         * @param  string $name  if is not null represent the alias used for this field in the result
194
         * @return object        the current DatabaseQueryBuilder instance
195
         */
196
        public function avg($field, $name = null) {
197
            return $this->select_min_max_sum_count_avg('AVG', $field, $name);
198
        }
199
200
        /**
201
         * Set the SQL JOIN statment
202
         * @param  string $table  the join table name
203
         * @param  string $field1 the first field for join conditions	
204
         * @param  string $op     the join condition operator. If is null the default will be "="
205
         * @param  string $field2 the second field for join conditions
206
         * @param  string $type   the type of join (INNER, LEFT, RIGHT)
207
         * @return object        the current DatabaseQueryBuilder instance
208
         */
209
        public function join($table, $field1 = null, $op = null, $field2 = null, $type = '') {
210
            $on = $field1;
211
            $prefix = $this->connection->getPrefix();
212
            $table = $prefix . $table;
213
            if (!is_null($op)) {
214
                $on = $prefix . $field1 . ' ' . $op . ' ' . $prefix . $field2;
215
                if (!in_array($op, $this->operatorList)) {
216
                    $on = $prefix . $field1 . ' = ' . $prefix . $op;
217
                }
218
            }
219
            if (empty($this->join)) {
220
                $this->join = $type . 'JOIN' . ' ' . $table . ' ON ' . $on;
221
            } else {
222
                $this->join = $this->join . ' ' . $type . 'JOIN' . ' ' . $table . ' ON ' . $on;
223
            }
224
            return $this;
225
        }
226
227
        /**
228
         * Set the SQL INNER JOIN statment
229
         * @see  DatabaseQueryBuilder::join()
230
         * @return object        the current DatabaseQueryBuilder instance
231
         */
232
        public function innerJoin($table, $field1, $op = null, $field2 = '') {
233
            return $this->join($table, $field1, $op, $field2, 'INNER ');
234
        }
235
236
        /**
237
         * Set the SQL LEFT JOIN statment
238
         * @see  DatabaseQueryBuilder::join()
239
         * @return object        the current DatabaseQueryBuilder instance
240
         */
241
        public function leftJoin($table, $field1, $op = null, $field2 = '') {
242
            return $this->join($table, $field1, $op, $field2, 'LEFT ');
243
        }
244
245
        /**
246
         * Set the SQL RIGHT JOIN statment
247
         * @see  DatabaseQueryBuilder::join()
248
         * @return object        the current DatabaseQueryBuilder instance
249
         */
250
        public function rightJoin($table, $field1, $op = null, $field2 = '') {
251
            return $this->join($table, $field1, $op, $field2, 'RIGHT ');
252
        }
253
254
        /**
255
         * Set the SQL FULL OUTER JOIN statment
256
         * @see  DatabaseQueryBuilder::join()
257
         * @return object        the current DatabaseQueryBuilder instance
258
         */
259
        public function fullOuterJoin($table, $field1, $op = null, $field2 = '') {
260
            return $this->join($table, $field1, $op, $field2, 'FULL OUTER ');
261
        }
262
263
        /**
264
         * Set the SQL LEFT OUTER JOIN statment
265
         * @see  DatabaseQueryBuilder::join()
266
         * @return object        the current DatabaseQueryBuilder instance
267
         */
268
        public function leftOuterJoin($table, $field1, $op = null, $field2 = '') {
269
            return $this->join($table, $field1, $op, $field2, 'LEFT OUTER ');
270
        }
271
272
        /**
273
         * Set the SQL RIGHT OUTER JOIN statment
274
         * @see  DatabaseQueryBuilder::join()
275
         * @return object        the current DatabaseQueryBuilder instance
276
         */
277
        public function rightOuterJoin($table, $field1, $op = null, $field2 = '') {
278
            return $this->join($table, $field1, $op, $field2, 'RIGHT OUTER ');
279
        }
280
281
        /**
282
         * Set the SQL WHERE CLAUSE for IS NULL
283
         * @see  DatabaseQueryBuilder::whereIsNullAndNotNull
284
         */
285
        public function whereIsNull($field, $andOr = 'AND') {
286
            return $this->whereIsNullAndNotNull($field, $andOr, 'IS NULL');
287
        }
288
289
        /**
290
         * Set the SQL WHERE CLAUSE for IS NOT NULL
291
         * @see  DatabaseQueryBuilder::whereIsNullAndNotNull
292
         */
293
        public function whereIsNotNull($field, $andOr = 'AND') {
294
            return $this->whereIsNullAndNotNull($field, $andOr, 'IS NOT NULL');
295
        }
296
    
297
        /**
298
         * Set the SQL WHERE CLAUSE statment
299
         * @param  string|array  $where the where field or array of field list
300
         * @param  array|string  $op     the condition operator. If is null the default will be "="
301
         * @param  mixed  $val    the where value
302
         * @param  string  $type   the type used for this where clause (NOT, etc.)
303
         * @param  string  $andOr the separator type used 'AND', 'OR', etc.
304
         * @param  boolean $escape whether to escape or not the $val
305
         * @return object        the current DatabaseQueryBuilder instance
306
         */
307
        public function where($where, $op = null, $val = null, $type = '', $andOr = 'AND', $escape = true) {
308
            $whereStr = '';
309
            if (is_array($where)) {
310
                $whereStr = $this->getWhereStrIfIsArray($where, $type, $andOr, $escape);
311
            } else {
312
                if (is_array($op)) {
313
                    $whereStr = $this->getWhereStrIfOperatorIsArray($where, $op, $type, $escape);
314
                } else {
315
                    $whereStr = $this->getWhereStrForOperator($where, $op, $val, $type, $escape);
316
                }
317
            }
318
            $this->setWhereStr($whereStr, $andOr);
319
            return $this;
320
        }
321
322
        /**
323
         * Set the SQL WHERE CLAUSE statment using OR
324
         * @see  DatabaseQueryBuilder::where()
325
         * @return object        the current DatabaseQueryBuilder instance
326
         */
327
        public function orWhere($where, $op = null, $val = null, $escape = true) {
328
            return $this->where($where, $op, $val, '', 'OR', $escape);
329
        }
330
331
        /**
332
         * Set the SQL WHERE CLAUSE statment using AND and NOT
333
         * @see  DatabaseQueryBuilder::where()
334
         * @return object        the current DatabaseQueryBuilder instance
335
         */
336
        public function notWhere($where, $op = null, $val = null, $escape = true) {
337
            return $this->where($where, $op, $val, 'NOT ', 'AND', $escape);
338
        }
339
340
        /**
341
         * Set the SQL WHERE CLAUSE statment using OR and NOT
342
         * @see  DatabaseQueryBuilder::where()
343
         * @return object        the current DatabaseQueryBuilder instance
344
         */
345
        public function orNotWhere($where, $op = null, $val = null, $escape = true) {
346
            return $this->where($where, $op, $val, 'NOT ', 'OR', $escape);
347
        }
348
349
        /**
350
         * Set the opened parenthesis for the complex SQL query
351
         * @param  string $type   the type of this grouped (NOT, etc.)
352
         * @param  string $andOr the multiple conditions separator (AND, OR, etc.)
353
         * @return object        the current DatabaseQueryBuilder instance
354
         */
355
        public function groupStart($type = '', $andOr = ' AND') {
356
            if (empty($this->where)) {
357
                $this->where = $type . '(';
358
            } else {
359
                if (substr(trim($this->where), -1) == '(') {
360
                    $this->where .= $type . '(';
361
                } else {
362
                    $this->where .= $andOr . $type . ' (';
363
                }
364
            }
365
            return $this;
366
        }
367
368
        /**
369
         * Set the opened parenthesis for the complex SQL query using NOT type
370
         * @see  DatabaseQueryBuilder::groupStart()
371
         * @return object        the current DatabaseQueryBuilder instance
372
         */
373
        public function notGroupStart() {
374
            return $this->groupStart(' NOT');
375
        }
376
377
        /**
378
         * Set the opened parenthesis for the complex SQL query using OR for separator
379
         * @see  DatabaseQueryBuilder::groupStart()
380
         * @return object        the current DatabaseQueryBuilder instance
381
         */
382
        public function orGroupStart() {
383
            return $this->groupStart('', ' OR');
384
        }
385
386
        /**
387
         * Set the opened parenthesis for the complex SQL query using OR for separator and NOT for type
388
         * @see  DatabaseQueryBuilder::groupStart()
389
         * @return object        the current DatabaseQueryBuilder instance
390
         */
391
        public function orNotGroupStart() {
392
            return $this->groupStart('NOT', ' OR');
393
        }
394
395
        /**
396
         * Close the parenthesis for the grouped SQL
397
         * @return object        the current DatabaseQueryBuilder instance
398
         */
399
        public function groupEnd() {
400
            $this->where .= ')';
401
            return $this;
402
        }
403
404
        /**
405
         * Set the SQL WHERE CLAUSE statment for IN
406
         * @param  string  $field  the field name for IN statment
407
         * @param  array   $keys   the list of values used
408
         * @param  string  $type   the condition separator type (NOT)
409
         * @param  string  $andOr the multiple conditions separator (OR, AND)
410
         * @param  boolean $escape whether to escape or not the values
411
         * @return object        the current DatabaseQueryBuilder instance
412
         */
413
        public function in($field, array $keys, $type = '', $andOr = 'AND', $escape = true) {
414
            $_keys = array();
415
            foreach ($keys as $k => $v) {
416
                $v = $this->checkForNullValue($v);
417
                if (! is_numeric($v)) {
418
                    $v = $this->connection->escape($v, $escape);
419
                }
420
                $_keys[] = $v;
421
            }
422
            $keys = implode(', ', $_keys);
423
            $whereStr = $field . $type . ' IN (' . $keys . ')';
424
            $this->setWhereStr($whereStr, $andOr);
425
            return $this;
426
        }
427
428
        /**
429
         * Set the SQL WHERE CLAUSE statment for NOT IN with AND separator
430
         * @see  DatabaseQueryBuilder::in()
431
         * @return object        the current DatabaseQueryBuilder instance
432
         */
433
        public function notIn($field, array $keys, $escape = true) {
434
            return $this->in($field, $keys, ' NOT', 'AND', $escape);
435
        }
436
437
        /**
438
         * Set the SQL WHERE CLAUSE statment for IN with OR separator
439
         * @see  DatabaseQueryBuilder::in()
440
         * @return object        the current DatabaseQueryBuilder instance
441
         */
442
        public function orIn($field, array $keys, $escape = true) {
443
            return $this->in($field, $keys, '', 'OR', $escape);
444
        }
445
446
        /**
447
         * Set the SQL WHERE CLAUSE statment for NOT IN with OR separator
448
         * @see  DatabaseQueryBuilder::in()
449
         * @return object        the current DatabaseQueryBuilder instance
450
         */
451
        public function orNotIn($field, array $keys, $escape = true) {
452
            return $this->in($field, $keys, ' NOT', 'OR', $escape);
453
        }
454
455
        /**
456
         * Set the SQL WHERE CLAUSE statment for BETWEEN
457
         * @param  string  $field  the field used for the BETWEEN statment
458
         * @param  mixed  $value1 the BETWEEN begin value
459
         * @param  mixed  $value2 the BETWEEN end value
460
         * @param  string  $type   the condition separator type (NOT)
461
         * @param  string  $andOr the multiple conditions separator (OR, AND)
462
         * @param  boolean $escape whether to escape or not the values
463
         * @return object        the current DatabaseQueryBuilder instance
464
         */
465
        public function between($field, $value1, $value2, $type = '', $andOr = 'AND', $escape = true) {
466
            $value1 = $this->checkForNullValue($value1);
467
            $value2 = $this->checkForNullValue($value2);
468
            $whereStr = $field . $type . ' BETWEEN ' . $this->connection->escape($value1, $escape) . ' AND ' . $this->connection->escape($value2, $escape);
469
            $this->setWhereStr($whereStr, $andOr);
470
            return $this;
471
        }
472
473
        /**
474
         * Set the SQL WHERE CLAUSE statment for BETWEEN with NOT type and AND separator
475
         * @see  DatabaseQueryBuilder::between()
476
         * @return object        the current DatabaseQueryBuilder instance
477
         */
478
        public function notBetween($field, $value1, $value2, $escape = true) {
479
            return $this->between($field, $value1, $value2, ' NOT', 'AND', $escape);
480
        }
481
482
        /**
483
         * Set the SQL WHERE CLAUSE statment for BETWEEN with OR separator
484
         * @see  DatabaseQueryBuilder::between()
485
         * @return object        the current DatabaseQueryBuilder instance
486
         */
487
        public function orBetween($field, $value1, $value2, $escape = true) {
488
            return $this->between($field, $value1, $value2, '', 'OR', $escape);
489
        }
490
491
        /**
492
         * Set the SQL WHERE CLAUSE statment for BETWEEN with NOT type and OR separator
493
         * @see  DatabaseQueryBuilder::between()
494
         * @return object        the current DatabaseQueryBuilder instance
495
         */
496
        public function orNotBetween($field, $value1, $value2, $escape = true) {
497
            return $this->between($field, $value1, $value2, ' NOT', 'OR', $escape);
498
        }
499
500
        /**
501
         * Set the SQL WHERE CLAUSE statment for LIKE
502
         * @param  string  $field  the field name used in LIKE statment
503
         * @param  string  $data   the LIKE value for this field including the '%', and '_' part
504
         * @param  string  $type   the condition separator type (NOT)
505
         * @param  string  $andOr the multiple conditions separator (OR, AND)
506
         * @param  boolean $escape whether to escape or not the values
507
         * @return object        the current DatabaseQueryBuilder instance
508
         */
509
        public function like($field, $data, $type = '', $andOr = 'AND', $escape = true) {
510
            $data = $this->checkForNullValue($data);
511
            $this->setWhereStr($field . $type . ' LIKE ' . ($this->connection->escape($data, $escape)), $andOr);
512
            return $this;
513
        }
514
515
        /**
516
         * Set the SQL WHERE CLAUSE statment for LIKE with OR separator
517
         * @see  DatabaseQueryBuilder::like()
518
         * @return object        the current DatabaseQueryBuilder instance
519
         */
520
        public function orLike($field, $data, $escape = true) {
521
            return $this->like($field, $data, '', 'OR', $escape);
522
        }
523
524
        /**
525
         * Set the SQL WHERE CLAUSE statment for LIKE with NOT type and AND separator
526
         * @see  DatabaseQueryBuilder::like()
527
         * @return object        the current DatabaseQueryBuilder instance
528
         */
529
        public function notLike($field, $data, $escape = true) {
530
            return $this->like($field, $data, ' NOT', 'AND', $escape);
531
        }
532
533
        /**
534
         * Set the SQL WHERE CLAUSE statment for LIKE with NOT type and OR separator
535
         * @see  DatabaseQueryBuilder::like()
536
         * @return object        the current DatabaseQueryBuilder instance
537
         */
538
        public function orNotLike($field, $data, $escape = true) {
539
            return $this->like($field, $data, ' NOT', 'OR', $escape);
540
        }
541
542
        /**
543
         * Set the SQL LIMIT statment
544
         * @param  int $limit    the limit offset. If $limitEnd is null this will be the limit count
545
         * like LIMIT n;
546
         * @param  int $limitEnd the limit count
547
         * @return object        the current DatabaseQueryBuilder instance
548
         */
549
        public function limit($limit, $limitEnd = null) {
550
            if (empty($limit)) {
551
                $limit = 0;
552
            }
553
            if (!is_null($limitEnd)) {
554
                $this->limit = $limit . ', ' . $limitEnd;
555
            } else {
556
                $this->limit = $limit;
557
            }
558
            return $this;
559
        }
560
561
        /**
562
         * Set the SQL ORDER BY CLAUSE statment
563
         * @param  string $orderBy   the field name used for order
564
         * @param  string $orderDir the order direction (ASC or DESC)
565
         * @return object        the current DatabaseQueryBuilder instance
566
         */
567
        public function orderBy($orderBy, $orderDir = 'ASC') {
568
            if (stristr($orderBy, ' ') || $orderBy == 'rand()') {
569
                $this->orderBy = empty($this->orderBy) ? $orderBy : $this->orderBy . ', ' . $orderBy;
570
            } else {
571
                $this->orderBy = empty($this->orderBy) 
572
                            ? ($orderBy . ' ' . strtoupper($orderDir)) 
573
                            : $this->orderBy . ', ' . $orderBy . ' ' . strtoupper($orderDir);
574
            }
575
            return $this;
576
        }
577
578
        /**
579
         * Set the SQL GROUP BY CLAUSE statment
580
         * @param  string|array $field the field name used or array of field list
581
         * @return object        the current DatabaseQueryBuilder instance
582
         */
583
        public function groupBy($field) {
584
            $groupBy = $field;
585
            if (is_array($field)) {
586
                $groupBy = implode(', ', $field);
587
            } 
588
            $this->groupBy = $groupBy;
0 ignored issues
show
Documentation Bug introduced by
It seems like $groupBy can also be of type array. However, the property $groupBy is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
589
            return $this;
590
        }
591
592
        /**
593
         * Set the SQL HAVING CLAUSE statment
594
         * @param  string  $field  the field name used for HAVING statment
595
         * @param  string|array  $op     the operator used or array
596
         * @param  mixed  $val    the value for HAVING comparaison
597
         * @param  boolean $escape whether to escape or not the values
598
         * @return object        the current DatabaseQueryBuilder instance
599
         */
600
        public function having($field, $op = null, $val = null, $escape = true) {
601
            if (is_array($op)) {
602
                $this->having = $this->getHavingStrIfOperatorIsArray($field, $op, $escape);
603
            } else if (!in_array($op, $this->operatorList)) {
604
                $op = $this->checkForNullValue($op);
605
                $this->having = $field . ' > ' . ($this->connection->escape($op, $escape));
606
            } else {
607
                $val = $this->checkForNullValue($val);
608
                $this->having = $field . ' ' . $op . ' ' . ($this->connection->escape($val, $escape));
609
            }
610
            return $this;
611
        }
612
613
        /**
614
         * Insert new record in the database
615
         * @param  array   $data   the record data
616
         * @param  boolean $escape  whether to escape or not the values
617
         * @return object  the current DatabaseQueryBuilder instance        
618
         */
619
        public function insert($data = array(), $escape = true) {
620
            $columns = array_keys($data);
621
            $column = implode(', ', $columns);
622
            $values = implode(', ', ($escape ? array_map(array($this->connection, 'escape'), $data) : $data));
623
624
            $this->query = 'INSERT INTO ' . $this->from . '(' . $column . ') VALUES (' . $values . ')';
625
            return $this;
626
        }
627
628
        /**
629
         * Update record in the database
630
         * @param  array   $data   the record data if is empty will use the $this->data array.
631
         * @param  boolean $escape  whether to escape or not the values
632
         * @return object  the current DatabaseQueryBuilder instance 
633
         */
634
        public function update($data = array(), $escape = true) {
635
            $query = 'UPDATE ' . $this->from . ' SET ';
636
            $values = array();
637
            foreach ($data as $column => $val) {
638
                $values[] = $column . ' = ' . ($this->connection->escape($val, $escape));
639
            }
640
            $query .= implode(', ', $values);
641
            $query .= $this->buildQueryPart('where', ' WHERE ');
642
            $query .= $this->buildQueryPart('orderBy', ' ORDER BY ');
643
            $query .= $this->buildQueryPart('limit', ' LIMIT ');
644
645
            $this->query = $query;
646
            return $this;
647
        }
648
649
        /**
650
         * Delete the record in database
651
         * @return object  the current DatabaseQueryBuilder instance 
652
         */
653
        public function delete() {
654
            $query = 'DELETE FROM ' . $this->from;
655
            $isTruncate = $query;
656
            $query .= $this->buildQueryPart('where', ' WHERE ');
657
            $query .= $this->buildQueryPart('orderBy', ' ORDER BY ');
658
            $query .= $this->buildQueryPart('limit', ' LIMIT ');
659
660
            if ($isTruncate == $query && $this->connection->getDriver() != 'sqlite') {  
661
                $query = 'TRUNCATE TABLE ' . $this->from;
662
            }
663
            $this->query = $query;
664
            return $this;
665
        }
666
667
        /**
668
         * Return the current SQL query string
669
         * @return string
670
         */
671
        public function getQuery() {
672
            //INSERT, UPDATE, DELETE already set it, if is SELECT we need set it now
673
            if (empty($this->query)) {
674
                $query = 'SELECT ' . $this->select . ' FROM ' . $this->from;
675
                $query .= $this->buildQueryPart('join', ' ');
676
                $query .= $this->buildQueryPart('where', ' WHERE ');
677
                $query .= $this->buildQueryPart('groupBy', ' GROUP BY ');
678
                $query .= $this->buildQueryPart('having', ' HAVING ');
679
                $query .= $this->buildQueryPart('orderBy', ' ORDER BY ');
680
                $query .= $this->buildQueryPart('limit', ' LIMIT ');
681
                $this->query = trim($query);
682
            }
683
            return $this->query;
684
        }
685
	
686
        /**
687
         * Reset the DatabaseQueryBuilder class attributs to the initial values before each query.
688
         * @return object  the current DatabaseQueryBuilder instance 
689
         */
690
        public function reset() {
691
            $this->select   = '*';
692
            $this->from     = null;
693
            $this->where    = null;
694
            $this->limit    = null;
695
            $this->orderBy  = null;
696
            $this->groupBy  = null;
697
            $this->having   = null;
698
            $this->join     = null;
699
            $this->query    = null;
700
            return $this;
701
        }
702
703
        /**
704
         * Return the DatabaseConnection instance
705
         * @return object DatabaseConnection
706
         */
707
        public function getConnection() {
708
            return $this->connection;
709
        }
710
711
        /**
712
         * Set the DatabaseConnection instance
713
         * @param object DatabaseConnection $connection the DatabaseConnection object
714
         *
715
         * @return object the current instance
716
         */
717
        public function setConnection(DatabaseConnection $connection) {
718
            $this->connection = $connection;
719
            return $this;
720
        }
721
722
723
        /**
724
         * Build the part of SQL query
725
         * @param  string $property the name of this class attribute, use after $this->
726
         * @param  string $command  the SQL command like WHERE, HAVING, etc.
727
         * 
728
         * @return string|null
729
         */
730
         protected function buildQueryPart($property, $command = ''){
731
            if (!empty($this->{$property})) {
732
                return $command . $this->{$property};
733
            }
734
            return null;
735
         }
736
737
738
        /**
739
         * Set the SQL WHERE CLAUSE for IS NULL ad IS NOT NULL
740
         * @param  string|array $field  the field name or array of field list
741
         * @param  string $andOr the separator type used 'AND', 'OR', etc.
742
         * @param string $clause the clause type "IS NULL", "IS NOT NULLs"
743
         * @return object        the current DatabaseQueryBuilder instance
744
         */
745
        protected function whereIsNullAndNotNull($field, $andOr = 'AND', $clause = 'IS NULL'){
746
            if (is_array($field)) {
747
                foreach ($field as $f) {
748
                    $this->whereIsNullAndNotNull($f, $andOr, $clause);
749
                }
750
            } else {
751
                $this->setWhereStr($field . ' ' . $clause, $andOr);
752
            }
753
            return $this;
754
        }
755
756
757
        /**
758
         * Set the value for SELECT command and update it if already exists
759
         * @param string $newSelect the new value to set
760
         *
761
         * @return object the current instance
762
         */
763
        protected function setSelectStr($newSelect){
764
            $this->select = (($this->select == '*' || empty($this->select)) 
765
                                    ? $newSelect 
766
                                    : $this->select . ', ' . $newSelect);
767
            return $this;
768
        }
769
770
        /**
771
         * Check if the value is null will return an empty string
772
         * to prevent have error like field1 =  ANd field2 = 'foo'
773
         * @param  string|null $value the value to check
774
         * @return string        the empty string if the value is null
775
         * otherwise the same value will be returned
776
         */
777
        protected function checkForNullValue($value){
778
            if(is_null($value)){
779
                return '';
780
            }
781
            return $value;
782
        }
783
784
        /**
785
         * Get the SQL HAVING clause when operator argument is an array
786
         * @see DatabaseQueryBuilder::having
787
         *
788
         * @return string
789
         */
790
        protected function getHavingStrIfOperatorIsArray($field, $op = null, $escape = true) {
791
            $x = explode('?', $field);
792
            $w = '';
793
            foreach ($x as $k => $v) {
794
                if (!empty($v)) {
795
                    if (!isset($op[$k])) {
796
                        $op[$k] = '';
797
                    }
798
                    $value = '';
799
                    if (isset($op[$k])) {
800
                        $value = $this->connection->escape($op[$k], $escape);
801
                    }
802
                    $w .= $v . $value;
803
                }
804
            }
805
            return $w;
806
        }
807
808
        /**
809
         * Get the SQL WHERE clause using array column => value
810
         * @see DatabaseQueryBuilder::where
811
         *
812
         * @return string
813
         */
814
        protected function getWhereStrIfIsArray(array $where, $type = '', $andOr = 'AND', $escape = true) {
815
            $_where = array();
816
            foreach ($where as $column => $data) {
817
                $data = $this->checkForNullValue($data);
818
                $_where[] = $type . $column . ' = ' . ($this->connection->escape($data, $escape));
819
            }
820
            $where = implode(' ' . $andOr . ' ', $_where);
821
            return $where;
822
        }
823
824
        /**
825
         * Get the SQL WHERE clause when operator argument is an array
826
         * @see DatabaseQueryBuilder::where
827
         *
828
         * @return string
829
         */
830
        protected function getWhereStrIfOperatorIsArray($where, array $op, $type = '', $escape = true) {
831
            $x = explode('?', $where);
832
            $w = '';
833
            foreach ($x as $k => $v) {
834
                if (!empty($v)) {
835
                    $value = '';
836
                    if (isset($op[$k])) {
837
                        $value = $this->connection->escape($op[$k], $escape);
838
                    }
839
                    $w .= $type . $v . $value;
840
                }
841
            }
842
            return $w;
843
        }
844
845
        /**
846
         * Get the default SQL WHERE clause using operator = or the operator argument
847
         * @see DatabaseQueryBuilder::where
848
         *
849
         * @return string
850
         */
851
        protected function getWhereStrForOperator($where, $op = null, $val = null, $type = '', $escape = true) {
852
            $w = '';
853
            if (!in_array((string) $op, $this->operatorList)) {
854
                $op = $this->checkForNullValue($op);
855
                $w = $type . $where . ' = ' . ($this->connection->escape($op, $escape));
856
            } else {
857
                $val = $this->checkForNullValue($val);
858
                $w = $type . $where . ' ' . $op . ' ' . ($this->connection->escape($val, $escape));
859
            }
860
            return $w;
861
        }
862
863
        /**
864
         * Set the $this->where property 
865
         * @param string $whereStr the WHERE clause string
866
         * @param  string  $andOr the separator type used 'AND', 'OR', etc.
867
         */
868
        protected function setWhereStr($whereStr, $andOr = 'AND') {
869
            if (empty($this->where)) {
870
                $this->where = $whereStr;
871
            } else {
872
                if (substr(trim($this->where), -1) == '(') {
873
                    $this->where = $this->where . $whereStr;
874
                } else {
875
                    $this->where = $this->where . ' ' . $andOr . ' ' . $whereStr;
876
                }
877
            }
878
        }
879
880
        /**
881
         * Set the SQL SELECT for function MIN, MAX, SUM, AVG, COUNT, AVG
882
         * @param  string $clause the clause type like MIN, MAX, etc.
883
         * @see  DatabaseQueryBuilder::min
884
         * @see  DatabaseQueryBuilder::max
885
         * @see  DatabaseQueryBuilder::sum
886
         * @see  DatabaseQueryBuilder::count
887
         * @see  DatabaseQueryBuilder::avg
888
         * @return object
889
         */
890
        protected function select_min_max_sum_count_avg($clause, $field, $name = null) {
891
            $clause = strtoupper($clause);
892
            $func = $clause . '(' . $field . ')' . (!is_null($name) ? ' AS ' . $name : '');
893
            return $this->setSelectStr($func);
894
        }
895
}
896