Allow setting of specific form actions that do not require validation

Move validation exemptions into CMSForm

Also fix buttonClicked() to skip CompositeField

Whitespace

Adding unit tests
This commit is contained in:
Loz Calver 2013-10-03 14:24:19 +01:00
parent bb7c973e34
commit 3172c7732e
3 changed files with 167 additions and 2 deletions

View File

@ -4,6 +4,23 @@
*/
class CMSForm extends Form {
/**
* @var array
*/
protected $validationExemptActions = array();
/**
* Always return true if the current form action is exempt from validation
*
* @return boolean
*/
public function validate() {
return (
in_array($this->buttonClicked()->actionName(), $this->getValidationExemptActions())
|| parent::validate()
);
}
/**
* Route validation error responses through response negotiator,
* so they return the correct markup as expected by the requesting client.
@ -19,6 +36,25 @@ class CMSForm extends Form {
}
}
/**
* Set actions that are exempt from validation
*
* @param array
*/
public function setValidationExemptActions($actions) {
$this->validationExemptActions = $actions;
return $this;
}
/**
* Get a list of actions that are exempt from validation
*
* @return array
*/
public function getValidationExemptActions() {
return $this->validationExemptActions;
}
/**
* Sets the response negotiator
* @param ResponseNegotiator $negotiator The response negotiator to use

127
admin/tests/CMSFormTest.php Normal file
View File

@ -0,0 +1,127 @@
<?php
/**
* @package framework
* @subpackage tests
*/
class CMSFormTest extends FunctionalTest {
public function testValidationExemptActions() {
$response = $this->get('CMSFormTest_Controller');
$response = $this->submitForm(
'Form_Form',
'action_doSubmit',
array(
'Email' => 'test@test.com'
)
);
// Firstly, assert that required fields still work when not using an exempt action
$this->assertPartialMatchBySelector(
'#SomeRequiredField span.required',
array(
'"Some Required Field" is required'
),
'Required fields show a notification on field when left blank'
);
// Re-submit the form using validation-exempt button
$response = $this->submitForm(
'Form_Form',
'action_doSubmitValidationExempt',
array(
'Email' => 'test@test.com'
)
);
// The required message should be empty if validation was skipped
$items = $this->cssParser()->getBySelector('#SomeRequiredField span.required');
$this->assertEmpty($items);
// And the session message should show up is submitted successfully
$this->assertPartialMatchBySelector(
'#Form_Form_error',
array(
'Validation skipped'
),
'Form->sessionMessage() shows up after reloading the form'
);
}
public function testSetValidationExemptActions() {
$form = $this->getStubForm();
$form->setValidationExemptActions(array('exemptaction'));
$exemptActions = $form->getValidationExemptActions();
$this->assertEquals('exemptaction', $exemptActions[0]);
}
protected function getStubForm() {
$form = new CMSForm(
new CMSFormTest_Controller(),
'CMSForm',
new FieldList(),
new FieldList()
);
return $form;
}
}
class CMSFormTest_Controller extends Controller implements TestOnly {
private static $allowed_actions = array('Form');
private static $url_handlers = array(
'$Action//$ID/$OtherID' => "handleAction",
);
protected $template = 'BlankPage';
public function Link($action = null) {
return Controller::join_links('CMSFormTest_Controller', $this->request->latestParam('Action'),
$this->request->latestParam('ID'), $action);
}
public function Form() {
$form = new CMSForm(
$this,
'Form',
new FieldList(
new EmailField('Email'),
new TextField('SomeRequiredField'),
new CheckboxSetField('Boxes', null, array('1'=>'one','2'=>'two'))
),
new FieldList(
new FormAction('doSubmit'),
new FormAction('doSubmitValidationExempt')
),
new RequiredFields(
'Email',
'SomeRequiredField'
)
);
$form->setValidationExemptActions(array('doSubmitValidationExempt'));
$form->setResponseNegotiator('foo'); // We aren't testing AJAX responses, so just set anything
$form->disableSecurityToken(); // Disable CSRF protection for easier form submission handling
return $form;
}
public function doSubmit($data, $form, $request) {
$form->sessionMessage('Test save was successful', 'good');
return $this->redirectBack();
}
public function doSubmitValidationExempt($data, $form, $request) {
$form->sessionMessage('Validation skipped', 'good');
return $this->redirectBack();
}
public function getViewer($action = null) {
return new SSViewer('BlankPage');
}
}

View File

@ -1380,8 +1380,10 @@ class Form extends RequestHandler {
}
public function buttonClicked() {
foreach($this->actions as $action) {
if($this->buttonClickedFunc == $action->actionName()) return $action;
foreach($this->actions->dataFields() as $action) {
if($action->hasMethod('actionname') && $this->buttonClickedFunc == $action->actionName()) {
return $action;
}
}
}