Passed
Push — master ( d01bf5...5a7f24 )
by Alexander
14:14
created

ActiveQuery::one()   A

Complexity

Conditions 6
Paths 10

Size

Total Lines 37
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 19
c 1
b 0
f 0
nc 10
nop 0
dl 0
loc 37
ccs 18
cts 18
cp 1
crap 6
rs 9.0111
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\ActiveRecord\Redis;
6
7
use JsonException;
8
use ReflectionException;
9
use Throwable;
10
use Yiisoft\ActiveRecord\ActiveQuery as BaseActiveQuery;
11
use Yiisoft\ActiveRecord\ActiveQueryInterface;
12
use Yiisoft\Arrays\ArrayHelper;
13
use Yiisoft\Db\Exception\Exception;
14
use Yiisoft\Db\Exception\InvalidConfigException;
15
use Yiisoft\Db\Exception\InvalidParamException;
16
use Yiisoft\Db\Exception\NotSupportedException;
17
use Yiisoft\Db\Expression\ExpressionInterface;
18
use Yiisoft\Db\Query\QueryInterface;
19
20
use function array_keys;
21
use function arsort;
22
use function asort;
23
use function count;
24
use function in_array;
25
use function is_array;
26
use function is_numeric;
27
use function is_string;
28
use function key;
29
use function reset;
30
31
/**
32
 * ActiveQuery represents a query associated with an Active Record class.
33
 *
34
 * An ActiveQuery can be a normal query or be used in a relational context.
35
 *
36
 * Relational queries are created by {@see ActiveRecord::hasOne()} and {@see ActiveRecord::hasMany()}.
37
 *
38
 * Normal Query
39
 * ------------
40
 *
41
 * ActiveQuery mainly provides the following methods to retrieve the query results:
42
 *
43
 * - {@see one()}: returns a single record populated with the first row of data.
44
 * - {@see all()}: returns all records based on the query results.
45
 * - {@see count()}: returns the number of records.
46
 * - {@see sum()}: returns the sum over the specified column.
47
 * - {@see average()}: returns the average over the specified column.
48
 * - {@see min()}: returns the min over the specified column.
49
 * - {@see max()}: returns the max over the specified column.
50
 * - {@see scalar()}: returns the value of the first column in the first row of the query result.
51
 * - {@see exists()}: returns a value indicating whether the query result has data or not.
52
 *
53
 * You can use query methods, such as {@see where()}, {@see limit()} and {@see orderBy()} to customize the query
54
 * options.
55
 *
56
 * ActiveQuery also provides the following additional query options:
57
 *
58
 * - {@see with()}: list of relations that this query should be performed with.
59
 * - {@see indexBy()}: the name of the column by which the query result should be indexed.
60
 * - {@see asArray()}: whether to return each record as an array.
61
 *
62
 * These options can be configured using methods of the same name. For example:
63
 *
64
 * ```php
65
 * $customerQuery = new ActiveQuery(Customer::class, $db);
66
 * $customers = $customerQuery->with('orders')->asArray()->all();
67
 * ```
68
 *
69
 * Relational query
70
 * ----------------
71
 *
72
 * In relational context ActiveQuery represents a relation between two Active Record classes.
73
 *
74
 * Relational ActiveQuery instances are usually created by calling {@see ActiveRecord::hasOne()} and
75
 * {@see ActiveRecord::hasMany()}. An Active Record class declares a relation by defining a getter method which calls
76
 * one of the above methods and returns the created ActiveQuery object.
77
 *
78
 * A relation is specified by {@see link} which represents the association between columns of different tables; and the
79
 * multiplicity of the relation is indicated by {@see multiple}.
80
 *
81
 * If a relation involves a junction table, it may be specified by {@see via()}.
82
 *
83
 * This methods may only be called in a relational context. Same is true for {@see inverseOf()}, which marks a relation
84
 * as inverse of another relation.
85
 */
86
class ActiveQuery extends BaseActiveQuery
87
{
88
    private string $attribute;
89
    private ?LuaScriptBuilder $luaScriptBuilder = null;
90
91
    /**
92
     * Executes the query and returns all results as an array.
93
     *
94
     * @throws Exception|InvalidConfigException|InvalidParamException|JsonException|NotSupportedException
95
     * @throws ReflectionException|Throwable
96 43
     *
97
     * @return array the query results. If the query results in nothing, an empty array will be returned.
98 43
     */
99
    public function all(): array
100 43
    {
101 2
        $indexBy = $this->getIndexBy();
102
103
        if ($this->shouldEmulateExecution()) {
104
            return [];
105 42
        }
106
107 42
        /** support for orderBy */
108 12
        $data = $this->executeScript('All');
109
110
        if (empty($data)) {
111 39
            return [];
112
        }
113 39
114 39
        $rows = [];
115 39
116 39
        foreach ($data as $dataRow) {
117 39
            $row = [];
118
            $c = count($dataRow);
119
            for ($i = 0; $i < $c;) {
120 39
                $row[$dataRow[$i++]] = $dataRow[$i++];
121
            }
122
123 39
            $rows[] = $row;
124
        }
125
126
        if (empty($rows)) {
127 39
            return [];
128
        }
129 39
130 7
        $models = $this->createModels($rows);
131
132
        if (!empty($this->getWith())) {
133 39
            $this->findWith($this->getWith(), $models);
134 3
        }
135 3
136 3
        if ($indexBy !== null) {
0 ignored issues
show
introduced by
The condition $indexBy !== null is always true.
Loading history...
137 3
            $indexedModels = [];
138 3
            if (is_string($indexBy)) {
139
                foreach ($models as $model) {
140
                    $key = $model[$indexBy];
141
                    $indexedModels[$key] = $model;
142
                }
143
            } else {
144
                foreach ($models as $model) {
145
                    $key = $this->indexBy($model);
146 3
                    $indexedModels[$key] = $model;
147
                }
148
            }
149 39
            $models = $indexedModels;
150
        }
151
152
        return $models;
153
    }
154
155
    /**
156
     * Executes the query and returns a single row of result.
157
     *
158
     * Null will be returned, if the query results in nothing.
159
     *
160
     * @throws Exception|InvalidConfigException|InvalidParamException|JsonException|NotSupportedException
161
     * @throws ReflectionException|Throwable
162
     *
163 48
     * @return ActiveRecord|array|null a single row of query result. Depending on the setting of {@see asArray}, the
164
     * query result may be either an array or an ActiveRecord object.
165 48
     */
166 1
    public function one()
167
    {
168
        if ($this->shouldEmulateExecution()) {
169
            return null;
170 47
        }
171
172 47
        /** add support for orderBy */
173 15
        $data = $this->executeScript('One');
174
175
        if (empty($data)) {
176 41
            return null;
177
        }
178 41
179
        $row = [];
180 41
181 41
        $c = count($data);
0 ignored issues
show
Bug introduced by
It seems like $data can also be of type boolean and string; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

181
        $c = count(/** @scrutinizer ignore-type */ $data);
Loading history...
182
183
        for ($i = 0; $i < $c;) {
184 41
            $row[$data[$i++]] = $data[$i++];
185 2
        }
186
187
        if ($this->isAsArray()) {
188 40
            $arClass = $row;
189
        } else {
190 40
            $arClass = $this->getARInstance();
191
            $arClass->populateRecord($arClass, $row);
0 ignored issues
show
Bug introduced by
The method populateRecord() does not exist on Yiisoft\ActiveRecord\ActiveRecordInterface. Did you maybe mean populateRelation()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

191
            $arClass->/** @scrutinizer ignore-call */ 
192
                      populateRecord($arClass, $row);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
192 40
        }
193
194 40
        if (!empty($this->getWith())) {
195
            $arClasses = [$arClass];
196
197 41
            $this->findWith($this->getWith(), $arClasses);
198 3
199
            $arClass = $arClasses[0];
200 3
        }
201
202 3
        return $arClass;
203
    }
204
205 41
    /**
206
     * Returns the number of records.
207
     *
208
     * @param string $q the COUNT expression. This parameter is ignored by this implementation.
209
     *
210
     *
211
     * @throws Exception|InvalidConfigException|InvalidParamException|JsonException|NotSupportedException
212
     * @throws ReflectionException|Throwable
213
     *
214
     * @return int number of records.
215
     */
216
    public function count(string $q = '*'): int
217
    {
218 16
        if ($this->shouldEmulateExecution()) {
219
            return 0;
220 16
        }
221 1
222
        if ($this->getWhere() === null) {
223
            return (int) $this->db->executeCommand('LLEN', [$this->getARInstance()->keyPrefix()]);
0 ignored issues
show
Bug introduced by
The method executeCommand() does not exist on Yiisoft\Db\Connection\ConnectionInterface. It seems like you code against a sub-type of Yiisoft\Db\Connection\ConnectionInterface such as Yiisoft\Db\Redis\Connection. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

223
            return (int) $this->db->/** @scrutinizer ignore-call */ executeCommand('LLEN', [$this->getARInstance()->keyPrefix()]);
Loading history...
Bug introduced by
The method keyPrefix() does not exist on Yiisoft\ActiveRecord\ActiveRecordInterface. It seems like you code against a sub-type of Yiisoft\ActiveRecord\ActiveRecordInterface such as Yiisoft\ActiveRecord\Redis\ActiveRecord. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

223
            return (int) $this->db->executeCommand('LLEN', [$this->getARInstance()->/** @scrutinizer ignore-call */ keyPrefix()]);
Loading history...
224 15
        }
225
226 13
        return (int) $this->executeScript('Count');
227
    }
228 13
229
    /**
230
     * Returns a value indicating whether the query result contains any row of data.
231 5
     *
232
     * @return bool whether the query result contains any row of data.
233
     *
234
     * @throws Exception|InvalidConfigException|InvalidParamException|JsonException|NotSupportedException
235
     * @throws ReflectionException|Throwable
236
     */
237
    public function exists(): bool
238
    {
239
        if ($this->shouldEmulateExecution()) {
240
            return false;
241
        }
242 3
243
        return $this->one() !== null;
244 3
    }
245 1
246
    /**
247
     * Returns the number of records.
248 2
     *
249
     * @param string $column the column to sum up. If this parameter is not given, the `db` application component will
250
     * be used.
251
     *
252
     * @throws Exception|InvalidConfigException|InvalidParamException|JsonException|NotSupportedException
253
     * @throws ReflectionException|Throwable
254
     *
255
     * @return int number of records.
256
     */
257
    public function sum(string $column): int
258
    {
259
        if ($this->shouldEmulateExecution()) {
260
            return 0;
261
        }
262 3
263
        return (int) $this->executeScript('Sum', !empty($column) ? $column : $this->attribute);
264 3
    }
265 1
266
    /**
267
     * Returns the average of the specified column values.
268 2
     *
269
     * @param string $column the column name or expression. Make sure you properly quote column names in the expression.
270
     *
271
     * @throws Exception|InvalidConfigException|InvalidParamException|JsonException|NotSupportedException
272
     * @throws ReflectionException|Throwable
273
     *
274
     * @return int the average of the specified column values.
275
     */
276
    public function average(string $column): int
277
    {
278
        if ($this->shouldEmulateExecution()) {
279
            return 0;
280
        }
281 3
282
        return (int) $this->executeScript('Average', !empty($column) ? $column : $this->attribute);
283 3
    }
284 1
285
    /**
286
     * Returns the minimum of the specified column values.
287 2
     *
288
     * @param string $column the column name or expression. Make sure you properly quote column names in the expression.
289
     *
290
     * @throws Exception|InvalidConfigException|InvalidParamException|JsonException|NotSupportedException
291
     * @throws ReflectionException|Throwable
292
     *
293
     * @return int the minimum of the specified column values.
294
     */
295
    public function min(string $column): ?int
296
    {
297
        if ($this->shouldEmulateExecution()) {
298
            return null;
299
        }
300 3
301
        return (int) $this->executeScript('Min', !empty($column) ? $column : $this->attribute);
302 3
    }
303 1
304
    /**
305
     * Returns the maximum of the specified column values.
306 2
     *
307
     * @param string $column the column name or expression. Make sure you properly quote column names in the expression.
308
     *
309
     * @throws Exception|InvalidConfigException|InvalidParamException|JsonException|NotSupportedException
310
     * @throws ReflectionException|Throwable
311
     *
312
     * @return int the maximum of the specified column values.
313
     */
314
    public function max(string $column): ?int
315
    {
316
        if ($this->shouldEmulateExecution()) {
317
            return null;
318
        }
319 3
320
        return (int) $this->executeScript('Max', !empty($column) ? $column : $this->attribute);
321 3
    }
322 1
323
    /**
324
     * Executes a script created by {@see LuaScriptBuilder}.
325 2
     *
326
     * @param string $type the type of the script to generate
327
     * @param string|null $columnName
328
     *
329
     * @throws Exception|JsonException|InvalidConfigException|InvalidParamException|NotSupportedException
330
     * @throws ReflectionException|Throwable
331
     *
332
     * @return array|bool|null|string
333
     */
334
    protected function executeScript(string $type, ?string $columnName = null)
335
    {
336
        if ($this->getPrimaryModel() !== null) {
337
            /** lazy loading */
338
            if ($this->getVia() instanceof self) {
339 68
                /** via junction table */
340
                $viaModels = $this->getVia()->findJunctionRows([$this->getPrimaryModel()]);
341 68
                $this->filterByModels($viaModels);
342
            } elseif (is_array($this->getVia())) {
343 15
                /**
344
                 * via relation
345
                 * @var $viaQuery ActiveQuery
346
                 */
347 15
                [$viaName, $viaQuery] = $this->getVia();
348
349
                if ($viaQuery->getMultiple()) {
350
                    $viaModels = $viaQuery->all();
351
                    $this->getPrimaryModel()->populateRelation($viaName, $viaModels);
352 9
                } else {
353
                    $model = $viaQuery->one();
354 9
                    $this->getPrimaryModel()->populateRelation($viaName, $model);
355 9
                    $viaModels = $model === null ? [] : [$model];
356 9
                }
357
358
                $this->filterByModels($viaModels);
359
            } else {
360
                $this->filterByModels([$this->getPrimaryModel()]);
361
            }
362
        }
363 9
364
        /** find by primary key if possible. This is much faster than scanning all records */
365 15
        if (
366
            is_array($this->getWhere()) &&
367
            (
368
                (!isset($this->getWhere()[0]) && $this->getARInstance()->isPrimaryKey(array_keys($this->getWhere()))) ||
369
                (
370
                    isset($this->getWhere()[0]) && $this->getWhere()[0] === 'in' &&
371 68
                    $this->getARInstance()->isPrimaryKey((array) $this->getWhere()[1])
372
                )
373 62
            )
374
        ) {
375 44
            return $this->findByPk($type, $columnName);
376 68
        }
377
378
        $method = 'build' . $type;
379
380 49
        $script = $this->getLuaScriptBuilder()->$method($this, $columnName);
381
382
        return $this->db->executeCommand('EVAL', [$script, 0]);
383 50
    }
384
385 50
    /**
386
     * Fetch by pk if possible as this is much faster.
387 50
     *
388
     * @param string $type the type of the script to generate.
389
     * @param string|null $columnName
390
     *
391
     * @throws InvalidParamException|JsonException|NotSupportedException
392
     *
393
     * @return array|bool|null|string
394
     */
395
    private function findByPk(string $type, ?string $columnName = null)
396
    {
397
        $limit = $this->getLimit();
398
        $offset = $this->getOffset();
399
        $orderBy = $this->getOrderBy();
400 49
        $needSort = !empty($orderBy) && in_array($type, ['All', 'One', 'Column']);
401
        $where = $this->getWhere();
402 49
403 49
        if ($needSort) {
404 49
            if (!is_array($orderBy) || count($orderBy) > 1) {
405 49
                throw new NotSupportedException(
406 49
                    'orderBy by multiple columns is not currently supported by redis ActiveRecord.'
407
                );
408 49
            }
409 9
410
            $k = key($orderBy);
411
            $v = $orderBy[$k];
412
413
            if (is_numeric($k)) {
414
                $orderColumn = $v;
415 9
                $orderType = SORT_ASC;
416 9
            } else {
417
                $orderColumn = $k;
418 9
                $orderType = $v;
419
            }
420
        }
421
422 9
        if (isset($where[0]) && $where[0] === 'in') {
423 9
            $pks = (array) $where[2];
424
        } elseif (count($where) === 1) {
0 ignored issues
show
Bug introduced by
It seems like $where can also be of type string; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

424
        } elseif (count(/** @scrutinizer ignore-type */ $where) === 1) {
Loading history...
425
            $pks = (array) reset($where);
0 ignored issues
show
Bug introduced by
It seems like $where can also be of type null and string; however, parameter $array of reset() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

425
            $pks = (array) reset(/** @scrutinizer ignore-type */ $where);
Loading history...
426
        } else {
427 49
            foreach ($where as $values) {
428 18
                if (is_array($values)) {
429 40
                    /** support composite IN for composite PK */
430 37
                    throw new NotSupportedException('Find by composite PK is not supported by redis ActiveRecord.');
431
                }
432 5
            }
433 5
            $pks = [$where];
434
        }
435
436
        if ($type === 'Count') {
437
            $start = 0;
438 5
            $limit = null;
439
        } else {
440
            $start = ($offset === null || $offset < 0) ? 0 : $offset;
441
            $limit = ($limit < 0) ? null : $limit;
442 49
        }
443
444 49
        $i = 0;
445 2
        $data = [];
446 2
        $orderArray = [];
447
448 47
        foreach ($pks as $pk) {
449 47
            if (++$i > $start && ($limit === null || $i <= $start + $limit)) {
450
                $key = $this->getARInstance()->keyPrefix() . ':a:' . $this->getARInstance()->buildKey($pk);
0 ignored issues
show
Bug introduced by
The method buildKey() does not exist on Yiisoft\ActiveRecord\ActiveRecordInterface. It seems like you code against a sub-type of Yiisoft\ActiveRecord\ActiveRecordInterface such as Yiisoft\ActiveRecord\Redis\ActiveRecord. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

450
                $key = $this->getARInstance()->keyPrefix() . ':a:' . $this->getARInstance()->/** @scrutinizer ignore-call */ buildKey($pk);
Loading history...
451
                $result = $this->db->executeCommand('HGETALL', [$key]);
452 49
                if (!empty($result)) {
453 49
                    $data[] = $result;
454 49
                    if ($needSort) {
455
                        $orderArray[] = $this->db->executeCommand(
456 49
                            'HGET',
457 48
                            [$key, $orderColumn]
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $orderColumn does not seem to be defined for all execution paths leading up to this point.
Loading history...
458 48
                        );
459 48
                    }
460 48
                    if ($type === 'One' && $orderBy === null) {
461 47
                        break;
462 47
                    }
463 9
                }
464 9
            }
465 9
        }
466
467
        if ($needSort) {
468 47
            $resultData = [];
469
470
            if ($orderType === SORT_ASC) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $orderType does not seem to be defined for all execution paths leading up to this point.
Loading history...
471
                asort($orderArray, SORT_NATURAL);
472
            } else {
473
                arsort($orderArray, SORT_NATURAL);
474
            }
475 49
476 9
            foreach ($orderArray as $orderKey => $orderItem) {
477
                $resultData[] = $data[$orderKey];
478 9
            }
479 9
480
            $data = $resultData;
481
        }
482
483
        switch ($type) {
484 9
            case 'All':
485 9
                return $data;
486
            case 'One':
487
                return reset($data);
488 9
            case 'Count':
489
                return count($data);
490
            case 'Column':
491
                $column = [];
492 49
                foreach ($data as $dataRow) {
493 25
                    $row = [];
494 41
                    $c = count($dataRow);
495 39
                    for ($i = 0; $i < $c;) {
496 2
                        $row[$dataRow[$i++]] = $dataRow[$i++];
497 2
                    }
498
                    $column[] = $row[$columnName];
499
                }
500
501
                return $column;
502
            case 'Sum':
503
                $sum = 0;
504
                foreach ($data as $dataRow) {
505
                    $c = count($dataRow);
506
                    for ($i = 0; $i < $c;) {
507
                        if ($dataRow[$i++] === $columnName) {
508
                            $sum += $dataRow[$i];
509
                            break;
510
                        }
511
                    }
512
                }
513
514
                return $sum;
515
            case 'Average':
516
                $sum = 0;
517
                $count = 0;
518
                foreach ($data as $dataRow) {
519
                    $count++;
520
                    $c = count($dataRow);
521
                    for ($i = 0; $i < $c;) {
522
                        if ($dataRow[$i++] === $columnName) {
523
                            $sum += $dataRow[$i];
524
                            break;
525
                        }
526
                    }
527
                }
528
529
                return $sum / $count;
530
            case 'Min':
531
                $min = null;
532
                foreach ($data as $dataRow) {
533
                    $c = count($dataRow);
534
                    for ($i = 0; $i < $c;) {
535
                        if ($dataRow[$i++] === $columnName && ($min === null || $dataRow[$i] < $min)) {
536
                            $min = $dataRow[$i];
537
                            break;
538
                        }
539
                    }
540
                }
541
542
                return $min;
543
            case 'Max':
544
                $max = null;
545
                foreach ($data as $dataRow) {
546
                    $c = count($dataRow);
547
                    for ($i = 0; $i < $c;) {
548
                        if ($dataRow[$i++] === $columnName && ($max === null || $dataRow[$i] > $max)) {
549
                            $max = $dataRow[$i];
550
                            break;
551
                        }
552
                    }
553
                }
554
555
                return $max;
556
        }
557
558
        throw new InvalidParamException('Unknown fetch type: ' . $type);
559
    }
560
561
    /**
562
     * Executes the query and returns the first column of the result.
563
     *
564
     * @throws Exception|InvalidConfigException|InvalidParamException|JsonException|NotSupportedException
565
     * @throws ReflectionException
566
     *
567
     * @return array the first column of the query result. An empty array is returned if the query results in nothing.
568
     */
569
    public function column(): array
570
    {
571
        if ($this->shouldEmulateExecution()) {
572
            return [];
573
        }
574
575
        /** TODO add support for orderBy */
576 2
        return $this->executeScript('Column', $this->attribute);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->executeScr...umn', $this->attribute) could return the type boolean|null|string which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
577
    }
578 2
579 1
    /**
580
     * Returns the query result as a scalar value.
581
     *
582
     * The value returned will be the specified attribute in the first record of the query results.
583 1
     *
584
     * @throws Exception|InvalidConfigException|InvalidParamException|ReflectionException|NotSupportedException
585
     * @throws JsonException
586
     *
587
     * @return string|null the value of the specified attribute in the first record of the query result. Null is
588
     * returned if the query result is empty.
589
     */
590
    public function scalar(): ?string
591
    {
592
        if ($this->shouldEmulateExecution()) {
593
            return null;
594
        }
595
596 3
        $record = $this->one();
597
598 3
        if ($record !== null) {
599 1
            return $record->hasAttribute($this->attribute) ? $record->getAttribute($this->attribute) : null;
600
        }
601
602 2
        return null;
603
    }
604 2
605 2
    public function withAttribute(string $value): self
606
    {
607
        $this->attribute = $value;
608
609
        return $this;
610
    }
611 5
612
    public function getLuaScriptBuilder(): LuaScriptBuilder
613 5
    {
614
        if ($this->luaScriptBuilder === null) {
615 5
            $this->luaScriptBuilder = new LuaScriptBuilder();
616
        }
617
618 50
        return $this->luaScriptBuilder;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->luaScriptBuilder could return the type null which is incompatible with the type-hinted return Yiisoft\ActiveRecord\Redis\LuaScriptBuilder. Consider adding an additional type-check to rule them out.
Loading history...
619
    }
620 50
621 50
    /**
622
     * Finds ActiveRecord instance(s) by the given condition.
623
     *
624 50
     * This method is internally called by {@see findOne()} and {@see findAll()}.
625
     *
626
     * @param mixed $condition please refer to {@see findOne()} for the explanation of this parameter.
627
     *
628
     * @throws InvalidConfigException if there is no primary key defined.
629
     *
630
     * @return ActiveQueryInterface the newly created {@see QueryInterface} instance.
631
     */
632
    protected function findByCondition($condition): ActiveQueryInterface
633
    {
634
        $arInstance = $this->getARInstance();
635
636
        if (!is_array($condition)) {
637
            $condition = [$condition];
638
        }
639
640
        if (!ArrayHelper::isAssociative($condition) && !$condition instanceof ExpressionInterface) {
641
            /** query by primary key */
642
            $primaryKey = $arInstance->primaryKey();
643
            if (isset($primaryKey[0])) {
644
                /**
645
                 * If condition is scalar, search for a single primary key, if it is array, search for multiple primary
646
                 * key values.
647
                 */
648
                $condition = [$primaryKey[0] => is_array($condition) ? array_values($condition) : $condition];
0 ignored issues
show
introduced by
The condition is_array($condition) is always true.
Loading history...
649
            } else {
650
                throw new InvalidConfigException('"' . get_class($arInstance) . '" must have a primary key.');
651
            }
652
        }
653
654
        return $this->andWhere($condition);
655
    }
656
}
657