Merge pull request #2493 from kinglozzer/2449-form-validation-exemptions

NEW: Allow setting of specific form actions that do not require validation on CMSForm
This commit is contained in:
Ingo Schommer 2013-10-08 01:51:11 -07:00
commit aa6ca49651
3 changed files with 167 additions and 2 deletions

View File

@ -3,6 +3,23 @@
* Deals with special form handling in CMS, mainly around {@link PjaxResponseNegotiator}
*/
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,
@ -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;
}
}
}