"Varchar", "OnCompleteMessage" => "HTMLText", "ShowClearButton" => "Boolean", 'DisableSaveSubmissions' => 'Boolean' ); /** * @var array Default values of variables when this page is created */ public static $defaults = array( 'Content' => '$UserDefinedForm', 'DisableSaveSubmissions' => 0, 'OnCompleteMessage' => '
Thanks, we\'ve received your submission.
' ); public static $extensions = array( "Versioned('Stage', 'Live')" ); /** * @var Array */ public static $has_many = array( "Fields" => "EditableFormField", "Submissions" => "SubmittedForm", "EmailRecipients" => "UserDefinedForm_EmailRecipient" ); /** * Setup the CMS Fields for the User Defined Form * * @return FieldSet */ public function getCMSFields() { $fields = parent::getCMSFields(); // define tabs $fields->findOrMakeTab('Root.FormContent', _t('UserDefinedForm.FORM', 'Form')); $fields->findOrMakeTab('Root.FormOptions', _t('UserDefinedForm.FORMOPTIONS', 'Form Options')); $fields->findOrMakeTab('Root.Submissions', _t('UserDefinedForm.FORMSUBMISSIONS', 'Form Submissions')); // field editor $fields->addFieldToTab("Root.FormContent", new FieldEditor("Fields", 'Fields', "", $this )); // 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', $this->OnCompleteMessage)) ); $onCompleteFieldSet->addExtraClass('field'); $editor->setRows(3); $label->addExtraClass('left'); UserDefinedForm_EmailRecipient::$summary_fields=array( 'EmailAddress' => _t('UserDefinedForm.EMAILADDRESS', 'Email'), 'EmailSubject' => _t('UserDefinedForm.EMAILSUBJECT', 'Subject'), 'EmailFrom' => _t('UserDefinedForm.EMAILFROM', 'From') ); // who do we email on submission $emailRecipients = new GridField("EmailRecipients", "EmailRecipients", $this->EmailRecipients(), GridFieldConfig_RecordEditor::create(10)); $emailRecipients->getConfig()->getComponentByType('GridFieldAddNewButton')->setButtonName('Add Email Recipient'); $fields->addFieldsToTab("Root.FormOptions", $onCompleteFieldSet); $fields->addFieldToTab("Root.FormOptions", $emailRecipients); $fields->addFieldsToTab("Root.FormOptions", $this->getFormOptions()); // view the submissions $fields->addFieldToTab("Root.Submissions", new SubmittedFormReportField( "Reports", _t('UserDefinedForm.RECEIVED', 'Received Submissions'), "", $this ) ); $fields->addFieldToTab("Root.Submissions", new CheckboxField('DisableSaveSubmissions',_t('UserDefinedForm.SAVESUBMISSIONS',"Disable Saving Submissions to Server"))); return $fields; } /** * Publishing Versioning support. * * When publishing copy the editable form fields to the live database * Not going to version emails and submissions as they are likely to * persist over multiple versions * * @return void */ public function doPublish() { // remove fields on the live table which could have been orphaned. $live = Versioned::get_by_stage("EditableFormField", "Live", "\"EditableFormField\".\"ParentID\" = $this->ID"); if($live) { foreach($live as $field) { $field->doDeleteFromStage('Live'); } } // publish the draft pages if($this->Fields()) { foreach($this->Fields() as $field) { $field->doPublish('Stage', 'Live'); } } parent::doPublish(); } /** * Unpublishing Versioning support * * When unpublishing the page it has to remove all the fields from * the live database table * * @return void */ public function doUnpublish() { if($this->Fields()) { foreach($this->Fields() as $field) { $field->doDeleteFromStage('Live'); } } parent::doUnpublish(); } /** * Roll back a form to a previous version. * * @param String|int Version to roll back to */ public function doRollbackTo($version) { parent::doRollbackTo($version); /* Not implemented yet // get the older version $reverted = Versioned::get_version($this->ClassName, $this->ID, $version); if($reverted) { // using the lastedited date of the reverted object we can work out which // form fields to revert back to if($this->Fields()) { foreach($this->Fields() as $field) { // query to see when the version of the page was pumped $editedDate = DB::query(" SELECT LastEdited FROM \"SiteTree_versions\" WHERE \"RecordID\" = '$this->ID' AND \"Version\" = $version ")->value(); // find a the latest version which has been edited $versionToGet = DB::query(" SELECT * FROM \"EditableFormField_versions\" WHERE \"RecordID\" = '$field->ID' AND \"LastEdited\" <= '$editedDate' ORDER BY Version DESC LIMIT 1 ")->record(); if($versionToGet) { Debug::show('publishing field'. $field->Name); Debug::show($versionToGet); $field->publish($versionToGet, "Stage", true); $field->writeWithoutVersion(); } else { Debug::show('deleting field'. $field->Name); $this->Fields()->remove($field); $field->delete(); $field->destroy(); } } } // @todo Emails } */ } /** * Revert the draft site to the current live site * * @return void */ public function doRevertToLive() { if($this->Fields()) { foreach($this->Fields() as $field) { $field->publish("Live", "Stage", false); $field->writeWithoutVersion(); } } parent::doRevertToLive(); } /** * Duplicate this UserDefinedForm page, and its form fields. * Submissions, on the other hand, won't be duplicated. * * @return Page */ public function duplicate($doWrite = true) { $page = parent::duplicate($doWrite); // the form fields if($this->Fields()) { foreach($this->Fields() as $field) { $newField = $field->duplicate(); $newField->ParentID = $page->ID; $newField->write(); } } // the emails if($this->EmailRecipients()) { foreach($this->EmailRecipients() as $email) { $newEmail = $email->duplicate(); $newEmail->FormID = $page->ID; $newEmail->write(); } } return $page; } /** * Custom options for the form. You can extend the built in options by * using {@link updateFormOptions()} * * @return FieldSet */ public function getFormOptions() { $submit = ($this->SubmitButtonText) ? $this->SubmitButtonText : _t('UserDefinedForm.SUBMITBUTTON', 'Submit'); $options = new FieldList( new TextField("SubmitButtonText", _t('UserDefinedForm.TEXTONSUBMIT', 'Text on submit button:'), $submit), new CheckboxField("ShowClearButton", _t('UserDefinedForm.SHOWCLEARFORM', 'Show Clear Form Button'), $this->ShowClearButton) ); $this->extend('updateFormOptions', $options); return $options; } /** * Return if this form has been modified on the stage site and not published. * this is used on the workflow module and for a couple highlighting things * * @todo make this a bit smarter - the issue with userforms is that it uses several * relationships to form fields which has a undefined amount of options so * for now just say its always modified */ public function getIsModifiedOnStage() { return true; } } /** * Controller for the {@link UserDefinedForm} page type. * * @package userform * @subpackage pagetypes */ class UserDefinedForm_Controller extends Page_Controller { /** * Load all the custom jquery needed to run the custom * validation */ public function init() { parent::init(); // load the jquery Requirements::javascript(FRAMEWORK_DIR .'/thirdparty/jquery/jquery.js'); Requirements::javascript('userforms/thirdparty/jquery-validate/jquery.validate.min.js'); Requirements::javascript('userforms/javascript/UserForm_frontend.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 = str_ireplace('$UserDefinedForm', $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() ); } /** * Keep the session alive for the user. */ function ping() { return 1; } /** * Get the form for the page. Form can be modified by calling {@link updateForm()} * on a UserDefinedForm extension * * @return Form|false */ public function Form() { $fields = $this->getFormFields(); if(!$fields || !$fields->exists()) return false; $actions = $this->getFormActions(); // get the required fields including the validation $required = $this->getRequiredFields(); // generate the conditional logic $this->generateConditionalJavascript(); $form = new Form($this, "Form", $fields, $actions, $required); $data = Session::get("FormInfo.{$form->FormName()}.data"); if(is_array($data)) $form->loadDataFrom($data); $this->extend('updateForm', $form); return $form; } /** * 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 * * @return FieldSet */ public function getFormFields() { $fields = new FieldList(); if($this->Fields()) { foreach($this->Fields() as $editableField) { // get the raw form field from the editable version $field = $editableField->getFormField(); if(!$field) break; // set the error / formatting messages $field->setCustomValidationMessage($editableField->getErrorMessage()); // set the right title on this field if($right = $editableField->getSetting('RightTitle')) { $field->setRightTitle($right); } // if this field is required add some if($editableField->Required) { $field->addExtraClass('requiredField'); if($identifier = UserDefinedForm::$required_identifier) { $title = $field->Title() ." ". $identifier . ""; $field->setTitle($title); } } // if this field has an extra class if($editableField->getSetting('ExtraClass')) { $field->addExtraClass(Convert::raw2att( $editableField->getSetting('ExtraClass') )); } // set the values passed by the url to the field $request = $this->getRequest(); if($var = $request->getVar($field->name)) { $field->value = Convert::raw2att($var); } $fields->push($field); } } $this->extend('updateFormFields', $fields); 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 FieldSet */ public function getFormActions() { $submitText = ($this->SubmitButtonText) ? $this->SubmitButtonText : _t('UserDefinedForm.SUBMITBUTTON', 'Submit'); $actions = new FieldList( new FormAction("process", $submitText) ); if($this->ShowClearButton) { $actions->push(new ResetFormAction("clearForm")); } $this->extend('updateFormActions', $actions); return $actions; } /** * Get the required form fields for this form. Includes building the jQuery * validate structure * * @return RequiredFields */ public function getRequiredFields() { $required = new RequiredFields(); $rules = array(); $validation = array(); $messages = array(); if($this->Fields()) { foreach($this->Fields() as $field) { $messages[$field->Name] = $field->getErrorMessage()->HTML(); if($field->Required && $field->CustomRules()->Count() == 0) { $rules[$field->Name] = array_merge(array('required' => true), $field->getValidation()); $required->addRequiredField($field->Name); } } } // Set the Form Name $rules = $this->array2json($rules); $messages = $this->array2json($messages); // set the custom script for this form Requirements::customScript(<<'._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." ) . "
"), new TextField('EmailFrom', _t('UserDefinedForm.FROMADDRESS','Send email from')), new TextField('EmailReplyTo', _t('UserDefinedForm.REPLYADDRESS', 'Email for reply to')), new TextField('EmailAddress', _t('UserDefinedForm.SENDEMAILTO','Send email to')), new CheckboxField('HideFormData', _t('UserDefinedForm.HIDEFORMDATA', 'Hide form data from email?')), new CheckboxField('SendPlain', _t('UserDefinedForm.SENDPLAIN', 'Send email as plain text? (HTML will be stripped)')), new TextareaField('EmailBody', _t('UserDefinedForm.EMAILBODY','Body')) ); if($this->Form()) { $dropdowns = array(); $validEmailFields = DataObject::get("EditableEmailField", "\"ParentID\" = '" . (int)$this->FormID . "'"); $multiOptionFields = DataObject::get("EditableMultipleOptionField", "\"ParentID\" = '" . (int)$this->FormID . "'"); // if they have email fields then we could send from it if($validEmailFields) { $fields->insertAfter($dropdowns[] = new DropdownField( 'SendEmailFromFieldID', _t('UserDefinedForm.ORSELECTAFIELDTOUSEASFROM', '.. or select a field to use as reply to address'), $validEmailFields->map('ID', 'Title') ), 'EmailReplyTo'); } // if they have multiple options if($multiOptionFields || $validEmailFields) { if($multiOptionFields && $validEmailFields) { $multiOptionFields = $multiOptionFields->toArray(); $multiOptionFields = array_merge( $multiOptionFields, $validEmailFields->toArray() ); $multiOptionFields = ArrayList::create($multiOptionFields); } else if(!$multiOptionFields) { $multiOptionFields = $validEmailFields; } $multiOptionFields = $multiOptionFields->map('ID', 'Title'); $fields->insertAfter($dropdowns[] = new DropdownField( 'SendEmailToFieldID', _t('UserDefinedForm.ORSELECTAFIELDTOUSEASTO', '.. or select a field to use as the to address'), $multiOptionFields ), 'EmailAddress'); } if($dropdowns) { foreach($dropdowns as $dropdown) { $dropdown->setHasEmptyDefault(true); $dropdown->setEmptyString(" "); } } } $this->extend('updateCMSFields', $fields); return $fields; } public function canView($member = null) { return $this->Form()->canView(); } public function canEdit($member = null) { return $this->Form()->canEdit(); } public function canDelete($member = null) { return $this->Form()->canDelete(); } } /** * Email that gets sent to the people listed in the Email Recipients * when a submission is made * * @package userforms */ class UserDefinedForm_SubmittedFormEmail extends Email { protected $ss_template = "SubmittedFormEmail"; protected $data; public function __construct($submittedFields = null) { parent::__construct($submittedFields = null); } }