mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
Update and fix PHP docblocks, document spelling mistakes and strip trailing whitespace on Form.php
This commit is contained in:
parent
04b803dfc6
commit
95860e9229
458
forms/Form.php
458
forms/Form.php
@ -11,13 +11,13 @@
|
||||
* can be passed using the URL or get variables. These restrictions are in place so that we can
|
||||
* recreate the form object upon form submission, without the use of a session, which would be too
|
||||
* resource-intensive.
|
||||
*
|
||||
*
|
||||
* You will need to create at least one method for processing the submission (through {@link FormAction}).
|
||||
* This method will be passed two parameters: the raw request data, and the form object.
|
||||
* Usually you want to save data into a {@link DataObject} by using {@link saveInto()}.
|
||||
* If you want to process the submitted data in any way, please use {@link getData()} rather than
|
||||
* the raw request data.
|
||||
*
|
||||
*
|
||||
* <h2>Validation</h2>
|
||||
* Each form needs some form of {@link Validator} to trigger the {@link FormField->validate()} methods for each field.
|
||||
* You can't disable validator for security reasons, because crucial behaviour like extension checks for file uploads
|
||||
@ -33,9 +33,9 @@
|
||||
* You can find out the base URL for your form by looking at the
|
||||
* <form action="..."> value. For example, the edit form in the CMS would be located at
|
||||
* "admin/EditForm". This URL will render the form without its surrounding
|
||||
* template when called through GET instead of POST.
|
||||
*
|
||||
* By appending to this URL, you can render invidual form elements
|
||||
* template when called through GET instead of POST.
|
||||
*
|
||||
* By appending to this URL, you can render individual form elements
|
||||
* through the {@link FormField->FieldHolder()} method.
|
||||
* For example, the "URLSegment" field in a standard CMS form would be
|
||||
* accessible through "admin/EditForm/field/URLSegment/FieldHolder".
|
||||
@ -53,37 +53,57 @@ class Form extends RequestHandler {
|
||||
* A performance enhancement over the generate-the-form-tag-and-then-remove-it code that was there previously
|
||||
*/
|
||||
public $IncludeFormTag = true;
|
||||
|
||||
|
||||
/**
|
||||
* @var FieldList
|
||||
*/
|
||||
protected $fields;
|
||||
|
||||
|
||||
/**
|
||||
* @var FieldList
|
||||
*/
|
||||
protected $actions;
|
||||
|
||||
/**
|
||||
* @var Controller
|
||||
*/
|
||||
protected $controller;
|
||||
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @var Validator
|
||||
*/
|
||||
protected $validator;
|
||||
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $formMethod = "post";
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
protected $strictFormMethodCheck = false;
|
||||
|
||||
protected static $current_action;
|
||||
|
||||
|
||||
/**
|
||||
* @var Dataobject $record Populated by {@link loadDataFrom()}.
|
||||
* @var string
|
||||
*/
|
||||
protected static $current_action;
|
||||
|
||||
/**
|
||||
* @var DataObject $record Populated by {@link loadDataFrom()}.
|
||||
*/
|
||||
protected $record;
|
||||
|
||||
/**
|
||||
* Keeps track of whether this form has a default action or not.
|
||||
* Set to false by $this->disableDefaultAction();
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $hasDefaultAction = true;
|
||||
|
||||
@ -95,47 +115,59 @@ class Form extends RequestHandler {
|
||||
* @var string
|
||||
*/
|
||||
protected $target;
|
||||
|
||||
|
||||
/**
|
||||
* Legend value, to be inserted into the
|
||||
* Legend value, to be inserted into the
|
||||
* <legend> element before the <fieldset>
|
||||
* in Form.ss template.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $legend;
|
||||
|
||||
|
||||
/**
|
||||
* The SS template to render this form HTML into.
|
||||
* Default is "Form", but this can be changed to
|
||||
* another template for customisation.
|
||||
*
|
||||
*
|
||||
* @see Form->setTemplate()
|
||||
* @var string
|
||||
*/
|
||||
protected $template;
|
||||
|
||||
protected $buttonClickedFunc;
|
||||
|
||||
protected $message;
|
||||
|
||||
protected $messageType;
|
||||
|
||||
|
||||
/**
|
||||
* Should we redirect the user back down to the
|
||||
* @var callable
|
||||
*/
|
||||
protected $buttonClickedFunc;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $message;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $messageType;
|
||||
|
||||
/**
|
||||
* Should we redirect the user back down to the
|
||||
* the form on validation errors rather then just the page
|
||||
*
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $redirectToFormOnValidationError = false;
|
||||
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $security = true;
|
||||
|
||||
|
||||
/**
|
||||
* @var SecurityToken
|
||||
*/
|
||||
protected $securityToken = null;
|
||||
|
||||
|
||||
/**
|
||||
* @var array $extraClasses List of additional CSS classes for the form tag.
|
||||
*/
|
||||
@ -152,17 +184,25 @@ class Form extends RequestHandler {
|
||||
*/
|
||||
protected $attributes = array();
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $allowed_actions = array(
|
||||
'handleField',
|
||||
'handleField',
|
||||
'httpSubmission',
|
||||
'forTemplate',
|
||||
);
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $securityTokenAdded;
|
||||
|
||||
/**
|
||||
* Create a new form, with the given fields an action buttons.
|
||||
*
|
||||
*
|
||||
* @param Controller $controller The parent controller, necessary to create the appropriate form action tag.
|
||||
* @param String $name The method on the controller that will return this form object.
|
||||
* @param string $name The method on the controller that will return this form object.
|
||||
* @param FieldList $fields All of the fields in the form - a {@link FieldList} of {@link FormField} objects.
|
||||
* @param FieldList $actions All of the action buttons in the form - a {@link FieldLis} of
|
||||
* {@link FormAction} objects
|
||||
@ -170,7 +210,7 @@ class Form extends RequestHandler {
|
||||
*/
|
||||
public function __construct($controller, $name, FieldList $fields, FieldList $actions, $validator = null) {
|
||||
parent::__construct();
|
||||
|
||||
|
||||
if(!$fields instanceof FieldList) {
|
||||
throw new InvalidArgumentException('$fields must be a valid FieldList instance');
|
||||
}
|
||||
@ -188,7 +228,7 @@ class Form extends RequestHandler {
|
||||
$this->actions = $actions;
|
||||
$this->controller = $controller;
|
||||
$this->name = $name;
|
||||
|
||||
|
||||
if(!$this->controller) user_error("$this->class form created without a controller", E_USER_ERROR);
|
||||
|
||||
// Form validation
|
||||
@ -197,7 +237,7 @@ class Form extends RequestHandler {
|
||||
|
||||
// Form error controls
|
||||
$this->setupFormErrors();
|
||||
|
||||
|
||||
// Check if CSRF protection is enabled, either on the parent controller or from the default setting. Note that
|
||||
// method_exists() is used as some controllers (e.g. GroupTest) do not always extend from Object.
|
||||
if(method_exists($controller, 'securityTokenEnabled') || (method_exists($controller, 'hasMethod')
|
||||
@ -207,10 +247,13 @@ class Form extends RequestHandler {
|
||||
} else {
|
||||
$securityEnabled = SecurityToken::is_enabled();
|
||||
}
|
||||
|
||||
|
||||
$this->securityToken = ($securityEnabled) ? new SecurityToken() : new NullSecurityToken();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $url_handlers = array(
|
||||
'field/$FieldName!' => 'handleField',
|
||||
'POST ' => 'httpSubmission',
|
||||
@ -221,6 +264,8 @@ class Form extends RequestHandler {
|
||||
/**
|
||||
* Set up current form errors in session to
|
||||
* the current form if appropriate.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setupFormErrors() {
|
||||
$errorInfo = Session::get("FormInfo.{$this->FormName()}");
|
||||
@ -247,17 +292,20 @@ class Form extends RequestHandler {
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle a form submission. GET and POST requests behave identically.
|
||||
* Populates the form with {@link loadDataFrom()}, calls {@link validate()},
|
||||
* and only triggers the requested form action/method
|
||||
* if the form is valid.
|
||||
*
|
||||
* @param SS_HTTPRequest $request
|
||||
* @throws SS_HTTPResponse_Exception
|
||||
*/
|
||||
public function httpSubmission($request) {
|
||||
// Strict method check
|
||||
if($this->strictFormMethodCheck) {
|
||||
|
||||
|
||||
// Throws an error if the method is bad...
|
||||
if($this->formMethod != strtolower($request->httpMethod())) {
|
||||
$response = Controller::curr()->getResponse();
|
||||
@ -265,15 +313,15 @@ class Form extends RequestHandler {
|
||||
$this->httpError(405, _t("Form.BAD_METHOD", "This form requires a ".$this->formMethod." submission"));
|
||||
}
|
||||
|
||||
// ...and only uses the vairables corresponding to that method type
|
||||
// ...and only uses the variables corresponding to that method type
|
||||
$vars = $this->formMethod == 'get' ? $request->getVars() : $request->postVars();
|
||||
} else {
|
||||
$vars = $request->requestVars();
|
||||
}
|
||||
|
||||
|
||||
// Populate the form
|
||||
$this->loadDataFrom($vars, true);
|
||||
|
||||
|
||||
// Protection against CSRF attacks
|
||||
$token = $this->getSecurityToken();
|
||||
if( ! $token->checkRequest($request)) {
|
||||
@ -296,7 +344,7 @@ class Form extends RequestHandler {
|
||||
return $this->controller->redirectBack();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Determine the action button clicked
|
||||
$funcName = null;
|
||||
foreach($vars as $paramName => $paramVal) {
|
||||
@ -308,18 +356,18 @@ class Form extends RequestHandler {
|
||||
parse_str($paramVars, $newRequestParams);
|
||||
$vars = array_merge((array)$vars, (array)$newRequestParams);
|
||||
}
|
||||
|
||||
|
||||
// Cleanup action_, _x and _y from image fields
|
||||
$funcName = preg_replace(array('/^action_/','/_x$|_y$/'),'',$paramName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the action wasnt' set, choose the default on the form.
|
||||
|
||||
// If the action wasn't set, choose the default on the form.
|
||||
if(!isset($funcName) && $defaultAction = $this->defaultAction()){
|
||||
$funcName = $defaultAction->actionName();
|
||||
}
|
||||
|
||||
|
||||
if(isset($funcName)) {
|
||||
Form::set_current_action($funcName);
|
||||
$this->setButtonClicked($funcName);
|
||||
@ -335,7 +383,7 @@ class Form extends RequestHandler {
|
||||
&& !$this->actions->dataFieldByName('action_' . $funcName)
|
||||
) {
|
||||
return $this->httpError(
|
||||
403,
|
||||
403,
|
||||
sprintf('Action "%s" not allowed on controller (Class: %s)', $funcName, get_class($this->controller))
|
||||
);
|
||||
} elseif(
|
||||
@ -345,7 +393,7 @@ class Form extends RequestHandler {
|
||||
// all form methods are callable (e.g. the legacy "callfieldmethod()")
|
||||
) {
|
||||
return $this->httpError(
|
||||
403,
|
||||
403,
|
||||
sprintf('Action "%s" not allowed on form (Name: "%s")', $funcName, $this->name)
|
||||
);
|
||||
}
|
||||
@ -362,17 +410,17 @@ class Form extends RequestHandler {
|
||||
}
|
||||
if (!$fieldsHaveMethod) {
|
||||
return $this->httpError(
|
||||
403,
|
||||
403,
|
||||
sprintf('Action "%s" not allowed on any fields of form (Name: "%s")', $funcName, $this->Name())
|
||||
);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
// Validate the form
|
||||
if(!$this->validate()) {
|
||||
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);
|
||||
@ -382,10 +430,14 @@ class Form extends RequestHandler {
|
||||
} elseif($field = $this->checkFieldsForAction($this->Fields(), $funcName)) {
|
||||
return $field->$funcName($vars, $this, $request);
|
||||
}
|
||||
|
||||
|
||||
return $this->httpError(404);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
* @return bool
|
||||
*/
|
||||
public function checkAccessAction($action) {
|
||||
return (
|
||||
parent::checkAccessAction($action)
|
||||
@ -403,15 +455,15 @@ class Form extends RequestHandler {
|
||||
* 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.
|
||||
* handles 'application/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
|
||||
// Special case for legacy Validator.js implementation
|
||||
// (assumes eval'ed javascript collected through FormResponse)
|
||||
$acceptType = $request->getHeader('Accept');
|
||||
if(strpos($acceptType, 'application/json') !== FALSE) {
|
||||
@ -424,7 +476,7 @@ class Form extends RequestHandler {
|
||||
$response = new SS_HTTPResponse($this->forTemplate());
|
||||
$response->addHeader('Content-Type', 'text/html');
|
||||
}
|
||||
|
||||
|
||||
return $response;
|
||||
} else {
|
||||
if($this->getRedirectToFormOnValidationError()) {
|
||||
@ -440,10 +492,12 @@ class Form extends RequestHandler {
|
||||
return $this->controller->redirectBack();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fields can have action to, let's check if anyone of the responds to $funcname them
|
||||
*
|
||||
*
|
||||
* @param SS_List|array $fields
|
||||
* @param callable $funcName
|
||||
* @return FormField
|
||||
*/
|
||||
protected function checkFieldsForAction($fields, $funcName) {
|
||||
@ -465,13 +519,13 @@ class Form extends RequestHandler {
|
||||
* for tabs instead. This means that if you have a tab and a
|
||||
* formfield with the same name, this method gives priority
|
||||
* to the formfield.
|
||||
*
|
||||
*
|
||||
* @param SS_HTTPRequest $request
|
||||
* @return FormField
|
||||
*/
|
||||
public function handleField($request) {
|
||||
$field = $this->Fields()->dataFieldByName($request->param('FieldName'));
|
||||
|
||||
|
||||
if($field) {
|
||||
return $field;
|
||||
} else {
|
||||
@ -486,19 +540,21 @@ class Form extends RequestHandler {
|
||||
public function makeReadonly() {
|
||||
$this->transform(new ReadonlyTransformation());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set whether the user should be redirected back down to the
|
||||
* form on the page upon validation errors in the form or if
|
||||
* Set whether the user should be redirected back down to the
|
||||
* form on the page upon validation errors in the form or if
|
||||
* they just need to redirect back to the page
|
||||
*
|
||||
* @param bool Redirect to the form
|
||||
* @param bool $bool
|
||||
* @return $this
|
||||
* @internal param Redirect $bool to the form
|
||||
*/
|
||||
public function setRedirectToFormOnValidationError($bool) {
|
||||
$this->redirectToFormOnValidationError = $bool;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get whether the user should be redirected back down to the
|
||||
* form on the page upon validation errors
|
||||
@ -512,6 +568,10 @@ class Form extends RequestHandler {
|
||||
/**
|
||||
* Add a plain text error message to a field on this form. It will be saved into the session
|
||||
* and used the next time this form is displayed.
|
||||
* @param string $fieldName
|
||||
* @param string $message
|
||||
* @param string $messageType
|
||||
* @param bool $escapeHtml
|
||||
*/
|
||||
public function addErrorMessage($fieldName, $message, $messageType, $escapeHtml = true) {
|
||||
Session::add_to_array("FormInfo.{$this->FormName()}.errors", array(
|
||||
@ -521,6 +581,9 @@ class Form extends RequestHandler {
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FormTransformation $trans
|
||||
*/
|
||||
public function transform(FormTransformation $trans) {
|
||||
$newFields = new FieldList();
|
||||
foreach($this->fields as $field) {
|
||||
@ -539,7 +602,7 @@ class Form extends RequestHandler {
|
||||
if($this->validator)
|
||||
$this->validator->removeValidation();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the {@link Validator} attached to this form.
|
||||
* @return Validator
|
||||
@ -550,8 +613,10 @@ class Form extends RequestHandler {
|
||||
|
||||
/**
|
||||
* Set the {@link Validator} on this form.
|
||||
* @param Validator $validator
|
||||
* @return $this
|
||||
*/
|
||||
public function setValidator( Validator $validator ) {
|
||||
public function setValidator(Validator $validator ) {
|
||||
if($validator) {
|
||||
$this->validator = $validator;
|
||||
$this->validator->setForm($this);
|
||||
@ -569,6 +634,7 @@ class Form extends RequestHandler {
|
||||
|
||||
/**
|
||||
* Convert this form to another format.
|
||||
* @param FormTransformation $format
|
||||
*/
|
||||
public function transformTo(FormTransformation $format) {
|
||||
$newFields = new FieldList();
|
||||
@ -582,48 +648,48 @@ class Form extends RequestHandler {
|
||||
$this->validator->removeValidation();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generate extra special fields - namely the security token field (if required).
|
||||
*
|
||||
*
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getExtraFields() {
|
||||
$extraFields = new FieldList();
|
||||
|
||||
|
||||
$token = $this->getSecurityToken();
|
||||
$tokenField = $token->updateFieldSet($this->fields);
|
||||
if($tokenField) $tokenField->setForm($this);
|
||||
$this->securityTokenAdded = true;
|
||||
|
||||
|
||||
// add the "real" HTTP method if necessary (for PUT, DELETE and HEAD)
|
||||
if($this->FormMethod() != $this->FormHttpMethod()) {
|
||||
$methodField = new HiddenField('_method', '', $this->FormHttpMethod());
|
||||
$methodField->setForm($this);
|
||||
$extraFields->push($methodField);
|
||||
}
|
||||
|
||||
|
||||
return $extraFields;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the form's fields - used by the templates
|
||||
*
|
||||
*
|
||||
* @return FieldList The form fields
|
||||
*/
|
||||
public function Fields() {
|
||||
foreach($this->getExtraFields() as $field) {
|
||||
if(!$this->fields->fieldByName($field->getName())) $this->fields->push($field);
|
||||
}
|
||||
|
||||
|
||||
return $this->fields;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return all <input type="hidden"> fields
|
||||
* in a form - including fields nested in {@link CompositeFields}.
|
||||
* Useful when doing custom field layouts.
|
||||
*
|
||||
*
|
||||
* @return FieldList
|
||||
*/
|
||||
public function HiddenFields() {
|
||||
@ -637,20 +703,21 @@ class Form extends RequestHandler {
|
||||
public function VisibleFields() {
|
||||
return $this->Fields()->VisibleFields();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Setter for the form fields.
|
||||
*
|
||||
* @param FieldList $fields
|
||||
* @return $this
|
||||
*/
|
||||
public function setFields($fields) {
|
||||
$this->fields = $fields;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the form's action buttons - used by the templates
|
||||
*
|
||||
*
|
||||
* @return FieldList The action list
|
||||
*/
|
||||
public function Actions() {
|
||||
@ -661,12 +728,13 @@ class Form extends RequestHandler {
|
||||
* Setter for the form actions.
|
||||
*
|
||||
* @param FieldList $actions
|
||||
* @return $this
|
||||
*/
|
||||
public function setActions($actions) {
|
||||
$this->actions = $actions;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unset all form actions
|
||||
*/
|
||||
@ -676,8 +744,9 @@ class Form extends RequestHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param String
|
||||
* @param String
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setAttribute($name, $value) {
|
||||
$this->attributes[$name] = $value;
|
||||
@ -685,12 +754,15 @@ class Form extends RequestHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String
|
||||
* @return string $name
|
||||
*/
|
||||
public function getAttribute($name) {
|
||||
if(isset($this->attributes[$name])) return $this->attributes[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAttributes() {
|
||||
$attrs = array(
|
||||
'id' => $this->FormName(),
|
||||
@ -712,10 +784,11 @@ class Form extends RequestHandler {
|
||||
|
||||
/**
|
||||
* Return the attributes of the form tag - used by the templates.
|
||||
*
|
||||
* @param Array Custom attributes to process. Falls back to {@link getAttributes()}.
|
||||
*
|
||||
* @param array Custom attributes to process. Falls back to {@link getAttributes()}.
|
||||
* If at least one argument is passed as a string, all arguments act as excludes by name.
|
||||
* @return String HTML attributes, ready for insertion into an HTML tag
|
||||
*
|
||||
* @return string HTML attributes, ready for insertion into an HTML tag
|
||||
*/
|
||||
public function getAttributesHTML($attrs = null) {
|
||||
$exclude = (is_string($attrs)) ? func_get_args() : null;
|
||||
@ -738,12 +811,12 @@ class Form extends RequestHandler {
|
||||
$attrs = $this->getAttributes();
|
||||
|
||||
// Remove empty
|
||||
$attrs = array_filter((array)$attrs, create_function('$v', 'return ($v || $v === 0);'));
|
||||
|
||||
$attrs = array_filter((array)$attrs, create_function('$v', 'return ($v || $v === 0);'));
|
||||
|
||||
// Remove excluded
|
||||
if($exclude) $attrs = array_diff_key($attrs, array_flip($exclude));
|
||||
|
||||
// Create markkup
|
||||
// Create markup
|
||||
$parts = array();
|
||||
foreach($attrs as $name => $value) {
|
||||
$parts[] = ($value === true) ? "{$name}=\"{$name}\"" : "{$name}=\"" . Convert::raw2att($value) . "\"";
|
||||
@ -757,41 +830,45 @@ class Form extends RequestHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the target of this form to any value - useful for opening the form contents in a new window or refreshing
|
||||
* another frame
|
||||
*
|
||||
* @param target The value of the target
|
||||
*/
|
||||
* Set the target of this form to any value - useful for opening the form contents in a new window or refreshing
|
||||
* another frame
|
||||
*
|
||||
* @param string $target The value of the target
|
||||
* @return $this
|
||||
*/
|
||||
public function setTarget($target) {
|
||||
$this->target = $target;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the legend value to be inserted into
|
||||
* the <legend> element in the Form.ss template.
|
||||
* @param $legend
|
||||
* @return $this
|
||||
*/
|
||||
public function setLegend($legend) {
|
||||
$this->legend = $legend;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the SS template that this form should use
|
||||
* to render with. The default is "Form".
|
||||
*
|
||||
*
|
||||
* @param string $template The name of the template (without the .ss extension)
|
||||
* @return $this
|
||||
*/
|
||||
public function setTemplate($template) {
|
||||
$this->template = $template;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the template to render this form with.
|
||||
* If the template isn't set, then default to the
|
||||
* form class name e.g "Form".
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTemplate() {
|
||||
@ -824,7 +901,8 @@ class Form extends RequestHandler {
|
||||
* Sets the form encoding type. The most common encoding types are defined
|
||||
* in {@link ENC_TYPE_URLENCODED} and {@link ENC_TYPE_MULTIPART}.
|
||||
*
|
||||
* @param string $enctype
|
||||
* @param $encType
|
||||
* @return $this
|
||||
*/
|
||||
public function setEncType($encType) {
|
||||
$this->encType = $encType;
|
||||
@ -840,18 +918,18 @@ class Form extends RequestHandler {
|
||||
* gets evaluated in {@link Director::direct()}.
|
||||
* See {@link FormMethod()} to get a HTTP method
|
||||
* for safe insertion into a <form> tag.
|
||||
*
|
||||
*
|
||||
* @return string HTTP method
|
||||
*/
|
||||
public function FormHttpMethod() {
|
||||
return $this->formMethod;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the form method to be used in the <form> tag.
|
||||
* See {@link FormHttpMethod()} to get the "real" method.
|
||||
*
|
||||
* @return string Form tag compatbile HTTP method: 'get' or 'post'
|
||||
*
|
||||
* @return string Form tag compatible HTTP method: 'get' or 'post'
|
||||
*/
|
||||
public function FormMethod() {
|
||||
if(in_array($this->formMethod,array('get','post'))) {
|
||||
@ -860,12 +938,13 @@ class Form extends RequestHandler {
|
||||
return 'post';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the form method: GET, POST, PUT, DELETE.
|
||||
*
|
||||
* @param $method string
|
||||
* @param $strict If non-null, pass value to {@link setStrictFormMethodCheck()}.
|
||||
*
|
||||
* @param string $method
|
||||
* @param bool $strict If non-null, pass value to {@link setStrictFormMethodCheck()}.
|
||||
* @return $this
|
||||
*/
|
||||
public function setFormMethod($method, $strict = null) {
|
||||
$this->formMethod = strtolower($method);
|
||||
@ -884,6 +963,7 @@ class Form extends RequestHandler {
|
||||
* form.
|
||||
*
|
||||
* @param $bool boolean
|
||||
* @return $this
|
||||
*/
|
||||
public function setStrictFormMethodCheck($bool) {
|
||||
$this->strictFormMethodCheck = (bool)$bool;
|
||||
@ -896,12 +976,12 @@ class Form extends RequestHandler {
|
||||
public function getStrictFormMethodCheck() {
|
||||
return $this->strictFormMethodCheck;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the form's action attribute.
|
||||
* This is build by adding an executeForm get variable to the parent controller's Link() value
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function FormAction() {
|
||||
if ($this->formActionPath) {
|
||||
@ -912,15 +992,18 @@ class Form extends RequestHandler {
|
||||
return Controller::join_links($this->controller->Link(), $this->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @ignore */
|
||||
private $formActionPath = false;
|
||||
|
||||
|
||||
/**
|
||||
* Set the form action attribute to a custom URL.
|
||||
*
|
||||
*
|
||||
* Note: For "normal" forms, you shouldn't need to use this method. It is recommended only for situations where
|
||||
* you have two relatively distinct parts of the system trying to communicate via a form post.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function setFormAction($path) {
|
||||
$this->formActionPath = $path;
|
||||
@ -942,12 +1025,15 @@ class Form extends RequestHandler {
|
||||
|
||||
/**
|
||||
* Set the HTML ID attribute of the form
|
||||
*
|
||||
* @param string $id
|
||||
* @return $this
|
||||
*/
|
||||
public function setHTMLID($id) {
|
||||
$this->htmlID = $id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns this form's controller.
|
||||
* This is used in the templates.
|
||||
@ -1005,14 +1091,14 @@ class Form extends RequestHandler {
|
||||
* The next functions store and modify the forms
|
||||
* message attributes. messages are stored in session under
|
||||
* $_SESSION[formname][message];
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function Message() {
|
||||
$this->getMessageFromSession();
|
||||
return $this->message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
@ -1037,12 +1123,13 @@ class Form extends RequestHandler {
|
||||
|
||||
/**
|
||||
* Set a status message for the form.
|
||||
*
|
||||
* @param message the text of the message
|
||||
* @param type Should be set to good, bad, or warning.
|
||||
*
|
||||
* @param string $message the text of the message
|
||||
* @param string $type Should be set to good, bad, or warning.
|
||||
* @param boolean $escapeHtml Automatically sanitize the message. Set to FALSE if the message contains HTML.
|
||||
* In that case, you might want to use {@link Convert::raw2xml()} to escape any
|
||||
* user supplied data in the message.
|
||||
* @return $this
|
||||
*/
|
||||
public function setMessage($message, $type, $escapeHtml = true) {
|
||||
$this->message = ($escapeHtml) ? Convert::raw2xml($message) : $message;
|
||||
@ -1052,16 +1139,16 @@ class Form extends RequestHandler {
|
||||
|
||||
/**
|
||||
* Set a message to the session, for display next time this form is shown.
|
||||
*
|
||||
* @param message the text of the message
|
||||
* @param type Should be set to good, bad, or warning.
|
||||
*
|
||||
* @param string $message the text of the message
|
||||
* @param string $type Should be set to good, bad, or warning.
|
||||
* @param boolean $escapeHtml Automatically sanitize the message. Set to FALSE if the message contains HTML.
|
||||
* In that case, you might want to use {@link Convert::raw2xml()} to escape any
|
||||
* user supplied data in the message.
|
||||
*/
|
||||
public function sessionMessage($message, $type, $escapeHtml = true) {
|
||||
Session::set(
|
||||
"FormInfo.{$this->FormName()}.formError.message",
|
||||
"FormInfo.{$this->FormName()}.formError.message",
|
||||
$escapeHtml ? Convert::raw2xml($message) : $message
|
||||
);
|
||||
Session::set("FormInfo.{$this->FormName()}.formError.type", $type);
|
||||
@ -1069,7 +1156,7 @@ class Form extends RequestHandler {
|
||||
|
||||
public static function messageForForm( $formName, $message, $type, $escapeHtml = true) {
|
||||
Session::set(
|
||||
"FormInfo.{$formName}.formError.message",
|
||||
"FormInfo.{$formName}.formError.message",
|
||||
$escapeHtml ? Convert::raw2xml($message) : $message
|
||||
);
|
||||
Session::set("FormInfo.{$formName}.formError.type", $type);
|
||||
@ -1089,13 +1176,13 @@ class Form extends RequestHandler {
|
||||
/**
|
||||
* Returns the DataObject that has given this form its data
|
||||
* through {@link loadDataFrom()}.
|
||||
*
|
||||
*
|
||||
* @return DataObject
|
||||
*/
|
||||
public function getRecord() {
|
||||
return $this->record;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the legend value to be inserted into the
|
||||
* <legend> element in Form.ss
|
||||
@ -1113,7 +1200,7 @@ class Form extends RequestHandler {
|
||||
* Triggered through {@link httpSubmission()}.
|
||||
* Note that CSRF protection takes place in {@link httpSubmission()},
|
||||
* if it fails the form data will never reach this method.
|
||||
*
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate(){
|
||||
@ -1123,7 +1210,7 @@ class Form extends RequestHandler {
|
||||
if($errors){
|
||||
// Load errors into session and post back
|
||||
$data = $this->getData();
|
||||
Session::set("FormInfo.{$this->FormName()}.errors", $errors);
|
||||
Session::set("FormInfo.{$this->FormName()}.errors", $errors);
|
||||
Session::set("FormInfo.{$this->FormName()}.data", $data);
|
||||
return false;
|
||||
}
|
||||
@ -1141,20 +1228,20 @@ class Form extends RequestHandler {
|
||||
* If you passed an array, it will call $object[MyField].
|
||||
* Doesn't save into dataless FormFields ({@link DatalessField}),
|
||||
* as determined by {@link FieldList->dataFields()}.
|
||||
*
|
||||
*
|
||||
* By default, if a field isn't set (as determined by isset()),
|
||||
* its value will not be saved to the field, retaining
|
||||
* potential existing values.
|
||||
*
|
||||
*
|
||||
* Passed data should not be escaped, and is saved to the FormField instances unescaped.
|
||||
* Escaping happens automatically on saving the data through {@link saveInto()}.
|
||||
*
|
||||
*
|
||||
* @uses FieldList->dataFields()
|
||||
* @uses FormField->setValue()
|
||||
*
|
||||
*
|
||||
* @param array|DataObject $data
|
||||
* @param int $mergeStrategy
|
||||
* For every field, {@link $data} is interogated whether it contains a relevant property/key, and
|
||||
* For every field, {@link $data} is interrogated whether it contains a relevant property/key, and
|
||||
* what that property/key's value is.
|
||||
*
|
||||
* By default, if {@link $data} does contain a property/key, the fields value is always replaced by {@link $data}'s
|
||||
@ -1172,7 +1259,7 @@ class Form extends RequestHandler {
|
||||
* For backwards compatibility reasons, this parameter can also be set to === true, which is the same as passing
|
||||
* CLEAR_MISSING
|
||||
*
|
||||
* @param $fieldList An optional list of fields to process. This can be useful when you have a
|
||||
* @param FieldList $fieldList An optional list of fields to process. This can be useful when you have a
|
||||
* form that has some fields that save to one object, and some that save to another.
|
||||
* @return Form
|
||||
*/
|
||||
@ -1198,9 +1285,9 @@ class Form extends RequestHandler {
|
||||
if($dataFields) foreach($dataFields as $field) {
|
||||
$name = $field->getName();
|
||||
|
||||
// Skip fields that have been exlcuded
|
||||
// Skip fields that have been excluded
|
||||
if($fieldList && !in_array($name, $fieldList)) continue;
|
||||
|
||||
|
||||
// First check looks for (fieldname)_unchanged, an indicator that we shouldn't overwrite the field value
|
||||
if(is_array($data) && isset($data[$name . '_unchanged'])) continue;
|
||||
|
||||
@ -1253,13 +1340,13 @@ class Form extends RequestHandler {
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save the contents of this form into the given data object.
|
||||
* It will make use of setCastedField() to do this.
|
||||
*
|
||||
* @param $dataObject The object to save data into
|
||||
* @param $fieldList An optional list of fields to process. This can be useful when you have a
|
||||
*
|
||||
* @param DataObjectInterface $dataObject The object to save data into
|
||||
* @param FieldList $fieldList An optional list of fields to process. This can be useful when you have a
|
||||
* form that has some fields that save to one object, and some that save to another.
|
||||
*/
|
||||
public function saveInto(DataObjectInterface $dataObject, $fieldList = null) {
|
||||
@ -1282,7 +1369,7 @@ class Form extends RequestHandler {
|
||||
}
|
||||
if($lastField) $lastField->saveInto($dataObject);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the submitted data from this form through
|
||||
* {@link FieldList->dataFields()}, which filters out
|
||||
@ -1290,13 +1377,13 @@ class Form extends RequestHandler {
|
||||
* Calls {@link FormField->dataValue()} on each field,
|
||||
* which returns a value suitable for insertion into a DataObject
|
||||
* property.
|
||||
*
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getData() {
|
||||
$dataFields = $this->fields->dataFields();
|
||||
$data = array();
|
||||
|
||||
|
||||
if($dataFields){
|
||||
foreach($dataFields as $field) {
|
||||
if($field->getName()) {
|
||||
@ -1311,8 +1398,9 @@ class Form extends RequestHandler {
|
||||
* Call the given method on the given field.
|
||||
* This is used by Ajax-savvy form fields. By putting '&action=callfieldmethod' to the end
|
||||
* of the form action, they can access server-side data.
|
||||
* @param fieldName The name of the field. Can be overridden by $_REQUEST[fieldName]
|
||||
* @param methodName The name of the field. Can be overridden by $_REQUEST[methodName]
|
||||
*
|
||||
* @param array $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function callfieldmethod($data) {
|
||||
$fieldName = $data['fieldName'];
|
||||
@ -1335,12 +1423,11 @@ class Form extends RequestHandler {
|
||||
} else {
|
||||
user_error("Form::callfieldmethod() Field '$fieldName' not found", E_USER_ERROR);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a rendered version of this form.
|
||||
*
|
||||
*
|
||||
* This is returned when you access a form as $FormObject rather
|
||||
* than <% with FormObject %>
|
||||
*/
|
||||
@ -1365,7 +1452,7 @@ class Form extends RequestHandler {
|
||||
$this->getTemplate(),
|
||||
'Form'
|
||||
));
|
||||
|
||||
|
||||
return $view->dontRewriteHashlinks()->process($this);
|
||||
}
|
||||
|
||||
@ -1391,6 +1478,8 @@ class Form extends RequestHandler {
|
||||
/**
|
||||
* Render this form using the given template, and return the result as a string
|
||||
* You can pass either an SSViewer or a template name
|
||||
* @param string|array $template
|
||||
* @return HTMLText
|
||||
*/
|
||||
public function renderWithoutActionButton($template) {
|
||||
$custom = $this->customise(array(
|
||||
@ -1404,13 +1493,18 @@ class Form extends RequestHandler {
|
||||
|
||||
/**
|
||||
* Sets the button that was clicked. This should only be called by the Controller.
|
||||
* @param funcName The name of the action method that will be called.
|
||||
*
|
||||
* @param callable $funcName The name of the action method that will be called.
|
||||
* @return $this
|
||||
*/
|
||||
public function setButtonClicked($funcName) {
|
||||
$this->buttonClickedFunc = $funcName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function buttonClicked() {
|
||||
foreach($this->actions->dataFields() as $action) {
|
||||
if($action->hasMethod('actionname') && $this->buttonClickedFunc == $action->actionName()) {
|
||||
@ -1421,6 +1515,8 @@ class Form extends RequestHandler {
|
||||
|
||||
/**
|
||||
* Return the default button that should be clicked when another one isn't available
|
||||
*
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function defaultAction() {
|
||||
if($this->hasDefaultAction && $this->actions)
|
||||
@ -1436,45 +1532,45 @@ class Form extends RequestHandler {
|
||||
$this->hasDefaultAction = false;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disable the requirement of a security token on this form instance. This security protects
|
||||
* against CSRF attacks, but you should disable this if you don't want to tie
|
||||
* against CSRF attacks, but you should disable this if you don't want to tie
|
||||
* a form to a session - eg a search form.
|
||||
*
|
||||
*
|
||||
* Check for token state with {@link getSecurityToken()} and {@link SecurityToken->isEnabled()}.
|
||||
*/
|
||||
public function disableSecurityToken() {
|
||||
$this->securityToken = new NullSecurityToken();
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable {@link SecurityToken} protection for this form instance.
|
||||
*
|
||||
*
|
||||
* Check for token state with {@link getSecurityToken()} and {@link SecurityToken->isEnabled()}.
|
||||
*/
|
||||
public function enableSecurityToken() {
|
||||
$this->securityToken = new SecurityToken();
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the security token for this form (if any exists).
|
||||
* Doesn't check for {@link securityTokenEnabled()}.
|
||||
* Use {@link SecurityToken::inst()} to get a global token.
|
||||
*
|
||||
*
|
||||
* @return SecurityToken|null
|
||||
*/
|
||||
public function getSecurityToken() {
|
||||
return $this->securityToken;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of a field, if that's the only field that the current controller is interested in.
|
||||
* It checks for a call to the callfieldmethod action.
|
||||
* This is useful for optimising your forms
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function single_field_required() {
|
||||
@ -1491,26 +1587,29 @@ class Form extends RequestHandler {
|
||||
|
||||
/**
|
||||
* Set the current form action. Should only be called by Controller.
|
||||
*
|
||||
* @param $action
|
||||
*/
|
||||
public static function set_current_action($action) {
|
||||
self::$current_action = $action;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compiles all CSS-classes.
|
||||
*
|
||||
* Compiles all CSS-classes.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function extraClass() {
|
||||
return implode(array_unique($this->extraClasses), ' ');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a CSS-class to the form-container. If needed, multiple classes can
|
||||
* be added by delimiting a string with spaces.
|
||||
* be added by delimiting a string with spaces.
|
||||
*
|
||||
* @param string $class A string containing a classname or several class
|
||||
* names delimited by a single space.
|
||||
* names delimited by a single space.
|
||||
* @return $this
|
||||
*/
|
||||
public function addExtraClass($class) {
|
||||
//split at white space
|
||||
@ -1527,6 +1626,7 @@ class Form extends RequestHandler {
|
||||
* be passed through as a space delimited string
|
||||
*
|
||||
* @param string $class
|
||||
* @return $this
|
||||
*/
|
||||
public function removeExtraClass($class) {
|
||||
//split at white space
|
||||
@ -1537,7 +1637,7 @@ class Form extends RequestHandler {
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function debug() {
|
||||
$result = "<h3>$this->class</h3><ul>";
|
||||
foreach($this->fields as $field) {
|
||||
@ -1550,28 +1650,34 @@ class Form extends RequestHandler {
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TESTING HELPERS
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* Test a submission of this form.
|
||||
* @param string $action
|
||||
* @param array $data
|
||||
* @return SS_HTTPResponse the response object that the handling controller produces. You can interrogate this in
|
||||
* your unit test.
|
||||
* @throws SS_HTTPResponse_Exception
|
||||
*/
|
||||
public function testSubmission($action, $data) {
|
||||
$data['action_' . $action] = true;
|
||||
|
||||
return Director::test($this->FormAction(), $data, Controller::curr()->getSession());
|
||||
|
||||
|
||||
//$response = $this->controller->run($data);
|
||||
//return $response;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test an ajax submission of this form.
|
||||
*
|
||||
* @param string $action
|
||||
* @param array $data
|
||||
* @return SS_HTTPResponse the response object that the handling controller produces. You can interrogate this in
|
||||
* your unit test.
|
||||
*/
|
||||
@ -1587,14 +1693,16 @@ class Form extends RequestHandler {
|
||||
*/
|
||||
class Form_FieldMap extends ViewableData {
|
||||
protected $form;
|
||||
|
||||
|
||||
public function __construct($form) {
|
||||
$this->form = $form;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ensure that all potential method calls get passed to __call(), therefore to dataFieldByName
|
||||
* @param string $method
|
||||
* @return bool
|
||||
*/
|
||||
public function hasMethod($method) {
|
||||
return true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user