Completed
Push — master ( 3152a4...36e9e8 )
by Hong
02:25
created

WhereTrait::buildWhere()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 9.2
c 0
b 0
f 0
cc 4
eloc 13
nc 5
nop 2
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Query
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Query\Traits\Clause;
16
17
use Phossa2\Query\Misc\Template;
18
use Phossa2\Query\Interfaces\Clause\WhereInterface;
19
use Phossa2\Query\Interfaces\Statement\SelectStatementInterface;
20
21
/**
22
 * WhereTrait
23
 *
24
 * Implementation of WhereInterface
25
 *
26
 * @package Phossa2\Query
27
 * @author  Hong Zhang <[email protected]>
28
 * @see     WhereInterface
29
 * @version 2.0.0
30
 * @since   2.0.0 added
31
 */
32
trait WhereTrait
33
{
34
    /**
35
     * {@inheritDoc}
36
     */
37
    public function where(
38
        $col,
39
        $operator = WhereInterface::NO_OPERATOR,
40
        $value = WhereInterface::NO_VALUE
41
    ) {
42
        return $this->realWhere($col, $operator, $value);
43
    }
44
45
    /**
46
     * {@inheritDoc}
47
     */
48
    public function whereTpl(/*# string */ $template, $col)
49
    {
50
        return $this->realWhere(new Template($template, $col),
51
            WhereInterface::NO_OPERATOR, WhereInterface::NO_VALUE, 'AND', '');
52
    }
53
54
    /**
55
     * {@inheritDoc}
56
     */
57
    public function orWhereTpl(/*# string */ $template, $col)
58
    {
59
        return $this->realWhere(new Template($template, $col),
60
            WhereInterface::NO_OPERATOR, WhereInterface::NO_VALUE, 'OR', '');
61
    }
62
63
    /**
64
     * {@inheritDoc}
65
     */
66
    public function whereRaw(/*# string */ $rawString)
67
    {
68
        return $this->realWhere($rawString, WhereInterface::NO_OPERATOR,
69
            WhereInterface::NO_VALUE, 'AND', '', true);
70
    }
71
72
    /**
73
     * {@inheritDoc}
74
     */
75
    public function orWhereRaw(/*# string */ $rawString)
76
    {
77
        return $this->realWhere($rawString, WhereInterface::NO_OPERATOR,
78
            WhereInterface::NO_VALUE, 'OR', '', true);
79
    }
80
81
    /**
82
     * {@inheritDoc}
83
     */
84
    public function andWhere(
85
        $col,
86
        $operator = WhereInterface::NO_OPERATOR,
87
        $value = WhereInterface::NO_VALUE
88
    ) {
89
        return $this->realWhere($col, $operator, $value);
90
    }
91
92
    /**
93
     * {@inheritDoc}
94
     */
95
    public function orWhere(
96
        $col,
97
        $operator = WhereInterface::NO_OPERATOR,
98
        $value = WhereInterface::NO_VALUE
99
    ) {
100
        return $this->realWhere($col, $operator, $value, 'OR');
101
    }
102
103
    /**
104
     * {@inheritDoc}
105
     */
106
    public function whereNot(
107
        $col,
108
        $operator = WhereInterface::NO_OPERATOR,
109
        $value = WhereInterface::NO_VALUE
110
    ) {
111
        return $this->realWhere($col, $operator, $value, 'AND', 'NOT');
112
    }
113
114
    /**
115
     * {@inheritDoc}
116
     */
117
    public function orWhereNot(
118
        $col,
119
        $operator = WhereInterface::NO_OPERATOR,
120
        $value = WhereInterface::NO_VALUE
121
    ) {
122
        return $this->realWhere($col, $operator, $value, 'OR', 'NOT');
123
    }
124
125
    /**
126
     * {@inheritDoc}
127
     */
128
    public function whereIn(/*# string */ $col, $value)
129
    {
130
        return $this->realWhere($col, 'IN', $value);
131
    }
132
133
    /**
134
     * {@inheritDoc}
135
     */
136
    public function orWhereIn(/*# string */ $col, $value)
137
    {
138
        return $this->realWhere($col, 'IN', $value, 'OR');
139
    }
140
141
    /**
142
     * {@inheritDoc}
143
     */
144
    public function whereNotIn(/*# string */ $col, $value)
145
    {
146
        return $this->realWhere($col, 'NOT IN', $value);
147
    }
148
149
    /**
150
     * {@inheritDoc}
151
     */
152
    public function orWhereNotIn(/*# string */ $col, $value)
153
    {
154
        return $this->realWhere($col, 'NOT IN', $value, 'OR');
155
    }
156
157
    /**
158
     * {@inheritDoc}
159
     */
160
    public function whereBetween(/*# string */ $col, $value1, $value2)
161
    {
162
        $val = sprintf('%s AND %s', $value1, $value2);
163
        return $this->realWhere($col, 'BETWEEN', $val);
164
    }
165
166
    /**
167
     * {@inheritDoc}
168
     */
169
    public function orWhereBetween(/*# string */ $col, $value1, $value2)
170
    {
171
        $val = sprintf('%s AND %s', $value1, $value2);
172
        return $this->realWhere($col, 'BETWEEN', $val, 'OR');
173
    }
174
175
    /**
176
     * {@inheritDoc}
177
     */
178
    public function whereNotBetween(/*# string */ $col, $value1, $value2)
179
    {
180
        $val = sprintf('%s AND %s', $value1, $value2);
181
        return $this->realWhere($col, 'NOT BETWEEN', $val);
182
    }
183
184
    /**
185
     * {@inheritDoc}
186
     */
187
    public function orWhereNotBetween(/*# string */ $col, $value1, $value2)
188
    {
189
        $val = sprintf('%s AND %s', $value1, $value2);
190
        return $this->realWhere($col, 'NOT BETWEEN', $val, 'OR');
191
    }
192
193
    /**
194
     * {@inheritDoc}
195
     */
196
    public function whereNull(/*# string */ $col)
197
    {
198
        return $this->realWhere($col, 'IS', 'NULL');
199
    }
200
201
    /**
202
     * {@inheritDoc}
203
     */
204
    public function orWhereNull(/*# string */ $col)
205
    {
206
        return $this->realWhere($col, 'IS', 'NULL', 'OR');
207
    }
208
209
    /**
210
     * {@inheritDoc}
211
     */
212
    public function whereNotNull(/*# string */ $col)
213
    {
214
        return $this->realWhere($col, 'IS', 'NOT NULL');
215
    }
216
217
    /**
218
     * {@inheritDoc}
219
     */
220
    public function orWhereNotNull(/*# string */ $col)
221
    {
222
        return $this->realWhere($col, 'IS', 'NOT NULL', 'OR');
223
    }
224
225
    /**
226
     * WHERE EXISTS
227
     *
228
     * ```php
229
     * // WHERE EXISTS (SELECT `user_id` FROM `users`)
230
     * ->whereExists($users->select('user_id'))
231
     * ```
232
     *
233
     * @param  SelectStatementInterface $sel
234
     * @return $this
235
     * @see    WhereInterface::where()
236
     * @access public
237
     * @api
238
     */
239
    public function whereExists(SelectStatementInterface $sel)
240
    {
241
        return $this->realWhere('', 'EXISTS', $sel);
242
    }
243
244
    /**
245
     * {@inheritDoc}
246
     */
247
    public function orWhereExists(SelectStatementInterface $sel)
248
    {
249
        return $this->realWhere('', 'EXISTS', $sel, 'OR');
250
    }
251
252
    /**
253
     * {@inheritDoc}
254
     */
255
    public function whereNotExists(SelectStatementInterface $sel)
256
    {
257
        return $this->realWhere('', 'NOT EXISTS', $sel);
258
    }
259
260
    /**
261
     * {@inheritDoc}
262
     */
263
    public function orWhereNotExists(SelectStatementInterface $sel)
264
    {
265
        return $this->realWhere('', 'NOT EXISTS', $sel, 'OR');
266
    }
267
268
    /**
269
     * Real where
270
     *
271
     * @param  string|string[]|Template $col col or cols
272
     * @param  mixed $operator
273
     * @param  mixed $value
274
     * @param  string $logicAnd 'AND'
275
     * @param  string $whereNot 'WHERE NOT'
276
     * @param  bool $rawMode
277
     * @param  string $clause 'where' or 'having'
278
     * @return $this
279
     * @access protected
280
     */
281
    protected function realWhere(
282
        $col,
283
        $operator = WhereInterface::NO_OPERATOR,
284
        $value    = WhereInterface::NO_VALUE,
285
        /*# string */ $logicAnd = 'AND',
286
        /*# string */ $whereNot = '',
287
        /*# bool */ $rawMode = false,
288
        /*# string */ $clause = 'WHERE'
289
    ) {
290
        $clause = &$this->getClause($clause);
291
        if (is_array($col)) {
292
            $this->multipleWhere($col, $logicAnd, $whereNot, $rawMode);
293
            return $this;
294
        }
295
        $this->fixOperatorValue($operator, $value, $rawMode);
296
297
        $clause[] = [$rawMode, $whereNot, $logicAnd, $col, $operator, $value];
298
        return $this;
299
    }
300
301
    /**
302
     * Fix operator and value
303
     *
304
     * @param  mixed $operator
305
     * @param  mixed $value
306
     * @param  bool $rawMode
307
     * @access protected
308
     */
309
    protected function fixOperatorValue(&$operator, &$value, &$rawMode)
310
    {
311
        if (WhereInterface::NO_OPERATOR === $operator) {
312
            $rawMode = true;
313
            $value = WhereInterface::NO_VALUE;
314
        } elseif (WhereInterface::NO_VALUE === $value) {
315
            $value = $operator;
316
            $operator = '=';
317
        }
318
    }
319
320
    /**
321
     * @param  array $cols
322
     * @param  string $logicAnd
323
     * @param  string $whereNot
324
     * @param  bool $rawMode
325
     * @access protected
326
     */
327
    protected function multipleWhere(
328
        array $cols,
329
        /*# string */ $logicAnd = 'AND',
330
        /*# string */ $whereNot = '',
331
        /*# bool */ $rawMode  = false
332
    ) {
333
        foreach ($cols as $fld => $val) {
334
            if (is_array($val)) {
335
                $opr = $val[0];
336
                $val = $val[1];
337
            } else {
338
                $opr = '=';
339
            }
340
            $this->realWhere($fld, $opr, $val, $logicAnd, $whereNot, $rawMode);
341
        }
342
    }
343
344
    /**
345
     * Build WHERE
346
     *
347
     * @param  string $clause 'where|having'
348
     * @return array
349
     * @access protected
350
     */
351
    protected function buildWhere(
352
        array $settings,
353
        /*# string */ $clause = 'WHERE'
354
    )/*# : string */ {
355
        $result = [];
356
        $wheres = &$this->getClause($clause);
357
        foreach ($wheres as $idx => $where) {
358
            $cls = [];
359
            // AND OR
360
            if ($idx) {
361
                $cls[] = $where[2];
362
            }
363
            // NOT
364
            if ($where[1]) {
365
                $cls[] = $where[1];
366
            }
367
            $result[] = $this->buildWhereClause($cls, $where, $settings);
368
        }
369
        return $this->joinClause($clause, '', $result, $settings);
370
    }
371
372
    /**
373
     * Build 'col = val' part
374
     *
375
     * @param  array $cls
376
     * @param  array $where
377
     * @param  array $settings
378
     * @return string
379
     * @access protected
380
     */
381
    protected function buildWhereClause(array $cls, array $where, array $settings)
382
    {
383
        // col
384
        if (!empty($where[3])) {
385
            $cls[] = $this->quoteItem(
386
                $where[3], $settings, $this->isRaw($where[3], $where[0])
387
            );
388
        }
389
390
        // operator
391
        if (WhereInterface::NO_OPERATOR !== $where[4]) {
392
            $cls[] = $where[4];
393
        }
394
395
        // value
396
        if (WhereInterface::NO_VALUE !== $where[5]) {
397
            $cls[] = $this->processValue($where[5], $settings);
398
        }
399
400
        return join(' ', $cls);
401
    }
402
403
    abstract protected function isRaw($str, /*# bool */ $rawMode)/*# : bool */;
404
    abstract protected function processValue($value, array $settings)/*# : string */;
405
    abstract protected function &getClause(/*# string */ $clauseName)/*# : array */;
406
    abstract protected function quoteItem($item, array $settings, /*# bool */ $rawMode = false)/*# : string */;
407
    abstract protected function joinClause(
408
        /*# : string */ $prefix,
409
        /*# : string */ $seperator,
410
        array $clause,
411
        array $settings
412
    )/*# : string */;
413
}
414