Skip to content

Commit 3cb4b43

Browse files
committed
Fix QueryString php variable extraction #146
1 parent 8e02a01 commit 3cb4b43

File tree

2 files changed

+52
-8
lines changed

2 files changed

+52
-8
lines changed

interfaces/QueryString.php

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -249,23 +249,27 @@ private static function extractPhpVariable(array $data, array|string $name, stri
249249
}
250250

251251
$key = substr($name, 0, $leftBracketPosition);
252+
if ('' === $key) {
253+
$key = '0';
254+
}
255+
252256
if (!array_key_exists($key, $data) || !is_array($data[$key])) {
253257
$data[$key] = [];
254258
}
255259

256-
$index = substr($name, $leftBracketPosition + 1, $rightBracketPosition - $leftBracketPosition - 1);
257-
if ('' === $index) {
260+
$remaining = substr($name, $rightBracketPosition + 1);
261+
if (!str_starts_with($remaining, '[') || !str_contains($remaining, ']')) {
262+
$remaining = '';
263+
}
264+
265+
$name = substr($name, $leftBracketPosition + 1, $rightBracketPosition - $leftBracketPosition - 1).$remaining;
266+
if ('' === $name) {
258267
$data[$key][] = $value;
259268

260269
return $data;
261270
}
262271

263-
$remaining = substr($name, $rightBracketPosition + 1);
264-
if (!str_starts_with($remaining, '[') || false === strpos($remaining, ']', 1)) {
265-
$remaining = '';
266-
}
267-
268-
$data[$key] = self::extractPhpVariable($data[$key], $index.$remaining, $value);
272+
$data[$key] = self::extractPhpVariable($data[$key], $name, $value);
269273

270274
return $data;
271275
}

interfaces/QueryStringTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use League\Uri\Components\Fragment;
1616
use League\Uri\Exceptions\SyntaxError;
1717
use PHPUnit\Framework\Attributes\DataProvider;
18+
use PHPUnit\Framework\Attributes\Test;
1819
use PHPUnit\Framework\TestCase;
1920
use Stringable;
2021

@@ -477,4 +478,43 @@ public static function queryProvider(): array
477478
'Encoded unreserved chars are not decoded' => ['q=v%61lue', 'q=value'],
478479
];
479480
}
481+
482+
#[Test]
483+
#[DataProvider('queryWithInnerEmptyBracetsProvider')]
484+
public function it_should_parse_empty_bracets_issue_146(string $query, string $expected): void
485+
{
486+
$data = QueryString::extract($query);
487+
parse_str($query, $result);
488+
489+
self::assertSame($data, $result);
490+
self::assertSame($expected, http_build_query($data, '', '&', PHP_QUERY_RFC3986));
491+
}
492+
493+
public static function queryWithInnerEmptyBracetsProvider(): iterable
494+
{
495+
yield 'query with on level empty bracets' => [
496+
'query' => 'foo[]=bar',
497+
'expected' => 'foo%5B0%5D=bar',
498+
];
499+
500+
yield 'query with two level bracets' => [
501+
'query' => 'key[][][foo][9]=bar',
502+
'expected' => 'key%5B0%5D%5B0%5D%5Bfoo%5D%5B9%5D=bar',
503+
];
504+
505+
yield 'query with invalid remaining; close bracet without an opening bracet' => [
506+
'query' => 'key[][]foo][9]=bar',
507+
'expected' => 'key%5B0%5D%5B0%5D=bar',
508+
];
509+
510+
yield 'query with invalid remaining; no opening bracet' => [
511+
'query' => 'key[]9=bar',
512+
'expected' => 'key%5B0%5D=bar',
513+
];
514+
515+
yield 'query with invalid remaining; opening bracet no at the start of the remaining string' => [
516+
'query' => 'key[]9[]=bar',
517+
'expected' => 'key%5B0%5D=bar',
518+
];
519+
}
480520
}

0 commit comments

Comments
 (0)