mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
API New CMSForm class to allow validation responses in CMS (fixes #1777)
Thanks to @willmorgan for getting this discussion started (see https://github.com/silverstripe/sapphire/pull/1814).
This commit is contained in:
parent
6ca27cd257
commit
bfff11eb9c
40
admin/code/CMSForm.php
Normal file
40
admin/code/CMSForm.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* Deals with special form handling in CMS, mainly around {@link PjaxResponseNegotiator}
|
||||
*/
|
||||
class CMSForm extends Form {
|
||||
|
||||
/**
|
||||
* Route validation error responses through response negotiator,
|
||||
* so they return the correct markup as expected by the requesting client.
|
||||
*/
|
||||
protected function getValidationErrorResponse() {
|
||||
$request = $this->getRequest();
|
||||
$negotiator = $this->getResponseNegotiator();
|
||||
if($request->isAjax() && $negotiator) {
|
||||
$negotiator->setResponse(new SS_HTTPResponse($this));
|
||||
return $negotiator->respond($request);
|
||||
} else {
|
||||
return parent::getValidationErrorResponse();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the response negotiator
|
||||
* @param ResponseNegotiator $negotiator The response negotiator to use
|
||||
* @return Form The current form
|
||||
*/
|
||||
public function setResponseNegotiator($negotiator) {
|
||||
$this->responseNegotiator = $negotiator;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current response negotiator
|
||||
* @return ResponseNegotiator|null
|
||||
*/
|
||||
public function getResponseNegotiator() {
|
||||
return $this->responseNegotiator;
|
||||
}
|
||||
|
||||
}
|
@ -1211,7 +1211,10 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
||||
$actionsFlattened = $actions->dataFields();
|
||||
if($actionsFlattened) foreach($actionsFlattened as $action) $action->setUseButtonTag(true);
|
||||
|
||||
$form = new Form($this, "EditForm", $fields, $actions);
|
||||
$form = CMSForm::create(
|
||||
$this, "EditForm", $fields, $actions
|
||||
)->setHTMLID('Form_EditForm');
|
||||
$form->setResponseNegotiator($this->getResponseNegotiator());
|
||||
$form->addExtraClass('cms-edit-form');
|
||||
$form->loadDataFrom($record);
|
||||
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
|
||||
@ -1264,7 +1267,7 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
||||
* @return Form
|
||||
*/
|
||||
public function EmptyForm() {
|
||||
$form = new Form(
|
||||
$form = CMSForm::create(
|
||||
$this,
|
||||
"EditForm",
|
||||
new FieldList(
|
||||
@ -1282,7 +1285,8 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
||||
// )
|
||||
),
|
||||
new FieldList()
|
||||
);
|
||||
)->setHTMLID('Form_EditForm');
|
||||
$form->setResponseNegotiator($this->getResponseNegotiator());
|
||||
$form->unsetValidator();
|
||||
$form->addExtraClass('cms-edit-form');
|
||||
$form->addExtraClass('root-form');
|
||||
|
@ -155,12 +155,13 @@ abstract class ModelAdmin extends LeftAndMain {
|
||||
$listField->getConfig()->getComponentByType('GridFieldDetailForm')->setValidator($detailValidator);
|
||||
}
|
||||
|
||||
$form = new Form(
|
||||
$form = CMSForm::create(
|
||||
$this,
|
||||
'EditForm',
|
||||
new FieldList($listField),
|
||||
new FieldList()
|
||||
);
|
||||
)->setHTMLID('Form_EditForm');
|
||||
$form->setResponseNegotiator($this->getResponseNegotiator());
|
||||
$form->addExtraClass('cms-edit-form cms-panel-padded center');
|
||||
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
|
||||
$editFormAction = Controller::join_links($this->Link($this->sanitiseClassName($this->modelClass)), 'EditForm');
|
||||
|
@ -154,12 +154,13 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
|
||||
|
||||
$actions = new FieldList();
|
||||
|
||||
$form = new Form(
|
||||
$form = CMSForm::create(
|
||||
$this,
|
||||
'EditForm',
|
||||
$fields,
|
||||
$actions
|
||||
);
|
||||
)->setHTMLID('Form_EditForm');
|
||||
$form->setResponseNegotiator($this->getResponseNegotiator());
|
||||
$form->addExtraClass('cms-edit-form');
|
||||
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
|
||||
// Tab nav in CMS is rendered through separate template
|
||||
|
@ -475,3 +475,6 @@ you can enable those warnings and future-proof your code already.
|
||||
by `updateCMSFields`. See the [DataExtension Reference](/reference/dataextension) for more information.
|
||||
* Magic quotes is now deprecated. Will trigger user_error on live sites, as well as an error on new installs
|
||||
* Support for Apache 1.x is removed.
|
||||
* Forms created in the CMS should now be instances of a new `CMSForm` class,
|
||||
and have the CMS controller's response negotiator passed into them.
|
||||
Example: `$form = new CMSForm(...); $form->setResponseNegotiator($this->getResponseNegotiator());`
|
@ -106,12 +106,15 @@ In order to set the correct layout classes, we also need a custom template.
|
||||
To obey the inheritance chain, we use `$this->getTemplatesWithSuffix('_EditForm')` for
|
||||
selecting the most specific template (so `MyAdmin_EditForm.ss`, if it exists).
|
||||
|
||||
The form should be of type `CMSForm` rather than `Form`, since it allows the use
|
||||
of a `PjaxResponseNegotiator` to handle its display.
|
||||
|
||||
Basic example form in a CMS controller subclass:
|
||||
|
||||
:::php
|
||||
class MyAdmin extends LeftAndMain {
|
||||
function getEditForm() {
|
||||
$form = new Form(
|
||||
return CMSForm::create(
|
||||
$this,
|
||||
'EditForm',
|
||||
new FieldSet(
|
||||
@ -125,11 +128,14 @@ Basic example form in a CMS controller subclass:
|
||||
new FieldSet(
|
||||
FormAction::create('doSubmit')
|
||||
)
|
||||
);
|
||||
// Required for correct CMS layout
|
||||
$form->addExtraClass('cms-edit-form');
|
||||
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
|
||||
return $form;
|
||||
)
|
||||
// JS and CSS use this identifier
|
||||
->setHTMLID('Form_EditForm')
|
||||
// Render correct responses on validation errors
|
||||
->setResponseNegotiator($this->getResponseNegotiator());
|
||||
// Required for correct CMS layout
|
||||
->addExtraClass('cms-edit-form')
|
||||
->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,9 +344,36 @@ class Form extends RequestHandler {
|
||||
|
||||
// Validate the form
|
||||
if(!$this->validate()) {
|
||||
if(Director::is_ajax()) {
|
||||
// Special case for legacy Validator.js implementation (assumes eval'ed javascript collected through
|
||||
// FormResponse)
|
||||
return $this->getValidationErrorResponse();
|
||||
}
|
||||
|
||||
// First, try a handler method on the controller (has been checked for allowed_actions above already)
|
||||
if($this->controller->hasMethod($funcName)) {
|
||||
return $this->controller->$funcName($vars, $this, $request);
|
||||
// Otherwise, try a handler method on the form object.
|
||||
} elseif($this->hasMethod($funcName)) {
|
||||
return $this->$funcName($vars, $this, $request);
|
||||
} elseif($field = $this->checkFieldsForAction($this->Fields(), $funcName)) {
|
||||
return $field->$funcName($vars, $this, $request);
|
||||
}
|
||||
|
||||
return $this->httpError(404);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate response up the controller chain
|
||||
* if {@link validate()} fails (which is checked prior to executing any form actions).
|
||||
* By default, returns different views for ajax/non-ajax request, and
|
||||
* handles 'appliction/json' requests with a JSON object containing the error messages.
|
||||
* Behaviour can be influenced by setting {@link $redirectToFormOnValidationError}.
|
||||
*
|
||||
* @return SS_HTTPResponse|string
|
||||
*/
|
||||
protected function getValidationErrorResponse() {
|
||||
$request = $this->getRequest();
|
||||
if($request->isAjax()) {
|
||||
// Special case for legacy Validator.js implementation
|
||||
// (assumes eval'ed javascript collected through FormResponse)
|
||||
$acceptType = $request->getHeader('Accept');
|
||||
if(strpos($acceptType, 'application/json') !== FALSE) {
|
||||
// Send validation errors back as JSON with a flag at the start
|
||||
@ -372,19 +399,6 @@ class Form extends RequestHandler {
|
||||
}
|
||||
return $this->controller->redirectBack();
|
||||
}
|
||||
}
|
||||
|
||||
// First, try a handler method on the controller (has been checked for allowed_actions above already)
|
||||
if($this->controller->hasMethod($funcName)) {
|
||||
return $this->controller->$funcName($vars, $this, $request);
|
||||
// Otherwise, try a handler method on the form object.
|
||||
} elseif($this->hasMethod($funcName)) {
|
||||
return $this->$funcName($vars, $this, $request);
|
||||
} elseif($field = $this->checkFieldsForAction($this->Fields(), $funcName)) {
|
||||
return $field->$funcName($vars, $this, $request);
|
||||
}
|
||||
|
||||
return $this->httpError(404);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user