Skip to content
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

ENH Config to toggle allowing whitespace only in Requiredfields #11491

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions src/Forms/RequiredFields.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
*/
class RequiredFields extends Validator
{
/**
* Whether to globally allow whitespace only as a valid value for a required field
* Can be overridden on a per-instance basis
*/
private static bool $allow_whitespace_only = true;

/**
* List of required fields
Expand All @@ -22,6 +27,12 @@ class RequiredFields extends Validator
*/
protected $required;

/**
* Whether to allow whitespace only as a valid value for a required field for this instance
* By default, this is set to null which will revert to the global default
*/
private ?bool $allowWhitespaceOnly = null;

/**
* Pass each field to be validated as a separate argument to the constructor
* of this object. (an array of elements are ok).
Expand All @@ -41,6 +52,22 @@ public function __construct()
parent::__construct();
}

/**
* Get whether to allow whitespace only as a valid value for a required field
*/
public function getAllowWhitespaceOnly(): ?bool
{
return $this->allowWhitespaceOnly ?? static::config()->get('allow_whitespace_only');
}

/**
* Set whether to allow whitespace only as a valid value for a required field
*/
public function setAllowWhitespaceOnly(?bool $allow)
{
$this->allowWhitespaceOnly = $allow;
}

/**
* Clears all the validation from this object.
*
Expand Down Expand Up @@ -122,6 +149,10 @@ public function php($data)
}
} else {
$stringValue = (string) $value;
if (!$this->getAllowWhitespaceOnly()) {
$stringValue = preg_replace('/^\s+/u', '', $stringValue);
$stringValue = preg_replace('/\s+$/u', '', $stringValue);
}
if (is_a($formField, HasOneRelationFieldInterface::class)) {
// test for blank string as well as '0' because older versions of silverstripe/admin FormBuilder
// forms created using redux-form would have a value of null for unsaved records
Expand Down
133 changes: 133 additions & 0 deletions tests/php/Forms/RequiredFieldsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -322,4 +324,135 @@ public function testHasOneRelationFieldInterfaceValidation(string $className)
// '1' passes required field validation
$this->assertTrue($validator->php(['TestField' => '1']));
}

public static function provideAllowWhitespaceOnly(): array
{
return [
'no-ws-false' => [
'value' => 'abc',
'allowWhitespaceOnly' => false,
'expected' => true,
],
'no-ws-true' => [
'value' => 'abc',
'allowWhitespaceOnly' => true,
'expected' => true,
],
'left-ws-false' => [
'value' => ' abc',
'allowWhitespaceOnly' => false,
'expected' => true,
],
'left-ws-true' => [
'value' => ' abc',
'allowWhitespaceOnly' => true,
'expected' => true,
],
'right-ws-false' => [
'value' => 'abc ',
'allowWhitespaceOnly' => false,
'expected' => true,
],
'right-ws-true' => [
'value' => 'abc ',
'allowWhitespaceOnly' => true,
'expected' => true,
],
'both-ws-false' => [
'value' => ' abc ',
'allowWhitespaceOnly' => false,
'expected' => true,
],
'both-ws-true' => [
'value' => ' abc ',
'allowWhitespaceOnly' => true,
'expected' => true,
],
'only-ws-false' => [
'value' => ' ',
'allowWhitespaceOnly' => false,
'expected' => false,
],
'only-ws-true' => [
'value' => ' ',
'allowWhitespaceOnly' => true,
'expected' => true,
],
'only-ws-nbsp-false' => [
'value' => "\xc2\xa0",
'allowWhitespaceOnly' => false,
'expected' => false,
],
'only-ws-nbsp-true' => [
'value' => "\xc2\xa0",
'allowWhitespaceOnly' => true,
'expected' => true,
],
'only-ws-unicode-false' => [
// zero width no-break space
'value' => "\u{2028}",
'allowWhitespaceOnly' => false,
'expected' => false,
],
'only-ws-unicode-true' => [
// zero width no-break space
'value' => "\u{2028}",
'allowWhitespaceOnly' => true,
'expected' => true,
],
'no-value-false' => [
'value' => '',
'allowWhitespaceOnly' => false,
'expected' => false,
],
'no-value-true' => [
'value' => '',
'allowWhitespaceOnly' => true,
'expected' => false,
],
];
}

/**
* @dataProvider provideAllowWhitespaceOnly
*/
public function testAllowWhitespaceOnlyConfig(
string $value,
bool $allowWhitespaceOnly,
bool $expected,
): void {
$validator = new RequiredFields(['TestField']);
$this->assertSame(true, $validator->getAllowWhitespaceOnly());
$field = new TextField('TestField');
$field->setValue($value);
$form = new Form(null, null, new FieldList([$field]), null, $validator);
RequiredFields::config()->set('allow_whitespace_only', $allowWhitespaceOnly);
$result = $validator->validate($form);
$this->assertEquals($expected, $result->isValid());
}

/**
* @dataProvider provideAllowWhitespaceOnly
*/
public function testAllowWhitespaceOnlySetter(
string $value,
bool $allowWhitespaceOnly,
bool $expected,
): void {
$validator = new RequiredFields(['TestField']);
$validator->setAllowWhitespaceOnly($allowWhitespaceOnly);
$this->assertSame($allowWhitespaceOnly, $validator->getAllowWhitespaceOnly());
$field = new TextField('TestField');
$field->setValue($value);
$form = new Form(null, null, new FieldList([$field]), null, $validator);
$result = $validator->validate($form);
$this->assertEquals($expected, $result->isValid());
// assert that global config makes no difference
RequiredFields::config()->set('allow_whitespace_only', true);
$result = $validator->validate($form);
$this->assertEquals($expected, $result->isValid());
RequiredFields::config()->set('allow_whitespace_only', false);
$result = $validator->validate($form);
$this->assertEquals($expected, $result->isValid());
}
}
Loading