Merge pull request #5377 from open-sausages/pulls/4.0/api-exempt-validation

API Allow actions to declare they are exempt from validation themselves
This commit is contained in:
Hamish Friedlander 2016-04-22 15:50:33 +12:00
commit 84193b00fd
5 changed files with 98 additions and 4 deletions

View File

@ -158,6 +158,27 @@ reusable and would not be possible within the `CMS` or other automated `UI` but
return $this->redirectBack();
}
}
## Exempt validation actions
In some cases you might need to disable validation for specific actions. E.g. actions which discard submitted
data may not need to check the validity of the posted content.
You can disable validation on individual using one of two methods:
:::php
$actions = new FieldList(
$action = FormAction::create('doSubmitForm', 'Submit')
);
$form = new Form($controller, 'MyForm', $fields, $actions);
// Disable actions on the form action themselves
$action->setValidationExempt(true);
// Alternatively, you can whitelist individual actions on the form object by name
$form->setValidationExemptActions(['doSubmitForm']);
## Server-side validation messages

View File

@ -89,6 +89,7 @@
* `hasStages` is addded to check if an object has a given stage.
* `stageTable` is added to get the table for a given class and stage.
* `ChangeSet` and `ChangeSetItem` have been added for batch publishing of versioned dataobjects.
* `FormAction::setValidationExempt` can be used to turn on or off form validation for individual actions
### Front-end build tooling for CMS interface

View File

@ -712,6 +712,22 @@ class Form extends RequestHandler {
return $this->validationExemptActions;
}
/**
* Passed a FormAction, returns true if that action is exempt from Form validation
*
* @param FormAction $action
* @return bool
*/
public function actionIsValidationExempt($action) {
if ($action->getValidationExempt()) {
return true;
}
if (in_array($action->actionName(), $this->getValidationExemptActions())) {
return true;
}
return false;
}
/**
* Convert this form to another format.
* @param FormTransformation $format
@ -1342,8 +1358,8 @@ class Form extends RequestHandler {
* @return boolean
*/
public function validate(){
$buttonClicked = $this->buttonClicked();
if($buttonClicked && in_array($buttonClicked->actionName(), $this->getValidationExemptActions())) {
$action = $this->buttonClicked();
if($action && $this->actionIsValidationExempt($action)) {
return true;
}

View File

@ -39,6 +39,13 @@ class FormAction extends FormField {
*/
protected $buttonContent = null;
/**
* Should validation be skipped when performing this action?
*
* @var bool
*/
protected $validationExempt = false;
/**
* Create a new action button.
*
@ -173,6 +180,26 @@ class FormAction extends FormField {
return $this->useButtonTag;
}
/**
* Set whether this action can be performed without validating the data
*
* @param bool $exempt
* @return $this
*/
public function setValidationExempt($exempt = true) {
$this->validationExempt = $exempt;
return $this;
}
/**
* Get whether this action can be performed without vaidating the data
*
* @return bool
*/
public function getValidationExempt() {
return $this->validationExempt;
}
/**
* Does not transform to readonly by purpose.
* Globally disabled buttons would break the CMS.

View File

@ -298,6 +298,28 @@ class FormTest extends FunctionalTest {
),
'Form->sessionMessage() shows up after reloading the form'
);
// Test this same behaviour, but with a form-action exempted via instance
$response = $this->submitForm(
'Form_Form',
'action_doSubmitActionExempt',
array(
'Email' => 'test@test.com'
)
);
// The required message should be empty if validation was skipped
$items = $this->cssParser()->getBySelector('#Form_Form_SomeRequiredField_Holder .required');
$this->assertEmpty($items);
// And the session message should show up is submitted successfully
$this->assertPartialMatchBySelector(
'#Form_Form_error',
array(
'Validation bypassed!'
),
'Form->sessionMessage() shows up after reloading the form'
);
}
public function testSessionValidationMessage() {
@ -773,8 +795,10 @@ class FormTest_Controller extends Controller implements TestOnly {
new NumericField('Number')
),
new FieldList(
new FormAction('doSubmit'),
new FormAction('doSubmitValidationExempt')
FormAction::create('doSubmit'),
FormAction::create('doSubmitValidationExempt'),
FormAction::create('doSubmitActionExempt')
->setValidationExempt(true)
),
new RequiredFields(
'Email',
@ -797,6 +821,11 @@ class FormTest_Controller extends Controller implements TestOnly {
return $this->redirectBack();
}
public function doSubmitActionExempt($data, $form, $request) {
$form->sessionMessage('Validation bypassed!', 'good');
return $this->redirectBack();
}
public function getViewer($action = null) {
return new SSViewer('BlankPage');
}