Skip to content

Commit

Permalink
Fix QueryString php variable extraction #146
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod committed Dec 4, 2024
1 parent 8e02a01 commit 3cb4b43
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 8 deletions.
20 changes: 12 additions & 8 deletions interfaces/QueryString.php
Original file line number Diff line number Diff line change
Expand Up @@ -249,23 +249,27 @@ private static function extractPhpVariable(array $data, array|string $name, stri
}

$key = substr($name, 0, $leftBracketPosition);
if ('' === $key) {
$key = '0';
}

if (!array_key_exists($key, $data) || !is_array($data[$key])) {
$data[$key] = [];
}

$index = substr($name, $leftBracketPosition + 1, $rightBracketPosition - $leftBracketPosition - 1);
if ('' === $index) {
$remaining = substr($name, $rightBracketPosition + 1);
if (!str_starts_with($remaining, '[') || !str_contains($remaining, ']')) {
$remaining = '';
}

$name = substr($name, $leftBracketPosition + 1, $rightBracketPosition - $leftBracketPosition - 1).$remaining;
if ('' === $name) {
$data[$key][] = $value;

return $data;
}

$remaining = substr($name, $rightBracketPosition + 1);
if (!str_starts_with($remaining, '[') || false === strpos($remaining, ']', 1)) {
$remaining = '';
}

$data[$key] = self::extractPhpVariable($data[$key], $index.$remaining, $value);
$data[$key] = self::extractPhpVariable($data[$key], $name, $value);

return $data;
}
Expand Down
40 changes: 40 additions & 0 deletions interfaces/QueryStringTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use League\Uri\Components\Fragment;
use League\Uri\Exceptions\SyntaxError;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Stringable;

Expand Down Expand Up @@ -477,4 +478,43 @@ public static function queryProvider(): array
'Encoded unreserved chars are not decoded' => ['q=v%61lue', 'q=value'],
];
}

#[Test]
#[DataProvider('queryWithInnerEmptyBracetsProvider')]
public function it_should_parse_empty_bracets_issue_146(string $query, string $expected): void
{
$data = QueryString::extract($query);
parse_str($query, $result);

self::assertSame($data, $result);
self::assertSame($expected, http_build_query($data, '', '&', PHP_QUERY_RFC3986));
}

public static function queryWithInnerEmptyBracetsProvider(): iterable
{
yield 'query with on level empty bracets' => [
'query' => 'foo[]=bar',
'expected' => 'foo%5B0%5D=bar',
];

yield 'query with two level bracets' => [
'query' => 'key[][][foo][9]=bar',
'expected' => 'key%5B0%5D%5B0%5D%5Bfoo%5D%5B9%5D=bar',
];

yield 'query with invalid remaining; close bracet without an opening bracet' => [
'query' => 'key[][]foo][9]=bar',
'expected' => 'key%5B0%5D%5B0%5D=bar',
];

yield 'query with invalid remaining; no opening bracet' => [
'query' => 'key[]9=bar',
'expected' => 'key%5B0%5D=bar',
];

yield 'query with invalid remaining; opening bracet no at the start of the remaining string' => [
'query' => 'key[]9[]=bar',
'expected' => 'key%5B0%5D=bar',
];
}
}

0 comments on commit 3cb4b43

Please sign in to comment.