Completed
Push — 2.x ( 09a4dc...f13b8e )
by Hari
01:28
created

Select::offset()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 9.6666
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 1
crap 2
1
<?php
2
/**
3
 *
4
 * This file is part of Aura for PHP.
5
 *
6
 * @license http://opensource.org/licenses/bsd-license.php BSD
7
 *
8
 */
9
namespace Aura\SqlQuery\Common;
10
11
use Aura\SqlQuery\AbstractQuery;
12
use Aura\SqlQuery\Exception;
13
14
/**
15
 *
16
 * An object for SELECT queries.
17
 *
18
 * @package Aura.SqlQuery
19
 *
20
 */
21
class Select extends AbstractQuery implements SelectInterface, SubselectInterface
22
{
23
    /**
24
     *
25
     * An array of union SELECT statements.
26
     *
27
     * @var array
28
     *
29
     */
30
    protected $union = array();
31
32
    /**
33
     *
34
     * Is this a SELECT FOR UPDATE?
35
     *
36
     * @var
37
     *
38
     */
39
    protected $for_update = false;
40
41
    /**
42
     *
43
     * The columns to be selected.
44
     *
45
     * @var array
46
     *
47
     */
48
    protected $cols = array();
49
50
    /**
51
     *
52
     * Select from these tables; includes JOIN clauses.
53
     *
54
     * @var array
55
     *
56
     */
57
    protected $from = array();
58
59
    /**
60
     *
61
     * The current key in the `$from` array.
62
     *
63
     * @var int
64
     *
65
     */
66
    protected $from_key = -1;
67
68
    /**
69
     *
70
     * Tracks which JOIN clauses are attached to which FROM tables.
71
     *
72
     * @var array
73
     *
74
     */
75
    protected $join = array();
76
77
    /**
78
     *
79
     * GROUP BY these columns.
80
     *
81
     * @var array
82
     *
83
     */
84
    protected $group_by = array();
85
86
    /**
87
     *
88
     * The list of HAVING conditions.
89
     *
90
     * @var array
91
     *
92
     */
93
    protected $having = array();
94
95
    /**
96
     *
97
     * The page number to select.
98
     *
99
     * @var int
100
     *
101
     */
102
    protected $page = 0;
103
104
    /**
105
     *
106
     * The number of rows per page.
107
     *
108
     * @var int
109
     *
110
     */
111
    protected $paging = 10;
112
113
    /**
114
     *
115
     * Tracks table references to avoid duplicate identifiers.
116
     *
117
     * @var array
118
     *
119
     */
120
    protected $table_refs = array();
121
122
    /**
123
     *
124
     * Returns this query object as an SQL statement string.
125
     *
126
     * @return string An SQL statement string.
127
     *
128
     */
129 184
    public function getStatement()
130
    {
131 184
        $union = '';
132 184
        if ($this->union) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->union of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
133 15
            $union = implode(PHP_EOL, $this->union) . PHP_EOL;
134
        }
135 184
        return $union . $this->build();
136
    }
137
138
    /**
139
     *
140
     * Sets the number of rows per page.
141
     *
142
     * @param int $paging The number of rows to page at.
143
     *
144
     * @return $this
145
     *
146
     */
147 10
    public function setPaging($paging)
148
    {
149 10
        $this->paging = (int) $paging;
150 10
        if ($this->page) {
151 5
            $this->setPagingLimitOffset();
152
        }
153 10
        return $this;
154
    }
155
156
    /**
157
     *
158
     * Gets the number of rows per page.
159
     *
160
     * @return int The number of rows per page.
161
     *
162
     */
163 10
    public function getPaging()
164
    {
165 10
        return $this->paging;
166
    }
167
168
    /**
169
     *
170
     * Makes the select FOR UPDATE (or not).
171
     *
172
     * @param bool $enable Whether or not the SELECT is FOR UPDATE (default
173
     * true).
174
     *
175
     * @return $this
176
     *
177
     */
178 20
    public function forUpdate($enable = true)
179
    {
180 20
        $this->for_update = (bool) $enable;
181 20
        return $this;
182
    }
183
184
    /**
185
     *
186
     * Makes the select DISTINCT (or not).
187
     *
188
     * @param bool $enable Whether or not the SELECT is DISTINCT (default
189
     * true).
190
     *
191
     * @return $this
192
     *
193
     */
194 16
    public function distinct($enable = true)
195
    {
196 16
        $this->setFlag('DISTINCT', $enable);
197 16
        return $this;
198
    }
199
200
    /**
201
     *
202
     * Adds columns to the query.
203
     *
204
     * Multiple calls to cols() will append to the list of columns, not
205
     * overwrite the previous columns.
206
     *
207
     * @param array $cols The column(s) to add to the query. The elements can be
208
     * any mix of these: `array("col", "col AS alias", "col" => "alias")`
209
     *
210
     * @return $this
211
     *
212
     */
213 224
    public function cols(array $cols)
214
    {
215 224
        foreach ($cols as $key => $val) {
216 224
            $this->addCol($key, $val);
217
        }
218 224
        return $this;
219
    }
220
221
    /**
222
     *
223
     * Adds a column and alias to the columns to be selected.
224
     *
225
     * @param mixed $key If an integer, ignored. Otherwise, the column to be
226
     * added.
227
     *
228
     * @param mixed $val If $key was an integer, the column to be added;
229
     * otherwise, the column alias.
230
     *
231
     * @return null
232
     *
233
     */
234 224
    protected function addCol($key, $val)
235
    {
236 224
        if (is_string($key)) {
237
            // [col => alias]
238 25
            $this->cols[$val] = $key;
239
        } else {
240 214
            $this->addColWithAlias($val);
241
        }
242 224
    }
243
244
    /**
245
     *
246
     * Adds a column with an alias to the columns to be selected.
247
     *
248
     * @param string $spec The column specification: "col alias",
249
     * "col AS alias", or something else entirely.
250
     *
251
     * @return null
252
     *
253
     */
254 214
    protected function addColWithAlias($spec)
255
    {
256 214
        $parts = explode(' ', $spec);
257 214
        $count = count($parts);
258 214
        if ($count == 2) {
259
            // "col alias"
260 5
            $this->cols[$parts[1]] = $parts[0];
261 214
        } elseif ($count == 3 && strtoupper($parts[1]) == 'AS') {
262
            // "col AS alias"
263 5
            $this->cols[$parts[2]] = $parts[0];
264
        } else {
265
            // no recognized alias
266 214
            $this->cols[] = $spec;
267
        }
268 214
    }
269
270
    /**
271
     *
272
     * Remove a column via its alias.
273
     *
274
     * @param string $alias The column to remove
275
     *
276
     * @return null
277
     *
278
     */
279 15
    public function removeCol($alias)
280
    {
281 15
        if (isset($this->cols[$alias])) {
282 5
            unset($this->cols[$alias]);
283
284 5
            return true;
285
        }
286
287 10
        $index = array_search($alias, $this->cols);
288 10
        if ($index !== false) {
289 5
            unset($this->cols[$index]);
290 5
            return true;
291
        }
292
293 5
        return false;
294
    }
295
296
    /**
297
     *
298
     * Does the query have any columns in it?
299
     *
300
     * @return bool
301
     *
302
     */
303 5
    public function hasCols()
304
    {
305 5
        return (bool) $this->cols;
306
    }
307
308
    /**
309
     *
310
     * Returns a list of columns.
311
     *
312
     * @return array
313
     *
314
     */
315 15
    public function getCols()
316
    {
317 15
        return $this->cols;
318
    }
319
320
    /**
321
     *
322
     * Tracks table references.
323
     *
324
     * @param string $type FROM, JOIN, etc.
325
     *
326
     * @param string $spec The table and alias name.
327
     *
328
     * @return null
329
     *
330
     * @throws Exception when the reference has already been used.
331
     *
332
     */
333 149
    protected function addTableRef($type, $spec)
334
    {
335 149
        $name = $spec;
336
337 149
        $pos = strripos($name, ' AS ');
338 149
        if ($pos !== false) {
339 35
            $name = trim(substr($name, $pos + 4));
340
        }
341
342 149
        if (isset($this->table_refs[$name])) {
343 25
            $used = $this->table_refs[$name];
344 25
            throw new Exception("Cannot reference '$type $spec' after '$used'");
345
        }
346
347 149
        $this->table_refs[$name] = "$type $spec";
348 149
    }
349
350
    /**
351
     *
352
     * Adds a FROM element to the query; quotes the table name automatically.
353
     *
354
     * @param string $spec The table specification; "foo" or "foo AS bar".
355
     *
356
     * @return $this
357
     *
358
     */
359 139
    public function from($spec)
360
    {
361 139
        $this->addTableRef('FROM', $spec);
362 139
        return $this->addFrom($this->quoter->quoteName($spec));
0 ignored issues
show
Bug introduced by
It seems like $this->quoter->quoteName($spec) targeting Aura\SqlQuery\Quoter::quoteName() can also be of type array; however, Aura\SqlQuery\Common\Select::addFrom() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
363
    }
364
365
    /**
366
     *
367
     * Adds a raw unquoted FROM element to the query; useful for adding FROM
368
     * elements that are functions.
369
     *
370
     * @param string $spec The table specification, e.g. "function_name()".
371
     *
372
     * @return $this
373
     *
374
     */
375 5
    public function fromRaw($spec)
376
    {
377 5
        $this->addTableRef('FROM', $spec);
378 5
        return $this->addFrom($spec);
379
    }
380
381
    /**
382
     *
383
     * Adds to the $from property and increments the key count.
384
     *
385
     * @param string $spec The table specification.
386
     *
387
     * @return $this
388
     *
389
     */
390 149
    protected function addFrom($spec)
391
    {
392 149
        $this->from[] = array($spec);
393 149
        $this->from_key ++;
394 149
        return $this;
395
    }
396
397
    /**
398
     *
399
     * Adds an aliased sub-select to the query.
400
     *
401
     * @param string|Select $spec If a Select object, use as the sub-select;
402
     * if a string, the sub-select string.
403
     *
404
     * @param string $name The alias name for the sub-select.
405
     *
406
     * @return $this
407
     *
408
     */
409 15
    public function fromSubSelect($spec, $name)
410
    {
411 15
        $this->addTableRef('FROM (SELECT ...) AS', $name);
412 10
        $spec = $this->subSelect($spec, '        ');
413 10
        $name = $this->quoter->quoteName($name);
414 10
        return $this->addFrom("({$spec}    ) AS $name");
415
    }
416
417
    /**
418
     *
419
     * Formats a sub-SELECT statement, binding values from a Select object as
420
     * needed.
421
     *
422
     * @param string|SelectInterface $spec A sub-SELECT specification.
423
     *
424
     * @param string $indent Indent each line with this string.
425
     *
426
     * @return string The sub-SELECT string.
427
     *
428
     */
429 25
    protected function subSelect($spec, $indent)
430
    {
431 25
        if ($spec instanceof SelectInterface) {
432 10
            $this->bindValues($spec->getBindValues());
433
        }
434
435 25
        return PHP_EOL . $indent
436 25
            . ltrim(preg_replace('/^/m', $indent, (string) $spec))
437 25
            . PHP_EOL;
438
    }
439
440
    /**
441
     *
442
     * Adds a JOIN table and columns to the query.
443
     *
444
     * @param string $join The join type: inner, left, natural, etc.
445
     *
446
     * @param string $spec The table specification; "foo" or "foo AS bar".
447
     *
448
     * @param string $cond Join on this condition.
449
     *
450
     * @param array $bind Values to bind to ?-placeholders in the condition.
451
     *
452
     * @return $this
453
     *
454
     * @throws Exception
455
     *
456
     */
457 45
    public function join($join, $spec, $cond = null, array $bind = array())
458
    {
459 45
        $join = strtoupper(ltrim("$join JOIN"));
460 45
        $this->addTableRef($join, $spec);
461
462 40
        $spec = $this->quoter->quoteName($spec);
463 40
        $cond = $this->fixJoinCondition($cond, $bind);
464 40
        return $this->addJoin(rtrim("$join $spec $cond"));
465
    }
466
467
    /**
468
     *
469
     * Fixes a JOIN condition to quote names in the condition and prefix it
470
     * with a condition type ('ON' is the default and 'USING' is recognized).
471
     *
472
     * @param string $cond Join on this condition.
473
     *
474
     * @param array $bind Values to bind to ?-placeholders in the condition.
475
     *
476
     * @return string
477
     *
478
     */
479 55
    protected function fixJoinCondition($cond, array $bind)
480
    {
481 55
        if (! $cond) {
482 25
            return;
483
        }
484
485 55
        $cond = $this->quoter->quoteNamesIn($cond);
486 55
        $cond = $this->rebuildCondAndBindValues($cond, $bind);
487
488 55
        if (strtoupper(substr(ltrim($cond), 0, 3)) == 'ON ') {
489 5
            return $cond;
490
        }
491
492 55
        if (strtoupper(substr(ltrim($cond), 0, 6)) == 'USING ') {
493 5
            return $cond;
494
        }
495
496 50
        return 'ON ' . $cond;
497
    }
498
499
    /**
500
     *
501
     * Adds a INNER JOIN table and columns to the query.
502
     *
503
     * @param string $spec The table specification; "foo" or "foo AS bar".
504
     *
505
     * @param string $cond Join on this condition.
506
     *
507
     * @param array $bind Values to bind to ?-placeholders in the condition.
508
     *
509
     * @return $this
510
     *
511
     * @throws Exception
512
     *
513
     */
514 10
    public function innerJoin($spec, $cond = null, array $bind = array())
515
    {
516 10
        return $this->join('INNER', $spec, $cond, $bind);
517
    }
518
519
    /**
520
     *
521
     * Adds a LEFT JOIN table and columns to the query.
522
     *
523
     * @param string $spec The table specification; "foo" or "foo AS bar".
524
     *
525
     * @param string $cond Join on this condition.
526
     *
527
     * @param array $bind Values to bind to ?-placeholders in the condition.
528
     *
529
     * @return $this
530
     *
531
     * @throws Exception
532
     *
533
     */
534 10
    public function leftJoin($spec, $cond = null, array $bind = array())
535
    {
536 10
        return $this->join('LEFT', $spec, $cond, $bind);
537
    }
538
539
    /**
540
     *
541
     * Adds a JOIN to an aliased subselect and columns to the query.
542
     *
543
     * @param string $join The join type: inner, left, natural, etc.
544
     *
545
     * @param string|Select $spec If a Select
546
     * object, use as the sub-select; if a string, the sub-select
547
     * command string.
548
     *
549
     * @param string $name The alias name for the sub-select.
550
     *
551
     * @param string $cond Join on this condition.
552
     *
553
     * @param array $bind Values to bind to ?-placeholders in the condition.
554
     *
555
     * @return $this
556
     *
557
     * @throws Exception
558
     *
559
     */
560 20
    public function joinSubSelect($join, $spec, $name, $cond = null, array $bind = array())
561
    {
562 20
        $join = strtoupper(ltrim("$join JOIN"));
563 20
        $this->addTableRef("$join (SELECT ...) AS", $name);
564
565 15
        $spec = $this->subSelect($spec, '            ');
566 15
        $name = $this->quoter->quoteName($name);
567 15
        $cond = $this->fixJoinCondition($cond, $bind);
568
569 15
        $text = rtrim("$join ($spec        ) AS $name $cond");
570 15
        return $this->addJoin('        ' . $text);
571
    }
572
573
    /**
574
     *
575
     * Adds the JOIN to the right place, given whether or not a FROM has been
576
     * specified yet.
577
     *
578
     * @param string $spec The JOIN clause.
579
     *
580
     * @return $this
581
     *
582
     */
583 55
    protected function addJoin($spec)
584
    {
585 55
        $from_key = ($this->from_key == -1) ? 0 : $this->from_key;
586 55
        $this->join[$from_key][] = $spec;
587 55
        return $this;
588
    }
589
590
    /**
591
     *
592
     * Adds grouping to the query.
593
     *
594
     * @param array $spec The column(s) to group by.
595
     *
596
     * @return $this
597
     *
598
     */
599 5
    public function groupBy(array $spec)
600
    {
601 5
        foreach ($spec as $col) {
602 5
            $this->group_by[] = $this->quoter->quoteNamesIn($col);
603
        }
604 5
        return $this;
605
    }
606
607
    /**
608
     *
609
     * Adds a HAVING condition to the query by AND. If the condition has
610
     * ?-placeholders, additional arguments to the method will be bound to
611
     * those placeholders sequentially.
612
     *
613
     * @param string $cond The HAVING condition.
614
     *
615
     * @return $this
616
     *
617
     */
618 10
    public function having($cond)
619
    {
620 10
        $this->addClauseCondWithBind('having', 'AND', func_get_args());
621 10
        return $this;
622
    }
623
624
    /**
625
     *
626
     * Adds a HAVING condition to the query by AND. If the condition has
627
     * ?-placeholders, additional arguments to the method will be bound to
628
     * those placeholders sequentially.
629
     *
630
     * @param string $cond The HAVING condition.
631
     *
632
     * @return $this
633
     *
634
     * @see having()
635
     *
636
     */
637 5
    public function orHaving($cond)
638
    {
639 5
        $this->addClauseCondWithBind('having', 'OR', func_get_args());
640 5
        return $this;
641
    }
642
643
    /**
644
     *
645
     * Sets the limit and count by page number.
646
     *
647
     * @param int $page Limit results to this page number.
648
     *
649
     * @return $this
650
     *
651
     */
652 25
    public function page($page)
653
    {
654 25
        $this->page = (int) $page;
655 25
        $this->setPagingLimitOffset();
656 25
        return $this;
657
    }
658
659
    /**
660
     *
661
     * Updates the limit and offset values when changing pagination.
662
     *
663
     * @return null
664
     *
665
     */
666 25
    protected function setPagingLimitOffset()
667
    {
668 25
        $this->limit  = 0;
669 25
        $this->offset = 0;
670 25
        if ($this->page) {
671 10
            $this->limit  = $this->paging;
672 10
            $this->offset = $this->paging * ($this->page - 1);
673
        }
674 25
    }
675
676
    /**
677
     *
678
     * Returns the page number being selected.
679
     *
680
     * @return int
681
     *
682
     */
683 5
    public function getPage()
684
    {
685 5
        return $this->page;
686
    }
687
688
    /**
689
     *
690
     * Takes the current select properties and retains them, then sets
691
     * UNION for the next set of properties.
692
     *
693
     * @return $this
694
     *
695
     */
696 10
    public function union()
697
    {
698 10
        $this->union[] = $this->build() . PHP_EOL . 'UNION';
699 10
        $this->reset();
700 10
        return $this;
701
    }
702
703
    /**
704
     *
705
     * Takes the current select properties and retains them, then sets
706
     * UNION ALL for the next set of properties.
707
     *
708
     * @return $this
709
     *
710
     */
711 5
    public function unionAll()
712
    {
713 5
        $this->union[] = $this->build() . PHP_EOL . 'UNION ALL';
714 5
        $this->reset();
715 5
        return $this;
716
    }
717
718
    /**
719
     *
720
     * Returns the LIMIT value.
721
     *
722
     * @return int
723
     *
724
     */
725 10
    public function getLimit()
726
    {
727 10
        return $this->limit;
728
    }
729
730
    /**
731
     *
732
     * Returns the OFFSET value.
733
     *
734
     * @return int
735
     *
736
     */
737 10
    public function getOffset()
738
    {
739 10
        return $this->offset;
740
    }
741
742
    /**
743
     *
744
     * Clears the current select properties; generally used after adding a
745
     * union.
746
     *
747
     * @return null
748
     *
749
     */
750 15
    protected function reset()
751
    {
752 15
        $this->resetFlags();
753 15
        $this->resetCols();
754 15
        $this->resetTables();
755 15
        $this->resetWhere();
756 15
        $this->resetGroupBy();
757 15
        $this->resetHaving();
758 15
        $this->resetOrderBy();
759 15
        $this->limit(0);
760 15
        $this->offset(0);
761 15
        $this->page(0);
762 15
        $this->forUpdate(false);
763 15
    }
764
765
    /**
766
     *
767
     * Resets the columns on the SELECT.
768
     *
769
     * @return $this
770
     *
771
     */
772 15
    public function resetCols()
773
    {
774 15
        $this->cols = array();
775 15
        return $this;
776
    }
777
778
    /**
779
     *
780
     * Resets the FROM and JOIN clauses on the SELECT.
781
     *
782
     * @return $this
783
     *
784
     */
785 15
    public function resetTables()
786
    {
787 15
        $this->from = array();
788 15
        $this->from_key = -1;
789 15
        $this->join = array();
790 15
        $this->table_refs = array();
791 15
        return $this;
792
    }
793
794
    /**
795
     *
796
     * Resets the WHERE clause on the SELECT.
797
     *
798
     * @return $this
799
     *
800
     */
801 15
    public function resetWhere()
802
    {
803 15
        $this->where = array();
804 15
        return $this;
805
    }
806
807
    /**
808
     *
809
     * Resets the GROUP BY clause on the SELECT.
810
     *
811
     * @return $this
812
     *
813
     */
814 15
    public function resetGroupBy()
815
    {
816 15
        $this->group_by = array();
817 15
        return $this;
818
    }
819
820
    /**
821
     *
822
     * Resets the HAVING clause on the SELECT.
823
     *
824
     * @return $this
825
     *
826
     */
827 15
    public function resetHaving()
828
    {
829 15
        $this->having = array();
830 15
        return $this;
831
    }
832
833
    /**
834
     *
835
     * Resets the ORDER BY clause on the SELECT.
836
     *
837
     * @return $this
838
     *
839
     */
840 15
    public function resetOrderBy()
841
    {
842 15
        $this->order_by = array();
843 15
        return $this;
844
    }
845
846
    /**
847
     *
848
     * Resets the UNION and UNION ALL clauses on the SELECT.
849
     *
850
     * @return $this
851
     *
852
     */
853
    public function resetUnions()
854
    {
855
        $this->union = array();
856
        return $this;
857
    }
858
859
    /**
860
     *
861
     * Builds this query object into a string.
862
     *
863
     * @return string
864
     *
865
     */
866 184
    protected function build()
867
    {
868
        return 'SELECT'
869 184
            . $this->buildFlags()
870 184
            . $this->buildCols()
871 179
            . $this->buildFrom() // includes JOIN
872 179
            . $this->buildWhere()
873 179
            . $this->buildGroupBy()
874 179
            . $this->buildHaving()
875 179
            . $this->buildOrderBy()
876 179
            . $this->buildLimit()
877 179
            . $this->buildForUpdate();
878
    }
879
880
    /**
881
     *
882
     * Builds the columns clause.
883
     *
884
     * @return string
885
     *
886
     * @throws Exception when there are no columns in the SELECT.
887
     *
888
     */
889 184
    protected function buildCols()
890
    {
891 184
        if (! $this->cols) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->cols of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
892 5
            throw new Exception('No columns in the SELECT.');
893
        }
894
895 179
        $cols = array();
896 179
        foreach ($this->cols as $key => $val) {
897 179
            if (is_int($key)) {
898 179
                $cols[] = $this->quoter->quoteNamesIn($val);
899
            } else {
900 179
                $cols[] = $this->quoter->quoteNamesIn("$val AS $key");
901
            }
902
        }
903
904 179
        return $this->indentCsv($cols);
905
    }
906
907
    /**
908
     *
909
     * Builds the FROM clause.
910
     *
911
     * @return string
912
     *
913
     */
914 179
    protected function buildFrom()
915
    {
916 179
        if (! $this->from) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->from of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
917 60
            return ''; // not applicable
918
        }
919
920 119
        $refs = array();
921 119
        foreach ($this->from as $from_key => $from) {
922 119
            if (isset($this->join[$from_key])) {
923 55
                $from = array_merge($from, $this->join[$from_key]);
924
            }
925 119
            $refs[] = implode(PHP_EOL, $from);
926
        }
927 119
        return PHP_EOL . 'FROM' . $this->indentCsv($refs);
928
    }
929
930
    /**
931
     *
932
     * Builds the GROUP BY clause.
933
     *
934
     * @return string
935
     *
936
     */
937 179
    protected function buildGroupBy()
938
    {
939 179
        if (! $this->group_by) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->group_by of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
940 174
            return ''; // not applicable
941
        }
942
943 5
        return PHP_EOL . 'GROUP BY' . $this->indentCsv($this->group_by);
944
    }
945
946
    /**
947
     *
948
     * Builds the HAVING clause.
949
     *
950
     * @return string
951
     *
952
     */
953 179
    protected function buildHaving()
954
    {
955 179
        if (! $this->having) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->having of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
956 164
            return ''; // not applicable
957
        }
958
959 15
        return PHP_EOL . 'HAVING' . $this->indent($this->having);
960
    }
961
962
    /**
963
     *
964
     * Builds the FOR UPDATE clause.
965
     *
966
     * @return string
967
     *
968
     */
969 179
    protected function buildForUpdate()
970
    {
971 179
        if (! $this->for_update) {
972 174
            return ''; // not applicable
973
        }
974
975 5
        return PHP_EOL . 'FOR UPDATE';
976
    }
977
978
    /**
979
     *
980
     * Adds a WHERE condition to the query by AND. If the condition has
981
     * ?-placeholders, additional arguments to the method will be bound to
982
     * those placeholders sequentially.
983
     *
984
     * @param string $cond The WHERE condition.
985
     * @param mixed ...$bind arguments to bind to placeholders
986
     *
987
     * @return $this
988
     *
989
     */
990 30
    public function where($cond)
991
    {
992 30
        $this->addWhere('AND', func_get_args());
993 30
        return $this;
994
    }
995
996
    /**
997
     *
998
     * Adds a WHERE condition to the query by OR. If the condition has
999
     * ?-placeholders, additional arguments to the method will be bound to
1000
     * those placeholders sequentially.
1001
     *
1002
     * @param string $cond The WHERE condition.
1003
     * @param mixed ...$bind arguments to bind to placeholders
1004
     *
1005
     * @return $this
1006
     *
1007
     * @see where()
1008
     *
1009
     */
1010 5
    public function orWhere($cond)
1011
    {
1012 5
        $this->addWhere('OR', func_get_args());
1013 5
        return $this;
1014
    }
1015
1016
    /**
1017
     *
1018
     * Sets a limit count on the query.
1019
     *
1020
     * @param int $limit The number of rows to select.
1021
     *
1022
     * @return $this
1023
     *
1024
     */
1025 30
    public function limit($limit)
1026
    {
1027 30
        $this->limit = (int) $limit;
1028 30
        if ($this->page) {
1029 5
            $this->page = 0;
1030 5
            $this->offset = 0;
1031
        }
1032 30
        return $this;
1033
    }
1034
1035
    /**
1036
     *
1037
     * Sets a limit offset on the query.
1038
     *
1039
     * @param int $offset Start returning after this many rows.
1040
     *
1041
     * @return $this
1042
     *
1043
     */
1044 30
    public function offset($offset)
1045
    {
1046 30
        $this->offset = (int) $offset;
1047 30
        if ($this->page) {
1048 5
            $this->page = 0;
1049 5
            $this->limit = 0;
1050
        }
1051 30
        return $this;
1052
    }
1053
1054
    /**
1055
     *
1056
     * Adds a column order to the query.
1057
     *
1058
     * @param array $spec The columns and direction to order by.
1059
     *
1060
     * @return $this
1061
     *
1062
     */
1063 5
    public function orderBy(array $spec)
1064
    {
1065 5
        return $this->addOrderBy($spec);
1066
    }
1067
}
1068