-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Form] Allow more permissive form input name and ID #53981
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 7.4
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -632,7 +632,7 @@ public function setIsEmptyCallback(?callable $isEmptyCallback): static | |
final public static function validateName(?string $name): void | ||
{ | ||
if (!self::isValidName($name)) { | ||
throw new InvalidArgumentException(sprintf('The name "%s" contains illegal characters. Names should start with a letter, digit or underscore and only contain letters, digits, numbers, underscores ("_"), hyphens ("-") and colons (":").', $name)); | ||
throw new InvalidArgumentException(sprintf('The name "%s" contains illegal characters or equals to "isindex". Names should only contain letters, digits, underscores ("_"), hyphens ("-") and colons (":").', $name)); | ||
} | ||
} | ||
|
||
|
@@ -642,12 +642,12 @@ final public static function validateName(?string $name): void | |
* A name is accepted if it | ||
* | ||
* * is empty | ||
* * starts with a letter, digit or underscore | ||
* * contains only letters, digits, numbers, underscores ("_"), | ||
* hyphens ("-") and colons (":") | ||
* * is not equal to "isindex" | ||
*/ | ||
final public static function isValidName(?string $name): bool | ||
{ | ||
return '' === $name || null === $name || preg_match('/^[a-zA-Z0-9_][a-zA-Z0-9_\-:]*$/D', $name); | ||
return ('' === $name || null === $name || preg_match('/^[a-zA-Z0-9_\-:]*$/D', $name)) && 'isindex' !== $name; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we fordbid There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because Yeah, it's a BC break. Any idea how to handle this case? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let‘s deprecate it in 7.1 and don’t accept it in 8.0. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is wrong though. Most of the Symfony form names could use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just adding that it's not only
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ | |
|
||
use PHPUnit\Framework\TestCase; | ||
use Symfony\Component\EventDispatcher\EventDispatcher; | ||
use Symfony\Component\Form\Exception\InvalidArgumentException; | ||
use Symfony\Component\Form\FormConfigBuilder; | ||
use Symfony\Component\Form\NativeRequestHandler; | ||
|
||
|
@@ -21,56 +22,86 @@ | |
*/ | ||
class FormConfigTest extends TestCase | ||
{ | ||
public static function getHtml4Ids() | ||
public static function provideInvalidFormInputName(): iterable | ||
{ | ||
return [ | ||
['isindex'], | ||
['#'], | ||
['a#'], | ||
['a$'], | ||
['a%'], | ||
['a '], | ||
["a\t"], | ||
["a\n"], | ||
|
||
// Periods are allowed by the HTML4 spec, but disallowed by us | ||
// because they break the generated property paths | ||
['a.'], | ||
]; | ||
} | ||
|
||
/** | ||
* @dataProvider provideInvalidFormInputName | ||
*/ | ||
public function testInvalidFormInputName(string $name) | ||
{ | ||
$this->expectException(InvalidArgumentException::class); | ||
$this->expectExceptionMessage(sprintf('The name "%s" contains illegal characters or equals to "isindex". Names should only contain letters, digits, underscores ("_"), hyphens ("-") and colons (":").', $name)); | ||
|
||
new FormConfigBuilder($name, null, new EventDispatcher()); | ||
} | ||
|
||
public static function provideValidFormInputName(): iterable | ||
{ | ||
return [ | ||
asispts marked this conversation as resolved.
Show resolved
Hide resolved
|
||
['z0'], | ||
['A0'], | ||
['A9'], | ||
['Z0'], | ||
['#', 'Symfony\Component\Form\Exception\InvalidArgumentException'], | ||
['a#', 'Symfony\Component\Form\Exception\InvalidArgumentException'], | ||
['a$', 'Symfony\Component\Form\Exception\InvalidArgumentException'], | ||
['a%', 'Symfony\Component\Form\Exception\InvalidArgumentException'], | ||
['a ', 'Symfony\Component\Form\Exception\InvalidArgumentException'], | ||
["a\t", 'Symfony\Component\Form\Exception\InvalidArgumentException'], | ||
["a\n", 'Symfony\Component\Form\Exception\InvalidArgumentException'], | ||
['a-'], | ||
['a_'], | ||
['a:'], | ||
// Periods are allowed by the HTML4 spec, but disallowed by us | ||
// because they break the generated property paths | ||
['a.', 'Symfony\Component\Form\Exception\InvalidArgumentException'], | ||
|
||
// Contrary to the HTML4 spec, we allow names starting with a | ||
// number, otherwise naming fields by collection indices is not | ||
// possible. | ||
// For root forms, leading digits will be stripped from the | ||
// "id" attribute to produce valid HTML4. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this comment still accurate ? |
||
['0'], | ||
['9'], | ||
|
||
// Contrary to the HTML4 spec, we allow names starting with an | ||
// underscore, since this is already a widely used practice in | ||
// Symfony. | ||
// For root forms, leading underscores will be stripped from the | ||
// "id" attribute to produce valid HTML4. | ||
['_'], | ||
|
||
// Integers are allowed | ||
[0], | ||
[123], | ||
|
||
// NULL is allowed | ||
[null], | ||
|
||
// Allowed in HTML 5 specification | ||
// See: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fe-name | ||
['_charset_'], | ||
['-x'], | ||
[':x'], | ||
['isINDEX'], | ||
|
||
// This value shouldn't be allowed. | ||
// However, many tests in Form component require empty name | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment is wrong to me. The fullname of a non-compound field should not be empty (as HTML form inputs will need a non-empty name). But this is not what is validated by the validation you run here. For instance, a perfectly valid use case is to have an empty name for the root form, so that names of fields look like |
||
[''], | ||
]; | ||
} | ||
|
||
/** | ||
* @dataProvider getHtml4Ids | ||
* @dataProvider provideValidFormInputName | ||
*/ | ||
public function testNameAcceptsOnlyNamesValidAsIdsInHtml4($name, $expectedException = null) | ||
public function testValidFormInputName(string|int|null $name) | ||
{ | ||
if (null !== $expectedException) { | ||
$this->expectException($expectedException); | ||
} | ||
|
||
$formConfigBuilder = new FormConfigBuilder($name, null, new EventDispatcher()); | ||
|
||
$this->assertSame((string) $name, $formConfigBuilder->getName()); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be kept IMO as written in #53976 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this change is kept (which I think is good - see my answer at #53976 (comment) ), then it's a BC break and therefore should target v8.0.