Commit 5a6116a6 authored by Carlos Barberis's avatar Carlos Barberis

initial commit

parents
<?php
class EditableFormFieldExtension extends DataExtension {
private static $db = array(
'Description' => 'HTMLText'
);
public function updateCMSFields(FieldList $fields) {
$fields->AddFieldToTab('Root.Main',
HTMLEditorField::create('Description', 'Field Description')
);
}
public function beforeUpdateFormField($field) {
if($this->owner->Description) {
$field->setAttribute('data-description', $this->owner->Description);
}
}
}
<?php
/**
* A component which lets the user select from a list of classes to create a new record form.
*
* By default the list of classes that are createable is the grid field's model class, and any
* subclasses. This can be customised using {@link setClasses()}.
*/
class GridFieldAddNewGroupedFields implements GridField_HTMLProvider, GridField_URLHandler {
private static $allowed_actions = array(
'handleAdd'
);
// Should we add an empty string to the add class dropdown?
private static $showEmptyString = true;
private $fragment;
private $title;
private $classes;
private $defaultClass;
private $groupedFieldsJson;
/**
* @var string
*/
protected $itemRequestClass = 'GridFieldAddNewMultiClassHandler';
/**
* @param string $fragment the fragment to render the button in
*/
public function __construct($fragment = 'before') {
$this->setFragment($fragment);
$this->setTitle(_t('GridFieldExtensions.ADD', 'Add'));
if(file_exists(BASE_PATH . '/mysite/groupedFields.json')) {
$this->groupedFieldsJson = file_get_contents(BASE_PATH . '/mysite/groupedFields.json');
}
}
/**
* Gets the fragment name this button is rendered into.
*
* @return string
*/
public function getFragment() {
return $this->fragment;
}
/**
* Sets the fragment name this button is rendered into.
*
* @param string $fragment
* @return GridFieldAddNewMultiClass $this
*/
public function setFragment($fragment) {
$this->fragment = $fragment;
return $this;
}
/**
* Gets the button title text.
*
* @return string
*/
public function getTitle() {
return $this->title;
}
/**
* Sets the button title text.
*
* @param string $title
* @return GridFieldAddNewMultiClass $this
*/
public function setTitle($title) {
$this->title = $title;
return $this;
}
/**
* Gets the classes that can be created using this button, defaulting to the model class and
* its subclasses.
*
* @param GridField $grid
* @return array a map of class name to title
*/
public function getClasses(GridField $grid) {
return $this->getGroups();
}
/**
* Sets the classes that can be created using this button.
*
* @param array $classes a set of class names, optionally mapped to titles
* @return GridFieldAddNewMultiClass $this
*/
public function setClasses(array $classes, $default = null) {
$this->classes = $classes;
if($default) $this->defaultClass = $default;
return $this;
}
/**
* Sets the default class that is selected automatically.
*
* @param string $default the class name to use as default
* @return GridFieldAddNewMultiClass $this
*/
public function setDefaultClass($default) {
$this->defaultClass = $default;
return $this;
}
/**
* Handles adding a new instance of a selected class.
*
* @param GridField $grid
* @param SS_HTTPRequest $request
* @return GridFieldAddNewMultiClassHandler
*/
public function handleAdd($grid, $request) {
$group = $request->param('ClassName');
$groupedFields = $this->findGroupedFieldsByID($group);
if(empty($groupedFields)) {
throw new SS_HTTPResponse_Exception(400);
}
// var_dump($groupedFields);
$classes = array_values(ClassInfo::subclassesFor('EditableFormField'));
// Add item to gridfield
$list = $grid->getList();
foreach($groupedFields as $field){
$item = $field['type']::create();
$item->Title = $field['title'];
$item->write();
$list->add($item);
}
// Should trigger a simple reload
return Controller::curr()->redirectBack();
}
/**
* Find the group by requested group ID in groupedFieldsJson
* @param (string) $groupID
* @return array
*
*/
public function findGroupedFieldsByID($groupID) {
$questionsArray = array();
if(array_key_exists($groupID, $this->getGroups())) {
$json = json_decode($this->groupedFieldsJson, true);
if(is_array($json)) {
foreach($json['groups'] as $key => $group) {
if($group['id'] == $groupID) {
$questionsArray = $group['questions'];
}
}
$questionFields = array();
foreach($questionsArray as $k => $question) {
$questionFields[] = $question['type'];
}
// return $questionFields;
}
}
return $questionsArray;
}
/**
* Get groups for dropdown list
*
*/
public function getGroups() {
$json = json_decode($this->groupedFieldsJson, true);
$groups = array();
if(is_array($json)) {
foreach($json['groups'] as $key => $group){
$groups[$group['id']] = $group['title'];
}
}
return $groups;
}
/**
* {@inheritDoc}
*/
public function getHTMLFragments($grid) {
$classes = $this->getClasses($grid);
if(!count($classes)) {
return array();
}
GridFieldExtensions::include_requirements();
$field = new DropdownField(sprintf('%s[ClassName]', __CLASS__), '', $classes, $this->defaultClass);
if (Config::inst()->get('GridFieldAddNewMultiClass', 'showEmptyString')) {
$field->setEmptyString(_t('GridFieldExtensions.SELECTTYPETOCREATE', '(Select type to create)'));
}
$field->addExtraClass('no-change-track');
$data = new ArrayData(array(
'Title' => $this->getTitle(),
'Link' => Controller::join_links($grid->Link(), 'add-multi-class', '{class}'),
'ClassField' => $field
));
return array(
$this->getFragment() => $data->renderWith('GridFieldAddNewMultiClass')
);
}
/**
* {@inheritDoc}
*/
public function getURLHandlers($grid) {
return array(
'add-multi-class/$ClassName!' => 'handleAdd'
);
}
public function setItemRequestClass($class) {
$this->itemRequestClass = $class;
return $this;
}
}
<?php
class UserFormGroupedFieldsExtension extends DataExtension {
public function updateCMSFields(FieldList $fields) {
$fieldEditor = $this->getFieldEditorGrid();
// $fields->insertAfter(new Tab('FormFields', _t('UserFormFieldEditorExtension.FORMFIELDS', 'Form Fields')), 'Main');
$fields->addFieldToTab('Root.FormFields', $fieldEditor);
return $fields;
}
/**
* 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();
// $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);
}
}
));
// if (Config::inst()->get('UserFormGroupedFieldsExtension', 'showAddGroup')) {
// $addFieldAction = new GridFieldAddNewMultiClass('buttons-before-right');
$addFieldAction = new GridFieldAddNewGroupedFields('buttons-before-right');
$config = GridFieldConfig::create()
->addComponent($addFieldAction);
// }
$config
->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');
// if (Config::inst()->get('UserFormFieldEditorExtension', 'showAddEdit')) {
$addFieldAction->setTitle('Add Field Block');
$fields = $addFieldAction->getClasses($fieldEditor);
$fields = array_diff_key($fields, array_flip(array('EditableFormStep', 'EditableFieldGroup', 'EditableFieldGroupEnd')));
asort($fields);
$addFieldAction->setClasses($fields);
// }
return $fieldEditor;
}
}
<?php
class SurveyUserForm extends UserForm {
/**
* 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(
FormAction::create("doProcess", $submitText)->setDisabled(true)
);
if($this->controller->ShowClearButton) {
$actions->push(new ResetFormAction("clearForm", $clearText));
}
$this->extend('updateFormActions', $actions);
return $actions;
}
}
<?php
class SurveyUserDefinedForm extends UserDefinedForm {
private static $db = array(
'FormPurpose' => 'HTMLText',
);
private static $defaults = array(
'Content' => '$SurveyUserDefinedForm',
);
private static $has_one = array(
'ContactInformation' => 'SurveyContactInformation',
);
/**
* @return SurveyPage
*/
public function Survey(){
return $this->getParent();
}
public function getSubmitURL() {
return $this->Survey()->submitURL();
}
public function getSubmitMethod() {
return $this->Survey()->submitMethod();
}
public function getGECode() {
if(Session::get('gecode')) {
return Session::get('gecode');
} return false;
}
public function getCMSFields() {
$fields = parent::getCMSFields();
// Remove unnecessary tabs, relating to standard UDF submission
$fields->removeFieldsFromTab('Root', array(
'Recipients',
'Submissions',
'Translations',
));
// Remove configuration options we aren't implementing
$fields->removeFieldsFromTab('Root.FormOptions', array(
'DisableSaveSubmissions',
'ShowClearButton',
'DisableAuthenicatedFinishAction',
));
$fields->addFieldsToTab('Root.FormOptions',
array(
LiteralField::create(
'EditContactInfo',
"You are able to edit or add contact information <a href=\"/admin/survey-contact-information\">here</a>"
),
DropdownField::create(
'ContactInformationID',
'Contact Information',
SurveyContactInformation::get()->map()
)->setEmptyString('Select one'),
HTMLEditorField::create('FormPurpose')->setRows(2)
),
'OnCompleteMessageLabel'
);
return $fields;
}
public function doProcess($data, $form) {
// Disable standard UDF submission for now
// @todo Implement call to SubmissionService
$link = Controller::join_links(Controller::curr()->Link(), '#finished');
return Controller::curr()->redirect($link);
}
}
class SurveyUserDefinedForm_Controller extends UserDefinedForm_Controller {
private static $allowed_actions = array(
'index',
'ping',
'Form',
'finished'
);
/**
* Using $SurveyUserDefinedForm 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, '$SurveyUserDefinedForm');
if($hasLocation)
{
$content = preg_replace('/(<p[^>]*>)?\\$SurveyUserDefinedForm(<\\/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()
);
}
public function init() {
parent::init();
$ip = $this->request->getIP();
// if there is no gecode in session, redirect to help page.
if($this->request->httpMethod() === 'GET') {
$gecode = Session::get('gecode-'.$ip);
SurveyActivity::add_activity($gecode, 'Start survey', $ip);
// inject necessary data into the template, this includes the survey with the json to generate the survey with Angularjs
//$thanksUrl = ($this->data()->Survey()->getThanksLink()) ? $this->data()->Survey()->getThanksLink() : '';
//$submitURL = $this->curr()->Link() . "submit";
//$jsonFile = ($this->Survey()->QuestionsFilePath) ? $this->Survey()->QuestionsFilePath : '/mysite/survey.json';
//$json = file_get_contents(BASE_PATH . '/mysite/survey-demo.json');
Requirements::customScript(<<<JS
var gecode = "$gecode";
JS
);
}
}
/**
* Get the form for the page. Form can be modified by calling {@link updateForm()}
* on a UserDefinedForm extension.
*
* @return Forms
*/
public function Form() {
$form = SurveyUserForm::create($this);
$this->generateConditionalJavascript();
if(isset($_GET['json'])) {
$fields = array();
foreach($form->getFormFields() as $f) {
$fields[] = $this->convertField($f);
// Debug::dump($f);
}
$data = (object)array(
'name' => $this->Title,
'purpose' => $this->FormPurpose,
'contact' => $this->ContactInformation()->dataForJson(),
'sections' => $fields,
);
header('Content-type: text/plain');
echo json_encode($data, JSON_PRETTY_PRINT); exit;
}
return $form;
}
public function convertField($f) {
$fields = array();
if($f instanceof UserFormsStepField && isset($f->children)) {
// Sections (pages in UDF terminology)
foreach($f->children->items as $i) {
$fields[] = $this->convertField($i);
}
return (object)array(
'Title' => $f->title,
'sectionQuestions' => array(array(
'questions' => $fields,
)),
);
} elseif($f instanceof UserFormsGroupField && isset($f->children)) {
// Groups
foreach($f->children->items as $i) {
$fields[] = $this->convertField($i);
}
return (object)array(
'label' => $f->title,
'type' => 'group',
'questions' => $fields,
);
} elseif($f instanceof FormField) {
$field = array(
'id' => $f->name,
'label' => trim(str_replace('<span class=\'required-identifier\'>(required)</span>', '', $f->title)),
'type' => $this->udfTypeToJsonType(get_class($f)),
);
// Default values
if(!empty($f->value)) {
if($f instanceof NumericField) {
$field['default'] = (int)$f->value;
} elseif($f instanceof CheckboxField) {
$field['default'] = (bool)$f->value;
} else {
$field['default'] = $f->value;
}
} elseif(!empty($f->defaultItems) && is_array($f->defaultItems)) {
$field['default'] = $f->defaultItems;
}
if(isset($f->attributes)) {
// Required field validation
if(isset($f->attributes['data-rule-required']) && $f->attributes['data-rule-required']) {
$field['mandatory'] = true;
if(!empty($f->attributes['data-msg-required'])) {
$field['errorText'] = $f->attributes['data-msg-required'];
}
}
if(!empty($f->attributes['data-description'])) {
$field['description'] = $f->attributes['data-description'];
}
// Numeric validation
if(!empty($f->attributes['data-rule-min'])) {
$field['min'] = (int)$f->attributes['data-rule-min'];
}
if(!empty($f->attributes['data-rule-max'])) {
$field['max'] = (int)$f->attributes['data-rule-max'];
}
// Field value length
if(!empty($f->attributes['data-rule-minlength'])) {
$field['minlength'] = (int)$f->attributes['data-rule-minlength'];
}
if(!empty($f->attributes['data-rule-maxlength'])) {
$field['maxlength'] = (int)$f->attributes['data-rule-maxlength'];
}
}
// Help text (right title)
if(!empty($f->rightTitle)) {
$field['helpText'] = $f->rightTitle;
}
// Fields with options
if($f instanceof DropdownField && isset($f->source)) {
$optionsName = get_class($f) === 'OptionsetField' ? 'buttons' : 'options';
$field[$optionsName] = array();
foreach($f->source as $value => $label) {
$field[$optionsName][] = (object)array(
'label' => $label,
'value' => $value,
);
}
}
// Headings
if($f instanceof HeaderField) {
$field['level'] = (int)$f->headingLevel;
}