Passed
Pull Request — master (#548)
by Wilmer
02:43
created

ArrayExpression   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 154
Duplicated Lines 0 %

Test Coverage

Coverage 35.48%

Importance

Changes 0
Metric Value
eloc 23
dl 0
loc 154
ccs 11
cts 31
cp 0.3548
rs 10
c 0
b 0
f 0
wmc 14

12 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 offsetExists() 0 5 1
A offsetSet() 0 6 1
A offsetUnset() 0 6 1
A offsetGet() 0 6 1
A validateKey() 0 7 2
A getIterator() 0 5 1
A validateValue() 0 7 2
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 mixed $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(): mixed
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
        $this->value = $this->validateValue($this->value);
100
101
        return $this->value[$key];
102
    }
103
104
    /**
105
     * Offset to set.
106
     *
107
     * @link http://php.net/manual/en/arrayaccess.offsetset.php
108
     *
109
     * @param mixed $offset The offset to assign the value to.
110
     * @param mixed $value The value to set.
111
     *
112
     * @throws InvalidConfigException If offset is not an integer.
113
     *
114
     */
115
    public function offsetSet(mixed $offset, mixed $value): void
116
    {
117
        $key = $this->validateKey($offset);
118
        $this->value = $this->validateValue($this->value);
119
120
        $this->value[$key] = $value;
121
    }
122
123
    /**
124
     * Offset to unset.
125
     *
126
     * @link http://php.net/manual/en/arrayaccess.offsetunset.php
127
     */
128
    public function offsetUnset(mixed $offset): void
129
    {
130
        $key = $this->validateKey($offset);
131
        $this->value = $this->validateValue($this->value);
132
133
        unset($this->value[$key]);
134
    }
135
136
    /**
137
     * Count elements of an object.
138
     *
139
     * @link http://php.net/manual/en/countable.count.php
140
     *
141
     * @return int The custom count as an integer.
142
     */
143
    public function count(): int
144
    {
145
        return count((array) $this->value);
146
    }
147
148
    /**
149
     * Retrieve an external iterator.
150
     *
151
     * @link http://php.net/manual/en/iteratoraggregate.getiterator.php
152
     *
153
     * @return ArrayIterator An instance of an object implementing `Iterator` or `Traversable`.
154
     */
155
    public function getIterator(): Traversable
156
    {
157
        $value = $this->validateValue($this->value);
158
159
        return new ArrayIterator($value);
160
    }
161
162
    /**
163
     * Validates the key of the array expression is an integer.
164
     *
165
     * @throws InvalidConfigException If offset is not an integer.
166
     */
167
    private function validateKey(mixed $key): int
168
    {
169
        if (!is_int($key)) {
170
            throw new InvalidConfigException('The ArrayExpression offset must be an integer.');
171
        }
172
173
        return $key;
174
    }
175
176
    /**
177
     * Validates the value of the array expression is an array.
178
     */
179
    private function validateValue(mixed $value): array
180
    {
181
        if (!is_array($value)) {
182
            throw new InvalidConfigException('The ArrayExpression value must be an array.');
183
        }
184
185
        return $value;
186
    }
187
}
188