diff --git a/src/Forms/RequiredFields.php b/src/Forms/RequiredFields.php index 3f0e055c0b7..30a23df27d8 100644 --- a/src/Forms/RequiredFields.php +++ b/src/Forms/RequiredFields.php @@ -3,6 +3,7 @@ namespace SilverStripe\Forms; use SilverStripe\ORM\ArrayLib; +use SilverStripe\Dev\Deprecation; /** * Required Fields allows you to set which fields need to be present before @@ -11,9 +12,15 @@ * * Validation is performed on a field by field basis through * {@link FormField::validate}. + * + * @deprecated 5.4.0 Will be renamed to SilverStripe\Forms\RequiredFieldsValidator */ class RequiredFields extends Validator { + /** + * Whether to allow whitespace only as a valid value for a required fields + */ + private static bool $allow_whitespace_only = true; /** * List of required fields @@ -28,6 +35,7 @@ class RequiredFields extends Validator */ public function __construct() { + Deprecation::noticeWithNoReplacment('5.4.0', 'Will be renamed to SilverStripe\\Forms\\RequiredFieldsValidator', Deprecation::SCOPE_CLASS); $required = func_get_args(); if (isset($required[0]) && is_array($required[0])) { $required = $required[0]; @@ -128,6 +136,10 @@ public function php($data) // the null value will have been converted to '' by the time it gets to this point $error = in_array($stringValue, ['0', '']); } else { + if (!static::config()->get('allow_whitespace_only')) { + $stringValue = preg_replace('/^\s+/u', '', $stringValue); + $stringValue = preg_replace('/\s+$/u', '', $stringValue); + } $error = strlen($stringValue) > 0 ? false : true; } } diff --git a/tests/php/Forms/RequiredFieldsTest.php b/tests/php/Forms/RequiredFieldsTest.php index 5c080cfc9f9..fca6891c856 100644 --- a/tests/php/Forms/RequiredFieldsTest.php +++ b/tests/php/Forms/RequiredFieldsTest.php @@ -8,6 +8,8 @@ use SilverStripe\Forms\SearchableDropdownField; use SilverStripe\Forms\TreeDropdownField; use SilverStripe\Security\Group; +use SilverStripe\Forms\TextField; +use SilverStripe\Forms\FieldList; class RequiredFieldsTest extends SapphireTest { @@ -322,4 +324,71 @@ public function testHasOneRelationFieldInterfaceValidation(string $className) // '1' passes required field validation $this->assertTrue($validator->php(['TestField' => '1'])); } + + public static function provideAllowWhitespaceOnly(): array + { + return [ + 'no-ws' => [ + 'value' => 'abc', + 'expectedTrue' => true, + 'expectedFalse' => true, + ], + 'left-ws' => [ + 'value' => 'abc', + 'expectedTrue' => true, + 'expectedFalse' => true, + ], + 'right-ws' => [ + 'value' => 'abc', + 'expectedTrue' => true, + 'expectedFalse' => true, + ], + 'both-ws' => [ + 'value' => 'abc', + 'expectedTrue' => true, + 'expectedFalse' => true, + ], + 'only-ws' => [ + 'value' => ' ', + 'expectedTrue' => true, + 'expectedFalse' => false, + ], + 'only-ws-nbsp' => [ + 'value' => "\xc2\xa0", + 'expectedTrue' => true, + 'expectedFalse' => false, + ], + 'only-ws-unicode' => [ + // zero width no-break space + 'value' => "\u{2028}", + 'expectedTrue' => true, + 'expectedFalse' => false, + ], + 'no-value' => [ + 'value' => '', + 'expectedTrue' => false, + 'expectedFalse' => false, + ], + ]; + } + + /** + * @dataProvider provideAllowWhitespaceOnly + */ + public function testAllowWhitespaceOnly(string $value, bool $expectedTrue, bool $expectedFalse): void + { + $validator = new RequiredFields(['TestField']); + $field = new TextField('TestField'); + $field->setValue($value); + $form = new Form(null, null, new FieldList([$field]), null, $validator); + $expecteds = [ + true => $expectedTrue, + false => $expectedFalse, + ]; + foreach ($expecteds as $bool => $expected) { + RequiredFields::config()->set('allow_whitespace_only', $bool); + $result = $validator->validate($form); + $this->assertEquals($expected, $result->isValid(), $bool); + } + } }