diff --git a/src/Forms/RequiredFields.php b/src/Forms/RequiredFields.php index d7c725baf..3f817aa49 100644 --- a/src/Forms/RequiredFields.php +++ b/src/Forms/RequiredFields.php @@ -116,8 +116,15 @@ class RequiredFields extends Validator $error = (count($value ?? [])) ? false : true; } } else { - // assume a string or integer - $error = (strlen($value ?? '')) ? false : true; + $stringValue = (string) $value; + if ($formField instanceof TreeDropdownField) { + // 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 + // the null value will have been converted to '' by the time it gets to this point + $error = in_array($stringValue, ['0', '']); + } else { + $error = strlen($stringValue) > 0 ? false : true; + } } if ($formField && $error) { diff --git a/src/Forms/TreeDropdownField.php b/src/Forms/TreeDropdownField.php index e61e5411d..3cea2178b 100644 --- a/src/Forms/TreeDropdownField.php +++ b/src/Forms/TreeDropdownField.php @@ -250,7 +250,12 @@ class TreeDropdownField extends FormField $this->addExtraClass('single'); - parent::__construct($name, $title); + // Set a default value of 0 instead of null + // Because TreedropdownField requires SourceObject to have the Hierarchy extension, make the default + // value the same as the default value for a RelationID, which is 0. + $value = 0; + + parent::__construct($name, $title, $value); } /** @@ -984,4 +989,16 @@ class TreeDropdownField extends FormField $this->showSelectedPath = $showSelectedPath; return $this; } + + /** + * @return array + */ + public function getSchemaValidation() + { + $validationList = parent::getSchemaValidation(); + if (array_key_exists('required', $validationList)) { + $validationList['required'] = ['extraEmptyValues' => ['0']]; + } + return $validationList; + } } diff --git a/tests/php/Forms/RequiredFieldsTest.php b/tests/php/Forms/RequiredFieldsTest.php index f620a63c1..7da79eda2 100644 --- a/tests/php/Forms/RequiredFieldsTest.php +++ b/tests/php/Forms/RequiredFieldsTest.php @@ -4,10 +4,12 @@ namespace SilverStripe\Forms\Tests; use SilverStripe\Dev\SapphireTest; use SilverStripe\Forms\RequiredFields; +use SilverStripe\Forms\Form; +use SilverStripe\Forms\TreeDropdownField; +use SilverStripe\Security\Group; class RequiredFieldsTest extends SapphireTest { - public function testConstructingWithArray() { //can we construct with an array? @@ -286,4 +288,18 @@ class RequiredFieldsTest extends SapphireTest "Unexpectedly returned true for a non-existent field" ); } + + public function testTreedropFieldValidation() + { + $form = new Form(); + $field = new TreeDropdownField('TestField', 'TestField', Group::class); + $form->Fields()->push($field); + $validator = new RequiredFields('TestField'); + $validator->setForm($form); + // blank string and '0' are fail required field validation + $this->assertFalse($validator->php(['TestField' => ''])); + $this->assertFalse($validator->php(['TestField' => '0'])); + // '1' passes required field validation + $this->assertTrue($validator->php(['TestField' => '1'])); + } } diff --git a/tests/php/Forms/TreeDropdownFieldTest.php b/tests/php/Forms/TreeDropdownFieldTest.php index 7636480c7..83e091f89 100644 --- a/tests/php/Forms/TreeDropdownFieldTest.php +++ b/tests/php/Forms/TreeDropdownFieldTest.php @@ -10,6 +10,7 @@ use SilverStripe\Dev\SapphireTest; use SilverStripe\Control\HTTPRequest; use SilverStripe\Forms\FieldList; use SilverStripe\Forms\Form; +use SilverStripe\Forms\RequiredFields; use SilverStripe\Forms\TreeDropdownField; use SilverStripe\ORM\DataObject; use SilverStripe\ORM\Tests\HierarchyTest\HierarchyOnSubclassTestObject; @@ -52,6 +53,22 @@ class TreeDropdownFieldTest extends SapphireTest ); } + public function testGetSchemaValidation(): void + { + // field is not required + $field = new TreeDropdownField('TestTree', 'Test tree', Folder::class); + $expected = []; + $this->assertSame($expected, $field->getSchemaValidation()); + // field is required + $fieldList = new FieldList([$field]); + $validator = new RequiredFields('TestTree'); + new Form(null, null, $fieldList, null, $validator); + $expected = [ + 'required' => ['extraEmptyValues' => ['0']], + ]; + $this->assertSame($expected, $field->getSchemaValidation()); + } + public function testTreeSearchJson() { $field = new TreeDropdownField('TestTree', 'Test tree', Folder::class);