Completed
Push — master ( 439406...4b2726 )
by Hong
03:09
created

WhereTrait   B

Complexity

Total Complexity 40

Size/Duplication

Total Lines 353
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 40
c 1
b 0
f 0
lcom 1
cbo 0
dl 0
loc 353
rs 8.2608

33 Methods

Rating   Name   Duplication   Size   Complexity  
A where() 0 7 1
A whereTpl() 0 6 1
A orWhereTpl() 0 6 1
A whereRaw() 0 5 1
A orWhereRaw() 0 5 1
A andWhere() 0 7 1
A orWhere() 0 7 1
A whereNot() 0 7 1
A orWhereNot() 0 7 1
A whereIn() 0 4 1
A orWhereIn() 0 4 1
A whereNotIn() 0 4 1
A orWhereNotIn() 0 4 1
A whereBetween() 0 5 1
A orWhereBetween() 0 5 1
A whereNotBetween() 0 5 1
A orWhereNotBetween() 0 5 1
A whereNull() 0 4 1
A orWhereNull() 0 4 1
A whereNotNull() 0 4 1
A orWhereNotNull() 0 4 1
A whereExists() 0 4 1
A orWhereExists() 0 4 1
A whereNotExists() 0 4 1
A orWhereNotExists() 0 4 1
B realWhere() 0 23 4
A multipleWhere() 0 16 3
C buildWhere() 0 37 8
processValue() 0 1 ?
clauseTpl() 0 1 ?
getClause() 0 1 ?
quoteItem() 0 1 ?
joinClause() 0 6 ?

How to fix   Complexity   

Complex Class

Complex classes like WhereTrait often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use WhereTrait, and based on these observations, apply Extract Interface, too.

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\Interfaces\Clause\WhereInterface;
18
use Phossa2\Query\Interfaces\Statement\SelectStatementInterface;
19
20
/**
21
 * WhereTrait
22
 *
23
 * Implementation of WhereInterface
24
 *
25
 * @package Phossa2\Query
26
 * @author  Hong Zhang <[email protected]>
27
 * @see     WhereInterface
28
 * @version 2.0.0
29
 * @since   2.0.0 added
30
 */
31
trait WhereTrait
32
{
33
    /**
34
     * {@inheritDoc}
35
     */
36
    public function where(
37
        $col,
38
        $operator = WhereInterface::NO_OPERATOR,
39
        $value = WhereInterface::NO_VALUE
40
    ) {
41
        return $this->realWhere($col, $operator, $value);
42
    }
43
44
    /**
45
     * {@inheritDoc}
46
     */
47
    public function whereTpl(/*# string */ $template, $col)
48
    {
49
        return $this->realWhere($this->clauseTpl($template, $col),
50
            WhereInterface::NO_OPERATOR, WhereInterface::NO_VALUE,
51
            true, false, true);
52
    }
53
54
    /**
55
     * {@inheritDoc}
56
     */
57
    public function orWhereTpl(/*# string */ $template, $col)
58
    {
59
        return $this->realWhere($this->clauseTpl($template, $col),
60
            WhereInterface::NO_OPERATOR, WhereInterface::NO_VALUE,
61
            false, false, true);
62
    }
63
64
    /**
65
     * {@inheritDoc}
66
     */
67
    public function whereRaw(/*# string */ $rawString)
68
    {
69
        return $this->realWhere($rawString, WhereInterface::NO_OPERATOR,
70
            WhereInterface::NO_VALUE, true, false, true);
71
    }
72
73
    /**
74
     * {@inheritDoc}
75
     */
76
    public function orWhereRaw(/*# string */ $rawString)
77
    {
78
        return $this->realWhere($rawString, WhereInterface::NO_OPERATOR,
79
            WhereInterface::NO_VALUE, false, false, true);
80
    }
81
82
    /**
83
     * {@inheritDoc}
84
     */
85
    public function andWhere(
86
        $col,
87
        $operator = WhereInterface::NO_OPERATOR,
88
        $value = WhereInterface::NO_VALUE
89
    ) {
90
        return $this->realWhere($col, $operator, $value);
91
    }
92
93
    /**
94
     * {@inheritDoc}
95
     */
96
    public function orWhere(
97
        $col,
98
        $operator = WhereInterface::NO_OPERATOR,
99
        $value = WhereInterface::NO_VALUE
100
    ) {
101
        return $this->realWhere($col, $operator, $value, false);
102
    }
103
104
    /**
105
     * {@inheritDoc}
106
     */
107
    public function whereNot(
108
        $col,
109
        $operator = WhereInterface::NO_OPERATOR,
110
        $value = WhereInterface::NO_VALUE
111
    ) {
112
        return $this->realWhere($col, $operator, $value, true, true);
113
    }
114
115
    /**
116
     * {@inheritDoc}
117
     */
118
    public function orWhereNot(
119
        $col,
120
        $operator = WhereInterface::NO_OPERATOR,
121
        $value = WhereInterface::NO_VALUE
122
    ) {
123
        return $this->realWhere($col, $operator, $value, false, true);
124
    }
125
126
    /**
127
     * {@inheritDoc}
128
     */
129
    public function whereIn(/*# string */ $col, $value)
130
    {
131
        return $this->realWhere($col, 'IN', $value);
132
    }
133
134
    /**
135
     * {@inheritDoc}
136
     */
137
    public function orWhereIn(/*# string */ $col, $value)
138
    {
139
        return $this->realWhere($col, 'IN', $value, false);
140
    }
141
142
    /**
143
     * {@inheritDoc}
144
     */
145
    public function whereNotIn(/*# string */ $col, $value)
146
    {
147
        return $this->realWhere($col, 'NOT IN', $value);
148
    }
149
150
    /**
151
     * {@inheritDoc}
152
     */
153
    public function orWhereNotIn(/*# string */ $col, $value)
154
    {
155
        return $this->realWhere($col, 'NOT IN', $value, false);
156
    }
157
158
    /**
159
     * {@inheritDoc}
160
     */
161
    public function whereBetween(/*# string */ $col, $value1, $value2)
162
    {
163
        $val = sprintf('%s AND %s', $value1, $value2);
164
        return $this->realWhere($col, 'BETWEEN', $val);
165
    }
166
167
    /**
168
     * {@inheritDoc}
169
     */
170
    public function orWhereBetween(/*# string */ $col, $value1, $value2)
171
    {
172
        $val = sprintf('%s AND %s', $value1, $value2);
173
        return $this->realWhere($col, 'BETWEEN', $val, false);
174
    }
175
176
    /**
177
     * {@inheritDoc}
178
     */
179
    public function whereNotBetween(/*# string */ $col, $value1, $value2)
180
    {
181
        $val = sprintf('%s AND %s', $value1, $value2);
182
        return $this->realWhere($col, 'NOT BETWEEN', $val);
183
    }
184
185
    /**
186
     * {@inheritDoc}
187
     */
188
    public function orWhereNotBetween(/*# string */ $col, $value1, $value2)
189
    {
190
        $val = sprintf('%s AND %s', $value1, $value2);
191
        return $this->realWhere($col, 'NOT BETWEEN', $val, false);
192
    }
193
194
    /**
195
     * {@inheritDoc}
196
     */
197
    public function whereNull(/*# string */ $col)
198
    {
199
        return $this->realWhere($col, 'IS', 'NULL');
200
    }
201
202
    /**
203
     * {@inheritDoc}
204
     */
205
    public function orWhereNull(/*# string */ $col)
206
    {
207
        return $this->realWhere($col, 'IS', 'NULL', false);
208
    }
209
210
    /**
211
     * {@inheritDoc}
212
     */
213
    public function whereNotNull(/*# string */ $col)
214
    {
215
        return $this->realWhere($col, 'IS', 'NOT NULL');
216
    }
217
218
    /**
219
     * {@inheritDoc}
220
     */
221
    public function orWhereNotNull(/*# string */ $col)
222
    {
223
        return $this->realWhere($col, 'IS', 'NOT NULL', false);
224
    }
225
226
    /**
227
     * WHERE EXISTS
228
     *
229
     * ```php
230
     * // WHERE EXISTS (SELECT `user_id` FROM `users`)
231
     * ->whereExists($users->select('user_id'))
232
     * ```
233
     *
234
     * @param  SelectStatementInterface $sel
235
     * @return $this
236
     * @see    WhereInterface::where()
237
     * @access public
238
     * @api
239
     */
240
    public function whereExists(SelectStatementInterface $sel)
241
    {
242
        return $this->realWhere('', 'EXISTS', $sel);
243
    }
244
245
    /**
246
     * {@inheritDoc}
247
     */
248
    public function orWhereExists(SelectStatementInterface $sel)
249
    {
250
        return $this->realWhere('', 'EXISTS', $sel, false);
251
    }
252
253
    /**
254
     * {@inheritDoc}
255
     */
256
    public function whereNotExists(SelectStatementInterface $sel)
257
    {
258
        return $this->realWhere('', 'NOT EXISTS', $sel);
259
    }
260
261
    /**
262
     * {@inheritDoc}
263
     */
264
    public function orWhereNotExists(SelectStatementInterface $sel)
265
    {
266
        return $this->realWhere('', 'NOT EXISTS', $sel, false);
267
    }
268
269
    /**
270
     * @param  string|array $col col or cols
271
     * @param  mixed $operator
272
     * @param  mixed $value
273
     * @param  bool $logicAnd 'AND'
274
     * @param  bool $whereNot 'WHERE NOT'
275
     * @param  bool $rawMode
276
     * @param  string $clause 'where' or 'having'
277
     * @return $this
278
     * @access protected
279
     */
280
    protected function realWhere(
281
        $col,
282
        $operator = WhereInterface::NO_OPERATOR,
283
        $value    = WhereInterface::NO_VALUE,
284
        /*# bool */ $logicAnd = true,
285
        /*# bool */ $whereNot = false,
286
        /*# bool */ $rawMode  = false,
287
        /*# string */ $clause = 'WHERE'
288
    ) {
289
        $clause = &$this->getClause($clause);
290
        if (is_array($col)) {
291
            $this->multipleWhere($col, $logicAnd, $whereNot, $rawMode);
292
            return $this;
293
        } elseif (WhereInterface::NO_OPERATOR === $operator) {
294
            $rawMode = true;
295
            $value = WhereInterface::NO_VALUE;
296
        } elseif (WhereInterface::NO_VALUE === $value) {
297
            $value = $operator;
298
            $operator = '=';
299
        }
300
        $clause[] = [$rawMode, $whereNot, $logicAnd, $col, $operator, $value];
301
        return $this;
302
    }
303
304
    /**
305
     * @param  array $cols
306
     * @param  bool $logicAnd
307
     * @param  bool $whereNot
308
     * @param  bool $rawMode
309
     * @access protected
310
     */
311
    protected function multipleWhere(
312
        array $cols,
313
        /*# bool */ $logicAnd = true,
314
        /*# bool */ $whereNot = false,
315
        /*# bool */ $rawMode  = false
316
    ) {
317
        foreach ($cols as $fld => $val) {
318
            if (is_array($val)) {
319
                $opr = $val[0];
320
                $val = $val[1];
321
            } else {
322
                $opr = '=';
323
            }
324
            $this->realWhere($fld, $opr, $val, $logicAnd, $whereNot, $rawMode);
325
        }
326
    }
327
328
    /**
329
     * Build WHERE
330
     *
331
     * @param  string $clause 'where|having'
332
     * @return array
333
     * @access protected
334
     */
335
    protected function buildWhere(
336
        array $settings,
337
        /*# string */ $clause = 'WHERE'
338
    )/*# : string */ {
339
        $result = [];
340
        $wheres = &$this->getClause($clause);
341
        foreach ($wheres as $idx => $where) {
342
            $cls = [];
343
344
            // logic
345
            if ($idx) {
346
                $cls[] = $where[2] ? 'AND' : 'OR';
347
            }
348
349
            // NOT
350
            if ($where[1]) {
351
                $cls[] = 'NOT';
352
            }
353
354
            if (!empty($where[3])) {
355
                $cls[] = $this->quoteItem($where[3], $this->isRaw($where[3], $where[0]));
0 ignored issues
show
Bug introduced by
It seems like isRaw() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
356
            }
357
358
            // operator
359
            if (WhereInterface::NO_OPERATOR !== $where[4]) {
360
                $cls[] = $where[4];
361
            }
362
363
            // value
364
            if (WhereInterface::NO_VALUE !== $where[5]) {
365
                $cls[] = $this->processValue($where[5]);
366
            }
367
368
            $result[] = join(' ', $cls);
369
        }
370
        return $this->joinClause($clause, '', $result, $settings);
371
    }
372
373
    abstract protected function processValue($value)/*# : string */;
374
    abstract protected function clauseTpl(/*# string */ $template, $col)/*# : string */;
375
    abstract protected function &getClause(/*# string */ $clauseName)/*# : array */;
376
    abstract protected function quoteItem($item, /*# bool */ $rawMode = false)/*# : string */;
377
    abstract protected function joinClause(
378
        /*# : string */ $prefix,
379
        /*# : string */ $seperator,
380
        array $clause,
381
        array $settings
382
    )/*# : string */;
383
}
384