Skip to content

Commit

Permalink
Be strict about supported name string syntax to avoid bizzare transla…
Browse files Browse the repository at this point in the history
…tion issues
  • Loading branch information
theseer committed Aug 12, 2023
1 parent 76d9931 commit 0b003c5
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 7 deletions.
8 changes: 7 additions & 1 deletion src/formdata/FormData.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public function value(string $key): string {
$lookupKey = $this->translateKey($key);

if (!$this->has($lookupKey)) {
throw new FormDataException(sprintf('No such key: %s', $key));
throw new FormDataException(sprintf('No such key: %s (%s)', $key, $lookupKey));
}

return $this->values[$lookupKey];
Expand All @@ -72,6 +72,12 @@ private function flattenArray(array $values, array $keyPrefixes = []): void {
}

private function translateKey(string $key): string {
if (preg_match('/^[^\p{C}\[\]]+(?:\[[^\p{C}\[\]]*\])*$/u', $key) === 0) {
throw new FormDataException(
sprintf('Invalid key name syntax ("%s") - cannot translate', $key)
);
}

return implode('|', preg_split('/\[|\]/', $key, flags: PREG_SPLIT_NO_EMPTY));
}
}
43 changes: 37 additions & 6 deletions tests/formdata/FormDataTest.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
<?php declare(strict_types = 1);
namespace Templado\Engine;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use stdClass;

/**
* @covers \Templado\Engine\FormData
*/
#[CoversClass(FormData::class)]
class FormDataTest extends TestCase {

/**
* @dataProvider validDataProvider
*/
#[DataProvider('validDataProvider')]
public function testCanBeInstantiatedWithUsableData(array $data, string $key): void {
$formdata = new FormData('foo', $data);
$this->assertInstanceOf(FormData::class, $formdata);
Expand Down Expand Up @@ -69,4 +67,37 @@ public function testValueOfExisingKeyCanBeRetrieved(): void {
$formdata = new FormData('test', ['a' => 'value']);
$this->assertEquals('value', $formdata->value('a'));
}

public function testHandlesMixedNestedArrayTypes(): void {
$formdata = new FormData('test', ['a' => 'a', 'b' => ['c','d'], 'e' => ['f' => ['g' => 'h']]]);
$this->assertEquals('a', $formdata->value('a'));
$this->assertEquals('c', $formdata->value('b[0]'));
$this->assertEquals('d', $formdata->value('b[1]'));
$this->assertEquals('h', $formdata->value('e[f][g]'));
}

#[DataProvider('invalidNameProvider')]
public function testThrowsExceptionOnInvalidNameSyntax(string $input): void {
$this->expectException(FormDataException::class);
(new FormData('foo', []))->has($input);
}

public static function invalidNameProvider(): array {
return [
'foo[]0' => ['foo[]0'],
'foo[0]a' => ['foo[0]a'],
'foo[0]a[1]' => ['foo[0]a[1]'],
'foo[' => ['foo['],
'foo]' => ['foo]'],
'foo[a[]]' => ['foo[a[]]'],
'[]foo' => ['[]foo'],
];
}

public function testAcceptsValidNames(): void {
$this->assertFalse(
(new FormData('foo', []))->has("😀")
);
}

}

0 comments on commit 0b003c5

Please sign in to comment.