|
4 | 4 |
|
5 | 5 | namespace Yiisoft\Db\Pgsql\Column; |
6 | 6 |
|
7 | | -use Traversable; |
8 | | -use Yiisoft\Db\Constant\ColumnType; |
9 | | -use Yiisoft\Db\Constant\PhpType; |
10 | | -use Yiisoft\Db\Expression\ArrayExpression; |
11 | | -use Yiisoft\Db\Expression\ExpressionInterface; |
12 | 7 | use Yiisoft\Db\Pgsql\ArrayParser; |
13 | | -use Yiisoft\Db\Schema\Column\AbstractColumnSchema; |
14 | | -use Yiisoft\Db\Schema\Column\ColumnSchemaInterface; |
| 8 | +use Yiisoft\Db\Schema\Column\ArrayColumnSchema as BaseArrayColumnSchema; |
| 9 | +use Yiisoft\Db\Syntax\ParserToArrayInterface; |
15 | 10 |
|
16 | | -use function array_map; |
17 | | -use function array_walk_recursive; |
18 | | -use function is_array; |
19 | | -use function is_iterable; |
20 | | -use function is_string; |
21 | | -use function iterator_to_array; |
22 | | - |
23 | | -final class ArrayColumnSchema extends AbstractColumnSchema |
| 11 | +final class ArrayColumnSchema extends BaseArrayColumnSchema |
24 | 12 | { |
25 | | - /** |
26 | | - * @var ColumnSchemaInterface|null The column of an array item. |
27 | | - */ |
28 | | - private ColumnSchemaInterface|null $column = null; |
29 | | - |
30 | | - /** |
31 | | - * @var int The dimension of array, must be greater than 0. |
32 | | - */ |
33 | | - private int $dimension = 1; |
34 | | - |
35 | | - /** |
36 | | - * @psalm-param ColumnType::* $type |
37 | | - */ |
38 | | - public function __construct( |
39 | | - string $type = ColumnType::ARRAY, |
40 | | - ) { |
41 | | - parent::__construct($type); |
42 | | - } |
43 | | - |
44 | | - /** |
45 | | - * Set column of an array item. |
46 | | - */ |
47 | | - public function column(ColumnSchemaInterface|null $column): static |
48 | | - { |
49 | | - $this->column = $column; |
50 | | - return $this; |
51 | | - } |
52 | | - |
53 | | - /** |
54 | | - * @return ColumnSchemaInterface the column of an array item. |
55 | | - */ |
56 | | - public function getColumn(): ColumnSchemaInterface |
57 | | - { |
58 | | - if ($this->column === null) { |
59 | | - $this->column = (new ColumnFactory())->fromDbType($this->getDbType() ?? ''); |
60 | | - $this->column->enumValues($this->getEnumValues()); |
61 | | - $this->column->scale($this->getScale()); |
62 | | - $this->column->size($this->getSize()); |
63 | | - } |
64 | | - |
65 | | - return $this->column; |
66 | | - } |
67 | | - |
68 | | - /** |
69 | | - * Set dimension of an array, must be greater than 0. |
70 | | - */ |
71 | | - public function dimension(int $dimension): static |
72 | | - { |
73 | | - $this->dimension = $dimension; |
74 | | - return $this; |
75 | | - } |
76 | | - |
77 | | - /** |
78 | | - * @return int the dimension of the array. |
79 | | - */ |
80 | | - public function getDimension(): int |
81 | | - { |
82 | | - return $this->dimension; |
83 | | - } |
84 | | - |
85 | | - public function getPhpType(): string |
86 | | - { |
87 | | - return PhpType::ARRAY; |
88 | | - } |
89 | | - |
90 | | - public function dbTypecast(mixed $value): ExpressionInterface|null |
91 | | - { |
92 | | - if ($value === null || $value instanceof ExpressionInterface) { |
93 | | - return $value; |
94 | | - } |
95 | | - |
96 | | - if ($this->dimension === 1 && is_array($value)) { |
97 | | - $value = array_map($this->getColumn()->dbTypecast(...), $value); |
98 | | - } else { |
99 | | - $value = $this->dbTypecastArray($value, $this->dimension); |
100 | | - } |
101 | | - |
102 | | - return new ArrayExpression($value, $this->getDbType() ?? $this->getColumn()->getDbType(), $this->dimension); |
103 | | - } |
104 | | - |
105 | | - public function phpTypecast(mixed $value): array|null |
106 | | - { |
107 | | - if (is_string($value)) { |
108 | | - $value = (new ArrayParser())->parse($value); |
109 | | - } |
110 | | - |
111 | | - if (!is_array($value)) { |
112 | | - return null; |
113 | | - } |
114 | | - |
115 | | - if ($this->getType() === ColumnType::STRING) { |
116 | | - return $value; |
117 | | - } |
118 | | - |
119 | | - $column = $this->getColumn(); |
120 | | - |
121 | | - if ($this->dimension === 1 && $column->getType() !== ColumnType::JSON) { |
122 | | - return array_map($column->phpTypecast(...), $value); |
123 | | - } |
124 | | - |
125 | | - array_walk_recursive($value, function (string|null &$val) use ($column): void { |
126 | | - $val = $column->phpTypecast($val); |
127 | | - }); |
128 | | - |
129 | | - return $value; |
130 | | - } |
131 | | - |
132 | | - /** |
133 | | - * Recursively converts array values for use in a db query. |
134 | | - * |
135 | | - * @param mixed $value The array or iterable object. |
136 | | - * @param int $dimension The array dimension. Should be more than 0. |
137 | | - * |
138 | | - * @return array|null Converted values. |
139 | | - */ |
140 | | - private function dbTypecastArray(mixed $value, int $dimension): array|null |
| 13 | + protected function getParser(): ParserToArrayInterface |
141 | 14 | { |
142 | | - if ($value === null) { |
143 | | - return null; |
144 | | - } |
145 | | - |
146 | | - if (!is_iterable($value)) { |
147 | | - return []; |
148 | | - } |
149 | | - |
150 | | - if ($dimension <= 1) { |
151 | | - return array_map( |
152 | | - $this->getColumn()->dbTypecast(...), |
153 | | - $value instanceof Traversable |
154 | | - ? iterator_to_array($value, false) |
155 | | - : $value |
156 | | - ); |
157 | | - } |
158 | | - |
159 | | - $items = []; |
160 | | - |
161 | | - foreach ($value as $val) { |
162 | | - $items[] = $this->dbTypecastArray($val, $dimension - 1); |
163 | | - } |
164 | | - |
165 | | - return $items; |
| 15 | + return new ArrayParser(); |
166 | 16 | } |
167 | 17 | } |
0 commit comments