mirror of
https://github.com/silverstripe/silverstripe-userforms.git
synced 2024-10-22 17:05:42 +02:00
Merge pull request #19 from tractorcow/pulls/field-groups
API Frontend form fields for nested composite fields
This commit is contained in:
commit
2c93124fb1
@ -40,19 +40,14 @@ class UserFormFieldEditorExtension extends DataExtension {
|
||||
$fieldClasses = $this->getEditableFieldClasses();
|
||||
$editableColumns->setDisplayFields(array(
|
||||
'ClassName' => function($record, $column, $grid) use ($fieldClasses) {
|
||||
if($record instanceof EditableFormStep) {
|
||||
return new LabelField($column, _t('UserFormFieldEditorExtension.PAGE_BREAK', 'Page Break'));
|
||||
} elseif($record instanceof EditableFieldGroup) {
|
||||
return new LabelField($column, _t('UserFormFieldEditorExtension.FIELD_GROUP_START', 'Field Group (start)'));
|
||||
} else if($record instanceof EditableFieldGroupEnd) {
|
||||
return new LabelField($column, _t('UserFormFieldEditorExtension.FIELD_GROUP_END', 'Field Group (end)'));
|
||||
} else {
|
||||
return DropdownField::create($column, '', $fieldClasses);
|
||||
if($record instanceof EditableFormField) {
|
||||
return $record->getInlineClassnameField($column, $fieldClasses);
|
||||
}
|
||||
},
|
||||
'Title' => function($record, $column, $grid) {
|
||||
return TextField::create($column, ' ')
|
||||
->setAttribute('placeholder', _t('UserDefinedForm.TITLE', 'Title'));
|
||||
if($record instanceof EditableFormField) {
|
||||
return $record->getInlineTitleField($column);
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
|
47
code/formfields/UserFormsCompositeField.php
Normal file
47
code/formfields/UserFormsCompositeField.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Represents a composite field group, which may contain other groups
|
||||
*/
|
||||
abstract class UserFormsCompositeField extends CompositeField implements UserFormsFieldContainer {
|
||||
|
||||
/**
|
||||
* Parent field
|
||||
*
|
||||
* @var UserFormsFieldContainer
|
||||
*/
|
||||
protected $parent = null;
|
||||
|
||||
public function getParent() {
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
public function setParent(UserFormsFieldContainer $parent) {
|
||||
$this->parent = $parent;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function processNext(EditableFormField $field) {
|
||||
// When we find a step, bubble up to the top
|
||||
if($field instanceof EditableFormStep) {
|
||||
return $this->getParent()->processNext($field);
|
||||
}
|
||||
|
||||
// Skip over fields that don't generate formfields
|
||||
$formField = $field->getFormField();
|
||||
if(!$formField) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Save this field
|
||||
$this->push($formField);
|
||||
|
||||
// Nest fields that are containers
|
||||
if($formField instanceof UserFormsFieldContainer) {
|
||||
return $formField->setParent($this);
|
||||
}
|
||||
|
||||
// Add any subsequent fields to this
|
||||
return $this;
|
||||
}
|
||||
}
|
30
code/formfields/UserFormsFieldContainer.php
Normal file
30
code/formfields/UserFormsFieldContainer.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Represents a field container which can iteratively process nested fields, converting it into a fieldset
|
||||
*/
|
||||
interface UserFormsFieldContainer {
|
||||
|
||||
/**
|
||||
* Process the next field in the list, returning the container to add the next field to.
|
||||
*
|
||||
* @param EditableFormField $field
|
||||
* @return EditableContainerField
|
||||
*/
|
||||
public function processNext(EditableFormField $field);
|
||||
|
||||
/**
|
||||
* Set the parent
|
||||
*
|
||||
* @param UserFormsFieldContainer $parent
|
||||
* @return $this
|
||||
*/
|
||||
public function setParent(UserFormsFieldContainer $parent);
|
||||
|
||||
/**
|
||||
* Get the parent
|
||||
*
|
||||
* @return UserFormsFieldContainer
|
||||
*/
|
||||
public function getParent();
|
||||
}
|
32
code/formfields/UserFormsFieldList.php
Normal file
32
code/formfields/UserFormsFieldList.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* A list of formfields which allows for iterative processing of nested composite fields
|
||||
*/
|
||||
class UserFormsFieldList extends FieldList implements UserFormsFieldContainer {
|
||||
|
||||
public function processNext(EditableFormField $field) {
|
||||
$formField = $field->getFormField();
|
||||
if(!$formField) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->push($formField);
|
||||
|
||||
if($formField instanceof UserFormsFieldContainer) {
|
||||
return $formField->setParent($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getParent() {
|
||||
// Field list does not have a parent
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setParent(UserFormsFieldContainer $parent) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
27
code/formfields/UserFormsGroupField.php
Normal file
27
code/formfields/UserFormsGroupField.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Front end composite field for userforms
|
||||
*/
|
||||
class UserFormsGroupField extends UserFormsCompositeField {
|
||||
|
||||
public function __construct($children = null) {
|
||||
parent::__construct($children);
|
||||
$this->setTag('fieldset');
|
||||
}
|
||||
|
||||
public function getLegend() {
|
||||
// Legend defaults to title
|
||||
return parent::getLegend() ?: $this->Title();
|
||||
}
|
||||
|
||||
public function processNext(EditableFormField $field) {
|
||||
// When ending a group, jump up one level
|
||||
if($field instanceof EditableFieldGroupEnd) {
|
||||
return $this->getParent();
|
||||
}
|
||||
|
||||
// Otherwise behave as per normal composite field
|
||||
return parent::processNext($field);
|
||||
}
|
||||
}
|
7
code/formfields/UserFormsStepField.php
Normal file
7
code/formfields/UserFormsStepField.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Represents a page step in a form, which may contain form fields or other groups
|
||||
*/
|
||||
class UserFormsStepField extends UserFormsCompositeField {
|
||||
}
|
@ -75,31 +75,11 @@ class UserForm extends Form {
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getFormFields() {
|
||||
$fields = new FieldList();
|
||||
$emptyStep = null; // Last empty step, which may or may not later have children
|
||||
|
||||
$fields = new UserFormsFieldList();
|
||||
$target = $fields;
|
||||
foreach ($this->controller->Fields() as $field) {
|
||||
// When we encounter a step, save it
|
||||
if ($field instanceof EditableFormStep) {
|
||||
$emptyStep = $field->getFormField();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ensure that the last field is a step
|
||||
if($emptyStep) {
|
||||
// When we reach the first non-step field, any empty step will no longer be empty
|
||||
$fields->push($emptyStep);
|
||||
$emptyStep = null;
|
||||
|
||||
} elseif(! $fields->last()) {
|
||||
// If no steps have been saved yet, warn
|
||||
trigger_error('Missing first step in form', E_USER_WARNING);
|
||||
$fields->push(singleton('EditableFormStep')->getFormField());
|
||||
}
|
||||
|
||||
$fields->last()->push($field->getFormField());
|
||||
$target = $target->processNext($field);
|
||||
}
|
||||
|
||||
$this->extend('updateFormFields', $fields);
|
||||
return $fields;
|
||||
}
|
||||
|
@ -12,5 +12,42 @@ class EditableFieldGroup extends EditableFormField {
|
||||
* @var bool
|
||||
*/
|
||||
private static $hidden = true;
|
||||
|
||||
public function getCMSFields() {
|
||||
$fields = parent::getCMSFields();
|
||||
$fields->removeByName(array('MergeField', 'Default', 'Validation', 'DisplayRules'));
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function getInlineClassnameField($column, $fieldClasses) {
|
||||
return new LabelField(
|
||||
$column,
|
||||
_t('EditableFieldGroup.FIELD_GROUP_START', 'Field Group (start)')
|
||||
);
|
||||
}
|
||||
|
||||
public function showInReports() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getFormField() {
|
||||
$field = UserFormsGroupField::create()
|
||||
->setTitle($this->EscapedTitle ?: false);
|
||||
$this->doUpdateFormField($field);
|
||||
return $field;
|
||||
}
|
||||
|
||||
protected function updateFormField($field) {
|
||||
// set the right title on this field
|
||||
if($this->RightTitle) {
|
||||
// Since this field expects raw html, safely escape the user data prior
|
||||
$field->setRightTitle(Convert::raw2xml($this->RightTitle));
|
||||
}
|
||||
|
||||
// if this field has an extra class
|
||||
if($field->ExtraClass) {
|
||||
$field->addExtraClass($field->ExtraClass);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,5 +12,34 @@ class EditableFieldGroupEnd extends EditableFormField {
|
||||
* @var bool
|
||||
*/
|
||||
private static $hidden = true;
|
||||
|
||||
public function getCMSFields() {
|
||||
$fields = parent::getCMSFields();
|
||||
$fields->removeByName(array('MergeField', 'Default', 'Validation', 'DisplayRules'));
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function getInlineClassnameField($column, $fieldClasses) {
|
||||
return new LabelField(
|
||||
$column,
|
||||
_t('EditableFieldGroupEnd.FIELD_GROUP_END', 'Field Group (end)')
|
||||
);
|
||||
}
|
||||
|
||||
public function getInlineTitleField($column) {
|
||||
return HiddenField::create($column);
|
||||
}
|
||||
|
||||
public function getFormField() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function showInReports() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function canEdit($member = null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -624,4 +624,27 @@ class EditableFormField extends DataObject {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the formfield to use when editing this inline in gridfield
|
||||
*
|
||||
* @param string $column name of column
|
||||
* @param array $fieldClasses List of allowed classnames if this formfield has a selectable class
|
||||
* @return FormField
|
||||
*/
|
||||
public function getInlineClassnameField($column, $fieldClasses) {
|
||||
return DropdownField::create($column, false, $fieldClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the formfield to use when editing the title inline
|
||||
*
|
||||
* @param string $column
|
||||
* @return FormField
|
||||
*/
|
||||
public function getInlineTitleField($column) {
|
||||
return TextField::create($column, false)
|
||||
->setAttribute('placeholder', _t('EditableFormField.TITLE', 'Title'))
|
||||
->setAttribute('data-placeholder', _t('EditableFormField.TITLE', 'Title'));
|
||||
}
|
||||
}
|
||||
|
@ -32,10 +32,7 @@ class EditableFormStep extends EditableFormField {
|
||||
public function getCMSFields() {
|
||||
$fields = parent::getCMSFields();
|
||||
|
||||
$fields->removeByName('MergeField');
|
||||
$fields->removeByName('Default');
|
||||
$fields->removeByName('Validation');
|
||||
$fields->removeByName('CustomRules');
|
||||
$fields->removeByName(array('MergeField', 'Default', 'Validation', 'DisplayRules'));
|
||||
|
||||
return $fields;
|
||||
}
|
||||
@ -44,7 +41,7 @@ class EditableFormStep extends EditableFormField {
|
||||
* @return FormField
|
||||
*/
|
||||
public function getFormField() {
|
||||
$field = CompositeField::create()
|
||||
$field = UserFormsStepField::create()
|
||||
->setTitle($this->EscapedTitle);
|
||||
$this->doUpdateFormField($field);
|
||||
return $field;
|
||||
@ -63,4 +60,11 @@ class EditableFormStep extends EditableFormField {
|
||||
public function showInReports() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getInlineClassnameField($column, $fieldClasses) {
|
||||
return new LabelField(
|
||||
$column,
|
||||
_t('EditableFieldGroupEnd.PAGE_BREAK', 'Page Break')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user