mirror of
https://github.com/silverstripe/silverstripe-userforms.git
synced 2024-10-22 17:05:42 +02:00
commit
9294734f73
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
if(!defined('USERFORMS_DIR')) {
|
||||
define('USERFORMS_DIR', basename(__DIR__));
|
||||
if (!defined('USERFORMS_DIR')) {
|
||||
define('USERFORMS_DIR', basename(__DIR__));
|
||||
}
|
||||
|
||||
Deprecation::notification_version('3.0', 'userforms');
|
||||
|
@ -7,113 +7,118 @@
|
||||
*
|
||||
* @package userforms
|
||||
*/
|
||||
class UserFormsGridFieldFilterHeader extends GridFieldFilterHeader {
|
||||
class UserFormsGridFieldFilterHeader extends GridFieldFilterHeader
|
||||
{
|
||||
|
||||
/**
|
||||
* A map of name => value of columns from all submissions
|
||||
* @var array
|
||||
*/
|
||||
protected $columns;
|
||||
/**
|
||||
* A map of name => value of columns from all submissions
|
||||
* @var array
|
||||
*/
|
||||
protected $columns;
|
||||
|
||||
public function setColumns($columns) {
|
||||
$this->columns = $columns;
|
||||
}
|
||||
public function setColumns($columns)
|
||||
{
|
||||
$this->columns = $columns;
|
||||
}
|
||||
|
||||
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
|
||||
if(!$this->checkDataType($gridField->getList())) {
|
||||
return;
|
||||
}
|
||||
public function handleAction(GridField $gridField, $actionName, $arguments, $data)
|
||||
{
|
||||
if (!$this->checkDataType($gridField->getList())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if($actionName === 'filter') {
|
||||
$gridField->State->UserFormsGridField = array(
|
||||
'filter' => isset($data['FieldNameFilter']) ? $data['FieldNameFilter'] : null,
|
||||
'value' => isset($data['FieldValue']) ? $data['FieldValue'] : null,
|
||||
'start' => isset($data['StartFilter']) ? $data['StartFilter'] : null,
|
||||
'end' => isset($data['EndFilter']) ? $data['EndFilter'] : null
|
||||
);
|
||||
}
|
||||
}
|
||||
if ($actionName === 'filter') {
|
||||
$gridField->State->UserFormsGridField = array(
|
||||
'filter' => isset($data['FieldNameFilter']) ? $data['FieldNameFilter'] : null,
|
||||
'value' => isset($data['FieldValue']) ? $data['FieldValue'] : null,
|
||||
'start' => isset($data['StartFilter']) ? $data['StartFilter'] : null,
|
||||
'end' => isset($data['EndFilter']) ? $data['EndFilter'] : null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getHTMLFragments($gridField) {
|
||||
$fields = new ArrayList();
|
||||
$state = $gridField->State->UserFormsGridField;
|
||||
public function getHTMLFragments($gridField)
|
||||
{
|
||||
$fields = new ArrayList();
|
||||
$state = $gridField->State->UserFormsGridField;
|
||||
|
||||
$selectedField = $state->filter;
|
||||
$selectedValue = $state->value;
|
||||
$selectedField = $state->filter;
|
||||
$selectedValue = $state->value;
|
||||
|
||||
// show dropdown of all the fields available from the submitted form fields
|
||||
// that have been saved. Takes the titles from the currently live form.
|
||||
$columnField = new DropdownField('FieldNameFilter', '');
|
||||
$columnField->setSource($this->columns);
|
||||
$columnField->setEmptyString(_t('UserFormsGridFieldFilterHeader.FILTERSUBMISSIONS', 'Filter Submissions..'));
|
||||
$columnField->setHasEmptyDefault(true);
|
||||
$columnField->setValue($selectedField);
|
||||
// show dropdown of all the fields available from the submitted form fields
|
||||
// that have been saved. Takes the titles from the currently live form.
|
||||
$columnField = new DropdownField('FieldNameFilter', '');
|
||||
$columnField->setSource($this->columns);
|
||||
$columnField->setEmptyString(_t('UserFormsGridFieldFilterHeader.FILTERSUBMISSIONS', 'Filter Submissions..'));
|
||||
$columnField->setHasEmptyDefault(true);
|
||||
$columnField->setValue($selectedField);
|
||||
|
||||
$valueField = new TextField('FieldValue', '', $selectedValue);
|
||||
$valueField = new TextField('FieldValue', '', $selectedValue);
|
||||
|
||||
$columnField->addExtraClass('ss-gridfield-sort');
|
||||
$columnField->addExtraClass('no-change-track');
|
||||
$columnField->addExtraClass('ss-gridfield-sort');
|
||||
$columnField->addExtraClass('no-change-track');
|
||||
|
||||
$valueField->addExtraClass('ss-gridfield-sort');
|
||||
$valueField->addExtraClass('no-change-track');
|
||||
$valueField->setAttribute(
|
||||
'placeholder',
|
||||
_t('UserFormsGridFieldFilterHeader.WHEREVALUEIS', 'where value is..'
|
||||
));
|
||||
$valueField->addExtraClass('ss-gridfield-sort');
|
||||
$valueField->addExtraClass('no-change-track');
|
||||
$valueField->setAttribute(
|
||||
'placeholder',
|
||||
_t('UserFormsGridFieldFilterHeader.WHEREVALUEIS', 'where value is..'
|
||||
));
|
||||
|
||||
$fields->push(new FieldGroup(new CompositeField(
|
||||
$columnField,
|
||||
$valueField
|
||||
)));
|
||||
$fields->push(new FieldGroup(new CompositeField(
|
||||
$columnField,
|
||||
$valueField
|
||||
)));
|
||||
|
||||
$fields->push(new FieldGroup(new CompositeField(
|
||||
$start = new DateField('StartFilter', _t('UserFormsGridFieldFilterHeader.FROM', 'From')),
|
||||
$end = new DateField('EndFilter', _t('UserFormsGridFieldFilterHeader.TILL', 'Till'))
|
||||
)));
|
||||
$fields->push(new FieldGroup(new CompositeField(
|
||||
$start = new DateField('StartFilter', _t('UserFormsGridFieldFilterHeader.FROM', 'From')),
|
||||
$end = new DateField('EndFilter', _t('UserFormsGridFieldFilterHeader.TILL', 'Till'))
|
||||
)));
|
||||
|
||||
foreach(array($start, $end) as $date) {
|
||||
$date->setConfig('showcalendar', true);
|
||||
$date->setConfig('dateformat', 'y-mm-dd');
|
||||
$date->setConfig('datavalueformat', 'y-mm-dd');
|
||||
$date->addExtraClass('no-change-track');
|
||||
}
|
||||
foreach (array($start, $end) as $date) {
|
||||
$date->setConfig('showcalendar', true);
|
||||
$date->setConfig('dateformat', 'y-mm-dd');
|
||||
$date->setConfig('datavalueformat', 'y-mm-dd');
|
||||
$date->addExtraClass('no-change-track');
|
||||
}
|
||||
|
||||
$end->setValue($state->end);
|
||||
$start->setValue($state->start);
|
||||
$end->setValue($state->end);
|
||||
$start->setValue($state->start);
|
||||
|
||||
|
||||
$fields->push($actions = new FieldGroup(
|
||||
GridField_FormAction::create($gridField, 'filter', false, 'filter', null)
|
||||
->addExtraClass('ss-gridfield-button-filter')
|
||||
->setAttribute('title', _t('GridField.Filter', "Filter"))
|
||||
->setAttribute('id', 'action_filter_' . $gridField->getModelClass() . '_' . $columnField),
|
||||
GridField_FormAction::create($gridField, 'reset', false, 'reset', null)
|
||||
->addExtraClass('ss-gridfield-button-close')
|
||||
->setAttribute('title', _t('GridField.ResetFilter', "Reset"))
|
||||
->setAttribute('id', 'action_reset_' . $gridField->getModelClass() . '_' . $columnField)
|
||||
)
|
||||
);
|
||||
$fields->push($actions = new FieldGroup(
|
||||
GridField_FormAction::create($gridField, 'filter', false, 'filter', null)
|
||||
->addExtraClass('ss-gridfield-button-filter')
|
||||
->setAttribute('title', _t('GridField.Filter', "Filter"))
|
||||
->setAttribute('id', 'action_filter_' . $gridField->getModelClass() . '_' . $columnField),
|
||||
GridField_FormAction::create($gridField, 'reset', false, 'reset', null)
|
||||
->addExtraClass('ss-gridfield-button-close')
|
||||
->setAttribute('title', _t('GridField.ResetFilter', "Reset"))
|
||||
->setAttribute('id', 'action_reset_' . $gridField->getModelClass() . '_' . $columnField)
|
||||
)
|
||||
);
|
||||
|
||||
$actions->addExtraClass('filter-buttons');
|
||||
$actions->addExtraClass('no-change-track');
|
||||
$actions->addExtraClass('filter-buttons');
|
||||
$actions->addExtraClass('no-change-track');
|
||||
|
||||
$forTemplate = new ArrayData(array(
|
||||
'Fields' => $fields
|
||||
));
|
||||
$forTemplate = new ArrayData(array(
|
||||
'Fields' => $fields
|
||||
));
|
||||
|
||||
|
||||
return array(
|
||||
'header' => $forTemplate->renderWith('GridFieldFilterHeader_Row')
|
||||
);
|
||||
}
|
||||
return array(
|
||||
'header' => $forTemplate->renderWith('GridFieldFilterHeader_Row')
|
||||
);
|
||||
}
|
||||
|
||||
public function getManipulatedData(GridField $gridField, SS_List $dataList) {
|
||||
$state = $gridField->State;
|
||||
public function getManipulatedData(GridField $gridField, SS_List $dataList)
|
||||
{
|
||||
$state = $gridField->State;
|
||||
|
||||
if($filter = $state->UserFormsGridField->toArray()) {
|
||||
if(isset($filter['filter']) && $filter['filter'] && isset($filter['value']) && $filter['value']) {
|
||||
$dataList = $dataList->where(sprintf("
|
||||
if ($filter = $state->UserFormsGridField->toArray()) {
|
||||
if (isset($filter['filter']) && $filter['filter'] && isset($filter['value']) && $filter['value']) {
|
||||
$dataList = $dataList->where(sprintf("
|
||||
SELECT COUNT(*) FROM SubmittedFormField
|
||||
WHERE (
|
||||
ParentID = SubmittedForm.ID AND
|
||||
@ -121,24 +126,24 @@ class UserFormsGridFieldFilterHeader extends GridFieldFilterHeader {
|
||||
Value LIKE '%s'
|
||||
) > 0",
|
||||
|
||||
Convert::raw2sql($filter['filter']),
|
||||
Convert::raw2sql($filter['value'])
|
||||
));
|
||||
}
|
||||
Convert::raw2sql($filter['filter']),
|
||||
Convert::raw2sql($filter['value'])
|
||||
));
|
||||
}
|
||||
|
||||
if(isset($filter['start']) && $filter['start']) {
|
||||
$dataList = $dataList->filter(array(
|
||||
'Created:GreaterThan' => $filter['start']
|
||||
));
|
||||
}
|
||||
if (isset($filter['start']) && $filter['start']) {
|
||||
$dataList = $dataList->filter(array(
|
||||
'Created:GreaterThan' => $filter['start']
|
||||
));
|
||||
}
|
||||
|
||||
if(isset($filter['end']) && $filter['end']) {
|
||||
$dataList = $dataList->filter(array(
|
||||
'Created:LessThan' => $filter['end']
|
||||
));
|
||||
}
|
||||
}
|
||||
if (isset($filter['end']) && $filter['end']) {
|
||||
$dataList = $dataList->filter(array(
|
||||
'Created:LessThan' => $filter['end']
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return $dataList;
|
||||
}
|
||||
return $dataList;
|
||||
}
|
||||
}
|
||||
|
@ -5,140 +5,147 @@
|
||||
*
|
||||
* {@see EditableFileField}
|
||||
*/
|
||||
class SecureEditableFileField extends DataExtension {
|
||||
class SecureEditableFileField extends DataExtension
|
||||
{
|
||||
|
||||
/**
|
||||
* Path to secure files location under assets
|
||||
*
|
||||
* @config
|
||||
* @var type
|
||||
*/
|
||||
private static $secure_folder_name = 'SecureUploads';
|
||||
/**
|
||||
* Path to secure files location under assets
|
||||
*
|
||||
* @config
|
||||
* @var type
|
||||
*/
|
||||
private static $secure_folder_name = 'SecureUploads';
|
||||
|
||||
/**
|
||||
* Disable file security if a user-defined mechanism is in place
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $disable_security = false;
|
||||
/**
|
||||
* Disable file security if a user-defined mechanism is in place
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $disable_security = false;
|
||||
|
||||
/*
|
||||
* Check if file security is enabled
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getIsSecurityEnabled() {
|
||||
// Skip if requested
|
||||
if($this->owner->config()->disable_security) {
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* Check if file security is enabled
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getIsSecurityEnabled()
|
||||
{
|
||||
// Skip if requested
|
||||
if ($this->owner->config()->disable_security) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for necessary security module
|
||||
if(!class_exists('SecureFileExtension')) {
|
||||
trigger_error('SecureEditableFileField requires secureassets module', E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
// Check for necessary security module
|
||||
if (!class_exists('SecureFileExtension')) {
|
||||
trigger_error('SecureEditableFileField requires secureassets module', E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function requireDefaultRecords() {
|
||||
// Skip if disabled
|
||||
if(!$this->getIsSecurityEnabled()) {
|
||||
return;
|
||||
}
|
||||
public function requireDefaultRecords()
|
||||
{
|
||||
// Skip if disabled
|
||||
if (!$this->getIsSecurityEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update all instances of editablefilefield which do NOT have a secure folder assigned
|
||||
foreach(EditableFileField::get() as $fileField) {
|
||||
// Skip if secured
|
||||
if($fileField->getIsSecure()) {
|
||||
continue;
|
||||
}
|
||||
// Update all instances of editablefilefield which do NOT have a secure folder assigned
|
||||
foreach (EditableFileField::get() as $fileField) {
|
||||
// Skip if secured
|
||||
if ($fileField->getIsSecure()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Force this field to secure itself on write
|
||||
$fileField->write(false, false, true);
|
||||
DB::alteration_message(
|
||||
"Restricting editable file field \"{$fileField->Title}\" to secure folder",
|
||||
"changed"
|
||||
);
|
||||
}
|
||||
}
|
||||
// Force this field to secure itself on write
|
||||
$fileField->write(false, false, true);
|
||||
DB::alteration_message(
|
||||
"Restricting editable file field \"{$fileField->Title}\" to secure folder",
|
||||
"changed"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Secure this field before saving
|
||||
*/
|
||||
public function onBeforeWrite() {
|
||||
$this->makeSecure();
|
||||
}
|
||||
/**
|
||||
* Secure this field before saving
|
||||
*/
|
||||
public function onBeforeWrite()
|
||||
{
|
||||
$this->makeSecure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this field is secured, but does not write changes to the database
|
||||
*/
|
||||
public function makeSecure() {
|
||||
// Skip if disabled or already secure
|
||||
if(!$this->getIsSecurityEnabled() || $this->owner->getIsSecure()) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Ensure this field is secured, but does not write changes to the database
|
||||
*/
|
||||
public function makeSecure()
|
||||
{
|
||||
// Skip if disabled or already secure
|
||||
if (!$this->getIsSecurityEnabled() || $this->owner->getIsSecure()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure folder exists
|
||||
$folder = $this->owner->Folder();
|
||||
if(!$folder || !$folder->exists()) {
|
||||
// Create new folder in default location
|
||||
$folder = Folder::find_or_make($this->owner->config()->secure_folder_name);
|
||||
$this->owner->FolderID = $folder->ID;
|
||||
// Ensure folder exists
|
||||
$folder = $this->owner->Folder();
|
||||
if (!$folder || !$folder->exists()) {
|
||||
// Create new folder in default location
|
||||
$folder = Folder::find_or_make($this->owner->config()->secure_folder_name);
|
||||
$this->owner->FolderID = $folder->ID;
|
||||
} elseif ($this->isFolderSecured($folder)) {
|
||||
// If folder exists and is secure stop
|
||||
return;
|
||||
}
|
||||
|
||||
} elseif($this->isFolderSecured($folder)) {
|
||||
// If folder exists and is secure stop
|
||||
return;
|
||||
}
|
||||
// Make secure
|
||||
$folder->CanViewType = 'OnlyTheseUsers';
|
||||
$folder->ViewerGroups()->add($this->findAdminGroup());
|
||||
$folder->write();
|
||||
}
|
||||
|
||||
// Make secure
|
||||
$folder->CanViewType = 'OnlyTheseUsers';
|
||||
$folder->ViewerGroups()->add($this->findAdminGroup());
|
||||
$folder->write();
|
||||
}
|
||||
/**
|
||||
* Find target group to record
|
||||
*
|
||||
* @return Group
|
||||
*/
|
||||
protected function findAdminGroup()
|
||||
{
|
||||
singleton('Group')->requireDefaultRecords();
|
||||
return Permission::get_groups_by_permission('ADMIN')->First();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find target group to record
|
||||
*
|
||||
* @return Group
|
||||
*/
|
||||
protected function findAdminGroup() {
|
||||
singleton('Group')->requireDefaultRecords();
|
||||
return Permission::get_groups_by_permission('ADMIN')->First();
|
||||
}
|
||||
/**
|
||||
* Determine if the field is secure
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getIsSecure()
|
||||
{
|
||||
return $this->isFolderSecured($this->owner->Folder());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the field is secure
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getIsSecure() {
|
||||
return $this->isFolderSecured($this->owner->Folder());
|
||||
}
|
||||
/**
|
||||
* Check if a Folder object is secure
|
||||
*
|
||||
* @param Folder $folder
|
||||
* @return boolean
|
||||
*/
|
||||
protected function isFolderSecured($folder)
|
||||
{
|
||||
if (! ($folder instanceof Folder) || !$folder->exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a Folder object is secure
|
||||
*
|
||||
* @param Folder $folder
|
||||
* @return boolean
|
||||
*/
|
||||
protected function isFolderSecured($folder) {
|
||||
if(! ($folder instanceof Folder) || !$folder->exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch($folder->CanViewType) {
|
||||
case 'OnlyTheseUsers':
|
||||
return true;
|
||||
case 'Inherit':
|
||||
$parent = $folder->Parent();
|
||||
return $parent && $parent->exists() && $this->isFolderSecured($parent);
|
||||
case 'Anyone':
|
||||
case 'LoggedInUsers':
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
switch ($folder->CanViewType) {
|
||||
case 'OnlyTheseUsers':
|
||||
return true;
|
||||
case 'Inherit':
|
||||
$parent = $folder->Parent();
|
||||
return $parent && $parent->exists() && $this->isFolderSecured($parent);
|
||||
case 'Anyone':
|
||||
case 'LoggedInUsers':
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,235 +3,245 @@
|
||||
/**
|
||||
* @package userforms
|
||||
*/
|
||||
class UserFormFieldEditorExtension extends DataExtension {
|
||||
class UserFormFieldEditorExtension extends DataExtension
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $has_many = array(
|
||||
'Fields' => 'EditableFormField'
|
||||
);
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $has_many = array(
|
||||
'Fields' => 'EditableFormField'
|
||||
);
|
||||
|
||||
/**
|
||||
* Adds the field editor to the page.
|
||||
*
|
||||
* @return FieldList
|
||||
*/
|
||||
public function updateCMSFields(FieldList $fields) {
|
||||
$fieldEditor = $this->getFieldEditorGrid();
|
||||
/**
|
||||
* Adds the field editor to the page.
|
||||
*
|
||||
* @return FieldList
|
||||
*/
|
||||
public function updateCMSFields(FieldList $fields)
|
||||
{
|
||||
$fieldEditor = $this->getFieldEditorGrid();
|
||||
|
||||
$fields->insertAfter(new Tab('FormFields', _t('UserFormFieldEditorExtension.FORMFIELDS', 'Form Fields')), 'Main');
|
||||
$fields->addFieldToTab('Root.FormFields', $fieldEditor);
|
||||
$fields->insertAfter(new Tab('FormFields', _t('UserFormFieldEditorExtension.FORMFIELDS', 'Form Fields')), 'Main');
|
||||
$fields->addFieldToTab('Root.FormFields', $fieldEditor);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the field editor, for adding and removing EditableFormFields.
|
||||
*
|
||||
* @return GridField
|
||||
*/
|
||||
public function getFieldEditorGrid() {
|
||||
Requirements::javascript(USERFORMS_DIR . '/javascript/FieldEditor.js');
|
||||
/**
|
||||
* Gets the field editor, for adding and removing EditableFormFields.
|
||||
*
|
||||
* @return GridField
|
||||
*/
|
||||
public function getFieldEditorGrid()
|
||||
{
|
||||
Requirements::javascript(USERFORMS_DIR . '/javascript/FieldEditor.js');
|
||||
|
||||
$fields = $this->owner->Fields();
|
||||
$fields = $this->owner->Fields();
|
||||
|
||||
$this->createInitialFormStep(true);
|
||||
$this->createInitialFormStep(true);
|
||||
|
||||
$editableColumns = new GridFieldEditableColumns();
|
||||
$fieldClasses = singleton('EditableFormField')->getEditableFieldClasses();
|
||||
$editableColumns->setDisplayFields(array(
|
||||
'ClassName' => function($record, $column, $grid) use ($fieldClasses) {
|
||||
if($record instanceof EditableFormField) {
|
||||
return $record->getInlineClassnameField($column, $fieldClasses);
|
||||
}
|
||||
},
|
||||
'Title' => function($record, $column, $grid) {
|
||||
if($record instanceof EditableFormField) {
|
||||
return $record->getInlineTitleField($column);
|
||||
}
|
||||
}
|
||||
));
|
||||
$editableColumns = new GridFieldEditableColumns();
|
||||
$fieldClasses = singleton('EditableFormField')->getEditableFieldClasses();
|
||||
$editableColumns->setDisplayFields(array(
|
||||
'ClassName' => function ($record, $column, $grid) use ($fieldClasses) {
|
||||
if ($record instanceof EditableFormField) {
|
||||
return $record->getInlineClassnameField($column, $fieldClasses);
|
||||
}
|
||||
},
|
||||
'Title' => function ($record, $column, $grid) {
|
||||
if ($record instanceof EditableFormField) {
|
||||
return $record->getInlineTitleField($column);
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
$config = GridFieldConfig::create()
|
||||
->addComponents(
|
||||
$editableColumns,
|
||||
new GridFieldButtonRow(),
|
||||
GridFieldAddClassesButton::create('EditableTextField')
|
||||
->setButtonName(_t('UserFormFieldEditorExtension.ADD_FIELD', 'Add Field'))
|
||||
->setButtonClass('ss-ui-action-constructive'),
|
||||
GridFieldAddClassesButton::create('EditableFormStep')
|
||||
->setButtonName(_t('UserFormFieldEditorExtension.ADD_PAGE_BREAK', 'Add Page Break')),
|
||||
GridFieldAddClassesButton::create(array('EditableFieldGroup', 'EditableFieldGroupEnd'))
|
||||
->setButtonName(_t('UserFormFieldEditorExtension.ADD_FIELD_GROUP', 'Add Field Group')),
|
||||
new GridFieldEditButton(),
|
||||
new GridFieldDeleteAction(),
|
||||
new GridFieldToolbarHeader(),
|
||||
new GridFieldOrderableRows('Sort'),
|
||||
new GridFieldDetailForm()
|
||||
);
|
||||
$config = GridFieldConfig::create()
|
||||
->addComponents(
|
||||
$editableColumns,
|
||||
new GridFieldButtonRow(),
|
||||
GridFieldAddClassesButton::create('EditableTextField')
|
||||
->setButtonName(_t('UserFormFieldEditorExtension.ADD_FIELD', 'Add Field'))
|
||||
->setButtonClass('ss-ui-action-constructive'),
|
||||
GridFieldAddClassesButton::create('EditableFormStep')
|
||||
->setButtonName(_t('UserFormFieldEditorExtension.ADD_PAGE_BREAK', 'Add Page Break')),
|
||||
GridFieldAddClassesButton::create(array('EditableFieldGroup', 'EditableFieldGroupEnd'))
|
||||
->setButtonName(_t('UserFormFieldEditorExtension.ADD_FIELD_GROUP', 'Add Field Group')),
|
||||
new GridFieldEditButton(),
|
||||
new GridFieldDeleteAction(),
|
||||
new GridFieldToolbarHeader(),
|
||||
new GridFieldOrderableRows('Sort'),
|
||||
new GridFieldDetailForm()
|
||||
);
|
||||
|
||||
$fieldEditor = GridField::create(
|
||||
'Fields',
|
||||
_t('UserDefinedForm.FIELDS', 'Fields'),
|
||||
$fields,
|
||||
$config
|
||||
)->addExtraClass('uf-field-editor');
|
||||
$fieldEditor = GridField::create(
|
||||
'Fields',
|
||||
_t('UserDefinedForm.FIELDS', 'Fields'),
|
||||
$fields,
|
||||
$config
|
||||
)->addExtraClass('uf-field-editor');
|
||||
|
||||
return $fieldEditor;
|
||||
}
|
||||
return $fieldEditor;
|
||||
}
|
||||
|
||||
/**
|
||||
* A UserForm must have at least one step.
|
||||
* If no steps exist, create an initial step, and put all fields inside it.
|
||||
*
|
||||
* @param bool $force
|
||||
* @return void
|
||||
*/
|
||||
public function createInitialFormStep($force = false) {
|
||||
// Only invoke once saved
|
||||
if(!$this->owner->exists()) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* A UserForm must have at least one step.
|
||||
* If no steps exist, create an initial step, and put all fields inside it.
|
||||
*
|
||||
* @param bool $force
|
||||
* @return void
|
||||
*/
|
||||
public function createInitialFormStep($force = false)
|
||||
{
|
||||
// Only invoke once saved
|
||||
if (!$this->owner->exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if first field is a step
|
||||
$fields = $this->owner->Fields();
|
||||
$firstField = $fields->first();
|
||||
if($firstField instanceof EditableFormStep) {
|
||||
return;
|
||||
}
|
||||
// Check if first field is a step
|
||||
$fields = $this->owner->Fields();
|
||||
$firstField = $fields->first();
|
||||
if ($firstField instanceof EditableFormStep) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't create steps on write if there are no formfields, as this
|
||||
// can create duplicate first steps during publish of new records
|
||||
if(!$force && !$firstField) {
|
||||
return;
|
||||
}
|
||||
// Don't create steps on write if there are no formfields, as this
|
||||
// can create duplicate first steps during publish of new records
|
||||
if (!$force && !$firstField) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Re-apply sort to each field starting at 2
|
||||
$next = 2;
|
||||
foreach($fields as $field) {
|
||||
$field->Sort = $next++;
|
||||
$field->write();
|
||||
}
|
||||
// Re-apply sort to each field starting at 2
|
||||
$next = 2;
|
||||
foreach ($fields as $field) {
|
||||
$field->Sort = $next++;
|
||||
$field->write();
|
||||
}
|
||||
|
||||
// Add step
|
||||
$step = EditableFormStep::create();
|
||||
$step->Title = _t('EditableFormStep.TITLE_FIRST', 'First Page');
|
||||
$step->Sort = 1;
|
||||
$step->write();
|
||||
$fields->add($step);
|
||||
}
|
||||
// Add step
|
||||
$step = EditableFormStep::create();
|
||||
$step->Title = _t('EditableFormStep.TITLE_FIRST', 'First Page');
|
||||
$step->Sort = 1;
|
||||
$step->write();
|
||||
$fields->add($step);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that at least one page exists at the start
|
||||
*/
|
||||
public function onAfterWrite() {
|
||||
$this->createInitialFormStep();
|
||||
}
|
||||
/**
|
||||
* Ensure that at least one page exists at the start
|
||||
*/
|
||||
public function onAfterWrite()
|
||||
{
|
||||
$this->createInitialFormStep();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see SiteTree::doPublish
|
||||
* @param Page $original
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onAfterPublish($original) {
|
||||
// Remove fields on the live table which could have been orphaned.
|
||||
$live = Versioned::get_by_stage("EditableFormField", "Live")
|
||||
->filter('ParentID', $original->ID);
|
||||
/**
|
||||
* @see SiteTree::doPublish
|
||||
* @param Page $original
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onAfterPublish($original)
|
||||
{
|
||||
// Remove fields on the live table which could have been orphaned.
|
||||
$live = Versioned::get_by_stage("EditableFormField", "Live")
|
||||
->filter('ParentID', $original->ID);
|
||||
|
||||
if($live) {
|
||||
foreach($live as $field) {
|
||||
$field->doDeleteFromStage('Live');
|
||||
}
|
||||
}
|
||||
if ($live) {
|
||||
foreach ($live as $field) {
|
||||
$field->doDeleteFromStage('Live');
|
||||
}
|
||||
}
|
||||
|
||||
foreach($this->owner->Fields() as $field) {
|
||||
$field->doPublish('Stage', 'Live');
|
||||
}
|
||||
}
|
||||
foreach ($this->owner->Fields() as $field) {
|
||||
$field->doPublish('Stage', 'Live');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see SiteTree::doUnpublish
|
||||
* @param Page $page
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onAfterUnpublish($page) {
|
||||
foreach($page->Fields() as $field) {
|
||||
$field->doDeleteFromStage('Live');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see SiteTree::doUnpublish
|
||||
* @param Page $page
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onAfterUnpublish($page)
|
||||
{
|
||||
foreach ($page->Fields() as $field) {
|
||||
$field->doDeleteFromStage('Live');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see SiteTree::duplicate
|
||||
* @param DataObject $newPage
|
||||
*
|
||||
* @return DataObject
|
||||
*/
|
||||
public function onAfterDuplicate($newPage) {
|
||||
// List of EditableFieldGroups, where the
|
||||
// key of the array is the ID of the old end group
|
||||
$fieldGroups = array();
|
||||
foreach($this->owner->Fields() as $field) {
|
||||
$newField = $field->duplicate(false);
|
||||
$newField->ParentID = $newPage->ID;
|
||||
$newField->ParentClass = $newPage->ClassName;
|
||||
$newField->Version = 0;
|
||||
$newField->write();
|
||||
/**
|
||||
* @see SiteTree::duplicate
|
||||
* @param DataObject $newPage
|
||||
*
|
||||
* @return DataObject
|
||||
*/
|
||||
public function onAfterDuplicate($newPage)
|
||||
{
|
||||
// List of EditableFieldGroups, where the
|
||||
// key of the array is the ID of the old end group
|
||||
$fieldGroups = array();
|
||||
foreach ($this->owner->Fields() as $field) {
|
||||
$newField = $field->duplicate(false);
|
||||
$newField->ParentID = $newPage->ID;
|
||||
$newField->ParentClass = $newPage->ClassName;
|
||||
$newField->Version = 0;
|
||||
$newField->write();
|
||||
|
||||
// If we encounter a group start, record it for later use
|
||||
if($field instanceof EditableFieldGroup) {
|
||||
$fieldGroups[$field->EndID] = $newField;
|
||||
}
|
||||
// If we encounter a group start, record it for later use
|
||||
if ($field instanceof EditableFieldGroup) {
|
||||
$fieldGroups[$field->EndID] = $newField;
|
||||
}
|
||||
|
||||
// If we encounter an end group, link it back to the group start
|
||||
if($field instanceof EditableFieldGroupEnd && isset($fieldGroups[$field->ID])) {
|
||||
$groupStart = $fieldGroups[$field->ID];
|
||||
$groupStart->EndID = $newField->ID;
|
||||
$groupStart->write();
|
||||
}
|
||||
// If we encounter an end group, link it back to the group start
|
||||
if ($field instanceof EditableFieldGroupEnd && isset($fieldGroups[$field->ID])) {
|
||||
$groupStart = $fieldGroups[$field->ID];
|
||||
$groupStart->EndID = $newField->ID;
|
||||
$groupStart->write();
|
||||
}
|
||||
|
||||
foreach ($field->DisplayRules() as $customRule) {
|
||||
$newRule = $customRule->duplicate(false);
|
||||
$newRule->ParentID = $newField->ID;
|
||||
$newRule->Version = 0;
|
||||
$newRule->write();
|
||||
}
|
||||
}
|
||||
foreach ($field->DisplayRules() as $customRule) {
|
||||
$newRule = $customRule->duplicate(false);
|
||||
$newRule->ParentID = $newField->ID;
|
||||
$newRule->Version = 0;
|
||||
$newRule->write();
|
||||
}
|
||||
}
|
||||
|
||||
return $newPage;
|
||||
}
|
||||
return $newPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see SiteTree::getIsModifiedOnStage
|
||||
* @param boolean $isModified
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function getIsModifiedOnStage($isModified) {
|
||||
if(!$isModified) {
|
||||
foreach($this->owner->Fields() as $field) {
|
||||
if($field->getIsModifiedOnStage()) {
|
||||
$isModified = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see SiteTree::getIsModifiedOnStage
|
||||
* @param boolean $isModified
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function getIsModifiedOnStage($isModified)
|
||||
{
|
||||
if (!$isModified) {
|
||||
foreach ($this->owner->Fields() as $field) {
|
||||
if ($field->getIsModifiedOnStage()) {
|
||||
$isModified = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $isModified;
|
||||
}
|
||||
return $isModified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see SiteTree::doRevertToLive
|
||||
* @param Page $page
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onAfterRevertToLive($page) {
|
||||
foreach($page->Fields() as $field) {
|
||||
$field->publish('Live', 'Stage', false);
|
||||
$field->writeWithoutVersion();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see SiteTree::doRevertToLive
|
||||
* @param Page $page
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onAfterRevertToLive($page)
|
||||
{
|
||||
foreach ($page->Fields() as $field) {
|
||||
$field->publish('Live', 'Stage', false);
|
||||
$field->writeWithoutVersion();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,126 +1,128 @@
|
||||
<?php
|
||||
|
||||
|
||||
class UserFormValidator extends RequiredFields {
|
||||
public function php($data) {
|
||||
if(!parent::php($data)) {
|
||||
return false;
|
||||
}
|
||||
class UserFormValidator extends RequiredFields
|
||||
{
|
||||
public function php($data)
|
||||
{
|
||||
if (!parent::php($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip unsaved records
|
||||
if(empty($data['ID']) || !is_numeric($data['ID'])) {
|
||||
return true;
|
||||
}
|
||||
// Skip unsaved records
|
||||
if (empty($data['ID']) || !is_numeric($data['ID'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$fields = EditableFormField::get()->filter('ParentID', $data['ID'])->sort('"Sort" ASC');
|
||||
$fields = EditableFormField::get()->filter('ParentID', $data['ID'])->sort('"Sort" ASC');
|
||||
|
||||
// Current nesting
|
||||
$stack = array();
|
||||
$conditionalStep = false; // Is the current step conditional?
|
||||
foreach($fields as $field) {
|
||||
if($field instanceof EditableFormStep) {
|
||||
// Page at top level, or after another page is ok
|
||||
if(empty($stack) || (count($stack) === 1 && $stack[0] instanceof EditableFormStep)) {
|
||||
$stack = array($field);
|
||||
$conditionalStep = $field->EffectiveDisplayRules()->count() > 0;
|
||||
continue;
|
||||
}
|
||||
// Current nesting
|
||||
$stack = array();
|
||||
$conditionalStep = false; // Is the current step conditional?
|
||||
foreach ($fields as $field) {
|
||||
if ($field instanceof EditableFormStep) {
|
||||
// Page at top level, or after another page is ok
|
||||
if (empty($stack) || (count($stack) === 1 && $stack[0] instanceof EditableFormStep)) {
|
||||
$stack = array($field);
|
||||
$conditionalStep = $field->EffectiveDisplayRules()->count() > 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->validationError(
|
||||
'FormFields',
|
||||
_t(
|
||||
"UserFormValidator.UNEXPECTED_BREAK",
|
||||
"Unexpected page break '{name}' inside nested field '{group}'",
|
||||
array(
|
||||
'name' => $field->CMSTitle,
|
||||
'group' => end($stack)->CMSTitle
|
||||
)
|
||||
),
|
||||
'error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$this->validationError(
|
||||
'FormFields',
|
||||
_t(
|
||||
"UserFormValidator.UNEXPECTED_BREAK",
|
||||
"Unexpected page break '{name}' inside nested field '{group}'",
|
||||
array(
|
||||
'name' => $field->CMSTitle,
|
||||
'group' => end($stack)->CMSTitle
|
||||
)
|
||||
),
|
||||
'error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate no pages
|
||||
if(empty($stack)) {
|
||||
$this->validationError(
|
||||
'FormFields',
|
||||
_t(
|
||||
"UserFormValidator.NO_PAGE",
|
||||
"Field '{name}' found before any pages",
|
||||
array(
|
||||
'name' => $field->CMSTitle
|
||||
)
|
||||
),
|
||||
'error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// Validate no pages
|
||||
if (empty($stack)) {
|
||||
$this->validationError(
|
||||
'FormFields',
|
||||
_t(
|
||||
"UserFormValidator.NO_PAGE",
|
||||
"Field '{name}' found before any pages",
|
||||
array(
|
||||
'name' => $field->CMSTitle
|
||||
)
|
||||
),
|
||||
'error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Nest field group
|
||||
if($field instanceof EditableFieldGroup) {
|
||||
$stack[] = $field;
|
||||
continue;
|
||||
}
|
||||
// Nest field group
|
||||
if ($field instanceof EditableFieldGroup) {
|
||||
$stack[] = $field;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Unnest field group
|
||||
if($field instanceof EditableFieldGroupEnd) {
|
||||
$top = end($stack);
|
||||
// Unnest field group
|
||||
if ($field instanceof EditableFieldGroupEnd) {
|
||||
$top = end($stack);
|
||||
|
||||
// Check that the top is a group at all
|
||||
if(!$top instanceof EditableFieldGroup) {
|
||||
$this->validationError(
|
||||
'FormFields',
|
||||
_t(
|
||||
"UserFormValidator.UNEXPECTED_GROUP_END",
|
||||
"'{name}' found without a matching group",
|
||||
array(
|
||||
'name' => $field->CMSTitle
|
||||
)
|
||||
),
|
||||
'error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// Check that the top is a group at all
|
||||
if (!$top instanceof EditableFieldGroup) {
|
||||
$this->validationError(
|
||||
'FormFields',
|
||||
_t(
|
||||
"UserFormValidator.UNEXPECTED_GROUP_END",
|
||||
"'{name}' found without a matching group",
|
||||
array(
|
||||
'name' => $field->CMSTitle
|
||||
)
|
||||
),
|
||||
'error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the top is the right group
|
||||
if($top->EndID != $field->ID) {
|
||||
$this->validationError(
|
||||
'FormFields',
|
||||
_t(
|
||||
"UserFormValidator.WRONG_GROUP_END",
|
||||
"'{name}' found closes the wrong group '{group}'",
|
||||
array(
|
||||
'name' => $field->CMSTitle,
|
||||
'group' => $top->CMSTitle
|
||||
)
|
||||
),
|
||||
'error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// Check that the top is the right group
|
||||
if ($top->EndID != $field->ID) {
|
||||
$this->validationError(
|
||||
'FormFields',
|
||||
_t(
|
||||
"UserFormValidator.WRONG_GROUP_END",
|
||||
"'{name}' found closes the wrong group '{group}'",
|
||||
array(
|
||||
'name' => $field->CMSTitle,
|
||||
'group' => $top->CMSTitle
|
||||
)
|
||||
),
|
||||
'error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unnest group
|
||||
array_pop($stack);
|
||||
}
|
||||
// Unnest group
|
||||
array_pop($stack);
|
||||
}
|
||||
|
||||
// Normal field type
|
||||
if($conditionalStep && $field->Required) {
|
||||
$this->validationError(
|
||||
'FormFields',
|
||||
_t(
|
||||
"UserFormValidator.CONDITIONAL_REQUIRED",
|
||||
"Required field '{name}' cannot be placed within a conditional page",
|
||||
array(
|
||||
'name' => $field->CMSTitle
|
||||
)
|
||||
),
|
||||
'error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Normal field type
|
||||
if ($conditionalStep && $field->Required) {
|
||||
$this->validationError(
|
||||
'FormFields',
|
||||
_t(
|
||||
"UserFormValidator.CONDITIONAL_REQUIRED",
|
||||
"Required field '{name}' cannot be placed within a conditional page",
|
||||
array(
|
||||
'name' => $field->CMSTitle
|
||||
)
|
||||
),
|
||||
'error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -3,63 +3,65 @@
|
||||
/**
|
||||
* @package userforms
|
||||
*/
|
||||
class UserFormsCheckboxSetField extends CheckboxSetField {
|
||||
class UserFormsCheckboxSetField extends CheckboxSetField
|
||||
{
|
||||
|
||||
/**
|
||||
* jQuery validate requires that the value of the option does not contain
|
||||
* the actual value of the input.
|
||||
*
|
||||
* @return ArrayList
|
||||
*/
|
||||
public function getOptions() {
|
||||
$options = parent::getOptions();
|
||||
/**
|
||||
* jQuery validate requires that the value of the option does not contain
|
||||
* the actual value of the input.
|
||||
*
|
||||
* @return ArrayList
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
$options = parent::getOptions();
|
||||
|
||||
foreach($options as $option) {
|
||||
$option->Name = "{$this->name}[]";
|
||||
}
|
||||
foreach ($options as $option) {
|
||||
$option->Name = "{$this->name}[]";
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSourceAsArray()
|
||||
{
|
||||
$array = parent::getSourceAsArray();
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSourceAsArray()
|
||||
{
|
||||
$array = parent::getSourceAsArray();
|
||||
|
||||
return array_values($array);
|
||||
}
|
||||
return array_values($array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function validate($validator)
|
||||
{
|
||||
// get the previous values (could contain comma-delimited list)
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function validate($validator)
|
||||
{
|
||||
// get the previous values (could contain comma-delimited list)
|
||||
|
||||
$previous = $value = $this->Value();
|
||||
$previous = $value = $this->Value();
|
||||
|
||||
if (is_string($value) && strstr($value, ",")) {
|
||||
$value = explode(",", $value);
|
||||
}
|
||||
if (is_string($value) && strstr($value, ",")) {
|
||||
$value = explode(",", $value);
|
||||
}
|
||||
|
||||
// set the value as an array for parent validation
|
||||
// set the value as an array for parent validation
|
||||
|
||||
$this->setValue($value);
|
||||
$this->setValue($value);
|
||||
|
||||
$validated = parent::validate($validator);
|
||||
$validated = parent::validate($validator);
|
||||
|
||||
// restore previous value after validation
|
||||
// restore previous value after validation
|
||||
|
||||
$this->setValue($previous);
|
||||
$this->setValue($previous);
|
||||
|
||||
return $validated;
|
||||
}
|
||||
return $validated;
|
||||
}
|
||||
}
|
||||
|
@ -3,45 +3,49 @@
|
||||
/**
|
||||
* Represents a composite field group, which may contain other groups
|
||||
*/
|
||||
abstract class UserFormsCompositeField extends CompositeField implements UserFormsFieldContainer {
|
||||
abstract class UserFormsCompositeField extends CompositeField implements UserFormsFieldContainer
|
||||
{
|
||||
|
||||
/**
|
||||
* Parent field
|
||||
*
|
||||
* @var UserFormsFieldContainer
|
||||
*/
|
||||
protected $parent = null;
|
||||
/**
|
||||
* Parent field
|
||||
*
|
||||
* @var UserFormsFieldContainer
|
||||
*/
|
||||
protected $parent = null;
|
||||
|
||||
public function getParent() {
|
||||
return $this->parent;
|
||||
}
|
||||
public function getParent()
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
public function setParent(UserFormsFieldContainer $parent) {
|
||||
$this->parent = $parent;
|
||||
return $this;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
// Skip over fields that don't generate formfields
|
||||
$formField = $field->getFormField();
|
||||
if (!$formField) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Save this field
|
||||
$this->push($formField);
|
||||
// Save this field
|
||||
$this->push($formField);
|
||||
|
||||
// Nest fields that are containers
|
||||
if($formField instanceof UserFormsFieldContainer) {
|
||||
return $formField->setParent($this);
|
||||
}
|
||||
// Nest fields that are containers
|
||||
if ($formField instanceof UserFormsFieldContainer) {
|
||||
return $formField->setParent($this);
|
||||
}
|
||||
|
||||
// Add any subsequent fields to this
|
||||
return $this;
|
||||
}
|
||||
// Add any subsequent fields to this
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -3,28 +3,29 @@
|
||||
/**
|
||||
* Represents a field container which can iteratively process nested fields, converting it into a fieldset
|
||||
*/
|
||||
interface UserFormsFieldContainer {
|
||||
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);
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* Set the parent
|
||||
*
|
||||
* @param UserFormsFieldContainer $parent
|
||||
* @return $this
|
||||
*/
|
||||
public function setParent(UserFormsFieldContainer $parent);
|
||||
|
||||
/**
|
||||
* Get the parent
|
||||
*
|
||||
* @return UserFormsFieldContainer
|
||||
*/
|
||||
public function getParent();
|
||||
/**
|
||||
* Get the parent
|
||||
*
|
||||
* @return UserFormsFieldContainer
|
||||
*/
|
||||
public function getParent();
|
||||
}
|
||||
|
@ -3,41 +3,45 @@
|
||||
/**
|
||||
* A list of formfields which allows for iterative processing of nested composite fields
|
||||
*/
|
||||
class UserFormsFieldList extends FieldList implements UserFormsFieldContainer {
|
||||
class UserFormsFieldList extends FieldList implements UserFormsFieldContainer
|
||||
{
|
||||
|
||||
public function processNext(EditableFormField $field) {
|
||||
$formField = $field->getFormField();
|
||||
if(!$formField) {
|
||||
return $this;
|
||||
}
|
||||
public function processNext(EditableFormField $field)
|
||||
{
|
||||
$formField = $field->getFormField();
|
||||
if (!$formField) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->push($formField);
|
||||
$this->push($formField);
|
||||
|
||||
if($formField instanceof UserFormsFieldContainer) {
|
||||
return $formField->setParent($this);
|
||||
}
|
||||
if ($formField instanceof UserFormsFieldContainer) {
|
||||
return $formField->setParent($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getParent() {
|
||||
// Field list does not have a parent
|
||||
return null;
|
||||
}
|
||||
public function getParent()
|
||||
{
|
||||
// Field list does not have a parent
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setParent(UserFormsFieldContainer $parent) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all empty steps
|
||||
*/
|
||||
public function clearEmptySteps() {
|
||||
foreach($this as $field) {
|
||||
if($field instanceof UserFormsStepField && count($field->getChildren()) === 0) {
|
||||
$this->remove($field);
|
||||
}
|
||||
}
|
||||
}
|
||||
public function setParent(UserFormsFieldContainer $parent)
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all empty steps
|
||||
*/
|
||||
public function clearEmptySteps()
|
||||
{
|
||||
foreach ($this as $field) {
|
||||
if ($field instanceof UserFormsStepField && count($field->getChildren()) === 0) {
|
||||
$this->remove($field);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,25 +3,29 @@
|
||||
/**
|
||||
* Front end composite field for userforms
|
||||
*/
|
||||
class UserFormsGroupField extends UserFormsCompositeField {
|
||||
class UserFormsGroupField extends UserFormsCompositeField
|
||||
{
|
||||
|
||||
public function __construct($children = null) {
|
||||
parent::__construct($children);
|
||||
$this->setTag('fieldset');
|
||||
}
|
||||
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 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();
|
||||
}
|
||||
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);
|
||||
}
|
||||
// Otherwise behave as per normal composite field
|
||||
return parent::processNext($field);
|
||||
}
|
||||
}
|
||||
|
@ -3,42 +3,46 @@
|
||||
/**
|
||||
* Represents a page step in a form, which may contain form fields or other groups
|
||||
*/
|
||||
class UserFormsStepField extends UserFormsCompositeField {
|
||||
class UserFormsStepField extends UserFormsCompositeField
|
||||
{
|
||||
|
||||
private static $casting = array(
|
||||
'StepNumber' => 'Int'
|
||||
);
|
||||
private static $casting = array(
|
||||
'StepNumber' => 'Int'
|
||||
);
|
||||
|
||||
/**
|
||||
* Numeric index (1 based) of this step
|
||||
*
|
||||
* Null if unassigned
|
||||
*
|
||||
* @var int|null
|
||||
*/
|
||||
protected $number = null;
|
||||
/**
|
||||
* Numeric index (1 based) of this step
|
||||
*
|
||||
* Null if unassigned
|
||||
*
|
||||
* @var int|null
|
||||
*/
|
||||
protected $number = null;
|
||||
|
||||
public function FieldHolder($properties = array()) {
|
||||
return $this->Field($properties);
|
||||
}
|
||||
public function FieldHolder($properties = array())
|
||||
{
|
||||
return $this->Field($properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the step number
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getStepNumber() {
|
||||
return $this->number;
|
||||
}
|
||||
/**
|
||||
* Get the step number
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getStepNumber()
|
||||
{
|
||||
return $this->number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-assign this step to another number
|
||||
*
|
||||
* @param type $number
|
||||
* @return $this
|
||||
*/
|
||||
public function setStepNumber($number) {
|
||||
$this->number = $number;
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Re-assign this step to another number
|
||||
*
|
||||
* @param type $number
|
||||
* @return $this
|
||||
*/
|
||||
public function setStepNumber($number)
|
||||
{
|
||||
$this->number = $number;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,13 @@
|
||||
* @deprecated since version 4.0
|
||||
* @package userforms
|
||||
*/
|
||||
class UserformsTreeDropdownField extends TreeDropdownField {
|
||||
class UserformsTreeDropdownField extends TreeDropdownField
|
||||
{
|
||||
|
||||
public function __construct($name, $title = null, $sourceObject = 'Group', $keyField = 'ID', $labelField = 'TreeTitle', $showSearch = true) {
|
||||
parent::__construct($name, $title, $sourceObject, $keyField, $labelField, $showSearch);
|
||||
public function __construct($name, $title = null, $sourceObject = 'Group', $keyField = 'ID', $labelField = 'TreeTitle', $showSearch = true)
|
||||
{
|
||||
parent::__construct($name, $title, $sourceObject, $keyField, $labelField, $showSearch);
|
||||
|
||||
Deprecation::notice('4.0', __CLASS__ . " is deprecated");
|
||||
}
|
||||
Deprecation::notice('4.0', __CLASS__ . " is deprecated");
|
||||
}
|
||||
}
|
@ -3,230 +3,246 @@
|
||||
/**
|
||||
* A button which allows objects to be created with a specified classname(s)
|
||||
*/
|
||||
class GridFieldAddClassesButton extends Object implements GridField_HTMLProvider, GridField_ActionProvider {
|
||||
class GridFieldAddClassesButton extends Object implements GridField_HTMLProvider, GridField_ActionProvider
|
||||
{
|
||||
|
||||
/**
|
||||
* Name of fragment to insert into
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $targetFragment;
|
||||
/**
|
||||
* Name of fragment to insert into
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $targetFragment;
|
||||
|
||||
/**
|
||||
* Button title
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $buttonName;
|
||||
/**
|
||||
* Button title
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $buttonName;
|
||||
|
||||
/**
|
||||
* Additonal CSS classes for the button
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $buttonClass = null;
|
||||
/**
|
||||
* Additonal CSS classes for the button
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $buttonClass = null;
|
||||
|
||||
/**
|
||||
* Class names
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $modelClasses = null;
|
||||
/**
|
||||
* Class names
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $modelClasses = null;
|
||||
|
||||
/**
|
||||
* @param array $classes Class or list of classes to create.
|
||||
* If you enter more than one class, each click of the "add" button will create one of each
|
||||
* @param string $targetFragment The fragment to render the button into
|
||||
*/
|
||||
public function __construct($classes, $targetFragment = 'buttons-before-left') {
|
||||
parent::__construct();
|
||||
$this->setClasses($classes);
|
||||
$this->setFragment($targetFragment);
|
||||
}
|
||||
/**
|
||||
* @param array $classes Class or list of classes to create.
|
||||
* If you enter more than one class, each click of the "add" button will create one of each
|
||||
* @param string $targetFragment The fragment to render the button into
|
||||
*/
|
||||
public function __construct($classes, $targetFragment = 'buttons-before-left')
|
||||
{
|
||||
parent::__construct();
|
||||
$this->setClasses($classes);
|
||||
$this->setFragment($targetFragment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the button name
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function setButtonName($name) {
|
||||
$this->buttonName = $name;
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Change the button name
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function setButtonName($name)
|
||||
{
|
||||
$this->buttonName = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the button name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getButtonName() {
|
||||
return $this->buttonName;
|
||||
}
|
||||
/**
|
||||
* Get the button name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getButtonName()
|
||||
{
|
||||
return $this->buttonName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fragment name this button is rendered into.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFragment() {
|
||||
return $this->targetFragment;
|
||||
}
|
||||
/**
|
||||
* Gets the fragment name this button is rendered into.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFragment()
|
||||
{
|
||||
return $this->targetFragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fragment name this button is rendered into.
|
||||
*
|
||||
* @param string $fragment
|
||||
* @return GridFieldAddNewInlineButton $this
|
||||
*/
|
||||
public function setFragment($fragment) {
|
||||
$this->targetFragment = $fragment;
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Sets the fragment name this button is rendered into.
|
||||
*
|
||||
* @param string $fragment
|
||||
* @return GridFieldAddNewInlineButton $this
|
||||
*/
|
||||
public function setFragment($fragment)
|
||||
{
|
||||
$this->targetFragment = $fragment;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extra button class
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getButtonClass() {
|
||||
return $this->buttonClass;
|
||||
}
|
||||
/**
|
||||
* Get extra button class
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getButtonClass()
|
||||
{
|
||||
return $this->buttonClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets extra CSS classes for this button
|
||||
*
|
||||
* @param string $buttonClass
|
||||
* @return $this
|
||||
*/
|
||||
public function setButtonClass($buttonClass) {
|
||||
$this->buttonClass = $buttonClass;
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Sets extra CSS classes for this button
|
||||
*
|
||||
* @param string $buttonClass
|
||||
* @return $this
|
||||
*/
|
||||
public function setButtonClass($buttonClass)
|
||||
{
|
||||
$this->buttonClass = $buttonClass;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the classes of the objects to create
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getClasses() {
|
||||
return $this->modelClasses;
|
||||
}
|
||||
/**
|
||||
* Get the classes of the objects to create
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getClasses()
|
||||
{
|
||||
return $this->modelClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of classes which can be created, with checks for permissions.
|
||||
* Will fallback to the default model class for the given DataGrid
|
||||
*
|
||||
* @param DataGrid $grid
|
||||
* @return array
|
||||
*/
|
||||
public function getClassesCreate($grid) {
|
||||
// Get explicit or fallback class list
|
||||
$classes = $this->getClasses();
|
||||
if(empty($classes) && $grid) {
|
||||
$classes = array($grid->getModelClass());
|
||||
}
|
||||
/**
|
||||
* Gets the list of classes which can be created, with checks for permissions.
|
||||
* Will fallback to the default model class for the given DataGrid
|
||||
*
|
||||
* @param DataGrid $grid
|
||||
* @return array
|
||||
*/
|
||||
public function getClassesCreate($grid)
|
||||
{
|
||||
// Get explicit or fallback class list
|
||||
$classes = $this->getClasses();
|
||||
if (empty($classes) && $grid) {
|
||||
$classes = array($grid->getModelClass());
|
||||
}
|
||||
|
||||
// Filter out classes without permission
|
||||
return array_filter($classes, function($class) {
|
||||
return singleton($class)->canCreate();
|
||||
});
|
||||
}
|
||||
// Filter out classes without permission
|
||||
return array_filter($classes, function ($class) {
|
||||
return singleton($class)->canCreate();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the classes to create
|
||||
*
|
||||
* @param array $classes
|
||||
*/
|
||||
public function setClasses($classes) {
|
||||
if(!is_array($classes)) {
|
||||
$classes = $classes ? array($classes) : array();
|
||||
}
|
||||
$this->modelClasses = $classes;
|
||||
}
|
||||
/**
|
||||
* Specify the classes to create
|
||||
*
|
||||
* @param array $classes
|
||||
*/
|
||||
public function setClasses($classes)
|
||||
{
|
||||
if (!is_array($classes)) {
|
||||
$classes = $classes ? array($classes) : array();
|
||||
}
|
||||
$this->modelClasses = $classes;
|
||||
}
|
||||
|
||||
public function getHTMLFragments($grid) {
|
||||
// Check create permission
|
||||
$singleton = singleton($grid->getModelClass());
|
||||
if(!$singleton->canCreate()) {
|
||||
return array();
|
||||
}
|
||||
public function getHTMLFragments($grid)
|
||||
{
|
||||
// Check create permission
|
||||
$singleton = singleton($grid->getModelClass());
|
||||
if (!$singleton->canCreate()) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// Get button name
|
||||
$buttonName = $this->getButtonName();
|
||||
if(!$buttonName) {
|
||||
// provide a default button name, can be changed by calling {@link setButtonName()} on this component
|
||||
$objectName = $singleton->i18n_singular_name();
|
||||
$buttonName = _t('GridField.Add', 'Add {name}', array('name' => $objectName));
|
||||
}
|
||||
// Get button name
|
||||
$buttonName = $this->getButtonName();
|
||||
if (!$buttonName) {
|
||||
// provide a default button name, can be changed by calling {@link setButtonName()} on this component
|
||||
$objectName = $singleton->i18n_singular_name();
|
||||
$buttonName = _t('GridField.Add', 'Add {name}', array('name' => $objectName));
|
||||
}
|
||||
|
||||
$addAction = new GridField_FormAction(
|
||||
$grid,
|
||||
$this->getAction(),
|
||||
$buttonName,
|
||||
$this->getAction(),
|
||||
array()
|
||||
);
|
||||
$addAction->setAttribute('data-icon', 'add');
|
||||
$addAction = new GridField_FormAction(
|
||||
$grid,
|
||||
$this->getAction(),
|
||||
$buttonName,
|
||||
$this->getAction(),
|
||||
array()
|
||||
);
|
||||
$addAction->setAttribute('data-icon', 'add');
|
||||
|
||||
if($this->getButtonClass()) {
|
||||
$addAction->addExtraClass($this->getButtonClass());
|
||||
}
|
||||
if ($this->getButtonClass()) {
|
||||
$addAction->addExtraClass($this->getButtonClass());
|
||||
}
|
||||
|
||||
return array(
|
||||
$this->targetFragment => $addAction->forTemplate()
|
||||
);
|
||||
}
|
||||
return array(
|
||||
$this->targetFragment => $addAction->forTemplate()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getActions($gridField) {
|
||||
return array(
|
||||
$this->getAction()
|
||||
);
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getActions($gridField)
|
||||
{
|
||||
return array(
|
||||
$this->getAction()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the action suburl for this component
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getAction() {
|
||||
return 'add-classes-' . strtolower(implode('-', $this->getClasses()));
|
||||
}
|
||||
/**
|
||||
* Get the action suburl for this component
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getAction()
|
||||
{
|
||||
return 'add-classes-' . strtolower(implode('-', $this->getClasses()));
|
||||
}
|
||||
|
||||
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
|
||||
switch(strtolower($actionName)) {
|
||||
case $this->getAction():
|
||||
return $this->handleAdd($gridField);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public function handleAction(GridField $gridField, $actionName, $arguments, $data)
|
||||
{
|
||||
switch (strtolower($actionName)) {
|
||||
case $this->getAction():
|
||||
return $this->handleAdd($gridField);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles adding a new instance of a selected class.
|
||||
*
|
||||
* @param GridField $grid
|
||||
* @return null
|
||||
*/
|
||||
public function handleAdd($grid) {
|
||||
$classes = $this->getClassesCreate($grid);
|
||||
if(empty($classes)) {
|
||||
throw new SS_HTTPResponse_Exception(400);
|
||||
}
|
||||
/**
|
||||
* Handles adding a new instance of a selected class.
|
||||
*
|
||||
* @param GridField $grid
|
||||
* @return null
|
||||
*/
|
||||
public function handleAdd($grid)
|
||||
{
|
||||
$classes = $this->getClassesCreate($grid);
|
||||
if (empty($classes)) {
|
||||
throw new SS_HTTPResponse_Exception(400);
|
||||
}
|
||||
|
||||
// Add item to gridfield
|
||||
$list = $grid->getList();
|
||||
foreach($classes as $class) {
|
||||
$item = $class::create();
|
||||
$item->write();
|
||||
$list->add($item);
|
||||
}
|
||||
// Add item to gridfield
|
||||
$list = $grid->getList();
|
||||
foreach ($classes as $class) {
|
||||
$item = $class::create();
|
||||
$item->write();
|
||||
$list->add($item);
|
||||
}
|
||||
|
||||
// Should trigger a simple reload
|
||||
return null;
|
||||
}
|
||||
// Should trigger a simple reload
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -3,167 +3,175 @@
|
||||
/**
|
||||
* @package userforms
|
||||
*/
|
||||
class UserForm extends Form {
|
||||
class UserForm extends Form
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Controller $controller
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct(Controller $controller, $name = 'Form') {
|
||||
/**
|
||||
* @param Controller $controller
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct(Controller $controller, $name = 'Form')
|
||||
{
|
||||
$this->controller = $controller;
|
||||
$this->setRedirectToFormOnValidationError(true);
|
||||
|
||||
$this->controller = $controller;
|
||||
$this->setRedirectToFormOnValidationError(true);
|
||||
parent::__construct(
|
||||
$controller,
|
||||
$name,
|
||||
new FieldList(),
|
||||
new FieldList()
|
||||
);
|
||||
|
||||
parent::__construct(
|
||||
$controller,
|
||||
$name,
|
||||
new FieldList(),
|
||||
new FieldList()
|
||||
);
|
||||
$this->setFields($fields = $this->getFormFields());
|
||||
$fields->setForm($this);
|
||||
$this->setActions($actions = $this->getFormActions());
|
||||
$actions->setForm($this);
|
||||
$this->setValidator($this->getRequiredFields());
|
||||
|
||||
$this->setFields($fields = $this->getFormFields());
|
||||
$fields->setForm($this);
|
||||
$this->setActions($actions = $this->getFormActions());
|
||||
$actions->setForm($this);
|
||||
$this->setValidator($this->getRequiredFields());
|
||||
// This needs to be re-evaluated since fields have been assigned
|
||||
$this->setupFormErrors();
|
||||
|
||||
// This needs to be re-evaluated since fields have been assigned
|
||||
$this->setupFormErrors();
|
||||
// Number each page
|
||||
$stepNumber = 1;
|
||||
foreach ($this->getSteps() as $step) {
|
||||
$step->setStepNumber($stepNumber++);
|
||||
}
|
||||
|
||||
// Number each page
|
||||
$stepNumber = 1;
|
||||
foreach($this->getSteps() as $step) {
|
||||
$step->setStepNumber($stepNumber++);
|
||||
}
|
||||
if ($controller->DisableCsrfSecurityToken) {
|
||||
$this->disableSecurityToken();
|
||||
}
|
||||
|
||||
if($controller->DisableCsrfSecurityToken) {
|
||||
$this->disableSecurityToken();
|
||||
}
|
||||
$data = Session::get("FormInfo.{$this->FormName()}.data");
|
||||
|
||||
$data = Session::get("FormInfo.{$this->FormName()}.data");
|
||||
if (is_array($data)) {
|
||||
$this->loadDataFrom($data);
|
||||
}
|
||||
|
||||
if(is_array($data)) {
|
||||
$this->loadDataFrom($data);
|
||||
}
|
||||
$this->extend('updateForm');
|
||||
}
|
||||
|
||||
$this->extend('updateForm');
|
||||
}
|
||||
public function setupFormErrors()
|
||||
{
|
||||
// Suppress setupFormErrors if fields haven't been bootstrapped
|
||||
if ($this->fields && $this->fields->exists()) {
|
||||
return parent::setupFormErrors();
|
||||
}
|
||||
|
||||
public function setupFormErrors()
|
||||
{
|
||||
// Suppress setupFormErrors if fields haven't been bootstrapped
|
||||
if($this->fields && $this->fields->exists()) {
|
||||
return parent::setupFormErrors();
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Used for partial caching in the template.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLastEdited()
|
||||
{
|
||||
return $this->controller->LastEdited;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for partial caching in the template.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLastEdited() {
|
||||
return $this->controller->LastEdited;
|
||||
}
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getDisplayErrorMessagesAtTop()
|
||||
{
|
||||
return (bool)$this->controller->DisplayErrorMessagesAtTop;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getDisplayErrorMessagesAtTop() {
|
||||
return (bool)$this->controller->DisplayErrorMessagesAtTop;
|
||||
}
|
||||
/**
|
||||
* Return the fieldlist, filtered to only contain steps
|
||||
*
|
||||
* @return ArrayList
|
||||
*/
|
||||
public function getSteps()
|
||||
{
|
||||
return $this->Fields()->filterByCallback(function ($field) {
|
||||
return $field instanceof UserFormsStepField;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the fieldlist, filtered to only contain steps
|
||||
*
|
||||
* @return ArrayList
|
||||
*/
|
||||
public function getSteps() {
|
||||
return $this->Fields()->filterByCallback(function($field) {
|
||||
return $field instanceof UserFormsStepField;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Get the form fields for the form on this page. Can modify this FieldSet
|
||||
* by using {@link updateFormFields()} on an {@link Extension} subclass which
|
||||
* is applied to this controller.
|
||||
*
|
||||
* This will be a list of top level composite steps
|
||||
*
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getFormFields()
|
||||
{
|
||||
$fields = new UserFormsFieldList();
|
||||
$target = $fields;
|
||||
foreach ($this->controller->Fields() as $field) {
|
||||
$target = $target->processNext($field);
|
||||
}
|
||||
$fields->clearEmptySteps();
|
||||
$this->extend('updateFormFields', $fields);
|
||||
$fields->setForm($this);
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the form fields for the form on this page. Can modify this FieldSet
|
||||
* by using {@link updateFormFields()} on an {@link Extension} subclass which
|
||||
* is applied to this controller.
|
||||
*
|
||||
* This will be a list of top level composite steps
|
||||
*
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getFormFields() {
|
||||
$fields = new UserFormsFieldList();
|
||||
$target = $fields;
|
||||
foreach ($this->controller->Fields() as $field) {
|
||||
$target = $target->processNext($field);
|
||||
}
|
||||
$fields->clearEmptySteps();
|
||||
$this->extend('updateFormFields', $fields);
|
||||
$fields->setForm($this);
|
||||
return $fields;
|
||||
}
|
||||
/**
|
||||
* Generate the form actions for the UserDefinedForm. You
|
||||
* can manipulate these by using {@link updateFormActions()} on
|
||||
* a decorator.
|
||||
*
|
||||
* @todo Make form actions editable via their own field editor.
|
||||
*
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getFormActions()
|
||||
{
|
||||
$submitText = ($this->controller->SubmitButtonText) ? $this->controller->SubmitButtonText : _t('UserDefinedForm.SUBMITBUTTON', 'Submit');
|
||||
$clearText = ($this->controller->ClearButtonText) ? $this->controller->ClearButtonText : _t('UserDefinedForm.CLEARBUTTON', 'Clear');
|
||||
|
||||
/**
|
||||
* Generate the form actions for the UserDefinedForm. You
|
||||
* can manipulate these by using {@link updateFormActions()} on
|
||||
* a decorator.
|
||||
*
|
||||
* @todo Make form actions editable via their own field editor.
|
||||
*
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getFormActions() {
|
||||
$submitText = ($this->controller->SubmitButtonText) ? $this->controller->SubmitButtonText : _t('UserDefinedForm.SUBMITBUTTON', 'Submit');
|
||||
$clearText = ($this->controller->ClearButtonText) ? $this->controller->ClearButtonText : _t('UserDefinedForm.CLEARBUTTON', 'Clear');
|
||||
$actions = new FieldList(
|
||||
new FormAction("process", $submitText)
|
||||
);
|
||||
|
||||
$actions = new FieldList(
|
||||
new FormAction("process", $submitText)
|
||||
);
|
||||
if ($this->controller->ShowClearButton) {
|
||||
$actions->push(new ResetFormAction("clearForm", $clearText));
|
||||
}
|
||||
|
||||
if($this->controller->ShowClearButton) {
|
||||
$actions->push(new ResetFormAction("clearForm", $clearText));
|
||||
}
|
||||
$this->extend('updateFormActions', $actions);
|
||||
$actions->setForm($this);
|
||||
return $actions;
|
||||
}
|
||||
|
||||
$this->extend('updateFormActions', $actions);
|
||||
$actions->setForm($this);
|
||||
return $actions;
|
||||
}
|
||||
/**
|
||||
* Get the required form fields for this form.
|
||||
*
|
||||
* @return RequiredFields
|
||||
*/
|
||||
public function getRequiredFields()
|
||||
{
|
||||
// Generate required field validator
|
||||
$requiredNames = $this
|
||||
->getController()
|
||||
->Fields()
|
||||
->filter('Required', true)
|
||||
->column('Name');
|
||||
$required = new RequiredFields($requiredNames);
|
||||
$this->extend('updateRequiredFields', $required);
|
||||
$required->setForm($this);
|
||||
return $required;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required form fields for this form.
|
||||
*
|
||||
* @return RequiredFields
|
||||
*/
|
||||
public function getRequiredFields() {
|
||||
// Generate required field validator
|
||||
$requiredNames = $this
|
||||
->getController()
|
||||
->Fields()
|
||||
->filter('Required', true)
|
||||
->column('Name');
|
||||
$required = new RequiredFields($requiredNames);
|
||||
$this->extend('updateRequiredFields', $required);
|
||||
$required->setForm($this);
|
||||
return $required;
|
||||
}
|
||||
/**
|
||||
* Override some we can add UserForm specific attributes to the form.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAttributes()
|
||||
{
|
||||
$attrs = parent::getAttributes();
|
||||
|
||||
/**
|
||||
* Override some we can add UserForm specific attributes to the form.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAttributes() {
|
||||
$attrs = parent::getAttributes();
|
||||
$attrs['class'] = $attrs['class'] . ' userform';
|
||||
$attrs['data-livevalidation'] = (bool)$this->controller->EnableLiveValidation;
|
||||
$attrs['data-toperrors'] = (bool)$this->controller->DisplayErrorMessagesAtTop;
|
||||
$attrs['data-hidefieldlabels'] = (bool)$this->controller->HideFieldLabels;
|
||||
|
||||
$attrs['class'] = $attrs['class'] . ' userform';
|
||||
$attrs['data-livevalidation'] = (bool)$this->controller->EnableLiveValidation;
|
||||
$attrs['data-toperrors'] = (bool)$this->controller->DisplayErrorMessagesAtTop;
|
||||
$attrs['data-hidefieldlabels'] = (bool)$this->controller->HideFieldLabels;
|
||||
|
||||
return $attrs;
|
||||
}
|
||||
return $attrs;
|
||||
}
|
||||
}
|
||||
|
@ -7,100 +7,107 @@
|
||||
* @method EditableFormField Parent()
|
||||
* @package userforms
|
||||
*/
|
||||
class EditableCustomRule extends DataObject {
|
||||
class EditableCustomRule extends DataObject
|
||||
{
|
||||
|
||||
private static $condition_options = array(
|
||||
"IsBlank" => "Is blank",
|
||||
"IsNotBlank" => "Is not blank",
|
||||
"HasValue" => "Equals",
|
||||
"ValueNot" => "Doesn't equal",
|
||||
"ValueLessThan" => "Less than",
|
||||
"ValueLessThanEqual" => "Less than or equal",
|
||||
"ValueGreaterThan" => "Greater than",
|
||||
"ValueGreaterThanEqual" => "Greater than or equal"
|
||||
);
|
||||
private static $condition_options = array(
|
||||
"IsBlank" => "Is blank",
|
||||
"IsNotBlank" => "Is not blank",
|
||||
"HasValue" => "Equals",
|
||||
"ValueNot" => "Doesn't equal",
|
||||
"ValueLessThan" => "Less than",
|
||||
"ValueLessThanEqual" => "Less than or equal",
|
||||
"ValueGreaterThan" => "Greater than",
|
||||
"ValueGreaterThanEqual" => "Greater than or equal"
|
||||
);
|
||||
|
||||
private static $db = array(
|
||||
'Display' => 'Enum("Show,Hide")',
|
||||
'ConditionOption' => 'Enum("IsBlank,IsNotBlank,HasValue,ValueNot,ValueLessThan,ValueLessThanEqual,ValueGreaterThan,ValueGreaterThanEqual")',
|
||||
'FieldValue' => 'Varchar(255)'
|
||||
);
|
||||
private static $db = array(
|
||||
'Display' => 'Enum("Show,Hide")',
|
||||
'ConditionOption' => 'Enum("IsBlank,IsNotBlank,HasValue,ValueNot,ValueLessThan,ValueLessThanEqual,ValueGreaterThan,ValueGreaterThanEqual")',
|
||||
'FieldValue' => 'Varchar(255)'
|
||||
);
|
||||
|
||||
private static $has_one = array(
|
||||
'Parent' => 'EditableFormField',
|
||||
'ConditionField' => 'EditableFormField'
|
||||
);
|
||||
private static $has_one = array(
|
||||
'Parent' => 'EditableFormField',
|
||||
'ConditionField' => 'EditableFormField'
|
||||
);
|
||||
|
||||
/**
|
||||
* Built in extensions required
|
||||
*
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $extensions = array(
|
||||
"Versioned('Stage', 'Live')"
|
||||
);
|
||||
/**
|
||||
* Built in extensions required
|
||||
*
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $extensions = array(
|
||||
"Versioned('Stage', 'Live')"
|
||||
);
|
||||
|
||||
/**
|
||||
* Publish this custom rule to the live site
|
||||
*
|
||||
* Wrapper for the {@link Versioned} publish function
|
||||
*/
|
||||
public function doPublish($fromStage, $toStage, $createNewVersion = false) {
|
||||
$this->publish($fromStage, $toStage, $createNewVersion);
|
||||
}
|
||||
/**
|
||||
* Publish this custom rule to the live site
|
||||
*
|
||||
* Wrapper for the {@link Versioned} publish function
|
||||
*/
|
||||
public function doPublish($fromStage, $toStage, $createNewVersion = false)
|
||||
{
|
||||
$this->publish($fromStage, $toStage, $createNewVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete this custom rule from a given stage
|
||||
*
|
||||
* Wrapper for the {@link Versioned} deleteFromStage function
|
||||
*/
|
||||
public function doDeleteFromStage($stage) {
|
||||
$this->deleteFromStage($stage);
|
||||
}
|
||||
/**
|
||||
* Delete this custom rule from a given stage
|
||||
*
|
||||
* Wrapper for the {@link Versioned} deleteFromStage function
|
||||
*/
|
||||
public function doDeleteFromStage($stage)
|
||||
{
|
||||
$this->deleteFromStage($stage);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Member $member
|
||||
* @return bool
|
||||
*/
|
||||
public function canDelete($member = null) {
|
||||
return $this->canEdit($member);
|
||||
}
|
||||
public function canDelete($member = null)
|
||||
{
|
||||
return $this->canEdit($member);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member $member
|
||||
* @return bool
|
||||
*/
|
||||
public function canEdit($member = null) {
|
||||
public function canEdit($member = null)
|
||||
{
|
||||
return $this->Parent()->canEdit($member);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member $member
|
||||
* @return bool
|
||||
*/
|
||||
public function canView($member = null) {
|
||||
return $this->Parent()->canView($member);
|
||||
}
|
||||
public function canView($member = null)
|
||||
{
|
||||
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 array $context Virtual parameter to allow context to be passed in to check
|
||||
* @return bool
|
||||
*/
|
||||
public function canCreate($member = null) {
|
||||
// Check parent page
|
||||
* @return bool
|
||||
*/
|
||||
public function canCreate($member = null)
|
||||
{
|
||||
// Check parent page
|
||||
$parent = $this->getCanCreateContext(func_get_args());
|
||||
if($parent) {
|
||||
if ($parent) {
|
||||
return $parent->canEdit($member);
|
||||
}
|
||||
|
||||
// Fall back to secure admin permissions
|
||||
return parent::canCreate($member);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to check the parent for this object
|
||||
@ -108,13 +115,14 @@ class EditableCustomRule extends DataObject {
|
||||
* @param array $args List of arguments passed to canCreate
|
||||
* @return DataObject Some parent dataobject to inherit permissions from
|
||||
*/
|
||||
protected function getCanCreateContext($args) {
|
||||
protected function getCanCreateContext($args)
|
||||
{
|
||||
// Inspect second parameter to canCreate for a 'Parent' context
|
||||
if(isset($args[1]['Parent'])) {
|
||||
if (isset($args[1]['Parent'])) {
|
||||
return $args[1]['Parent'];
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
|
||||
@ -126,7 +134,8 @@ class EditableCustomRule extends DataObject {
|
||||
* @param Member $member
|
||||
* @return bool
|
||||
*/
|
||||
public function canPublish($member = null) {
|
||||
public function canPublish($member = null)
|
||||
{
|
||||
return $this->canEdit($member);
|
||||
}
|
||||
|
||||
@ -134,7 +143,8 @@ class EditableCustomRule extends DataObject {
|
||||
* @param Member $member
|
||||
* @return bool
|
||||
*/
|
||||
public function canUnpublish($member = null) {
|
||||
public function canUnpublish($member = null)
|
||||
{
|
||||
return $this->canDelete($member);
|
||||
}
|
||||
}
|
||||
|
@ -4,178 +4,180 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class UserDefinedForm extends Page {
|
||||
class UserDefinedForm extends Page
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private static $icon = 'userforms/images/sitetree_icon.png';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private static $icon = 'userforms/images/sitetree_icon.png';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private static $description = 'Adds a customizable form.';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private static $description = 'Adds a customizable form.';
|
||||
|
||||
/**
|
||||
* @var string Required Identifier
|
||||
*/
|
||||
private static $required_identifier = null;
|
||||
/**
|
||||
* @var string Required Identifier
|
||||
*/
|
||||
private static $required_identifier = null;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private static $email_template_directory = 'userforms/templates/email/';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private static $email_template_directory = 'userforms/templates/email/';
|
||||
|
||||
/**
|
||||
* Should this module automatically upgrade on dev/build?
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $upgrade_on_build = true;
|
||||
|
||||
/**
|
||||
* Built in extensions required by this page
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $extensions = array(
|
||||
'UserFormFieldEditorExtension'
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array Fields on the user defined form page.
|
||||
*/
|
||||
private static $db = array(
|
||||
"SubmitButtonText" => "Varchar",
|
||||
"ClearButtonText" => "Varchar",
|
||||
"OnCompleteMessage" => "HTMLText",
|
||||
"ShowClearButton" => "Boolean",
|
||||
'DisableSaveSubmissions' => 'Boolean',
|
||||
'EnableLiveValidation' => 'Boolean',
|
||||
'HideFieldLabels' => 'Boolean',
|
||||
'DisplayErrorMessagesAtTop' => 'Boolean',
|
||||
'DisableAuthenicatedFinishAction' => 'Boolean',
|
||||
'DisableCsrfSecurityToken' => 'Boolean'
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array Default values of variables when this page is created
|
||||
*/
|
||||
private static $defaults = array(
|
||||
'Content' => '$UserDefinedForm',
|
||||
'DisableSaveSubmissions' => 0,
|
||||
'OnCompleteMessage' => '<p>Thanks, we\'ve received your submission.</p>'
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $has_many = array(
|
||||
"Submissions" => "SubmittedForm",
|
||||
"EmailRecipients" => "UserDefinedForm_EmailRecipient"
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @config
|
||||
*/
|
||||
private static $casting = array(
|
||||
'ErrorContainerID' => 'Text'
|
||||
);
|
||||
|
||||
/**
|
||||
* Error container selector which matches the element for grouped messages
|
||||
*
|
||||
* @var string
|
||||
* @config
|
||||
*/
|
||||
private static $error_container_id = 'error-container';
|
||||
|
||||
/**
|
||||
* The configuration used to determine whether a confirmation message is to
|
||||
* appear when navigating away from a partially completed form.
|
||||
*
|
||||
* @var boolean
|
||||
* @config
|
||||
*/
|
||||
private static $enable_are_you_sure = true;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
/**
|
||||
* Should this module automatically upgrade on dev/build?
|
||||
*
|
||||
* @config
|
||||
*/
|
||||
private static $recipients_warning_enabled = false;
|
||||
* @var bool
|
||||
*/
|
||||
private static $upgrade_on_build = true;
|
||||
|
||||
/**
|
||||
* Temporary storage of field ids when the form is duplicated.
|
||||
* Example layout: array('EditableCheckbox3' => 'EditableCheckbox14')
|
||||
* @var array
|
||||
*/
|
||||
protected $fieldsFromTo = array();
|
||||
/**
|
||||
* Built in extensions required by this page
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $extensions = array(
|
||||
'UserFormFieldEditorExtension'
|
||||
);
|
||||
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields() {
|
||||
Requirements::css(USERFORMS_DIR . '/css/UserForm_cms.css');
|
||||
/**
|
||||
* @var array Fields on the user defined form page.
|
||||
*/
|
||||
private static $db = array(
|
||||
"SubmitButtonText" => "Varchar",
|
||||
"ClearButtonText" => "Varchar",
|
||||
"OnCompleteMessage" => "HTMLText",
|
||||
"ShowClearButton" => "Boolean",
|
||||
'DisableSaveSubmissions' => 'Boolean',
|
||||
'EnableLiveValidation' => 'Boolean',
|
||||
'HideFieldLabels' => 'Boolean',
|
||||
'DisplayErrorMessagesAtTop' => 'Boolean',
|
||||
'DisableAuthenicatedFinishAction' => 'Boolean',
|
||||
'DisableCsrfSecurityToken' => 'Boolean'
|
||||
);
|
||||
|
||||
$self = $this;
|
||||
/**
|
||||
* @var array Default values of variables when this page is created
|
||||
*/
|
||||
private static $defaults = array(
|
||||
'Content' => '$UserDefinedForm',
|
||||
'DisableSaveSubmissions' => 0,
|
||||
'OnCompleteMessage' => '<p>Thanks, we\'ve received your submission.</p>'
|
||||
);
|
||||
|
||||
$this->beforeUpdateCMSFields(function($fields) use ($self) {
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $has_many = array(
|
||||
"Submissions" => "SubmittedForm",
|
||||
"EmailRecipients" => "UserDefinedForm_EmailRecipient"
|
||||
);
|
||||
|
||||
// define tabs
|
||||
$fields->findOrMakeTab('Root.FormOptions', _t('UserDefinedForm.CONFIGURATION', 'Configuration'));
|
||||
$fields->findOrMakeTab('Root.Recipients', _t('UserDefinedForm.RECIPIENTS', 'Recipients'));
|
||||
$fields->findOrMakeTab('Root.Submissions', _t('UserDefinedForm.SUBMISSIONS', 'Submissions'));
|
||||
/**
|
||||
* @var array
|
||||
* @config
|
||||
*/
|
||||
private static $casting = array(
|
||||
'ErrorContainerID' => 'Text'
|
||||
);
|
||||
|
||||
// text to show on complete
|
||||
$onCompleteFieldSet = new CompositeField(
|
||||
$label = new LabelField('OnCompleteMessageLabel',_t('UserDefinedForm.ONCOMPLETELABEL', 'Show on completion')),
|
||||
$editor = new HtmlEditorField( 'OnCompleteMessage', '', _t('UserDefinedForm.ONCOMPLETEMESSAGE', $self->OnCompleteMessage))
|
||||
);
|
||||
/**
|
||||
* Error container selector which matches the element for grouped messages
|
||||
*
|
||||
* @var string
|
||||
* @config
|
||||
*/
|
||||
private static $error_container_id = 'error-container';
|
||||
|
||||
$onCompleteFieldSet->addExtraClass('field');
|
||||
/**
|
||||
* The configuration used to determine whether a confirmation message is to
|
||||
* appear when navigating away from a partially completed form.
|
||||
*
|
||||
* @var boolean
|
||||
* @config
|
||||
*/
|
||||
private static $enable_are_you_sure = true;
|
||||
|
||||
$editor->setRows(3);
|
||||
$label->addExtraClass('left');
|
||||
/**
|
||||
* @var bool
|
||||
* @config
|
||||
*/
|
||||
private static $recipients_warning_enabled = false;
|
||||
|
||||
// Define config for email recipients
|
||||
$emailRecipientsConfig = GridFieldConfig_RecordEditor::create(10);
|
||||
$emailRecipientsConfig->getComponentByType('GridFieldAddNewButton')
|
||||
->setButtonName(
|
||||
_t('UserDefinedForm.ADDEMAILRECIPIENT', 'Add Email Recipient')
|
||||
);
|
||||
/**
|
||||
* Temporary storage of field ids when the form is duplicated.
|
||||
* Example layout: array('EditableCheckbox3' => 'EditableCheckbox14')
|
||||
* @var array
|
||||
*/
|
||||
protected $fieldsFromTo = array();
|
||||
|
||||
// who do we email on submission
|
||||
$emailRecipients = new GridField(
|
||||
'EmailRecipients',
|
||||
_t('UserDefinedForm.EMAILRECIPIENTS', 'Email Recipients'),
|
||||
$self->EmailRecipients(),
|
||||
$emailRecipientsConfig
|
||||
);
|
||||
$emailRecipients
|
||||
->getConfig()
|
||||
->getComponentByType('GridFieldDetailForm')
|
||||
->setItemRequestClass('UserFormRecipientItemRequest');
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
Requirements::css(USERFORMS_DIR . '/css/UserForm_cms.css');
|
||||
|
||||
$fields->addFieldsToTab('Root.FormOptions', $onCompleteFieldSet);
|
||||
$fields->addFieldToTab('Root.Recipients', $emailRecipients);
|
||||
$fields->addFieldsToTab('Root.FormOptions', $self->getFormOptions());
|
||||
$self = $this;
|
||||
|
||||
$this->beforeUpdateCMSFields(function ($fields) use ($self) {
|
||||
|
||||
// define tabs
|
||||
$fields->findOrMakeTab('Root.FormOptions', _t('UserDefinedForm.CONFIGURATION', 'Configuration'));
|
||||
$fields->findOrMakeTab('Root.Recipients', _t('UserDefinedForm.RECIPIENTS', 'Recipients'));
|
||||
$fields->findOrMakeTab('Root.Submissions', _t('UserDefinedForm.SUBMISSIONS', 'Submissions'));
|
||||
|
||||
// text to show on complete
|
||||
$onCompleteFieldSet = new CompositeField(
|
||||
$label = new LabelField('OnCompleteMessageLabel', _t('UserDefinedForm.ONCOMPLETELABEL', 'Show on completion')),
|
||||
$editor = new HtmlEditorField('OnCompleteMessage', '', _t('UserDefinedForm.ONCOMPLETEMESSAGE', $self->OnCompleteMessage))
|
||||
);
|
||||
|
||||
$onCompleteFieldSet->addExtraClass('field');
|
||||
|
||||
$editor->setRows(3);
|
||||
$label->addExtraClass('left');
|
||||
|
||||
// Define config for email recipients
|
||||
$emailRecipientsConfig = GridFieldConfig_RecordEditor::create(10);
|
||||
$emailRecipientsConfig->getComponentByType('GridFieldAddNewButton')
|
||||
->setButtonName(
|
||||
_t('UserDefinedForm.ADDEMAILRECIPIENT', 'Add Email Recipient')
|
||||
);
|
||||
|
||||
// who do we email on submission
|
||||
$emailRecipients = new GridField(
|
||||
'EmailRecipients',
|
||||
_t('UserDefinedForm.EMAILRECIPIENTS', 'Email Recipients'),
|
||||
$self->EmailRecipients(),
|
||||
$emailRecipientsConfig
|
||||
);
|
||||
$emailRecipients
|
||||
->getConfig()
|
||||
->getComponentByType('GridFieldDetailForm')
|
||||
->setItemRequestClass('UserFormRecipientItemRequest');
|
||||
|
||||
$fields->addFieldsToTab('Root.FormOptions', $onCompleteFieldSet);
|
||||
$fields->addFieldToTab('Root.Recipients', $emailRecipients);
|
||||
$fields->addFieldsToTab('Root.FormOptions', $self->getFormOptions());
|
||||
|
||||
|
||||
// view the submissions
|
||||
$submissions = new GridField(
|
||||
'Submissions',
|
||||
_t('UserDefinedForm.SUBMISSIONS', 'Submissions'),
|
||||
$self->Submissions()->sort('Created', 'DESC')
|
||||
);
|
||||
// view the submissions
|
||||
$submissions = new GridField(
|
||||
'Submissions',
|
||||
_t('UserDefinedForm.SUBMISSIONS', 'Submissions'),
|
||||
$self->Submissions()->sort('Created', 'DESC')
|
||||
);
|
||||
|
||||
// make sure a numeric not a empty string is checked against this int column for SQL server
|
||||
$parentID = (!empty($self->ID)) ? (int) $self->ID : 0;
|
||||
// make sure a numeric not a empty string is checked against this int column for SQL server
|
||||
$parentID = (!empty($self->ID)) ? (int) $self->ID : 0;
|
||||
|
||||
// get a list of all field names and values used for print and export CSV views of the GridField below.
|
||||
$columnSQL = <<<SQL
|
||||
// get a list of all field names and values used for print and export CSV views of the GridField below.
|
||||
$columnSQL = <<<SQL
|
||||
SELECT "SubmittedFormField"."Name" as "Name", "SubmittedFormField"."Title" as "Title", COALESCE("EditableFormField"."Sort", 999) AS "Sort"
|
||||
FROM "SubmittedFormField"
|
||||
LEFT JOIN "SubmittedForm" ON "SubmittedForm"."ID" = "SubmittedFormField"."ParentID"
|
||||
@ -183,147 +185,152 @@ LEFT JOIN "EditableFormField" ON "EditableFormField"."Title" = "SubmittedFormFie
|
||||
WHERE "SubmittedForm"."ParentID" = '$parentID'
|
||||
ORDER BY "Sort", "Title"
|
||||
SQL;
|
||||
// Sanitise periods in title
|
||||
$columns = array();
|
||||
foreach(DB::query($columnSQL)->map() as $name => $title) {
|
||||
$columns[$name] = trim(strtr($title, '.', ' '));
|
||||
}
|
||||
// Sanitise periods in title
|
||||
$columns = array();
|
||||
foreach (DB::query($columnSQL)->map() as $name => $title) {
|
||||
$columns[$name] = trim(strtr($title, '.', ' '));
|
||||
}
|
||||
|
||||
$config = new GridFieldConfig();
|
||||
$config->addComponent(new GridFieldToolbarHeader());
|
||||
$config->addComponent($sort = new GridFieldSortableHeader());
|
||||
$config->addComponent($filter = new UserFormsGridFieldFilterHeader());
|
||||
$config->addComponent(new GridFieldDataColumns());
|
||||
$config->addComponent(new GridFieldEditButton());
|
||||
$config->addComponent(new GridFieldDeleteAction());
|
||||
$config->addComponent(new GridFieldPageCount('toolbar-header-right'));
|
||||
$config->addComponent($pagination = new GridFieldPaginator(25));
|
||||
$config->addComponent(new GridFieldDetailForm());
|
||||
$config->addComponent(new GridFieldButtonRow('after'));
|
||||
$config->addComponent($export = new GridFieldExportButton('buttons-after-left'));
|
||||
$config->addComponent($print = new GridFieldPrintButton('buttons-after-left'));
|
||||
$config = new GridFieldConfig();
|
||||
$config->addComponent(new GridFieldToolbarHeader());
|
||||
$config->addComponent($sort = new GridFieldSortableHeader());
|
||||
$config->addComponent($filter = new UserFormsGridFieldFilterHeader());
|
||||
$config->addComponent(new GridFieldDataColumns());
|
||||
$config->addComponent(new GridFieldEditButton());
|
||||
$config->addComponent(new GridFieldDeleteAction());
|
||||
$config->addComponent(new GridFieldPageCount('toolbar-header-right'));
|
||||
$config->addComponent($pagination = new GridFieldPaginator(25));
|
||||
$config->addComponent(new GridFieldDetailForm());
|
||||
$config->addComponent(new GridFieldButtonRow('after'));
|
||||
$config->addComponent($export = new GridFieldExportButton('buttons-after-left'));
|
||||
$config->addComponent($print = new GridFieldPrintButton('buttons-after-left'));
|
||||
|
||||
/**
|
||||
* Support for {@link https://github.com/colymba/GridFieldBulkEditingTools}
|
||||
*/
|
||||
if(class_exists('GridFieldBulkManager')) {
|
||||
$config->addComponent(new GridFieldBulkManager());
|
||||
}
|
||||
/**
|
||||
* Support for {@link https://github.com/colymba/GridFieldBulkEditingTools}
|
||||
*/
|
||||
if (class_exists('GridFieldBulkManager')) {
|
||||
$config->addComponent(new GridFieldBulkManager());
|
||||
}
|
||||
|
||||
$sort->setThrowExceptionOnBadDataType(false);
|
||||
$filter->setThrowExceptionOnBadDataType(false);
|
||||
$pagination->setThrowExceptionOnBadDataType(false);
|
||||
$sort->setThrowExceptionOnBadDataType(false);
|
||||
$filter->setThrowExceptionOnBadDataType(false);
|
||||
$pagination->setThrowExceptionOnBadDataType(false);
|
||||
|
||||
// attach every column to the print view form
|
||||
$columns['Created'] = 'Created';
|
||||
$filter->setColumns($columns);
|
||||
// attach every column to the print view form
|
||||
$columns['Created'] = 'Created';
|
||||
$filter->setColumns($columns);
|
||||
|
||||
// print configuration
|
||||
// print configuration
|
||||
|
||||
$print->setPrintHasHeader(true);
|
||||
$print->setPrintColumns($columns);
|
||||
$print->setPrintHasHeader(true);
|
||||
$print->setPrintColumns($columns);
|
||||
|
||||
// export configuration
|
||||
$export->setCsvHasHeader(true);
|
||||
$export->setExportColumns($columns);
|
||||
// export configuration
|
||||
$export->setCsvHasHeader(true);
|
||||
$export->setExportColumns($columns);
|
||||
|
||||
$submissions->setConfig($config);
|
||||
$fields->addFieldToTab('Root.Submissions', $submissions);
|
||||
$fields->addFieldToTab('Root.FormOptions', new CheckboxField('DisableSaveSubmissions', _t('UserDefinedForm.SAVESUBMISSIONS', 'Disable Saving Submissions to Server')));
|
||||
$submissions->setConfig($config);
|
||||
$fields->addFieldToTab('Root.Submissions', $submissions);
|
||||
$fields->addFieldToTab('Root.FormOptions', new CheckboxField('DisableSaveSubmissions', _t('UserDefinedForm.SAVESUBMISSIONS', 'Disable Saving Submissions to Server')));
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
$fields = parent::getCMSFields();
|
||||
$fields = parent::getCMSFields();
|
||||
|
||||
if($this->EmailRecipients()->Count() == 0 && static::config()->recipients_warning_enabled) {
|
||||
$fields->addFieldToTab("Root.Main", new LiteralField("EmailRecipientsWarning",
|
||||
"<p class=\"message warning\">" . _t("UserDefinedForm.NORECIPIENTS",
|
||||
"Warning: You have not configured any recipients. Form submissions may be missed.")
|
||||
. "</p>"), "Title");
|
||||
}
|
||||
if ($this->EmailRecipients()->Count() == 0 && static::config()->recipients_warning_enabled) {
|
||||
$fields->addFieldToTab("Root.Main", new LiteralField("EmailRecipientsWarning",
|
||||
"<p class=\"message warning\">" . _t("UserDefinedForm.NORECIPIENTS",
|
||||
"Warning: You have not configured any recipients. Form submissions may be missed.")
|
||||
. "</p>"), "Title");
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow overriding the EmailRecipients on a {@link DataExtension}
|
||||
* so you can customise who receives an email.
|
||||
* Converts the RelationList to an ArrayList so that manipulation
|
||||
* of the original source data isn't possible.
|
||||
*
|
||||
* @return ArrayList
|
||||
*/
|
||||
public function FilteredEmailRecipients($data = null, $form = null) {
|
||||
$recipients = new ArrayList($this->EmailRecipients()->toArray());
|
||||
/**
|
||||
* Allow overriding the EmailRecipients on a {@link DataExtension}
|
||||
* so you can customise who receives an email.
|
||||
* Converts the RelationList to an ArrayList so that manipulation
|
||||
* of the original source data isn't possible.
|
||||
*
|
||||
* @return ArrayList
|
||||
*/
|
||||
public function FilteredEmailRecipients($data = null, $form = null)
|
||||
{
|
||||
$recipients = new ArrayList($this->EmailRecipients()->toArray());
|
||||
|
||||
// Filter by rules
|
||||
$recipients = $recipients->filterByCallback(function($recipient) use ($data, $form) {
|
||||
return $recipient->canSend($data, $form);
|
||||
});
|
||||
// Filter by rules
|
||||
$recipients = $recipients->filterByCallback(function ($recipient) use ($data, $form) {
|
||||
return $recipient->canSend($data, $form);
|
||||
});
|
||||
|
||||
$this->extend('updateFilteredEmailRecipients', $recipients, $data, $form);
|
||||
$this->extend('updateFilteredEmailRecipients', $recipients, $data, $form);
|
||||
|
||||
return $recipients;
|
||||
}
|
||||
return $recipients;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom options for the form. You can extend the built in options by
|
||||
* using {@link updateFormOptions()}
|
||||
*
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getFormOptions() {
|
||||
$submit = ($this->SubmitButtonText) ? $this->SubmitButtonText : _t('UserDefinedForm.SUBMITBUTTON', 'Submit');
|
||||
$clear = ($this->ClearButtonText) ? $this->ClearButtonText : _t('UserDefinedForm.CLEARBUTTON', 'Clear');
|
||||
/**
|
||||
* Custom options for the form. You can extend the built in options by
|
||||
* using {@link updateFormOptions()}
|
||||
*
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getFormOptions()
|
||||
{
|
||||
$submit = ($this->SubmitButtonText) ? $this->SubmitButtonText : _t('UserDefinedForm.SUBMITBUTTON', 'Submit');
|
||||
$clear = ($this->ClearButtonText) ? $this->ClearButtonText : _t('UserDefinedForm.CLEARBUTTON', 'Clear');
|
||||
|
||||
$options = new FieldList(
|
||||
new TextField("SubmitButtonText", _t('UserDefinedForm.TEXTONSUBMIT', 'Text on submit button:'), $submit),
|
||||
new TextField("ClearButtonText", _t('UserDefinedForm.TEXTONCLEAR', 'Text on clear button:'), $clear),
|
||||
new CheckboxField("ShowClearButton", _t('UserDefinedForm.SHOWCLEARFORM', 'Show Clear Form Button'), $this->ShowClearButton),
|
||||
new CheckboxField("EnableLiveValidation", _t('UserDefinedForm.ENABLELIVEVALIDATION', 'Enable live validation')),
|
||||
new CheckboxField("HideFieldLabels", _t('UserDefinedForm.HIDEFIELDLABELS', 'Hide field labels')),
|
||||
new CheckboxField("DisplayErrorMessagesAtTop", _t('UserDefinedForm.DISPLAYERRORMESSAGESATTOP', 'Display error messages above the form?')),
|
||||
new CheckboxField('DisableCsrfSecurityToken', _t('UserDefinedForm.DISABLECSRFSECURITYTOKEN', 'Disable CSRF Token')),
|
||||
new CheckboxField('DisableAuthenicatedFinishAction', _t('UserDefinedForm.DISABLEAUTHENICATEDFINISHACTION', 'Disable Authentication on finish action'))
|
||||
);
|
||||
$options = new FieldList(
|
||||
new TextField("SubmitButtonText", _t('UserDefinedForm.TEXTONSUBMIT', 'Text on submit button:'), $submit),
|
||||
new TextField("ClearButtonText", _t('UserDefinedForm.TEXTONCLEAR', 'Text on clear button:'), $clear),
|
||||
new CheckboxField("ShowClearButton", _t('UserDefinedForm.SHOWCLEARFORM', 'Show Clear Form Button'), $this->ShowClearButton),
|
||||
new CheckboxField("EnableLiveValidation", _t('UserDefinedForm.ENABLELIVEVALIDATION', 'Enable live validation')),
|
||||
new CheckboxField("HideFieldLabels", _t('UserDefinedForm.HIDEFIELDLABELS', 'Hide field labels')),
|
||||
new CheckboxField("DisplayErrorMessagesAtTop", _t('UserDefinedForm.DISPLAYERRORMESSAGESATTOP', 'Display error messages above the form?')),
|
||||
new CheckboxField('DisableCsrfSecurityToken', _t('UserDefinedForm.DISABLECSRFSECURITYTOKEN', 'Disable CSRF Token')),
|
||||
new CheckboxField('DisableAuthenicatedFinishAction', _t('UserDefinedForm.DISABLEAUTHENICATEDFINISHACTION', 'Disable Authentication on finish action'))
|
||||
);
|
||||
|
||||
$this->extend('updateFormOptions', $options);
|
||||
$this->extend('updateFormOptions', $options);
|
||||
|
||||
return $options;
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTML id of the error container displayed above the form.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getErrorContainerID() {
|
||||
return $this->config()->error_container_id;
|
||||
}
|
||||
/**
|
||||
* Get the HTML id of the error container displayed above the form.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getErrorContainerID()
|
||||
{
|
||||
return $this->config()->error_container_id;
|
||||
}
|
||||
|
||||
public function requireDefaultRecords() {
|
||||
parent::requireDefaultRecords();
|
||||
public function requireDefaultRecords()
|
||||
{
|
||||
parent::requireDefaultRecords();
|
||||
|
||||
if(!$this->config()->upgrade_on_build) {
|
||||
return;
|
||||
}
|
||||
if (!$this->config()->upgrade_on_build) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform migrations
|
||||
Injector::inst()
|
||||
->create('UserFormsUpgradeService')
|
||||
->setQuiet(true)
|
||||
->run();
|
||||
// Perform migrations
|
||||
Injector::inst()
|
||||
->create('UserFormsUpgradeService')
|
||||
->setQuiet(true)
|
||||
->run();
|
||||
|
||||
DB::alteration_message('Migrated userforms', 'changed');
|
||||
}
|
||||
DB::alteration_message('Migrated userforms', 'changed');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate formfields
|
||||
*/
|
||||
public function getCMSValidator() {
|
||||
return new UserFormValidator();
|
||||
}
|
||||
/**
|
||||
* Validate formfields
|
||||
*/
|
||||
public function getCMSValidator()
|
||||
{
|
||||
return new UserFormValidator();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -332,232 +339,238 @@ SQL;
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class UserDefinedForm_Controller extends Page_Controller {
|
||||
class UserDefinedForm_Controller extends Page_Controller
|
||||
{
|
||||
|
||||
private static $finished_anchor = '#uff';
|
||||
private static $finished_anchor = '#uff';
|
||||
|
||||
private static $allowed_actions = array(
|
||||
'index',
|
||||
'ping',
|
||||
'Form',
|
||||
'finished'
|
||||
);
|
||||
private static $allowed_actions = array(
|
||||
'index',
|
||||
'ping',
|
||||
'Form',
|
||||
'finished'
|
||||
);
|
||||
|
||||
public function init() {
|
||||
parent::init();
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
// load the jquery
|
||||
$lang = i18n::get_lang_from_locale(i18n::get_locale());
|
||||
Requirements::css(USERFORMS_DIR . '/css/UserForm.css');
|
||||
Requirements::javascript(FRAMEWORK_DIR .'/thirdparty/jquery/jquery.js');
|
||||
Requirements::javascript(USERFORMS_DIR . '/thirdparty/jquery-validate/jquery.validate.min.js');
|
||||
Requirements::add_i18n_javascript(USERFORMS_DIR . '/javascript/lang');
|
||||
Requirements::javascript(USERFORMS_DIR . '/javascript/UserForm.js');
|
||||
// load the jquery
|
||||
$lang = i18n::get_lang_from_locale(i18n::get_locale());
|
||||
Requirements::css(USERFORMS_DIR . '/css/UserForm.css');
|
||||
Requirements::javascript(FRAMEWORK_DIR .'/thirdparty/jquery/jquery.js');
|
||||
Requirements::javascript(USERFORMS_DIR . '/thirdparty/jquery-validate/jquery.validate.min.js');
|
||||
Requirements::add_i18n_javascript(USERFORMS_DIR . '/javascript/lang');
|
||||
Requirements::javascript(USERFORMS_DIR . '/javascript/UserForm.js');
|
||||
|
||||
Requirements::javascript(
|
||||
USERFORMS_DIR . "/thirdparty/jquery-validate/localization/messages_{$lang}.min.js"
|
||||
);
|
||||
Requirements::javascript(
|
||||
USERFORMS_DIR . "/thirdparty/jquery-validate/localization/methods_{$lang}.min.js"
|
||||
);
|
||||
if($this->HideFieldLabels) {
|
||||
Requirements::javascript(USERFORMS_DIR . '/thirdparty/Placeholders.js/Placeholders.min.js');
|
||||
}
|
||||
Requirements::javascript(
|
||||
USERFORMS_DIR . "/thirdparty/jquery-validate/localization/messages_{$lang}.min.js"
|
||||
);
|
||||
Requirements::javascript(
|
||||
USERFORMS_DIR . "/thirdparty/jquery-validate/localization/methods_{$lang}.min.js"
|
||||
);
|
||||
if ($this->HideFieldLabels) {
|
||||
Requirements::javascript(USERFORMS_DIR . '/thirdparty/Placeholders.js/Placeholders.min.js');
|
||||
}
|
||||
|
||||
// Bind a confirmation message when navigating away from a partially completed form.
|
||||
$page = $this->data();
|
||||
if($page::config()->enable_are_you_sure) {
|
||||
Requirements::javascript(USERFORMS_DIR . '/thirdparty/jquery.are-you-sure/jquery.are-you-sure.js');
|
||||
}
|
||||
}
|
||||
// Bind a confirmation message when navigating away from a partially completed form.
|
||||
$page = $this->data();
|
||||
if ($page::config()->enable_are_you_sure) {
|
||||
Requirements::javascript(USERFORMS_DIR . '/thirdparty/jquery.are-you-sure/jquery.are-you-sure.js');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Using $UserDefinedForm in the Content area of the page shows
|
||||
* where the form should be rendered into. If it does not exist
|
||||
* then default back to $Form.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function index() {
|
||||
if($this->Content && $form = $this->Form()) {
|
||||
$hasLocation = stristr($this->Content, '$UserDefinedForm');
|
||||
if($hasLocation) {
|
||||
$content = preg_replace('/(<p[^>]*>)?\\$UserDefinedForm(<\\/p>)?/i', $form->forTemplate(), $this->Content);
|
||||
return array(
|
||||
'Content' => DBField::create_field('HTMLText', $content),
|
||||
'Form' => ""
|
||||
);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Using $UserDefinedForm in the Content area of the page shows
|
||||
* where the form should be rendered into. If it does not exist
|
||||
* then default back to $Form.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->Content && $form = $this->Form()) {
|
||||
$hasLocation = stristr($this->Content, '$UserDefinedForm');
|
||||
if ($hasLocation) {
|
||||
$content = preg_replace('/(<p[^>]*>)?\\$UserDefinedForm(<\\/p>)?/i', $form->forTemplate(), $this->Content);
|
||||
return array(
|
||||
'Content' => DBField::create_field('HTMLText', $content),
|
||||
'Form' => ""
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'Content' => DBField::create_field('HTMLText', $this->Content),
|
||||
'Form' => $this->Form()
|
||||
);
|
||||
}
|
||||
return array(
|
||||
'Content' => DBField::create_field('HTMLText', $this->Content),
|
||||
'Form' => $this->Form()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep the session alive for the user.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function ping() {
|
||||
return 1;
|
||||
}
|
||||
/**
|
||||
* Keep the session alive for the user.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function ping()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the form for the page. Form can be modified by calling {@link updateForm()}
|
||||
* on a UserDefinedForm extension.
|
||||
*
|
||||
* @return Forms
|
||||
*/
|
||||
public function Form() {
|
||||
$form = UserForm::create($this);
|
||||
$this->generateConditionalJavascript();
|
||||
return $form;
|
||||
}
|
||||
/**
|
||||
* Get the form for the page. Form can be modified by calling {@link updateForm()}
|
||||
* on a UserDefinedForm extension.
|
||||
*
|
||||
* @return Forms
|
||||
*/
|
||||
public function Form()
|
||||
{
|
||||
$form = UserForm::create($this);
|
||||
$this->generateConditionalJavascript();
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the javascript for the conditional field show / hiding logic.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function generateConditionalJavascript() {
|
||||
$default = "";
|
||||
$rules = "";
|
||||
/**
|
||||
* Generate the javascript for the conditional field show / hiding logic.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function generateConditionalJavascript()
|
||||
{
|
||||
$default = "";
|
||||
$rules = "";
|
||||
|
||||
$watch = array();
|
||||
$watchLoad = array();
|
||||
$watch = array();
|
||||
$watchLoad = array();
|
||||
|
||||
if($this->Fields()) {
|
||||
foreach($this->Fields() as $field) {
|
||||
$holderSelector = $field->getSelectorHolder();
|
||||
if ($this->Fields()) {
|
||||
foreach ($this->Fields() as $field) {
|
||||
$holderSelector = $field->getSelectorHolder();
|
||||
|
||||
// Is this Field Show by Default
|
||||
if(!$field->ShowOnLoad) {
|
||||
$default .= "{$holderSelector}.hide().trigger('userform.field.hide');\n";
|
||||
}
|
||||
// Is this Field Show by Default
|
||||
if (!$field->ShowOnLoad) {
|
||||
$default .= "{$holderSelector}.hide().trigger('userform.field.hide');\n";
|
||||
}
|
||||
|
||||
// Check for field dependencies / default
|
||||
foreach($field->EffectiveDisplayRules() as $rule) {
|
||||
// Check for field dependencies / default
|
||||
foreach ($field->EffectiveDisplayRules() as $rule) {
|
||||
|
||||
// Get the field which is effected
|
||||
$formFieldWatch = EditableFormField::get()->byId($rule->ConditionFieldID);
|
||||
// Get the field which is effected
|
||||
$formFieldWatch = EditableFormField::get()->byId($rule->ConditionFieldID);
|
||||
|
||||
// Skip deleted fields
|
||||
if(!$formFieldWatch) {
|
||||
continue;
|
||||
}
|
||||
// Skip deleted fields
|
||||
if (!$formFieldWatch) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fieldToWatch = $formFieldWatch->getSelectorField($rule);
|
||||
$fieldToWatchOnLoad = $formFieldWatch->getSelectorField($rule, true);
|
||||
$fieldToWatch = $formFieldWatch->getSelectorField($rule);
|
||||
$fieldToWatchOnLoad = $formFieldWatch->getSelectorField($rule, true);
|
||||
|
||||
// show or hide?
|
||||
$view = ($rule->Display == 'Hide') ? 'hide' : 'show';
|
||||
$opposite = ($view == "show") ? "hide" : "show";
|
||||
// show or hide?
|
||||
$view = ($rule->Display == 'Hide') ? 'hide' : 'show';
|
||||
$opposite = ($view == "show") ? "hide" : "show";
|
||||
|
||||
// what action do we need to keep track of. Something nicer here maybe?
|
||||
// @todo encapulsation
|
||||
$action = "change";
|
||||
// what action do we need to keep track of. Something nicer here maybe?
|
||||
// @todo encapulsation
|
||||
$action = "change";
|
||||
|
||||
if($formFieldWatch instanceof EditableTextField) {
|
||||
$action = "keyup";
|
||||
}
|
||||
if ($formFieldWatch instanceof EditableTextField) {
|
||||
$action = "keyup";
|
||||
}
|
||||
|
||||
// is this field a special option field
|
||||
$checkboxField = false;
|
||||
$radioField = false;
|
||||
// is this field a special option field
|
||||
$checkboxField = false;
|
||||
$radioField = false;
|
||||
|
||||
if(in_array($formFieldWatch->ClassName, array('EditableCheckboxGroupField', 'EditableCheckbox'))) {
|
||||
$action = "click";
|
||||
$checkboxField = true;
|
||||
} else if ($formFieldWatch->ClassName == "EditableRadioField") {
|
||||
$radioField = true;
|
||||
}
|
||||
if (in_array($formFieldWatch->ClassName, array('EditableCheckboxGroupField', 'EditableCheckbox'))) {
|
||||
$action = "click";
|
||||
$checkboxField = true;
|
||||
} elseif ($formFieldWatch->ClassName == "EditableRadioField") {
|
||||
$radioField = true;
|
||||
}
|
||||
|
||||
// and what should we evaluate
|
||||
switch($rule->ConditionOption) {
|
||||
case 'IsNotBlank':
|
||||
$expression = ($checkboxField || $radioField) ? '$(this).is(":checked")' :'$(this).val() != ""';
|
||||
// and what should we evaluate
|
||||
switch ($rule->ConditionOption) {
|
||||
case 'IsNotBlank':
|
||||
$expression = ($checkboxField || $radioField) ? '$(this).is(":checked")' :'$(this).val() != ""';
|
||||
|
||||
break;
|
||||
case 'IsBlank':
|
||||
$expression = ($checkboxField || $radioField) ? '!($(this).is(":checked"))' : '$(this).val() == ""';
|
||||
break;
|
||||
case 'IsBlank':
|
||||
$expression = ($checkboxField || $radioField) ? '!($(this).is(":checked"))' : '$(this).val() == ""';
|
||||
|
||||
break;
|
||||
case 'HasValue':
|
||||
if ($checkboxField) {
|
||||
$expression = '$(this).prop("checked")';
|
||||
} else if ($radioField) {
|
||||
// We cannot simply get the value of the radio group, we need to find the checked option first.
|
||||
$expression = '$(this).parents(".field, .control-group").find("input:checked").val()=="'. $rule->FieldValue .'"';
|
||||
} else {
|
||||
$expression = '$(this).val() == "'. $rule->FieldValue .'"';
|
||||
}
|
||||
break;
|
||||
case 'HasValue':
|
||||
if ($checkboxField) {
|
||||
$expression = '$(this).prop("checked")';
|
||||
} elseif ($radioField) {
|
||||
// We cannot simply get the value of the radio group, we need to find the checked option first.
|
||||
$expression = '$(this).parents(".field, .control-group").find("input:checked").val()=="'. $rule->FieldValue .'"';
|
||||
} else {
|
||||
$expression = '$(this).val() == "'. $rule->FieldValue .'"';
|
||||
}
|
||||
|
||||
break;
|
||||
case 'ValueLessThan':
|
||||
$expression = '$(this).val() < parseFloat("'. $rule->FieldValue .'")';
|
||||
break;
|
||||
case 'ValueLessThan':
|
||||
$expression = '$(this).val() < parseFloat("'. $rule->FieldValue .'")';
|
||||
|
||||
break;
|
||||
case 'ValueLessThanEqual':
|
||||
$expression = '$(this).val() <= parseFloat("'. $rule->FieldValue .'")';
|
||||
break;
|
||||
case 'ValueLessThanEqual':
|
||||
$expression = '$(this).val() <= parseFloat("'. $rule->FieldValue .'")';
|
||||
|
||||
break;
|
||||
case 'ValueGreaterThan':
|
||||
$expression = '$(this).val() > parseFloat("'. $rule->FieldValue .'")';
|
||||
break;
|
||||
case 'ValueGreaterThan':
|
||||
$expression = '$(this).val() > parseFloat("'. $rule->FieldValue .'")';
|
||||
|
||||
break;
|
||||
case 'ValueGreaterThanEqual':
|
||||
$expression = '$(this).val() >= parseFloat("'. $rule->FieldValue .'")';
|
||||
break;
|
||||
case 'ValueGreaterThanEqual':
|
||||
$expression = '$(this).val() >= parseFloat("'. $rule->FieldValue .'")';
|
||||
|
||||
break;
|
||||
default: // ==HasNotValue
|
||||
if ($checkboxField) {
|
||||
$expression = '!$(this).prop("checked")';
|
||||
} else if ($radioField) {
|
||||
// We cannot simply get the value of the radio group, we need to find the checked option first.
|
||||
$expression = '$(this).parents(".field, .control-group").find("input:checked").val()!="'. $rule->FieldValue .'"';
|
||||
} else {
|
||||
$expression = '$(this).val() != "'. $rule->FieldValue .'"';
|
||||
}
|
||||
break;
|
||||
default: // ==HasNotValue
|
||||
if ($checkboxField) {
|
||||
$expression = '!$(this).prop("checked")';
|
||||
} elseif ($radioField) {
|
||||
// We cannot simply get the value of the radio group, we need to find the checked option first.
|
||||
$expression = '$(this).parents(".field, .control-group").find("input:checked").val()!="'. $rule->FieldValue .'"';
|
||||
} else {
|
||||
$expression = '$(this).val() != "'. $rule->FieldValue .'"';
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(!isset($watch[$fieldToWatch])) {
|
||||
$watch[$fieldToWatch] = array();
|
||||
}
|
||||
if (!isset($watch[$fieldToWatch])) {
|
||||
$watch[$fieldToWatch] = array();
|
||||
}
|
||||
|
||||
$watch[$fieldToWatch][] = array(
|
||||
'expression' => $expression,
|
||||
'holder_selector' => $holderSelector,
|
||||
'view' => $view,
|
||||
'opposite' => $opposite,
|
||||
'action' => $action
|
||||
);
|
||||
$watch[$fieldToWatch][] = array(
|
||||
'expression' => $expression,
|
||||
'holder_selector' => $holderSelector,
|
||||
'view' => $view,
|
||||
'opposite' => $opposite,
|
||||
'action' => $action
|
||||
);
|
||||
|
||||
$watchLoad[$fieldToWatchOnLoad] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
$watchLoad[$fieldToWatchOnLoad] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($watch) {
|
||||
foreach($watch as $key => $values) {
|
||||
$logic = array();
|
||||
$actions = array();
|
||||
if ($watch) {
|
||||
foreach ($watch as $key => $values) {
|
||||
$logic = array();
|
||||
$actions = array();
|
||||
|
||||
foreach($values as $rule) {
|
||||
// Assign action
|
||||
$actions[$rule['action']] = $rule['action'];
|
||||
foreach ($values as $rule) {
|
||||
// Assign action
|
||||
$actions[$rule['action']] = $rule['action'];
|
||||
|
||||
// Assign behaviour
|
||||
$expression = $rule['expression'];
|
||||
$holder = $rule['holder_selector'];
|
||||
$view = $rule['view']; // hide or show
|
||||
$opposite = $rule['opposite'];
|
||||
// Generated javascript for triggering visibility
|
||||
$logic[] = <<<"EOS"
|
||||
// Assign behaviour
|
||||
$expression = $rule['expression'];
|
||||
$holder = $rule['holder_selector'];
|
||||
$view = $rule['view']; // hide or show
|
||||
$opposite = $rule['opposite'];
|
||||
// Generated javascript for triggering visibility
|
||||
$logic[] = <<<"EOS"
|
||||
if({$expression}) {
|
||||
{$holder}
|
||||
.{$view}()
|
||||
@ -568,33 +581,33 @@ if({$expression}) {
|
||||
.trigger('userform.field.{$opposite}');
|
||||
}
|
||||
EOS;
|
||||
}
|
||||
}
|
||||
|
||||
$logic = implode("\n", $logic);
|
||||
$rules .= $key.".each(function() {\n
|
||||
$logic = implode("\n", $logic);
|
||||
$rules .= $key.".each(function() {\n
|
||||
$(this).data('userformConditions', function() {\n
|
||||
$logic\n
|
||||
}); \n
|
||||
});\n";
|
||||
foreach($actions as $action) {
|
||||
$rules .= $key.".$action(function() {
|
||||
foreach ($actions as $action) {
|
||||
$rules .= $key.".$action(function() {
|
||||
$(this).data('userformConditions').call(this);\n
|
||||
});\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($watchLoad) {
|
||||
foreach($watchLoad as $key => $value) {
|
||||
$rules .= $key.".each(function() {
|
||||
if ($watchLoad) {
|
||||
foreach ($watchLoad as $key => $value) {
|
||||
$rules .= $key.".each(function() {
|
||||
$(this).data('userformConditions').call(this);\n
|
||||
});\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only add customScript if $default or $rules is defined
|
||||
if($default || $rules) {
|
||||
Requirements::customScript(<<<JS
|
||||
// Only add customScript if $default or $rules is defined
|
||||
if ($default || $rules) {
|
||||
Requirements::customScript(<<<JS
|
||||
(function($) {
|
||||
$(document).ready(function() {
|
||||
$default
|
||||
@ -604,265 +617,266 @@ EOS;
|
||||
})(jQuery);
|
||||
JS
|
||||
, 'UserFormsConditional');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the form that is submitted through the site
|
||||
*
|
||||
* {@see UserForm::validate()} for validation step prior to processing
|
||||
*
|
||||
* @param array $data
|
||||
* @param Form $form
|
||||
*
|
||||
* @return Redirection
|
||||
*/
|
||||
public function process($data, $form) {
|
||||
$submittedForm = Object::create('SubmittedForm');
|
||||
$submittedForm->SubmittedByID = ($id = Member::currentUserID()) ? $id : 0;
|
||||
$submittedForm->ParentID = $this->ID;
|
||||
/**
|
||||
* Process the form that is submitted through the site
|
||||
*
|
||||
* {@see UserForm::validate()} for validation step prior to processing
|
||||
*
|
||||
* @param array $data
|
||||
* @param Form $form
|
||||
*
|
||||
* @return Redirection
|
||||
*/
|
||||
public function process($data, $form)
|
||||
{
|
||||
$submittedForm = Object::create('SubmittedForm');
|
||||
$submittedForm->SubmittedByID = ($id = Member::currentUserID()) ? $id : 0;
|
||||
$submittedForm->ParentID = $this->ID;
|
||||
|
||||
// if saving is not disabled save now to generate the ID
|
||||
if(!$this->DisableSaveSubmissions) {
|
||||
$submittedForm->write();
|
||||
}
|
||||
// if saving is not disabled save now to generate the ID
|
||||
if (!$this->DisableSaveSubmissions) {
|
||||
$submittedForm->write();
|
||||
}
|
||||
|
||||
$attachments = array();
|
||||
$submittedFields = new ArrayList();
|
||||
$attachments = array();
|
||||
$submittedFields = new ArrayList();
|
||||
|
||||
foreach($this->Fields() as $field) {
|
||||
if(!$field->showInReports()) {
|
||||
continue;
|
||||
}
|
||||
foreach ($this->Fields() as $field) {
|
||||
if (!$field->showInReports()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$submittedField = $field->getSubmittedFormField();
|
||||
$submittedField->ParentID = $submittedForm->ID;
|
||||
$submittedField->Name = $field->Name;
|
||||
$submittedField->Title = $field->getField('Title');
|
||||
$submittedField = $field->getSubmittedFormField();
|
||||
$submittedField->ParentID = $submittedForm->ID;
|
||||
$submittedField->Name = $field->Name;
|
||||
$submittedField->Title = $field->getField('Title');
|
||||
|
||||
// save the value from the data
|
||||
if($field->hasMethod('getValueFromData')) {
|
||||
$submittedField->Value = $field->getValueFromData($data);
|
||||
} else {
|
||||
if(isset($data[$field->Name])) {
|
||||
$submittedField->Value = $data[$field->Name];
|
||||
}
|
||||
}
|
||||
// save the value from the data
|
||||
if ($field->hasMethod('getValueFromData')) {
|
||||
$submittedField->Value = $field->getValueFromData($data);
|
||||
} else {
|
||||
if (isset($data[$field->Name])) {
|
||||
$submittedField->Value = $data[$field->Name];
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($data[$field->Name])) {
|
||||
if(in_array("EditableFileField", $field->getClassAncestry())) {
|
||||
if(isset($_FILES[$field->Name])) {
|
||||
$foldername = $field->getFormField()->getFolderName();
|
||||
if (!empty($data[$field->Name])) {
|
||||
if (in_array("EditableFileField", $field->getClassAncestry())) {
|
||||
if (isset($_FILES[$field->Name])) {
|
||||
$foldername = $field->getFormField()->getFolderName();
|
||||
|
||||
// create the file from post data
|
||||
$upload = new Upload();
|
||||
$file = new File();
|
||||
$file->ShowInSearch = 0;
|
||||
try {
|
||||
$upload->loadIntoFile($_FILES[$field->Name], $file, $foldername);
|
||||
} catch( ValidationException $e ) {
|
||||
$validationResult = $e->getResult();
|
||||
$form->addErrorMessage($field->Name, $validationResult->message(), 'bad');
|
||||
Controller::curr()->redirectBack();
|
||||
return;
|
||||
}
|
||||
// create the file from post data
|
||||
$upload = new Upload();
|
||||
$file = new File();
|
||||
$file->ShowInSearch = 0;
|
||||
try {
|
||||
$upload->loadIntoFile($_FILES[$field->Name], $file, $foldername);
|
||||
} catch (ValidationException $e) {
|
||||
$validationResult = $e->getResult();
|
||||
$form->addErrorMessage($field->Name, $validationResult->message(), 'bad');
|
||||
Controller::curr()->redirectBack();
|
||||
return;
|
||||
}
|
||||
|
||||
// write file to form field
|
||||
$submittedField->UploadedFileID = $file->ID;
|
||||
// write file to form field
|
||||
$submittedField->UploadedFileID = $file->ID;
|
||||
|
||||
// attach a file only if lower than 1MB
|
||||
if($file->getAbsoluteSize() < 1024*1024*1) {
|
||||
$attachments[] = $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// attach a file only if lower than 1MB
|
||||
if ($file->getAbsoluteSize() < 1024*1024*1) {
|
||||
$attachments[] = $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$submittedField->extend('onPopulationFromField', $field);
|
||||
$submittedField->extend('onPopulationFromField', $field);
|
||||
|
||||
if(!$this->DisableSaveSubmissions) {
|
||||
$submittedField->write();
|
||||
}
|
||||
if (!$this->DisableSaveSubmissions) {
|
||||
$submittedField->write();
|
||||
}
|
||||
|
||||
$submittedFields->push($submittedField);
|
||||
}
|
||||
$submittedFields->push($submittedField);
|
||||
}
|
||||
|
||||
$emailData = array(
|
||||
"Sender" => Member::currentUser(),
|
||||
"Fields" => $submittedFields
|
||||
);
|
||||
$emailData = array(
|
||||
"Sender" => Member::currentUser(),
|
||||
"Fields" => $submittedFields
|
||||
);
|
||||
|
||||
$this->extend('updateEmailData', $emailData, $attachments);
|
||||
$this->extend('updateEmailData', $emailData, $attachments);
|
||||
|
||||
// email users on submit.
|
||||
if($recipients = $this->FilteredEmailRecipients($data, $form)) {
|
||||
// email users on submit.
|
||||
if ($recipients = $this->FilteredEmailRecipients($data, $form)) {
|
||||
foreach ($recipients as $recipient) {
|
||||
$email = new UserFormRecipientEmail($submittedFields);
|
||||
$mergeFields = $this->getMergeFieldsMap($emailData['Fields']);
|
||||
|
||||
foreach($recipients as $recipient) {
|
||||
$email = new UserFormRecipientEmail($submittedFields);
|
||||
$mergeFields = $this->getMergeFieldsMap($emailData['Fields']);
|
||||
if ($attachments) {
|
||||
foreach ($attachments as $file) {
|
||||
if ($file->ID != 0) {
|
||||
$email->attachFile(
|
||||
$file->Filename,
|
||||
$file->Filename,
|
||||
HTTP::get_mime_type($file->Filename)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($attachments) {
|
||||
foreach($attachments as $file) {
|
||||
if($file->ID != 0) {
|
||||
$email->attachFile(
|
||||
$file->Filename,
|
||||
$file->Filename,
|
||||
HTTP::get_mime_type($file->Filename)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
$parsedBody = SSViewer::execute_string($recipient->getEmailBodyContent(), $mergeFields);
|
||||
|
||||
$parsedBody = SSViewer::execute_string($recipient->getEmailBodyContent(), $mergeFields);
|
||||
if (!$recipient->SendPlain && $recipient->emailTemplateExists()) {
|
||||
$email->setTemplate($recipient->EmailTemplate);
|
||||
}
|
||||
|
||||
if (!$recipient->SendPlain && $recipient->emailTemplateExists()) {
|
||||
$email->setTemplate($recipient->EmailTemplate);
|
||||
}
|
||||
$email->populateTemplate($recipient);
|
||||
$email->populateTemplate($emailData);
|
||||
$email->setFrom($recipient->EmailFrom);
|
||||
$email->setBody($parsedBody);
|
||||
$email->setTo($recipient->EmailAddress);
|
||||
$email->setSubject($recipient->EmailSubject);
|
||||
|
||||
$email->populateTemplate($recipient);
|
||||
$email->populateTemplate($emailData);
|
||||
$email->setFrom($recipient->EmailFrom);
|
||||
$email->setBody($parsedBody);
|
||||
$email->setTo($recipient->EmailAddress);
|
||||
$email->setSubject($recipient->EmailSubject);
|
||||
if ($recipient->EmailReplyTo) {
|
||||
$email->setReplyTo($recipient->EmailReplyTo);
|
||||
}
|
||||
|
||||
if($recipient->EmailReplyTo) {
|
||||
$email->setReplyTo($recipient->EmailReplyTo);
|
||||
}
|
||||
// check to see if they are a dynamic reply to. eg based on a email field a user selected
|
||||
if ($recipient->SendEmailFromField()) {
|
||||
$submittedFormField = $submittedFields->find('Name', $recipient->SendEmailFromField()->Name);
|
||||
|
||||
// check to see if they are a dynamic reply to. eg based on a email field a user selected
|
||||
if($recipient->SendEmailFromField()) {
|
||||
$submittedFormField = $submittedFields->find('Name', $recipient->SendEmailFromField()->Name);
|
||||
if ($submittedFormField && is_string($submittedFormField->Value)) {
|
||||
$email->setReplyTo($submittedFormField->Value);
|
||||
}
|
||||
}
|
||||
// check to see if they are a dynamic reciever eg based on a dropdown field a user selected
|
||||
if ($recipient->SendEmailToField()) {
|
||||
$submittedFormField = $submittedFields->find('Name', $recipient->SendEmailToField()->Name);
|
||||
|
||||
if($submittedFormField && is_string($submittedFormField->Value)) {
|
||||
$email->setReplyTo($submittedFormField->Value);
|
||||
}
|
||||
}
|
||||
// check to see if they are a dynamic reciever eg based on a dropdown field a user selected
|
||||
if($recipient->SendEmailToField()) {
|
||||
$submittedFormField = $submittedFields->find('Name', $recipient->SendEmailToField()->Name);
|
||||
if ($submittedFormField && is_string($submittedFormField->Value)) {
|
||||
$email->setTo($submittedFormField->Value);
|
||||
}
|
||||
}
|
||||
|
||||
if($submittedFormField && is_string($submittedFormField->Value)) {
|
||||
$email->setTo($submittedFormField->Value);
|
||||
}
|
||||
}
|
||||
// check to see if there is a dynamic subject
|
||||
if ($recipient->SendEmailSubjectField()) {
|
||||
$submittedFormField = $submittedFields->find('Name', $recipient->SendEmailSubjectField()->Name);
|
||||
|
||||
// check to see if there is a dynamic subject
|
||||
if($recipient->SendEmailSubjectField()) {
|
||||
$submittedFormField = $submittedFields->find('Name', $recipient->SendEmailSubjectField()->Name);
|
||||
if ($submittedFormField && trim($submittedFormField->Value)) {
|
||||
$email->setSubject($submittedFormField->Value);
|
||||
}
|
||||
}
|
||||
|
||||
if($submittedFormField && trim($submittedFormField->Value)) {
|
||||
$email->setSubject($submittedFormField->Value);
|
||||
}
|
||||
}
|
||||
$this->extend('updateEmail', $email, $recipient, $emailData);
|
||||
|
||||
$this->extend('updateEmail', $email, $recipient, $emailData);
|
||||
if ($recipient->SendPlain) {
|
||||
$body = strip_tags($recipient->getEmailBodyContent()) . "\n";
|
||||
if (isset($emailData['Fields']) && !$recipient->HideFormData) {
|
||||
foreach ($emailData['Fields'] as $Field) {
|
||||
$body .= $Field->Title .': '. $Field->Value ." \n";
|
||||
}
|
||||
}
|
||||
|
||||
if($recipient->SendPlain) {
|
||||
$body = strip_tags($recipient->getEmailBodyContent()) . "\n";
|
||||
if(isset($emailData['Fields']) && !$recipient->HideFormData) {
|
||||
foreach($emailData['Fields'] as $Field) {
|
||||
$body .= $Field->Title .': '. $Field->Value ." \n";
|
||||
}
|
||||
}
|
||||
$email->setBody($body);
|
||||
$email->sendPlain();
|
||||
} else {
|
||||
$email->send();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$email->setBody($body);
|
||||
$email->sendPlain();
|
||||
}
|
||||
else {
|
||||
$email->send();
|
||||
}
|
||||
}
|
||||
}
|
||||
$submittedForm->extend('updateAfterProcess');
|
||||
|
||||
$submittedForm->extend('updateAfterProcess');
|
||||
Session::clear("FormInfo.{$form->FormName()}.errors");
|
||||
Session::clear("FormInfo.{$form->FormName()}.data");
|
||||
|
||||
Session::clear("FormInfo.{$form->FormName()}.errors");
|
||||
Session::clear("FormInfo.{$form->FormName()}.data");
|
||||
$referrer = (isset($data['Referrer'])) ? '?referrer=' . urlencode($data['Referrer']) : "";
|
||||
|
||||
$referrer = (isset($data['Referrer'])) ? '?referrer=' . urlencode($data['Referrer']) : "";
|
||||
// set a session variable from the security ID to stop people accessing
|
||||
// the finished method directly.
|
||||
if (!$this->DisableAuthenicatedFinishAction) {
|
||||
if (isset($data['SecurityID'])) {
|
||||
Session::set('FormProcessed', $data['SecurityID']);
|
||||
} else {
|
||||
// if the form has had tokens disabled we still need to set FormProcessed
|
||||
// to allow us to get through the finshed method
|
||||
if (!$this->Form()->getSecurityToken()->isEnabled()) {
|
||||
$randNum = rand(1, 1000);
|
||||
$randHash = md5($randNum);
|
||||
Session::set('FormProcessed', $randHash);
|
||||
Session::set('FormProcessedNum', $randNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set a session variable from the security ID to stop people accessing
|
||||
// the finished method directly.
|
||||
if(!$this->DisableAuthenicatedFinishAction) {
|
||||
if (isset($data['SecurityID'])) {
|
||||
Session::set('FormProcessed',$data['SecurityID']);
|
||||
} else {
|
||||
// if the form has had tokens disabled we still need to set FormProcessed
|
||||
// to allow us to get through the finshed method
|
||||
if (!$this->Form()->getSecurityToken()->isEnabled()) {
|
||||
$randNum = rand(1, 1000);
|
||||
$randHash = md5($randNum);
|
||||
Session::set('FormProcessed',$randHash);
|
||||
Session::set('FormProcessedNum',$randNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$this->DisableSaveSubmissions) {
|
||||
Session::set('userformssubmission'. $this->ID, $submittedForm->ID);
|
||||
}
|
||||
|
||||
if(!$this->DisableSaveSubmissions) {
|
||||
Session::set('userformssubmission'. $this->ID, $submittedForm->ID);
|
||||
}
|
||||
return $this->redirect($this->Link('finished') . $referrer . $this->config()->finished_anchor);
|
||||
}
|
||||
|
||||
return $this->redirect($this->Link('finished') . $referrer . $this->config()->finished_anchor);
|
||||
}
|
||||
/**
|
||||
* Allows the use of field values in email body.
|
||||
*
|
||||
* @param ArrayList fields
|
||||
* @return ArrayData
|
||||
*/
|
||||
private function getMergeFieldsMap($fields = array())
|
||||
{
|
||||
$data = new ArrayData(array());
|
||||
|
||||
/**
|
||||
* Allows the use of field values in email body.
|
||||
*
|
||||
* @param ArrayList fields
|
||||
* @return ArrayData
|
||||
*/
|
||||
private function getMergeFieldsMap($fields = array()) {
|
||||
$data = new ArrayData(array());
|
||||
foreach ($fields as $field) {
|
||||
$data->setField($field->Name, DBField::create_field('Text', $field->Value));
|
||||
}
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$data->setField($field->Name, DBField::create_field('Text', $field->Value));
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
/**
|
||||
* This action handles rendering the "finished" message, which is
|
||||
* customizable by editing the ReceivedFormSubmission template.
|
||||
*
|
||||
* @return ViewableData
|
||||
*/
|
||||
public function finished()
|
||||
{
|
||||
$submission = Session::get('userformssubmission'. $this->ID);
|
||||
|
||||
/**
|
||||
* This action handles rendering the "finished" message, which is
|
||||
* customizable by editing the ReceivedFormSubmission template.
|
||||
*
|
||||
* @return ViewableData
|
||||
*/
|
||||
public function finished() {
|
||||
$submission = Session::get('userformssubmission'. $this->ID);
|
||||
if ($submission) {
|
||||
$submission = SubmittedForm::get()->byId($submission);
|
||||
}
|
||||
|
||||
if($submission) {
|
||||
$submission = SubmittedForm::get()->byId($submission);
|
||||
}
|
||||
$referrer = isset($_GET['referrer']) ? urldecode($_GET['referrer']) : null;
|
||||
|
||||
$referrer = isset($_GET['referrer']) ? urldecode($_GET['referrer']) : null;
|
||||
if (!$this->DisableAuthenicatedFinishAction) {
|
||||
$formProcessed = Session::get('FormProcessed');
|
||||
|
||||
if(!$this->DisableAuthenicatedFinishAction) {
|
||||
$formProcessed = Session::get('FormProcessed');
|
||||
if (!isset($formProcessed)) {
|
||||
return $this->redirect($this->Link() . $referrer);
|
||||
} else {
|
||||
$securityID = Session::get('SecurityID');
|
||||
// make sure the session matches the SecurityID and is not left over from another form
|
||||
if ($formProcessed != $securityID) {
|
||||
// they may have disabled tokens on the form
|
||||
$securityID = md5(Session::get('FormProcessedNum'));
|
||||
if ($formProcessed != $securityID) {
|
||||
return $this->redirect($this->Link() . $referrer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($formProcessed)) {
|
||||
return $this->redirect($this->Link() . $referrer);
|
||||
} else {
|
||||
$securityID = Session::get('SecurityID');
|
||||
// make sure the session matches the SecurityID and is not left over from another form
|
||||
if ($formProcessed != $securityID) {
|
||||
// they may have disabled tokens on the form
|
||||
$securityID = md5(Session::get('FormProcessedNum'));
|
||||
if ($formProcessed != $securityID) {
|
||||
return $this->redirect($this->Link() . $referrer);
|
||||
}
|
||||
}
|
||||
}
|
||||
Session::clear('FormProcessed');
|
||||
}
|
||||
|
||||
Session::clear('FormProcessed');
|
||||
}
|
||||
|
||||
return $this->customise(array(
|
||||
'Content' => $this->customise(array(
|
||||
'Submission' => $submission,
|
||||
'Link' => $referrer
|
||||
))->renderWith('ReceivedFormSubmission'),
|
||||
'Form' => '',
|
||||
));
|
||||
}
|
||||
return $this->customise(array(
|
||||
'Content' => $this->customise(array(
|
||||
'Submission' => $submission,
|
||||
'Link' => $referrer
|
||||
))->renderWith('ReceivedFormSubmission'),
|
||||
'Form' => '',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -7,53 +7,58 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class EditableCheckbox extends EditableFormField {
|
||||
class EditableCheckbox extends EditableFormField
|
||||
{
|
||||
|
||||
private static $singular_name = 'Checkbox Field';
|
||||
private static $singular_name = 'Checkbox Field';
|
||||
|
||||
private static $plural_name = 'Checkboxes';
|
||||
private static $plural_name = 'Checkboxes';
|
||||
|
||||
private static $db = array(
|
||||
'CheckedDefault' => 'Boolean' // from CustomSettings
|
||||
);
|
||||
private static $db = array(
|
||||
'CheckedDefault' => 'Boolean' // from CustomSettings
|
||||
);
|
||||
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields() {
|
||||
$fields = parent::getCMSFields();
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
$fields = parent::getCMSFields();
|
||||
|
||||
$fields->replaceField('Default', CheckboxField::create(
|
||||
"CheckedDefault",
|
||||
_t('EditableFormField.CHECKEDBYDEFAULT', 'Checked by Default?')
|
||||
));
|
||||
$fields->replaceField('Default', CheckboxField::create(
|
||||
"CheckedDefault",
|
||||
_t('EditableFormField.CHECKEDBYDEFAULT', 'Checked by Default?')
|
||||
));
|
||||
|
||||
return $fields;
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function getFormField() {
|
||||
$field = CheckboxField::create($this->Name, $this->EscapedTitle, $this->CheckedDefault)
|
||||
->setFieldHolderTemplate('UserFormsCheckboxField_holder')
|
||||
->setTemplate('UserFormsCheckboxField');
|
||||
public function getFormField()
|
||||
{
|
||||
$field = CheckboxField::create($this->Name, $this->EscapedTitle, $this->CheckedDefault)
|
||||
->setFieldHolderTemplate('UserFormsCheckboxField_holder')
|
||||
->setTemplate('UserFormsCheckboxField');
|
||||
|
||||
$this->doUpdateFormField($field);
|
||||
$this->doUpdateFormField($field);
|
||||
|
||||
return $field;
|
||||
}
|
||||
return $field;
|
||||
}
|
||||
|
||||
public function getValueFromData($data) {
|
||||
$value = (isset($data[$this->Name])) ? $data[$this->Name] : false;
|
||||
public function getValueFromData($data)
|
||||
{
|
||||
$value = (isset($data[$this->Name])) ? $data[$this->Name] : false;
|
||||
|
||||
return ($value) ? _t('EditableFormField.YES', 'Yes') : _t('EditableFormField.NO', 'No');
|
||||
}
|
||||
return ($value) ? _t('EditableFormField.YES', 'Yes') : _t('EditableFormField.NO', 'No');
|
||||
}
|
||||
|
||||
public function migrateSettings($data) {
|
||||
// Migrate 'Default' setting to 'CheckedDefault'
|
||||
if(isset($data['Default'])) {
|
||||
$this->CheckedDefault = (bool)$data['Default'];
|
||||
unset($data['Default']);
|
||||
}
|
||||
public function migrateSettings($data)
|
||||
{
|
||||
// Migrate 'Default' setting to 'CheckedDefault'
|
||||
if (isset($data['Default'])) {
|
||||
$this->CheckedDefault = (bool)$data['Default'];
|
||||
unset($data['Default']);
|
||||
}
|
||||
|
||||
parent::migrateSettings($data);
|
||||
}
|
||||
parent::migrateSettings($data);
|
||||
}
|
||||
}
|
||||
|
@ -7,52 +7,56 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class EditableCheckboxGroupField extends EditableMultipleOptionField {
|
||||
class EditableCheckboxGroupField extends EditableMultipleOptionField
|
||||
{
|
||||
|
||||
private static $singular_name = "Checkbox Group";
|
||||
private static $singular_name = "Checkbox Group";
|
||||
|
||||
private static $plural_name = "Checkbox Groups";
|
||||
private static $plural_name = "Checkbox Groups";
|
||||
|
||||
public function getFormField() {
|
||||
$field = new UserFormsCheckboxSetField($this->Name, $this->EscapedTitle, $this->getOptionsMap());
|
||||
$field->setFieldHolderTemplate('UserFormsMultipleOptionField_holder');
|
||||
public function getFormField()
|
||||
{
|
||||
$field = new UserFormsCheckboxSetField($this->Name, $this->EscapedTitle, $this->getOptionsMap());
|
||||
$field->setFieldHolderTemplate('UserFormsMultipleOptionField_holder');
|
||||
|
||||
// Set the default checked items
|
||||
$defaultCheckedItems = $this->getDefaultOptions();
|
||||
if ($defaultCheckedItems->count()) {
|
||||
$field->setDefaultItems($defaultCheckedItems->map('EscapedTitle')->keys());
|
||||
}
|
||||
// Set the default checked items
|
||||
$defaultCheckedItems = $this->getDefaultOptions();
|
||||
if ($defaultCheckedItems->count()) {
|
||||
$field->setDefaultItems($defaultCheckedItems->map('EscapedTitle')->keys());
|
||||
}
|
||||
|
||||
$this->doUpdateFormField($field);
|
||||
return $field;
|
||||
}
|
||||
$this->doUpdateFormField($field);
|
||||
return $field;
|
||||
}
|
||||
|
||||
public function getValueFromData($data) {
|
||||
$result = '';
|
||||
$entries = (isset($data[$this->Name])) ? $data[$this->Name] : false;
|
||||
public function getValueFromData($data)
|
||||
{
|
||||
$result = '';
|
||||
$entries = (isset($data[$this->Name])) ? $data[$this->Name] : false;
|
||||
|
||||
if($entries) {
|
||||
if(!is_array($data[$this->Name])) {
|
||||
$entries = array($data[$this->Name]);
|
||||
}
|
||||
foreach($entries as $selected => $value) {
|
||||
if(!$result) {
|
||||
$result = $value;
|
||||
} else {
|
||||
$result .= ", " . $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
if ($entries) {
|
||||
if (!is_array($data[$this->Name])) {
|
||||
$entries = array($data[$this->Name]);
|
||||
}
|
||||
foreach ($entries as $selected => $value) {
|
||||
if (!$result) {
|
||||
$result = $value;
|
||||
} else {
|
||||
$result .= ", " . $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getSelectorField(EditableCustomRule $rule, $forOnLoad = false) {
|
||||
// watch out for checkboxs as the inputs don't have values but are 'checked
|
||||
// @todo - Test this
|
||||
if($rule->FieldValue) {
|
||||
return "$(\"input[name='{$this->Name}[]'][value='{$rule->FieldValue}']\")";
|
||||
} else {
|
||||
return "$(\"input[name='{$this->Name}[]']:first\")";
|
||||
}
|
||||
}
|
||||
public function getSelectorField(EditableCustomRule $rule, $forOnLoad = false)
|
||||
{
|
||||
// watch out for checkboxs as the inputs don't have values but are 'checked
|
||||
// @todo - Test this
|
||||
if ($rule->FieldValue) {
|
||||
return "$(\"input[name='{$this->Name}[]'][value='{$rule->FieldValue}']\")";
|
||||
} else {
|
||||
return "$(\"input[name='{$this->Name}[]']:first\")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,45 +5,51 @@
|
||||
*
|
||||
* @package userforms
|
||||
*/
|
||||
class EditableCountryDropdownField extends EditableFormField {
|
||||
class EditableCountryDropdownField extends EditableFormField
|
||||
{
|
||||
|
||||
private static $singular_name = 'Country Dropdown';
|
||||
private static $singular_name = 'Country Dropdown';
|
||||
|
||||
private static $plural_name = 'Country Dropdowns';
|
||||
private static $plural_name = 'Country Dropdowns';
|
||||
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields() {
|
||||
$fields = parent::getCMSFields();
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
$fields = parent::getCMSFields();
|
||||
|
||||
$fields->removeByName('Default');
|
||||
$fields->removeByName('Default');
|
||||
|
||||
return $fields;
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function getFormField() {
|
||||
$field = CountryDropdownField::create($this->Name, $this->EscapedTitle)
|
||||
->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsDropdownField');
|
||||
public function getFormField()
|
||||
{
|
||||
$field = CountryDropdownField::create($this->Name, $this->EscapedTitle)
|
||||
->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsDropdownField');
|
||||
|
||||
$this->doUpdateFormField($field);
|
||||
$this->doUpdateFormField($field);
|
||||
|
||||
return $field;
|
||||
}
|
||||
return $field;
|
||||
}
|
||||
|
||||
public function getValueFromData($data) {
|
||||
if(isset($data[$this->Name])) {
|
||||
$source = $this->getFormField()->getSource();
|
||||
return $source[$data[$this->Name]];
|
||||
}
|
||||
}
|
||||
public function getValueFromData($data)
|
||||
{
|
||||
if (isset($data[$this->Name])) {
|
||||
$source = $this->getFormField()->getSource();
|
||||
return $source[$data[$this->Name]];
|
||||
}
|
||||
}
|
||||
|
||||
public function getIcon() {
|
||||
return USERFORMS_DIR . '/images/editabledropdown.png';
|
||||
}
|
||||
public function getIcon()
|
||||
{
|
||||
return USERFORMS_DIR . '/images/editabledropdown.png';
|
||||
}
|
||||
|
||||
public function getSelectorField(EditableCustomRule $rule, $forOnLoad = false) {
|
||||
return "$(\"select[name='{$this->Name}']\")";
|
||||
}
|
||||
public function getSelectorField(EditableCustomRule $rule, $forOnLoad = false)
|
||||
{
|
||||
return "$(\"select[name='{$this->Name}']\")";
|
||||
}
|
||||
}
|
@ -7,60 +7,65 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class EditableDateField extends EditableFormField {
|
||||
class EditableDateField extends EditableFormField
|
||||
{
|
||||
|
||||
private static $singular_name = 'Date Field';
|
||||
private static $singular_name = 'Date Field';
|
||||
|
||||
private static $plural_name = 'Date Fields';
|
||||
private static $plural_name = 'Date Fields';
|
||||
|
||||
private static $db = array(
|
||||
'DefaultToToday' => 'Boolean' // From customsettings
|
||||
);
|
||||
private static $db = array(
|
||||
'DefaultToToday' => 'Boolean' // From customsettings
|
||||
);
|
||||
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields() {
|
||||
$this->beforeUpdateCMSFields(function(FieldList $fields) {
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
CheckboxField::create(
|
||||
'DefaultToToday',
|
||||
_t('EditableFormField.DEFAULTTOTODAY', 'Default to Today?')
|
||||
),
|
||||
'RightTitle'
|
||||
);
|
||||
});
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
$this->beforeUpdateCMSFields(function (FieldList $fields) {
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
CheckboxField::create(
|
||||
'DefaultToToday',
|
||||
_t('EditableFormField.DEFAULTTOTODAY', 'Default to Today?')
|
||||
),
|
||||
'RightTitle'
|
||||
);
|
||||
});
|
||||
|
||||
return parent::getCMSFields();
|
||||
}
|
||||
return parent::getCMSFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the form field
|
||||
*
|
||||
*/
|
||||
public function getFormField() {
|
||||
$defaultValue = $this->DefaultToToday
|
||||
? SS_Datetime::now()->Format('Y-m-d')
|
||||
: $this->Default;
|
||||
/**
|
||||
* Return the form field
|
||||
*
|
||||
*/
|
||||
public function getFormField()
|
||||
{
|
||||
$defaultValue = $this->DefaultToToday
|
||||
? SS_Datetime::now()->Format('Y-m-d')
|
||||
: $this->Default;
|
||||
|
||||
$field = EditableDateField_FormField::create( $this->Name, $this->EscapedTitle, $defaultValue)
|
||||
->setConfig('showcalendar', true)
|
||||
->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsField');
|
||||
$field = EditableDateField_FormField::create($this->Name, $this->EscapedTitle, $defaultValue)
|
||||
->setConfig('showcalendar', true)
|
||||
->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsField');
|
||||
|
||||
$this->doUpdateFormField($field);
|
||||
$this->doUpdateFormField($field);
|
||||
|
||||
return $field;
|
||||
}
|
||||
return $field;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @package userforms
|
||||
*/
|
||||
class EditableDateField_FormField extends DateField {
|
||||
class EditableDateField_FormField extends DateField
|
||||
{
|
||||
|
||||
public function Type() {
|
||||
return "date-alt text";
|
||||
}
|
||||
public function Type()
|
||||
{
|
||||
return "date-alt text";
|
||||
}
|
||||
}
|
@ -7,41 +7,45 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class EditableDropdown extends EditableMultipleOptionField {
|
||||
class EditableDropdown extends EditableMultipleOptionField
|
||||
{
|
||||
|
||||
private static $singular_name = 'Dropdown Field';
|
||||
private static $singular_name = 'Dropdown Field';
|
||||
|
||||
private static $plural_name = 'Dropdowns';
|
||||
private static $plural_name = 'Dropdowns';
|
||||
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields() {
|
||||
$fields = parent::getCMSFields();
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
$fields = parent::getCMSFields();
|
||||
|
||||
$fields->removeByName('Default');
|
||||
$fields->removeByName('Default');
|
||||
|
||||
return $fields;
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DropdownField
|
||||
*/
|
||||
public function getFormField() {
|
||||
$field = DropdownField::create($this->Name, $this->EscapedTitle, $this->getOptionsMap())
|
||||
->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsDropdownField');
|
||||
/**
|
||||
* @return DropdownField
|
||||
*/
|
||||
public function getFormField()
|
||||
{
|
||||
$field = DropdownField::create($this->Name, $this->EscapedTitle, $this->getOptionsMap())
|
||||
->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsDropdownField');
|
||||
|
||||
// Set default
|
||||
$defaultOption = $this->getDefaultOptions()->first();
|
||||
if($defaultOption) {
|
||||
$field->setValue($defaultOption->EscapedTitle);
|
||||
}
|
||||
$this->doUpdateFormField($field);
|
||||
return $field;
|
||||
}
|
||||
// Set default
|
||||
$defaultOption = $this->getDefaultOptions()->first();
|
||||
if ($defaultOption) {
|
||||
$field->setValue($defaultOption->EscapedTitle);
|
||||
}
|
||||
$this->doUpdateFormField($field);
|
||||
return $field;
|
||||
}
|
||||
|
||||
public function getSelectorField(EditableCustomRule $rule, $forOnLoad = false) {
|
||||
return "$(\"select[name='{$this->Name}']\")";
|
||||
}
|
||||
public function getSelectorField(EditableCustomRule $rule, $forOnLoad = false)
|
||||
{
|
||||
return "$(\"select[name='{$this->Name}']\")";
|
||||
}
|
||||
}
|
@ -7,56 +7,61 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class EditableEmailField extends EditableFormField {
|
||||
class EditableEmailField extends EditableFormField
|
||||
{
|
||||
|
||||
private static $singular_name = 'Email Field';
|
||||
private static $singular_name = 'Email Field';
|
||||
|
||||
private static $plural_name = 'Email Fields';
|
||||
private static $plural_name = 'Email Fields';
|
||||
|
||||
private static $db = array(
|
||||
'Placeholder' => 'Varchar(255)'
|
||||
);
|
||||
private static $db = array(
|
||||
'Placeholder' => 'Varchar(255)'
|
||||
);
|
||||
|
||||
public function getCMSFields() {
|
||||
$this->beforeUpdateCMSFields(function($fields) {
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
TextField::create(
|
||||
'Placeholder',
|
||||
_t('EditableTextField.PLACEHOLDER', 'Placeholder')
|
||||
)
|
||||
);
|
||||
});
|
||||
public function getCMSFields()
|
||||
{
|
||||
$this->beforeUpdateCMSFields(function ($fields) {
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
TextField::create(
|
||||
'Placeholder',
|
||||
_t('EditableTextField.PLACEHOLDER', 'Placeholder')
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
return parent::getCMSFields();
|
||||
}
|
||||
return parent::getCMSFields();
|
||||
}
|
||||
|
||||
public function getSetsOwnError() {
|
||||
return true;
|
||||
}
|
||||
public function getSetsOwnError()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getFormField() {
|
||||
$field = EmailField::create($this->Name, $this->EscapedTitle, $this->Default)
|
||||
->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsField');
|
||||
public function getFormField()
|
||||
{
|
||||
$field = EmailField::create($this->Name, $this->EscapedTitle, $this->Default)
|
||||
->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsField');
|
||||
|
||||
$this->doUpdateFormField($field);
|
||||
$this->doUpdateFormField($field);
|
||||
|
||||
return $field;
|
||||
}
|
||||
return $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a formfield with the additional metadata specified by this field
|
||||
*
|
||||
* @param FormField $field
|
||||
*/
|
||||
protected function updateFormField($field) {
|
||||
parent::updateFormField($field);
|
||||
/**
|
||||
* Updates a formfield with the additional metadata specified by this field
|
||||
*
|
||||
* @param FormField $field
|
||||
*/
|
||||
protected function updateFormField($field)
|
||||
{
|
||||
parent::updateFormField($field);
|
||||
|
||||
$field->setAttribute('data-rule-email', true);
|
||||
$field->setAttribute('data-rule-email', true);
|
||||
|
||||
if($this->Placeholder) {
|
||||
$field->setAttribute('placeholder', $this->Placeholder);
|
||||
}
|
||||
}
|
||||
if ($this->Placeholder) {
|
||||
$field->setAttribute('placeholder', $this->Placeholder);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,90 +3,98 @@
|
||||
/**
|
||||
* Specifies that this ends a group of fields
|
||||
*/
|
||||
class EditableFieldGroup extends EditableFormField {
|
||||
class EditableFieldGroup extends EditableFormField
|
||||
{
|
||||
|
||||
private static $has_one = array(
|
||||
'End' => 'EditableFieldGroupEnd'
|
||||
);
|
||||
private static $has_one = array(
|
||||
'End' => 'EditableFieldGroupEnd'
|
||||
);
|
||||
|
||||
/**
|
||||
* Disable selection of group class
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $hidden = true;
|
||||
/**
|
||||
* Disable selection of group class
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $hidden = true;
|
||||
|
||||
/**
|
||||
* Non-data field type
|
||||
*
|
||||
* @var type
|
||||
*/
|
||||
private static $literal = true;
|
||||
/**
|
||||
* Non-data field type
|
||||
*
|
||||
* @var type
|
||||
*/
|
||||
private static $literal = true;
|
||||
|
||||
public function getCMSFields() {
|
||||
$fields = parent::getCMSFields();
|
||||
$fields->removeByName(array('MergeField', 'Default', 'Validation', 'DisplayRules'));
|
||||
return $fields;
|
||||
}
|
||||
public function getCMSFields()
|
||||
{
|
||||
$fields = parent::getCMSFields();
|
||||
$fields->removeByName(array('MergeField', 'Default', 'Validation', 'DisplayRules'));
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function getCMSTitle() {
|
||||
$title = $this->getFieldNumber()
|
||||
?: $this->Title
|
||||
?: 'group';
|
||||
public function getCMSTitle()
|
||||
{
|
||||
$title = $this->getFieldNumber()
|
||||
?: $this->Title
|
||||
?: 'group';
|
||||
|
||||
return _t(
|
||||
'EditableFieldGroupEnd.FIELD_GROUP_START',
|
||||
'Group {group}',
|
||||
array(
|
||||
'group' => $title
|
||||
)
|
||||
);
|
||||
}
|
||||
return _t(
|
||||
'EditableFieldGroupEnd.FIELD_GROUP_START',
|
||||
'Group {group}',
|
||||
array(
|
||||
'group' => $title
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function getInlineClassnameField($column, $fieldClasses) {
|
||||
return new LabelField($column, $this->CMSTitle);
|
||||
}
|
||||
public function getInlineClassnameField($column, $fieldClasses)
|
||||
{
|
||||
return new LabelField($column, $this->CMSTitle);
|
||||
}
|
||||
|
||||
public function showInReports() {
|
||||
return false;
|
||||
}
|
||||
public function showInReports()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getFormField() {
|
||||
$field = UserFormsGroupField::create()
|
||||
->setTitle($this->EscapedTitle ?: false)
|
||||
->setName($this->Name);
|
||||
$this->doUpdateFormField($field);
|
||||
return $field;
|
||||
}
|
||||
public function getFormField()
|
||||
{
|
||||
$field = UserFormsGroupField::create()
|
||||
->setTitle($this->EscapedTitle ?: false)
|
||||
->setName($this->Name);
|
||||
$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));
|
||||
}
|
||||
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($this->ExtraClass) {
|
||||
$field->addExtraClass($this->ExtraClass);
|
||||
}
|
||||
}
|
||||
// if this field has an extra class
|
||||
if ($this->ExtraClass) {
|
||||
$field->addExtraClass($this->ExtraClass);
|
||||
}
|
||||
}
|
||||
|
||||
protected function onBeforeDelete() {
|
||||
parent::onBeforeDelete();
|
||||
protected function onBeforeDelete()
|
||||
{
|
||||
parent::onBeforeDelete();
|
||||
|
||||
// Ensures EndID is lazy-loaded for onAfterDelete
|
||||
$this->EndID;
|
||||
}
|
||||
// Ensures EndID is lazy-loaded for onAfterDelete
|
||||
$this->EndID;
|
||||
}
|
||||
|
||||
protected function onAfterDelete() {
|
||||
parent::onAfterDelete();
|
||||
|
||||
// Delete end
|
||||
if(($end = $this->End()) && $end->exists()) {
|
||||
$end->delete();
|
||||
}
|
||||
}
|
||||
protected function onAfterDelete()
|
||||
{
|
||||
parent::onAfterDelete();
|
||||
|
||||
// Delete end
|
||||
if (($end = $this->End()) && $end->exists()) {
|
||||
$end->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,92 +3,100 @@
|
||||
/**
|
||||
* Specifies that this ends a group of fields
|
||||
*/
|
||||
class EditableFieldGroupEnd extends EditableFormField {
|
||||
class EditableFieldGroupEnd extends EditableFormField
|
||||
{
|
||||
|
||||
private static $belongs_to = array(
|
||||
'Group' => 'EditableFieldGroup'
|
||||
);
|
||||
private static $belongs_to = array(
|
||||
'Group' => 'EditableFieldGroup'
|
||||
);
|
||||
|
||||
/**
|
||||
* Disable selection of group class
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $hidden = true;
|
||||
/**
|
||||
* Disable selection of group class
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $hidden = true;
|
||||
|
||||
/**
|
||||
* Non-data type
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $literal = true;
|
||||
/**
|
||||
* Non-data type
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $literal = true;
|
||||
|
||||
public function getCMSTitle() {
|
||||
$group = $this->Group();
|
||||
return _t(
|
||||
'EditableFieldGroupEnd.FIELD_GROUP_END',
|
||||
'{group} end',
|
||||
array(
|
||||
'group' => ($group && $group->exists()) ? $group->CMSTitle : 'Group'
|
||||
)
|
||||
);
|
||||
}
|
||||
public function getCMSTitle()
|
||||
{
|
||||
$group = $this->Group();
|
||||
return _t(
|
||||
'EditableFieldGroupEnd.FIELD_GROUP_END',
|
||||
'{group} end',
|
||||
array(
|
||||
'group' => ($group && $group->exists()) ? $group->CMSTitle : 'Group'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function getCMSFields() {
|
||||
$fields = parent::getCMSFields();
|
||||
$fields->removeByName(array('MergeField', 'Default', 'Validation', 'DisplayRules'));
|
||||
return $fields;
|
||||
}
|
||||
public function getCMSFields()
|
||||
{
|
||||
$fields = parent::getCMSFields();
|
||||
$fields->removeByName(array('MergeField', 'Default', 'Validation', 'DisplayRules'));
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function getInlineClassnameField($column, $fieldClasses) {
|
||||
return new LabelField($column, $this->CMSTitle);
|
||||
}
|
||||
public function getInlineClassnameField($column, $fieldClasses)
|
||||
{
|
||||
return new LabelField($column, $this->CMSTitle);
|
||||
}
|
||||
|
||||
public function getInlineTitleField($column) {
|
||||
return HiddenField::create($column);
|
||||
}
|
||||
public function getInlineTitleField($column)
|
||||
{
|
||||
return HiddenField::create($column);
|
||||
}
|
||||
|
||||
public function getFormField() {
|
||||
return null;
|
||||
}
|
||||
public function getFormField()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function showInReports() {
|
||||
return false;
|
||||
}
|
||||
public function showInReports()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onAfterWrite() {
|
||||
parent::onAfterWrite();
|
||||
public function onAfterWrite()
|
||||
{
|
||||
parent::onAfterWrite();
|
||||
|
||||
// If this is not attached to a group, find the first group prior to this
|
||||
// with no end attached
|
||||
$group = $this->Group();
|
||||
if(!($group && $group->exists()) && $this->ParentID) {
|
||||
$group = EditableFieldGroup::get()
|
||||
->filter(array(
|
||||
'ParentID' => $this->ParentID,
|
||||
'Sort:LessThanOrEqual' => $this->Sort
|
||||
))
|
||||
->where('"EditableFieldGroup"."EndID" IS NULL OR "EditableFieldGroup"."EndID" = 0')
|
||||
->sort('"Sort" DESC')
|
||||
->first();
|
||||
// If this is not attached to a group, find the first group prior to this
|
||||
// with no end attached
|
||||
$group = $this->Group();
|
||||
if (!($group && $group->exists()) && $this->ParentID) {
|
||||
$group = EditableFieldGroup::get()
|
||||
->filter(array(
|
||||
'ParentID' => $this->ParentID,
|
||||
'Sort:LessThanOrEqual' => $this->Sort
|
||||
))
|
||||
->where('"EditableFieldGroup"."EndID" IS NULL OR "EditableFieldGroup"."EndID" = 0')
|
||||
->sort('"Sort" DESC')
|
||||
->first();
|
||||
|
||||
// When a group is found, attach it to this end
|
||||
if($group) {
|
||||
$group->EndID = $this->ID;
|
||||
$group->write();
|
||||
}
|
||||
}
|
||||
}
|
||||
// When a group is found, attach it to this end
|
||||
if ($group) {
|
||||
$group->EndID = $this->ID;
|
||||
$group->write();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function onAfterDelete() {
|
||||
parent::onAfterDelete();
|
||||
|
||||
// Delete group
|
||||
if(($group = $this->Group()) && $group->exists()) {
|
||||
$group->delete();
|
||||
}
|
||||
}
|
||||
protected function onAfterDelete()
|
||||
{
|
||||
parent::onAfterDelete();
|
||||
|
||||
// Delete group
|
||||
if (($group = $this->Group()) && $group->exists()) {
|
||||
$group->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,99 +6,105 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class EditableFileField extends EditableFormField {
|
||||
class EditableFileField extends EditableFormField
|
||||
{
|
||||
|
||||
private static $singular_name = 'File Upload Field';
|
||||
private static $singular_name = 'File Upload Field';
|
||||
|
||||
private static $plural_names = 'File Fields';
|
||||
private static $plural_names = 'File Fields';
|
||||
|
||||
private static $has_one = array(
|
||||
'Folder' => 'Folder' // From CustomFields
|
||||
);
|
||||
private static $has_one = array(
|
||||
'Folder' => 'Folder' // From CustomFields
|
||||
);
|
||||
|
||||
/**
|
||||
* Further limit uploadable file extensions in addition to the restrictions
|
||||
* imposed by the File.allowed_extensions global configuration.
|
||||
* @config
|
||||
*/
|
||||
private static $allowed_extensions_blacklist = array(
|
||||
'htm', 'html', 'xhtml', 'swf', 'xml'
|
||||
);
|
||||
/**
|
||||
* Further limit uploadable file extensions in addition to the restrictions
|
||||
* imposed by the File.allowed_extensions global configuration.
|
||||
* @config
|
||||
*/
|
||||
private static $allowed_extensions_blacklist = array(
|
||||
'htm', 'html', 'xhtml', 'swf', 'xml'
|
||||
);
|
||||
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields() {
|
||||
$fields = parent::getCMSFields();
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
$fields = parent::getCMSFields();
|
||||
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
TreeDropdownField::create(
|
||||
'FolderID',
|
||||
_t('EditableUploadField.SELECTUPLOADFOLDER', 'Select upload folder'),
|
||||
'Folder'
|
||||
)
|
||||
);
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
TreeDropdownField::create(
|
||||
'FolderID',
|
||||
_t('EditableUploadField.SELECTUPLOADFOLDER', 'Select upload folder'),
|
||||
'Folder'
|
||||
)
|
||||
);
|
||||
|
||||
$fields->addFieldToTab("Root.Main", new LiteralField("FileUploadWarning",
|
||||
"<p class=\"message notice\">" . _t("UserDefinedForm.FileUploadWarning",
|
||||
"Files uploaded through this field could be publicly accessible if the exact URL is known")
|
||||
. "</p>"), "Type");
|
||||
$fields->addFieldToTab("Root.Main", new LiteralField("FileUploadWarning",
|
||||
"<p class=\"message notice\">" . _t("UserDefinedForm.FileUploadWarning",
|
||||
"Files uploaded through this field could be publicly accessible if the exact URL is known")
|
||||
. "</p>"), "Type");
|
||||
|
||||
return $fields;
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function getFormField() {
|
||||
public function getFormField()
|
||||
{
|
||||
$field = FileField::create($this->Name, $this->EscapedTitle)
|
||||
->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsFileField');
|
||||
->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsFileField');
|
||||
|
||||
$field->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsFileField');
|
||||
$field->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsFileField');
|
||||
|
||||
$field->getValidator()->setAllowedExtensions(
|
||||
array_diff(
|
||||
// filter out '' since this would be a regex problem on JS end
|
||||
array_filter(Config::inst()->get('File', 'allowed_extensions')),
|
||||
$this->config()->allowed_extensions_blacklist
|
||||
)
|
||||
);
|
||||
$field->getValidator()->setAllowedExtensions(
|
||||
array_diff(
|
||||
// filter out '' since this would be a regex problem on JS end
|
||||
array_filter(Config::inst()->get('File', 'allowed_extensions')),
|
||||
$this->config()->allowed_extensions_blacklist
|
||||
)
|
||||
);
|
||||
|
||||
$folder = $this->Folder();
|
||||
if($folder && $folder->exists()) {
|
||||
$field->setFolderName(
|
||||
preg_replace("/^assets\//","", $folder->Filename)
|
||||
);
|
||||
}
|
||||
$folder = $this->Folder();
|
||||
if ($folder && $folder->exists()) {
|
||||
$field->setFolderName(
|
||||
preg_replace("/^assets\//", "", $folder->Filename)
|
||||
);
|
||||
}
|
||||
|
||||
$this->doUpdateFormField($field);
|
||||
$this->doUpdateFormField($field);
|
||||
|
||||
return $field;
|
||||
}
|
||||
return $field;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the value for the database, link to the file is stored as a
|
||||
* relation so value for the field can be null.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getValueFromData() {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Return the value for the database, link to the file is stored as a
|
||||
* relation so value for the field can be null.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getValueFromData()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getSubmittedFormField() {
|
||||
return new SubmittedFileField();
|
||||
}
|
||||
public function getSubmittedFormField()
|
||||
{
|
||||
return new SubmittedFileField();
|
||||
}
|
||||
|
||||
|
||||
public function migrateSettings($data) {
|
||||
// Migrate 'Folder' setting to 'FolderID'
|
||||
if(isset($data['Folder'])) {
|
||||
$this->FolderID = $data['Folder'];
|
||||
unset($data['Folder']);
|
||||
}
|
||||
public function migrateSettings($data)
|
||||
{
|
||||
// Migrate 'Folder' setting to 'FolderID'
|
||||
if (isset($data['Folder'])) {
|
||||
$this->FolderID = $data['Folder'];
|
||||
unset($data['Folder']);
|
||||
}
|
||||
|
||||
parent::migrateSettings($data);
|
||||
}
|
||||
parent::migrateSettings($data);
|
||||
}
|
||||
}
|
||||
|
@ -17,380 +17,387 @@ use SilverStripe\Forms\SegmentField;
|
||||
* @method UserDefinedForm Parent() Parent page
|
||||
* @method DataList DisplayRules() List of EditableCustomRule objects
|
||||
*/
|
||||
class EditableFormField extends DataObject {
|
||||
class EditableFormField extends DataObject
|
||||
{
|
||||
|
||||
/**
|
||||
* Set to true to hide from class selector
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $hidden = false;
|
||||
/**
|
||||
* Set to true to hide from class selector
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $hidden = false;
|
||||
|
||||
/**
|
||||
* Define this field as abstract (not inherited)
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $abstract = true;
|
||||
/**
|
||||
* Define this field as abstract (not inherited)
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $abstract = true;
|
||||
|
||||
/**
|
||||
* Flag this field type as non-data (e.g. literal, header, html)
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $literal = false;
|
||||
/**
|
||||
* Flag this field type as non-data (e.g. literal, header, html)
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $literal = false;
|
||||
|
||||
/**
|
||||
* Default sort order
|
||||
*
|
||||
* @config
|
||||
* @var string
|
||||
*/
|
||||
private static $default_sort = '"Sort"';
|
||||
/**
|
||||
* Default sort order
|
||||
*
|
||||
* @config
|
||||
* @var string
|
||||
*/
|
||||
private static $default_sort = '"Sort"';
|
||||
|
||||
/**
|
||||
* A list of CSS classes that can be added
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $allowed_css = array();
|
||||
/**
|
||||
* A list of CSS classes that can be added
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $allowed_css = array();
|
||||
|
||||
/**
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $summary_fields = array(
|
||||
'Title'
|
||||
);
|
||||
/**
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $summary_fields = array(
|
||||
'Title'
|
||||
);
|
||||
|
||||
/**
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $db = array(
|
||||
"Name" => "Varchar",
|
||||
"Title" => "Varchar(255)",
|
||||
"Default" => "Varchar(255)",
|
||||
"Sort" => "Int",
|
||||
"Required" => "Boolean",
|
||||
"CustomErrorMessage" => "Varchar(255)",
|
||||
/**
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $db = array(
|
||||
"Name" => "Varchar",
|
||||
"Title" => "Varchar(255)",
|
||||
"Default" => "Varchar(255)",
|
||||
"Sort" => "Int",
|
||||
"Required" => "Boolean",
|
||||
"CustomErrorMessage" => "Varchar(255)",
|
||||
|
||||
"CustomRules" => "Text", // @deprecated from 2.0
|
||||
"CustomSettings" => "Text", // @deprecated from 2.0
|
||||
"Migrated" => "Boolean", // set to true when migrated
|
||||
"CustomRules" => "Text", // @deprecated from 2.0
|
||||
"CustomSettings" => "Text", // @deprecated from 2.0
|
||||
"Migrated" => "Boolean", // set to true when migrated
|
||||
|
||||
"ExtraClass" => "Text", // from CustomSettings
|
||||
"RightTitle" => "Varchar(255)", // from CustomSettings
|
||||
"ShowOnLoad" => "Boolean(1)", // from CustomSettings
|
||||
);
|
||||
"ExtraClass" => "Text", // from CustomSettings
|
||||
"RightTitle" => "Varchar(255)", // from CustomSettings
|
||||
"ShowOnLoad" => "Boolean(1)", // from CustomSettings
|
||||
);
|
||||
|
||||
private static $defaults = array(
|
||||
'ShowOnLoad' => true,
|
||||
);
|
||||
private static $defaults = array(
|
||||
'ShowOnLoad' => true,
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $has_one = array(
|
||||
"Parent" => "UserDefinedForm",
|
||||
);
|
||||
/**
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $has_one = array(
|
||||
"Parent" => "UserDefinedForm",
|
||||
);
|
||||
|
||||
/**
|
||||
* Built in extensions required
|
||||
*
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $extensions = array(
|
||||
"Versioned('Stage', 'Live')"
|
||||
);
|
||||
/**
|
||||
* Built in extensions required
|
||||
*
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $extensions = array(
|
||||
"Versioned('Stage', 'Live')"
|
||||
);
|
||||
|
||||
/**
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $has_many = array(
|
||||
"DisplayRules" => "EditableCustomRule.Parent" // from CustomRules
|
||||
);
|
||||
/**
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $has_many = array(
|
||||
"DisplayRules" => "EditableCustomRule.Parent" // from CustomRules
|
||||
);
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $readonly;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $readonly;
|
||||
|
||||
/**
|
||||
* Set the visibility of an individual form field
|
||||
*
|
||||
* @param bool
|
||||
*/
|
||||
public function setReadonly($readonly = true) {
|
||||
$this->readonly = $readonly;
|
||||
}
|
||||
/**
|
||||
* Set the visibility of an individual form field
|
||||
*
|
||||
* @param bool
|
||||
*/
|
||||
public function setReadonly($readonly = true)
|
||||
{
|
||||
$this->readonly = $readonly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this field is readonly
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isReadonly() {
|
||||
return $this->readonly;
|
||||
}
|
||||
/**
|
||||
* Returns whether this field is readonly
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isReadonly()
|
||||
{
|
||||
return $this->readonly;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields() {
|
||||
$fields = new FieldList(new TabSet('Root'));
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
$fields = new FieldList(new TabSet('Root'));
|
||||
|
||||
// Main tab
|
||||
$fields->addFieldsToTab(
|
||||
'Root.Main',
|
||||
array(
|
||||
ReadonlyField::create(
|
||||
'Type',
|
||||
_t('EditableFormField.TYPE', 'Type'),
|
||||
$this->i18n_singular_name()
|
||||
),
|
||||
LiteralField::create(
|
||||
'MergeField',
|
||||
_t(
|
||||
'EditableFormField.MERGEFIELDNAME',
|
||||
'<div class="field readonly">' .
|
||||
'<label class="left">Merge field</label>' .
|
||||
'<div class="middleColumn">' .
|
||||
'<span class="readonly">$' . $this->Name . '</span>' .
|
||||
'</div>' .
|
||||
'</div>'
|
||||
)
|
||||
),
|
||||
TextField::create('Title'),
|
||||
TextField::create('Default', _t('EditableFormField.DEFAULT', 'Default value')),
|
||||
TextField::create('RightTitle', _t('EditableFormField.RIGHTTITLE', 'Right title')),
|
||||
SegmentField::create('Name')->setModifiers(array(
|
||||
UnderscoreSegmentFieldModifier::create()->setDefault('FieldName'),
|
||||
DisambiguationSegmentFieldModifier::create(),
|
||||
))->setPreview($this->Name)
|
||||
)
|
||||
);
|
||||
// Main tab
|
||||
$fields->addFieldsToTab(
|
||||
'Root.Main',
|
||||
array(
|
||||
ReadonlyField::create(
|
||||
'Type',
|
||||
_t('EditableFormField.TYPE', 'Type'),
|
||||
$this->i18n_singular_name()
|
||||
),
|
||||
LiteralField::create(
|
||||
'MergeField',
|
||||
_t(
|
||||
'EditableFormField.MERGEFIELDNAME',
|
||||
'<div class="field readonly">' .
|
||||
'<label class="left">Merge field</label>' .
|
||||
'<div class="middleColumn">' .
|
||||
'<span class="readonly">$' . $this->Name . '</span>' .
|
||||
'</div>' .
|
||||
'</div>'
|
||||
)
|
||||
),
|
||||
TextField::create('Title'),
|
||||
TextField::create('Default', _t('EditableFormField.DEFAULT', 'Default value')),
|
||||
TextField::create('RightTitle', _t('EditableFormField.RIGHTTITLE', 'Right title')),
|
||||
SegmentField::create('Name')->setModifiers(array(
|
||||
UnderscoreSegmentFieldModifier::create()->setDefault('FieldName'),
|
||||
DisambiguationSegmentFieldModifier::create(),
|
||||
))->setPreview($this->Name)
|
||||
)
|
||||
);
|
||||
|
||||
// Custom settings
|
||||
if (!empty(self::$allowed_css)) {
|
||||
$cssList = array();
|
||||
foreach(self::$allowed_css as $k => $v) {
|
||||
if (!is_array($v)) {
|
||||
$cssList[$k]=$v;
|
||||
} elseif ($k === $this->ClassName) {
|
||||
$cssList = array_merge($cssList, $v);
|
||||
}
|
||||
}
|
||||
// Custom settings
|
||||
if (!empty(self::$allowed_css)) {
|
||||
$cssList = array();
|
||||
foreach (self::$allowed_css as $k => $v) {
|
||||
if (!is_array($v)) {
|
||||
$cssList[$k]=$v;
|
||||
} elseif ($k === $this->ClassName) {
|
||||
$cssList = array_merge($cssList, $v);
|
||||
}
|
||||
}
|
||||
|
||||
$fields->addFieldToTab('Root.Main',
|
||||
DropdownField::create(
|
||||
'ExtraClass',
|
||||
_t('EditableFormField.EXTRACLASS_TITLE', 'Extra Styling/Layout'),
|
||||
$cssList
|
||||
)->setDescription(_t(
|
||||
'EditableFormField.EXTRACLASS_SELECT',
|
||||
'Select from the list of allowed styles'
|
||||
))
|
||||
);
|
||||
} else {
|
||||
$fields->addFieldToTab('Root.Main',
|
||||
TextField::create(
|
||||
'ExtraClass',
|
||||
_t('EditableFormField.EXTRACLASS_Title', 'Extra CSS classes')
|
||||
)->setDescription(_t(
|
||||
'EditableFormField.EXTRACLASS_MULTIPLE',
|
||||
'Separate each CSS class with a single space'
|
||||
))
|
||||
);
|
||||
}
|
||||
$fields->addFieldToTab('Root.Main',
|
||||
DropdownField::create(
|
||||
'ExtraClass',
|
||||
_t('EditableFormField.EXTRACLASS_TITLE', 'Extra Styling/Layout'),
|
||||
$cssList
|
||||
)->setDescription(_t(
|
||||
'EditableFormField.EXTRACLASS_SELECT',
|
||||
'Select from the list of allowed styles'
|
||||
))
|
||||
);
|
||||
} else {
|
||||
$fields->addFieldToTab('Root.Main',
|
||||
TextField::create(
|
||||
'ExtraClass',
|
||||
_t('EditableFormField.EXTRACLASS_Title', 'Extra CSS classes')
|
||||
)->setDescription(_t(
|
||||
'EditableFormField.EXTRACLASS_MULTIPLE',
|
||||
'Separate each CSS class with a single space'
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
// Validation
|
||||
$validationFields = $this->getFieldValidationOptions();
|
||||
if($validationFields && $validationFields->count()) {
|
||||
$fields->addFieldsToTab('Root.Validation', $validationFields);
|
||||
}
|
||||
// Validation
|
||||
$validationFields = $this->getFieldValidationOptions();
|
||||
if ($validationFields && $validationFields->count()) {
|
||||
$fields->addFieldsToTab('Root.Validation', $validationFields);
|
||||
}
|
||||
|
||||
// Add display rule fields
|
||||
$displayFields = $this->getDisplayRuleFields();
|
||||
if($displayFields && $displayFields->count()) {
|
||||
$fields->addFieldsToTab('Root.DisplayRules', $displayFields);
|
||||
}
|
||||
// Add display rule fields
|
||||
$displayFields = $this->getDisplayRuleFields();
|
||||
if ($displayFields && $displayFields->count()) {
|
||||
$fields->addFieldsToTab('Root.DisplayRules', $displayFields);
|
||||
}
|
||||
|
||||
$this->extend('updateCMSFields', $fields);
|
||||
$this->extend('updateCMSFields', $fields);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return fields to display on the 'Display Rules' tab
|
||||
*
|
||||
* @return FieldList
|
||||
*/
|
||||
protected function getDisplayRuleFields() {
|
||||
// Check display rules
|
||||
if($this->Required) {
|
||||
return new FieldList(
|
||||
LabelField::create(_t(
|
||||
'EditableFormField.DISPLAY_RULES_DISABLED',
|
||||
'Display rules are not enabled for required fields. ' .
|
||||
'Please uncheck "Is this field Required?" under "Validation" to re-enable.'
|
||||
))->addExtraClass('message warning')
|
||||
);
|
||||
}
|
||||
$self = $this;
|
||||
$allowedClasses = array_keys($this->getEditableFieldClasses(false));
|
||||
$editableColumns = new GridFieldEditableColumns();
|
||||
$editableColumns->setDisplayFields(array(
|
||||
'Display' => '',
|
||||
'ConditionFieldID' => function($record, $column, $grid) use ($allowedClasses, $self) {
|
||||
return DropdownField::create(
|
||||
$column,
|
||||
'',
|
||||
EditableFormField::get()
|
||||
->filter(array(
|
||||
'ParentID' => $self->ParentID,
|
||||
'ClassName' => $allowedClasses
|
||||
))
|
||||
->exclude(array(
|
||||
'ID' => $self->ID
|
||||
))
|
||||
->map('ID', 'Title')
|
||||
);
|
||||
},
|
||||
'ConditionOption' => function($record, $column, $grid) {
|
||||
$options = Config::inst()->get('EditableCustomRule', 'condition_options');
|
||||
return DropdownField::create($column, '', $options);
|
||||
},
|
||||
'FieldValue' => function($record, $column, $grid) {
|
||||
return TextField::create($column);
|
||||
},
|
||||
'ParentID' => function($record, $column, $grid) use ($self) {
|
||||
return HiddenField::create($column, '', $self->ID);
|
||||
}
|
||||
));
|
||||
/**
|
||||
* Return fields to display on the 'Display Rules' tab
|
||||
*
|
||||
* @return FieldList
|
||||
*/
|
||||
protected function getDisplayRuleFields()
|
||||
{
|
||||
// Check display rules
|
||||
if ($this->Required) {
|
||||
return new FieldList(
|
||||
LabelField::create(_t(
|
||||
'EditableFormField.DISPLAY_RULES_DISABLED',
|
||||
'Display rules are not enabled for required fields. ' .
|
||||
'Please uncheck "Is this field Required?" under "Validation" to re-enable.'
|
||||
))->addExtraClass('message warning')
|
||||
);
|
||||
}
|
||||
$self = $this;
|
||||
$allowedClasses = array_keys($this->getEditableFieldClasses(false));
|
||||
$editableColumns = new GridFieldEditableColumns();
|
||||
$editableColumns->setDisplayFields(array(
|
||||
'Display' => '',
|
||||
'ConditionFieldID' => function ($record, $column, $grid) use ($allowedClasses, $self) {
|
||||
return DropdownField::create(
|
||||
$column,
|
||||
'',
|
||||
EditableFormField::get()
|
||||
->filter(array(
|
||||
'ParentID' => $self->ParentID,
|
||||
'ClassName' => $allowedClasses
|
||||
))
|
||||
->exclude(array(
|
||||
'ID' => $self->ID
|
||||
))
|
||||
->map('ID', 'Title')
|
||||
);
|
||||
},
|
||||
'ConditionOption' => function ($record, $column, $grid) {
|
||||
$options = Config::inst()->get('EditableCustomRule', 'condition_options');
|
||||
return DropdownField::create($column, '', $options);
|
||||
},
|
||||
'FieldValue' => function ($record, $column, $grid) {
|
||||
return TextField::create($column);
|
||||
},
|
||||
'ParentID' => function ($record, $column, $grid) use ($self) {
|
||||
return HiddenField::create($column, '', $self->ID);
|
||||
}
|
||||
));
|
||||
|
||||
// Custom rules
|
||||
$customRulesConfig = GridFieldConfig::create()
|
||||
->addComponents(
|
||||
$editableColumns,
|
||||
new GridFieldButtonRow(),
|
||||
new GridFieldToolbarHeader(),
|
||||
new GridFieldAddNewInlineButton(),
|
||||
new GridFieldDeleteAction()
|
||||
);
|
||||
// Custom rules
|
||||
$customRulesConfig = GridFieldConfig::create()
|
||||
->addComponents(
|
||||
$editableColumns,
|
||||
new GridFieldButtonRow(),
|
||||
new GridFieldToolbarHeader(),
|
||||
new GridFieldAddNewInlineButton(),
|
||||
new GridFieldDeleteAction()
|
||||
);
|
||||
|
||||
return new FieldList(
|
||||
CheckboxField::create('ShowOnLoad')
|
||||
->setDescription(_t(
|
||||
'EditableFormField.SHOWONLOAD',
|
||||
'Initial visibility before processing these rules'
|
||||
)),
|
||||
GridField::create(
|
||||
'DisplayRules',
|
||||
_t('EditableFormField.CUSTOMRULES', 'Custom Rules'),
|
||||
$this->DisplayRules(),
|
||||
$customRulesConfig
|
||||
)
|
||||
);
|
||||
}
|
||||
return new FieldList(
|
||||
CheckboxField::create('ShowOnLoad')
|
||||
->setDescription(_t(
|
||||
'EditableFormField.SHOWONLOAD',
|
||||
'Initial visibility before processing these rules'
|
||||
)),
|
||||
GridField::create(
|
||||
'DisplayRules',
|
||||
_t('EditableFormField.CUSTOMRULES', 'Custom Rules'),
|
||||
$this->DisplayRules(),
|
||||
$customRulesConfig
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function onBeforeWrite() {
|
||||
parent::onBeforeWrite();
|
||||
public function onBeforeWrite()
|
||||
{
|
||||
parent::onBeforeWrite();
|
||||
|
||||
// Set a field name.
|
||||
if(!$this->Name) {
|
||||
// New random name
|
||||
$this->Name = $this->generateName();
|
||||
// Set a field name.
|
||||
if (!$this->Name) {
|
||||
// New random name
|
||||
$this->Name = $this->generateName();
|
||||
} elseif ($this->Name === 'Field') {
|
||||
throw new ValidationException('Field name cannot be "Field"');
|
||||
}
|
||||
|
||||
} elseif($this->Name === 'Field') {
|
||||
throw new ValidationException('Field name cannot be "Field"');
|
||||
}
|
||||
if (!$this->Sort && $this->ParentID) {
|
||||
$parentID = $this->ParentID;
|
||||
$this->Sort = EditableFormField::get()
|
||||
->filter('ParentID', $parentID)
|
||||
->max('Sort') + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$this->Sort && $this->ParentID) {
|
||||
$parentID = $this->ParentID;
|
||||
$this->Sort = EditableFormField::get()
|
||||
->filter('ParentID', $parentID)
|
||||
->max('Sort') + 1;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Generate a new non-conflicting Name value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateName()
|
||||
{
|
||||
do {
|
||||
// Generate a new random name after this class
|
||||
$class = get_class($this);
|
||||
$entropy = substr(sha1(uniqid()), 0, 5);
|
||||
$name = "{$class}_{$entropy}";
|
||||
|
||||
/**
|
||||
* Generate a new non-conflicting Name value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateName() {
|
||||
do {
|
||||
// Generate a new random name after this class
|
||||
$class = get_class($this);
|
||||
$entropy = substr(sha1(uniqid()), 0, 5);
|
||||
$name = "{$class}_{$entropy}";
|
||||
// Check if it conflicts
|
||||
$exists = EditableFormField::get()->filter('Name', $name)->count() > 0;
|
||||
} while ($exists);
|
||||
return $name;
|
||||
}
|
||||
|
||||
// Check if it conflicts
|
||||
$exists = EditableFormField::get()->filter('Name', $name)->count() > 0;
|
||||
} while($exists);
|
||||
return $name;
|
||||
}
|
||||
/**
|
||||
* Flag indicating that this field will set its own error message via data-msg='' attributes
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getSetsOwnError()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag indicating that this field will set its own error message via data-msg='' attributes
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getSetsOwnError() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether a user can delete this form field
|
||||
* based on whether they can edit the page
|
||||
*
|
||||
/**
|
||||
* Return whether a user can delete this form field
|
||||
* based on whether they can edit the page
|
||||
*
|
||||
* @param Member $member
|
||||
* @return bool
|
||||
*/
|
||||
public function canDelete($member = null) {
|
||||
return $this->canEdit($member);
|
||||
}
|
||||
* @return bool
|
||||
*/
|
||||
public function canDelete($member = null)
|
||||
{
|
||||
return $this->canEdit($member);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether a user can edit this form field
|
||||
* based on whether they can edit the page
|
||||
*
|
||||
/**
|
||||
* Return whether a user can edit this form field
|
||||
* based on whether they can edit the page
|
||||
*
|
||||
* @param Member $member
|
||||
* @return bool
|
||||
*/
|
||||
public function canEdit($member = null) {
|
||||
* @return bool
|
||||
*/
|
||||
public function canEdit($member = null)
|
||||
{
|
||||
$parent = $this->Parent();
|
||||
if($parent && $parent->exists()) {
|
||||
return $parent->canEdit($member) && !$this->isReadonly();
|
||||
} else if (!$this->exists() && Controller::has_curr()) {
|
||||
// This is for GridFieldOrderableRows support as it checks edit permissions on
|
||||
// singleton of the class. Allows editing of User Defined Form pages by
|
||||
// 'Content Authors' and those with permission to edit the UDF page. (ie. CanEditType/EditorGroups)
|
||||
// This is to restore User Forms 2.x backwards compatibility.
|
||||
$controller = Controller::curr();
|
||||
if ($controller && $controller instanceof CMSPageEditController)
|
||||
{
|
||||
$parent = $controller->getRecord($controller->currentPageID());
|
||||
// Only allow this behaviour on pages using UserFormFieldEditorExtension, such
|
||||
// as UserDefinedForm page type.
|
||||
if ($parent && $parent->hasExtension('UserFormFieldEditorExtension'))
|
||||
{
|
||||
return $parent->canEdit($member);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($parent && $parent->exists()) {
|
||||
return $parent->canEdit($member) && !$this->isReadonly();
|
||||
} elseif (!$this->exists() && Controller::has_curr()) {
|
||||
// This is for GridFieldOrderableRows support as it checks edit permissions on
|
||||
// singleton of the class. Allows editing of User Defined Form pages by
|
||||
// 'Content Authors' and those with permission to edit the UDF page. (ie. CanEditType/EditorGroups)
|
||||
// This is to restore User Forms 2.x backwards compatibility.
|
||||
$controller = Controller::curr();
|
||||
if ($controller && $controller instanceof CMSPageEditController) {
|
||||
$parent = $controller->getRecord($controller->currentPageID());
|
||||
// Only allow this behaviour on pages using UserFormFieldEditorExtension, such
|
||||
// as UserDefinedForm page type.
|
||||
if ($parent && $parent->hasExtension('UserFormFieldEditorExtension')) {
|
||||
return $parent->canEdit($member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to secure admin permissions
|
||||
return parent::canEdit($member);
|
||||
}
|
||||
return parent::canEdit($member);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether a user can view this form field
|
||||
@ -399,32 +406,34 @@ class EditableFormField extends DataObject {
|
||||
* @param Member $member
|
||||
* @return bool
|
||||
*/
|
||||
public function canView($member = null) {
|
||||
$parent = $this->Parent();
|
||||
if($parent && $parent->exists()) {
|
||||
return $parent->canView($member);
|
||||
}
|
||||
public function canView($member = null)
|
||||
{
|
||||
$parent = $this->Parent();
|
||||
if ($parent && $parent->exists()) {
|
||||
return $parent->canView($member);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 array $context Virtual parameter to allow context to be passed in to check
|
||||
* @return bool
|
||||
*/
|
||||
public function canCreate($member = null) {
|
||||
// Check parent page
|
||||
* @return bool
|
||||
*/
|
||||
public function canCreate($member = null)
|
||||
{
|
||||
// Check parent page
|
||||
$parent = $this->getCanCreateContext(func_get_args());
|
||||
if($parent) {
|
||||
if ($parent) {
|
||||
return $parent->canEdit($member);
|
||||
}
|
||||
|
||||
// Fall back to secure admin permissions
|
||||
return parent::canCreate($member);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to check the parent for this object
|
||||
@ -432,13 +441,14 @@ class EditableFormField extends DataObject {
|
||||
* @param array $args List of arguments passed to canCreate
|
||||
* @return SiteTree Parent page instance
|
||||
*/
|
||||
protected function getCanCreateContext($args) {
|
||||
protected function getCanCreateContext($args)
|
||||
{
|
||||
// Inspect second parameter to canCreate for a 'Parent' context
|
||||
if(isset($args[1]['Parent'])) {
|
||||
if (isset($args[1]['Parent'])) {
|
||||
return $args[1]['Parent'];
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
|
||||
@ -452,7 +462,8 @@ class EditableFormField extends DataObject {
|
||||
* @param Member $member
|
||||
* @return bool
|
||||
*/
|
||||
public function canPublish($member = null) {
|
||||
public function canPublish($member = null)
|
||||
{
|
||||
return $this->canEdit($member);
|
||||
}
|
||||
|
||||
@ -462,445 +473,483 @@ class EditableFormField extends DataObject {
|
||||
* @param Member $member
|
||||
* @return bool
|
||||
*/
|
||||
public function canUnpublish($member = null) {
|
||||
public function canUnpublish($member = null)
|
||||
{
|
||||
return $this->canDelete($member);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish this Form Field to the live site
|
||||
*
|
||||
* Wrapper for the {@link Versioned} publish function
|
||||
*/
|
||||
public function doPublish($fromStage, $toStage, $createNewVersion = false) {
|
||||
$this->publish($fromStage, $toStage, $createNewVersion);
|
||||
/**
|
||||
* Publish this Form Field to the live site
|
||||
*
|
||||
* Wrapper for the {@link Versioned} publish function
|
||||
*/
|
||||
public function doPublish($fromStage, $toStage, $createNewVersion = false)
|
||||
{
|
||||
$this->publish($fromStage, $toStage, $createNewVersion);
|
||||
|
||||
// Don't forget to publish the related custom rules...
|
||||
foreach ($this->DisplayRules() as $rule) {
|
||||
$rule->doPublish($fromStage, $toStage, $createNewVersion);
|
||||
}
|
||||
}
|
||||
// Don't forget to publish the related custom rules...
|
||||
foreach ($this->DisplayRules() as $rule) {
|
||||
$rule->doPublish($fromStage, $toStage, $createNewVersion);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete this field from a given stage
|
||||
*
|
||||
* Wrapper for the {@link Versioned} deleteFromStage function
|
||||
*/
|
||||
public function doDeleteFromStage($stage) {
|
||||
// Remove custom rules in this stage
|
||||
$rules = Versioned::get_by_stage('EditableCustomRule', $stage)
|
||||
->filter('ParentID', $this->ID);
|
||||
foreach ($rules as $rule) {
|
||||
$rule->deleteFromStage($stage);
|
||||
}
|
||||
/**
|
||||
* Delete this field from a given stage
|
||||
*
|
||||
* Wrapper for the {@link Versioned} deleteFromStage function
|
||||
*/
|
||||
public function doDeleteFromStage($stage)
|
||||
{
|
||||
// Remove custom rules in this stage
|
||||
$rules = Versioned::get_by_stage('EditableCustomRule', $stage)
|
||||
->filter('ParentID', $this->ID);
|
||||
foreach ($rules as $rule) {
|
||||
$rule->deleteFromStage($stage);
|
||||
}
|
||||
|
||||
// Remove record
|
||||
$this->deleteFromStage($stage);
|
||||
}
|
||||
// Remove record
|
||||
$this->deleteFromStage($stage);
|
||||
}
|
||||
|
||||
/**
|
||||
* checks wether record is new, copied from Sitetree
|
||||
*/
|
||||
function isNew() {
|
||||
if(empty($this->ID)) return true;
|
||||
/**
|
||||
* checks wether record is new, copied from Sitetree
|
||||
*/
|
||||
public function isNew()
|
||||
{
|
||||
if (empty($this->ID)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(is_numeric($this->ID)) return false;
|
||||
if (is_numeric($this->ID)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return stripos($this->ID, 'new') === 0;
|
||||
}
|
||||
return stripos($this->ID, 'new') === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if records is changed on stage
|
||||
* @return boolean
|
||||
*/
|
||||
public function getIsModifiedOnStage() {
|
||||
// new unsaved fields could be never be published
|
||||
if($this->isNew()) return false;
|
||||
/**
|
||||
* checks if records is changed on stage
|
||||
* @return boolean
|
||||
*/
|
||||
public function getIsModifiedOnStage()
|
||||
{
|
||||
// new unsaved fields could be never be published
|
||||
if ($this->isNew()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$stageVersion = Versioned::get_versionnumber_by_stage('EditableFormField', 'Stage', $this->ID);
|
||||
$liveVersion = Versioned::get_versionnumber_by_stage('EditableFormField', 'Live', $this->ID);
|
||||
$stageVersion = Versioned::get_versionnumber_by_stage('EditableFormField', 'Stage', $this->ID);
|
||||
$liveVersion = Versioned::get_versionnumber_by_stage('EditableFormField', 'Live', $this->ID);
|
||||
|
||||
return ($stageVersion && $stageVersion != $liveVersion);
|
||||
}
|
||||
return ($stageVersion && $stageVersion != $liveVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
public function getSettings() {
|
||||
Deprecation::notice('4.0', 'getSettings is deprecated');
|
||||
return (!empty($this->CustomSettings)) ? unserialize($this->CustomSettings) : array();
|
||||
}
|
||||
/**
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
public function getSettings()
|
||||
{
|
||||
Deprecation::notice('4.0', 'getSettings is deprecated');
|
||||
return (!empty($this->CustomSettings)) ? unserialize($this->CustomSettings) : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
public function setSettings($settings = array()) {
|
||||
Deprecation::notice('4.0', 'setSettings is deprecated');
|
||||
$this->CustomSettings = serialize($settings);
|
||||
}
|
||||
/**
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
public function setSettings($settings = array())
|
||||
{
|
||||
Deprecation::notice('4.0', 'setSettings is deprecated');
|
||||
$this->CustomSettings = serialize($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
public function setSetting($key, $value) {
|
||||
Deprecation::notice('4.0', "setSetting({$key}) is deprecated");
|
||||
$settings = $this->getSettings();
|
||||
$settings[$key] = $value;
|
||||
/**
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
public function setSetting($key, $value)
|
||||
{
|
||||
Deprecation::notice('4.0', "setSetting({$key}) is deprecated");
|
||||
$settings = $this->getSettings();
|
||||
$settings[$key] = $value;
|
||||
|
||||
$this->setSettings($settings);
|
||||
}
|
||||
$this->setSettings($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the allowed css classes for the extraClass custom setting
|
||||
*
|
||||
* @param array The permissible CSS classes to add
|
||||
*/
|
||||
public function setAllowedCss(array $allowed) {
|
||||
if (is_array($allowed)) {
|
||||
foreach ($allowed as $k => $v) {
|
||||
self::$allowed_css[$k] = (!is_null($v)) ? $v : $k;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Set the allowed css classes for the extraClass custom setting
|
||||
*
|
||||
* @param array The permissible CSS classes to add
|
||||
*/
|
||||
public function setAllowedCss(array $allowed)
|
||||
{
|
||||
if (is_array($allowed)) {
|
||||
foreach ($allowed as $k => $v) {
|
||||
self::$allowed_css[$k] = (!is_null($v)) ? $v : $k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
public function getSetting($setting) {
|
||||
Deprecation::notice("4.0", "getSetting({$setting}) is deprecated");
|
||||
/**
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
public function getSetting($setting)
|
||||
{
|
||||
Deprecation::notice("4.0", "getSetting({$setting}) is deprecated");
|
||||
|
||||
$settings = $this->getSettings();
|
||||
if(isset($settings) && count($settings) > 0) {
|
||||
if(isset($settings[$setting])) {
|
||||
return $settings[$setting];
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
$settings = $this->getSettings();
|
||||
if (isset($settings) && count($settings) > 0) {
|
||||
if (isset($settings[$setting])) {
|
||||
return $settings[$setting];
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to the icon for this field type, relative to the site root.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIcon() {
|
||||
return USERFORMS_DIR . '/images/' . strtolower($this->class) . '.png';
|
||||
}
|
||||
/**
|
||||
* Get the path to the icon for this field type, relative to the site root.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIcon()
|
||||
{
|
||||
return USERFORMS_DIR . '/images/' . strtolower($this->class) . '.png';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether or not this field has addable options
|
||||
* such as a dropdown field or radio set
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getHasAddableOptions() {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Return whether or not this field has addable options
|
||||
* such as a dropdown field or radio set
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getHasAddableOptions()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether or not this field needs to show the extra
|
||||
* options dropdown list
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function showExtraOptions() {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Return whether or not this field needs to show the extra
|
||||
* options dropdown list
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function showExtraOptions()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Title for rendering in the front-end (with XML values escaped)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEscapedTitle() {
|
||||
return Convert::raw2xml($this->Title);
|
||||
}
|
||||
/**
|
||||
* Returns the Title for rendering in the front-end (with XML values escaped)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEscapedTitle()
|
||||
{
|
||||
return Convert::raw2xml($this->Title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the numeric indicator (1.1.2) that represents it's nesting value
|
||||
*
|
||||
* Only useful for fields attached to a current page, and that contain other fields such as pages
|
||||
* or groups
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFieldNumber() {
|
||||
// Check if exists
|
||||
if(!$this->exists()) {
|
||||
return null;
|
||||
}
|
||||
// Check parent
|
||||
$form = $this->Parent();
|
||||
if(!$form || !$form->exists() || !($fields = $form->Fields())) {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Find the numeric indicator (1.1.2) that represents it's nesting value
|
||||
*
|
||||
* Only useful for fields attached to a current page, and that contain other fields such as pages
|
||||
* or groups
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFieldNumber()
|
||||
{
|
||||
// Check if exists
|
||||
if (!$this->exists()) {
|
||||
return null;
|
||||
}
|
||||
// Check parent
|
||||
$form = $this->Parent();
|
||||
if (!$form || !$form->exists() || !($fields = $form->Fields())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$prior = 0; // Number of prior group at this level
|
||||
$stack = array(); // Current stack of nested groups, where the top level = the page
|
||||
foreach($fields->map('ID', 'ClassName') as $id => $className) {
|
||||
if($className === 'EditableFormStep') {
|
||||
$priorPage = empty($stack) ? $prior : $stack[0];
|
||||
$stack = array($priorPage + 1);
|
||||
$prior = 0;
|
||||
} elseif($className === 'EditableFieldGroup') {
|
||||
$stack[] = $prior + 1;
|
||||
$prior = 0;
|
||||
} elseif($className === 'EditableFieldGroupEnd') {
|
||||
$prior = array_pop($stack);
|
||||
}
|
||||
if($id == $this->ID) {
|
||||
return implode('.', $stack);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
$prior = 0; // Number of prior group at this level
|
||||
$stack = array(); // Current stack of nested groups, where the top level = the page
|
||||
foreach ($fields->map('ID', 'ClassName') as $id => $className) {
|
||||
if ($className === 'EditableFormStep') {
|
||||
$priorPage = empty($stack) ? $prior : $stack[0];
|
||||
$stack = array($priorPage + 1);
|
||||
$prior = 0;
|
||||
} elseif ($className === 'EditableFieldGroup') {
|
||||
$stack[] = $prior + 1;
|
||||
$prior = 0;
|
||||
} elseif ($className === 'EditableFieldGroupEnd') {
|
||||
$prior = array_pop($stack);
|
||||
}
|
||||
if ($id == $this->ID) {
|
||||
return implode('.', $stack);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getCMSTitle() {
|
||||
return $this->i18n_singular_name() . ' (' . $this->Title . ')';
|
||||
}
|
||||
public function getCMSTitle()
|
||||
{
|
||||
return $this->i18n_singular_name() . ' (' . $this->Title . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
public function getFieldName($field = false) {
|
||||
Deprecation::notice('4.0', "getFieldName({$field}) is deprecated");
|
||||
return ($field) ? "Fields[".$this->ID."][".$field."]" : "Fields[".$this->ID."]";
|
||||
}
|
||||
/**
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
public function getFieldName($field = false)
|
||||
{
|
||||
Deprecation::notice('4.0', "getFieldName({$field}) is deprecated");
|
||||
return ($field) ? "Fields[".$this->ID."][".$field."]" : "Fields[".$this->ID."]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
public function getSettingName($field) {
|
||||
Deprecation::notice('4.0', "getSettingName({$field}) is deprecated");
|
||||
$name = $this->getFieldName('CustomSettings');
|
||||
/**
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
public function getSettingName($field)
|
||||
{
|
||||
Deprecation::notice('4.0', "getSettingName({$field}) is deprecated");
|
||||
$name = $this->getFieldName('CustomSettings');
|
||||
|
||||
return $name . '[' . $field .']';
|
||||
}
|
||||
return $name . '[' . $field .']';
|
||||
}
|
||||
|
||||
/**
|
||||
* Append custom validation fields to the default 'Validation'
|
||||
* section in the editable options view
|
||||
*
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getFieldValidationOptions() {
|
||||
$fields = new FieldList(
|
||||
CheckboxField::create('Required', _t('EditableFormField.REQUIRED', 'Is this field Required?'))
|
||||
->setDescription(_t('EditableFormField.REQUIRED_DESCRIPTION', 'Please note that conditional fields can\'t be required')),
|
||||
TextField::create('CustomErrorMessage', _t('EditableFormField.CUSTOMERROR','Custom Error Message'))
|
||||
);
|
||||
/**
|
||||
* Append custom validation fields to the default 'Validation'
|
||||
* section in the editable options view
|
||||
*
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getFieldValidationOptions()
|
||||
{
|
||||
$fields = new FieldList(
|
||||
CheckboxField::create('Required', _t('EditableFormField.REQUIRED', 'Is this field Required?'))
|
||||
->setDescription(_t('EditableFormField.REQUIRED_DESCRIPTION', 'Please note that conditional fields can\'t be required')),
|
||||
TextField::create('CustomErrorMessage', _t('EditableFormField.CUSTOMERROR', 'Custom Error Message'))
|
||||
);
|
||||
|
||||
$this->extend('updateFieldValidationOptions', $fields);
|
||||
$this->extend('updateFieldValidationOptions', $fields);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a FormField to appear on the front end. Implement on
|
||||
* your subclass.
|
||||
*
|
||||
* @return FormField
|
||||
*/
|
||||
public function getFormField() {
|
||||
user_error("Please implement a getFormField() on your EditableFormClass ". $this->ClassName, E_USER_ERROR);
|
||||
}
|
||||
/**
|
||||
* Return a FormField to appear on the front end. Implement on
|
||||
* your subclass.
|
||||
*
|
||||
* @return FormField
|
||||
*/
|
||||
public function getFormField()
|
||||
{
|
||||
user_error("Please implement a getFormField() on your EditableFormClass ". $this->ClassName, E_USER_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a formfield with extensions
|
||||
*
|
||||
* @param FormField $field
|
||||
*/
|
||||
public function doUpdateFormField($field) {
|
||||
$this->extend('beforeUpdateFormField', $field);
|
||||
$this->updateFormField($field);
|
||||
$this->extend('afterUpdateFormField', $field);
|
||||
}
|
||||
/**
|
||||
* Updates a formfield with extensions
|
||||
*
|
||||
* @param FormField $field
|
||||
*/
|
||||
public function doUpdateFormField($field)
|
||||
{
|
||||
$this->extend('beforeUpdateFormField', $field);
|
||||
$this->updateFormField($field);
|
||||
$this->extend('afterUpdateFormField', $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a formfield with the additional metadata specified by this field
|
||||
*
|
||||
* @param FormField $field
|
||||
*/
|
||||
protected function updateFormField($field) {
|
||||
// set the error / formatting messages
|
||||
$field->setCustomValidationMessage($this->getErrorMessage()->RAW());
|
||||
/**
|
||||
* Updates a formfield with the additional metadata specified by this field
|
||||
*
|
||||
* @param FormField $field
|
||||
*/
|
||||
protected function updateFormField($field)
|
||||
{
|
||||
// set the error / formatting messages
|
||||
$field->setCustomValidationMessage($this->getErrorMessage()->RAW());
|
||||
|
||||
// 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));
|
||||
}
|
||||
// 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 is required add some
|
||||
if($this->Required) {
|
||||
// Required validation can conflict so add the Required validation messages as input attributes
|
||||
$errorMessage = $this->getErrorMessage()->HTML();
|
||||
$field->addExtraClass('requiredField');
|
||||
$field->setAttribute('data-rule-required', 'true');
|
||||
$field->setAttribute('data-msg-required', $errorMessage);
|
||||
// if this field is required add some
|
||||
if ($this->Required) {
|
||||
// Required validation can conflict so add the Required validation messages as input attributes
|
||||
$errorMessage = $this->getErrorMessage()->HTML();
|
||||
$field->addExtraClass('requiredField');
|
||||
$field->setAttribute('data-rule-required', 'true');
|
||||
$field->setAttribute('data-msg-required', $errorMessage);
|
||||
|
||||
if($identifier = UserDefinedForm::config()->required_identifier) {
|
||||
$title = $field->Title() . " <span class='required-identifier'>". $identifier . "</span>";
|
||||
$field->setTitle($title);
|
||||
}
|
||||
}
|
||||
if ($identifier = UserDefinedForm::config()->required_identifier) {
|
||||
$title = $field->Title() . " <span class='required-identifier'>". $identifier . "</span>";
|
||||
$field->setTitle($title);
|
||||
}
|
||||
}
|
||||
|
||||
// if this field has an extra class
|
||||
if($this->ExtraClass) {
|
||||
$field->addExtraClass($this->ExtraClass);
|
||||
}
|
||||
}
|
||||
// if this field has an extra class
|
||||
if ($this->ExtraClass) {
|
||||
$field->addExtraClass($this->ExtraClass);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the instance of the submission field class
|
||||
*
|
||||
* @return SubmittedFormField
|
||||
*/
|
||||
public function getSubmittedFormField() {
|
||||
return new SubmittedFormField();
|
||||
}
|
||||
/**
|
||||
* Return the instance of the submission field class
|
||||
*
|
||||
* @return SubmittedFormField
|
||||
*/
|
||||
public function getSubmittedFormField()
|
||||
{
|
||||
return new SubmittedFormField();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show this form field (and its related value) in the reports and in emails.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function showInReports() {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Show this form field (and its related value) in the reports and in emails.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function showInReports()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the error message for this field. Either uses the custom
|
||||
* one (if provided) or the default SilverStripe message
|
||||
*
|
||||
* @return Varchar
|
||||
*/
|
||||
public function getErrorMessage() {
|
||||
$title = strip_tags("'". ($this->Title ? $this->Title : $this->Name) . "'");
|
||||
$standard = sprintf(_t('Form.FIELDISREQUIRED', '%s is required').'.', $title);
|
||||
/**
|
||||
* Return the error message for this field. Either uses the custom
|
||||
* one (if provided) or the default SilverStripe message
|
||||
*
|
||||
* @return Varchar
|
||||
*/
|
||||
public function getErrorMessage()
|
||||
{
|
||||
$title = strip_tags("'". ($this->Title ? $this->Title : $this->Name) . "'");
|
||||
$standard = sprintf(_t('Form.FIELDISREQUIRED', '%s is required').'.', $title);
|
||||
|
||||
// only use CustomErrorMessage if it has a non empty value
|
||||
$errorMessage = (!empty($this->CustomErrorMessage)) ? $this->CustomErrorMessage : $standard;
|
||||
// only use CustomErrorMessage if it has a non empty value
|
||||
$errorMessage = (!empty($this->CustomErrorMessage)) ? $this->CustomErrorMessage : $standard;
|
||||
|
||||
return DBField::create_field('Varchar', $errorMessage);
|
||||
}
|
||||
return DBField::create_field('Varchar', $errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by UserFormUpgradeService to migrate settings specific to this field from CustomSettings
|
||||
* to the field proper
|
||||
*
|
||||
* @param array $data Unserialised data
|
||||
*/
|
||||
public function migrateSettings($data) {
|
||||
// Map 'Show' / 'Hide' to boolean
|
||||
if(isset($data['ShowOnLoad'])) {
|
||||
$this->ShowOnLoad = $data['ShowOnLoad'] === '' || ($data['ShowOnLoad'] && $data['ShowOnLoad'] !== 'Hide');
|
||||
unset($data['ShowOnLoad']);
|
||||
}
|
||||
/**
|
||||
* Invoked by UserFormUpgradeService to migrate settings specific to this field from CustomSettings
|
||||
* to the field proper
|
||||
*
|
||||
* @param array $data Unserialised data
|
||||
*/
|
||||
public function migrateSettings($data)
|
||||
{
|
||||
// Map 'Show' / 'Hide' to boolean
|
||||
if (isset($data['ShowOnLoad'])) {
|
||||
$this->ShowOnLoad = $data['ShowOnLoad'] === '' || ($data['ShowOnLoad'] && $data['ShowOnLoad'] !== 'Hide');
|
||||
unset($data['ShowOnLoad']);
|
||||
}
|
||||
|
||||
// Migrate all other settings
|
||||
foreach($data as $key => $value) {
|
||||
if($this->hasField($key)) {
|
||||
$this->setField($key, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Migrate all other settings
|
||||
foreach ($data as $key => $value) {
|
||||
if ($this->hasField($key)) {
|
||||
$this->setField($key, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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'));
|
||||
}
|
||||
/**
|
||||
* 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'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JS expression for selecting the holder for this field
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSelectorHolder() {
|
||||
return "$(\"#{$this->Name}\")";
|
||||
}
|
||||
/**
|
||||
* Get the JS expression for selecting the holder for this field
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSelectorHolder()
|
||||
{
|
||||
return "$(\"#{$this->Name}\")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the JS expression for selecting the value for this field
|
||||
*
|
||||
* @param EditableCustomRule $rule Custom rule this selector will be used with
|
||||
* @param bool $forOnLoad Set to true if this will be invoked on load
|
||||
*/
|
||||
public function getSelectorField(EditableCustomRule $rule, $forOnLoad = false) {
|
||||
return "$(\"input[name='{$this->Name}']\")";
|
||||
}
|
||||
/**
|
||||
* Gets the JS expression for selecting the value for this field
|
||||
*
|
||||
* @param EditableCustomRule $rule Custom rule this selector will be used with
|
||||
* @param bool $forOnLoad Set to true if this will be invoked on load
|
||||
*/
|
||||
public function getSelectorField(EditableCustomRule $rule, $forOnLoad = false)
|
||||
{
|
||||
return "$(\"input[name='{$this->Name}']\")";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the list of classes that can be selected and used as data-values
|
||||
*
|
||||
* @param $includeLiterals Set to false to exclude non-data fields
|
||||
* @return array
|
||||
*/
|
||||
public function getEditableFieldClasses($includeLiterals = true) {
|
||||
$classes = ClassInfo::getValidSubClasses('EditableFormField');
|
||||
/**
|
||||
* Get the list of classes that can be selected and used as data-values
|
||||
*
|
||||
* @param $includeLiterals Set to false to exclude non-data fields
|
||||
* @return array
|
||||
*/
|
||||
public function getEditableFieldClasses($includeLiterals = true)
|
||||
{
|
||||
$classes = ClassInfo::getValidSubClasses('EditableFormField');
|
||||
|
||||
// Remove classes we don't want to display in the dropdown.
|
||||
$editableFieldClasses = array();
|
||||
foreach ($classes as $class) {
|
||||
// Skip abstract / hidden classes
|
||||
if(Config::inst()->get($class, 'abstract', Config::UNINHERITED) || Config::inst()->get($class, 'hidden')
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
// Remove classes we don't want to display in the dropdown.
|
||||
$editableFieldClasses = array();
|
||||
foreach ($classes as $class) {
|
||||
// Skip abstract / hidden classes
|
||||
if (Config::inst()->get($class, 'abstract', Config::UNINHERITED) || Config::inst()->get($class, 'hidden')
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!$includeLiterals && Config::inst()->get($class, 'literal')) {
|
||||
continue;
|
||||
}
|
||||
if (!$includeLiterals && Config::inst()->get($class, 'literal')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$singleton = singleton($class);
|
||||
if(!$singleton->canCreate()) {
|
||||
continue;
|
||||
}
|
||||
$singleton = singleton($class);
|
||||
if (!$singleton->canCreate()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$editableFieldClasses[$class] = $singleton->i18n_singular_name();
|
||||
}
|
||||
$editableFieldClasses[$class] = $singleton->i18n_singular_name();
|
||||
}
|
||||
|
||||
asort($editableFieldClasses);
|
||||
return $editableFieldClasses;
|
||||
}
|
||||
asort($editableFieldClasses);
|
||||
return $editableFieldClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EditableFormFieldValidator
|
||||
*/
|
||||
public function getCMSValidator() {
|
||||
return EditableFormFieldValidator::create()
|
||||
->setRecord($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine effective display rules for this field.
|
||||
*
|
||||
* @return SS_List
|
||||
*/
|
||||
public function EffectiveDisplayRules() {
|
||||
if($this->Required) {
|
||||
return new ArrayList();
|
||||
}
|
||||
return $this->DisplayRules();
|
||||
}
|
||||
/**
|
||||
* @return EditableFormFieldValidator
|
||||
*/
|
||||
public function getCMSValidator()
|
||||
{
|
||||
return EditableFormFieldValidator::create()
|
||||
->setRecord($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine effective display rules for this field.
|
||||
*
|
||||
* @return SS_List
|
||||
*/
|
||||
public function EffectiveDisplayRules()
|
||||
{
|
||||
if ($this->Required) {
|
||||
return new ArrayList();
|
||||
}
|
||||
return $this->DisplayRules();
|
||||
}
|
||||
}
|
||||
|
@ -1,61 +1,65 @@
|
||||
<?php
|
||||
|
||||
class EditableFormFieldValidator extends RequiredFields {
|
||||
class EditableFormFieldValidator extends RequiredFields
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* @var EditableFormField
|
||||
*/
|
||||
protected $record = null;
|
||||
/**
|
||||
*
|
||||
* @var EditableFormField
|
||||
*/
|
||||
protected $record = null;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param EditableFormField $record
|
||||
* @return $this
|
||||
*/
|
||||
public function setRecord($record) {
|
||||
$this->record = $record;
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param EditableFormField $record
|
||||
* @return $this
|
||||
*/
|
||||
public function setRecord($record)
|
||||
{
|
||||
$this->record = $record;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return EditableFormField
|
||||
*/
|
||||
public function getRecord() {
|
||||
return $this->record;
|
||||
}
|
||||
/*
|
||||
* @return EditableFormField
|
||||
*/
|
||||
public function getRecord()
|
||||
{
|
||||
return $this->record;
|
||||
}
|
||||
|
||||
|
||||
public function php($data) {
|
||||
if(!parent::php($data)) {
|
||||
return false;
|
||||
}
|
||||
public function php($data)
|
||||
{
|
||||
if (!parent::php($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip unsaved records
|
||||
if(!$this->record || !$this->record->exists()) {
|
||||
return true;
|
||||
}
|
||||
// Skip unsaved records
|
||||
if (!$this->record || !$this->record->exists()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip validation if not required
|
||||
if(empty($data['Required'])) {
|
||||
return;
|
||||
}
|
||||
// Skip validation if not required
|
||||
if (empty($data['Required'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip validation if no rules
|
||||
$count = EditableCustomRule::get()->filter('ParentID', $this->record->ID)->count();
|
||||
if($count == 0) {
|
||||
return true;
|
||||
}
|
||||
// Skip validation if no rules
|
||||
$count = EditableCustomRule::get()->filter('ParentID', $this->record->ID)->count();
|
||||
if ($count == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Both required = true and rules > 0 should error
|
||||
$this->validationError(
|
||||
'Required_Error',
|
||||
_t(
|
||||
"EditableFormFieldValidator.REQUIRED_ERROR",
|
||||
"Form fields cannot be required and have conditional display rules."
|
||||
),
|
||||
'error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// Both required = true and rules > 0 should error
|
||||
$this->validationError(
|
||||
'Required_Error',
|
||||
_t(
|
||||
"EditableFormFieldValidator.REQUIRED_ERROR",
|
||||
"Form fields cannot be required and have conditional display rules."
|
||||
),
|
||||
'error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -5,89 +5,97 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class EditableFormHeading extends EditableFormField {
|
||||
class EditableFormHeading extends EditableFormField
|
||||
{
|
||||
|
||||
private static $singular_name = 'Heading';
|
||||
private static $singular_name = 'Heading';
|
||||
|
||||
private static $plural_name = 'Headings';
|
||||
private static $plural_name = 'Headings';
|
||||
|
||||
private static $literal = true;
|
||||
private static $literal = true;
|
||||
|
||||
private static $db = array(
|
||||
'Level' => 'Int(3)', // From CustomSettings
|
||||
'HideFromReports' => 'Boolean(0)' // from CustomSettings
|
||||
);
|
||||
private static $db = array(
|
||||
'Level' => 'Int(3)', // From CustomSettings
|
||||
'HideFromReports' => 'Boolean(0)' // from CustomSettings
|
||||
);
|
||||
|
||||
private static $defaults = array(
|
||||
'Level' => 3,
|
||||
'HideFromReports' => false
|
||||
);
|
||||
private static $defaults = array(
|
||||
'Level' => 3,
|
||||
'HideFromReports' => false
|
||||
);
|
||||
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields() {
|
||||
$fields = parent::getCMSFields();
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
$fields = parent::getCMSFields();
|
||||
|
||||
$fields->removeByName(array('Default', 'Validation', 'RightTitle'));
|
||||
$fields->removeByName(array('Default', 'Validation', 'RightTitle'));
|
||||
|
||||
$levels = array(
|
||||
'1' => '1',
|
||||
'2' => '2',
|
||||
'3' => '3',
|
||||
'4' => '4',
|
||||
'5' => '5',
|
||||
'6' => '6'
|
||||
);
|
||||
$levels = array(
|
||||
'1' => '1',
|
||||
'2' => '2',
|
||||
'3' => '3',
|
||||
'4' => '4',
|
||||
'5' => '5',
|
||||
'6' => '6'
|
||||
);
|
||||
|
||||
$fields->addFieldsToTab('Root.Main', array(
|
||||
DropdownField::create(
|
||||
'Level',
|
||||
_t('EditableFormHeading.LEVEL', 'Select Heading Level'),
|
||||
$levels
|
||||
),
|
||||
CheckboxField::create(
|
||||
'HideFromReports',
|
||||
_t('EditableLiteralField.HIDEFROMREPORT', 'Hide from reports?')
|
||||
)
|
||||
));
|
||||
$fields->addFieldsToTab('Root.Main', array(
|
||||
DropdownField::create(
|
||||
'Level',
|
||||
_t('EditableFormHeading.LEVEL', 'Select Heading Level'),
|
||||
$levels
|
||||
),
|
||||
CheckboxField::create(
|
||||
'HideFromReports',
|
||||
_t('EditableLiteralField.HIDEFROMREPORT', 'Hide from reports?')
|
||||
)
|
||||
));
|
||||
|
||||
return $fields;
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function getFormField() {
|
||||
$labelField = new HeaderField($this->Name, $this->EscapedTitle, $this->Level);
|
||||
$labelField->addExtraClass('FormHeading');
|
||||
$labelField->setAttribute('data-id', $this->Name);
|
||||
$this->doUpdateFormField($labelField);
|
||||
return $labelField;
|
||||
}
|
||||
public function getFormField()
|
||||
{
|
||||
$labelField = new HeaderField($this->Name, $this->EscapedTitle, $this->Level);
|
||||
$labelField->addExtraClass('FormHeading');
|
||||
$labelField->setAttribute('data-id', $this->Name);
|
||||
$this->doUpdateFormField($labelField);
|
||||
return $labelField;
|
||||
}
|
||||
|
||||
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($this->ExtraClass) {
|
||||
$field->addExtraClass($this->ExtraClass);
|
||||
}
|
||||
}
|
||||
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 ($this->ExtraClass) {
|
||||
$field->addExtraClass($this->ExtraClass);
|
||||
}
|
||||
}
|
||||
|
||||
public function showInReports() {
|
||||
return !$this->HideFromReports;
|
||||
}
|
||||
public function showInReports()
|
||||
{
|
||||
return !$this->HideFromReports;
|
||||
}
|
||||
|
||||
public function getFieldValidationOptions() {
|
||||
return false;
|
||||
}
|
||||
public function getFieldValidationOptions()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getSelectorHolder() {
|
||||
return "$(\":header[data-id='{$this->Name}']\")";
|
||||
}
|
||||
public function getSelectorHolder()
|
||||
{
|
||||
return "$(\":header[data-id='{$this->Name}']\")";
|
||||
}
|
||||
|
||||
public function getLevel() {
|
||||
return $this->getField('Level') ?: 3;
|
||||
}
|
||||
public function getLevel()
|
||||
{
|
||||
return $this->getField('Level') ?: 3;
|
||||
}
|
||||
}
|
||||
|
@ -4,83 +4,91 @@
|
||||
*
|
||||
* @package userforms
|
||||
*/
|
||||
class EditableFormStep extends EditableFormField {
|
||||
class EditableFormStep extends EditableFormField
|
||||
{
|
||||
|
||||
private static $singular_name = 'Page Break';
|
||||
private static $singular_name = 'Page Break';
|
||||
|
||||
private static $plural_name = 'Page Breaks';
|
||||
private static $plural_name = 'Page Breaks';
|
||||
|
||||
/**
|
||||
* Disable selection of step class
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $hidden = true;
|
||||
/**
|
||||
* Disable selection of step class
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $hidden = true;
|
||||
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields() {
|
||||
$fields = parent::getCMSFields();
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
$fields = parent::getCMSFields();
|
||||
|
||||
$fields->removeByName(array('MergeField', 'Default', 'Validation', 'RightTitle'));
|
||||
$fields->removeByName(array('MergeField', 'Default', 'Validation', 'RightTitle'));
|
||||
|
||||
return $fields;
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FormField
|
||||
*/
|
||||
public function getFormField() {
|
||||
$field = UserFormsStepField::create()
|
||||
->setName($this->Name)
|
||||
->setTitle($this->EscapedTitle);
|
||||
$this->doUpdateFormField($field);
|
||||
return $field;
|
||||
}
|
||||
/**
|
||||
* @return FormField
|
||||
*/
|
||||
public function getFormField()
|
||||
{
|
||||
$field = UserFormsStepField::create()
|
||||
->setName($this->Name)
|
||||
->setTitle($this->EscapedTitle);
|
||||
$this->doUpdateFormField($field);
|
||||
return $field;
|
||||
}
|
||||
|
||||
protected function updateFormField($field) {
|
||||
// if this field has an extra class
|
||||
if($this->ExtraClass) {
|
||||
$field->addExtraClass($this->ExtraClass);
|
||||
}
|
||||
}
|
||||
protected function updateFormField($field)
|
||||
{
|
||||
// if this field has an extra class
|
||||
if ($this->ExtraClass) {
|
||||
$field->addExtraClass($this->ExtraClass);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function showInReports() {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function showInReports()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getInlineClassnameField($column, $fieldClasses) {
|
||||
return new LabelField(
|
||||
$column,
|
||||
$this->CMSTitle
|
||||
);
|
||||
}
|
||||
public function getInlineClassnameField($column, $fieldClasses)
|
||||
{
|
||||
return new LabelField(
|
||||
$column,
|
||||
$this->CMSTitle
|
||||
);
|
||||
}
|
||||
|
||||
public function getCMSTitle() {
|
||||
$title = $this->getFieldNumber()
|
||||
?: $this->Title
|
||||
?: '';
|
||||
public function getCMSTitle()
|
||||
{
|
||||
$title = $this->getFieldNumber()
|
||||
?: $this->Title
|
||||
?: '';
|
||||
|
||||
return _t(
|
||||
'EditableFormStep.STEP_TITLE',
|
||||
'Page {page}',
|
||||
array(
|
||||
'page' => $title
|
||||
)
|
||||
);
|
||||
}
|
||||
return _t(
|
||||
'EditableFormStep.STEP_TITLE',
|
||||
'Page {page}',
|
||||
array(
|
||||
'page' => $title
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JS expression for selecting the holder for this field
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSelectorHolder() {
|
||||
return "$(\".step-button-wrapper[data-for='{$this->Name}']\")";
|
||||
}
|
||||
/**
|
||||
* Get the JS expression for selecting the holder for this field
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSelectorHolder()
|
||||
{
|
||||
return "$(\".step-button-wrapper[data-for='{$this->Name}']\")";
|
||||
}
|
||||
}
|
||||
|
@ -7,142 +7,154 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class EditableLiteralField extends EditableFormField {
|
||||
class EditableLiteralField extends EditableFormField
|
||||
{
|
||||
|
||||
private static $singular_name = 'HTML Block';
|
||||
private static $singular_name = 'HTML Block';
|
||||
|
||||
private static $plural_name = 'HTML Blocks';
|
||||
private static $plural_name = 'HTML Blocks';
|
||||
|
||||
/**
|
||||
* Mark as literal only
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $literal = true;
|
||||
/**
|
||||
* Mark as literal only
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $literal = true;
|
||||
|
||||
/**
|
||||
* Get the name of the editor config to use for HTML sanitisation. Defaults to the active config.
|
||||
*
|
||||
* @var string
|
||||
* @config
|
||||
*/
|
||||
private static $editor_config = null;
|
||||
/**
|
||||
* Get the name of the editor config to use for HTML sanitisation. Defaults to the active config.
|
||||
*
|
||||
* @var string
|
||||
* @config
|
||||
*/
|
||||
private static $editor_config = null;
|
||||
|
||||
private static $db = array(
|
||||
'Content' => 'HTMLText', // From CustomSettings
|
||||
'HideFromReports' => 'Boolean(0)', // from CustomSettings
|
||||
'HideLabel' => 'Boolean(0)'
|
||||
);
|
||||
private static $db = array(
|
||||
'Content' => 'HTMLText', // From CustomSettings
|
||||
'HideFromReports' => 'Boolean(0)', // from CustomSettings
|
||||
'HideLabel' => 'Boolean(0)'
|
||||
);
|
||||
|
||||
private static $defaults = array(
|
||||
'HideFromReports' => false
|
||||
);
|
||||
private static $defaults = array(
|
||||
'HideFromReports' => false
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns the {@see HtmlEditorConfig} instance to use for sanitisation
|
||||
*
|
||||
* @return HtmlEditorConfig
|
||||
*/
|
||||
protected function getEditorConfig() {
|
||||
$editorConfig = $this->config()->editor_config;
|
||||
if($editorConfig) return HtmlEditorConfig::get($editorConfig);
|
||||
return HtmlEditorConfig::get_active();
|
||||
}
|
||||
/**
|
||||
* Returns the {@see HtmlEditorConfig} instance to use for sanitisation
|
||||
*
|
||||
* @return HtmlEditorConfig
|
||||
*/
|
||||
protected function getEditorConfig()
|
||||
{
|
||||
$editorConfig = $this->config()->editor_config;
|
||||
if ($editorConfig) {
|
||||
return HtmlEditorConfig::get($editorConfig);
|
||||
}
|
||||
return HtmlEditorConfig::get_active();
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely sanitise html content, if enabled
|
||||
*
|
||||
* @param string $content Raw html
|
||||
* @return string Safely sanitised html
|
||||
*/
|
||||
protected function sanitiseContent($content) {
|
||||
// Check if sanitisation is enabled
|
||||
if(!HtmlEditorField::config()->sanitise_server_side) return $content;
|
||||
/**
|
||||
* Safely sanitise html content, if enabled
|
||||
*
|
||||
* @param string $content Raw html
|
||||
* @return string Safely sanitised html
|
||||
*/
|
||||
protected function sanitiseContent($content)
|
||||
{
|
||||
// Check if sanitisation is enabled
|
||||
if (!HtmlEditorField::config()->sanitise_server_side) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
// Perform sanitisation
|
||||
$htmlValue = Injector::inst()->create('HTMLValue', $content);
|
||||
$santiser = Injector::inst()->create('HtmlEditorSanitiser', $this->getEditorConfig());
|
||||
$santiser->sanitise($htmlValue);
|
||||
return $htmlValue->getContent();
|
||||
}
|
||||
// Perform sanitisation
|
||||
$htmlValue = Injector::inst()->create('HTMLValue', $content);
|
||||
$santiser = Injector::inst()->create('HtmlEditorSanitiser', $this->getEditorConfig());
|
||||
$santiser->sanitise($htmlValue);
|
||||
return $htmlValue->getContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get HTML Content of this literal field
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent() {
|
||||
// Apply html editor sanitisation rules
|
||||
$content = $this->getField('Content');
|
||||
return $this->sanitiseContent($content);
|
||||
}
|
||||
/**
|
||||
* Get HTML Content of this literal field
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
// Apply html editor sanitisation rules
|
||||
$content = $this->getField('Content');
|
||||
return $this->sanitiseContent($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the content with the given value
|
||||
*
|
||||
* @param string $content
|
||||
*/
|
||||
public function setContent($content) {
|
||||
// Apply html editor sanitisation rules
|
||||
$content = $this->sanitiseContent($content);
|
||||
$this->setField('Content', $content);
|
||||
}
|
||||
/**
|
||||
* Set the content with the given value
|
||||
*
|
||||
* @param string $content
|
||||
*/
|
||||
public function setContent($content)
|
||||
{
|
||||
// Apply html editor sanitisation rules
|
||||
$content = $this->sanitiseContent($content);
|
||||
$this->setField('Content', $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields() {
|
||||
$fields = parent::getCMSFields();
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
$fields = parent::getCMSFields();
|
||||
|
||||
$fields->removeByName(array('Default', 'Validation', 'RightTitle'));
|
||||
$fields->removeByName(array('Default', 'Validation', 'RightTitle'));
|
||||
|
||||
$fields->addFieldsToTab('Root.Main', array(
|
||||
HTMLEditorField::create('Content', _t('EditableLiteralField.CONTENT', 'HTML'))
|
||||
->setRows(4)
|
||||
->setColumns(20),
|
||||
CheckboxField::create(
|
||||
'HideFromReports',
|
||||
_t('EditableLiteralField.HIDEFROMREPORT', 'Hide from reports?')
|
||||
),
|
||||
CheckboxField::create(
|
||||
'HideLabel',
|
||||
_t('EditableLiteralField.HIDELABEL', "Hide 'Title' label on frontend?")
|
||||
)
|
||||
));
|
||||
$fields->addFieldsToTab('Root.Main', array(
|
||||
HTMLEditorField::create('Content', _t('EditableLiteralField.CONTENT', 'HTML'))
|
||||
->setRows(4)
|
||||
->setColumns(20),
|
||||
CheckboxField::create(
|
||||
'HideFromReports',
|
||||
_t('EditableLiteralField.HIDEFROMREPORT', 'Hide from reports?')
|
||||
),
|
||||
CheckboxField::create(
|
||||
'HideLabel',
|
||||
_t('EditableLiteralField.HIDELABEL', "Hide 'Title' label on frontend?")
|
||||
)
|
||||
));
|
||||
|
||||
return $fields;
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function getFormField() {
|
||||
// Build label and css classes
|
||||
$label = '';
|
||||
$classes = $this->ExtraClass;
|
||||
if(empty($this->Title) || $this->HideLabel) {
|
||||
$classes .= " nolabel";
|
||||
} else {
|
||||
$label = "<label class='left'>{$this->EscapedTitle}</label>";
|
||||
}
|
||||
public function getFormField()
|
||||
{
|
||||
// Build label and css classes
|
||||
$label = '';
|
||||
$classes = $this->ExtraClass;
|
||||
if (empty($this->Title) || $this->HideLabel) {
|
||||
$classes .= " nolabel";
|
||||
} else {
|
||||
$label = "<label class='left'>{$this->EscapedTitle}</label>";
|
||||
}
|
||||
|
||||
$field = new LiteralField(
|
||||
"LiteralField[{$this->ID}]",
|
||||
sprintf(
|
||||
"<div id='%s' class='field text %s'>
|
||||
$field = new LiteralField(
|
||||
"LiteralField[{$this->ID}]",
|
||||
sprintf(
|
||||
"<div id='%s' class='field text %s'>
|
||||
%s
|
||||
<div class='middleColumn literalFieldArea'>%s</div>".
|
||||
"</div>",
|
||||
Convert::raw2htmlname($this->Name),
|
||||
Convert::raw2att($classes),
|
||||
$label,
|
||||
$this->Content
|
||||
)
|
||||
);
|
||||
"</div>",
|
||||
Convert::raw2htmlname($this->Name),
|
||||
Convert::raw2att($classes),
|
||||
$label,
|
||||
$this->Content
|
||||
)
|
||||
);
|
||||
|
||||
// When dealing with literal fields there is no further customisation that can be added at this point
|
||||
return $field;
|
||||
}
|
||||
// When dealing with literal fields there is no further customisation that can be added at this point
|
||||
return $field;
|
||||
}
|
||||
|
||||
public function showInReports() {
|
||||
return ! $this->HideFromReports;
|
||||
}
|
||||
public function showInReports()
|
||||
{
|
||||
return ! $this->HideFromReports;
|
||||
}
|
||||
}
|
||||
|
@ -5,55 +5,59 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class EditableMemberListField extends EditableFormField {
|
||||
class EditableMemberListField extends EditableFormField
|
||||
{
|
||||
|
||||
private static $singular_name = 'Member List Field';
|
||||
private static $singular_name = 'Member List Field';
|
||||
|
||||
private static $plural_name = 'Member List Fields';
|
||||
private static $plural_name = 'Member List Fields';
|
||||
|
||||
private static $has_one = array(
|
||||
'Group' => 'Group'
|
||||
);
|
||||
private static $has_one = array(
|
||||
'Group' => 'Group'
|
||||
);
|
||||
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields() {
|
||||
$fields = parent::getCMSFields();
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
$fields = parent::getCMSFields();
|
||||
|
||||
$fields->removeByName('Default');
|
||||
$fields->removeByName('Validation');
|
||||
$fields->removeByName('Default');
|
||||
$fields->removeByName('Validation');
|
||||
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
DropdownField::create(
|
||||
"GroupID",
|
||||
_t('EditableFormField.GROUP', 'Group'),
|
||||
Group::get()->map()
|
||||
)->setEmptyString(' ')
|
||||
);
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
DropdownField::create(
|
||||
"GroupID",
|
||||
_t('EditableFormField.GROUP', 'Group'),
|
||||
Group::get()->map()
|
||||
)->setEmptyString(' ')
|
||||
);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function getFormField() {
|
||||
if(empty($this->GroupID)) {
|
||||
return false;
|
||||
}
|
||||
public function getFormField()
|
||||
{
|
||||
if (empty($this->GroupID)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$members = Member::map_in_groups($this->GroupID);
|
||||
$field = new DropdownField($this->Name, $this->EscapedTitle, $members);
|
||||
$this->doUpdateFormField($field);
|
||||
return $field;
|
||||
}
|
||||
$members = Member::map_in_groups($this->GroupID);
|
||||
$field = new DropdownField($this->Name, $this->EscapedTitle, $members);
|
||||
$this->doUpdateFormField($field);
|
||||
return $field;
|
||||
}
|
||||
|
||||
public function getValueFromData($data) {
|
||||
if(isset($data[$this->Name])) {
|
||||
$memberID = $data[$this->Name];
|
||||
$member = Member::get()->byID($memberID);
|
||||
return $member ? $member->getName() : "";
|
||||
}
|
||||
public function getValueFromData($data)
|
||||
{
|
||||
if (isset($data[$this->Name])) {
|
||||
$memberID = $data[$this->Name];
|
||||
$member = Member::get()->byID($memberID);
|
||||
return $member ? $member->getName() : "";
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -13,183 +13,192 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class EditableMultipleOptionField extends EditableFormField {
|
||||
class EditableMultipleOptionField extends EditableFormField
|
||||
{
|
||||
|
||||
/**
|
||||
* Define this field as abstract (not inherited)
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $abstract = true;
|
||||
/**
|
||||
* Define this field as abstract (not inherited)
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $abstract = true;
|
||||
|
||||
private static $has_many = array(
|
||||
"Options" => "EditableOption"
|
||||
);
|
||||
private static $has_many = array(
|
||||
"Options" => "EditableOption"
|
||||
);
|
||||
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields() {
|
||||
$fields = parent::getCMSFields();
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
$fields = parent::getCMSFields();
|
||||
|
||||
$editableColumns = new GridFieldEditableColumns();
|
||||
$editableColumns->setDisplayFields(array(
|
||||
'Title' => array(
|
||||
'title' => _t('EditableMultipleOptionField.TITLE', 'Title'),
|
||||
'callback' => function($record, $column, $grid) {
|
||||
return TextField::create($column);
|
||||
}
|
||||
),
|
||||
'Value' => array(
|
||||
'title' => _t('EditableMultipleOptionField.VALUE', 'Value'),
|
||||
'callback' => function($record, $column, $grid) {
|
||||
$editableColumns = new GridFieldEditableColumns();
|
||||
$editableColumns->setDisplayFields(array(
|
||||
'Title' => array(
|
||||
'title' => _t('EditableMultipleOptionField.TITLE', 'Title'),
|
||||
'callback' => function ($record, $column, $grid) {
|
||||
return TextField::create($column);
|
||||
}
|
||||
),
|
||||
'Default' => array(
|
||||
'title' => _t('EditableMultipleOptionField.DEFAULT', 'Selected by default?'),
|
||||
'callback' => function($record, $column, $grid) {
|
||||
return CheckboxField::create($column);
|
||||
}
|
||||
)
|
||||
));
|
||||
'Value' => array(
|
||||
'title' => _t('EditableMultipleOptionField.VALUE', 'Value'),
|
||||
'callback' => function ($record, $column, $grid) {
|
||||
return TextField::create($column);
|
||||
}
|
||||
),
|
||||
'Default' => array(
|
||||
'title' => _t('EditableMultipleOptionField.DEFAULT', 'Selected by default?'),
|
||||
'callback' => function ($record, $column, $grid) {
|
||||
return CheckboxField::create($column);
|
||||
}
|
||||
)
|
||||
));
|
||||
|
||||
$optionsConfig = GridFieldConfig::create()
|
||||
->addComponents(
|
||||
new GridFieldToolbarHeader(),
|
||||
new GridFieldTitleHeader(),
|
||||
new GridFieldOrderableRows('Sort'),
|
||||
$editableColumns,
|
||||
new GridFieldButtonRow(),
|
||||
new GridFieldAddNewInlineButton(),
|
||||
new GridFieldDeleteAction()
|
||||
);
|
||||
$optionsConfig = GridFieldConfig::create()
|
||||
->addComponents(
|
||||
new GridFieldToolbarHeader(),
|
||||
new GridFieldTitleHeader(),
|
||||
new GridFieldOrderableRows('Sort'),
|
||||
$editableColumns,
|
||||
new GridFieldButtonRow(),
|
||||
new GridFieldAddNewInlineButton(),
|
||||
new GridFieldDeleteAction()
|
||||
);
|
||||
|
||||
$optionsGrid = GridField::create(
|
||||
'Options',
|
||||
_t('EditableFormField.CUSTOMOPTIONS', 'Options'),
|
||||
$this->Options(),
|
||||
$optionsConfig
|
||||
);
|
||||
$optionsGrid = GridField::create(
|
||||
'Options',
|
||||
_t('EditableFormField.CUSTOMOPTIONS', 'Options'),
|
||||
$this->Options(),
|
||||
$optionsConfig
|
||||
);
|
||||
|
||||
$fields->insertAfter(new Tab('Options', _t('EditableMultipleOptionField.OPTIONSTAB','Options')), 'Main');
|
||||
$fields->addFieldToTab('Root.Options', $optionsGrid);
|
||||
$fields->insertAfter(new Tab('Options', _t('EditableMultipleOptionField.OPTIONSTAB', 'Options')), 'Main');
|
||||
$fields->addFieldToTab('Root.Options', $optionsGrid);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Publishing Versioning support.
|
||||
*
|
||||
* When publishing it needs to handle copying across / publishing
|
||||
* each of the individual field options
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function doPublish($fromStage, $toStage, $createNewVersion = false) {
|
||||
$live = Versioned::get_by_stage("EditableOption", "Live", "\"EditableOption\".\"ParentID\" = $this->ID");
|
||||
/**
|
||||
* Publishing Versioning support.
|
||||
*
|
||||
* When publishing it needs to handle copying across / publishing
|
||||
* each of the individual field options
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function doPublish($fromStage, $toStage, $createNewVersion = false)
|
||||
{
|
||||
$live = Versioned::get_by_stage("EditableOption", "Live", "\"EditableOption\".\"ParentID\" = $this->ID");
|
||||
|
||||
if($live) {
|
||||
foreach($live as $option) {
|
||||
$option->delete();
|
||||
}
|
||||
}
|
||||
if ($live) {
|
||||
foreach ($live as $option) {
|
||||
$option->delete();
|
||||
}
|
||||
}
|
||||
|
||||
if($this->Options()) {
|
||||
foreach($this->Options() as $option) {
|
||||
$option->publish($fromStage, $toStage, $createNewVersion);
|
||||
}
|
||||
}
|
||||
if ($this->Options()) {
|
||||
foreach ($this->Options() as $option) {
|
||||
$option->publish($fromStage, $toStage, $createNewVersion);
|
||||
}
|
||||
}
|
||||
|
||||
parent::doPublish($fromStage, $toStage, $createNewVersion);
|
||||
}
|
||||
parent::doPublish($fromStage, $toStage, $createNewVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpublishing Versioning support
|
||||
*
|
||||
* When unpublishing the field it has to remove all options attached
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function doDeleteFromStage($stage) {
|
||||
// Remove options
|
||||
$options = Versioned::get_by_stage('EditableOption', $stage)
|
||||
->filter('ParentID', $this->ID);
|
||||
foreach($options as $option) {
|
||||
$option->deleteFromStage($stage);
|
||||
}
|
||||
/**
|
||||
* Unpublishing Versioning support
|
||||
*
|
||||
* When unpublishing the field it has to remove all options attached
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function doDeleteFromStage($stage)
|
||||
{
|
||||
// Remove options
|
||||
$options = Versioned::get_by_stage('EditableOption', $stage)
|
||||
->filter('ParentID', $this->ID);
|
||||
foreach ($options as $option) {
|
||||
$option->deleteFromStage($stage);
|
||||
}
|
||||
|
||||
parent::doDeleteFromStage($stage);
|
||||
}
|
||||
parent::doDeleteFromStage($stage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all the options attached to this field before deleting the
|
||||
* field. Keeps stray options from floating around
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete() {
|
||||
$options = $this->Options();
|
||||
/**
|
||||
* Deletes all the options attached to this field before deleting the
|
||||
* field. Keeps stray options from floating around
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$options = $this->Options();
|
||||
|
||||
if($options) {
|
||||
foreach($options as $option) {
|
||||
$option->delete();
|
||||
}
|
||||
}
|
||||
if ($options) {
|
||||
foreach ($options as $option) {
|
||||
$option->delete();
|
||||
}
|
||||
}
|
||||
|
||||
parent::delete();
|
||||
}
|
||||
parent::delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate a pages content. We need to make sure all the fields attached
|
||||
* to that page go with it
|
||||
*
|
||||
* @return DataObject
|
||||
*/
|
||||
public function duplicate($doWrite = true) {
|
||||
$clonedNode = parent::duplicate();
|
||||
/**
|
||||
* Duplicate a pages content. We need to make sure all the fields attached
|
||||
* to that page go with it
|
||||
*
|
||||
* @return DataObject
|
||||
*/
|
||||
public function duplicate($doWrite = true)
|
||||
{
|
||||
$clonedNode = parent::duplicate();
|
||||
|
||||
foreach($this->Options() as $field) {
|
||||
$newField = $field->duplicate(false);
|
||||
$newField->ParentID = $clonedNode->ID;
|
||||
$newField->Version = 0;
|
||||
$newField->write();
|
||||
}
|
||||
foreach ($this->Options() as $field) {
|
||||
$newField = $field->duplicate(false);
|
||||
$newField->ParentID = $clonedNode->ID;
|
||||
$newField->Version = 0;
|
||||
$newField->write();
|
||||
}
|
||||
|
||||
return $clonedNode;
|
||||
}
|
||||
return $clonedNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether or not this field has addable options such as a
|
||||
* {@link EditableDropdownField} or {@link EditableRadioField}
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getHasAddableOptions() {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Return whether or not this field has addable options such as a
|
||||
* {@link EditableDropdownField} or {@link EditableRadioField}
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getHasAddableOptions()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets map of field options suitable for use in a form
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptionsMap() {
|
||||
$optionSet = $this->Options();
|
||||
$optionMap = $optionSet->map('Value', 'Title');
|
||||
if($optionMap instanceof SS_Map) {
|
||||
return $optionMap->toArray();
|
||||
}
|
||||
return $optionMap;
|
||||
}
|
||||
/**
|
||||
* Gets map of field options suitable for use in a form
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptionsMap()
|
||||
{
|
||||
$optionSet = $this->Options();
|
||||
$optionMap = $optionSet->map('Value', 'Title');
|
||||
if ($optionMap instanceof SS_Map) {
|
||||
return $optionMap->toArray();
|
||||
}
|
||||
return $optionMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all default options
|
||||
*
|
||||
* @return SS_List
|
||||
*/
|
||||
protected function getDefaultOptions() {
|
||||
return $this->Options()->filter('Default', 1);
|
||||
}
|
||||
/**
|
||||
* Returns all default options
|
||||
*
|
||||
* @return SS_List
|
||||
*/
|
||||
protected function getDefaultOptions()
|
||||
{
|
||||
return $this->Options()->filter('Default', 1);
|
||||
}
|
||||
}
|
||||
|
@ -7,81 +7,87 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class EditableNumericField extends EditableFormField {
|
||||
class EditableNumericField extends EditableFormField
|
||||
{
|
||||
|
||||
private static $singular_name = 'Numeric Field';
|
||||
private static $singular_name = 'Numeric Field';
|
||||
|
||||
private static $plural_name = 'Numeric Fields';
|
||||
private static $plural_name = 'Numeric Fields';
|
||||
|
||||
private static $db = array(
|
||||
'MinValue' => 'Int',
|
||||
'MaxValue' => 'Int',
|
||||
'Placeholder' => 'Varchar(255)'
|
||||
);
|
||||
private static $db = array(
|
||||
'MinValue' => 'Int',
|
||||
'MaxValue' => 'Int',
|
||||
'Placeholder' => 'Varchar(255)'
|
||||
);
|
||||
|
||||
public function getSetsOwnError() {
|
||||
return true;
|
||||
}
|
||||
public function getSetsOwnError()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getCMSFields() {
|
||||
$this->beforeUpdateCMSFields(function($fields) {
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
TextField::create(
|
||||
'Placeholder',
|
||||
_t('EditableTextField.PLACEHOLDER', 'Placeholder')
|
||||
)
|
||||
);
|
||||
});
|
||||
public function getCMSFields()
|
||||
{
|
||||
$this->beforeUpdateCMSFields(function ($fields) {
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
TextField::create(
|
||||
'Placeholder',
|
||||
_t('EditableTextField.PLACEHOLDER', 'Placeholder')
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
return parent::getCMSFields();
|
||||
}
|
||||
return parent::getCMSFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NumericField
|
||||
*/
|
||||
public function getFormField() {
|
||||
$field = NumericField::create($this->Name, $this->EscapedTitle, $this->Default)
|
||||
->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsField')
|
||||
->addExtraClass('number');
|
||||
/**
|
||||
* @return NumericField
|
||||
*/
|
||||
public function getFormField()
|
||||
{
|
||||
$field = NumericField::create($this->Name, $this->EscapedTitle, $this->Default)
|
||||
->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsField')
|
||||
->addExtraClass('number');
|
||||
|
||||
$this->doUpdateFormField($field);
|
||||
$this->doUpdateFormField($field);
|
||||
|
||||
return $field;
|
||||
}
|
||||
return $field;
|
||||
}
|
||||
|
||||
public function getFieldValidationOptions() {
|
||||
$fields = parent::getFieldValidationOptions();
|
||||
$fields->push(FieldGroup::create(
|
||||
_t("EditableNumericField.RANGE", "Allowed numeric range"),
|
||||
array(
|
||||
new NumericField('MinValue', false),
|
||||
new LiteralField('RangeValue', _t("EditableNumericField.RANGE_TO", "to")),
|
||||
new NumericField('MaxValue', false)
|
||||
)
|
||||
));
|
||||
return $fields;
|
||||
}
|
||||
public function getFieldValidationOptions()
|
||||
{
|
||||
$fields = parent::getFieldValidationOptions();
|
||||
$fields->push(FieldGroup::create(
|
||||
_t("EditableNumericField.RANGE", "Allowed numeric range"),
|
||||
array(
|
||||
new NumericField('MinValue', false),
|
||||
new LiteralField('RangeValue', _t("EditableNumericField.RANGE_TO", "to")),
|
||||
new NumericField('MaxValue', false)
|
||||
)
|
||||
));
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a formfield with the additional metadata specified by this field
|
||||
*
|
||||
* @param FormField $field
|
||||
*/
|
||||
protected function updateFormField($field) {
|
||||
parent::updateFormField($field);
|
||||
/**
|
||||
* Updates a formfield with the additional metadata specified by this field
|
||||
*
|
||||
* @param FormField $field
|
||||
*/
|
||||
protected function updateFormField($field)
|
||||
{
|
||||
parent::updateFormField($field);
|
||||
|
||||
if($this->MinValue) {
|
||||
$field->setAttribute('data-rule-min', $this->MinValue);
|
||||
}
|
||||
if ($this->MinValue) {
|
||||
$field->setAttribute('data-rule-min', $this->MinValue);
|
||||
}
|
||||
|
||||
if($this->MaxValue) {
|
||||
$field->setAttribute('data-rule-max', $this->MaxValue);
|
||||
}
|
||||
if ($this->MaxValue) {
|
||||
$field->setAttribute('data-rule-max', $this->MaxValue);
|
||||
}
|
||||
|
||||
if($this->Placeholder) {
|
||||
$field->setAttribute('placeholder', $this->Placeholder);
|
||||
}
|
||||
}
|
||||
if ($this->Placeholder) {
|
||||
$field->setAttribute('placeholder', $this->Placeholder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,30 +7,31 @@
|
||||
* @method EditableMultipleOptionField Parent()
|
||||
* @package userforms
|
||||
*/
|
||||
class EditableOption extends DataObject {
|
||||
class EditableOption extends DataObject
|
||||
{
|
||||
|
||||
private static $default_sort = "Sort";
|
||||
private static $default_sort = "Sort";
|
||||
|
||||
private static $db = array(
|
||||
"Name" => "Varchar(255)",
|
||||
"Title" => "Varchar(255)",
|
||||
"Default" => "Boolean",
|
||||
private static $db = array(
|
||||
"Name" => "Varchar(255)",
|
||||
"Title" => "Varchar(255)",
|
||||
"Default" => "Boolean",
|
||||
"Sort" => "Int",
|
||||
"Value" => "Varchar(255)",
|
||||
);
|
||||
);
|
||||
|
||||
private static $has_one = array(
|
||||
"Parent" => "EditableMultipleOptionField",
|
||||
);
|
||||
private static $has_one = array(
|
||||
"Parent" => "EditableMultipleOptionField",
|
||||
);
|
||||
|
||||
private static $extensions = array(
|
||||
"Versioned('Stage', 'Live')"
|
||||
);
|
||||
private static $extensions = array(
|
||||
"Versioned('Stage', 'Live')"
|
||||
);
|
||||
|
||||
private static $summary_fields = array(
|
||||
'Title',
|
||||
'Default'
|
||||
);
|
||||
private static $summary_fields = array(
|
||||
'Title',
|
||||
'Default'
|
||||
);
|
||||
|
||||
protected static $allow_empty_values = false;
|
||||
|
||||
@ -39,7 +40,8 @@ class EditableOption extends DataObject {
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function allow_empty_values() {
|
||||
public static function allow_empty_values()
|
||||
{
|
||||
return (bool) self::$allow_empty_values;
|
||||
}
|
||||
|
||||
@ -48,57 +50,63 @@ class EditableOption extends DataObject {
|
||||
*
|
||||
* @param boolean $allow
|
||||
*/
|
||||
public static function set_allow_empty_values($allow) {
|
||||
public static function set_allow_empty_values($allow)
|
||||
{
|
||||
self::$allow_empty_values = (bool) $allow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member $member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canEdit($member = null) {
|
||||
return $this->Parent()->canEdit($member);
|
||||
}
|
||||
/**
|
||||
* @param Member $member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canEdit($member = null)
|
||||
{
|
||||
return $this->Parent()->canEdit($member);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member $member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canDelete($member = null) {
|
||||
return $this->canEdit($member);
|
||||
}
|
||||
/**
|
||||
* @param Member $member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canDelete($member = null)
|
||||
{
|
||||
return $this->canEdit($member);
|
||||
}
|
||||
|
||||
public function getEscapedTitle() {
|
||||
return Convert::raw2att($this->Title);
|
||||
}
|
||||
public function getEscapedTitle()
|
||||
{
|
||||
return Convert::raw2att($this->Title);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member $member
|
||||
* @return bool
|
||||
*/
|
||||
public function canView($member = null) {
|
||||
return $this->Parent()->canView($member);
|
||||
}
|
||||
public function canView($member = null)
|
||||
{
|
||||
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 array $context Virtual parameter to allow context to be passed in to check
|
||||
* @return bool
|
||||
*/
|
||||
public function canCreate($member = null) {
|
||||
// Check parent page
|
||||
* @return bool
|
||||
*/
|
||||
public function canCreate($member = null)
|
||||
{
|
||||
// Check parent page
|
||||
$parent = $this->getCanCreateContext(func_get_args());
|
||||
if($parent) {
|
||||
if ($parent) {
|
||||
return $parent->canEdit($member);
|
||||
}
|
||||
|
||||
// Fall back to secure admin permissions
|
||||
return parent::canCreate($member);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to check the parent for this object
|
||||
@ -106,13 +114,14 @@ class EditableOption extends DataObject {
|
||||
* @param array $args List of arguments passed to canCreate
|
||||
* @return DataObject Some parent dataobject to inherit permissions from
|
||||
*/
|
||||
protected function getCanCreateContext($args) {
|
||||
protected function getCanCreateContext($args)
|
||||
{
|
||||
// Inspect second parameter to canCreate for a 'Parent' context
|
||||
if(isset($args[1]['Parent'])) {
|
||||
if (isset($args[1]['Parent'])) {
|
||||
return $args[1]['Parent'];
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
|
||||
@ -124,7 +133,8 @@ class EditableOption extends DataObject {
|
||||
* @param Member $member
|
||||
* @return bool
|
||||
*/
|
||||
public function canPublish($member = null) {
|
||||
public function canPublish($member = null)
|
||||
{
|
||||
return $this->canEdit($member);
|
||||
}
|
||||
|
||||
@ -132,7 +142,8 @@ class EditableOption extends DataObject {
|
||||
* @param Member $member
|
||||
* @return bool
|
||||
*/
|
||||
public function canUnpublish($member = null) {
|
||||
public function canUnpublish($member = null)
|
||||
{
|
||||
return $this->canDelete($member);
|
||||
}
|
||||
|
||||
@ -145,7 +156,7 @@ class EditableOption extends DataObject {
|
||||
public function getValue()
|
||||
{
|
||||
$value = $this->getField('Value');
|
||||
if(empty($value) && !self::allow_empty_values()) {
|
||||
if (empty($value) && !self::allow_empty_values()) {
|
||||
return $this->Title;
|
||||
}
|
||||
return $value;
|
||||
|
@ -7,39 +7,43 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class EditableRadioField extends EditableMultipleOptionField {
|
||||
class EditableRadioField extends EditableMultipleOptionField
|
||||
{
|
||||
|
||||
private static $singular_name = 'Radio Group';
|
||||
private static $singular_name = 'Radio Group';
|
||||
|
||||
private static $plural_name = 'Radio Groups';
|
||||
private static $plural_name = 'Radio Groups';
|
||||
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields() {
|
||||
$fields = parent::getCMSFields();
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
$fields = parent::getCMSFields();
|
||||
|
||||
$fields->removeByName('Default');
|
||||
$fields->removeByName('Default');
|
||||
|
||||
return $fields;
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function getFormField() {
|
||||
$field = OptionsetField::create($this->Name, $this->EscapedTitle, $this->getOptionsMap());
|
||||
$field->setFieldHolderTemplate('UserFormsMultipleOptionField_holder');
|
||||
public function getFormField()
|
||||
{
|
||||
$field = OptionsetField::create($this->Name, $this->EscapedTitle, $this->getOptionsMap());
|
||||
$field->setFieldHolderTemplate('UserFormsMultipleOptionField_holder');
|
||||
|
||||
// Set default item
|
||||
$defaultOption = $this->getDefaultOptions()->first();
|
||||
if($defaultOption) {
|
||||
$field->setValue($defaultOption->EscapedTitle);
|
||||
}
|
||||
$this->doUpdateFormField($field);
|
||||
return $field;
|
||||
}
|
||||
// Set default item
|
||||
$defaultOption = $this->getDefaultOptions()->first();
|
||||
if ($defaultOption) {
|
||||
$field->setValue($defaultOption->EscapedTitle);
|
||||
}
|
||||
$this->doUpdateFormField($field);
|
||||
return $field;
|
||||
}
|
||||
|
||||
public function getSelectorField(EditableCustomRule $rule, $forOnLoad = false) {
|
||||
// We only want to trigger on load once for the radio group - hence we focus on the first option only.
|
||||
$first = $forOnLoad ? ':first' : '';
|
||||
return "$(\"input[name='{$this->Name}']{$first}\")";
|
||||
}
|
||||
public function getSelectorField(EditableCustomRule $rule, $forOnLoad = false)
|
||||
{
|
||||
// We only want to trigger on load once for the radio group - hence we focus on the first option only.
|
||||
$first = $forOnLoad ? ':first' : '';
|
||||
return "$(\"input[name='{$this->Name}']{$first}\")";
|
||||
}
|
||||
}
|
||||
|
@ -7,109 +7,114 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class EditableTextField extends EditableFormField {
|
||||
class EditableTextField extends EditableFormField
|
||||
{
|
||||
|
||||
private static $singular_name = 'Text Field';
|
||||
private static $singular_name = 'Text Field';
|
||||
|
||||
private static $plural_name = 'Text Fields';
|
||||
private static $plural_name = 'Text Fields';
|
||||
|
||||
private static $db = array(
|
||||
'MinLength' => 'Int',
|
||||
'MaxLength' => 'Int',
|
||||
'Rows' => 'Int(1)',
|
||||
'Placeholder' => 'Varchar(255)'
|
||||
);
|
||||
private static $db = array(
|
||||
'MinLength' => 'Int',
|
||||
'MaxLength' => 'Int',
|
||||
'Rows' => 'Int(1)',
|
||||
'Placeholder' => 'Varchar(255)'
|
||||
);
|
||||
|
||||
private static $defaults = array(
|
||||
'Rows' => 1
|
||||
);
|
||||
private static $defaults = array(
|
||||
'Rows' => 1
|
||||
);
|
||||
|
||||
public function getCMSFields() {
|
||||
$this->beforeUpdateCMSFields(function($fields) {
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
NumericField::create(
|
||||
'Rows',
|
||||
_t('EditableTextField.NUMBERROWS', 'Number of rows')
|
||||
)->setDescription(_t(
|
||||
'EditableTextField.NUMBERROWS_DESCRIPTION',
|
||||
'Fields with more than one row will be generated as a textarea'
|
||||
))
|
||||
);
|
||||
public function getCMSFields()
|
||||
{
|
||||
$this->beforeUpdateCMSFields(function ($fields) {
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
NumericField::create(
|
||||
'Rows',
|
||||
_t('EditableTextField.NUMBERROWS', 'Number of rows')
|
||||
)->setDescription(_t(
|
||||
'EditableTextField.NUMBERROWS_DESCRIPTION',
|
||||
'Fields with more than one row will be generated as a textarea'
|
||||
))
|
||||
);
|
||||
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
TextField::create(
|
||||
'Placeholder',
|
||||
_t('EditableTextField.PLACEHOLDER', 'Placeholder')
|
||||
)
|
||||
);
|
||||
});
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
TextField::create(
|
||||
'Placeholder',
|
||||
_t('EditableTextField.PLACEHOLDER', 'Placeholder')
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
return parent::getCMSFields();
|
||||
}
|
||||
return parent::getCMSFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getFieldValidationOptions() {
|
||||
$fields = parent::getFieldValidationOptions();
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getFieldValidationOptions()
|
||||
{
|
||||
$fields = parent::getFieldValidationOptions();
|
||||
|
||||
$fields->merge(array(
|
||||
FieldGroup::create(
|
||||
_t('EditableTextField.TEXTLENGTH', 'Allowed text length'),
|
||||
array(
|
||||
NumericField::create('MinLength', false),
|
||||
LiteralField::create('RangeLength', _t("EditableTextField.RANGE_TO", "to")),
|
||||
NumericField::create('MaxLength', false)
|
||||
)
|
||||
)
|
||||
));
|
||||
$fields->merge(array(
|
||||
FieldGroup::create(
|
||||
_t('EditableTextField.TEXTLENGTH', 'Allowed text length'),
|
||||
array(
|
||||
NumericField::create('MinLength', false),
|
||||
LiteralField::create('RangeLength', _t("EditableTextField.RANGE_TO", "to")),
|
||||
NumericField::create('MaxLength', false)
|
||||
)
|
||||
)
|
||||
));
|
||||
|
||||
return $fields;
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TextareaField|TextField
|
||||
*/
|
||||
public function getFormField() {
|
||||
if($this->Rows > 1) {
|
||||
$field = TextareaField::create($this->Name, $this->EscapedTitle, $this->Default)
|
||||
->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsTextareaField')
|
||||
->setRows($this->Rows);
|
||||
} else {
|
||||
$field = TextField::create($this->Name, $this->EscapedTitle, $this->Default)
|
||||
->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsField');
|
||||
}
|
||||
/**
|
||||
* @return TextareaField|TextField
|
||||
*/
|
||||
public function getFormField()
|
||||
{
|
||||
if ($this->Rows > 1) {
|
||||
$field = TextareaField::create($this->Name, $this->EscapedTitle, $this->Default)
|
||||
->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsTextareaField')
|
||||
->setRows($this->Rows);
|
||||
} else {
|
||||
$field = TextField::create($this->Name, $this->EscapedTitle, $this->Default)
|
||||
->setFieldHolderTemplate('UserFormsField_holder')
|
||||
->setTemplate('UserFormsField');
|
||||
}
|
||||
|
||||
$this->doUpdateFormField($field);
|
||||
$this->doUpdateFormField($field);
|
||||
|
||||
return $field;
|
||||
}
|
||||
return $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a formfield with the additional metadata specified by this field
|
||||
*
|
||||
* @param FormField $field
|
||||
*/
|
||||
protected function updateFormField($field) {
|
||||
parent::updateFormField($field);
|
||||
/**
|
||||
* Updates a formfield with the additional metadata specified by this field
|
||||
*
|
||||
* @param FormField $field
|
||||
*/
|
||||
protected function updateFormField($field)
|
||||
{
|
||||
parent::updateFormField($field);
|
||||
|
||||
if(is_numeric($this->MinLength) && $this->MinLength > 0) {
|
||||
$field->setAttribute('data-rule-minlength', intval($this->MinLength));
|
||||
}
|
||||
if (is_numeric($this->MinLength) && $this->MinLength > 0) {
|
||||
$field->setAttribute('data-rule-minlength', intval($this->MinLength));
|
||||
}
|
||||
|
||||
if(is_numeric($this->MaxLength) && $this->MaxLength > 0) {
|
||||
if($field instanceof TextField) {
|
||||
if (is_numeric($this->MaxLength) && $this->MaxLength > 0) {
|
||||
if ($field instanceof TextField) {
|
||||
$field->setMaxLength(intval($this->MaxLength));
|
||||
}
|
||||
$field->setAttribute('data-rule-maxlength', intval($this->MaxLength));
|
||||
}
|
||||
$field->setAttribute('data-rule-maxlength', intval($this->MaxLength));
|
||||
}
|
||||
|
||||
if($this->Placeholder) {
|
||||
$field->setAttribute('placeholder', $this->Placeholder);
|
||||
}
|
||||
}
|
||||
if ($this->Placeholder) {
|
||||
$field->setAttribute('placeholder', $this->Placeholder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,305 +7,312 @@
|
||||
*
|
||||
* @package userforms
|
||||
*/
|
||||
class UserDefinedForm_EmailRecipient extends DataObject {
|
||||
class UserDefinedForm_EmailRecipient extends DataObject
|
||||
{
|
||||
|
||||
private static $db = array(
|
||||
'EmailAddress' => 'Varchar(200)',
|
||||
'EmailSubject' => 'Varchar(200)',
|
||||
'EmailFrom' => 'Varchar(200)',
|
||||
'EmailReplyTo' => 'Varchar(200)',
|
||||
'EmailBody' => 'Text',
|
||||
'EmailBodyHtml' => 'HTMLText',
|
||||
'EmailTemplate' => 'Varchar',
|
||||
'SendPlain' => 'Boolean',
|
||||
'HideFormData' => 'Boolean',
|
||||
'CustomRulesCondition' => 'Enum("And,Or")'
|
||||
);
|
||||
private static $db = array(
|
||||
'EmailAddress' => 'Varchar(200)',
|
||||
'EmailSubject' => 'Varchar(200)',
|
||||
'EmailFrom' => 'Varchar(200)',
|
||||
'EmailReplyTo' => 'Varchar(200)',
|
||||
'EmailBody' => 'Text',
|
||||
'EmailBodyHtml' => 'HTMLText',
|
||||
'EmailTemplate' => 'Varchar',
|
||||
'SendPlain' => 'Boolean',
|
||||
'HideFormData' => 'Boolean',
|
||||
'CustomRulesCondition' => 'Enum("And,Or")'
|
||||
);
|
||||
|
||||
private static $has_one = array(
|
||||
'Form' => 'UserDefinedForm',
|
||||
'SendEmailFromField' => 'EditableFormField',
|
||||
'SendEmailToField' => 'EditableFormField',
|
||||
'SendEmailSubjectField' => 'EditableFormField'
|
||||
);
|
||||
private static $has_one = array(
|
||||
'Form' => 'UserDefinedForm',
|
||||
'SendEmailFromField' => 'EditableFormField',
|
||||
'SendEmailToField' => 'EditableFormField',
|
||||
'SendEmailSubjectField' => 'EditableFormField'
|
||||
);
|
||||
|
||||
private static $has_many = array(
|
||||
'CustomRules' => 'UserDefinedForm_EmailRecipientCondition'
|
||||
);
|
||||
private static $has_many = array(
|
||||
'CustomRules' => 'UserDefinedForm_EmailRecipientCondition'
|
||||
);
|
||||
|
||||
private static $summary_fields = array(
|
||||
'EmailAddress',
|
||||
'EmailSubject',
|
||||
'EmailFrom'
|
||||
);
|
||||
private static $summary_fields = array(
|
||||
'EmailAddress',
|
||||
'EmailSubject',
|
||||
'EmailFrom'
|
||||
);
|
||||
|
||||
/**
|
||||
* Setting this to true will allow you to select "risky" fields as
|
||||
* email recipient, such as free-text entry fields.
|
||||
*
|
||||
* It's advisable to leave this off.
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $allow_unbound_recipient_fields = false;
|
||||
/**
|
||||
* Setting this to true will allow you to select "risky" fields as
|
||||
* email recipient, such as free-text entry fields.
|
||||
*
|
||||
* It's advisable to leave this off.
|
||||
*
|
||||
* @config
|
||||
* @var bool
|
||||
*/
|
||||
private static $allow_unbound_recipient_fields = false;
|
||||
|
||||
public function summaryFields() {
|
||||
$fields = parent::summaryFields();
|
||||
if(isset($fields['EmailAddress'])) {
|
||||
$fields['EmailAddress'] = _t('UserDefinedForm.EMAILADDRESS', 'Email');
|
||||
}
|
||||
if(isset($fields['EmailSubject'])) {
|
||||
$fields['EmailSubject'] = _t('UserDefinedForm.EMAILSUBJECT', 'Subject');
|
||||
}
|
||||
if(isset($fields['EmailFrom'])) {
|
||||
$fields['EmailFrom'] = _t('UserDefinedForm.EMAILFROM', 'From');
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
public function summaryFields()
|
||||
{
|
||||
$fields = parent::summaryFields();
|
||||
if (isset($fields['EmailAddress'])) {
|
||||
$fields['EmailAddress'] = _t('UserDefinedForm.EMAILADDRESS', 'Email');
|
||||
}
|
||||
if (isset($fields['EmailSubject'])) {
|
||||
$fields['EmailSubject'] = _t('UserDefinedForm.EMAILSUBJECT', 'Subject');
|
||||
}
|
||||
if (isset($fields['EmailFrom'])) {
|
||||
$fields['EmailFrom'] = _t('UserDefinedForm.EMAILFROM', 'From');
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get instance of UserDefinedForm when editing in getCMSFields
|
||||
*
|
||||
* @return UserDefinedFrom
|
||||
*/
|
||||
protected function getFormParent() {
|
||||
$formID = $this->FormID
|
||||
? $this->FormID
|
||||
: Session::get('CMSMain.currentPage');
|
||||
return UserDefinedForm::get()->byID($formID);
|
||||
}
|
||||
/**
|
||||
* Get instance of UserDefinedForm when editing in getCMSFields
|
||||
*
|
||||
* @return UserDefinedFrom
|
||||
*/
|
||||
protected function getFormParent()
|
||||
{
|
||||
$formID = $this->FormID
|
||||
? $this->FormID
|
||||
: Session::get('CMSMain.currentPage');
|
||||
return UserDefinedForm::get()->byID($formID);
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
if($this->EmailAddress) {
|
||||
return $this->EmailAddress;
|
||||
}
|
||||
if($this->EmailSubject) {
|
||||
return $this->EmailSubject;
|
||||
}
|
||||
return parent::getTitle();
|
||||
}
|
||||
public function getTitle()
|
||||
{
|
||||
if ($this->EmailAddress) {
|
||||
return $this->EmailAddress;
|
||||
}
|
||||
if ($this->EmailSubject) {
|
||||
return $this->EmailSubject;
|
||||
}
|
||||
return parent::getTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a gridfield config for editing filter rules
|
||||
*
|
||||
* @return GridFieldConfig
|
||||
*/
|
||||
protected function getRulesConfig() {
|
||||
$formFields = $this->getFormParent()->Fields();
|
||||
/**
|
||||
* Generate a gridfield config for editing filter rules
|
||||
*
|
||||
* @return GridFieldConfig
|
||||
*/
|
||||
protected function getRulesConfig()
|
||||
{
|
||||
$formFields = $this->getFormParent()->Fields();
|
||||
|
||||
$config = GridFieldConfig::create()
|
||||
->addComponents(
|
||||
new GridFieldButtonRow('before'),
|
||||
new GridFieldToolbarHeader(),
|
||||
new GridFieldAddNewInlineButton(),
|
||||
new GridFieldDeleteAction(),
|
||||
$columns = new GridFieldEditableColumns()
|
||||
);
|
||||
$config = GridFieldConfig::create()
|
||||
->addComponents(
|
||||
new GridFieldButtonRow('before'),
|
||||
new GridFieldToolbarHeader(),
|
||||
new GridFieldAddNewInlineButton(),
|
||||
new GridFieldDeleteAction(),
|
||||
$columns = new GridFieldEditableColumns()
|
||||
);
|
||||
|
||||
$columns->setDisplayFields(array(
|
||||
'ConditionFieldID' => function($record, $column, $grid) use ($formFields) {
|
||||
return DropdownField::create($column, false, $formFields->map('ID', 'Title'));
|
||||
},
|
||||
'ConditionOption' => function($record, $column, $grid) {
|
||||
$options = UserDefinedForm_EmailRecipientCondition::config()->condition_options;
|
||||
return DropdownField::create($column, false, $options);
|
||||
},
|
||||
'ConditionValue' => function($record, $column, $grid) {
|
||||
return TextField::create($column);
|
||||
}
|
||||
));
|
||||
$columns->setDisplayFields(array(
|
||||
'ConditionFieldID' => function ($record, $column, $grid) use ($formFields) {
|
||||
return DropdownField::create($column, false, $formFields->map('ID', 'Title'));
|
||||
},
|
||||
'ConditionOption' => function ($record, $column, $grid) {
|
||||
$options = UserDefinedForm_EmailRecipientCondition::config()->condition_options;
|
||||
return DropdownField::create($column, false, $options);
|
||||
},
|
||||
'ConditionValue' => function ($record, $column, $grid) {
|
||||
return TextField::create($column);
|
||||
}
|
||||
));
|
||||
|
||||
return $config;
|
||||
}
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields() {
|
||||
Requirements::javascript(USERFORMS_DIR . '/javascript/Recipient.js');
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
Requirements::javascript(USERFORMS_DIR . '/javascript/Recipient.js');
|
||||
|
||||
// Determine optional field values
|
||||
$form = $this->getFormParent();
|
||||
// Determine optional field values
|
||||
$form = $this->getFormParent();
|
||||
|
||||
// predefined choices are also candidates
|
||||
$multiOptionFields = EditableMultipleOptionField::get()->filter('ParentID', $form->ID);
|
||||
// predefined choices are also candidates
|
||||
$multiOptionFields = EditableMultipleOptionField::get()->filter('ParentID', $form->ID);
|
||||
|
||||
// if they have email fields then we could send from it
|
||||
$validEmailFromFields = EditableEmailField::get()->filter('ParentID', $form->ID);
|
||||
// if they have email fields then we could send from it
|
||||
$validEmailFromFields = EditableEmailField::get()->filter('ParentID', $form->ID);
|
||||
|
||||
// For the subject, only one-line entry boxes make sense
|
||||
$validSubjectFields = ArrayList::create(
|
||||
EditableTextField::get()
|
||||
->filter('ParentID', $form->ID)
|
||||
->exclude('Rows:GreaterThan', 1)
|
||||
->toArray()
|
||||
);
|
||||
$validSubjectFields->merge($multiOptionFields);
|
||||
// For the subject, only one-line entry boxes make sense
|
||||
$validSubjectFields = ArrayList::create(
|
||||
EditableTextField::get()
|
||||
->filter('ParentID', $form->ID)
|
||||
->exclude('Rows:GreaterThan', 1)
|
||||
->toArray()
|
||||
);
|
||||
$validSubjectFields->merge($multiOptionFields);
|
||||
|
||||
|
||||
// Check valid email-recipient fields
|
||||
if($this->config()->allow_unbound_recipient_fields) {
|
||||
// To address can only be email fields or multi option fields
|
||||
$validEmailToFields = ArrayList::create($validEmailFromFields->toArray());
|
||||
$validEmailToFields->merge($multiOptionFields);
|
||||
} else {
|
||||
// To address cannot be unbound, so restrict to pre-defined lists
|
||||
$validEmailToFields = $multiOptionFields;
|
||||
}
|
||||
// Check valid email-recipient fields
|
||||
if ($this->config()->allow_unbound_recipient_fields) {
|
||||
// To address can only be email fields or multi option fields
|
||||
$validEmailToFields = ArrayList::create($validEmailFromFields->toArray());
|
||||
$validEmailToFields->merge($multiOptionFields);
|
||||
} else {
|
||||
// To address cannot be unbound, so restrict to pre-defined lists
|
||||
$validEmailToFields = $multiOptionFields;
|
||||
}
|
||||
|
||||
// Build fieldlist
|
||||
$fields = FieldList::create(Tabset::create('Root')->addExtraClass('EmailRecipientForm'));
|
||||
// Build fieldlist
|
||||
$fields = FieldList::create(Tabset::create('Root')->addExtraClass('EmailRecipientForm'));
|
||||
|
||||
// Configuration fields
|
||||
$fields->addFieldsToTab('Root.EmailDetails', array(
|
||||
// Subject
|
||||
FieldGroup::create(
|
||||
TextField::create('EmailSubject', _t('UserDefinedForm.TYPESUBJECT', 'Type subject'))
|
||||
->setAttribute('style', 'min-width: 400px;'),
|
||||
DropdownField::create(
|
||||
'SendEmailSubjectFieldID',
|
||||
_t('UserDefinedForm.SELECTAFIELDTOSETSUBJECT', '.. or select a field to use as the subject'),
|
||||
$validSubjectFields->map('ID', 'Title')
|
||||
)->setEmptyString('')
|
||||
)
|
||||
->setTitle(_t('UserDefinedForm.EMAILSUBJECT', 'Email subject')),
|
||||
// Configuration fields
|
||||
$fields->addFieldsToTab('Root.EmailDetails', array(
|
||||
// Subject
|
||||
FieldGroup::create(
|
||||
TextField::create('EmailSubject', _t('UserDefinedForm.TYPESUBJECT', 'Type subject'))
|
||||
->setAttribute('style', 'min-width: 400px;'),
|
||||
DropdownField::create(
|
||||
'SendEmailSubjectFieldID',
|
||||
_t('UserDefinedForm.SELECTAFIELDTOSETSUBJECT', '.. or select a field to use as the subject'),
|
||||
$validSubjectFields->map('ID', 'Title')
|
||||
)->setEmptyString('')
|
||||
)
|
||||
->setTitle(_t('UserDefinedForm.EMAILSUBJECT', 'Email subject')),
|
||||
|
||||
// To
|
||||
FieldGroup::create(
|
||||
TextField::create('EmailAddress', _t('UserDefinedForm.TYPETO', 'Type to address'))
|
||||
->setAttribute('style', 'min-width: 400px;'),
|
||||
DropdownField::create(
|
||||
'SendEmailToFieldID',
|
||||
_t('UserDefinedForm.ORSELECTAFIELDTOUSEASTO', '.. or select a field to use as the to address'),
|
||||
$validEmailToFields->map('ID', 'Title')
|
||||
)->setEmptyString(' ')
|
||||
)
|
||||
->setTitle(_t('UserDefinedForm.SENDEMAILTO','Send email to'))
|
||||
->setDescription(_t(
|
||||
'UserDefinedForm.SENDEMAILTO_DESCRIPTION',
|
||||
'You may enter multiple email addresses as a comma separated list.'
|
||||
)),
|
||||
// To
|
||||
FieldGroup::create(
|
||||
TextField::create('EmailAddress', _t('UserDefinedForm.TYPETO', 'Type to address'))
|
||||
->setAttribute('style', 'min-width: 400px;'),
|
||||
DropdownField::create(
|
||||
'SendEmailToFieldID',
|
||||
_t('UserDefinedForm.ORSELECTAFIELDTOUSEASTO', '.. or select a field to use as the to address'),
|
||||
$validEmailToFields->map('ID', 'Title')
|
||||
)->setEmptyString(' ')
|
||||
)
|
||||
->setTitle(_t('UserDefinedForm.SENDEMAILTO', 'Send email to'))
|
||||
->setDescription(_t(
|
||||
'UserDefinedForm.SENDEMAILTO_DESCRIPTION',
|
||||
'You may enter multiple email addresses as a comma separated list.'
|
||||
)),
|
||||
|
||||
|
||||
// From
|
||||
TextField::create('EmailFrom', _t('UserDefinedForm.FROMADDRESS','Send email from'))
|
||||
->setDescription(_t(
|
||||
'UserDefinedForm.EmailFromContent',
|
||||
"The from address allows you to set who the email comes from. On most servers this ".
|
||||
"will need to be set to an email address on the same domain name as your site. ".
|
||||
"For example on yoursite.com the from address may need to be something@yoursite.com. ".
|
||||
"You can however, set any email address you wish as the reply to address."
|
||||
)),
|
||||
// From
|
||||
TextField::create('EmailFrom', _t('UserDefinedForm.FROMADDRESS', 'Send email from'))
|
||||
->setDescription(_t(
|
||||
'UserDefinedForm.EmailFromContent',
|
||||
"The from address allows you to set who the email comes from. On most servers this ".
|
||||
"will need to be set to an email address on the same domain name as your site. ".
|
||||
"For example on yoursite.com the from address may need to be something@yoursite.com. ".
|
||||
"You can however, set any email address you wish as the reply to address."
|
||||
)),
|
||||
|
||||
|
||||
// Reply-To
|
||||
FieldGroup::create(
|
||||
TextField::create('EmailReplyTo', _t('UserDefinedForm.TYPEREPLY', 'Type reply address'))
|
||||
->setAttribute('style', 'min-width: 400px;'),
|
||||
DropdownField::create(
|
||||
'SendEmailFromFieldID',
|
||||
_t('UserDefinedForm.ORSELECTAFIELDTOUSEASFROM', '.. or select a field to use as reply to address'),
|
||||
$validEmailFromFields->map('ID', 'Title')
|
||||
)->setEmptyString(' ')
|
||||
)
|
||||
->setTitle(_t('UserDefinedForm.REPLYADDRESS', 'Email for reply to'))
|
||||
->setDescription(_t(
|
||||
'UserDefinedForm.REPLYADDRESS_DESCRIPTION',
|
||||
'The email address which the recipient is able to \'reply\' to.'
|
||||
))
|
||||
));
|
||||
// Reply-To
|
||||
FieldGroup::create(
|
||||
TextField::create('EmailReplyTo', _t('UserDefinedForm.TYPEREPLY', 'Type reply address'))
|
||||
->setAttribute('style', 'min-width: 400px;'),
|
||||
DropdownField::create(
|
||||
'SendEmailFromFieldID',
|
||||
_t('UserDefinedForm.ORSELECTAFIELDTOUSEASFROM', '.. or select a field to use as reply to address'),
|
||||
$validEmailFromFields->map('ID', 'Title')
|
||||
)->setEmptyString(' ')
|
||||
)
|
||||
->setTitle(_t('UserDefinedForm.REPLYADDRESS', 'Email for reply to'))
|
||||
->setDescription(_t(
|
||||
'UserDefinedForm.REPLYADDRESS_DESCRIPTION',
|
||||
'The email address which the recipient is able to \'reply\' to.'
|
||||
))
|
||||
));
|
||||
|
||||
$fields->fieldByName('Root.EmailDetails')->setTitle(_t('UserDefinedForm_EmailRecipient.EMAILDETAILSTAB', 'Email Details'));
|
||||
$fields->fieldByName('Root.EmailDetails')->setTitle(_t('UserDefinedForm_EmailRecipient.EMAILDETAILSTAB', 'Email Details'));
|
||||
|
||||
// Only show the preview link if the recipient has been saved.
|
||||
if (!empty($this->EmailTemplate)) {
|
||||
$preview = sprintf(
|
||||
'<p><a href="%s" target="_blank" class="ss-ui-button">%s</a></p><em>%s</em>',
|
||||
"admin/pages/edit/EditForm/field/EmailRecipients/item/{$this->ID}/preview",
|
||||
_t('UserDefinedForm.PREVIEW_EMAIL', 'Preview email'),
|
||||
_t('UserDefinedForm.PREVIEW_EMAIL_DESCRIPTION', 'Note: Unsaved changes will not appear in the preview.')
|
||||
);
|
||||
} else {
|
||||
$preview = sprintf(
|
||||
'<em>%s</em>',
|
||||
_t(
|
||||
'UserDefinedForm.PREVIEW_EMAIL_UNAVAILABLE',
|
||||
'You can preview this email once you have saved the Recipient.'
|
||||
)
|
||||
);
|
||||
}
|
||||
// Only show the preview link if the recipient has been saved.
|
||||
if (!empty($this->EmailTemplate)) {
|
||||
$preview = sprintf(
|
||||
'<p><a href="%s" target="_blank" class="ss-ui-button">%s</a></p><em>%s</em>',
|
||||
"admin/pages/edit/EditForm/field/EmailRecipients/item/{$this->ID}/preview",
|
||||
_t('UserDefinedForm.PREVIEW_EMAIL', 'Preview email'),
|
||||
_t('UserDefinedForm.PREVIEW_EMAIL_DESCRIPTION', 'Note: Unsaved changes will not appear in the preview.')
|
||||
);
|
||||
} else {
|
||||
$preview = sprintf(
|
||||
'<em>%s</em>',
|
||||
_t(
|
||||
'UserDefinedForm.PREVIEW_EMAIL_UNAVAILABLE',
|
||||
'You can preview this email once you have saved the Recipient.'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Email templates
|
||||
$fields->addFieldsToTab('Root.EmailContent', array(
|
||||
CheckboxField::create('HideFormData', _t('UserDefinedForm.HIDEFORMDATA', 'Hide form data from email?')),
|
||||
CheckboxField::create(
|
||||
'SendPlain',
|
||||
_t('UserDefinedForm.SENDPLAIN', 'Send email as plain text? (HTML will be stripped)')
|
||||
),
|
||||
DropdownField::create(
|
||||
'EmailTemplate',
|
||||
_t('UserDefinedForm.EMAILTEMPLATE', 'Email template'),
|
||||
$this->getEmailTemplateDropdownValues()
|
||||
)->addExtraClass('toggle-html-only'),
|
||||
HTMLEditorField::create('EmailBodyHtml', _t('UserDefinedForm.EMAILBODYHTML','Body'))
|
||||
->addExtraClass('toggle-html-only'),
|
||||
TextareaField::create('EmailBody', _t('UserDefinedForm.EMAILBODY','Body'))
|
||||
->addExtraClass('toggle-plain-only'),
|
||||
LiteralField::create(
|
||||
'EmailPreview',
|
||||
'<div id="EmailPreview" class="field toggle-html-only">' . $preview . '</div>'
|
||||
)
|
||||
));
|
||||
// Email templates
|
||||
$fields->addFieldsToTab('Root.EmailContent', array(
|
||||
CheckboxField::create('HideFormData', _t('UserDefinedForm.HIDEFORMDATA', 'Hide form data from email?')),
|
||||
CheckboxField::create(
|
||||
'SendPlain',
|
||||
_t('UserDefinedForm.SENDPLAIN', 'Send email as plain text? (HTML will be stripped)')
|
||||
),
|
||||
DropdownField::create(
|
||||
'EmailTemplate',
|
||||
_t('UserDefinedForm.EMAILTEMPLATE', 'Email template'),
|
||||
$this->getEmailTemplateDropdownValues()
|
||||
)->addExtraClass('toggle-html-only'),
|
||||
HTMLEditorField::create('EmailBodyHtml', _t('UserDefinedForm.EMAILBODYHTML', 'Body'))
|
||||
->addExtraClass('toggle-html-only'),
|
||||
TextareaField::create('EmailBody', _t('UserDefinedForm.EMAILBODY', 'Body'))
|
||||
->addExtraClass('toggle-plain-only'),
|
||||
LiteralField::create(
|
||||
'EmailPreview',
|
||||
'<div id="EmailPreview" class="field toggle-html-only">' . $preview . '</div>'
|
||||
)
|
||||
));
|
||||
|
||||
$fields->fieldByName('Root.EmailContent')->setTitle(_t('UserDefinedForm_EmailRecipient.EMAILCONTENTTAB', 'Email Content'));
|
||||
$fields->fieldByName('Root.EmailContent')->setTitle(_t('UserDefinedForm_EmailRecipient.EMAILCONTENTTAB', 'Email Content'));
|
||||
|
||||
// Custom rules for sending this field
|
||||
$grid = new GridField(
|
||||
"CustomRules",
|
||||
_t('EditableFormField.CUSTOMRULES', 'Custom Rules'),
|
||||
$this->CustomRules(),
|
||||
$this->getRulesConfig()
|
||||
);
|
||||
$grid->setDescription(_t(
|
||||
'UserDefinedForm.RulesDescription',
|
||||
'Emails will only be sent to the recipient if the custom rules are met. If no rules are defined, this receipient will receive notifications for every submission.'
|
||||
));
|
||||
$fields->addFieldsToTab('Root.CustomRules', array(
|
||||
new DropdownField(
|
||||
'CustomRulesCondition',
|
||||
_t('UserDefinedForm.SENDIF', 'Send condition'),
|
||||
array(
|
||||
'Or' => _t('UserDefinedForm.SENDIFOR', 'Any conditions are true'),
|
||||
'And' => _t('UserDefinedForm.SENDIFAND', 'All conditions are true')
|
||||
)
|
||||
),
|
||||
$grid
|
||||
));
|
||||
// Custom rules for sending this field
|
||||
$grid = new GridField(
|
||||
"CustomRules",
|
||||
_t('EditableFormField.CUSTOMRULES', 'Custom Rules'),
|
||||
$this->CustomRules(),
|
||||
$this->getRulesConfig()
|
||||
);
|
||||
$grid->setDescription(_t(
|
||||
'UserDefinedForm.RulesDescription',
|
||||
'Emails will only be sent to the recipient if the custom rules are met. If no rules are defined, this receipient will receive notifications for every submission.'
|
||||
));
|
||||
$fields->addFieldsToTab('Root.CustomRules', array(
|
||||
new DropdownField(
|
||||
'CustomRulesCondition',
|
||||
_t('UserDefinedForm.SENDIF', 'Send condition'),
|
||||
array(
|
||||
'Or' => _t('UserDefinedForm.SENDIFOR', 'Any conditions are true'),
|
||||
'And' => _t('UserDefinedForm.SENDIFAND', 'All conditions are true')
|
||||
)
|
||||
),
|
||||
$grid
|
||||
));
|
||||
|
||||
$fields->fieldByName('Root.CustomRules')->setTitle(_t('UserDefinedForm_EmailRecipient.CUSTOMRULESTAB', 'Custom Rules'));
|
||||
$fields->fieldByName('Root.CustomRules')->setTitle(_t('UserDefinedForm_EmailRecipient.CUSTOMRULESTAB', 'Custom Rules'));
|
||||
|
||||
$this->extend('updateCMSFields', $fields);
|
||||
return $fields;
|
||||
}
|
||||
$this->extend('updateCMSFields', $fields);
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 array $context Virtual parameter to allow context to be passed in to check
|
||||
* @return bool
|
||||
*/
|
||||
public function canCreate($member = null) {
|
||||
// Check parent page
|
||||
* @return bool
|
||||
*/
|
||||
public function canCreate($member = null)
|
||||
{
|
||||
// Check parent page
|
||||
$parent = $this->getCanCreateContext(func_get_args());
|
||||
if($parent) {
|
||||
if ($parent) {
|
||||
return $parent->canEdit($member);
|
||||
}
|
||||
|
||||
// Fall back to secure admin permissions
|
||||
return parent::canCreate($member);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to check the parent for this object
|
||||
@ -313,13 +320,14 @@ class UserDefinedForm_EmailRecipient extends DataObject {
|
||||
* @param array $args List of arguments passed to canCreate
|
||||
* @return SiteTree Parent page instance
|
||||
*/
|
||||
protected function getCanCreateContext($args) {
|
||||
protected function getCanCreateContext($args)
|
||||
{
|
||||
// Inspect second parameter to canCreate for a 'Parent' context
|
||||
if(isset($args[1]['Form'])) {
|
||||
if (isset($args[1]['Form'])) {
|
||||
return $args[1]['Form'];
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
|
||||
@ -327,104 +335,111 @@ class UserDefinedForm_EmailRecipient extends DataObject {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canView($member = null) {
|
||||
return $this->Form()->canView($member);
|
||||
}
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canView($member = null)
|
||||
{
|
||||
return $this->Form()->canView($member);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canEdit($member = null) {
|
||||
return $this->Form()->canEdit($member);
|
||||
}
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canEdit($member = null)
|
||||
{
|
||||
return $this->Form()->canEdit($member);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canDelete($member = null) {
|
||||
return $this->canEdit($member);
|
||||
}
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canDelete($member = null)
|
||||
{
|
||||
return $this->canEdit($member);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if this recipient may receive notifications for this submission
|
||||
*
|
||||
* @param array $data
|
||||
* @param Form $form
|
||||
* @return bool
|
||||
*/
|
||||
public function canSend($data, $form) {
|
||||
// Skip if no rules configured
|
||||
$customRules = $this->CustomRules();
|
||||
if(!$customRules->count()) {
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* Determine if this recipient may receive notifications for this submission
|
||||
*
|
||||
* @param array $data
|
||||
* @param Form $form
|
||||
* @return bool
|
||||
*/
|
||||
public function canSend($data, $form)
|
||||
{
|
||||
// Skip if no rules configured
|
||||
$customRules = $this->CustomRules();
|
||||
if (!$customRules->count()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check all rules
|
||||
$isAnd = $this->CustomRulesCondition === 'And';
|
||||
foreach($customRules as $customRule) {
|
||||
$matches = $customRule->matches($data, $form);
|
||||
if($isAnd && !$matches) {
|
||||
return false;
|
||||
}
|
||||
if(!$isAnd && $matches) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Check all rules
|
||||
$isAnd = $this->CustomRulesCondition === 'And';
|
||||
foreach ($customRules as $customRule) {
|
||||
$matches = $customRule->matches($data, $form);
|
||||
if ($isAnd && !$matches) {
|
||||
return false;
|
||||
}
|
||||
if (!$isAnd && $matches) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Once all rules are checked
|
||||
return $isAnd;
|
||||
}
|
||||
// Once all rules are checked
|
||||
return $isAnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the email template saved against the recipient exists on the file system.
|
||||
*
|
||||
* @param string
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function emailTemplateExists($template = '') {
|
||||
$t = ($template ? $template : $this->EmailTemplate);
|
||||
/**
|
||||
* Make sure the email template saved against the recipient exists on the file system.
|
||||
*
|
||||
* @param string
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function emailTemplateExists($template = '')
|
||||
{
|
||||
$t = ($template ? $template : $this->EmailTemplate);
|
||||
|
||||
return in_array($t, $this->getEmailTemplateDropdownValues());
|
||||
}
|
||||
return in_array($t, $this->getEmailTemplateDropdownValues());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the email body for the current email format
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEmailBodyContent() {
|
||||
return $this->SendPlain ? $this->EmailBody : $this->EmailBodyHtml;
|
||||
}
|
||||
/**
|
||||
* Get the email body for the current email format
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEmailBodyContent()
|
||||
{
|
||||
return $this->SendPlain ? $this->EmailBody : $this->EmailBodyHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of email templates suitable for populating the email template dropdown.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getEmailTemplateDropdownValues() {
|
||||
$templates = array();
|
||||
/**
|
||||
* Gets a list of email templates suitable for populating the email template dropdown.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getEmailTemplateDropdownValues()
|
||||
{
|
||||
$templates = array();
|
||||
|
||||
$finder = new SS_FileFinder();
|
||||
$finder->setOption('name_regex', '/^.*\.ss$/');
|
||||
$finder = new SS_FileFinder();
|
||||
$finder->setOption('name_regex', '/^.*\.ss$/');
|
||||
|
||||
$found = $finder->find(BASE_PATH . '/' . UserDefinedForm::config()->email_template_directory);
|
||||
$found = $finder->find(BASE_PATH . '/' . UserDefinedForm::config()->email_template_directory);
|
||||
|
||||
foreach ($found as $key => $value) {
|
||||
$template = pathinfo($value);
|
||||
foreach ($found as $key => $value) {
|
||||
$template = pathinfo($value);
|
||||
|
||||
$templates[$template['filename']] = $template['filename'];
|
||||
}
|
||||
$templates[$template['filename']] = $template['filename'];
|
||||
}
|
||||
|
||||
return $templates;
|
||||
}
|
||||
return $templates;
|
||||
}
|
||||
}
|
||||
|
@ -6,71 +6,74 @@
|
||||
*
|
||||
* @method UserDefinedForm_EmailRecipient Parent()
|
||||
*/
|
||||
class UserDefinedForm_EmailRecipientCondition extends DataObject {
|
||||
class UserDefinedForm_EmailRecipientCondition extends DataObject
|
||||
{
|
||||
|
||||
/**
|
||||
* List of options
|
||||
*
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $condition_options = array(
|
||||
"IsBlank" => "Is blank",
|
||||
"IsNotBlank" => "Is not blank",
|
||||
"Equals" => "Equals",
|
||||
"NotEquals" => "Doesn't equal"
|
||||
);
|
||||
/**
|
||||
* List of options
|
||||
*
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $condition_options = array(
|
||||
"IsBlank" => "Is blank",
|
||||
"IsNotBlank" => "Is not blank",
|
||||
"Equals" => "Equals",
|
||||
"NotEquals" => "Doesn't equal"
|
||||
);
|
||||
|
||||
private static $db = array(
|
||||
'ConditionOption' => 'Enum("IsBlank,IsNotBlank,Equals,NotEquals")',
|
||||
'ConditionValue' => 'Varchar'
|
||||
);
|
||||
private static $db = array(
|
||||
'ConditionOption' => 'Enum("IsBlank,IsNotBlank,Equals,NotEquals")',
|
||||
'ConditionValue' => 'Varchar'
|
||||
);
|
||||
|
||||
private static $has_one = array(
|
||||
'Parent' => 'UserDefinedForm_EmailRecipient',
|
||||
'ConditionField' => 'EditableFormField'
|
||||
);
|
||||
private static $has_one = array(
|
||||
'Parent' => 'UserDefinedForm_EmailRecipient',
|
||||
'ConditionField' => 'EditableFormField'
|
||||
);
|
||||
|
||||
/**
|
||||
* Determine if this rule matches the given condition
|
||||
*
|
||||
* @param array $data
|
||||
* @param Form $form
|
||||
* @return bool
|
||||
*/
|
||||
public function matches($data, $form) {
|
||||
$fieldName = $this->ConditionField()->Name;
|
||||
$fieldValue = isset($data[$fieldName]) ? $data[$fieldName] : null;
|
||||
switch($this->ConditionOption) {
|
||||
case 'IsBlank':
|
||||
return empty($fieldValue);
|
||||
case 'IsNotBlank':
|
||||
return !empty($fieldValue);
|
||||
default:
|
||||
$matches = is_array($fieldValue)
|
||||
? in_array($this->ConditionValue, $fieldValue)
|
||||
: $this->ConditionValue === (string) $fieldValue;
|
||||
return ($this->ConditionOption === 'Equals') === (bool)$matches;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Determine if this rule matches the given condition
|
||||
*
|
||||
* @param array $data
|
||||
* @param Form $form
|
||||
* @return bool
|
||||
*/
|
||||
public function matches($data, $form)
|
||||
{
|
||||
$fieldName = $this->ConditionField()->Name;
|
||||
$fieldValue = isset($data[$fieldName]) ? $data[$fieldName] : null;
|
||||
switch ($this->ConditionOption) {
|
||||
case 'IsBlank':
|
||||
return empty($fieldValue);
|
||||
case 'IsNotBlank':
|
||||
return !empty($fieldValue);
|
||||
default:
|
||||
$matches = is_array($fieldValue)
|
||||
? in_array($this->ConditionValue, $fieldValue)
|
||||
: $this->ConditionValue === (string) $fieldValue;
|
||||
return ($this->ConditionOption === 'Equals') === (bool)$matches;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 array $context Virtual parameter to allow context to be passed in to check
|
||||
* @return bool
|
||||
*/
|
||||
public function canCreate($member = null) {
|
||||
// Check parent page
|
||||
* @return bool
|
||||
*/
|
||||
public function canCreate($member = null)
|
||||
{
|
||||
// Check parent page
|
||||
$parent = $this->getCanCreateContext(func_get_args());
|
||||
if($parent) {
|
||||
if ($parent) {
|
||||
return $parent->canEdit($member);
|
||||
}
|
||||
|
||||
// Fall back to secure admin permissions
|
||||
return parent::canCreate($member);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to check the parent for this object
|
||||
@ -78,13 +81,14 @@ class UserDefinedForm_EmailRecipientCondition extends DataObject {
|
||||
* @param array $args List of arguments passed to canCreate
|
||||
* @return SiteTree Parent page instance
|
||||
*/
|
||||
protected function getCanCreateContext($args) {
|
||||
protected function getCanCreateContext($args)
|
||||
{
|
||||
// Inspect second parameter to canCreate for a 'Parent' context
|
||||
if(isset($args[1]['Parent'])) {
|
||||
if (isset($args[1]['Parent'])) {
|
||||
return $args[1]['Parent'];
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
|
||||
@ -92,30 +96,33 @@ class UserDefinedForm_EmailRecipientCondition extends DataObject {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canView($member = null) {
|
||||
return $this->Parent()->canView($member);
|
||||
}
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canView($member = null)
|
||||
{
|
||||
return $this->Parent()->canView($member);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canEdit($member = null) {
|
||||
return $this->Parent()->canEdit($member);
|
||||
}
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canEdit($member = null)
|
||||
{
|
||||
return $this->Parent()->canEdit($member);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canDelete($member = null) {
|
||||
return $this->canEdit($member);
|
||||
}
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canDelete($member = null)
|
||||
{
|
||||
return $this->canEdit($member);
|
||||
}
|
||||
}
|
||||
|
@ -8,23 +8,26 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class UserFormRecipientEmail extends Email {
|
||||
class UserFormRecipientEmail extends Email
|
||||
{
|
||||
|
||||
protected $ss_template = "SubmittedFormEmail";
|
||||
protected $ss_template = "SubmittedFormEmail";
|
||||
|
||||
protected $data;
|
||||
protected $data;
|
||||
|
||||
public function __construct($submittedFields = null) {
|
||||
parent::__construct($submittedFields = null);
|
||||
}
|
||||
public function __construct($submittedFields = null)
|
||||
{
|
||||
parent::__construct($submittedFields = null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the "Reply-To" header with an email address rather than append as
|
||||
* {@link Email::replyTo} does.
|
||||
*
|
||||
* @param string $email The email address to set the "Reply-To" header to
|
||||
*/
|
||||
public function setReplyTo($email) {
|
||||
$this->customHeaders['Reply-To'] = $email;
|
||||
}
|
||||
/**
|
||||
* Set the "Reply-To" header with an email address rather than append as
|
||||
* {@link Email::replyTo} does.
|
||||
*
|
||||
* @param string $email The email address to set the "Reply-To" header to
|
||||
*/
|
||||
public function setReplyTo($email)
|
||||
{
|
||||
$this->customHeaders['Reply-To'] = $email;
|
||||
}
|
||||
}
|
||||
|
@ -5,47 +5,50 @@
|
||||
*
|
||||
* @package userforms
|
||||
*/
|
||||
class UserFormRecipientItemRequest extends GridFieldDetailForm_ItemRequest {
|
||||
class UserFormRecipientItemRequest extends GridFieldDetailForm_ItemRequest
|
||||
{
|
||||
|
||||
private static $allowed_actions = array(
|
||||
'edit',
|
||||
'view',
|
||||
'ItemEditForm',
|
||||
'preview'
|
||||
);
|
||||
private static $allowed_actions = array(
|
||||
'edit',
|
||||
'view',
|
||||
'ItemEditForm',
|
||||
'preview'
|
||||
);
|
||||
|
||||
/**
|
||||
* Renders a preview of the recipient email.
|
||||
*/
|
||||
public function preview() {
|
||||
return $this->customise(new ArrayData(array(
|
||||
'Body' => $this->record->getEmailBodyContent(),
|
||||
'HideFormData' => $this->record->HideFormData,
|
||||
'Fields' => $this->getPreviewFieldData()
|
||||
)))->renderWith($this->record->EmailTemplate);
|
||||
}
|
||||
/**
|
||||
* Renders a preview of the recipient email.
|
||||
*/
|
||||
public function preview()
|
||||
{
|
||||
return $this->customise(new ArrayData(array(
|
||||
'Body' => $this->record->getEmailBodyContent(),
|
||||
'HideFormData' => $this->record->HideFormData,
|
||||
'Fields' => $this->getPreviewFieldData()
|
||||
)))->renderWith($this->record->EmailTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get some placeholder field values to display in the preview
|
||||
* @return ArrayList
|
||||
*/
|
||||
private function getPreviewFieldData() {
|
||||
$data = new ArrayList();
|
||||
/**
|
||||
* Get some placeholder field values to display in the preview
|
||||
* @return ArrayList
|
||||
*/
|
||||
private function getPreviewFieldData()
|
||||
{
|
||||
$data = new ArrayList();
|
||||
|
||||
$fields = $this->record->Form()->Fields()->filter(array(
|
||||
'ClassName:not' => 'EditableLiteralField',
|
||||
'ClassName:not' => 'EditableFormHeading'
|
||||
));
|
||||
$fields = $this->record->Form()->Fields()->filter(array(
|
||||
'ClassName:not' => 'EditableLiteralField',
|
||||
'ClassName:not' => 'EditableFormHeading'
|
||||
));
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$data->push(new ArrayData(array(
|
||||
'Name' => $field->Name,
|
||||
'Title' => $field->Title,
|
||||
'Value' => '$' . $field->Name,
|
||||
'FormattedValue' => '$' . $field->Name
|
||||
)));
|
||||
}
|
||||
foreach ($fields as $field) {
|
||||
$data->push(new ArrayData(array(
|
||||
'Name' => $field->Name,
|
||||
'Title' => $field->Title,
|
||||
'Value' => '$' . $field->Name,
|
||||
'FormattedValue' => '$' . $field->Name
|
||||
)));
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
@ -7,63 +7,68 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class SubmittedFileField extends SubmittedFormField {
|
||||
class SubmittedFileField extends SubmittedFormField
|
||||
{
|
||||
|
||||
private static $has_one = array(
|
||||
"UploadedFile" => "File"
|
||||
);
|
||||
private static $has_one = array(
|
||||
"UploadedFile" => "File"
|
||||
);
|
||||
|
||||
/**
|
||||
* Return the value of this field for inclusion into things such as
|
||||
* reports.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFormattedValue() {
|
||||
$name = $this->getFileName();
|
||||
$link = $this->getLink();
|
||||
$title = _t('SubmittedFileField.DOWNLOADFILE', 'Download File');
|
||||
/**
|
||||
* Return the value of this field for inclusion into things such as
|
||||
* reports.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFormattedValue()
|
||||
{
|
||||
$name = $this->getFileName();
|
||||
$link = $this->getLink();
|
||||
$title = _t('SubmittedFileField.DOWNLOADFILE', 'Download File');
|
||||
|
||||
if($link) {
|
||||
return DBField::create_field('HTMLText', sprintf(
|
||||
'%s - <a href="%s" target="_blank">%s</a>',
|
||||
$name, $link, $title
|
||||
));
|
||||
}
|
||||
if ($link) {
|
||||
return DBField::create_field('HTMLText', sprintf(
|
||||
'%s - <a href="%s" target="_blank">%s</a>',
|
||||
$name, $link, $title
|
||||
));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value for this field in the CSV export.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getExportValue() {
|
||||
return ($link = $this->getLink()) ? $link : "";
|
||||
}
|
||||
/**
|
||||
* Return the value for this field in the CSV export.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getExportValue()
|
||||
{
|
||||
return ($link = $this->getLink()) ? $link : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the link for the file attached to this submitted form field.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLink() {
|
||||
if($file = $this->UploadedFile()) {
|
||||
if(trim($file->getFilename(), '/') != trim(ASSETS_DIR,'/')) {
|
||||
return $this->UploadedFile()->URL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Return the link for the file attached to this submitted form field.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLink()
|
||||
{
|
||||
if ($file = $this->UploadedFile()) {
|
||||
if (trim($file->getFilename(), '/') != trim(ASSETS_DIR, '/')) {
|
||||
return $this->UploadedFile()->URL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the file, if present
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFileName() {
|
||||
if($this->UploadedFile()) {
|
||||
return $this->UploadedFile()->Name;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Return the name of the file, if present
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFileName()
|
||||
{
|
||||
if ($this->UploadedFile()) {
|
||||
return $this->UploadedFile()->Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,143 +5,150 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class SubmittedForm extends DataObject {
|
||||
class SubmittedForm extends DataObject
|
||||
{
|
||||
|
||||
private static $has_one = array(
|
||||
"SubmittedBy" => "Member",
|
||||
"Parent" => "UserDefinedForm",
|
||||
);
|
||||
private static $has_one = array(
|
||||
"SubmittedBy" => "Member",
|
||||
"Parent" => "UserDefinedForm",
|
||||
);
|
||||
|
||||
private static $has_many = array(
|
||||
"Values" => "SubmittedFormField"
|
||||
);
|
||||
private static $has_many = array(
|
||||
"Values" => "SubmittedFormField"
|
||||
);
|
||||
|
||||
private static $summary_fields = array(
|
||||
'ID',
|
||||
'Created'
|
||||
);
|
||||
private static $summary_fields = array(
|
||||
'ID',
|
||||
'Created'
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns the value of a relation or, in the case of this form, the value
|
||||
* of a given child {@link SubmittedFormField}
|
||||
*
|
||||
* @param string
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function relField($fieldName) {
|
||||
// default case
|
||||
if($value = parent::relField($fieldName)) {
|
||||
return $value;
|
||||
}
|
||||
/**
|
||||
* Returns the value of a relation or, in the case of this form, the value
|
||||
* of a given child {@link SubmittedFormField}
|
||||
*
|
||||
* @param string
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function relField($fieldName)
|
||||
{
|
||||
// default case
|
||||
if ($value = parent::relField($fieldName)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
// check values for a form field with the matching name.
|
||||
$formField = SubmittedFormField::get()->filter(array(
|
||||
'ParentID' => $this->ID,
|
||||
'Name' => $fieldName
|
||||
))->first();
|
||||
// check values for a form field with the matching name.
|
||||
$formField = SubmittedFormField::get()->filter(array(
|
||||
'ParentID' => $this->ID,
|
||||
'Name' => $fieldName
|
||||
))->first();
|
||||
|
||||
if($formField) {
|
||||
return $formField->getFormattedValue();
|
||||
}
|
||||
}
|
||||
if ($formField) {
|
||||
return $formField->getFormattedValue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields() {
|
||||
/**
|
||||
* @return FieldList
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
$self = $this;
|
||||
|
||||
$self = $this;
|
||||
$this->beforeUpdateCMSFields(function ($fields) use ($self) {
|
||||
$fields->removeByName('Values');
|
||||
$fields->dataFieldByName('SubmittedByID')->setDisabled(true);
|
||||
|
||||
$this->beforeUpdateCMSFields(function($fields) use ($self) {
|
||||
$fields->removeByName('Values');
|
||||
$fields->dataFieldByName('SubmittedByID')->setDisabled(true);
|
||||
$values = new GridField(
|
||||
'Values',
|
||||
'SubmittedFormField',
|
||||
$self->Values()->sort('Created', 'ASC')
|
||||
);
|
||||
|
||||
$values = new GridField(
|
||||
'Values',
|
||||
'SubmittedFormField',
|
||||
$self->Values()->sort('Created', 'ASC')
|
||||
);
|
||||
$config = new GridFieldConfig();
|
||||
$config->addComponent(new GridFieldDataColumns());
|
||||
$config->addComponent(new GridFieldExportButton());
|
||||
$config->addComponent(new GridFieldPrintButton());
|
||||
$values->setConfig($config);
|
||||
|
||||
$config = new GridFieldConfig();
|
||||
$config->addComponent(new GridFieldDataColumns());
|
||||
$config->addComponent(new GridFieldExportButton());
|
||||
$config->addComponent(new GridFieldPrintButton());
|
||||
$values->setConfig($config);
|
||||
$fields->addFieldToTab('Root.Main', $values);
|
||||
});
|
||||
|
||||
$fields->addFieldToTab('Root.Main', $values);
|
||||
});
|
||||
$fields = parent::getCMSFields();
|
||||
|
||||
$fields = parent::getCMSFields();
|
||||
return $fields;
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canCreate($member = null)
|
||||
{
|
||||
$extended = $this->extendedCan(__FUNCTION__, $member);
|
||||
if ($extended !== null) {
|
||||
return $extended;
|
||||
}
|
||||
return $this->Parent()->canCreate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canCreate($member = null) {
|
||||
$extended = $this->extendedCan(__FUNCTION__, $member);
|
||||
if($extended !== null) {
|
||||
return $extended;
|
||||
}
|
||||
return $this->Parent()->canCreate();
|
||||
}
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canView($member = null)
|
||||
{
|
||||
$extended = $this->extendedCan(__FUNCTION__, $member);
|
||||
if ($extended !== null) {
|
||||
return $extended;
|
||||
}
|
||||
return $this->Parent()->canView();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canView($member = null) {
|
||||
$extended = $this->extendedCan(__FUNCTION__, $member);
|
||||
if($extended !== null) {
|
||||
return $extended;
|
||||
}
|
||||
return $this->Parent()->canView();
|
||||
}
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canEdit($member = null)
|
||||
{
|
||||
$extended = $this->extendedCan(__FUNCTION__, $member);
|
||||
if ($extended !== null) {
|
||||
return $extended;
|
||||
}
|
||||
return $this->Parent()->canEdit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canEdit($member = null) {
|
||||
$extended = $this->extendedCan(__FUNCTION__, $member);
|
||||
if($extended !== null) {
|
||||
return $extended;
|
||||
}
|
||||
return $this->Parent()->canEdit();
|
||||
}
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canDelete($member = null)
|
||||
{
|
||||
$extended = $this->extendedCan(__FUNCTION__, $member);
|
||||
if ($extended !== null) {
|
||||
return $extended;
|
||||
}
|
||||
return $this->Parent()->canDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canDelete($member = null) {
|
||||
$extended = $this->extendedCan(__FUNCTION__, $member);
|
||||
if($extended !== null) {
|
||||
return $extended;
|
||||
}
|
||||
return $this->Parent()->canDelete();
|
||||
}
|
||||
/**
|
||||
* Before we delete this form make sure we delete all the
|
||||
* field values so that we don't leave old data round
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function onBeforeDelete()
|
||||
{
|
||||
if ($this->Values()) {
|
||||
foreach ($this->Values() as $value) {
|
||||
$value->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Before we delete this form make sure we delete all the
|
||||
* field values so that we don't leave old data round
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function onBeforeDelete() {
|
||||
if($this->Values()) {
|
||||
foreach($this->Values() as $value) {
|
||||
$value->delete();
|
||||
}
|
||||
}
|
||||
|
||||
parent::onBeforeDelete();
|
||||
}
|
||||
parent::onBeforeDelete();
|
||||
}
|
||||
}
|
||||
|
@ -5,93 +5,101 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class SubmittedFormField extends DataObject {
|
||||
class SubmittedFormField extends DataObject
|
||||
{
|
||||
|
||||
private static $db = array(
|
||||
"Name" => "Varchar",
|
||||
"Value" => "Text",
|
||||
"Title" => "Varchar(255)"
|
||||
);
|
||||
private static $db = array(
|
||||
"Name" => "Varchar",
|
||||
"Value" => "Text",
|
||||
"Title" => "Varchar(255)"
|
||||
);
|
||||
|
||||
private static $has_one = array(
|
||||
"Parent" => "SubmittedForm"
|
||||
);
|
||||
private static $has_one = array(
|
||||
"Parent" => "SubmittedForm"
|
||||
);
|
||||
|
||||
private static $summary_fields = array(
|
||||
'Title' => 'Title',
|
||||
'FormattedValue' => 'Value'
|
||||
);
|
||||
private static $summary_fields = array(
|
||||
'Title' => 'Title',
|
||||
'FormattedValue' => 'Value'
|
||||
);
|
||||
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canCreate($member = null) {
|
||||
return $this->Parent()->canCreate();
|
||||
}
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canCreate($member = null)
|
||||
{
|
||||
return $this->Parent()->canCreate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canView($member = null) {
|
||||
return $this->Parent()->canView();
|
||||
}
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canView($member = null)
|
||||
{
|
||||
return $this->Parent()->canView();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canEdit($member = null) {
|
||||
return $this->Parent()->canEdit();
|
||||
}
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canEdit($member = null)
|
||||
{
|
||||
return $this->Parent()->canEdit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canDelete($member = null) {
|
||||
return $this->Parent()->canDelete();
|
||||
}
|
||||
/**
|
||||
* @param Member
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canDelete($member = null)
|
||||
{
|
||||
return $this->Parent()->canDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a formatted value for the reports and email notifications.
|
||||
* Converts new lines (which are stored in the database text field) as
|
||||
* <brs> so they will output as newlines in the reports
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFormattedValue() {
|
||||
return nl2br($this->dbObject('Value')->ATT());
|
||||
}
|
||||
/**
|
||||
* Generate a formatted value for the reports and email notifications.
|
||||
* Converts new lines (which are stored in the database text field) as
|
||||
* <brs> so they will output as newlines in the reports
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFormattedValue()
|
||||
{
|
||||
return nl2br($this->dbObject('Value')->ATT());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of this submitted form field suitable for inclusion
|
||||
* into the CSV
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function getExportValue() {
|
||||
return $this->Value;
|
||||
}
|
||||
/**
|
||||
* Return the value of this submitted form field suitable for inclusion
|
||||
* into the CSV
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function getExportValue()
|
||||
{
|
||||
return $this->Value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find equivalent editable field for this submission.
|
||||
*
|
||||
* Note the field may have been modified or deleted from the original form
|
||||
* so this may not always return the data you expect. If you need to save
|
||||
* a particular state of editable form field at time of submission, copy
|
||||
* that value to the submission.
|
||||
*
|
||||
* @return EditableFormField
|
||||
*/
|
||||
public function getEditableField() {
|
||||
return $this->Parent()->Parent()->Fields()->filter(array(
|
||||
'Name' => $this->Name
|
||||
))->First();
|
||||
}
|
||||
/**
|
||||
* Find equivalent editable field for this submission.
|
||||
*
|
||||
* Note the field may have been modified or deleted from the original form
|
||||
* so this may not always return the data you expect. If you need to save
|
||||
* a particular state of editable form field at time of submission, copy
|
||||
* that value to the submission.
|
||||
*
|
||||
* @return EditableFormField
|
||||
*/
|
||||
public function getEditableField()
|
||||
{
|
||||
return $this->Parent()->Parent()->Fields()->filter(array(
|
||||
'Name' => $this->Name
|
||||
))->First();
|
||||
}
|
||||
}
|
||||
|
@ -2,53 +2,56 @@
|
||||
|
||||
use SilverStripe\Forms\SegmentFieldModifier\AbstractSegmentFieldModifier;
|
||||
|
||||
class DisambiguationSegmentFieldModifier extends AbstractSegmentFieldModifier {
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPreview($value) {
|
||||
if($this->form instanceof Form && $record = $this->form->getRecord()) {
|
||||
$parent = $record->Parent();
|
||||
class DisambiguationSegmentFieldModifier extends AbstractSegmentFieldModifier
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPreview($value)
|
||||
{
|
||||
if ($this->form instanceof Form && $record = $this->form->getRecord()) {
|
||||
$parent = $record->Parent();
|
||||
|
||||
$try = $value;
|
||||
$try = $value;
|
||||
|
||||
$sibling = EditableformField::get()
|
||||
->filter('ParentID', $parent->ID)
|
||||
->filter('Name', $try)
|
||||
->where('"ID" != ' . $record->ID)
|
||||
->first();
|
||||
$sibling = EditableformField::get()
|
||||
->filter('ParentID', $parent->ID)
|
||||
->filter('Name', $try)
|
||||
->where('"ID" != ' . $record->ID)
|
||||
->first();
|
||||
|
||||
$counter = 1;
|
||||
$counter = 1;
|
||||
|
||||
while($sibling !== null) {
|
||||
$try = $value . '_' . $counter++;
|
||||
while ($sibling !== null) {
|
||||
$try = $value . '_' . $counter++;
|
||||
|
||||
$sibling = EditableformField::get()
|
||||
->filter('ParentID', $parent->ID)
|
||||
->filter('Name', $try)
|
||||
->first();
|
||||
}
|
||||
$sibling = EditableformField::get()
|
||||
->filter('ParentID', $parent->ID)
|
||||
->filter('Name', $try)
|
||||
->first();
|
||||
}
|
||||
|
||||
if ($try !== $value) {
|
||||
return $try;
|
||||
}
|
||||
}
|
||||
if ($try !== $value) {
|
||||
return $try;
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSuggestion($value) {
|
||||
return $this->getPreview($value);
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSuggestion($value)
|
||||
{
|
||||
return $this->getPreview($value);
|
||||
}
|
||||
}
|
||||
|
@ -2,26 +2,29 @@
|
||||
|
||||
use SilverStripe\Forms\SegmentFieldModifier\SlugSegmentFieldModifier;
|
||||
|
||||
class UnderscoreSegmentFieldModifier extends SlugSegmentFieldModifier {
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPreview($value) {
|
||||
return str_replace('-', '_', parent::getPreview($value));
|
||||
}
|
||||
class UnderscoreSegmentFieldModifier extends SlugSegmentFieldModifier
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPreview($value)
|
||||
{
|
||||
return str_replace('-', '_', parent::getPreview($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSuggestion($value) {
|
||||
return str_replace('-', '_', parent::getSuggestion($value));
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSuggestion($value)
|
||||
{
|
||||
return str_replace('-', '_', parent::getSuggestion($value));
|
||||
}
|
||||
}
|
||||
|
@ -8,54 +8,54 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class UserFormsColumnCleanTask extends MigrationTask {
|
||||
class UserFormsColumnCleanTask extends MigrationTask
|
||||
{
|
||||
|
||||
protected $title = "UserForms EditableFormField Column Clean task";
|
||||
protected $title = "UserForms EditableFormField Column Clean task";
|
||||
|
||||
protected $description = "Removes unused columns from EditableFormField for MySQL databases;";
|
||||
protected $description = "Removes unused columns from EditableFormField for MySQL databases;";
|
||||
|
||||
protected $tables = array('EditableFormField');
|
||||
protected $tables = array('EditableFormField');
|
||||
|
||||
protected $keepColumns = array('ID');
|
||||
protected $keepColumns = array('ID');
|
||||
|
||||
/**
|
||||
* Publish the existing forms.
|
||||
*
|
||||
*/
|
||||
public function run($request) {
|
||||
foreach ($this->tables as $db) {
|
||||
$obj = new $db();
|
||||
$columns = $obj->database_fields($db);
|
||||
$query = "SHOW COLUMNS FROM $db";
|
||||
$liveColumns = DB::query($query)->column();
|
||||
$backedUp = 0;
|
||||
$query = "SHOW TABLES LIKE 'Backup_$db'";
|
||||
$tableExists = DB::query($query)->value();
|
||||
if ($tableExists != null) {
|
||||
echo "Tasks run already on $db exiting";
|
||||
return;
|
||||
}
|
||||
$backedUp = 0;
|
||||
foreach ($liveColumns as $index => $column) {
|
||||
if ($backedUp == 0) {
|
||||
echo "Backing up $db <br />";
|
||||
echo "Creating Backup_$db <br />";
|
||||
// backup table
|
||||
$query = "CREATE TABLE Backup_$db LIKE $db";
|
||||
DB::query($query);
|
||||
echo "Populating Backup_$db <br />";
|
||||
$query = "INSERT Backup_$db SELECT * FROM $db";
|
||||
DB::query($query);
|
||||
$backedUp = 1;
|
||||
}
|
||||
if (!isset($columns[$column]) && !in_array($column, $this->keepColumns)) {
|
||||
echo "Dropping $column from $db <br />";
|
||||
$query = "ALTER TABLE $db DROP COLUMN $column";
|
||||
DB::query($query);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Publish the existing forms.
|
||||
*
|
||||
*/
|
||||
public function run($request)
|
||||
{
|
||||
foreach ($this->tables as $db) {
|
||||
$obj = new $db();
|
||||
$columns = $obj->database_fields($db);
|
||||
$query = "SHOW COLUMNS FROM $db";
|
||||
$liveColumns = DB::query($query)->column();
|
||||
$backedUp = 0;
|
||||
$query = "SHOW TABLES LIKE 'Backup_$db'";
|
||||
$tableExists = DB::query($query)->value();
|
||||
if ($tableExists != null) {
|
||||
echo "Tasks run already on $db exiting";
|
||||
return;
|
||||
}
|
||||
$backedUp = 0;
|
||||
foreach ($liveColumns as $index => $column) {
|
||||
if ($backedUp == 0) {
|
||||
echo "Backing up $db <br />";
|
||||
echo "Creating Backup_$db <br />";
|
||||
// backup table
|
||||
$query = "CREATE TABLE Backup_$db LIKE $db";
|
||||
DB::query($query);
|
||||
echo "Populating Backup_$db <br />";
|
||||
$query = "INSERT Backup_$db SELECT * FROM $db";
|
||||
DB::query($query);
|
||||
$backedUp = 1;
|
||||
}
|
||||
if (!isset($columns[$column]) && !in_array($column, $this->keepColumns)) {
|
||||
echo "Dropping $column from $db <br />";
|
||||
$query = "ALTER TABLE $db DROP COLUMN $column";
|
||||
DB::query($query);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,216 +3,225 @@
|
||||
/**
|
||||
* Service to support upgrade of userforms module
|
||||
*/
|
||||
class UserFormsUpgradeService {
|
||||
class UserFormsUpgradeService
|
||||
{
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $quiet;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $quiet;
|
||||
|
||||
public function run() {
|
||||
$this->log("Upgrading formfield rules and custom settings");
|
||||
public function run()
|
||||
{
|
||||
$this->log("Upgrading formfield rules and custom settings");
|
||||
|
||||
// List of rules that have been created in all stages
|
||||
$fields = Versioned::get_including_deleted('EditableFormField');
|
||||
foreach($fields as $field) {
|
||||
$this->upgradeField($field);
|
||||
}
|
||||
}
|
||||
// List of rules that have been created in all stages
|
||||
$fields = Versioned::get_including_deleted('EditableFormField');
|
||||
foreach ($fields as $field) {
|
||||
$this->upgradeField($field);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate a versioned field in all stages
|
||||
*
|
||||
* @param EditableFormField $field
|
||||
*/
|
||||
protected function upgradeField(EditableFormField $field) {
|
||||
$this->log("Upgrading formfield ID = ".$field->ID);
|
||||
/**
|
||||
* Migrate a versioned field in all stages
|
||||
*
|
||||
* @param EditableFormField $field
|
||||
*/
|
||||
protected function upgradeField(EditableFormField $field)
|
||||
{
|
||||
$this->log("Upgrading formfield ID = ".$field->ID);
|
||||
|
||||
// Check versions this field exists on
|
||||
$filter = sprintf('"EditableFormField"."ID" = \'%d\' AND "Migrated" = 0', $field->ID);
|
||||
$stageField = Versioned::get_one_by_stage('EditableFormField', 'Stage', $filter);
|
||||
$liveField = Versioned::get_one_by_stage('EditableFormField', 'Live', $filter);
|
||||
// Check versions this field exists on
|
||||
$filter = sprintf('"EditableFormField"."ID" = \'%d\' AND "Migrated" = 0', $field->ID);
|
||||
$stageField = Versioned::get_one_by_stage('EditableFormField', 'Stage', $filter);
|
||||
$liveField = Versioned::get_one_by_stage('EditableFormField', 'Live', $filter);
|
||||
|
||||
if($stageField) {
|
||||
$this->upgradeFieldInStage($stageField, 'Stage');
|
||||
}
|
||||
if ($stageField) {
|
||||
$this->upgradeFieldInStage($stageField, 'Stage');
|
||||
}
|
||||
|
||||
if($liveField) {
|
||||
$this->upgradeFieldInStage($liveField, 'Live');
|
||||
}
|
||||
}
|
||||
if ($liveField) {
|
||||
$this->upgradeFieldInStage($liveField, 'Live');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate a versioned field in a single stage
|
||||
*
|
||||
* @param EditableFormField $field
|
||||
* @param stage $stage
|
||||
*/
|
||||
protected function upgradeFieldInStage(EditableFormField $field, $stage) {
|
||||
Versioned::reading_stage($stage);
|
||||
/**
|
||||
* Migrate a versioned field in a single stage
|
||||
*
|
||||
* @param EditableFormField $field
|
||||
* @param stage $stage
|
||||
*/
|
||||
protected function upgradeFieldInStage(EditableFormField $field, $stage)
|
||||
{
|
||||
Versioned::reading_stage($stage);
|
||||
|
||||
// Migrate field rules
|
||||
$this->migrateRules($field, $stage);
|
||||
// Migrate field rules
|
||||
$this->migrateRules($field, $stage);
|
||||
|
||||
// Migrate custom settings
|
||||
$this->migrateCustomSettings($field, $stage);
|
||||
// Migrate custom settings
|
||||
$this->migrateCustomSettings($field, $stage);
|
||||
|
||||
// Flag as migrated
|
||||
$field->Migrated = true;
|
||||
$field->write();
|
||||
}
|
||||
// Flag as migrated
|
||||
$field->Migrated = true;
|
||||
$field->write();
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate custom rules for the given field
|
||||
*
|
||||
* @param EditableFormField $field
|
||||
* @param string $stage
|
||||
*/
|
||||
protected function migrateRules(EditableFormField $field, $stage) {
|
||||
$rulesData = $field->CustomRules
|
||||
? unserialize($field->CustomRules)
|
||||
: array();
|
||||
/**
|
||||
* Migrate custom rules for the given field
|
||||
*
|
||||
* @param EditableFormField $field
|
||||
* @param string $stage
|
||||
*/
|
||||
protected function migrateRules(EditableFormField $field, $stage)
|
||||
{
|
||||
$rulesData = $field->CustomRules
|
||||
? unserialize($field->CustomRules)
|
||||
: array();
|
||||
|
||||
// Skip blank rules or fields with custom rules already
|
||||
if(empty($rulesData) || $field->DisplayRules()->count()) {
|
||||
return;
|
||||
}
|
||||
// Skip blank rules or fields with custom rules already
|
||||
if (empty($rulesData) || $field->DisplayRules()->count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check value of this condition
|
||||
foreach($rulesData as $ruleDataItem) {
|
||||
if(empty($ruleDataItem['ConditionOption']) || empty($ruleDataItem['Display'])) {
|
||||
continue;
|
||||
}
|
||||
// Check value of this condition
|
||||
foreach ($rulesData as $ruleDataItem) {
|
||||
if (empty($ruleDataItem['ConditionOption']) || empty($ruleDataItem['Display'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get data for this rule
|
||||
$conditionOption = $ruleDataItem['ConditionOption'];
|
||||
$display = $ruleDataItem['Display'];
|
||||
$conditionFieldName = empty($ruleDataItem['ConditionField']) ? null : $ruleDataItem['ConditionField'];
|
||||
$value = isset($ruleDataItem['Value'])
|
||||
? $ruleDataItem['Value']
|
||||
: null;
|
||||
// Get data for this rule
|
||||
$conditionOption = $ruleDataItem['ConditionOption'];
|
||||
$display = $ruleDataItem['Display'];
|
||||
$conditionFieldName = empty($ruleDataItem['ConditionField']) ? null : $ruleDataItem['ConditionField'];
|
||||
$value = isset($ruleDataItem['Value'])
|
||||
? $ruleDataItem['Value']
|
||||
: null;
|
||||
|
||||
// Create rule
|
||||
$rule = $this->findOrCreateRule($field, $stage, $conditionOption, $display, $conditionFieldName, $value);
|
||||
$this->log("Upgrading rule ID = " . $rule->ID);
|
||||
}
|
||||
}
|
||||
// Create rule
|
||||
$rule = $this->findOrCreateRule($field, $stage, $conditionOption, $display, $conditionFieldName, $value);
|
||||
$this->log("Upgrading rule ID = " . $rule->ID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Migrate custom settings for the given field
|
||||
*
|
||||
* @param EditableFormField $field
|
||||
* @param string $stage
|
||||
*/
|
||||
protected function migrateCustomSettings(EditableFormField $field, $stage) {
|
||||
// Custom settings include:
|
||||
// - ExtraClass
|
||||
// - RightTitle
|
||||
// - ShowOnLoad (show or '' are treated as true)
|
||||
//
|
||||
// - CheckedDefault (new field on EditableCheckbox - should be read from old "default" value)
|
||||
// - Default (EditableCheckbox)
|
||||
// - DefaultToToday (EditableDateField)
|
||||
// - Folder (EditableFileField)
|
||||
// - Level (EditableFormHeading)
|
||||
// - HideFromReports (EditableFormHeading / EditableLiteralField)
|
||||
// - Content (EditableLiteralField)
|
||||
// - GroupID (EditableMemberListField)
|
||||
// - MinValue (EditableNumericField)
|
||||
// - MaxValue (EditableNumericField)
|
||||
// - MinLength (EditableTextField)
|
||||
// - MaxLength (EditableTextField)
|
||||
// - Rows (EditableTextField)
|
||||
/**
|
||||
* Migrate custom settings for the given field
|
||||
*
|
||||
* @param EditableFormField $field
|
||||
* @param string $stage
|
||||
*/
|
||||
protected function migrateCustomSettings(EditableFormField $field, $stage)
|
||||
{
|
||||
// Custom settings include:
|
||||
// - ExtraClass
|
||||
// - RightTitle
|
||||
// - ShowOnLoad (show or '' are treated as true)
|
||||
//
|
||||
// - CheckedDefault (new field on EditableCheckbox - should be read from old "default" value)
|
||||
// - Default (EditableCheckbox)
|
||||
// - DefaultToToday (EditableDateField)
|
||||
// - Folder (EditableFileField)
|
||||
// - Level (EditableFormHeading)
|
||||
// - HideFromReports (EditableFormHeading / EditableLiteralField)
|
||||
// - Content (EditableLiteralField)
|
||||
// - GroupID (EditableMemberListField)
|
||||
// - MinValue (EditableNumericField)
|
||||
// - MaxValue (EditableNumericField)
|
||||
// - MinLength (EditableTextField)
|
||||
// - MaxLength (EditableTextField)
|
||||
// - Rows (EditableTextField)
|
||||
|
||||
$customSettings = $field->CustomSettings
|
||||
? unserialize($field->CustomSettings)
|
||||
: array();
|
||||
$customSettings = $field->CustomSettings
|
||||
? unserialize($field->CustomSettings)
|
||||
: array();
|
||||
|
||||
// Skip blank rules or fields with custom rules already
|
||||
if(empty($customSettings)) {
|
||||
return;
|
||||
}
|
||||
// Skip blank rules or fields with custom rules already
|
||||
if (empty($customSettings)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$field->migrateSettings($customSettings);
|
||||
$field->write();
|
||||
}
|
||||
$field->migrateSettings($customSettings);
|
||||
$field->write();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create or find an existing field with the matched specification
|
||||
*
|
||||
* @param EditableFormField $field
|
||||
* @param string $stage
|
||||
* @param string $conditionOption
|
||||
* @param string $display
|
||||
* @param string $conditionFieldName
|
||||
* @param string $value
|
||||
* @return EditableCustomRule
|
||||
*/
|
||||
protected function findOrCreateRule(EditableFormField $field, $stage, $conditionOption, $display, $conditionFieldName, $value) {
|
||||
// Get id of field
|
||||
$conditionField = $conditionFieldName
|
||||
? EditableFormField::get()->filter('Name', $conditionFieldName)->first()
|
||||
: null;
|
||||
/**
|
||||
* Create or find an existing field with the matched specification
|
||||
*
|
||||
* @param EditableFormField $field
|
||||
* @param string $stage
|
||||
* @param string $conditionOption
|
||||
* @param string $display
|
||||
* @param string $conditionFieldName
|
||||
* @param string $value
|
||||
* @return EditableCustomRule
|
||||
*/
|
||||
protected function findOrCreateRule(EditableFormField $field, $stage, $conditionOption, $display, $conditionFieldName, $value)
|
||||
{
|
||||
// Get id of field
|
||||
$conditionField = $conditionFieldName
|
||||
? EditableFormField::get()->filter('Name', $conditionFieldName)->first()
|
||||
: null;
|
||||
|
||||
// If live, search stage record for matching one
|
||||
if($stage === 'Live') {
|
||||
$list = Versioned::get_by_stage('EditableCustomRule', 'Stage')
|
||||
->filter(array(
|
||||
'ParentID' => $field->ID,
|
||||
'ConditionFieldID' => $conditionField ? $conditionField->ID : 0,
|
||||
'Display' => $display,
|
||||
'ConditionOption' => $conditionOption
|
||||
));
|
||||
if($value) {
|
||||
$list = $list->filter('FieldValue', $value);
|
||||
} else {
|
||||
$list = $list->where('"FieldValue" IS NULL OR "FieldValue" = \'\'');
|
||||
}
|
||||
$rule = $list->first();
|
||||
if($rule) {
|
||||
$rule->write();
|
||||
$rule->publish("Stage", "Live");
|
||||
return $rule;
|
||||
}
|
||||
}
|
||||
// If live, search stage record for matching one
|
||||
if ($stage === 'Live') {
|
||||
$list = Versioned::get_by_stage('EditableCustomRule', 'Stage')
|
||||
->filter(array(
|
||||
'ParentID' => $field->ID,
|
||||
'ConditionFieldID' => $conditionField ? $conditionField->ID : 0,
|
||||
'Display' => $display,
|
||||
'ConditionOption' => $conditionOption
|
||||
));
|
||||
if ($value) {
|
||||
$list = $list->filter('FieldValue', $value);
|
||||
} else {
|
||||
$list = $list->where('"FieldValue" IS NULL OR "FieldValue" = \'\'');
|
||||
}
|
||||
$rule = $list->first();
|
||||
if ($rule) {
|
||||
$rule->write();
|
||||
$rule->publish("Stage", "Live");
|
||||
return $rule;
|
||||
}
|
||||
}
|
||||
|
||||
// If none found, or in stage, create new record
|
||||
$rule = new EditableCustomRule();
|
||||
$rule->ParentID = $field->ID;
|
||||
$rule->ConditionFieldID = $conditionField ? $conditionField->ID : 0;
|
||||
$rule->Display = $display;
|
||||
$rule->ConditionOption = $conditionOption;
|
||||
$rule->FieldValue = $value;
|
||||
$rule->write();
|
||||
return $rule;
|
||||
}
|
||||
// If none found, or in stage, create new record
|
||||
$rule = new EditableCustomRule();
|
||||
$rule->ParentID = $field->ID;
|
||||
$rule->ConditionFieldID = $conditionField ? $conditionField->ID : 0;
|
||||
$rule->Display = $display;
|
||||
$rule->ConditionOption = $conditionOption;
|
||||
$rule->FieldValue = $value;
|
||||
$rule->write();
|
||||
return $rule;
|
||||
}
|
||||
|
||||
public function log($message) {
|
||||
if($this->getQuiet()) {
|
||||
return;
|
||||
}
|
||||
if(Director::is_cli()) {
|
||||
echo "{$message}\n";
|
||||
} else {
|
||||
echo "{$message}<br />";
|
||||
}
|
||||
}
|
||||
public function log($message)
|
||||
{
|
||||
if ($this->getQuiet()) {
|
||||
return;
|
||||
}
|
||||
if (Director::is_cli()) {
|
||||
echo "{$message}\n";
|
||||
} else {
|
||||
echo "{$message}<br />";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if this service should be quiet
|
||||
*
|
||||
* @param bool $quiet
|
||||
* @return $ths
|
||||
*/
|
||||
public function setQuiet($quiet) {
|
||||
$this->quiet = $quiet;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getQuiet() {
|
||||
return $this->quiet;
|
||||
}
|
||||
/**
|
||||
* Set if this service should be quiet
|
||||
*
|
||||
* @param bool $quiet
|
||||
* @return $ths
|
||||
*/
|
||||
public function setQuiet($quiet)
|
||||
{
|
||||
$this->quiet = $quiet;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getQuiet()
|
||||
{
|
||||
return $this->quiet;
|
||||
}
|
||||
}
|
||||
|
@ -5,17 +5,19 @@
|
||||
*
|
||||
* @author dmooyman
|
||||
*/
|
||||
class UserFormsUpgradeTask extends BuildTask {
|
||||
class UserFormsUpgradeTask extends BuildTask
|
||||
{
|
||||
|
||||
protected $title = "UserForms 3.0 Migration Tool";
|
||||
protected $title = "UserForms 3.0 Migration Tool";
|
||||
|
||||
protected $description = "Upgrade tool for sites upgrading to userforms 3.0";
|
||||
protected $description = "Upgrade tool for sites upgrading to userforms 3.0";
|
||||
|
||||
public function run($request) {
|
||||
$service = Injector::inst()->create('UserFormsUpgradeService');
|
||||
$service->log("Upgrading userforms module");
|
||||
$service->setQuiet(false)
|
||||
->run();
|
||||
$service->log("Done");
|
||||
}
|
||||
public function run($request)
|
||||
{
|
||||
$service = Injector::inst()->create('UserFormsUpgradeService');
|
||||
$service->log("Upgrading userforms module");
|
||||
$service->setQuiet(false)
|
||||
->run();
|
||||
$service->log("Done");
|
||||
}
|
||||
}
|
||||
|
@ -10,30 +10,29 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class UserFormsVersionedTask extends MigrationTask {
|
||||
class UserFormsVersionedTask extends MigrationTask
|
||||
{
|
||||
|
||||
protected $title = "UserForms Versioned Initial Migration";
|
||||
protected $title = "UserForms Versioned Initial Migration";
|
||||
|
||||
protected $description = "Publishes the existing forms";
|
||||
protected $description = "Publishes the existing forms";
|
||||
|
||||
/**
|
||||
* Publish the existing forms.
|
||||
*
|
||||
*/
|
||||
public function run($request) {
|
||||
$forms = Versioned::get_by_stage('UserDefinedForm', 'Live');
|
||||
/**
|
||||
* Publish the existing forms.
|
||||
*
|
||||
*/
|
||||
public function run($request)
|
||||
{
|
||||
$forms = Versioned::get_by_stage('UserDefinedForm', 'Live');
|
||||
|
||||
if($forms) {
|
||||
foreach($forms as $form) {
|
||||
echo "Publishing $form->Title <br />";
|
||||
$form->doPublish();
|
||||
}
|
||||
echo "Complete";
|
||||
}
|
||||
else {
|
||||
echo "No Forms Found";
|
||||
}
|
||||
}
|
||||
if ($forms) {
|
||||
foreach ($forms as $form) {
|
||||
echo "Publishing $form->Title <br />";
|
||||
$form->doPublish();
|
||||
}
|
||||
echo "Complete";
|
||||
} else {
|
||||
echo "No Forms Found";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,167 +4,178 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class EditableFormFieldTest extends FunctionalTest {
|
||||
class EditableFormFieldTest extends FunctionalTest
|
||||
{
|
||||
|
||||
static $fixture_file = 'userforms/tests/EditableFormFieldTest.yml';
|
||||
public static $fixture_file = 'userforms/tests/EditableFormFieldTest.yml';
|
||||
|
||||
function testFormFieldPermissions() {
|
||||
$text = $this->objFromFixture('EditableTextField', 'basic-text');
|
||||
public function testFormFieldPermissions()
|
||||
{
|
||||
$text = $this->objFromFixture('EditableTextField', 'basic-text');
|
||||
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$this->assertTrue($text->canCreate());
|
||||
$this->assertTrue($text->canView());
|
||||
$this->assertTrue($text->canEdit());
|
||||
$this->assertTrue($text->canDelete());
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$this->assertTrue($text->canCreate());
|
||||
$this->assertTrue($text->canView());
|
||||
$this->assertTrue($text->canEdit());
|
||||
$this->assertTrue($text->canDelete());
|
||||
|
||||
$text->setReadonly(true);
|
||||
$this->assertTrue($text->canView());
|
||||
$this->assertFalse($text->canEdit());
|
||||
$this->assertFalse($text->canDelete());
|
||||
$text->setReadonly(true);
|
||||
$this->assertTrue($text->canView());
|
||||
$this->assertFalse($text->canEdit());
|
||||
$this->assertFalse($text->canDelete());
|
||||
|
||||
$text->setReadonly(false);
|
||||
$this->assertTrue($text->canView());
|
||||
$this->assertTrue($text->canEdit());
|
||||
$this->assertTrue($text->canDelete());
|
||||
$text->setReadonly(false);
|
||||
$this->assertTrue($text->canView());
|
||||
$this->assertTrue($text->canEdit());
|
||||
$this->assertTrue($text->canDelete());
|
||||
|
||||
$member = Member::currentUser();
|
||||
$member->logout();
|
||||
$member = Member::currentUser();
|
||||
$member->logout();
|
||||
|
||||
$this->logInWithPermission('SITETREE_VIEW_ALL');
|
||||
$this->assertFalse($text->canCreate());
|
||||
$this->logInWithPermission('SITETREE_VIEW_ALL');
|
||||
$this->assertFalse($text->canCreate());
|
||||
|
||||
$text->setReadonly(false);
|
||||
$this->assertTrue($text->canView());
|
||||
$this->assertFalse($text->canEdit());
|
||||
$this->assertFalse($text->canDelete());
|
||||
$text->setReadonly(false);
|
||||
$this->assertTrue($text->canView());
|
||||
$this->assertFalse($text->canEdit());
|
||||
$this->assertFalse($text->canDelete());
|
||||
|
||||
$text->setReadonly(true);
|
||||
$this->assertTrue($text->canView());
|
||||
$this->assertFalse($text->canEdit());
|
||||
$this->assertFalse($text->canDelete());
|
||||
}
|
||||
$text->setReadonly(true);
|
||||
$this->assertTrue($text->canView());
|
||||
$this->assertFalse($text->canEdit());
|
||||
$this->assertFalse($text->canDelete());
|
||||
}
|
||||
|
||||
function testCustomRules() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'custom-rules-form');
|
||||
public function testCustomRules()
|
||||
{
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'custom-rules-form');
|
||||
|
||||
$checkbox = $form->Fields()->find('ClassName', 'EditableCheckbox');
|
||||
$field = $form->Fields()->find('ClassName', 'EditableTextField');
|
||||
$checkbox = $form->Fields()->find('ClassName', 'EditableCheckbox');
|
||||
$field = $form->Fields()->find('ClassName', 'EditableTextField');
|
||||
|
||||
$rules = $checkbox->DisplayRules();
|
||||
$rules = $checkbox->DisplayRules();
|
||||
|
||||
// form has 2 fields - a checkbox and a text field
|
||||
// it has 1 rule - when ticked the checkbox hides the text field
|
||||
$this->assertEquals(1, $rules->Count());
|
||||
$this->assertEquals($rules, $checkbox->EffectiveDisplayRules());
|
||||
// form has 2 fields - a checkbox and a text field
|
||||
// it has 1 rule - when ticked the checkbox hides the text field
|
||||
$this->assertEquals(1, $rules->Count());
|
||||
$this->assertEquals($rules, $checkbox->EffectiveDisplayRules());
|
||||
|
||||
$checkboxRule = $rules->First();
|
||||
$checkboxRule->ConditionFieldID = $field->ID;
|
||||
$checkboxRule = $rules->First();
|
||||
$checkboxRule->ConditionFieldID = $field->ID;
|
||||
|
||||
$this->assertEquals($checkboxRule->Display, 'Hide');
|
||||
$this->assertEquals($checkboxRule->ConditionOption, 'HasValue');
|
||||
$this->assertEquals($checkboxRule->FieldValue, '6');
|
||||
$this->assertEquals($checkboxRule->Display, 'Hide');
|
||||
$this->assertEquals($checkboxRule->ConditionOption, 'HasValue');
|
||||
$this->assertEquals($checkboxRule->FieldValue, '6');
|
||||
|
||||
// If field is required then all custom rules are disabled
|
||||
$checkbox->Required = true;
|
||||
$this->assertEquals(0, $checkbox->EffectiveDisplayRules()->count());
|
||||
}
|
||||
// If field is required then all custom rules are disabled
|
||||
$checkbox->Required = true;
|
||||
$this->assertEquals(0, $checkbox->EffectiveDisplayRules()->count());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers EditableOption::getValue
|
||||
*/
|
||||
public function testEditableOptionEmptyValue() {
|
||||
$option = $this->objFromFixture('EditableOption', 'option-1');
|
||||
$option->Value = '';
|
||||
public function testEditableOptionEmptyValue()
|
||||
{
|
||||
$option = $this->objFromFixture('EditableOption', 'option-1');
|
||||
$option->Value = '';
|
||||
|
||||
// Disallow empty values
|
||||
EditableOption::set_allow_empty_values(false);
|
||||
$this->assertEquals($option->Title, $option->Value);
|
||||
$this->assertEquals($option->Title, $option->Value);
|
||||
|
||||
$option->Value = 'test';
|
||||
$this->assertEquals('test', $option->Value);
|
||||
$option->Value = 'test';
|
||||
$this->assertEquals('test', $option->Value);
|
||||
|
||||
// Allow empty values
|
||||
EditableOption::set_allow_empty_values(true);
|
||||
$option->Value = '';
|
||||
$this->assertEquals('', $option->Value);
|
||||
$option->Value = '';
|
||||
$this->assertEquals('', $option->Value);
|
||||
}
|
||||
|
||||
function testEditableDropdownField() {
|
||||
$dropdown = $this->objFromFixture('EditableDropdown', 'basic-dropdown');
|
||||
public function testEditableDropdownField()
|
||||
{
|
||||
$dropdown = $this->objFromFixture('EditableDropdown', 'basic-dropdown');
|
||||
|
||||
$field = $dropdown->getFormField();
|
||||
$field = $dropdown->getFormField();
|
||||
|
||||
|
||||
$this->assertThat($field, $this->isInstanceOf('DropdownField'));
|
||||
$values = $field->getSource();
|
||||
$this->assertThat($field, $this->isInstanceOf('DropdownField'));
|
||||
$values = $field->getSource();
|
||||
|
||||
$this->assertEquals(array('Option 1' => 'Option 1', 'Option 2' => 'Option 2'), $values);
|
||||
}
|
||||
$this->assertEquals(array('Option 1' => 'Option 1', 'Option 2' => 'Option 2'), $values);
|
||||
}
|
||||
|
||||
function testEditableRadioField() {
|
||||
$radio = $this->objFromFixture('EditableRadioField', 'radio-field');
|
||||
public function testEditableRadioField()
|
||||
{
|
||||
$radio = $this->objFromFixture('EditableRadioField', 'radio-field');
|
||||
|
||||
$field = $radio->getFormField();
|
||||
$field = $radio->getFormField();
|
||||
|
||||
$this->assertThat($field, $this->isInstanceOf('OptionsetField'));
|
||||
$values = $field->getSource();
|
||||
$this->assertThat($field, $this->isInstanceOf('OptionsetField'));
|
||||
$values = $field->getSource();
|
||||
|
||||
$this->assertEquals(array('Option 5' => 'Option 5', 'Option 6' => 'Option 6'), $values);
|
||||
}
|
||||
$this->assertEquals(array('Option 5' => 'Option 5', 'Option 6' => 'Option 6'), $values);
|
||||
}
|
||||
|
||||
function testMultipleOptionDuplication() {
|
||||
$dropdown = $this->objFromFixture('EditableDropdown','basic-dropdown');
|
||||
public function testMultipleOptionDuplication()
|
||||
{
|
||||
$dropdown = $this->objFromFixture('EditableDropdown', 'basic-dropdown');
|
||||
|
||||
$clone = $dropdown->duplicate();
|
||||
$clone = $dropdown->duplicate();
|
||||
|
||||
$this->assertEquals($clone->Options()->Count(), $dropdown->Options()->Count());
|
||||
$this->assertEquals($clone->Options()->Count(), $dropdown->Options()->Count());
|
||||
|
||||
foreach($clone->Options() as $option) {
|
||||
$orginal = $dropdown->Options()->find('Title', $option->Title);
|
||||
foreach ($clone->Options() as $option) {
|
||||
$orginal = $dropdown->Options()->find('Title', $option->Title);
|
||||
|
||||
$this->assertEquals($orginal->Sort, $option->Sort);
|
||||
}
|
||||
}
|
||||
$this->assertEquals($orginal->Sort, $option->Sort);
|
||||
}
|
||||
}
|
||||
|
||||
public function testFileField() {
|
||||
$fileField = $this->objFromFixture('EditableFileField', 'file-field');
|
||||
$formField = $fileField->getFormField();
|
||||
public function testFileField()
|
||||
{
|
||||
$fileField = $this->objFromFixture('EditableFileField', 'file-field');
|
||||
$formField = $fileField->getFormField();
|
||||
|
||||
$this->assertContains('jpg', $formField->getValidator()->getAllowedExtensions());
|
||||
$this->assertNotContains('notallowedextension', $formField->getValidator()->getAllowedExtensions());
|
||||
}
|
||||
$this->assertContains('jpg', $formField->getValidator()->getAllowedExtensions());
|
||||
$this->assertNotContains('notallowedextension', $formField->getValidator()->getAllowedExtensions());
|
||||
}
|
||||
|
||||
public function testFileFieldAllowedExtensionsBlacklist() {
|
||||
Config::inst()->update('EditableFileField', 'allowed_extensions_blacklist', array('jpg'));
|
||||
$fileField = $this->objFromFixture('EditableFileField', 'file-field');
|
||||
$formField = $fileField->getFormField();
|
||||
public function testFileFieldAllowedExtensionsBlacklist()
|
||||
{
|
||||
Config::inst()->update('EditableFileField', 'allowed_extensions_blacklist', array('jpg'));
|
||||
$fileField = $this->objFromFixture('EditableFileField', 'file-field');
|
||||
$formField = $fileField->getFormField();
|
||||
|
||||
$this->assertNotContains('jpg', $formField->getValidator()->getAllowedExtensions());
|
||||
}
|
||||
$this->assertNotContains('jpg', $formField->getValidator()->getAllowedExtensions());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that unique names are automatically generated for each formfield
|
||||
*/
|
||||
public function testUniqueName() {
|
||||
$textfield1 = new EditableTextField();
|
||||
$this->assertEmpty($textfield1->Name);
|
||||
/**
|
||||
* Verify that unique names are automatically generated for each formfield
|
||||
*/
|
||||
public function testUniqueName()
|
||||
{
|
||||
$textfield1 = new EditableTextField();
|
||||
$this->assertEmpty($textfield1->Name);
|
||||
|
||||
// Write values
|
||||
$textfield1->write();
|
||||
$textfield2 = new EditableTextField();
|
||||
$textfield2->write();
|
||||
$checkboxField = new EditableCheckbox();
|
||||
$checkboxField->write();
|
||||
// Write values
|
||||
$textfield1->write();
|
||||
$textfield2 = new EditableTextField();
|
||||
$textfield2->write();
|
||||
$checkboxField = new EditableCheckbox();
|
||||
$checkboxField->write();
|
||||
|
||||
// Test values are in the expected format
|
||||
$this->assertRegExp('/^EditableTextField_.+/', $textfield1->Name);
|
||||
$this->assertRegExp('/^EditableTextField_.+/', $textfield2->Name);
|
||||
$this->assertRegExp('/^EditableCheckbox_.+/', $checkboxField->Name);
|
||||
$this->assertNotEquals($textfield1->Name, $textfield2->Name);
|
||||
}
|
||||
// Test values are in the expected format
|
||||
$this->assertRegExp('/^EditableTextField_.+/', $textfield1->Name);
|
||||
$this->assertRegExp('/^EditableTextField_.+/', $textfield2->Name);
|
||||
$this->assertRegExp('/^EditableCheckbox_.+/', $checkboxField->Name);
|
||||
$this->assertNotEquals($textfield1->Name, $textfield2->Name);
|
||||
}
|
||||
|
||||
public function testLengthRange() {
|
||||
public function testLengthRange()
|
||||
{
|
||||
/** @var EditableTextField $textField */
|
||||
$textField = $this->objFromFixture('EditableTextField', 'basic-text');
|
||||
|
||||
@ -193,6 +204,4 @@ class EditableFormFieldTest extends FunctionalTest {
|
||||
$this->assertEquals(10, $attributes['data-rule-minlength']);
|
||||
$this->assertEquals(20, $attributes['data-rule-maxlength']);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -3,40 +3,44 @@
|
||||
/**
|
||||
* Tests the {@see EditableLiteralField} class
|
||||
*/
|
||||
class EditableLiteralFieldTest extends SapphireTest {
|
||||
class EditableLiteralFieldTest extends SapphireTest
|
||||
{
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
HtmlEditorConfig::set_active('cms');
|
||||
}
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
HtmlEditorConfig::set_active('cms');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the sanitisation of HTML content
|
||||
*/
|
||||
public function testSanitisation() {
|
||||
$rawContent = '<h1>Welcome</h1><script>alert("Hello!");</script><p>Giant Robots!</p>';
|
||||
$safeContent = '<h1>Welcome</h1><p>Giant Robots!</p>';
|
||||
$field = new EditableLiteralField();
|
||||
/**
|
||||
* Tests the sanitisation of HTML content
|
||||
*/
|
||||
public function testSanitisation()
|
||||
{
|
||||
$rawContent = '<h1>Welcome</h1><script>alert("Hello!");</script><p>Giant Robots!</p>';
|
||||
$safeContent = '<h1>Welcome</h1><p>Giant Robots!</p>';
|
||||
$field = new EditableLiteralField();
|
||||
|
||||
// Test with sanitisation enabled
|
||||
Config::inst()->update('HtmlEditorField', 'sanitise_server_side', true);
|
||||
$field->setContent($rawContent);
|
||||
$this->assertEquals($safeContent, $field->getContent());
|
||||
// Test with sanitisation enabled
|
||||
Config::inst()->update('HtmlEditorField', 'sanitise_server_side', true);
|
||||
$field->setContent($rawContent);
|
||||
$this->assertEquals($safeContent, $field->getContent());
|
||||
|
||||
// Test with sanitisation disabled
|
||||
Config::inst()->remove('HtmlEditorField', 'sanitise_server_side');
|
||||
$field->setContent($rawContent);
|
||||
$this->assertEquals($rawContent, $field->getContent());
|
||||
}
|
||||
// Test with sanitisation disabled
|
||||
Config::inst()->remove('HtmlEditorField', 'sanitise_server_side');
|
||||
$field->setContent($rawContent);
|
||||
$this->assertEquals($rawContent, $field->getContent());
|
||||
}
|
||||
|
||||
public function testHideLabel() {
|
||||
$field = new EditableLiteralField(array(
|
||||
'Title' => 'Test label'
|
||||
));
|
||||
public function testHideLabel()
|
||||
{
|
||||
$field = new EditableLiteralField(array(
|
||||
'Title' => 'Test label'
|
||||
));
|
||||
|
||||
$this->assertContains('Test label', $field->getFormField()->Field());
|
||||
$this->assertContains('Test label', $field->getFormField()->Field());
|
||||
|
||||
$field->HideLabel = true;
|
||||
$this->assertNotContains('Test label', $field->getFormField()->Field());
|
||||
}
|
||||
$field->HideLabel = true;
|
||||
$this->assertNotContains('Test label', $field->getFormField()->Field());
|
||||
}
|
||||
}
|
||||
|
@ -5,79 +5,85 @@
|
||||
*
|
||||
* @author dmooyman
|
||||
*/
|
||||
class SecureEditableFileFieldTest extends SapphireTest {
|
||||
class SecureEditableFileFieldTest extends SapphireTest
|
||||
{
|
||||
|
||||
protected $usesDatabase = true;
|
||||
protected $usesDatabase = true;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if(!class_exists('SecureFileExtension')) {
|
||||
$this->skipTest = true;
|
||||
$this->markTestSkipped(get_class() . ' skipped unless running with securefiles');
|
||||
}
|
||||
Config::inst()->update('EditableFileField', 'secure_folder_name', 'SecureEditableFileFieldTest/SecureUploads');
|
||||
$this->clearPath();
|
||||
}
|
||||
if (!class_exists('SecureFileExtension')) {
|
||||
$this->skipTest = true;
|
||||
$this->markTestSkipped(get_class() . ' skipped unless running with securefiles');
|
||||
}
|
||||
Config::inst()->update('EditableFileField', 'secure_folder_name', 'SecureEditableFileFieldTest/SecureUploads');
|
||||
$this->clearPath();
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
$this->clearPath();
|
||||
parent::tearDown();
|
||||
}
|
||||
public function tearDown()
|
||||
{
|
||||
$this->clearPath();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
protected function clearPath() {
|
||||
if(file_exists(ASSETS_PATH . '/SecureEditableFileFieldTest')) {
|
||||
Filesystem::removeFolder(ASSETS_PATH . '/SecureEditableFileFieldTest');
|
||||
}
|
||||
}
|
||||
protected function clearPath()
|
||||
{
|
||||
if (file_exists(ASSETS_PATH . '/SecureEditableFileFieldTest')) {
|
||||
Filesystem::removeFolder(ASSETS_PATH . '/SecureEditableFileFieldTest');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that newly created folders are secure
|
||||
*/
|
||||
public function testCreateFolder() {
|
||||
$field = new EditableFileField();
|
||||
$field->write();
|
||||
$this->assertTrue($field->getIsSecure());
|
||||
$this->assertTrue($field->Folder()->exists());
|
||||
$this->assertEquals('assets/SecureEditableFileFieldTest/SecureUploads/', $field->Folder()->Filename);
|
||||
$this->assertEquals('OnlyTheseUsers', $field->Folder()->CanViewType);
|
||||
$this->assertEquals(1, $field->Folder()->ViewerGroups()->first()->Permissions()->filter('code', 'ADMIN')->count());
|
||||
}
|
||||
/**
|
||||
* Test that newly created folders are secure
|
||||
*/
|
||||
public function testCreateFolder()
|
||||
{
|
||||
$field = new EditableFileField();
|
||||
$field->write();
|
||||
$this->assertTrue($field->getIsSecure());
|
||||
$this->assertTrue($field->Folder()->exists());
|
||||
$this->assertEquals('assets/SecureEditableFileFieldTest/SecureUploads/', $field->Folder()->Filename);
|
||||
$this->assertEquals('OnlyTheseUsers', $field->Folder()->CanViewType);
|
||||
$this->assertEquals(1, $field->Folder()->ViewerGroups()->first()->Permissions()->filter('code', 'ADMIN')->count());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test new folders that are created without security enabled
|
||||
*/
|
||||
public function testCreateInsecure() {
|
||||
Config::inst()->update('EditableFileField', 'disable_security', true);
|
||||
/**
|
||||
* Test new folders that are created without security enabled
|
||||
*/
|
||||
public function testCreateInsecure()
|
||||
{
|
||||
Config::inst()->update('EditableFileField', 'disable_security', true);
|
||||
|
||||
// Esure folder is created without a folder
|
||||
$field = new EditableFileField();
|
||||
$field->write();
|
||||
$this->assertFalse($field->getIsSecure());
|
||||
$this->assertFalse($field->Folder()->exists());
|
||||
// Esure folder is created without a folder
|
||||
$field = new EditableFileField();
|
||||
$field->write();
|
||||
$this->assertFalse($field->getIsSecure());
|
||||
$this->assertFalse($field->Folder()->exists());
|
||||
|
||||
// Assigning a non-secure folder doesn't secure this
|
||||
$folder = Folder::find_or_make('SecureEditableFileFieldTest/PublicFolder');
|
||||
$field->FolderID = $folder->ID;
|
||||
$field->write();
|
||||
// Assigning a non-secure folder doesn't secure this
|
||||
$folder = Folder::find_or_make('SecureEditableFileFieldTest/PublicFolder');
|
||||
$field->FolderID = $folder->ID;
|
||||
$field->write();
|
||||
|
||||
$this->assertFalse($field->getIsSecure());
|
||||
$this->assertTrue($field->Folder()->exists());
|
||||
$this->assertEquals('assets/SecureEditableFileFieldTest/PublicFolder/', $field->Folder()->Filename);
|
||||
$this->assertEquals('Inherit', $field->Folder()->CanViewType);
|
||||
$this->assertFalse($field->getIsSecure());
|
||||
$this->assertTrue($field->Folder()->exists());
|
||||
$this->assertEquals('assets/SecureEditableFileFieldTest/PublicFolder/', $field->Folder()->Filename);
|
||||
$this->assertEquals('Inherit', $field->Folder()->CanViewType);
|
||||
|
||||
// Enabling security and re-saving will force this field to be made secure (but not changed)
|
||||
Config::inst()->update('EditableFileField', 'disable_security', false);
|
||||
singleton('EditableFileField')->requireDefaultRecords();
|
||||
// Enabling security and re-saving will force this field to be made secure (but not changed)
|
||||
Config::inst()->update('EditableFileField', 'disable_security', false);
|
||||
singleton('EditableFileField')->requireDefaultRecords();
|
||||
|
||||
// Reload record from DB
|
||||
$field = EditableFileField::get()->byID($field->ID);
|
||||
// Reload record from DB
|
||||
$field = EditableFileField::get()->byID($field->ID);
|
||||
|
||||
// Existing folder is now secured (retro-actively secures any old uploads)
|
||||
$this->assertTrue($field->getIsSecure());
|
||||
$this->assertTrue($field->Folder()->exists());
|
||||
$this->assertEquals('assets/SecureEditableFileFieldTest/PublicFolder/', $field->Folder()->Filename);
|
||||
$this->assertEquals('OnlyTheseUsers', $field->Folder()->CanViewType);
|
||||
$this->assertEquals(1, $field->Folder()->ViewerGroups()->first()->Permissions()->filter('code', 'ADMIN')->count());
|
||||
}
|
||||
// Existing folder is now secured (retro-actively secures any old uploads)
|
||||
$this->assertTrue($field->getIsSecure());
|
||||
$this->assertTrue($field->Folder()->exists());
|
||||
$this->assertEquals('assets/SecureEditableFileFieldTest/PublicFolder/', $field->Folder()->Filename);
|
||||
$this->assertEquals('OnlyTheseUsers', $field->Folder()->CanViewType);
|
||||
$this->assertEquals(1, $field->Folder()->ViewerGroups()->first()->Permissions()->filter('code', 'ADMIN')->count());
|
||||
}
|
||||
}
|
@ -4,282 +4,296 @@
|
||||
* @package userforms
|
||||
*/
|
||||
|
||||
class UserDefinedFormControllerTest extends FunctionalTest {
|
||||
class UserDefinedFormControllerTest extends FunctionalTest
|
||||
{
|
||||
|
||||
static $fixture_file = 'UserDefinedFormTest.yml';
|
||||
public static $fixture_file = 'UserDefinedFormTest.yml';
|
||||
|
||||
public function testProcess() {
|
||||
$form = $this->setupFormFrontend();
|
||||
public function testProcess()
|
||||
{
|
||||
$form = $this->setupFormFrontend();
|
||||
|
||||
$controller = new UserDefinedFormControllerTest_Controller($form);
|
||||
$controller = new UserDefinedFormControllerTest_Controller($form);
|
||||
|
||||
$this->autoFollowRedirection = false;
|
||||
$this->clearEmails();
|
||||
$this->autoFollowRedirection = false;
|
||||
$this->clearEmails();
|
||||
|
||||
// load the form
|
||||
$this->get($form->URLSegment);
|
||||
// load the form
|
||||
$this->get($form->URLSegment);
|
||||
|
||||
$field = $this->objFromFixture('EditableTextField', 'basic-text');
|
||||
$field = $this->objFromFixture('EditableTextField', 'basic-text');
|
||||
|
||||
$response = $this->submitForm('UserForm_Form', null, array($field->Name => 'Basic Value'));
|
||||
$response = $this->submitForm('UserForm_Form', null, array($field->Name => 'Basic Value'));
|
||||
|
||||
// should have a submitted form field now
|
||||
$submitted = DataObject::get('SubmittedFormField', "\"Name\" = 'basic-text-name'");
|
||||
$this->assertDOSAllMatch(array('Name' => 'basic-text-name', 'Value' => 'Basic Value', 'Title' => 'Basic Text Field'), $submitted);
|
||||
// should have a submitted form field now
|
||||
$submitted = DataObject::get('SubmittedFormField', "\"Name\" = 'basic-text-name'");
|
||||
$this->assertDOSAllMatch(array('Name' => 'basic-text-name', 'Value' => 'Basic Value', 'Title' => 'Basic Text Field'), $submitted);
|
||||
|
||||
// check emails
|
||||
$this->assertEmailSent('test@example.com', 'no-reply@example.com', 'Email Subject');
|
||||
$email = $this->findEmail('test@example.com', 'no-reply@example.com', 'Email Subject');
|
||||
// check emails
|
||||
$this->assertEmailSent('test@example.com', 'no-reply@example.com', 'Email Subject');
|
||||
$email = $this->findEmail('test@example.com', 'no-reply@example.com', 'Email Subject');
|
||||
|
||||
// assert that the email has the field title and the value html email
|
||||
$parser = new CSSContentParser($email['content']);
|
||||
$title = $parser->getBySelector('strong');
|
||||
// assert that the email has the field title and the value html email
|
||||
$parser = new CSSContentParser($email['content']);
|
||||
$title = $parser->getBySelector('strong');
|
||||
|
||||
$this->assertEquals('Basic Text Field', (string) $title[0], 'Email contains the field name');
|
||||
$this->assertEquals('Basic Text Field', (string) $title[0], 'Email contains the field name');
|
||||
|
||||
$value = $parser->getBySelector('dd');
|
||||
$this->assertEquals('Basic Value', (string) $value[0], 'Email contains the value');
|
||||
$value = $parser->getBySelector('dd');
|
||||
$this->assertEquals('Basic Value', (string) $value[0], 'Email contains the value');
|
||||
|
||||
// no html
|
||||
$this->assertEmailSent('nohtml@example.com', 'no-reply@example.com', 'Email Subject');
|
||||
$nohtml = $this->findEmail('nohtml@example.com', 'no-reply@example.com', 'Email Subject');
|
||||
// no html
|
||||
$this->assertEmailSent('nohtml@example.com', 'no-reply@example.com', 'Email Subject');
|
||||
$nohtml = $this->findEmail('nohtml@example.com', 'no-reply@example.com', 'Email Subject');
|
||||
|
||||
$this->assertContains('Basic Text Field: Basic Value', $nohtml['content'], 'Email contains no html');
|
||||
$this->assertContains('Basic Text Field: Basic Value', $nohtml['content'], 'Email contains no html');
|
||||
|
||||
// no data
|
||||
$this->assertEmailSent('nodata@example.com', 'no-reply@example.com', 'Email Subject');
|
||||
$nodata = $this->findEmail('nodata@example.com', 'no-reply@example.com', 'Email Subject');
|
||||
// no data
|
||||
$this->assertEmailSent('nodata@example.com', 'no-reply@example.com', 'Email Subject');
|
||||
$nodata = $this->findEmail('nodata@example.com', 'no-reply@example.com', 'Email Subject');
|
||||
|
||||
$parser = new CSSContentParser($nodata['content']);
|
||||
$list = $parser->getBySelector('dl');
|
||||
$parser = new CSSContentParser($nodata['content']);
|
||||
$list = $parser->getBySelector('dl');
|
||||
|
||||
$this->assertFalse(isset($list[0]), 'Email contains no fields');
|
||||
$this->assertFalse(isset($list[0]), 'Email contains no fields');
|
||||
|
||||
// check to see if the user was redirected (301)
|
||||
$this->assertEquals($response->getStatusCode(), 302);
|
||||
$this->assertStringEndsWith('finished#uff', $response->getHeader('Location'));
|
||||
}
|
||||
// check to see if the user was redirected (301)
|
||||
$this->assertEquals($response->getStatusCode(), 302);
|
||||
$this->assertStringEndsWith('finished#uff', $response->getHeader('Location'));
|
||||
}
|
||||
|
||||
public function testValidation() {
|
||||
$form = $this->setupFormFrontend('email-form');
|
||||
public function testValidation()
|
||||
{
|
||||
$form = $this->setupFormFrontend('email-form');
|
||||
|
||||
// Post with no fields
|
||||
$this->get($form->URLSegment);
|
||||
$response = $this->submitForm('UserForm_Form', null, array());
|
||||
$this->assertPartialMatchBySelector(
|
||||
'.field .message',
|
||||
array('This field is required')
|
||||
);
|
||||
// Post with no fields
|
||||
$this->get($form->URLSegment);
|
||||
$response = $this->submitForm('UserForm_Form', null, array());
|
||||
$this->assertPartialMatchBySelector(
|
||||
'.field .message',
|
||||
array('This field is required')
|
||||
);
|
||||
|
||||
// Post with all fields, but invalid email
|
||||
$this->get($form->URLSegment);
|
||||
$this->submitForm('UserForm_Form', null, array(
|
||||
'required-email' => 'invalid',
|
||||
'required-text' => 'bob'
|
||||
));
|
||||
$this->assertPartialMatchBySelector(
|
||||
'.field .message',
|
||||
array('Please enter an email address')
|
||||
);
|
||||
// Post with all fields, but invalid email
|
||||
$this->get($form->URLSegment);
|
||||
$this->submitForm('UserForm_Form', null, array(
|
||||
'required-email' => 'invalid',
|
||||
'required-text' => 'bob'
|
||||
));
|
||||
$this->assertPartialMatchBySelector(
|
||||
'.field .message',
|
||||
array('Please enter an email address')
|
||||
);
|
||||
|
||||
// Post with only required
|
||||
$this->get($form->URLSegment);
|
||||
$this->submitForm('UserForm_Form', null, array(
|
||||
'required-text' => 'bob'
|
||||
));
|
||||
$this->assertPartialMatchBySelector(
|
||||
'p',
|
||||
array("Thanks, we've received your submission.")
|
||||
);
|
||||
}
|
||||
// Post with only required
|
||||
$this->get($form->URLSegment);
|
||||
$this->submitForm('UserForm_Form', null, array(
|
||||
'required-text' => 'bob'
|
||||
));
|
||||
$this->assertPartialMatchBySelector(
|
||||
'p',
|
||||
array("Thanks, we've received your submission.")
|
||||
);
|
||||
}
|
||||
|
||||
public function testFinished() {
|
||||
$form = $this->setupFormFrontend();
|
||||
public function testFinished()
|
||||
{
|
||||
$form = $this->setupFormFrontend();
|
||||
|
||||
// set formProcessed and SecurityID to replicate the form being filled out
|
||||
$this->session()->inst_set('SecurityID', 1);
|
||||
$this->session()->inst_set('FormProcessed', 1);
|
||||
// set formProcessed and SecurityID to replicate the form being filled out
|
||||
$this->session()->inst_set('SecurityID', 1);
|
||||
$this->session()->inst_set('FormProcessed', 1);
|
||||
|
||||
$response = $this->get($form->URLSegment.'/finished');
|
||||
$response = $this->get($form->URLSegment.'/finished');
|
||||
|
||||
$this->assertContains($form->OnCompleteMessage ,$response->getBody());
|
||||
}
|
||||
$this->assertContains($form->OnCompleteMessage, $response->getBody());
|
||||
}
|
||||
|
||||
public function testAppendingFinished() {
|
||||
$form = $this->setupFormFrontend();
|
||||
public function testAppendingFinished()
|
||||
{
|
||||
$form = $this->setupFormFrontend();
|
||||
|
||||
// replicate finished being added to the end of the form URL without the form being filled out
|
||||
$this->session()->inst_set('SecurityID', 1);
|
||||
$this->session()->inst_set('FormProcessed', null);
|
||||
// replicate finished being added to the end of the form URL without the form being filled out
|
||||
$this->session()->inst_set('SecurityID', 1);
|
||||
$this->session()->inst_set('FormProcessed', null);
|
||||
|
||||
$response = $this->get($form->URLSegment.'/finished');
|
||||
$response = $this->get($form->URLSegment.'/finished');
|
||||
|
||||
$this->assertNotContains($form->OnCompleteMessage ,$response->getBody());
|
||||
}
|
||||
$this->assertNotContains($form->OnCompleteMessage, $response->getBody());
|
||||
}
|
||||
|
||||
public function testForm() {
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
public function testForm()
|
||||
{
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
|
||||
$controller = new UserDefinedFormControllerTest_Controller($form);
|
||||
$controller = new UserDefinedFormControllerTest_Controller($form);
|
||||
|
||||
// test form
|
||||
$this->assertEquals($controller->Form()->getName(), 'Form', 'The form is referenced as Form');
|
||||
$this->assertEquals($controller->Form()->Fields()->Count(), 1); // disabled SecurityID token fields
|
||||
$this->assertEquals($controller->Form()->Actions()->Count(), 1);
|
||||
$this->assertEquals(count($controller->Form()->getValidator()->getRequired()), 0);
|
||||
// test form
|
||||
$this->assertEquals($controller->Form()->getName(), 'Form', 'The form is referenced as Form');
|
||||
$this->assertEquals($controller->Form()->Fields()->Count(), 1); // disabled SecurityID token fields
|
||||
$this->assertEquals($controller->Form()->Actions()->Count(), 1);
|
||||
$this->assertEquals(count($controller->Form()->getValidator()->getRequired()), 0);
|
||||
|
||||
$requiredForm = $this->objFromFixture('UserDefinedForm', 'validation-form');
|
||||
$controller = new UserDefinedFormControllerTest_Controller($requiredForm);
|
||||
$requiredForm = $this->objFromFixture('UserDefinedForm', 'validation-form');
|
||||
$controller = new UserDefinedFormControllerTest_Controller($requiredForm);
|
||||
|
||||
$this->assertEquals($controller->Form()->Fields()->Count(), 1); // disabled SecurityID token fields
|
||||
$this->assertEquals($controller->Form()->Actions()->Count(), 1);
|
||||
$this->assertEquals(count($controller->Form()->getValidator()->getRequired()), 1);
|
||||
}
|
||||
$this->assertEquals($controller->Form()->Fields()->Count(), 1); // disabled SecurityID token fields
|
||||
$this->assertEquals($controller->Form()->Actions()->Count(), 1);
|
||||
$this->assertEquals(count($controller->Form()->getValidator()->getRequired()), 1);
|
||||
}
|
||||
|
||||
public function testGetFormFields() {
|
||||
// generating the fieldset of fields
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
public function testGetFormFields()
|
||||
{
|
||||
// generating the fieldset of fields
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
|
||||
$controller = new UserDefinedFormControllerTest_Controller($form);
|
||||
$controller = new UserDefinedFormControllerTest_Controller($form);
|
||||
|
||||
$formSteps = $controller->Form()->getFormFields();
|
||||
$firstStep = $formSteps->first();
|
||||
|
||||
$formSteps = $controller->Form()->getFormFields();
|
||||
$firstStep = $formSteps->first();
|
||||
$this->assertEquals($formSteps->Count(), 1);
|
||||
$this->assertEquals($firstStep->getChildren()->Count(), 1);
|
||||
|
||||
$this->assertEquals($formSteps->Count(), 1);
|
||||
$this->assertEquals($firstStep->getChildren()->Count(), 1);
|
||||
// custom error message on a form field
|
||||
$requiredForm = $this->objFromFixture('UserDefinedForm', 'validation-form');
|
||||
$controller = new UserDefinedFormControllerTest_Controller($requiredForm);
|
||||
|
||||
// custom error message on a form field
|
||||
$requiredForm = $this->objFromFixture('UserDefinedForm', 'validation-form');
|
||||
$controller = new UserDefinedFormControllerTest_Controller($requiredForm);
|
||||
UserDefinedForm::config()->required_identifier = "*";
|
||||
|
||||
UserDefinedForm::config()->required_identifier = "*";
|
||||
$formSteps = $controller->Form()->getFormFields();
|
||||
$firstStep = $formSteps->first();
|
||||
$firstField = $firstStep->getChildren()->first();
|
||||
|
||||
$formSteps = $controller->Form()->getFormFields();
|
||||
$firstStep = $formSteps->first();
|
||||
$firstField = $firstStep->getChildren()->first();
|
||||
$this->assertEquals('Custom Error Message', $firstField->getCustomValidationMessage());
|
||||
$this->assertEquals($firstField->Title(), 'Required Text Field <span class=\'required-identifier\'>*</span>');
|
||||
|
||||
$this->assertEquals('Custom Error Message', $firstField->getCustomValidationMessage());
|
||||
$this->assertEquals($firstField->Title(), 'Required Text Field <span class=\'required-identifier\'>*</span>');
|
||||
// test custom right title
|
||||
$field = $form->Fields()->limit(1, 1)->First();
|
||||
$field->RightTitle = 'Right Title';
|
||||
$field->write();
|
||||
|
||||
// test custom right title
|
||||
$field = $form->Fields()->limit(1, 1)->First();
|
||||
$field->RightTitle = 'Right Title';
|
||||
$field->write();
|
||||
$controller = new UserDefinedFormControllerTest_Controller($form);
|
||||
$formSteps = $controller->Form()->getFormFields();
|
||||
$firstStep = $formSteps->first();
|
||||
|
||||
$controller = new UserDefinedFormControllerTest_Controller($form);
|
||||
$formSteps = $controller->Form()->getFormFields();
|
||||
$firstStep = $formSteps->first();
|
||||
$this->assertEquals($firstStep->getChildren()->First()->RightTitle(), "Right Title");
|
||||
|
||||
$this->assertEquals($firstStep->getChildren()->First()->RightTitle(), "Right Title");
|
||||
// test empty form
|
||||
$emptyForm = $this->objFromFixture('UserDefinedForm', 'empty-form');
|
||||
$controller = new UserDefinedFormControllerTest_Controller($emptyForm);
|
||||
|
||||
// test empty form
|
||||
$emptyForm = $this->objFromFixture('UserDefinedForm', 'empty-form');
|
||||
$controller = new UserDefinedFormControllerTest_Controller($emptyForm);
|
||||
$this->assertFalse($controller->Form()->getFormFields()->exists());
|
||||
}
|
||||
|
||||
$this->assertFalse($controller->Form()->getFormFields()->exists());
|
||||
}
|
||||
public function testGetFormActions()
|
||||
{
|
||||
// generating the fieldset of actions
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
|
||||
public function testGetFormActions()
|
||||
{
|
||||
// generating the fieldset of actions
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
$controller = new UserDefinedFormControllerTest_Controller($form);
|
||||
$actions = $controller->Form()->getFormActions();
|
||||
|
||||
$controller = new UserDefinedFormControllerTest_Controller($form);
|
||||
$actions = $controller->Form()->getFormActions();
|
||||
// by default will have 1 submit button which links to process
|
||||
$expected = new FieldList(new FormAction('process', 'Submit'));
|
||||
$expected->setForm($controller->Form());
|
||||
|
||||
// by default will have 1 submit button which links to process
|
||||
$expected = new FieldList(new FormAction('process', 'Submit'));
|
||||
$expected->setForm($controller->Form());
|
||||
$this->assertEquals($actions, $expected);
|
||||
|
||||
$this->assertEquals($actions, $expected);
|
||||
// the custom popup should have a reset button and a custom text
|
||||
$custom = $this->objFromFixture('UserDefinedForm', 'form-with-reset-and-custom-action');
|
||||
$controller = new UserDefinedFormControllerTest_Controller($custom);
|
||||
$actions = $controller->Form()->getFormActions();
|
||||
|
||||
// the custom popup should have a reset button and a custom text
|
||||
$custom = $this->objFromFixture('UserDefinedForm', 'form-with-reset-and-custom-action');
|
||||
$controller = new UserDefinedFormControllerTest_Controller($custom);
|
||||
$actions = $controller->Form()->getFormActions();
|
||||
$expected = new FieldList(new FormAction('process', 'Custom Button'));
|
||||
$expected->push(new ResetFormAction("clearForm", "Clear"));
|
||||
$expected->setForm($controller->Form());
|
||||
|
||||
$expected = new FieldList(new FormAction('process', 'Custom Button'));
|
||||
$expected->push(new ResetFormAction("clearForm", "Clear"));
|
||||
$expected->setForm($controller->Form());
|
||||
$this->assertEquals($actions, $expected);
|
||||
}
|
||||
|
||||
$this->assertEquals($actions, $expected);
|
||||
}
|
||||
public function testRenderingIntoFormTemplate()
|
||||
{
|
||||
$form = $this->setupFormFrontend();
|
||||
|
||||
public function testRenderingIntoFormTemplate() {
|
||||
$form = $this->setupFormFrontend();
|
||||
$form->Content = 'This is some content without a form nested between it';
|
||||
$form->doPublish();
|
||||
|
||||
$form->Content = 'This is some content without a form nested between it';
|
||||
$form->doPublish();
|
||||
$controller = new UserDefinedFormControllerTest_Controller($form);
|
||||
|
||||
$controller = new UserDefinedFormControllerTest_Controller($form);
|
||||
// check to see if $Form is replaced to inside the content
|
||||
$index = new ArrayData($controller->index());
|
||||
$parser = new CSSContentParser($index->renderWith(array('UserDefinedFormControllerTest')));
|
||||
|
||||
// check to see if $Form is replaced to inside the content
|
||||
$index = new ArrayData($controller->index());
|
||||
$parser = new CSSContentParser($index->renderWith(array('UserDefinedFormControllerTest')));
|
||||
$this->checkTemplateIsCorrect($parser);
|
||||
}
|
||||
|
||||
$this->checkTemplateIsCorrect($parser);
|
||||
}
|
||||
public function testRenderingIntoTemplateWithSubstringReplacement()
|
||||
{
|
||||
$form = $this->setupFormFrontend();
|
||||
|
||||
public function testRenderingIntoTemplateWithSubstringReplacement() {
|
||||
$form = $this->setupFormFrontend();
|
||||
$controller = new UserDefinedFormControllerTest_Controller($form);
|
||||
|
||||
$controller = new UserDefinedFormControllerTest_Controller($form);
|
||||
// check to see if $Form is replaced to inside the content
|
||||
$index = new ArrayData($controller->index());
|
||||
$parser = new CSSContentParser($index->renderWith(array('UserDefinedFormControllerTest')));
|
||||
|
||||
// check to see if $Form is replaced to inside the content
|
||||
$index = new ArrayData($controller->index());
|
||||
$parser = new CSSContentParser($index->renderWith(array('UserDefinedFormControllerTest')));
|
||||
$this->checkTemplateIsCorrect($parser);
|
||||
}
|
||||
/**
|
||||
* Publish a form for use on the frontend
|
||||
*
|
||||
* @param string $fixtureName
|
||||
* @return UserDefinedForm
|
||||
*/
|
||||
protected function setupFormFrontend($fixtureName = 'basic-form-page')
|
||||
{
|
||||
$form = $this->objFromFixture('UserDefinedForm', $fixtureName);
|
||||
$this->logInWithPermission('ADMIN');
|
||||
|
||||
$this->checkTemplateIsCorrect($parser);
|
||||
}
|
||||
/**
|
||||
* Publish a form for use on the frontend
|
||||
*
|
||||
* @param string $fixtureName
|
||||
* @return UserDefinedForm
|
||||
*/
|
||||
protected function setupFormFrontend($fixtureName = 'basic-form-page') {
|
||||
$form = $this->objFromFixture('UserDefinedForm', $fixtureName);
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$form->doPublish();
|
||||
|
||||
$form->doPublish();
|
||||
$member = Member::currentUser();
|
||||
$member->logOut();
|
||||
|
||||
$member = Member::currentUser();
|
||||
$member->logOut();
|
||||
return $form;
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
public function checkTemplateIsCorrect($parser)
|
||||
{
|
||||
$this->assertArrayHasKey(0, $parser->getBySelector('form#UserForm_Form'));
|
||||
|
||||
public function checkTemplateIsCorrect($parser) {
|
||||
$this->assertArrayHasKey(0, $parser->getBySelector('form#UserForm_Form'));
|
||||
// check for the input
|
||||
$this->assertArrayHasKey(0, $parser->getBySelector('input.text'));
|
||||
|
||||
// check for the input
|
||||
$this->assertArrayHasKey(0, $parser->getBySelector('input.text'));
|
||||
// check for the label and the text
|
||||
$label = $parser->getBySelector('label.left');
|
||||
$this->assertArrayHasKey(0, $label);
|
||||
|
||||
// check for the label and the text
|
||||
$label = $parser->getBySelector('label.left');
|
||||
$this->assertArrayHasKey(0, $label);
|
||||
$this->assertEquals((string) $label[0][0], "Basic Text Field", "Label contains correct field name");
|
||||
|
||||
$this->assertEquals((string) $label[0][0], "Basic Text Field", "Label contains correct field name");
|
||||
// check for the action
|
||||
$action = $parser->getBySelector('input.action');
|
||||
$this->assertArrayHasKey(0, $action);
|
||||
|
||||
// check for the action
|
||||
$action = $parser->getBySelector('input.action');
|
||||
$this->assertArrayHasKey(0, $action);
|
||||
|
||||
$this->assertEquals((string) $action[0]['value'], "Submit", "Submit button has default text");
|
||||
}
|
||||
$this->assertEquals((string) $action[0]['value'], "Submit", "Submit button has default text");
|
||||
}
|
||||
}
|
||||
|
||||
class UserDefinedFormControllerTest_Controller extends UserDefinedForm_Controller implements TestOnly {
|
||||
class UserDefinedFormControllerTest_Controller extends UserDefinedForm_Controller implements TestOnly
|
||||
{
|
||||
|
||||
/**
|
||||
* Overloaded to avoid inconsistencies between 2.4.2 and 2.4.3 (disables all security tokens in unit tests by default)
|
||||
*/
|
||||
public function Form() {
|
||||
$form = parent::Form();
|
||||
/**
|
||||
* Overloaded to avoid inconsistencies between 2.4.2 and 2.4.3 (disables all security tokens in unit tests by default)
|
||||
*/
|
||||
public function Form()
|
||||
{
|
||||
$form = parent::Form();
|
||||
|
||||
if($form) $form->disableSecurityToken();
|
||||
|
||||
return $form;
|
||||
}
|
||||
if ($form) {
|
||||
$form->disableSecurityToken();
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
|
@ -3,421 +3,436 @@
|
||||
/**
|
||||
* @package userforms
|
||||
*/
|
||||
class UserDefinedFormTest extends FunctionalTest {
|
||||
class UserDefinedFormTest extends FunctionalTest
|
||||
{
|
||||
|
||||
static $fixture_file = 'UserDefinedFormTest.yml';
|
||||
public static $fixture_file = 'UserDefinedFormTest.yml';
|
||||
|
||||
public function testRollbackToVersion() {
|
||||
$this->markTestSkipped(
|
||||
'UserDefinedForm::rollback() has not been implemented completely'
|
||||
);
|
||||
public function testRollbackToVersion()
|
||||
{
|
||||
$this->markTestSkipped(
|
||||
'UserDefinedForm::rollback() has not been implemented completely'
|
||||
);
|
||||
|
||||
// @todo
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
// @todo
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
|
||||
$form->SubmitButtonText = 'Button Text';
|
||||
$form->write();
|
||||
$form->doPublish();
|
||||
$origVersion = $form->Version;
|
||||
$form->SubmitButtonText = 'Button Text';
|
||||
$form->write();
|
||||
$form->doPublish();
|
||||
$origVersion = $form->Version;
|
||||
|
||||
$form->SubmitButtonText = 'Updated Button Text';
|
||||
$form->write();
|
||||
$form->doPublish();
|
||||
$form->SubmitButtonText = 'Updated Button Text';
|
||||
$form->write();
|
||||
$form->doPublish();
|
||||
|
||||
// check published site
|
||||
$updated = Versioned::get_one_by_stage("UserDefinedForm", "Stage", "\"UserDefinedForm\".\"ID\" = $form->ID");
|
||||
$this->assertEquals($updated->SubmitButtonText, 'Updated Button Text');
|
||||
// check published site
|
||||
$updated = Versioned::get_one_by_stage("UserDefinedForm", "Stage", "\"UserDefinedForm\".\"ID\" = $form->ID");
|
||||
$this->assertEquals($updated->SubmitButtonText, 'Updated Button Text');
|
||||
|
||||
$form->doRollbackTo($origVersion);
|
||||
$form->doRollbackTo($origVersion);
|
||||
|
||||
$orignal = Versioned::get_one_by_stage("UserDefinedForm", "Stage", "\"UserDefinedForm\".\"ID\" = $form->ID");
|
||||
$this->assertEquals($orignal->SubmitButtonText, 'Button Text');
|
||||
}
|
||||
$orignal = Versioned::get_one_by_stage("UserDefinedForm", "Stage", "\"UserDefinedForm\".\"ID\" = $form->ID");
|
||||
$this->assertEquals($orignal->SubmitButtonText, 'Button Text');
|
||||
}
|
||||
|
||||
public function testGetCMSFields() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
public function testGetCMSFields()
|
||||
{
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
|
||||
$fields = $form->getCMSFields();
|
||||
$fields = $form->getCMSFields();
|
||||
|
||||
$this->assertTrue($fields->dataFieldByName('Fields') !== null);
|
||||
$this->assertTrue($fields->dataFieldByName('EmailRecipients') != null);
|
||||
$this->assertTrue($fields->dataFieldByName('Submissions') != null);
|
||||
$this->assertTrue($fields->dataFieldByName('OnCompleteMessage') != null);
|
||||
}
|
||||
$this->assertTrue($fields->dataFieldByName('Fields') !== null);
|
||||
$this->assertTrue($fields->dataFieldByName('EmailRecipients') != null);
|
||||
$this->assertTrue($fields->dataFieldByName('Submissions') != null);
|
||||
$this->assertTrue($fields->dataFieldByName('OnCompleteMessage') != null);
|
||||
}
|
||||
|
||||
public function testEmailRecipientPopup() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
public function testEmailRecipientPopup()
|
||||
{
|
||||
$this->logInWithPermission('ADMIN');
|
||||
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
|
||||
$popup = new UserDefinedForm_EmailRecipient();
|
||||
$popup->FormID = $form->ID;
|
||||
$popup = new UserDefinedForm_EmailRecipient();
|
||||
$popup->FormID = $form->ID;
|
||||
|
||||
$fields = $popup->getCMSFields();
|
||||
$fields = $popup->getCMSFields();
|
||||
|
||||
$this->assertTrue($fields->dataFieldByName('EmailSubject') !== null);
|
||||
$this->assertTrue($fields->dataFieldByName('EmailFrom') !== null);
|
||||
$this->assertTrue($fields->dataFieldByName('EmailAddress') !== null);
|
||||
$this->assertTrue($fields->dataFieldByName('HideFormData') !== null);
|
||||
$this->assertTrue($fields->dataFieldByName('SendPlain') !== null);
|
||||
$this->assertTrue($fields->dataFieldByName('EmailBody') !== null);
|
||||
$this->assertTrue($fields->dataFieldByName('EmailSubject') !== null);
|
||||
$this->assertTrue($fields->dataFieldByName('EmailFrom') !== null);
|
||||
$this->assertTrue($fields->dataFieldByName('EmailAddress') !== null);
|
||||
$this->assertTrue($fields->dataFieldByName('HideFormData') !== null);
|
||||
$this->assertTrue($fields->dataFieldByName('SendPlain') !== null);
|
||||
$this->assertTrue($fields->dataFieldByName('EmailBody') !== null);
|
||||
|
||||
// add an email field, it should now add a or from X address picker
|
||||
$email = $this->objFromFixture('EditableEmailField','email-field');
|
||||
$form->Fields()->add($email);
|
||||
// add an email field, it should now add a or from X address picker
|
||||
$email = $this->objFromFixture('EditableEmailField', 'email-field');
|
||||
$form->Fields()->add($email);
|
||||
|
||||
$popup->write();
|
||||
$popup->write();
|
||||
|
||||
$fields = $popup->getCMSFields();
|
||||
$this->assertThat($fields->dataFieldByName('SendEmailToFieldID'), $this->isInstanceOf('DropdownField'));
|
||||
$fields = $popup->getCMSFields();
|
||||
$this->assertThat($fields->dataFieldByName('SendEmailToFieldID'), $this->isInstanceOf('DropdownField'));
|
||||
|
||||
// if the front end has checkboxs or dropdown they can select from that can also be used to send things
|
||||
$dropdown = $this->objFromFixture('EditableDropdown', 'department-dropdown');
|
||||
$form->Fields()->add($dropdown);
|
||||
// if the front end has checkboxs or dropdown they can select from that can also be used to send things
|
||||
$dropdown = $this->objFromFixture('EditableDropdown', 'department-dropdown');
|
||||
$form->Fields()->add($dropdown);
|
||||
|
||||
$fields = $popup->getCMSFields();
|
||||
$this->assertTrue($fields->dataFieldByName('SendEmailToFieldID') !== null);
|
||||
$fields = $popup->getCMSFields();
|
||||
$this->assertTrue($fields->dataFieldByName('SendEmailToFieldID') !== null);
|
||||
|
||||
$popup->delete();
|
||||
}
|
||||
$popup->delete();
|
||||
}
|
||||
|
||||
function testGetEmailBodyContent() {
|
||||
$recipient = new UserDefinedForm_EmailRecipient();
|
||||
public function testGetEmailBodyContent()
|
||||
{
|
||||
$recipient = new UserDefinedForm_EmailRecipient();
|
||||
|
||||
$emailBody = 'not html';
|
||||
$emailBodyHtml = '<p>html</p>';
|
||||
$emailBody = 'not html';
|
||||
$emailBodyHtml = '<p>html</p>';
|
||||
|
||||
$recipient->EmailBody = $emailBody;
|
||||
$recipient->EmailBodyHtml = $emailBodyHtml;
|
||||
$recipient->write();
|
||||
$recipient->EmailBody = $emailBody;
|
||||
$recipient->EmailBodyHtml = $emailBodyHtml;
|
||||
$recipient->write();
|
||||
|
||||
$this->assertEquals($recipient->SendPlain, 0);
|
||||
$this->assertEquals($recipient->getEmailBodyContent(), $emailBodyHtml);
|
||||
$this->assertEquals($recipient->SendPlain, 0);
|
||||
$this->assertEquals($recipient->getEmailBodyContent(), $emailBodyHtml);
|
||||
|
||||
$recipient->SendPlain = 1;
|
||||
$recipient->write();
|
||||
$recipient->SendPlain = 1;
|
||||
$recipient->write();
|
||||
|
||||
$this->assertEquals($recipient->getEmailBodyContent(), $emailBody);
|
||||
$this->assertEquals($recipient->getEmailBodyContent(), $emailBody);
|
||||
|
||||
$recipient->delete();
|
||||
}
|
||||
$recipient->delete();
|
||||
}
|
||||
|
||||
function testGetEmailTemplateDropdownValues() {
|
||||
$recipient = new UserDefinedForm_EmailRecipient();
|
||||
public function testGetEmailTemplateDropdownValues()
|
||||
{
|
||||
$recipient = new UserDefinedForm_EmailRecipient();
|
||||
|
||||
$defaultValues = array('SubmittedFormEmail' => 'SubmittedFormEmail');
|
||||
$defaultValues = array('SubmittedFormEmail' => 'SubmittedFormEmail');
|
||||
|
||||
$this->assertEquals($recipient->getEmailTemplateDropdownValues(), $defaultValues);
|
||||
}
|
||||
$this->assertEquals($recipient->getEmailTemplateDropdownValues(), $defaultValues);
|
||||
}
|
||||
|
||||
function testEmailTemplateExists() {
|
||||
$recipient = new UserDefinedForm_EmailRecipient();
|
||||
public function testEmailTemplateExists()
|
||||
{
|
||||
$recipient = new UserDefinedForm_EmailRecipient();
|
||||
|
||||
// Set the default template
|
||||
$recipient->EmailTemplate = current(array_keys($recipient->getEmailTemplateDropdownValues()));
|
||||
$recipient->write();
|
||||
// Set the default template
|
||||
$recipient->EmailTemplate = current(array_keys($recipient->getEmailTemplateDropdownValues()));
|
||||
$recipient->write();
|
||||
|
||||
// The default template exists
|
||||
$this->assertTrue($recipient->emailTemplateExists());
|
||||
// The default template exists
|
||||
$this->assertTrue($recipient->emailTemplateExists());
|
||||
|
||||
// A made up template doesn't exists
|
||||
$this->assertFalse($recipient->emailTemplateExists('MyTemplateThatsNotThere'));
|
||||
// A made up template doesn't exists
|
||||
$this->assertFalse($recipient->emailTemplateExists('MyTemplateThatsNotThere'));
|
||||
|
||||
$recipient->delete();
|
||||
}
|
||||
$recipient->delete();
|
||||
}
|
||||
|
||||
function testCanEditAndDeleteRecipient() {
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
public function testCanEditAndDeleteRecipient()
|
||||
{
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
|
||||
$this->logInWithPermission('ADMIN');
|
||||
foreach($form->EmailRecipients() as $recipient) {
|
||||
$this->assertTrue($recipient->canEdit());
|
||||
$this->assertTrue($recipient->canDelete());
|
||||
}
|
||||
$this->logInWithPermission('ADMIN');
|
||||
foreach ($form->EmailRecipients() as $recipient) {
|
||||
$this->assertTrue($recipient->canEdit());
|
||||
$this->assertTrue($recipient->canDelete());
|
||||
}
|
||||
|
||||
$member = Member::currentUser();
|
||||
$member->logOut();
|
||||
$member = Member::currentUser();
|
||||
$member->logOut();
|
||||
|
||||
$this->logInWithPermission('SITETREE_VIEW_ALL');
|
||||
foreach($form->EmailRecipients() as $recipient) {
|
||||
$this->assertFalse($recipient->canEdit());
|
||||
$this->assertFalse($recipient->canDelete());
|
||||
}
|
||||
}
|
||||
$this->logInWithPermission('SITETREE_VIEW_ALL');
|
||||
foreach ($form->EmailRecipients() as $recipient) {
|
||||
$this->assertFalse($recipient->canEdit());
|
||||
$this->assertFalse($recipient->canDelete());
|
||||
}
|
||||
}
|
||||
|
||||
function testPublishing() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
public function testPublishing()
|
||||
{
|
||||
$this->logInWithPermission('ADMIN');
|
||||
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
$form->write();
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
$form->write();
|
||||
|
||||
$form->doPublish();
|
||||
$form->doPublish();
|
||||
|
||||
$live = Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = $form->ID");
|
||||
$live = Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = $form->ID");
|
||||
|
||||
$this->assertNotNull($live);
|
||||
$this->assertEquals(2, $live->Fields()->Count()); // one page and one field
|
||||
$this->assertNotNull($live);
|
||||
$this->assertEquals(2, $live->Fields()->Count()); // one page and one field
|
||||
|
||||
$dropdown = $this->objFromFixture('EditableDropdown', 'basic-dropdown');
|
||||
$form->Fields()->add($dropdown);
|
||||
$dropdown = $this->objFromFixture('EditableDropdown', 'basic-dropdown');
|
||||
$form->Fields()->add($dropdown);
|
||||
|
||||
$stage = Versioned::get_one_by_stage("UserDefinedForm", "Stage", "\"UserDefinedForm\".\"ID\" = $form->ID");
|
||||
$this->assertEquals(3, $stage->Fields()->Count());
|
||||
$stage = Versioned::get_one_by_stage("UserDefinedForm", "Stage", "\"UserDefinedForm\".\"ID\" = $form->ID");
|
||||
$this->assertEquals(3, $stage->Fields()->Count());
|
||||
|
||||
// should not have published the dropdown
|
||||
$liveDropdown = Versioned::get_one_by_stage("EditableFormField", "Live", "\"EditableFormField_Live\".\"ID\" = $dropdown->ID");
|
||||
$this->assertNull($liveDropdown);
|
||||
// should not have published the dropdown
|
||||
$liveDropdown = Versioned::get_one_by_stage("EditableFormField", "Live", "\"EditableFormField_Live\".\"ID\" = $dropdown->ID");
|
||||
$this->assertNull($liveDropdown);
|
||||
|
||||
// when publishing it should have added it
|
||||
$form->doPublish();
|
||||
// when publishing it should have added it
|
||||
$form->doPublish();
|
||||
|
||||
$live = Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = $form->ID");
|
||||
$this->assertEquals(3, $live->Fields()->Count());
|
||||
$live = Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = $form->ID");
|
||||
$this->assertEquals(3, $live->Fields()->Count());
|
||||
|
||||
// edit the title
|
||||
$text = $form->Fields()->limit(1, 1)->First();
|
||||
$text->Title = 'Edited title';
|
||||
$text->write();
|
||||
// edit the title
|
||||
$text = $form->Fields()->limit(1, 1)->First();
|
||||
$text->Title = 'Edited title';
|
||||
$text->write();
|
||||
|
||||
$liveText = Versioned::get_one_by_stage("EditableFormField", "Live", "\"EditableFormField_Live\".\"ID\" = $text->ID");
|
||||
$this->assertFalse($liveText->Title == $text->Title);
|
||||
$liveText = Versioned::get_one_by_stage("EditableFormField", "Live", "\"EditableFormField_Live\".\"ID\" = $text->ID");
|
||||
$this->assertFalse($liveText->Title == $text->Title);
|
||||
|
||||
$form->doPublish();
|
||||
$form->doPublish();
|
||||
|
||||
$liveText = Versioned::get_one_by_stage("EditableFormField", "Live", "\"EditableFormField_Live\".\"ID\" = $text->ID");
|
||||
$this->assertTrue($liveText->Title == $text->Title);
|
||||
$liveText = Versioned::get_one_by_stage("EditableFormField", "Live", "\"EditableFormField_Live\".\"ID\" = $text->ID");
|
||||
$this->assertTrue($liveText->Title == $text->Title);
|
||||
|
||||
// Add a display rule to the dropdown
|
||||
$displayRule = new EditableCustomRule();
|
||||
$displayRule->ParentID = $dropdown->ID;
|
||||
$displayRule->ConditionFieldID = $text->ID;
|
||||
$displayRule->write();
|
||||
$ruleID = $displayRule->ID;
|
||||
// Add a display rule to the dropdown
|
||||
$displayRule = new EditableCustomRule();
|
||||
$displayRule->ParentID = $dropdown->ID;
|
||||
$displayRule->ConditionFieldID = $text->ID;
|
||||
$displayRule->write();
|
||||
$ruleID = $displayRule->ID;
|
||||
|
||||
// Not live
|
||||
$liveRule = Versioned::get_one_by_stage("EditableCustomRule", "Live", "\"EditableCustomRule_Live\".\"ID\" = $ruleID");
|
||||
$this->assertEmpty($liveRule);
|
||||
// Not live
|
||||
$liveRule = Versioned::get_one_by_stage("EditableCustomRule", "Live", "\"EditableCustomRule_Live\".\"ID\" = $ruleID");
|
||||
$this->assertEmpty($liveRule);
|
||||
|
||||
// Publish form, it's now live
|
||||
$form->doPublish();
|
||||
$liveRule = Versioned::get_one_by_stage("EditableCustomRule", "Live", "\"EditableCustomRule_Live\".\"ID\" = $ruleID");
|
||||
$this->assertNotEmpty($liveRule);
|
||||
// Publish form, it's now live
|
||||
$form->doPublish();
|
||||
$liveRule = Versioned::get_one_by_stage("EditableCustomRule", "Live", "\"EditableCustomRule_Live\".\"ID\" = $ruleID");
|
||||
$this->assertNotEmpty($liveRule);
|
||||
|
||||
// Remove rule
|
||||
$displayRule->delete();
|
||||
// Remove rule
|
||||
$displayRule->delete();
|
||||
|
||||
// Live rule still exists
|
||||
$liveRule = Versioned::get_one_by_stage("EditableCustomRule", "Live", "\"EditableCustomRule_Live\".\"ID\" = $ruleID");
|
||||
$this->assertNotEmpty($liveRule);
|
||||
// Live rule still exists
|
||||
$liveRule = Versioned::get_one_by_stage("EditableCustomRule", "Live", "\"EditableCustomRule_Live\".\"ID\" = $ruleID");
|
||||
$this->assertNotEmpty($liveRule);
|
||||
|
||||
// Publish form, it should remove this rule
|
||||
$form->doPublish();
|
||||
$liveRule = Versioned::get_one_by_stage("EditableCustomRule", "Live", "\"EditableCustomRule_Live\".\"ID\" = $ruleID");
|
||||
$this->assertEmpty($liveRule);
|
||||
}
|
||||
// Publish form, it should remove this rule
|
||||
$form->doPublish();
|
||||
$liveRule = Versioned::get_one_by_stage("EditableCustomRule", "Live", "\"EditableCustomRule_Live\".\"ID\" = $ruleID");
|
||||
$this->assertEmpty($liveRule);
|
||||
}
|
||||
|
||||
function testUnpublishing() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
$form->write();
|
||||
$this->assertEquals(0, DB::query("SELECT COUNT(*) FROM \"EditableFormField_Live\"")->value());
|
||||
$form->doPublish();
|
||||
public function testUnpublishing()
|
||||
{
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
$form->write();
|
||||
$this->assertEquals(0, DB::query("SELECT COUNT(*) FROM \"EditableFormField_Live\"")->value());
|
||||
$form->doPublish();
|
||||
|
||||
// assert that it exists and has a field
|
||||
$live = Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = $form->ID");
|
||||
|
||||
$this->assertTrue(isset($live));
|
||||
$this->assertEquals(2, DB::query("SELECT COUNT(*) FROM \"EditableFormField_Live\"")->value());
|
||||
|
||||
// unpublish
|
||||
$form->doUnpublish();
|
||||
|
||||
$this->assertNull(Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = $form->ID"));
|
||||
$this->assertEquals(0, DB::query("SELECT COUNT(*) FROM \"EditableFormField_Live\"")->value());
|
||||
}
|
||||
|
||||
function testDoRevertToLive() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
$field = $form->Fields()->First();
|
||||
|
||||
$field->Title = 'Title';
|
||||
$field->write();
|
||||
|
||||
$form->doPublish();
|
||||
|
||||
$field->Title = 'Edited title';
|
||||
$field->write();
|
||||
|
||||
// check that the published version is not updated
|
||||
$live = Versioned::get_one_by_stage("EditableFormField", "Live", "\"EditableFormField_Live\".\"ID\" = $field->ID");
|
||||
$this->assertEquals('Title', $live->Title);
|
||||
|
||||
// revert back to the live data
|
||||
$form->doRevertToLive();
|
||||
$form->flushCache();
|
||||
|
||||
$check = Versioned::get_one_by_stage("EditableFormField", "Stage", "\"EditableFormField\".\"ID\" = $field->ID");
|
||||
|
||||
$this->assertEquals('Title', $check->Title);
|
||||
}
|
||||
|
||||
function testDuplicatingForm() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
|
||||
$duplicate = $form->duplicate();
|
||||
|
||||
$this->assertEquals($form->Fields()->Count(), $duplicate->Fields()->Count());
|
||||
$this->assertEquals($form->EmailRecipients()->Count(), $form->EmailRecipients()->Count());
|
||||
|
||||
// can't compare object since the dates/ids change
|
||||
$this->assertEquals($form->Fields()->First()->Title, $duplicate->Fields()->First()->Title);
|
||||
|
||||
// Test duplicate with group
|
||||
$form2 = $this->objFromFixture('UserDefinedForm', 'page-with-group');
|
||||
$form2Validator = new UserFormValidator();
|
||||
$form2Validator->setForm(new Form(new Controller(), 'Form', new FieldList(), new FieldList()));
|
||||
$this->assertTrue($form2Validator->php($form2->toMap()));
|
||||
|
||||
// Check field groups exist
|
||||
$form2GroupStart = $form2->Fields()->filter('ClassName', 'EditableFieldGroup')->first();
|
||||
$form2GroupEnd = $form2->Fields()->filter('ClassName', 'EditableFieldGroupEnd')->first();
|
||||
$this->assertEquals($form2GroupEnd->ID, $form2GroupStart->EndID);
|
||||
|
||||
// Duplicate this
|
||||
$form3 = $form2->duplicate();
|
||||
$form3Validator = new UserFormValidator();
|
||||
$form3Validator->setForm(new Form(new Controller(), 'Form', new FieldList(), new FieldList()));
|
||||
$this->assertTrue($form3Validator->php($form3->toMap()));
|
||||
|
||||
// Check field groups exist
|
||||
$form3GroupStart = $form3->Fields()->filter('ClassName', 'EditableFieldGroup')->first();
|
||||
$form3GroupEnd = $form3->Fields()->filter('ClassName', 'EditableFieldGroupEnd')->first();
|
||||
$this->assertEquals($form3GroupEnd->ID, $form3GroupStart->EndID);
|
||||
$this->assertNotEquals($form2GroupEnd->ID, $form3GroupStart->EndID);
|
||||
}
|
||||
|
||||
function testFormOptions() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
|
||||
$fields = $form->getFormOptions();
|
||||
$submit = $fields->fieldByName('SubmitButtonText');
|
||||
$reset = $fields->fieldByName('ShowClearButton');
|
||||
|
||||
$this->assertEquals($submit->Title(), 'Text on submit button:');
|
||||
$this->assertEquals($reset->Title(), 'Show Clear Form Button');
|
||||
}
|
||||
|
||||
public function testEmailRecipientFilters() {
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'filtered-form-page');
|
||||
|
||||
// Check unfiltered recipients
|
||||
$result0 = $form
|
||||
->EmailRecipients()
|
||||
->sort('EmailAddress')
|
||||
->column('EmailAddress');
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'filtered1@example.com',
|
||||
'filtered2@example.com',
|
||||
'unfiltered@example.com'
|
||||
),
|
||||
$result0
|
||||
);
|
||||
|
||||
// check filters based on given data
|
||||
$result1 = $form->FilteredEmailRecipients(
|
||||
array(
|
||||
'your-name' => 'Value',
|
||||
'address' => '',
|
||||
'street' => 'Anything',
|
||||
'city' => 'Matches Not Equals',
|
||||
'colours' => array('Red') // matches 2
|
||||
), null
|
||||
)
|
||||
->sort('EmailAddress')
|
||||
->column('EmailAddress');
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'filtered2@example.com',
|
||||
'unfiltered@example.com'
|
||||
),
|
||||
$result1
|
||||
);
|
||||
|
||||
// Check all positive matches
|
||||
$result2 = $form->FilteredEmailRecipients(
|
||||
array(
|
||||
'your-name' => '',
|
||||
'address' => 'Anything',
|
||||
'street' => 'Matches Equals',
|
||||
'city' => 'Anything',
|
||||
'colours' => array('Red', 'Blue') // matches 2
|
||||
), null
|
||||
)
|
||||
->sort('EmailAddress')
|
||||
->column('EmailAddress');
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'filtered1@example.com',
|
||||
'filtered2@example.com',
|
||||
'unfiltered@example.com'
|
||||
),
|
||||
$result2
|
||||
);
|
||||
|
||||
|
||||
$result3 = $form->FilteredEmailRecipients(
|
||||
array(
|
||||
'your-name' => 'Should be blank but is not',
|
||||
'address' => 'Anything',
|
||||
'street' => 'Matches Equals',
|
||||
'city' => 'Anything',
|
||||
'colours' => array('Blue')
|
||||
), null
|
||||
)->column('EmailAddress');
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'unfiltered@example.com'
|
||||
),
|
||||
$result3
|
||||
);
|
||||
|
||||
|
||||
$result4 = $form->FilteredEmailRecipients(
|
||||
array(
|
||||
'your-name' => '',
|
||||
'address' => 'Anything',
|
||||
'street' => 'Wrong value for this field',
|
||||
'city' => '',
|
||||
'colours' => array('Blue', 'Green')
|
||||
), null
|
||||
)->column('EmailAddress');
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'unfiltered@example.com'
|
||||
),
|
||||
$result4
|
||||
);
|
||||
}
|
||||
|
||||
public function testIndex() {
|
||||
// Test that the $UserDefinedForm is stripped out
|
||||
$page = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
$page->publish('Stage', 'Live');
|
||||
|
||||
$result = $this->get($page->Link());
|
||||
$body = Convert::nl2os($result->getBody(), ''); // strip out newlines
|
||||
$this->assertFalse($result->isError());
|
||||
$this->assertContains('<p>Here is my form</p><form', $body);
|
||||
$this->assertContains('</form><p>Thank you for filling it out</p>', $body);
|
||||
|
||||
$this->assertNotContains('<p>$UserDefinedForm</p>', $body);
|
||||
$this->assertNotContains('<p></p>', $body);
|
||||
$this->assertNotContains('</p><p>Thank you for filling it out</p>', $body);
|
||||
}
|
||||
// assert that it exists and has a field
|
||||
$live = Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = $form->ID");
|
||||
|
||||
$this->assertTrue(isset($live));
|
||||
$this->assertEquals(2, DB::query("SELECT COUNT(*) FROM \"EditableFormField_Live\"")->value());
|
||||
|
||||
// unpublish
|
||||
$form->doUnpublish();
|
||||
|
||||
$this->assertNull(Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = $form->ID"));
|
||||
$this->assertEquals(0, DB::query("SELECT COUNT(*) FROM \"EditableFormField_Live\"")->value());
|
||||
}
|
||||
|
||||
public function testDoRevertToLive()
|
||||
{
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
$field = $form->Fields()->First();
|
||||
|
||||
$field->Title = 'Title';
|
||||
$field->write();
|
||||
|
||||
$form->doPublish();
|
||||
|
||||
$field->Title = 'Edited title';
|
||||
$field->write();
|
||||
|
||||
// check that the published version is not updated
|
||||
$live = Versioned::get_one_by_stage("EditableFormField", "Live", "\"EditableFormField_Live\".\"ID\" = $field->ID");
|
||||
$this->assertEquals('Title', $live->Title);
|
||||
|
||||
// revert back to the live data
|
||||
$form->doRevertToLive();
|
||||
$form->flushCache();
|
||||
|
||||
$check = Versioned::get_one_by_stage("EditableFormField", "Stage", "\"EditableFormField\".\"ID\" = $field->ID");
|
||||
|
||||
$this->assertEquals('Title', $check->Title);
|
||||
}
|
||||
|
||||
public function testDuplicatingForm()
|
||||
{
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
|
||||
$duplicate = $form->duplicate();
|
||||
|
||||
$this->assertEquals($form->Fields()->Count(), $duplicate->Fields()->Count());
|
||||
$this->assertEquals($form->EmailRecipients()->Count(), $form->EmailRecipients()->Count());
|
||||
|
||||
// can't compare object since the dates/ids change
|
||||
$this->assertEquals($form->Fields()->First()->Title, $duplicate->Fields()->First()->Title);
|
||||
|
||||
// Test duplicate with group
|
||||
$form2 = $this->objFromFixture('UserDefinedForm', 'page-with-group');
|
||||
$form2Validator = new UserFormValidator();
|
||||
$form2Validator->setForm(new Form(new Controller(), 'Form', new FieldList(), new FieldList()));
|
||||
$this->assertTrue($form2Validator->php($form2->toMap()));
|
||||
|
||||
// Check field groups exist
|
||||
$form2GroupStart = $form2->Fields()->filter('ClassName', 'EditableFieldGroup')->first();
|
||||
$form2GroupEnd = $form2->Fields()->filter('ClassName', 'EditableFieldGroupEnd')->first();
|
||||
$this->assertEquals($form2GroupEnd->ID, $form2GroupStart->EndID);
|
||||
|
||||
// Duplicate this
|
||||
$form3 = $form2->duplicate();
|
||||
$form3Validator = new UserFormValidator();
|
||||
$form3Validator->setForm(new Form(new Controller(), 'Form', new FieldList(), new FieldList()));
|
||||
$this->assertTrue($form3Validator->php($form3->toMap()));
|
||||
|
||||
// Check field groups exist
|
||||
$form3GroupStart = $form3->Fields()->filter('ClassName', 'EditableFieldGroup')->first();
|
||||
$form3GroupEnd = $form3->Fields()->filter('ClassName', 'EditableFieldGroupEnd')->first();
|
||||
$this->assertEquals($form3GroupEnd->ID, $form3GroupStart->EndID);
|
||||
$this->assertNotEquals($form2GroupEnd->ID, $form3GroupStart->EndID);
|
||||
}
|
||||
|
||||
public function testFormOptions()
|
||||
{
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
|
||||
$fields = $form->getFormOptions();
|
||||
$submit = $fields->fieldByName('SubmitButtonText');
|
||||
$reset = $fields->fieldByName('ShowClearButton');
|
||||
|
||||
$this->assertEquals($submit->Title(), 'Text on submit button:');
|
||||
$this->assertEquals($reset->Title(), 'Show Clear Form Button');
|
||||
}
|
||||
|
||||
public function testEmailRecipientFilters()
|
||||
{
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'filtered-form-page');
|
||||
|
||||
// Check unfiltered recipients
|
||||
$result0 = $form
|
||||
->EmailRecipients()
|
||||
->sort('EmailAddress')
|
||||
->column('EmailAddress');
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'filtered1@example.com',
|
||||
'filtered2@example.com',
|
||||
'unfiltered@example.com'
|
||||
),
|
||||
$result0
|
||||
);
|
||||
|
||||
// check filters based on given data
|
||||
$result1 = $form->FilteredEmailRecipients(
|
||||
array(
|
||||
'your-name' => 'Value',
|
||||
'address' => '',
|
||||
'street' => 'Anything',
|
||||
'city' => 'Matches Not Equals',
|
||||
'colours' => array('Red') // matches 2
|
||||
), null
|
||||
)
|
||||
->sort('EmailAddress')
|
||||
->column('EmailAddress');
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'filtered2@example.com',
|
||||
'unfiltered@example.com'
|
||||
),
|
||||
$result1
|
||||
);
|
||||
|
||||
// Check all positive matches
|
||||
$result2 = $form->FilteredEmailRecipients(
|
||||
array(
|
||||
'your-name' => '',
|
||||
'address' => 'Anything',
|
||||
'street' => 'Matches Equals',
|
||||
'city' => 'Anything',
|
||||
'colours' => array('Red', 'Blue') // matches 2
|
||||
), null
|
||||
)
|
||||
->sort('EmailAddress')
|
||||
->column('EmailAddress');
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'filtered1@example.com',
|
||||
'filtered2@example.com',
|
||||
'unfiltered@example.com'
|
||||
),
|
||||
$result2
|
||||
);
|
||||
|
||||
|
||||
$result3 = $form->FilteredEmailRecipients(
|
||||
array(
|
||||
'your-name' => 'Should be blank but is not',
|
||||
'address' => 'Anything',
|
||||
'street' => 'Matches Equals',
|
||||
'city' => 'Anything',
|
||||
'colours' => array('Blue')
|
||||
), null
|
||||
)->column('EmailAddress');
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'unfiltered@example.com'
|
||||
),
|
||||
$result3
|
||||
);
|
||||
|
||||
|
||||
$result4 = $form->FilteredEmailRecipients(
|
||||
array(
|
||||
'your-name' => '',
|
||||
'address' => 'Anything',
|
||||
'street' => 'Wrong value for this field',
|
||||
'city' => '',
|
||||
'colours' => array('Blue', 'Green')
|
||||
), null
|
||||
)->column('EmailAddress');
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'unfiltered@example.com'
|
||||
),
|
||||
$result4
|
||||
);
|
||||
}
|
||||
|
||||
public function testIndex()
|
||||
{
|
||||
// Test that the $UserDefinedForm is stripped out
|
||||
$page = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
$page->publish('Stage', 'Live');
|
||||
|
||||
$result = $this->get($page->Link());
|
||||
$body = Convert::nl2os($result->getBody(), ''); // strip out newlines
|
||||
$this->assertFalse($result->isError());
|
||||
$this->assertContains('<p>Here is my form</p><form', $body);
|
||||
$this->assertContains('</form><p>Thank you for filling it out</p>', $body);
|
||||
|
||||
$this->assertNotContains('<p>$UserDefinedForm</p>', $body);
|
||||
$this->assertNotContains('<p></p>', $body);
|
||||
$this->assertNotContains('</p><p>Thank you for filling it out</p>', $body);
|
||||
}
|
||||
}
|
@ -1,18 +1,20 @@
|
||||
<?php
|
||||
|
||||
|
||||
class UserFormTest extends SapphireTest {
|
||||
class UserFormTest extends SapphireTest
|
||||
{
|
||||
|
||||
protected static $fixture_file = 'UserDefinedFormTest.yml';
|
||||
protected static $fixture_file = 'UserDefinedFormTest.yml';
|
||||
|
||||
/**
|
||||
* Tests that a form will not generate empty pages
|
||||
*/
|
||||
public function testEmptyPages() {
|
||||
$page = $this->objFromFixture('UserDefinedForm', 'empty-page');
|
||||
$this->assertEquals(5, $page->Fields()->count());
|
||||
$controller = ModelAsController::controller_for($page);
|
||||
$form = new UserForm($controller);
|
||||
$this->assertEquals(2, $form->getSteps()->count());
|
||||
}
|
||||
/**
|
||||
* Tests that a form will not generate empty pages
|
||||
*/
|
||||
public function testEmptyPages()
|
||||
{
|
||||
$page = $this->objFromFixture('UserDefinedForm', 'empty-page');
|
||||
$this->assertEquals(5, $page->Fields()->count());
|
||||
$controller = ModelAsController::controller_for($page);
|
||||
$form = new UserForm($controller);
|
||||
$this->assertEquals(2, $form->getSteps()->count());
|
||||
}
|
||||
}
|
@ -1,216 +1,220 @@
|
||||
<?php
|
||||
|
||||
class UserFormsUpgradeServiceTest extends SapphireTest {
|
||||
class UserFormsUpgradeServiceTest extends SapphireTest
|
||||
{
|
||||
|
||||
static $fixture_file = 'UserFormsUpgradeServiceTest.yml';
|
||||
public static $fixture_file = 'UserFormsUpgradeServiceTest.yml';
|
||||
|
||||
public function setUp() {
|
||||
Config::inst()->update('UserDefinedForm', 'upgrade_on_build', false);
|
||||
parent::setUp();
|
||||
public function setUp()
|
||||
{
|
||||
Config::inst()->update('UserDefinedForm', 'upgrade_on_build', false);
|
||||
parent::setUp();
|
||||
|
||||
// Assign rules programatically
|
||||
$field1 = $this->objFromFixture('EditableTextField', 'text1');
|
||||
$field2 = $this->objFromFixture('EditableTextField', 'text2');
|
||||
$field3 = $this->objFromFixture('EditableTextField', 'text3');
|
||||
// Assign rules programatically
|
||||
$field1 = $this->objFromFixture('EditableTextField', 'text1');
|
||||
$field2 = $this->objFromFixture('EditableTextField', 'text2');
|
||||
$field3 = $this->objFromFixture('EditableTextField', 'text3');
|
||||
|
||||
$field3->CustomRules = serialize(array(
|
||||
array(
|
||||
'Display' => 'Show',
|
||||
'ConditionField' => $field1->Name,
|
||||
'ConditionOption' => 'IsBlank',
|
||||
'Value' => ''
|
||||
),
|
||||
array(
|
||||
'Display' => 'Hide',
|
||||
'ConditionField' => $field2->Name,
|
||||
'ConditionOption' => 'HasValue',
|
||||
'Value' => 'bob'
|
||||
)
|
||||
));
|
||||
$field3->write();
|
||||
$field3->CustomRules = serialize(array(
|
||||
array(
|
||||
'Display' => 'Show',
|
||||
'ConditionField' => $field1->Name,
|
||||
'ConditionOption' => 'IsBlank',
|
||||
'Value' => ''
|
||||
),
|
||||
array(
|
||||
'Display' => 'Hide',
|
||||
'ConditionField' => $field2->Name,
|
||||
'ConditionOption' => 'HasValue',
|
||||
'Value' => 'bob'
|
||||
)
|
||||
));
|
||||
$field3->write();
|
||||
|
||||
// Assign settings programatically
|
||||
$field4 = $this->objFromFixture('EditableTextField', 'text4');
|
||||
$field4->CustomSettings = serialize(array(
|
||||
'MinLength' => 20,
|
||||
'MaxLength' => 100,
|
||||
'Rows' => 4,
|
||||
'ExtraClass' => 'special class',
|
||||
'RightTitle' => 'My Field',
|
||||
'ShowOnLoad' => '',
|
||||
'Default' => 'Enter your text here'
|
||||
));
|
||||
$field4->write();
|
||||
// Assign settings programatically
|
||||
$field4 = $this->objFromFixture('EditableTextField', 'text4');
|
||||
$field4->CustomSettings = serialize(array(
|
||||
'MinLength' => 20,
|
||||
'MaxLength' => 100,
|
||||
'Rows' => 4,
|
||||
'ExtraClass' => 'special class',
|
||||
'RightTitle' => 'My Field',
|
||||
'ShowOnLoad' => '',
|
||||
'Default' => 'Enter your text here'
|
||||
));
|
||||
$field4->write();
|
||||
|
||||
$numeric1 = $this->objFromFixture('EditableNumericField', 'numeric1');
|
||||
$numeric1->CustomSettings = serialize(array(
|
||||
'RightTitle' => 'Number of %',
|
||||
'Default' => 1,
|
||||
'MinValue' => 1,
|
||||
'MaxValue' => 100,
|
||||
'ShowOnLoad' => 'Show'
|
||||
));
|
||||
$numeric1->write();
|
||||
$numeric1 = $this->objFromFixture('EditableNumericField', 'numeric1');
|
||||
$numeric1->CustomSettings = serialize(array(
|
||||
'RightTitle' => 'Number of %',
|
||||
'Default' => 1,
|
||||
'MinValue' => 1,
|
||||
'MaxValue' => 100,
|
||||
'ShowOnLoad' => 'Show'
|
||||
));
|
||||
$numeric1->write();
|
||||
|
||||
$group1 = $this->objFromFixture('Group', 'group1');
|
||||
$members1 = $this->objFromFixture('EditableMemberListField', 'members1');
|
||||
$members1->CustomSettings = serialize(array(
|
||||
'RightTitle' => 'Select group',
|
||||
'GroupID' => $group1->ID,
|
||||
'ShowOnLoad' => 'Hide'
|
||||
));
|
||||
$members1->write();
|
||||
$group1 = $this->objFromFixture('Group', 'group1');
|
||||
$members1 = $this->objFromFixture('EditableMemberListField', 'members1');
|
||||
$members1->CustomSettings = serialize(array(
|
||||
'RightTitle' => 'Select group',
|
||||
'GroupID' => $group1->ID,
|
||||
'ShowOnLoad' => 'Hide'
|
||||
));
|
||||
$members1->write();
|
||||
|
||||
$literal1 = $this->objFromFixture('EditableLiteralField', 'literal1');
|
||||
$literal1->CustomSettings = serialize(array(
|
||||
'HideFromReports' => 1,
|
||||
'RightTitle' => 'Literal',
|
||||
'Content' => '<p>Content</p>',
|
||||
'ShowOnLoad' => true
|
||||
));
|
||||
$literal1->write();
|
||||
$literal1 = $this->objFromFixture('EditableLiteralField', 'literal1');
|
||||
$literal1->CustomSettings = serialize(array(
|
||||
'HideFromReports' => 1,
|
||||
'RightTitle' => 'Literal',
|
||||
'Content' => '<p>Content</p>',
|
||||
'ShowOnLoad' => true
|
||||
));
|
||||
$literal1->write();
|
||||
|
||||
$heading1 = $this->objFromFixture('EditableFormHeading', 'heading1');
|
||||
$heading1->CustomSettings = serialize(array(
|
||||
'RightTitle' => 'Right',
|
||||
'Level' => 3,
|
||||
'HideFromReports' => true,
|
||||
'ShowOnLoad' => false
|
||||
));
|
||||
$heading1->write();
|
||||
$heading1 = $this->objFromFixture('EditableFormHeading', 'heading1');
|
||||
$heading1->CustomSettings = serialize(array(
|
||||
'RightTitle' => 'Right',
|
||||
'Level' => 3,
|
||||
'HideFromReports' => true,
|
||||
'ShowOnLoad' => false
|
||||
));
|
||||
$heading1->write();
|
||||
|
||||
$folder = $this->objFromFixture('Folder', 'folder1');
|
||||
$file1 = $this->objFromFixture('EditableFileField', 'file1');
|
||||
$file1->CustomSettings = serialize(array(
|
||||
'RightTitle' => 'File field',
|
||||
'Folder' => $folder->ID
|
||||
));
|
||||
$file1->write();
|
||||
$folder = $this->objFromFixture('Folder', 'folder1');
|
||||
$file1 = $this->objFromFixture('EditableFileField', 'file1');
|
||||
$file1->CustomSettings = serialize(array(
|
||||
'RightTitle' => 'File field',
|
||||
'Folder' => $folder->ID
|
||||
));
|
||||
$file1->write();
|
||||
|
||||
$date1 = $this->objFromFixture('EditableDateField', 'date1');
|
||||
$date1->CustomSettings = serialize(array(
|
||||
'RightTitle' => 'Date field',
|
||||
'DefaultToToday' => '1'
|
||||
));
|
||||
$date1->write();
|
||||
$date1 = $this->objFromFixture('EditableDateField', 'date1');
|
||||
$date1->CustomSettings = serialize(array(
|
||||
'RightTitle' => 'Date field',
|
||||
'DefaultToToday' => '1'
|
||||
));
|
||||
$date1->write();
|
||||
|
||||
$checkbox1 = $this->objFromFixture('EditableCheckbox', 'checkbox1');
|
||||
$checkbox1->CustomSettings = serialize(array(
|
||||
'Default' => true,
|
||||
'RightTitle' => 'Check this'
|
||||
));
|
||||
$checkbox1->write();
|
||||
$checkbox1 = $this->objFromFixture('EditableCheckbox', 'checkbox1');
|
||||
$checkbox1->CustomSettings = serialize(array(
|
||||
'Default' => true,
|
||||
'RightTitle' => 'Check this'
|
||||
));
|
||||
$checkbox1->write();
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @return UserFormsUpgradeService;
|
||||
*/
|
||||
protected function getService()
|
||||
{
|
||||
return singleton('UserFormsUpgradeService');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UserFormsUpgradeService;
|
||||
*/
|
||||
protected function getService() {
|
||||
return singleton('UserFormsUpgradeService');
|
||||
}
|
||||
/**
|
||||
* Tests migration of custom rules
|
||||
*/
|
||||
public function testCustomRulesMigration()
|
||||
{
|
||||
$service = $this->getService();
|
||||
$service->setQuiet(true);
|
||||
$service->run();
|
||||
|
||||
/**
|
||||
* Tests migration of custom rules
|
||||
*/
|
||||
public function testCustomRulesMigration() {
|
||||
$service = $this->getService();
|
||||
$service->setQuiet(true);
|
||||
$service->run();
|
||||
$field1 = $this->objFromFixture('EditableTextField', 'text1');
|
||||
$field2 = $this->objFromFixture('EditableTextField', 'text2');
|
||||
$field3 = $this->objFromFixture('EditableTextField', 'text3');
|
||||
|
||||
$field1 = $this->objFromFixture('EditableTextField', 'text1');
|
||||
$field2 = $this->objFromFixture('EditableTextField', 'text2');
|
||||
$field3 = $this->objFromFixture('EditableTextField', 'text3');
|
||||
$this->assertDOSEquals(array(
|
||||
array(
|
||||
'Display' => 'Show',
|
||||
'ConditionFieldID' => $field1->ID,
|
||||
'ConditionOption' => 'IsBlank'
|
||||
),
|
||||
array(
|
||||
'Display' => 'Hide',
|
||||
'ConditionFieldID' => $field2->ID,
|
||||
'ConditionOption' => 'HasValue',
|
||||
'FieldValue' => 'bob'
|
||||
)
|
||||
), $field3->DisplayRules());
|
||||
}
|
||||
|
||||
$this->assertDOSEquals(array(
|
||||
array(
|
||||
'Display' => 'Show',
|
||||
'ConditionFieldID' => $field1->ID,
|
||||
'ConditionOption' => 'IsBlank'
|
||||
),
|
||||
array(
|
||||
'Display' => 'Hide',
|
||||
'ConditionFieldID' => $field2->ID,
|
||||
'ConditionOption' => 'HasValue',
|
||||
'FieldValue' => 'bob'
|
||||
)
|
||||
), $field3->DisplayRules());
|
||||
}
|
||||
/**
|
||||
* Tests migration of all custom settings
|
||||
*/
|
||||
public function testCustomSettingsMigration()
|
||||
{
|
||||
$service = $this->getService();
|
||||
$service->setQuiet(true);
|
||||
$service->run();
|
||||
|
||||
/**
|
||||
* Tests migration of all custom settings
|
||||
*/
|
||||
public function testCustomSettingsMigration() {
|
||||
$service = $this->getService();
|
||||
$service->setQuiet(true);
|
||||
$service->run();
|
||||
$group1 = $this->objFromFixture('Group', 'group1');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'form-with-settings');
|
||||
$folder = $this->objFromFixture('Folder', 'folder1');
|
||||
|
||||
$group1 = $this->objFromFixture('Group', 'group1');
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'form-with-settings');
|
||||
$folder = $this->objFromFixture('Folder', 'folder1');
|
||||
|
||||
$this->assertDOSEquals(array(
|
||||
array(
|
||||
'ClassName' => 'EditableTextField',
|
||||
'Title' => 'Text with rule',
|
||||
'MinLength' => 20,
|
||||
'MaxLength' => 100,
|
||||
'Rows' => 4,
|
||||
'ExtraClass' => 'special class',
|
||||
'RightTitle' => 'My Field',
|
||||
'ShowOnLoad' => true,
|
||||
'Default' => 'Enter your text here',
|
||||
),
|
||||
array(
|
||||
'ClassName' => 'EditableNumericField',
|
||||
'Title' => 'Numeric 1',
|
||||
'RightTitle' => 'Number of %',
|
||||
'Default' => 1,
|
||||
'MinValue' => 1,
|
||||
'MaxValue' => 100,
|
||||
'ShowOnLoad' => true,
|
||||
),
|
||||
array(
|
||||
'ClassName' => 'EditableMemberListField',
|
||||
'Title' => 'Members 1',
|
||||
'RightTitle' => 'Select group',
|
||||
'GroupID' => $group1->ID,
|
||||
'ShowOnLoad' => false,
|
||||
),
|
||||
array(
|
||||
'ClassName' => 'EditableLiteralField',
|
||||
'Title' => 'Literal 1',
|
||||
'HideFromReports' => true,
|
||||
'RightTitle' => 'Literal',
|
||||
'Content' => '<p>Content</p>',
|
||||
'ShowOnLoad' => true,
|
||||
),
|
||||
array(
|
||||
'ClassName' => 'EditableFormHeading',
|
||||
'Title' => 'Heading 1',
|
||||
'RightTitle' => 'Right',
|
||||
'Level' => 3,
|
||||
'HideFromReports' => true,
|
||||
'ShowOnLoad' => false,
|
||||
),
|
||||
array(
|
||||
'ClassName' => 'EditableFileField',
|
||||
'Title' => 'File 1',
|
||||
'RightTitle' => 'File field',
|
||||
'FolderID' => $folder->ID,
|
||||
),
|
||||
array(
|
||||
'ClassName' => 'EditableDateField',
|
||||
'Title' => 'Date 1',
|
||||
'RightTitle' => 'Date field',
|
||||
'DefaultToToday' => true,
|
||||
),
|
||||
array(
|
||||
'ClassName' => 'EditableCheckbox',
|
||||
'Title' => 'Checkbox 1',
|
||||
'CheckedDefault' => true,
|
||||
'RightTitle' => 'Check this',
|
||||
),
|
||||
), $form->Fields());
|
||||
}
|
||||
$this->assertDOSEquals(array(
|
||||
array(
|
||||
'ClassName' => 'EditableTextField',
|
||||
'Title' => 'Text with rule',
|
||||
'MinLength' => 20,
|
||||
'MaxLength' => 100,
|
||||
'Rows' => 4,
|
||||
'ExtraClass' => 'special class',
|
||||
'RightTitle' => 'My Field',
|
||||
'ShowOnLoad' => true,
|
||||
'Default' => 'Enter your text here',
|
||||
),
|
||||
array(
|
||||
'ClassName' => 'EditableNumericField',
|
||||
'Title' => 'Numeric 1',
|
||||
'RightTitle' => 'Number of %',
|
||||
'Default' => 1,
|
||||
'MinValue' => 1,
|
||||
'MaxValue' => 100,
|
||||
'ShowOnLoad' => true,
|
||||
),
|
||||
array(
|
||||
'ClassName' => 'EditableMemberListField',
|
||||
'Title' => 'Members 1',
|
||||
'RightTitle' => 'Select group',
|
||||
'GroupID' => $group1->ID,
|
||||
'ShowOnLoad' => false,
|
||||
),
|
||||
array(
|
||||
'ClassName' => 'EditableLiteralField',
|
||||
'Title' => 'Literal 1',
|
||||
'HideFromReports' => true,
|
||||
'RightTitle' => 'Literal',
|
||||
'Content' => '<p>Content</p>',
|
||||
'ShowOnLoad' => true,
|
||||
),
|
||||
array(
|
||||
'ClassName' => 'EditableFormHeading',
|
||||
'Title' => 'Heading 1',
|
||||
'RightTitle' => 'Right',
|
||||
'Level' => 3,
|
||||
'HideFromReports' => true,
|
||||
'ShowOnLoad' => false,
|
||||
),
|
||||
array(
|
||||
'ClassName' => 'EditableFileField',
|
||||
'Title' => 'File 1',
|
||||
'RightTitle' => 'File field',
|
||||
'FolderID' => $folder->ID,
|
||||
),
|
||||
array(
|
||||
'ClassName' => 'EditableDateField',
|
||||
'Title' => 'Date 1',
|
||||
'RightTitle' => 'Date field',
|
||||
'DefaultToToday' => true,
|
||||
),
|
||||
array(
|
||||
'ClassName' => 'EditableCheckbox',
|
||||
'Title' => 'Checkbox 1',
|
||||
'CheckedDefault' => true,
|
||||
'RightTitle' => 'Check this',
|
||||
),
|
||||
), $form->Fields());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user