Passed
Pull Request — master (#547)
by Wilmer
24:11 queued 21:59
created

ArrayExpression   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 134
Duplicated Lines 0 %

Test Coverage

Coverage 35.48%

Importance

Changes 0
Metric Value
eloc 15
dl 0
loc 134
ccs 11
cts 31
cp 0.3548
rs 10
c 0
b 0
f 0
wmc 12

11 Methods

Rating   Name   Duplication   Size   Complexity  
A count() 0 3 1
A getValue() 0 3 1
A getDimension() 0 3 1
A getType() 0 3 1
A __construct() 0 2 1
A offsetSet() 0 5 1
A offsetUnset() 0 3 1
A offsetExists() 0 5 1
A offsetGet() 0 5 1
A validateKey() 0 7 2
A getIterator() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Expression;
6
7
use ArrayAccess;
8
use ArrayIterator;
9
use Countable;
10
use IteratorAggregate;
11
use Traversable;
12
use Yiisoft\Db\Exception\InvalidConfigException;
13
use Yiisoft\Db\Query\QueryInterface;
14
15
use function count;
16
17
/**
18
 * The ArrayExpression class represents an array SQL expression.
19
 *
20
 * Expressions of this type can be used in conditions as well:
21
 *
22
 * ```php
23
 * $query->andWhere(['@>', 'items', new ArrayExpression([1, 2, 3], 'integer')])
24
 * ```
25
 *
26
 * Which, depending on DBMS, will result in a well-prepared condition. For example, in PostgresSQL it will be compiled
27
 * to `WHERE "items" @> ARRAY[1, 2, 3]::integer[]`.
28
 *
29 9
 * @template-implements ArrayAccess<int, mixed>
30
 * @template-implements IteratorAggregate<int>
31 9
 */
32 1
class ArrayExpression implements ExpressionInterface, ArrayAccess, Countable, IteratorAggregate
33
{
34
    public function __construct(private array $value = [], private string|null $type = null, private int $dimension = 1)
35 9
    {
36 9
    }
37 9
38 9
    /**
39
     * The type of the array elements. Defaults to `null` which means the type is not explicitly specified.
40
     *
41
     * Note that in case when type is not specified explicitly and DBMS can not guess it from the context, SQL error
42
     * will be raised.
43
     */
44
    public function getType(): string|null
45
    {
46
        return $this->type;
47
    }
48 32
49
    /**
50 32
     * The array's content. In can be represented as an array of values or a {@see QueryInterface} that returns these
51
     * values.
52
     */
53
    public function getValue(): array
54
    {
55
        return $this->value;
56
    }
57
58 32
    /**
59
     * @return int The number of indices needed to select an element
60 32
     */
61
    public function getDimension(): int
62
    {
63
        return $this->dimension;
64
    }
65
66 29
    /**
67
     * Whether an offset exists.
68 29
     *
69
     * @link http://php.net/manual/en/arrayaccess.offsetexists.php
70
     *
71
     * @param mixed $offset An offset to check for.
72
     *
73
     * @throws InvalidConfigException If offset is not an integer
74
     *
75
     * @return bool `true` on success or `false` on failure. The return value will be cast to boolean if non-boolean
76
     * was returned.
77
     */
78
    public function offsetExists(mixed $offset): bool
79
    {
80
        $key = $this->validateKey($offset);
81
82
        return isset($this->value[$key]);
83
    }
84
85
    /**
86
     * Offset to retrieve.
87
     *
88
     * @link http://php.net/manual/en/arrayaccess.offsetget.php
89
     *
90
     * @param mixed $offset The offset to retrieve.
91
     *
92
     * @throws InvalidConfigException If offset is not an integer
93
     *
94
     * @return mixed Can return all value types.
95
     */
96
    public function offsetGet(mixed $offset): mixed
97
    {
98
        $key = $this->validateKey($offset);
99
100
        return $this->value[$key];
101
    }
102
103
    /**
104
     * Offset to set.
105
     *
106
     * @link http://php.net/manual/en/arrayaccess.offsetset.php
107
     *
108
     * @param mixed $offset The offset to assign the value to.
109
     * @param mixed $value The value to set.
110
     *
111
     * @throws InvalidConfigException
112
     */
113
    public function offsetSet(mixed $offset, mixed $value): void
114
    {
115
        $key = $this->validateKey($offset);
116
117
        $this->value[$key] = $value;
118
    }
119
120
    /**
121
     * Offset to unset.
122
     *
123
     * @link http://php.net/manual/en/arrayaccess.offsetunset.php
124
     */
125
    public function offsetUnset(mixed $offset): void
126
    {
127
        unset($this->value[$offset]);
128
    }
129
130
    /**
131
     * Count elements of an object.
132
     *
133
     * @link http://php.net/manual/en/countable.count.php
134
     *
135
     * @return int The custom count as an integer.
136
     */
137
    public function count(): int
138
    {
139
        return count($this->value);
140
    }
141
142
    /**
143
     * Retrieve an external iterator.
144
     *
145
     * @link http://php.net/manual/en/iteratoraggregate.getiterator.php
146
     *
147
     * @return ArrayIterator An instance of an object implementing <b>Iterator</b> or <b>Traversable</b>.
148
     */
149
    public function getIterator(): Traversable
150
    {
151
        return new ArrayIterator($this->value);
152
    }
153
154
    /**
155
     * Validates the key of the array expression is an integer.
156
     *
157
     * @throws InvalidConfigException
158
     */
159
    private function validateKey(mixed $key): int
160
    {
161
        if (!is_int($key)) {
162
            throw new InvalidConfigException('The ArrayExpression offset must be an integer.');
163
        }
164
165
        return $key;
166
    }
167
}
168