Skip to content

Commit eddc8c2

Browse files
authored
fix: support for more complex Array Tuple params (#268)
1 parent 4384ce7 commit eddc8c2

File tree

2 files changed

+53
-7
lines changed

2 files changed

+53
-7
lines changed

src/Param/ParamValueConverterRegistry.php

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
use function explode;
1616
use function implode;
1717
use function in_array;
18+
use function is_array;
1819
use function is_string;
1920
use function json_encode;
2021
use function sprintf;
2122
use function str_replace;
23+
use function strlen;
2224
use function strtolower;
2325
use function trim;
2426

@@ -101,7 +103,7 @@ public function __construct()
101103
return $v;
102104
}
103105

104-
$types = array_map(static fn ($type) => explode(' ', trim($type))[1], explode(',', $type->params));
106+
$types = array_map(static fn ($type) => explode(' ', trim($type))[1], $this->splitTypes($type->params));
105107

106108
return sprintf('[%s]', implode(',', array_map(
107109
fn (array $row) => sprintf('(%s)', implode(',', array_map(
@@ -167,17 +169,23 @@ public function __construct()
167169
return $this->get($innerType)($v, $innerType, true);
168170
}, $v),
169171
)),
170-
'Tuple' => function (array|string $v, Type $type) {
171-
if (is_string($v)) {
172+
'Tuple' => function (mixed $v, Type $type) {
173+
if (! is_array($v)) {
172174
return $v;
173175
}
174176

175-
$types = array_map(static fn ($p) => trim($p), explode(',', $type->params));
177+
$innerTypes = $this->splitTypes($type->params);
176178

177-
return '(' . implode(
179+
$innerExpression = implode(
178180
',',
179-
array_map(fn (mixed $i) => $this->get($types[$i])($v[$i], null, true), array_keys($v)),
180-
) . ')';
181+
array_map(function (int $i) use ($innerTypes, $v) {
182+
$innerType = Type::fromString($innerTypes[$i]);
183+
184+
return $this->get($innerType)($v[$i], $innerType, true);
185+
}, array_keys($v)),
186+
);
187+
188+
return '(' . $innerExpression . ')';
181189
},
182190
];
183191
$this->registry = $registry;
@@ -254,4 +262,36 @@ private static function dateIntervalConverter(): Closure
254262
{
255263
return static fn (int|float $v) => $v;
256264
}
265+
266+
/** @return list<string> */
267+
private function splitTypes(string $types): array
268+
{
269+
$result = [];
270+
$depth = 0;
271+
$current = '';
272+
273+
for ($i = 0; $i < strlen($types); $i++) {
274+
$char = $types[$i];
275+
if ($char === '(') {
276+
$depth++;
277+
} elseif ($char === ')') {
278+
$depth--;
279+
} elseif ($char === ',' && $depth === 0) {
280+
$result[] = $current;
281+
$current = '';
282+
283+
continue;
284+
}
285+
286+
$current .= $char;
287+
}
288+
289+
$current = trim($current);
290+
291+
if ($current !== '') {
292+
$result[] = $current;
293+
}
294+
295+
return $result;
296+
}
257297
}

tests/Param/ParamValueConverterRegistryTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ public static function providerConvert(): Generator
113113
yield 'Array LC' => ['Array(LowCardinality(String))', "['foo','bar']", "['foo','bar']"];
114114
yield 'Array (array)' => ['Array(String)', ['foo', 'bar'], "['foo','bar']"];
115115
yield 'Array Tuple' => ['Array(Tuple(String, String))', [['foo', 'bar']], "[('foo','bar')]"];
116+
yield 'Array Tuple Complex' => [
117+
'Array(Tuple(Tuple(UInt32, UUID), String))',
118+
[[[1, '084caa96-915b-449d-8fc6-0292c73d6399'], 'bar']],
119+
"[((1,'084caa96-915b-449d-8fc6-0292c73d6399'),'bar')]",
120+
];
121+
116122
yield 'Tuple' => ['Tuple(String, Int8)', "('k',1)", "('k',1)"];
117123
yield 'Tuple (array)' => ['Tuple(String, Int8)', ['k', 1], "('k',1)"];
118124

0 commit comments

Comments
 (0)