Merge pull request #5814 from kinglozzer/2534-form-actions

FIX: Fixes support for "inline" form actions (fixes #2534)
This commit is contained in:
Daniel Hensby 2016-07-15 14:19:18 +01:00 committed by GitHub
commit a6f1544621
2 changed files with 82 additions and 17 deletions

View File

@ -416,7 +416,8 @@ class Form extends RequestHandler {
$this->controller->hasMethod($funcName) $this->controller->hasMethod($funcName)
&& !$this->controller->checkAccessAction($funcName) && !$this->controller->checkAccessAction($funcName)
// If a button exists, allow it on the controller // If a button exists, allow it on the controller
&& !$this->actions->dataFieldByName('action_' . $funcName) // buttonClicked() validates that the action set above is valid
&& !$this->buttonClicked()
) { ) {
return $this->httpError( return $this->httpError(
403, 403,
@ -475,16 +476,28 @@ class Form extends RequestHandler {
* @return bool * @return bool
*/ */
public function checkAccessAction($action) { public function checkAccessAction($action) {
return ( if (parent::checkAccessAction($action)) {
parent::checkAccessAction($action) return true;
}
// Always allow actions which map to buttons. See httpSubmission() for further access checks. // Always allow actions which map to buttons. See httpSubmission() for further access checks.
|| $this->actions->dataFieldByName('action_' . $action) $fields = $this->fields->dataFields() ?: array();
$actions = $this->actions->dataFields() ?: array();
$fieldsAndActions = array_merge($fields, $actions);
foreach ($fieldsAndActions as $fieldOrAction) {
if ($fieldOrAction instanceof FormAction && $fieldOrAction->actionName() === $action) {
return true;
}
}
// Always allow actions on fields // Always allow actions on fields
|| ( $field = $this->checkFieldsForAction($this->Fields(), $action);
$field = $this->checkFieldsForAction($this->Fields(), $action) if ($field && $field->checkAccessAction($action)) {
&& $field->checkAccessAction($action) return true;
) }
);
return false;
} }
/** /**
@ -1635,16 +1648,20 @@ class Form extends RequestHandler {
* @return FormAction * @return FormAction
*/ */
public function buttonClicked() { public function buttonClicked() {
$actions = $this->actions->dataFields(); $fields = $this->fields->dataFields() ?: array();
if(!$actions) { $actions = $this->actions->dataFields() ?: array();
if(!$actions && !$fields) {
return null; return null;
} }
foreach($actions as $action) { $fieldsAndActions = array_merge($fields, $actions);
if($action instanceof FormAction && $this->buttonClickedFunc == $action->actionName()) { foreach ($fieldsAndActions as $fieldOrAction) {
return $action; if ($fieldOrAction instanceof FormAction && $this->buttonClickedFunc === $fieldOrAction->actionName()) {
return $fieldOrAction;
} }
} }
return null; return null;
} }

View File

@ -541,6 +541,54 @@ class FormTest extends FunctionalTest {
$form = $this->getStubForm(); $form = $this->getStubForm();
$action = $form->buttonClicked(); $action = $form->buttonClicked();
$this->assertNull($action); $this->assertNull($action);
$controller = new FormTest_Controller();
$form = $controller->Form();
$request = new SS_HTTPRequest('POST', 'FormTest_Controller/Form', array(), array(
'Email' => 'test@test.com',
'SomeRequiredField' => 1,
'action_doSubmit' => 1
));
$form->httpSubmission($request);
$button = $form->buttonClicked();
$this->assertInstanceOf('FormAction', $button);
$this->assertEquals('doSubmit', $button->actionName());
$form = new Form(
$controller,
'Form',
new FieldList(new FormAction('doSubmit', 'Inline action')),
new FieldList()
);
$form->disableSecurityToken();
$request = new SS_HTTPRequest('POST', 'FormTest_Controller/Form', array(), array(
'action_doSubmit' => 1
));
$form->httpSubmission($request);
$button = $form->buttonClicked();
$this->assertInstanceOf('FormAction', $button);
$this->assertEquals('doSubmit', $button->actionName());
}
public function testCheckAccessAction() {
$controller = new FormTest_Controller();
$form = new Form(
$controller,
'Form',
new FieldList(),
new FieldList(new FormAction('actionName', 'Action'))
);
$this->assertTrue($form->checkAccessAction('actionName'));
$form = new Form(
$controller,
'Form',
new FieldList(new FormAction('inlineAction', 'Inline action')),
new FieldList()
);
$this->assertTrue($form->checkAccessAction('inlineAction'));
} }
public function testAttributesHTML() { public function testAttributesHTML() {