Merge pull request #44 from chillu/pulls/validate-field-fix

Validate field fix
This commit is contained in:
Damian Mooyman 2016-01-22 12:53:30 +13:00
commit 078b0f51f9
3 changed files with 194 additions and 3 deletions

View File

@ -31,6 +31,7 @@ before_script:
- php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss - php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss
- cd ~/builds/ss - cd ~/builds/ss
- composer install - composer install
- composer require silverstripe/userforms
script: script:
- vendor/bin/phpunit spamprotection/tests - vendor/bin/phpunit spamprotection/tests

View File

@ -24,8 +24,17 @@ if (class_exists('EditableFormField')) {
'EditableNumericField' 'EditableNumericField'
); );
/**
* @var FormField
*/
protected $formField = null;
public function getFormField() public function getFormField()
{ {
if ($this->formField) {
return $this->formField;
}
// Get protector // Get protector
$protector = FormSpamProtectionExtension::get_protector(); $protector = FormSpamProtectionExtension::get_protector();
if (!$protector) { if (!$protector) {
@ -45,6 +54,17 @@ if (class_exists('EditableFormField')) {
return $protector->getFormField($this->Name, $this->Title, null); return $protector->getFormField($this->Name, $this->Title, null);
} }
/**
* @param FormField $field
* @return self
*/
public function setFormField(FormField $field)
{
$this->formField = $field;
return $this;
}
/** /**
* Gets the list of all candidate spam detectable fields on this field's form * Gets the list of all candidate spam detectable fields on this field's form
* *
@ -110,11 +130,46 @@ if (class_exists('EditableFormField')) {
return $fields; return $fields;
} }
/**
* Using custom validateField method
* as Spam Protection Field implementations may have their own error messages
* and may not be based on the field being required, e.g. Honeypot Field
*
* @param array $data
* @param Form $form
* @return void
*/
public function validateField($data, $form) public function validateField($data, $form)
{ {
$formField = $this->getFormField(); $formField = $this->getFormField();
if (!$formField->validate($form->getValidator())) {
$form->addErrorMessage($this->Name, $this->getErrorMessage()->HTML(), 'error', false); if (isset($data[$this->Name])) {
$formField->setValue($data[$this->Name]);
}
$validator = $form->getValidator();
if (!$formField->validate($validator)) {
$errors = $validator->getErrors();
$foundError = false;
// field validate implementation may not add error to validator
if (count($errors) > 0) {
// check if error already added from fields' validate method
foreach ($errors as $error) {
if ($error['fieldName'] == $this->Name) {
$foundError = $error;
break;
}
}
}
if ($foundError !== false) {
// use error messaging already set from validate method
$form->addErrorMessage($this->Name, $foundError['message'], $foundError['messageType'], false);
} else {
// fallback to custom message set in CMS or default message if none set
$form->addErrorMessage($this->Name, $this->getErrorMessage()->HTML(), 'error', false);
}
} }
} }

View File

@ -0,0 +1,135 @@
<?php
class EditableSpamProtectionFieldTest extends SapphireTest
{
protected $usesDatabase = true;
public function setUp()
{
parent::setUp();
Config::inst()->update(
'FormSpamProtectionExtension', 'default_spam_protector',
'EditableSpamProtectionFieldTest_Protector'
);
}
public function testValidateFieldDoesntAddErrorOnSuccess()
{
if (!class_exists('EditableSpamProtectionField')) {
$this->markTestSkipped('"userforms" module not installed');
}
$formMock = $this->getFormMock();
$formFieldMock = $this->getEditableFormFieldMock();
$formFieldMock
->getFormField() // mock
->expects($this->once())
->method('validate')
->will($this->returnValue(true));
$formMock
->expects($this->never())
->method('addErrorMessage');
$formFieldMock->validateField(array('MyField' => null), $formMock);
}
public function testValidateFieldAddsErrorFromField()
{
if (!class_exists('EditableSpamProtectionField')) {
$this->markTestSkipped('"userforms" module not installed');
}
$formMock = $this->getFormMock();
$formFieldMock = $this->getEditableFormFieldMock();
$formFieldMock
->getFormField() // mock
->expects($this->once())
->method('validate')
->will($this->returnValue(false));
$formMock->getValidator()->validationError('MyField', 'some field message', 'required');
$formMock
->expects($this->once())
->method('addErrorMessage')
->with($this->anything(), $this->stringContains('some field message'), $this->anything(), $this->anything());;
$formFieldMock->validateField(array('MyField' => null), $formMock);
}
public function testValidateFieldAddsDefaultError()
{
if (!class_exists('EditableSpamProtectionField')) {
$this->markTestSkipped('"userforms" module not installed');
}
$formMock = $this->getFormMock();
$formFieldMock = $this->getEditableFormFieldMock();
$formFieldMock
->getFormField() // mock
->expects($this->once())
->method('validate')
->will($this->returnValue(false));
// field doesn't set any validation errors here
$formMock
->expects($this->once())
->method('addErrorMessage')
->with($this->anything(), $this->stringContains('default error message'), $this->anything(), $this->anything());
$formFieldMock->validateField(array('MyField' => null), $formMock);
}
protected function getFormMock()
{
$formMock = $this->getMockBuilder('Form', array('addErrorMessage'))
->disableOriginalConstructor()
->getMock();
$formMock
->expects($this->any())
->method('getValidator')
->will($this->returnValue(new RequiredFields()));
return $formMock;
}
protected function getEditableFormFieldMock()
{
$page = new UserDefinedForm();
$page->write();
$formFieldMock = $this->getMockBuilder('TextField')
->disableOriginalConstructor()
->getMock();
$editableFormFieldMock = new EditableSpamProtectionField(array(
'ParentID' => $page->ID,
'Name' => 'MyField',
'CustomErrorMessage' => 'default error message'
));
$editableFormFieldMock->write();
$editableFormFieldMock->setFormField($formFieldMock);
return $editableFormFieldMock;
}
}
class EditableSpamProtectionFieldTest_Protector implements SpamProtector, TestOnly
{
public function getFormField($name = null, $title = null, $value = null)
{
return new TextField($name, 'Foo', $value);
}
public function setFieldMapping($fieldMapping)
{
}
}