Completed
Push — master ( 4b2726...162df7 )
by Hong
03:18
created

WhereTrait::realWhere()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 19
rs 9.4285
cc 2
eloc 15
nc 2
nop 7
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),
0 ignored issues
show
Documentation introduced by
new \Phossa2\Query\Misc\Template($template, $col) is of type object<Phossa2\Query\Misc\Template>, but the function expects a string|array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
51
            WhereInterface::NO_OPERATOR, WhereInterface::NO_VALUE,
52
            true, false, true);
53
    }
54
55
    /**
56
     * {@inheritDoc}
57
     */
58
    public function orWhereTpl(/*# string */ $template, $col)
59
    {
60
        return $this->realWhere(new Template($template, $col),
0 ignored issues
show
Documentation introduced by
new \Phossa2\Query\Misc\Template($template, $col) is of type object<Phossa2\Query\Misc\Template>, but the function expects a string|array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
61
            WhereInterface::NO_OPERATOR, WhereInterface::NO_VALUE,
62
            false, false, true);
63
    }
64
65
    /**
66
     * {@inheritDoc}
67
     */
68
    public function whereRaw(/*# string */ $rawString)
69
    {
70
        return $this->realWhere($rawString, WhereInterface::NO_OPERATOR,
71
            WhereInterface::NO_VALUE, true, false, true);
72
    }
73
74
    /**
75
     * {@inheritDoc}
76
     */
77
    public function orWhereRaw(/*# string */ $rawString)
78
    {
79
        return $this->realWhere($rawString, WhereInterface::NO_OPERATOR,
80
            WhereInterface::NO_VALUE, false, false, true);
81
    }
82
83
    /**
84
     * {@inheritDoc}
85
     */
86
    public function andWhere(
87
        $col,
88
        $operator = WhereInterface::NO_OPERATOR,
89
        $value = WhereInterface::NO_VALUE
90
    ) {
91
        return $this->realWhere($col, $operator, $value);
92
    }
93
94
    /**
95
     * {@inheritDoc}
96
     */
97
    public function orWhere(
98
        $col,
99
        $operator = WhereInterface::NO_OPERATOR,
100
        $value = WhereInterface::NO_VALUE
101
    ) {
102
        return $this->realWhere($col, $operator, $value, false);
103
    }
104
105
    /**
106
     * {@inheritDoc}
107
     */
108
    public function whereNot(
109
        $col,
110
        $operator = WhereInterface::NO_OPERATOR,
111
        $value = WhereInterface::NO_VALUE
112
    ) {
113
        return $this->realWhere($col, $operator, $value, true, true);
114
    }
115
116
    /**
117
     * {@inheritDoc}
118
     */
119
    public function orWhereNot(
120
        $col,
121
        $operator = WhereInterface::NO_OPERATOR,
122
        $value = WhereInterface::NO_VALUE
123
    ) {
124
        return $this->realWhere($col, $operator, $value, false, true);
125
    }
126
127
    /**
128
     * {@inheritDoc}
129
     */
130
    public function whereIn(/*# string */ $col, $value)
131
    {
132
        return $this->realWhere($col, 'IN', $value);
133
    }
134
135
    /**
136
     * {@inheritDoc}
137
     */
138
    public function orWhereIn(/*# string */ $col, $value)
139
    {
140
        return $this->realWhere($col, 'IN', $value, false);
141
    }
142
143
    /**
144
     * {@inheritDoc}
145
     */
146
    public function whereNotIn(/*# string */ $col, $value)
147
    {
148
        return $this->realWhere($col, 'NOT IN', $value);
149
    }
150
151
    /**
152
     * {@inheritDoc}
153
     */
154
    public function orWhereNotIn(/*# string */ $col, $value)
155
    {
156
        return $this->realWhere($col, 'NOT IN', $value, false);
157
    }
158
159
    /**
160
     * {@inheritDoc}
161
     */
162
    public function whereBetween(/*# string */ $col, $value1, $value2)
163
    {
164
        $val = sprintf('%s AND %s', $value1, $value2);
165
        return $this->realWhere($col, 'BETWEEN', $val);
166
    }
167
168
    /**
169
     * {@inheritDoc}
170
     */
171
    public function orWhereBetween(/*# string */ $col, $value1, $value2)
172
    {
173
        $val = sprintf('%s AND %s', $value1, $value2);
174
        return $this->realWhere($col, 'BETWEEN', $val, false);
175
    }
176
177
    /**
178
     * {@inheritDoc}
179
     */
180
    public function whereNotBetween(/*# string */ $col, $value1, $value2)
181
    {
182
        $val = sprintf('%s AND %s', $value1, $value2);
183
        return $this->realWhere($col, 'NOT BETWEEN', $val);
184
    }
185
186
    /**
187
     * {@inheritDoc}
188
     */
189
    public function orWhereNotBetween(/*# string */ $col, $value1, $value2)
190
    {
191
        $val = sprintf('%s AND %s', $value1, $value2);
192
        return $this->realWhere($col, 'NOT BETWEEN', $val, false);
193
    }
194
195
    /**
196
     * {@inheritDoc}
197
     */
198
    public function whereNull(/*# string */ $col)
199
    {
200
        return $this->realWhere($col, 'IS', 'NULL');
201
    }
202
203
    /**
204
     * {@inheritDoc}
205
     */
206
    public function orWhereNull(/*# string */ $col)
207
    {
208
        return $this->realWhere($col, 'IS', 'NULL', false);
209
    }
210
211
    /**
212
     * {@inheritDoc}
213
     */
214
    public function whereNotNull(/*# string */ $col)
215
    {
216
        return $this->realWhere($col, 'IS', 'NOT NULL');
217
    }
218
219
    /**
220
     * {@inheritDoc}
221
     */
222
    public function orWhereNotNull(/*# string */ $col)
223
    {
224
        return $this->realWhere($col, 'IS', 'NOT NULL', false);
225
    }
226
227
    /**
228
     * WHERE EXISTS
229
     *
230
     * ```php
231
     * // WHERE EXISTS (SELECT `user_id` FROM `users`)
232
     * ->whereExists($users->select('user_id'))
233
     * ```
234
     *
235
     * @param  SelectStatementInterface $sel
236
     * @return $this
237
     * @see    WhereInterface::where()
238
     * @access public
239
     * @api
240
     */
241
    public function whereExists(SelectStatementInterface $sel)
242
    {
243
        return $this->realWhere('', 'EXISTS', $sel);
244
    }
245
246
    /**
247
     * {@inheritDoc}
248
     */
249
    public function orWhereExists(SelectStatementInterface $sel)
250
    {
251
        return $this->realWhere('', 'EXISTS', $sel, false);
252
    }
253
254
    /**
255
     * {@inheritDoc}
256
     */
257
    public function whereNotExists(SelectStatementInterface $sel)
258
    {
259
        return $this->realWhere('', 'NOT EXISTS', $sel);
260
    }
261
262
    /**
263
     * {@inheritDoc}
264
     */
265
    public function orWhereNotExists(SelectStatementInterface $sel)
266
    {
267
        return $this->realWhere('', 'NOT EXISTS', $sel, false);
268
    }
269
270
    /**
271
     * @param  string|array $col col or cols
272
     * @param  mixed $operator
273
     * @param  mixed $value
274
     * @param  bool $logicAnd 'AND'
275
     * @param  bool $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
        /*# bool */ $logicAnd = true,
286
        /*# bool */ $whereNot = false,
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  bool $logicAnd
323
     * @param  bool $whereNot
324
     * @param  bool $rawMode
325
     * @access protected
326
     */
327
    protected function multipleWhere(
328
        array $cols,
329
        /*# bool */ $logicAnd = true,
330
        /*# bool */ $whereNot = false,
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
360
            // logic
361
            if ($idx) {
362
                $cls[] = $where[2] ? 'AND' : 'OR';
363
            }
364
365
            // NOT
366
            if ($where[1]) {
367
                $cls[] = 'NOT';
368
            }
369
370
            if (!empty($where[3])) {
371
                $cls[] = $this->quoteItem(
372
                    $where[3], $settings, $this->isRaw($where[3], $where[0])
373
                );
374
            }
375
376
            // operator
377
            if (WhereInterface::NO_OPERATOR !== $where[4]) {
378
                $cls[] = $where[4];
379
            }
380
381
            // value
382
            if (WhereInterface::NO_VALUE !== $where[5]) {
383
                $cls[] = $this->processValue($where[5]);
384
            }
385
386
            $result[] = join(' ', $cls);
387
        }
388
        return $this->joinClause($clause, '', $result, $settings);
389
    }
390
391
    abstract protected function isRaw($str, /*# bool */ $rawMode)/*# : bool */;
392
    abstract protected function processValue($value)/*# : string */;
393
    abstract protected function &getClause(/*# string */ $clauseName)/*# : array */;
394
    abstract protected function quoteItem($item, array $settings, /*# bool */ $rawMode = false)/*# : string */;
395
    abstract protected function joinClause(
396
        /*# : string */ $prefix,
397
        /*# : string */ $seperator,
398
        array $clause,
399
        array $settings
400
    )/*# : string */;
401
}
402