GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 53a2a4...560332 )
by Robert
11:42
created

QueryTrait::addOrderBy()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
ccs 7
cts 7
cp 1
cc 2
eloc 7
nc 2
nop 1
crap 2
1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\db;
9
10
use yii\base\NotSupportedException;
11
12
/**
13
 * The BaseQuery trait represents the minimum method set of a database Query.
14
 *
15
 * It is supposed to be used in a class that implements the [[QueryInterface]].
16
 *
17
 * @author Qiang Xue <[email protected]>
18
 * @author Carsten Brandt <[email protected]>
19
 * @since 2.0
20
 */
21
trait QueryTrait
22
{
23
    /**
24
     * @var string|array query condition. This refers to the WHERE clause in a SQL statement.
25
     * For example, `['age' => 31, 'team' => 1]`.
26
     * @see where() for valid syntax on specifying this value.
27
     */
28
    public $where;
29
    /**
30
     * @var int maximum number of records to be returned. If not set or less than 0, it means no limit.
31
     */
32
    public $limit;
33
    /**
34
     * @var int zero-based offset from where the records are to be returned. If not set or
35
     * less than 0, it means starting from the beginning.
36
     */
37
    public $offset;
38
    /**
39
     * @var array how to sort the query results. This is used to construct the ORDER BY clause in a SQL statement.
40
     * The array keys are the columns to be sorted by, and the array values are the corresponding sort directions which
41
     * can be either [SORT_ASC](http://php.net/manual/en/array.constants.php#constant.sort-asc)
42
     * or [SORT_DESC](http://php.net/manual/en/array.constants.php#constant.sort-desc).
43
     * The array may also contain [[Expression]] objects. If that is the case, the expressions
44
     * will be converted into strings without any change.
45
     */
46
    public $orderBy;
47
    /**
48
     * @var string|callable $column the name of the column by which the query results should be indexed by.
49
     * This can also be a callable (e.g. anonymous function) that returns the index value based on the given
50
     * row data. For more details, see [[indexBy()]]. This property is only used by [[QueryInterface::all()|all()]].
51
     */
52
    public $indexBy;
53
    /**
54
     * @var boolean whether to emulate the actual query execution, returning empty or false results.
55
     * @see emulateExecution()
56
     * @since 2.0.11
57
     */
58
    public $emulateExecution = false;
59
60
61
    /**
62
     * Sets the [[indexBy]] property.
63
     * @param string|callable $column the name of the column by which the query results should be indexed by.
64
     * This can also be a callable (e.g. anonymous function) that returns the index value based on the given
65
     * row data. The signature of the callable should be:
66
     *
67
     * ```php
68
     * function ($row)
69
     * {
70
     *     // return the index value corresponding to $row
71
     * }
72
     * ```
73
     *
74
     * @return $this the query object itself
75
     */
76 36
    public function indexBy($column)
77
    {
78 36
        $this->indexBy = $column;
79 36
        return $this;
80
    }
81
82
    /**
83
     * Sets the WHERE part of the query.
84
     *
85
     * See [[QueryInterface::where()]] for detailed documentation.
86
     *
87
     * @param string|array $condition the conditions that should be put in the WHERE part.
88
     * @return $this the query object itself
89
     * @see andWhere()
90
     * @see orWhere()
91
     */
92
    public function where($condition)
93
    {
94
        $this->where = $condition;
95
        return $this;
96
    }
97
98
    /**
99
     * Adds an additional WHERE condition to the existing one.
100
     * The new condition and the existing one will be joined using the 'AND' operator.
101
     * @param string|array $condition the new WHERE condition. Please refer to [[where()]]
102
     * on how to specify this parameter.
103
     * @return $this the query object itself
104
     * @see where()
105
     * @see orWhere()
106
     */
107
    public function andWhere($condition)
108
    {
109
        if ($this->where === null) {
110
            $this->where = $condition;
111
        } else {
112
            $this->where = ['and', $this->where, $condition];
113
        }
114
        return $this;
115
    }
116
117
    /**
118
     * Adds an additional WHERE condition to the existing one.
119
     * The new condition and the existing one will be joined using the 'OR' operator.
120
     * @param string|array $condition the new WHERE condition. Please refer to [[where()]]
121
     * on how to specify this parameter.
122
     * @return $this the query object itself
123
     * @see where()
124
     * @see andWhere()
125
     */
126
    public function orWhere($condition)
127
    {
128
        if ($this->where === null) {
129
            $this->where = $condition;
130
        } else {
131
            $this->where = ['or', $this->where, $condition];
132
        }
133
        return $this;
134
    }
135
136
    /**
137
     * Sets the WHERE part of the query but ignores [[isEmpty()|empty operands]].
138
     *
139
     * This method is similar to [[where()]]. The main difference is that this method will
140
     * remove [[isEmpty()|empty query operands]]. As a result, this method is best suited
141
     * for building query conditions based on filter values entered by users.
142
     *
143
     * The following code shows the difference between this method and [[where()]]:
144
     *
145
     * ```php
146
     * // WHERE `age`=:age
147
     * $query->filterWhere(['name' => null, 'age' => 20]);
148
     * // WHERE `age`=:age
149
     * $query->where(['age' => 20]);
150
     * // WHERE `name` IS NULL AND `age`=:age
151
     * $query->where(['name' => null, 'age' => 20]);
152
     * ```
153
     *
154
     * Note that unlike [[where()]], you cannot pass binding parameters to this method.
155
     *
156
     * @param array $condition the conditions that should be put in the WHERE part.
157
     * See [[where()]] on how to specify this parameter.
158
     * @return $this the query object itself
159
     * @see where()
160
     * @see andFilterWhere()
161
     * @see orFilterWhere()
162
     */
163 72
    public function filterWhere(array $condition)
164
    {
165 72
        $condition = $this->filterCondition($condition);
166 72
        if ($condition !== []) {
167 21
            $this->where($condition);
168 21
        }
169 72
        return $this;
170
    }
171
172
    /**
173
     * Adds an additional WHERE condition to the existing one but ignores [[isEmpty()|empty operands]].
174
     * The new condition and the existing one will be joined using the 'AND' operator.
175
     *
176
     * This method is similar to [[andWhere()]]. The main difference is that this method will
177
     * remove [[isEmpty()|empty query operands]]. As a result, this method is best suited
178
     * for building query conditions based on filter values entered by users.
179
     *
180
     * @param array $condition the new WHERE condition. Please refer to [[where()]]
181
     * on how to specify this parameter.
182
     * @return $this the query object itself
183
     * @see filterWhere()
184
     * @see orFilterWhere()
185
     */
186 6
    public function andFilterWhere(array $condition)
187
    {
188 6
        $condition = $this->filterCondition($condition);
189 6
        if ($condition !== []) {
190 3
            $this->andWhere($condition);
191 3
        }
192 6
        return $this;
193
    }
194
195
    /**
196
     * Adds an additional WHERE condition to the existing one but ignores [[isEmpty()|empty operands]].
197
     * The new condition and the existing one will be joined using the 'OR' operator.
198
     *
199
     * This method is similar to [[orWhere()]]. The main difference is that this method will
200
     * remove [[isEmpty()|empty query operands]]. As a result, this method is best suited
201
     * for building query conditions based on filter values entered by users.
202
     *
203
     * @param array $condition the new WHERE condition. Please refer to [[where()]]
204
     * on how to specify this parameter.
205
     * @return $this the query object itself
206
     * @see filterWhere()
207
     * @see andFilterWhere()
208
     */
209 3
    public function orFilterWhere(array $condition)
210
    {
211 3
        $condition = $this->filterCondition($condition);
212 3
        if ($condition !== []) {
213
            $this->orWhere($condition);
214
        }
215 3
        return $this;
216
    }
217
218
    /**
219
     * Removes [[isEmpty()|empty operands]] from the given query condition.
220
     *
221
     * @param array $condition the original condition
222
     * @return array the condition with [[isEmpty()|empty operands]] removed.
223
     * @throws NotSupportedException if the condition operator is not supported
224
     */
225 75
    protected function filterCondition($condition)
226
    {
227 75
        if (!is_array($condition)) {
228 21
            return $condition;
229
        }
230
231 75
        if (!isset($condition[0])) {
232
            // hash format: 'column1' => 'value1', 'column2' => 'value2', ...
233 6
            foreach ($condition as $name => $value) {
234 6
                if ($this->isEmpty($value)) {
235 3
                    unset($condition[$name]);
236 3
                }
237 6
            }
238 6
            return $condition;
239
        }
240
241
        // operator format: operator, operand 1, operand 2, ...
242
243 75
        $operator = array_shift($condition);
244
245 75
        switch (strtoupper($operator)) {
246 75
            case 'NOT':
247 75
            case 'AND':
248 75
            case 'OR':
249 27
                foreach ($condition as $i => $operand) {
250 27
                    $subCondition = $this->filterCondition($operand);
251 27
                    if ($this->isEmpty($subCondition)) {
252 27
                        unset($condition[$i]);
253 27
                    } else {
254 18
                        $condition[$i] = $subCondition;
255
                    }
256 27
                }
257
258 27
                if (empty($condition)) {
259 12
                    return [];
260
                }
261 18
                break;
262 54
            case 'BETWEEN':
263 54
            case 'NOT BETWEEN':
264 9
                if (array_key_exists(1, $condition) && array_key_exists(2, $condition)) {
265 9
                    if ($this->isEmpty($condition[1]) || $this->isEmpty($condition[2])) {
266 9
                        return [];
267
                    }
268
                }
269
                break;
270 48
            default:
271 48
                if (array_key_exists(1, $condition) && $this->isEmpty($condition[1])) {
272 48
                    return [];
273
                }
274 63
        }
275
276 24
        array_unshift($condition, $operator);
277
278 24
        return $condition;
279
    }
280
281
    /**
282
     * Returns a value indicating whether the give value is "empty".
283
     *
284
     * The value is considered "empty", if one of the following conditions is satisfied:
285
     *
286
     * - it is `null`,
287
     * - an empty string (`''`),
288
     * - a string containing only whitespace characters,
289
     * - or an empty array.
290
     *
291
     * @param mixed $value
292
     * @return bool if the value is empty
293
     */
294 75
    protected function isEmpty($value)
295
    {
296 75
        return $value === '' || $value === [] || $value === null || is_string($value) && trim($value) === '';
297
    }
298
299
    /**
300
     * Sets the ORDER BY part of the query.
301
     * @param string|array|Expression $columns the columns (and the directions) to be ordered by.
302
     * Columns can be specified in either a string (e.g. `"id ASC, name DESC"`) or an array
303
     * (e.g. `['id' => SORT_ASC, 'name' => SORT_DESC]`).
304
     *
305
     * The method will automatically quote the column names unless a column contains some parenthesis
306
     * (which means the column contains a DB expression).
307
     *
308
     * Note that if your order-by is an expression containing commas, you should always use an array
309
     * to represent the order-by information. Otherwise, the method will not be able to correctly determine
310
     * the order-by columns.
311
     *
312
     * Since version 2.0.7, an [[Expression]] object can be passed to specify the ORDER BY part explicitly in plain SQL.
313
     * @return $this the query object itself
314
     * @see addOrderBy()
315
     */
316 142
    public function orderBy($columns)
317
    {
318 142
        $this->orderBy = $this->normalizeOrderBy($columns);
319 142
        return $this;
320
    }
321
322
    /**
323
     * Adds additional ORDER BY columns to the query.
324
     * @param string|array|Expression $columns the columns (and the directions) to be ordered by.
325
     * Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array
326
     * (e.g. `['id' => SORT_ASC, 'name' => SORT_DESC]`).
327
     *
328
     * The method will automatically quote the column names unless a column contains some parenthesis
329
     * (which means the column contains a DB expression).
330
     *
331
     * Note that if your order-by is an expression containing commas, you should always use an array
332
     * to represent the order-by information. Otherwise, the method will not be able to correctly determine
333
     * the order-by columns.
334
     *
335
     * Since version 2.0.7, an [[Expression]] object can be passed to specify the ORDER BY part explicitly in plain SQL.
336
     * @return $this the query object itself
337
     * @see orderBy()
338
     */
339 36
    public function addOrderBy($columns)
340
    {
341 36
        $columns = $this->normalizeOrderBy($columns);
342 36
        if ($this->orderBy === null) {
343 15
            $this->orderBy = $columns;
344 15
        } else {
345 33
            $this->orderBy = array_merge($this->orderBy, $columns);
346
        }
347 36
        return $this;
348
    }
349
350
    /**
351
     * Normalizes format of ORDER BY data
352
     *
353
     * @param array|string|Expression $columns the columns value to normalize. See [[orderBy]] and [[addOrderBy]].
354
     * @return array
355
     */
356 142
    protected function normalizeOrderBy($columns)
357
    {
358 142
        if ($columns instanceof Expression) {
359 6
            return [$columns];
360 142
        } elseif (is_array($columns)) {
361 70
            return $columns;
362
        } else {
363 114
            $columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY);
364 114
            $result = [];
365 114
            foreach ($columns as $column) {
366 114
                if (preg_match('/^(.*?)\s+(asc|desc)$/i', $column, $matches)) {
367 15
                    $result[$matches[1]] = strcasecmp($matches[2], 'desc') ? SORT_ASC : SORT_DESC;
368 15
                } else {
369 111
                    $result[$column] = SORT_ASC;
370
                }
371 114
            }
372 114
            return $result;
373
        }
374
    }
375
376
    /**
377
     * Sets the LIMIT part of the query.
378
     * @param int $limit the limit. Use null or negative value to disable limit.
379
     * @return $this the query object itself
380
     */
381 56
    public function limit($limit)
382
    {
383 56
        $this->limit = $limit;
384 56
        return $this;
385
    }
386
387
    /**
388
     * Sets the OFFSET part of the query.
389
     * @param int $offset the offset. Use null or negative value to disable offset.
390
     * @return $this the query object itself
391
     */
392 33
    public function offset($offset)
393
    {
394 33
        $this->offset = $offset;
395 33
        return $this;
396
    }
397
398
    /**
399
     * Sets whether to emulate query execution, preventing any interaction with data storage.
400
     * After this mode is enabled, methods, returning query results like [[one()]], [[all()]], [[exists()]]
401
     * and so on, will return empty or false values.
402
     * You should use this method in case your program logic indicates query should not return any results, like
403
     * in case you set false where condition like `0=1`.
404
     * @param boolean $value whether to prevent query execution.
405
     * @return $this the query object itself.
406
     * @since 2.0.11
407
     */
408 21
    public function emulateExecution($value = true)
409
    {
410 21
        $this->emulateExecution = $value;
411 21
        return $this;
412
    }
413
}
414