Where::between()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
dl 0
loc 7
c 1
b 0
f 1
rs 9.4286
cc 1
eloc 4
nc 1
nop 3
1
<?php
2
/**
3
 * Author: Nil Portugués Calderó <[email protected]>
4
 * Date: 6/3/14
5
 * Time: 12:07 AM.
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace NilPortugues\Sql\QueryBuilder\Syntax;
12
13
use NilPortugues\Sql\QueryBuilder\Manipulation\QueryInterface;
14
use NilPortugues\Sql\QueryBuilder\Manipulation\QueryException;
15
use NilPortugues\Sql\QueryBuilder\Manipulation\QueryFactory;
16
use NilPortugues\Sql\QueryBuilder\Manipulation\Select;
17
18
/**
19
 * Class Where.
20
 */
21
class Where
22
{
23
    const OPERATOR_GREATER_THAN_OR_EQUAL = '>=';
24
    const OPERATOR_GREATER_THAN = '>';
25
    const OPERATOR_LESS_THAN_OR_EQUAL = '<=';
26
    const OPERATOR_LESS_THAN = '<';
27
    const OPERATOR_LIKE = 'LIKE';
28
    const OPERATOR_NOT_LIKE = 'NOT LIKE';
29
    const OPERATOR_EQUAL = '=';
30
    const OPERATOR_NOT_EQUAL = '<>';
31
    const CONJUNCTION_AND = 'AND';
32
    const CONJUNCTION_OR = 'OR';
33
    const CONJUNCTION_EXISTS = 'EXISTS';
34
    const CONJUNCTION_NOT_EXISTS = 'NOT EXISTS';
35
36
    /**
37
     * @var array
38
     */
39
    private $comparisons = [];
40
41
    /**
42
     * @var array
43
     */
44
    private $betweens = [];
45
46
    /**
47
     * @var array
48
     */
49
    private $isNull = [];
50
51
    /**
52
     * @var array
53
     */
54
    private $isNotNull = [];
55
56
    /**
57
     * @var array
58
     */
59
    private $booleans = [];
60
61
    /**
62
     * @var array
63
     */
64
    private $match = [];
65
66
    /**
67
     * @var array
68
     */
69
    private $ins = [];
70
71
    /**
72
     * @var array
73
     */
74
    private $notIns = [];
75
76
    /**
77
     * @var array
78
     */
79
    private $subWheres = [];
80
81
    /**
82
     * @var string
83
     */
84
    private $conjunction = self::CONJUNCTION_AND;
85
86
    /**
87
     * @var QueryInterface
88
     */
89
    private $query;
90
91
    /**
92
     * @var Table
93
     */
94
    private $table;
95
96
    /**
97
     * @var array
98
     */
99
    private $exists = [];
100
101
    /**
102
     * @var array
103
     */
104
    private $notExists = [];
105
106
    /**
107
     * @param QueryInterface $query
108
     */
109
    public function __construct(QueryInterface $query)
110
    {
111
        $this->query = $query;
112
    }
113
114
    /**
115
     * Deep copy for nested references.
116
     *
117
     * @return mixed
118
     */
119
    public function __clone()
120
    {
121
        return \unserialize(\serialize($this));
122
    }
123
124
    /**
125
     * @return bool
126
     */
127
    public function isEmpty()
128
    {
129
        $empty = \array_merge(
130
            $this->comparisons,
131
            $this->booleans,
132
            $this->betweens,
133
            $this->isNotNull,
134
            $this->isNull,
135
            $this->ins,
136
            $this->notIns,
137
            $this->subWheres,
138
            $this->exists
139
        );
140
141
        return 0 == \count($empty);
142
    }
143
144
    /**
145
     * @return string
146
     */
147
    public function getConjunction()
148
    {
149
        return $this->conjunction;
150
    }
151
152
    /**
153
     * @return array
154
     */
155
    public function getSubWheres()
156
    {
157
        return $this->subWheres;
158
    }
159
160
    /**
161
     * @param $operator
162
     *
163
     * @return Where
164
     */
165
    public function subWhere($operator = 'OR')
166
    {
167
        /** @var Where $filter */
168
        $filter = QueryFactory::createWhere($this->query);
169
        $filter->conjunction($operator);
170
        $filter->setTable($this->getTable());
171
172
        $this->subWheres[] = $filter;
173
174
        return $filter;
175
    }
176
177
    /**
178
     * @param string $operator
179
     *
180
     * @return $this
181
     *
182
     * @throws QueryException
183
     */
184
    public function conjunction($operator)
185
    {
186
        if (false === \in_array($operator, [self::CONJUNCTION_AND, self::CONJUNCTION_OR])) {
187
            throw new QueryException(
188
                "Invalid conjunction specified, must be one of AND or OR, but '".$operator."' was found."
189
            );
190
        }
191
        $this->conjunction = $operator;
192
193
        return $this;
194
    }
195
196
    /**
197
     * @return Table
198
     */
199
    public function getTable()
200
    {
201
        return $this->query->getTable();
202
    }
203
204
    /**
205
     * Used for subWhere query building.
206
     *
207
     * @param Table $table string
208
     *
209
     * @return $this
210
     */
211
    public function setTable($table)
212
    {
213
        $this->table = $table;
214
215
        return $this;
216
    }
217
218
    /**
219
     * equals alias.
220
     *
221
     * @param $column
222
     * @param int $value
223
     *
224
     * @return static
225
     */
226
    public function eq($column, $value)
227
    {
228
        return $this->equals($column, $value);
229
    }
230
231
    /**
232
     * @param $column
233
     * @param $value
234
     *
235
     * @return static
236
     */
237
    public function equals($column, $value)
238
    {
239
        return $this->compare($column, $value, self::OPERATOR_EQUAL);
240
    }
241
242
    /**
243
     * @param $column
244
     * @param $value
245
     * @param string $operator
246
     *
247
     * @return $this
248
     */
249
    public function compare($column, $value, $operator)
250
    {
251
        $column = $this->prepareColumn($column);
252
253
        $this->comparisons[] = [
254
            'subject' => $column,
255
            'conjunction' => $operator,
256
            'target' => $value,
257
        ];
258
259
        return $this;
260
    }
261
262
    /**
263
     * @param $column
264
     *
265
     * @return Column|Select
266
     */
267
    private function prepareColumn($column)
268
    {
269
        //This condition handles the "Select as a a column" special case.
270
        if ($column instanceof Select) {
271
            return $column;
272
        }
273
274
        $newColumn = [$column];
275
276
        return SyntaxFactory::createColumn($newColumn, $this->getTable());
277
    }
278
279
    /**
280
     * @param string $column
281
     * @param int    $value
282
     *
283
     * @return static
284
     */
285
    public function notEquals($column, $value)
286
    {
287
        return $this->compare($column, $value, self::OPERATOR_NOT_EQUAL);
288
    }
289
290
    /**
291
     * @param string $column
292
     * @param int    $value
293
     *
294
     * @return static
295
     */
296
    public function greaterThan($column, $value)
297
    {
298
        return $this->compare($column, $value, self::OPERATOR_GREATER_THAN);
299
    }
300
301
    /**
302
     * @param string $column
303
     * @param int    $value
304
     *
305
     * @return static
306
     */
307
    public function greaterThanOrEqual($column, $value)
308
    {
309
        return $this->compare($column, $value, self::OPERATOR_GREATER_THAN_OR_EQUAL);
310
    }
311
312
    /**
313
     * @param string $column
314
     * @param int    $value
315
     *
316
     * @return static
317
     */
318
    public function lessThan($column, $value)
319
    {
320
        return $this->compare($column, $value, self::OPERATOR_LESS_THAN);
321
    }
322
323
    /**
324
     * @param string $column
325
     * @param int    $value
326
     *
327
     * @return static
328
     */
329
    public function lessThanOrEqual($column, $value)
330
    {
331
        return $this->compare($column, $value, self::OPERATOR_LESS_THAN_OR_EQUAL);
332
    }
333
334
    /**
335
     * @param string $column
336
     * @param $value
337
     *
338
     * @return static
339
     */
340
    public function like($column, $value)
341
    {
342
        return $this->compare($column, $value, self::OPERATOR_LIKE);
343
    }
344
345
    /**
346
     * @param string $column
347
     * @param int    $value
348
     *
349
     * @return static
350
     */
351
    public function notLike($column, $value)
352
    {
353
        return $this->compare($column, $value, self::OPERATOR_NOT_LIKE);
354
    }
355
356
    /**
357
     * @param string[] $columns
358
     * @param mixed[]  $values
359
     *
360
     * @return static
361
     */
362
    public function match(array $columns, array $values)
363
    {
364
        return $this->genericMatch($columns, $values, 'natural');
365
    }
366
367
    /**
368
     * @param string[] $columns
369
     * @param mixed[]  $values
370
     * @param string   $mode
371
     *
372
     * @return $this
373
     */
374
    protected function genericMatch(array &$columns, array &$values, $mode)
375
    {
376
        $this->match[] = [
377
            'columns' => $columns,
378
            'values' => $values,
379
            'mode' => $mode,
380
        ];
381
382
        return $this;
383
    }
384
385
    /**
386
     * @param string $literal
387
     *
388
     * @return $this
389
     */
390
    public function asLiteral($literal)
391
    {
392
        $this->comparisons[] = $literal;
393
394
        return $this;
395
    }
396
397
    /**
398
     * @param string[] $columns
399
     * @param mixed[]  $values
400
     *
401
     * @return $this
402
     */
403
    public function matchBoolean(array $columns, array $values)
404
    {
405
        return $this->genericMatch($columns, $values, 'boolean');
406
    }
407
408
    /**
409
     * @param string[] $columns
410
     * @param mixed[]  $values
411
     *
412
     * @return $this
413
     */
414
    public function matchWithQueryExpansion(array $columns, array $values)
415
    {
416
        return $this->genericMatch($columns, $values, 'query_expansion');
417
    }
418
419
    /**
420
     * @param string    $column
421
     * @param integer[] $values
422
     *
423
     * @return $this
424
     */
425
    public function in($column, array $values)
426
    {
427
        $this->ins[$column] = $values;
428
429
        return $this;
430
    }
431
432
    /**
433
     * @param string    $column
434
     * @param integer[] $values
435
     *
436
     * @return $this
437
     */
438
    public function notIn($column, array $values)
439
    {
440
        $this->notIns[$column] = $values;
441
442
        return $this;
443
    }
444
445
    /**
446
     * @param string $column
447
     * @param int    $a
448
     * @param int    $b
449
     *
450
     * @return $this
451
     */
452
    public function between($column, $a, $b)
453
    {
454
        $column = $this->prepareColumn($column);
455
        $this->betweens[] = ['subject' => $column, 'a' => $a, 'b' => $b];
456
457
        return $this;
458
    }
459
460
    /**
461
     * @param string $column
462
     *
463
     * @return static
464
     */
465
    public function isNull($column)
466
    {
467
        $column = $this->prepareColumn($column);
468
        $this->isNull[] = ['subject' => $column];
469
470
        return $this;
471
    }
472
473
    /**
474
     * @param string $column
475
     *
476
     * @return $this
477
     */
478
    public function isNotNull($column)
479
    {
480
        $column = $this->prepareColumn($column);
481
        $this->isNotNull[] = ['subject' => $column];
482
483
        return $this;
484
    }
485
486
    /**
487
     * @param string $column
488
     * @param int    $value
489
     *
490
     * @return $this
491
     */
492
    public function addBitClause($column, $value)
493
    {
494
        $column = $this->prepareColumn($column);
495
        $this->booleans[] = ['subject' => $column, 'value' => $value];
496
497
        return $this;
498
    }
499
500
    /**
501
     * @param Select $select
502
     *
503
     * @return $this
504
     */
505
    public function exists(Select $select)
506
    {
507
        $this->exists[] = $select;
508
509
        return $this;
510
    }
511
512
    /**
513
     * @param Select $select
514
     *
515
     * @return $this
516
     */
517
    public function notExists(Select $select)
518
    {
519
        $this->notExists[] = $select;
520
521
        return $this;
522
    }
523
524
    /**
525
     * @return array
526
     */
527
    public function getMatches()
528
    {
529
        return $this->match;
530
    }
531
532
    /**
533
     * @return array
534
     */
535
    public function getIns()
536
    {
537
        return $this->ins;
538
    }
539
540
    /**
541
     * @return array
542
     */
543
    public function getNotIns()
544
    {
545
        return $this->notIns;
546
    }
547
548
    /**
549
     * @return array
550
     */
551
    public function getBetweens()
552
    {
553
        return $this->betweens;
554
    }
555
556
    /**
557
     * @return array
558
     */
559
    public function getBooleans()
560
    {
561
        return $this->booleans;
562
    }
563
564
    /**
565
     * @return array
566
     */
567
    public function getComparisons()
568
    {
569
        return $this->comparisons;
570
    }
571
572
    /**
573
     * @return array
574
     */
575
    public function getNotNull()
576
    {
577
        return $this->isNotNull;
578
    }
579
580
    /**
581
     * @return array
582
     */
583
    public function getNull()
584
    {
585
        return $this->isNull;
586
    }
587
588
    /**
589
     * @return array
590
     */
591
    public function getExists()
592
    {
593
        return $this->exists;
594
    }
595
596
    /**
597
     * @return array
598
     */
599
    public function getNotExists()
600
    {
601
        return $this->notExists;
602
    }
603
}
604