Update and fix PHP docblocks, document spelling mistakes and strip trailing whitespace on Form.php

This commit is contained in:
Stig Lindqvist 2015-06-12 10:28:32 +12:00
parent 04b803dfc6
commit 95860e9229

View File

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