Skip to content

Commit

Permalink
ENH Config to toggle allowing whitespace only in Requiredfields
Browse files Browse the repository at this point in the history
  • Loading branch information
emteknetnz committed Dec 5, 2024
1 parent 4d78f78 commit beaefae
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 0 deletions.
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());
}
}

0 comments on commit beaefae

Please sign in to comment.