Merge remote-tracking branch 'origin/3.1'

# Conflicts:
#	code/forms/UserForm.php
#	code/model/UserDefinedForm.php
#	code/model/editableformfields/EditableFileField.php
#	code/model/editableformfields/EditableOption.php
This commit is contained in:
Damian Mooyman 2016-08-18 10:20:56 +12:00
commit c6c609a4c9
5 changed files with 188 additions and 163 deletions

View File

@ -6,49 +6,49 @@
class UserForm extends Form class UserForm extends Form
{ {
/** /**
* @param Controller $controller * @param Controller $controller
* @param string $name * @param string $name
*/ */
public function __construct(Controller $controller, $name = 'Form') public function __construct(Controller $controller, $name = 'Form')
{ {
$this->controller = $controller; $this->controller = $controller;
$this->setRedirectToFormOnValidationError(true); $this->setRedirectToFormOnValidationError(true);
parent::__construct( parent::__construct(
$controller, $controller,
$name, $name,
new FieldList(), new FieldList(),
new FieldList() new FieldList()
); );
$this->setFields($fields = $this->getFormFields()); $this->setFields($fields = $this->getFormFields());
$fields->setForm($this); $fields->setForm($this);
$this->setActions($actions = $this->getFormActions()); $this->setActions($actions = $this->getFormActions());
$actions->setForm($this); $actions->setForm($this);
$this->setValidator($this->getRequiredFields()); $this->setValidator($this->getRequiredFields());
// This needs to be re-evaluated since fields have been assigned // This needs to be re-evaluated since fields have been assigned
$this->setupFormErrors(); $this->setupFormErrors();
// Number each page // Number each page
$stepNumber = 1; $stepNumber = 1;
foreach ($this->getSteps() as $step) { foreach($this->getSteps() as $step) {
$step->setStepNumber($stepNumber++); $step->setStepNumber($stepNumber++);
} }
if ($controller->DisableCsrfSecurityToken) { if($controller->DisableCsrfSecurityToken) {
$this->disableSecurityToken(); $this->disableSecurityToken();
} }
$data = Session::get("FormInfo.{$this->FormName()}.data"); $data = Session::get("FormInfo.{$this->FormName()}.data");
if (is_array($data)) { if(is_array($data)) {
$this->loadDataFrom($data); $this->loadDataFrom($data);
} }
$this->extend('updateForm'); $this->extend('updateForm');
} }
public function setupFormErrors() public function setupFormErrors()
{ {
@ -60,118 +60,126 @@ class UserForm extends Form
return $this; return $this;
} }
/** /**
* Used for partial caching in the template. * Used for partial caching in the template.
* *
* @return string * @return string
*/ */
public function getLastEdited() public function getLastEdited()
{ {
return $this->controller->LastEdited; return $this->controller->LastEdited;
} }
/** /**
* @return bool * @return bool
*/ */
public function getDisplayErrorMessagesAtTop() public function getDisplayErrorMessagesAtTop()
{ {
return (bool)$this->controller->DisplayErrorMessagesAtTop; return (bool)$this->controller->DisplayErrorMessagesAtTop;
} }
/** /**
* Return the fieldlist, filtered to only contain steps * Return the fieldlist, filtered to only contain steps
* *
* @return ArrayList * @return ArrayList
*/ */
public function getSteps() public function getSteps()
{ {
return $this->Fields()->filterByCallback(function ($field) { return $this->Fields()->filterByCallback(function($field) {
return $field instanceof UserFormsStepField; return $field instanceof UserFormsStepField;
}); });
} }
/** /**
* Get the form fields for the form on this page. Can modify this FieldSet * Get the form fields for the form on this page. Can modify this FieldSet
* by using {@link updateFormFields()} on an {@link Extension} subclass which * by using {@link updateFormFields()} on an {@link Extension} subclass which
* is applied to this controller. * is applied to this controller.
* *
* This will be a list of top level composite steps * This will be a list of top level composite steps
* *
* @return FieldList * @return FieldList
*/ */
public function getFormFields() public function getFormFields()
{ {
$fields = new UserFormsFieldList(); $fields = new UserFormsFieldList();
$target = $fields; $target = $fields;
foreach ($this->controller->Fields() as $field) { foreach ($this->controller->Fields() as $field) {
$target = $target->processNext($field); $target = $target->processNext($field);
} }
$fields->clearEmptySteps(); $fields->clearEmptySteps();
$this->extend('updateFormFields', $fields); $this->extend('updateFormFields', $fields);
$fields->setForm($this); $fields->setForm($this);
return $fields; return $fields;
} }
/** /**
* Generate the form actions for the UserDefinedForm. You * Generate the form actions for the UserDefinedForm. You
* can manipulate these by using {@link updateFormActions()} on * can manipulate these by using {@link updateFormActions()} on
* a decorator. * a decorator.
* *
* @todo Make form actions editable via their own field editor. * @todo Make form actions editable via their own field editor.
* *
* @return FieldList * @return FieldList
*/ */
public function getFormActions() public function getFormActions()
{ {
$submitText = ($this->controller->SubmitButtonText) ? $this->controller->SubmitButtonText : _t('UserDefinedForm.SUBMITBUTTON', 'Submit'); $submitText = ($this->controller->SubmitButtonText) ? $this->controller->SubmitButtonText : _t('UserDefinedForm.SUBMITBUTTON', 'Submit');
$clearText = ($this->controller->ClearButtonText) ? $this->controller->ClearButtonText : _t('UserDefinedForm.CLEARBUTTON', 'Clear'); $clearText = ($this->controller->ClearButtonText) ? $this->controller->ClearButtonText : _t('UserDefinedForm.CLEARBUTTON', 'Clear');
$actions = new FieldList( $actions = new FieldList(
new FormAction("process", $submitText) new FormAction("process", $submitText)
); );
if ($this->controller->ShowClearButton) { if($this->controller->ShowClearButton) {
$actions->push(new ResetFormAction("clearForm", $clearText)); $actions->push(new ResetFormAction("clearForm", $clearText));
} }
$this->extend('updateFormActions', $actions); $this->extend('updateFormActions', $actions);
$actions->setForm($this); $actions->setForm($this);
return $actions; return $actions;
} }
/** /**
* Get the required form fields for this form. * Get the required form fields for this form.
* *
* @return RequiredFields * @return RequiredFields
*/ */
public function getRequiredFields() public function getRequiredFields()
{ {
// Generate required field validator // Generate required field validator
$requiredNames = $this $requiredNames = $this
->getController() ->getController()
->Fields() ->Fields()
->filter('Required', true) ->filter('Required', true)
->column('Name'); ->column('Name');
$required = new RequiredFields($requiredNames); $required = new RequiredFields($requiredNames);
$this->extend('updateRequiredFields', $required); $this->extend('updateRequiredFields', $required);
$required->setForm($this); $required->setForm($this);
return $required; return $required;
} }
/** /**
* Override some we can add UserForm specific attributes to the form. * Override some we can add UserForm specific attributes to the form.
* *
* @return array * @return array
*/ */
public function getAttributes() public function getAttributes()
{ {
$attrs = parent::getAttributes(); $attrs = parent::getAttributes();
$attrs['class'] = $attrs['class'] . ' userform'; $attrs['class'] = $attrs['class'] . ' userform';
$attrs['data-livevalidation'] = (bool)$this->controller->EnableLiveValidation; $attrs['data-livevalidation'] = (bool)$this->controller->EnableLiveValidation;
$attrs['data-toperrors'] = (bool)$this->controller->DisplayErrorMessagesAtTop; $attrs['data-toperrors'] = (bool)$this->controller->DisplayErrorMessagesAtTop;
$attrs['data-hidefieldlabels'] = (bool)$this->controller->HideFieldLabels; $attrs['data-hidefieldlabels'] = (bool)$this->controller->HideFieldLabels;
return $attrs; return $attrs;
}
/**
* @return string
*/
public function getButtonText() {
return $this->config()->get('button_text');
} }
} }

View File

@ -10,32 +10,32 @@
class EditableOption extends DataObject class EditableOption extends DataObject
{ {
private static $default_sort = "Sort"; private static $default_sort = "Sort";
private static $db = array( private static $db = array(
"Name" => "Varchar(255)", "Name" => "Varchar(255)",
"Title" => "Varchar(255)", "Title" => "Varchar(255)",
"Default" => "Boolean", "Default" => "Boolean",
"Sort" => "Int", "Sort" => "Int",
"Value" => "Varchar(255)", "Value" => "Varchar(255)",
); );
private static $has_one = array( private static $has_one = array(
"Parent" => "EditableMultipleOptionField", "Parent" => "EditableMultipleOptionField",
); );
private static $extensions = array( private static $extensions = array(
"Versioned('Stage', 'Live')" "Versioned('Stage', 'Live')"
); );
private static $summary_fields = array( private static $summary_fields = array(
'Title', 'Title',
'Default' 'Default'
); );
protected static $allow_empty_values = false; protected static $allow_empty_values = false;
/** /**
* Returns whether to allow empty values or not. * Returns whether to allow empty values or not.
* *
* @return boolean * @return boolean
@ -56,29 +56,29 @@ class EditableOption extends DataObject
} }
/** /**
* @param Member $member * @param Member $member
* *
* @return boolean * @return boolean
*/ */
public function canEdit($member = null) public function canEdit($member = null)
{ {
return $this->Parent()->canEdit($member); return $this->Parent()->canEdit($member);
} }
/** /**
* @param Member $member * @param Member $member
* *
* @return boolean * @return boolean
*/ */
public function canDelete($member = null) public function canDelete($member = null)
{ {
return $this->canEdit($member); return $this->canEdit($member);
} }
public function getEscapedTitle() public function getEscapedTitle()
{ {
return Convert::raw2att($this->Title); return Convert::raw2att($this->Title);
} }
/** /**
* @param Member $member * @param Member $member
@ -86,27 +86,27 @@ class EditableOption extends DataObject
*/ */
public function canView($member = null) public function canView($member = null)
{ {
return $this->Parent()->canView($member); return $this->Parent()->canView($member);
} }
/** /**
* Return whether a user can create an object of this type * Return whether a user can create an object of this type
* *
* @param Member $member * @param Member $member
* @param array $context Virtual parameter to allow context to be passed in to check * @param array $context Virtual parameter to allow context to be passed in to check
* @return bool * @return bool
*/ */
public function canCreate($member = null) public function canCreate($member = null)
{ {
// Check parent page // Check parent page
$parent = $this->getCanCreateContext(func_get_args()); $parent = $this->getCanCreateContext(func_get_args());
if ($parent) { if($parent) {
return $parent->canEdit($member); return $parent->canEdit($member);
} }
// Fall back to secure admin permissions // Fall back to secure admin permissions
return parent::canCreate($member); return parent::canCreate($member);
} }
/** /**
* Helper method to check the parent for this object * Helper method to check the parent for this object
@ -117,11 +117,11 @@ class EditableOption extends DataObject
protected function getCanCreateContext($args) protected function getCanCreateContext($args)
{ {
// Inspect second parameter to canCreate for a 'Parent' context // Inspect second parameter to canCreate for a 'Parent' context
if (isset($args[1]['Parent'])) { if(isset($args[1]['Parent'])) {
return $args[1]['Parent']; return $args[1]['Parent'];
} }
// Hack in currently edited page if context is missing // Hack in currently edited page if context is missing
if (Controller::has_curr() && Controller::curr() instanceof CMSMain) { if(Controller::has_curr() && Controller::curr() instanceof CMSMain) {
return Controller::curr()->currentPage(); return Controller::curr()->currentPage();
} }
@ -161,4 +161,12 @@ class EditableOption extends DataObject
} }
return $value; return $value;
} }
protected function onBeforeWrite() {
if (!$this->Sort) {
$this->Sort = EditableOption::get()->max('Sort') + 1;
}
parent::onBeforeWrite();
}
} }

View File

@ -83,4 +83,13 @@ UserDefinedForm:
email_template_directory: your/template/path/ email_template_directory: your/template/path/
```` ````
Any SilverStripe templates placed in your `email_template_directory` directory will be available for use with submission emails. Any SilverStripe templates placed in your `email_template_directory` directory will be available for use with submission emails.
### Custom Multi-Step button Text
If you want to change the button text when using the Multi-Step/Page Break feature, simply add the following to your `config.yml`:
````
UserForm:
button_text: 'Your Text Here'
````

View File

@ -468,7 +468,7 @@ jQuery(function ($) {
this.$buttons.each(function (i, stepButton) { this.$buttons.each(function (i, stepButton) {
$(stepButton).on('click', function (e) { $(stepButton).on('click', function (e) {
e.preventDefault(); e.preventDefault();
self.$el.trigger('userform.progress.changestep', [parseInt($(this).text(), 10)]); self.$el.trigger('userform.progress.changestep', [parseInt($(this).data('step'), 10)]);
}); });
}); });
@ -552,7 +552,7 @@ jQuery(function ($) {
var $element = $(element), var $element = $(element),
$item = $element.parent(); $item = $element.parent();
if (parseInt($element.text(), 10) === stepNumber && $element.is(':visible')) { if (parseInt($element.data('step'), 10) === stepNumber && $element.is(':visible')) {
$item.addClass('current viewed'); $item.addClass('current viewed');
$element.removeAttr('disabled'); $element.removeAttr('disabled');

View File

@ -9,7 +9,7 @@
<% loop $Steps %> <% loop $Steps %>
<li class="step-button-wrapper<% if $First %> current<% end_if %>" data-for="$Name"> <li class="step-button-wrapper<% if $First %> current<% end_if %>" data-for="$Name">
<%-- Remove js-align class to remove javascript positioning --%> <%-- Remove js-align class to remove javascript positioning --%>
<button class="step-button-jump js-align" disabled="disabled">$Pos</button> <button class="step-button-jump js-align" disabled="disabled" data-step="$Pos"><% if $Top.ButtonText %>$Top.ButtonText <% end_if %>$Pos</button>
</li> </li>
<% end_loop %> <% end_loop %>
</ul> </ul>