Webylon 3.1 API Docs
  • Package
  • Class
  • Tree
  • Deprecated
  • Download
Version: current
  • 3.2
  • 3.1

Packages

  • auth
  • Booking
  • cart
    • shipping
    • steppedcheckout
  • Catalog
  • cms
    • assets
    • batchaction
    • batchactions
    • bulkloading
    • comments
    • content
    • core
    • export
    • newsletter
    • publishers
    • reports
    • security
    • tasks
  • Dashboard
  • DataObjectManager
  • event
  • faq
  • forms
    • actions
    • core
    • fields-basic
    • fields-dataless
    • fields-datetime
    • fields-files
    • fields-formatted
    • fields-formattedinput
    • fields-relational
    • fields-structural
    • transformations
    • validators
  • googlesitemaps
  • guestbook
  • installer
  • newsletter
  • None
  • photo
    • gallery
  • PHP
  • polls
  • recaptcha
  • sapphire
    • api
    • bulkloading
    • control
    • core
    • cron
    • dev
    • email
    • fields-formattedinput
    • filesystem
    • formatters
    • forms
    • i18n
    • integration
    • misc
    • model
    • parsers
    • search
    • security
    • tasks
    • testing
    • tools
    • validation
    • view
    • widgets
  • seo
    • open
      • graph
  • sfDateTimePlugin
  • spamprotection
  • stealth
    • captha
  • subsites
  • userform
    • pagetypes
  • userforms
  • webylon
  • widgets

Classes

  • UserDefinedForm_Controller
  1 <?php
  2 
  3 /**
  4  * User Defined Form Page type that lets users build a form in the CMS 
  5  * using the FieldEditor Field. 
  6  * 
  7  * @todo Allow UserDefinedForm instances on Page subclasses (eg via decorator)
  8  *
  9  * @package userforms
 10  */
 11 
 12 class UserDefinedForm extends Page {
 13     
 14     /**
 15      * @var String Required Identifier
 16      */
 17     static $required_identifier = null;
 18 
 19     /**
 20      * @var Array Fields on the user defined form page. 
 21      */
 22     static $db = array(
 23         "SubmitButtonText" => "Varchar",
 24         "OnCompleteMessage" => "HTMLText",      
 25         'DisableSaveSubmissions' => 'Boolean'
 26     );
 27     
 28     /**
 29      * @var Array Default values of variables when this page is created
 30      */ 
 31     static $defaults = array(
 32         'Content' => '$UserDefinedForm',
 33         'DisableSaveSubmissions' => 0,
 34     );
 35 
 36     static $extensions = array(
 37         "Versioned('Stage', 'Live')"
 38     );
 39 
 40     /**
 41      * @var Array
 42      */
 43     static $has_many = array( 
 44         "Fields" => "EditableFormField",
 45         "Submissions" => "SubmittedForm",
 46         "EmailRecipients" => "UserDefinedForm_EmailRecipient"
 47     );
 48     
 49 
 50     /**
 51     * Change extended mode
 52     *
 53     */
 54     static function set_extended_mode($mode = false) { return true; }
 55     
 56     /**
 57      * @var Флаг использования js-валидации
 58      */
 59     static $use_js_validation = true;
 60     
 61     public function populateDefaults() {
 62         parent::populateDefaults();
 63         $this->OnCompleteMessage = _t('UserDefinedForm.OnCompleteMessage');        
 64     }
 65     
 66     /**
 67      * Setup the CMS Fields for the User Defined Form
 68      * 
 69      * @return FieldSet
 70      */
 71     public function getCMSFields() {
 72         $fields = parent::getCMSFields();
 73         Requirements::add_i18n_javascript('userforms/javascript/lang');
 74 
 75         // define tabs
 76         $fields->findOrMakeTab('Root.Content.Form', _t('UserDefinedForm.FORM', 'Form'));
 77         $fields->findOrMakeTab('Root.Content.Options', _t('UserDefinedForm.OPTIONS', 'Options'));
 78         $fields->findOrMakeTab('Root.Content.EmailRecipients', _t('UserDefinedForm.EMAILRECIPIENTS', 'Email Recipients'));
 79         $fields->findOrMakeTab('Root.Content.OnComplete', _t('UserDefinedForm.ONCOMPLETE', 'On Complete'));
 80         $fields->findOrMakeTab('Root.Content.Submissions', _t('UserDefinedForm.SUBMISSIONS', 'Submissions'));
 81 
 82         // field editor
 83         $fields->addFieldToTab("Root.Content.Form", new FieldEditor("Fields", 'Fields', "", $this ));
 84         
 85         // view the submissions
 86         $fields->addFieldToTab("Root.Content.Submissions", new CheckboxField('DisableSaveSubmissions',_t('UserDefinedForm.SAVESUBMISSIONS',"Disable Saving Submissions to Server")));
 87         $fields->addFieldToTab("Root.Content.Submissions", new SubmittedFormReportField( "Reports", _t('UserDefinedForm.RECEIVED', 'Received Submissions'), "", $this ) );
 88 
 89         // who do we email on submission
 90         $emailRecipients = new ComplexTableField(
 91             $this,
 92             'EmailRecipients',
 93             'UserDefinedForm_EmailRecipient',
 94             array(
 95                 'EmailAddress' => _t('UserDefinedForm.EMAILADDRESS', 'Email'),
 96                 'EmailSubject' => _t('UserDefinedForm.EMAILSUBJECT', 'Subject'),
 97                 'EmailFrom' => _t('UserDefinedForm.EMAILFROM', 'From')
 98             ),
 99             'getCMSFields_forPopup',
100             "\"FormID\" = '$this->ID'"
101         );
102         $emailRecipients->setAddTitle(_t('UserDefinedForm.AEMAILRECIPIENT', 'A Email Recipient'));
103         
104         $fields->addFieldToTab("Root.Content.EmailRecipients", $emailRecipients);
105     
106         // text to show on complete
107         $onCompleteFieldSet = new FieldSet(
108             new HtmlEditorField( "OnCompleteMessage", _t('UserDefinedForm.ONCOMPLETELABEL', 'Show on completion'),3,"",_t('UserDefinedForm.ONCOMPLETEMESSAGE', $this->OnCompleteMessage), $this )
109         );
110         
111         $fields->addFieldsToTab("Root.Content.OnComplete", $onCompleteFieldSet);
112         $fields->addFieldsToTab("Root.Content.Options", $this->getFormOptions());
113         
114         return $fields;
115     }
116     
117     
118     /**
119      * Publishing Versioning support.
120      *
121      * When publishing copy the editable form fields to the live database
122      * Not going to version emails and submissions as they are likely to 
123      * persist over multiple versions
124      *
125      * @return void
126      */
127     public function doPublish() {
128         // remove fields on the live table which could have been orphaned.
129         $live = Versioned::get_by_stage("EditableFormField", "Live", "\"EditableFormField\".\"ParentID\" = $this->ID");
130 
131         if($live) {
132             foreach($live as $field) {
133                 $field->doDeleteFromStage('Live');
134             }
135         }
136 
137         // publish the draft pages
138         if($this->Fields()) {
139             foreach($this->Fields() as $field) {
140                 $field->doPublish('Stage', 'Live');
141             }
142         }
143 
144         parent::doPublish();
145     }
146     
147     /**
148      * Unpublishing Versioning support
149      * 
150      * When unpublishing the page it has to remove all the fields from 
151      * the live database table
152      *
153      * @return void
154      */
155     public function doUnpublish() {
156         if($this->Fields()) {
157             foreach($this->Fields() as $field) {
158                 $field->doDeleteFromStage('Live');
159             }
160         }
161         
162         parent::doUnpublish();
163     }
164     
165     /**
166      * Roll back a form to a previous version.
167      *
168      * @param String|int Version to roll back to
169      */
170     public function doRollbackTo($version) {
171         parent::doRollbackTo($version);
172         
173         /*
174             Not implemented yet 
175     
176         // get the older version
177         $reverted = Versioned::get_version($this->ClassName, $this->ID, $version);
178         
179         if($reverted) {
180             
181             // using the lastedited date of the reverted object we can work out which
182             // form fields to revert back to
183             if($this->Fields()) {
184                 foreach($this->Fields() as $field) {
185                     // query to see when the version of the page was pumped
186                     $editedDate = DB::query("
187                         SELECT LastEdited
188                         FROM \"SiteTree_versions\"
189                         WHERE \"RecordID\" = '$this->ID' AND \"Version\" = $version
190                     ")->value(); 
191                     
192 
193                     // find a the latest version which has been edited
194                     $versionToGet = DB::query("
195                         SELECT *
196                         FROM \"EditableFormField_versions\" 
197                         WHERE \"RecordID\" = '$field->ID' AND \"LastEdited\" <= '$editedDate'
198                         ORDER BY Version DESC
199                         LIMIT 1
200                     ")->record();
201 
202                     if($versionToGet) {
203                         Debug::show('publishing field'. $field->Name);
204                         Debug::show($versionToGet);
205                         $field->publish($versionToGet, "Stage", true);
206                         $field->writeWithoutVersion();
207                     }
208                     else {
209                         Debug::show('deleting field'. $field->Name);
210                         $this->Fields()->remove($field);
211                         
212                         $field->delete();
213                         $field->destroy();
214                     }
215                 }
216             }
217             
218             // @todo Emails
219         }
220         */
221     }
222     
223     /**
224      * Revert the draft site to the current live site
225      *
226      * @return void
227      */
228     public function doRevertToLive() {
229         if($this->Fields()) {
230             foreach($this->Fields() as $field) {
231                 $field->publish("Live", "Stage", false);
232                 $field->writeWithoutVersion();
233             }
234         }
235         
236         parent::doRevertToLive();
237     }
238     
239     /**
240      * Duplicate this UserDefinedForm page, and its form fields.
241      * Submissions, on the other hand, won't be duplicated.
242      *
243      * @return Page
244      */
245     public function duplicate() {
246         $page = parent::duplicate();
247         
248         // the form fields
249         if($this->Fields()) {
250             foreach($this->Fields() as $field) {
251                 $newField = $field->duplicate();
252                 $newField->ParentID = $page->ID;
253                 $newField->write();
254             }
255         }
256         
257         // the emails
258         if($this->EmailRecipients()) {
259             foreach($this->EmailRecipients() as $email) {
260                 $newEmail = $email->duplicate();
261                 $newEmail->FormID = $page->ID;
262                 $newEmail->write();
263             }
264         }
265         
266         return $page;
267     }
268     
269     /**
270      * Custom options for the form. You can extend the built in options by 
271      * using {@link updateFormOptions()}
272      *
273      * @return FieldSet
274      */
275     public function getFormOptions() {
276         $submit = ($this->SubmitButtonText) ? $this->SubmitButtonText : _t('UserDefinedForm.SUBMITBUTTON', 'Submit');
277         
278         $options = new FieldSet(
279             new TextField("SubmitButtonText", _t('UserDefinedForm.TEXTONSUBMIT', 'Text on submit button:'), $submit)
280         );
281         
282         $this->extend('updateFormOptions', $options);
283         
284         return $options;
285     }
286     
287     /**
288      * Return if this form has been modified on the stage site and not published.
289      * this is used on the workflow module and for a couple highlighting things
290      *
291      * @todo make this a bit smarter - the issue with userforms is that it uses several
292      *      relationships to form fields which has a undefined amount of options so 
293      *      for now just say its always modified
294      */
295 
296     public function getIsModifiedOnStage() {
297         if ($this->RelationshipAggregate('Fields')->Max('LastEdited') > $this->LastEdited) return true;
298         if ($this->RelationshipAggregate('EmailRecipients')->Max('LastEdited') > $this->LastEdited) return true;
299         return parent::getIsModifiedOnStage();
300     }
301     
302     function getSubmitLetterEmail() {
303         return new UserDefinedForm_SubmittedFormEmail();
304     }
305 }
306 
307 /**
308  * Controller for the {@link UserDefinedForm} page type.
309  *
310  * @package userform
311  * @subpackage pagetypes
312  */
313 
314 class UserDefinedForm_Controller extends Page_Controller {
315     
316     // суффикс для ID-формы, чтоб отличать одинаковые формы на одной странице
317     protected $suffix;
318 
319     /**
320      * Load all the custom jquery needed to run the custom 
321      * validation 
322      */
323     public function init() {
324         parent::init();
325         
326         $this->formInit();
327     }
328     
329     /**
330      * Выносим подгрузку скриптов в функцию, чтоб ее можно было вызвать отдельно (напр. в виджете)
331      * 
332      */
333     function formInit() {
334         // block prototype validation
335         Validator::set_javascript_validation_handler('none');
336         
337         // load the jquery
338         Requirements::javascript(JQUERY_PATH);
339         Requirements::javascript('userforms/thirdparty/jquery-validate/jquery.validate.min.js');
340         Requirements::javascript('userforms/thirdparty/jquery-validate/localization/messages_'.i18n::get_lang_from_locale(i18n::get_locale()).'.js'); 
341     }
342     
343     /**
344      * Using $UserDefinedForm in the Content area of the page shows
345      * where the form should be rendered into. If it does not exist
346      * then default back to $Form
347      *
348      * @return Array
349      */
350     public function index() {
351         $form = $this->Form();
352         $customScripts = '';
353         if ($this->isAjax()) {
354             $this->suffix = 'ajax';
355             $form->setHtmlID($this->generateFormID());
356             $form->loadDataFrom(array('HtmlIDSuffix' => $this->suffix));
357             $customScripts = $this->generateConditionalJavascript(true);
358         }
359         if($this->Content && $form) {
360             $hasLocation = stristr($this->Content, '$UserDefinedForm');
361             if($hasLocation) {
362                 $content = str_ireplace('$UserDefinedForm', $form->forTemplate(), $this->Content);
363                 return array(
364                     'Content' => DBField::create('HTMLText', $content),
365                     'Form' => "",
366                     'customScripts' => $customScripts,
367                 );
368             }
369         }
370 
371         return array(
372             'Content' => DBField::create('HTMLText', $this->Content),
373             'Form' => $form,
374             'customScripts' => $customScripts,
375         );
376     }
377 
378     /**
379      * Get the form for the page. Form can be modified by calling {@link updateForm()}
380      * on a UserDefinedForm extension
381      *
382      * @return Form|false
383      */
384     function Form() {
385         $fields = $this->getFormFields();
386         if(!$fields) return false;
387                 
388         if (isset($_REQUEST['HtmlIDSuffix']) && trim($_REQUEST['HtmlIDSuffix'])) {
389             $this->suffix = trim($_REQUEST['HtmlIDSuffix']);
390         }
391         $actions = $this->getFormActions();
392         
393         // get the required fields including the validation
394         $required = $this->getRequiredFields();
395 
396         // generate the conditional logic 
397         $this->generateConditionalJavascript();
398 
399         $form = new Form($this, "Form", $fields, $actions, $required);
400         
401         $form->setHtmlID($this->generateFormID());
402         $form->addExtraClass('UserForm');
403         
404         // дополнительно формируем ошибки после указания правильного HtmlID
405         $form->setupFormErrors();
406         
407         $data = Session::get("FormInfo.{$form->FormName()}.data");
408         
409         if(is_array($data)) $form->loadDataFrom($data);
410         
411         $this->extend('updateForm', $form);
412 
413         return $form;
414     }
415 
416     function generateFormID() {
417 //      return 'Form_Form';
418         return 'UserForm'.$this->ID.($this->suffix ? "_{$this->suffix}" : "");
419     }
420     
421     /**
422      * Get the form fields for the form on this page. Can modify this FieldSet
423      * by using {@link updateFormFields()} on an {@link Extension} subclass which
424      * is applied to this controller
425      *
426      * @return FieldSet
427      */
428     function getFormFields() {
429         $fields = new FieldSet();
430 
431         if($this->Fields()) {
432             foreach($this->Fields() as $editableField) {
433                 // get the raw form field from the editable version
434                 $field = $editableField->getFormField();
435                 if(!$field) break;
436                 
437                 // set the error / formatting messages
438                 $field->setCustomValidationMessage($editableField->getErrorMessage());
439 
440                 // set the right title on this field
441                 if($right = $editableField->getSetting('RightTitle')) {
442                     $field->setRightTitle($right);
443                 }
444                 
445                 // if this field is required add some
446                 if($editableField->Required) {
447                     $field->addExtraClass('requiredField');
448                     
449                     if($identifier = UserDefinedForm::$required_identifier) {
450                         
451                         $title = $field->Title() ." <span class='required-identifier'>". $identifier . "</span>";
452                         $field->setTitle($title);
453                     }
454                 }
455                 // if this field has an extra class
456                 if($editableField->getSetting('ExtraClass')) {
457                     $extraClasses = explode(' ', $editableField->getSetting('ExtraClass'));
458                     foreach($extraClasses as $extraClass) {
459                         if (trim($extraClass)) {
460                             $field->addExtraClass(Convert::raw2att(trim($extraClass)));
461                         }
462                     }
463                 }
464                 
465                 //добавляем placeholder
466                 if($editableField->getSetting('Placeholder')) {
467                     $field->addExtraAttribute('placeholder', Convert::raw2att($editableField->getSetting('Placeholder')));
468                 }               
469                 
470                 // set the values passed by the url to the field
471                 $request = $this->getRequest();
472                 if($request && $var = $request->getVar($field->name)) {
473                     $field->value = Convert::raw2att($var);
474                 }
475                 
476                 $fields->push($field);
477             }
478         }
479         $fields->push(new HiddenField('HtmlIDSuffix'));
480         $this->extend('updateFormFields', $fields);
481 
482         return $fields;
483     }
484     
485     /**
486      * Generate the form actions for the UserDefinedForm. You 
487      * can manipulate these by using {@link updateFormActions()} on
488      * a decorator.
489      *
490      * @todo Make form actions editable via their own field editor.
491      *
492      * @return FieldSet
493      */
494     function getFormActions() {
495         $submitText = ($this->SubmitButtonText) ? $this->SubmitButtonText : _t('UserDefinedForm.SUBMITBUTTON', 'Submit');
496         
497         $actions = new FieldSet(
498             new FormAction("process", $submitText)
499         );
500 
501         $this->extend('updateFormActions', $actions);
502         
503         return $actions;
504     }
505     
506     /**
507      * Get the required form fields for this form. Includes building the jQuery
508      * validate structure
509      *
510      * @return RequiredFields
511      */
512     function getRequiredFields() {
513         $required = new RequiredFields();
514         
515         $rules = array();
516         $validation = array();
517         $messages = array();
518         
519         if($this->Fields()) {
520             foreach($this->Fields() as $field) {
521                 $messages[$field->Name] = $field->getErrorMessage()->HTML();
522     
523                 if ($field->CustomRules()->Count() == 0) {
524                     $rules[$field->Name] = $field->getValidation();
525                     if ($field->Required) {
526                         $required->addRequiredField($field->Name);
527                     }
528                 }
529             }
530         }
531         
532         if (UserDefinedForm::$use_js_validation) {
533             // Set the Form Name
534             $rules = $this->array2json($rules);
535             $messages = $this->array2json($messages);
536         
537             // set the custom script for this form
538             Requirements::customScript(<<<JS
539 (function($) {
540     $(document).ready(function() {
541         $("#{$this->generateFormID()}").validate({
542             ignore: [':hidden'],
543             errorClass: "hasError",
544             errorPlacement: function(error, element) {
545                 if(element.is(":radio")) {
546                     error.insertAfter(element.closest("ul"));
547                 } else {
548                     error.insertAfter(element);
549                 }
550             },
551             messages:
552                 $messages,
553             rules: 
554                 $rules
555         });
556     });
557 })(jQuery);
558 JS
559                 , 'Validation' . $this->generateFormID());
560         }
561         
562         $this->extend('updateRequiredFields', $required);
563         
564         return $required;
565     }
566     
567     /**
568      * Generate the javascript for the conditional field show / hiding logic.
569      * Allows complex rules to be created 
570      * @return void
571      */
572     function generateConditionalJavascript() {
573         $default = "";
574         $rules = "";
575         
576         if($this->Fields()) {
577             foreach($this->Fields() as $field) {
578                 $fieldId = $field->Name;
579                 
580                 if($field->ClassName == 'EditableFormHeading') { 
581                     $fieldId = $this->generateFormID().'_'.$field->Name;
582                 }
583                 
584                 // Is this Field Show by Default
585                 if(!$field->getShowOnLoad()) {
586                     $default .= "$(\"#" . $fieldId . "\").hide();\n";
587                 }
588 
589                 // Check for field dependencies / default
590                 if($field->Dependencies()) {
591                     foreach($field->Dependencies() as $dependency) {
592                         if(is_array($dependency) && isset($dependency['ConditionField']) && $dependency['ConditionField'] != "") {
593                             // get the field which is effected
594                             $formName = Convert::raw2sql($dependency['ConditionField']);
595                             $formFieldWatch = DataObject::get_one("EditableFormField", "\"Name\" = '$formName'");
596                             $fieldWatchId = $this->generateFormID().'_'.$formFieldWatch->Name;
597                             
598                             if(!$formFieldWatch) break;
599                             
600                             // watch out for multiselect options - radios and check boxes
601                             if(is_a($formFieldWatch, 'EditableDropdown')) {
602                                 $fieldToWatch = "$(\"select#{$fieldWatchId}\")";    
603                             }
604                             
605                             // watch out for checkboxs as the inputs don't have values but are 'checked
606                             else if(is_a($formFieldWatch, 'EditableCheckboxGroupField')) {
607                                 $fieldToWatch = "$(\"input#{$fieldWatchId}[".$dependency['Value']."]']\")";
608                             }
609                             else {
610                                 $fieldToWatch = "$(\"input#{$fieldWatchId}\")";
611                             }
612                             
613                             // show or hide?
614                             $view = (isset($dependency['Display']) && $dependency['Display'] == "Hide") ? "hide" : "show";
615                             $opposite = ($view == "show") ? "hide" : "show";
616                             
617                             // what action do we need to keep track of. Something nicer here maybe?
618                             // @todo encapulsation
619                             $action = "change";
620                             
621                             if($formFieldWatch->ClassName == "EditableTextField" || $formFieldWatch->ClassName == "EditableDateField") {
622                                 $action = "keyup";
623                             }
624                             
625                             // is this field a special option field
626                             $checkboxField = false;
627                             if(in_array($formFieldWatch->ClassName, array('EditableCheckboxGroupField', 'EditableCheckbox'))) {
628                                 $action = "click";
629                                 $checkboxField = true;
630                             }
631                             
632                             // and what should we evaluate
633                             switch($dependency['ConditionOption']) {
634                                 case 'IsNotBlank':
635                                     $expression = ($checkboxField) ? '$(this).attr("checked")' :'$(this).val() != ""';
636 
637                                     break;
638                                 case 'IsBlank':
639                                     $expression = ($checkboxField) ? '!($(this).attr("checked"))' : '$(this).val() == ""';
640                                     
641                                     break;
642                                 case 'HasValue':
643                                     $expression = ($checkboxField) ? '$(this).attr("checked")' : '$(this).val() == "'. $dependency['Value'] .'"';
644 
645                                     break;
646                                 case 'ValueLessThan':
647                                     $expression = '$(this).val() < parseFloat("'. $dependency['Value'] .'")';
648                                     
649                                     break;
650                                 case 'ValueLessThanEqual':
651                                     $expression = '$(this).val() <= parseFloat("'. $dependency['Value'] .'")';
652                                     
653                                     break;
654                                 case 'ValueGreaterThan':
655                                     $expression = '$(this).val() > parseFloat("'. $dependency['Value'] .'")';
656 
657                                     break;
658                                 case 'ValueGreaterThanEqual':
659                                     $expression = '$(this).val() >= parseFloat("'. $dependency['Value'] .'")';
660 
661                                     break;  
662                                 default:
663                                     $expression = ($checkboxField) ? '!($(this).attr("checked"))' : '$(this).val() != "'. $dependency['Value'] .'"';
664                                 
665                                     break;
666                             }
667                             // put it all together
668                             $rules .= $fieldToWatch.".$action(function() {
669                                 if(". $expression ." ) {
670                                     $(\"#". $fieldId ."\").".$view."();
671                                 }
672                                 else {
673                                     $(\"#". $fieldId ."\").".$opposite."();
674                                 }
675                             });";
676                         }
677                     }
678                 }
679             }
680         }
681         
682         if ($rules || $default) {
683         Requirements::customScript(<<<JS
684             (function($) {
685                 $(document).ready(function() {
686                     $rules
687                     
688                     $default
689                 })
690             })(jQuery);
691 JS
692 , 'Conditional' . $this->generateFormID());
693         }
694 
695     }
696     
697     /**
698      * Convert a PHP array to a JSON string. We cannot use {@link Convert::array2json}
699      * as it escapes our values with "" which appears to break the validate plugin
700      *
701      * @param Array array to convert
702      * @return JSON 
703      */
704     function array2json($array) {
705         foreach($array as $key => $value)
706             if(is_array( $value )) {
707                 $result[] = "$key:" . $this->array2json($value);
708             } else {
709                 $value = (is_bool($value)) ? $value : "\"$value\"";
710                 $result[] = "$key:$value";
711             }
712         return (isset($result)) ? "{\n".implode( ', ', $result ) ."\n}\n": '{}';
713     }
714     
715     /**
716      * Process the form that is submitted through the site
717      * 
718      * @param Array Data
719      * @param Form Form 
720      * @return Redirection
721      */
722     function process($data, $form) {
723         if (isset($data['HtmlIDSuffix']) && trim($data['HtmlIDSuffix'])) {
724             $this->suffix = trim($data['HtmlIDSuffix']);
725             $form->setHtmlID($this->generateFormID());
726         }
727         Session::set("FormInfo.{$form->FormName()}.data",$data);    
728         Session::clear("FormInfo.{$form->FormName()}.errors");
729         
730         foreach($this->Fields() as $field) {
731             $messages[$field->Name] = $field->getErrorMessage()->HTML();
732             if($field->Required && $field->CustomRules()->Count() == 0 && $field->ClassName != 'EditableSpamProtectionField') {
733                 // EditableSpamProtectionField - можно проверить всего 1 раз и это делает $this->validator
734                 if( !isset($data[$field->Name]) ||
735                     !$data[$field->Name] ||
736                     !$field->getFormField()->validate($this->validator)
737                 ){
738                     $form->addErrorMessage($field->Name,$field->getErrorMessage()->HTML(),'bad');
739                 }
740             }
741         }
742         if(Session::get("FormInfo.{$form->FormName()}.errors")){
743             Director::redirectBack();
744             return;
745         }
746         
747         $submittedForm = Object::create('SubmittedForm');
748         $submittedForm->SubmittedByID = ($id = Member::currentUserID()) ? $id : 0;
749         $submittedForm->ParentID = $this->ID;
750 
751         // if saving is not disabled save now to generate the ID
752         if(!$this->DisableSaveSubmissions) $submittedForm->write();
753         
754         $values = array();
755         $attachments = array();
756 
757         $submittedFields = new DataObjectSet();
758         
759         foreach($this->Fields() as $field) {
760             
761             if(!$field->showInReports()) continue;
762             
763             $submittedField = $field->getSubmittedFormField();
764             $submittedField->ParentID = $submittedForm->ID;
765             $submittedField->Name = $field->Name;
766             $submittedField->Title = $field->getField('Title');
767             
768             // save the value from the data
769             if($field->hasMethod('getValueFromData')) {
770                 $submittedField->Value = $field->getValueFromData($data);
771             }
772             else {
773                 if(isset($data[$field->Name])) $submittedField->Value = $data[$field->Name];
774             }
775 
776             if(!empty($data[$field->Name])){
777                 if(in_array("EditableFileField", $field->getClassAncestry())) {
778                     if(isset($_FILES[$field->Name])) {
779                         
780                         // create the file from post data
781                         $upload = new Upload();
782                         $file = new File();
783                         $file->ShowInSearch = 0;
784                         
785                         $upload->loadIntoFile($_FILES[$field->Name], $file);
786 
787                         // write file to form field
788                         $submittedField->UploadedFileID = $file->ID;
789                         
790                         // attach a file only if lower than 1MB
791                         if($file->getAbsoluteSize() < 1024*1024*1){
792                             $attachments[] = $file;
793                         }
794                     }                                   
795                 }
796             }
797             
798             if(!$this->DisableSaveSubmissions) $submittedField->write();
799     
800             $submittedFields->push($submittedField);
801         }
802         
803         $emailData = $this->getEmailData();
804         $emailData["Fields"] = $submittedFields;
805 
806         // email users on submit.
807         if($this->EmailRecipients()) {
808             
809             $email = $this->getSubmitLetterEmail();
810             $email->populateTemplate($emailData);
811             
812             if($attachments){
813                 foreach($attachments as $file){
814                     if($file->ID != 0) {
815                         $email->attachFile($file->Filename,$file->Filename, HTTP::getMimeType($file->Filename));
816                     }
817                 }
818             }
819 
820             foreach($this->EmailRecipients() as $recipient) {
821                 $email->populateTemplate($recipient);
822                 $email->populateTemplate($emailData);
823                 $email->setFrom($recipient->EmailFrom);
824                 $email->setBody($recipient->EmailBody);
825                 $email->setSubject($recipient->EmailSubject);
826                 $email->setTo($recipient->EmailAddress);
827                 
828                 // check to see if they are a dynamic sender. eg based on a email field a user selected
829                 if($recipient->SendEmailFromField()) {
830                     $submittedFormField = $submittedFields->find('Name', $recipient->SendEmailFromField()->Name);
831                     if($submittedFormField) {
832                         $email->setFrom($submittedFormField->Value);    
833                     }
834                 }
835                 // check to see if they are a dynamic reciever eg based on a dropdown field a user selected
836                 if($recipient->SendEmailToField()) {
837                     $submittedFormField = $submittedFields->find('Name', $recipient->SendEmailToField()->Name);
838                     
839                     if($submittedFormField) {
840                         $email->setTo($submittedFormField->Value);  
841                     }
842                 }
843                 
844                 if($recipient->SendPlain) {
845                     $body = strip_tags($recipient->EmailBody) . "\n ";
846                     if(isset($emailData['Fields']) && !$recipient->HideFormData) {
847                         foreach($emailData['Fields'] as $Field) {
848                             $body .= $Field->Title .' - '. $Field->Value .' \n';
849                         }
850                     }
851                     $email->setBody($body);
852                     $email->sendPlain();
853                 }
854                 else {
855                     $email->send(); 
856                 }
857             }
858         }
859         
860         Session::clear("FormInfo.{$form->FormName()}.errors");
861         Session::clear("FormInfo.{$form->FormName()}.data");
862 
863         if (Director::is_ajax()) return $this->OnCompleteMessage;
864         $referrer = (isset($data['Referrer'])) ? '?referrer=' . urlencode($data['Referrer']) : "";
865         return Director::redirect($this->Link() . 'finished' . $referrer);
866     }
867 
868     /**
869      * This action handles rendering the "finished" message,
870      * which is customisable by editing the ReceivedFormSubmission.ss
871      * template.
872      *
873      * @return ViewableData
874      */
875     function finished() {
876         $referrer = isset($_GET['referrer']) ? urldecode($_GET['referrer']) : null;
877         
878         return $this->customise(array(
879             'Content' => $this->customise(
880                 array(
881                     'Link' => $referrer
882                 ))->renderWith('ReceivedFormSubmission'),
883             'Form' => '',
884         ));
885     }
886     
887     function getEmailData() {
888         $emailData = array(
889             "Sender" => Member::currentUser(),          
890             'SenderIP' => $_SERVER{'REMOTE_ADDR'},
891         );
892         return $emailData;
893     }
894 }
895 
896 /**
897  * A Form can have multiply members / emails to email the submission 
898  * to and custom subjects
899  * 
900  * @package userforms
901  */
902 class UserDefinedForm_EmailRecipient extends DataObject {
903     
904     static $db = array(
905         'EmailAddress' => 'Varchar(200)',
906         'EmailSubject' => 'Varchar(200)',
907         'EmailFrom' => 'Varchar(200)',
908         'EmailBody' => 'Text',
909         'SendPlain' => 'Boolean',
910         'HideFormData' => 'Boolean'
911     );
912     
913     static $has_one = array(
914         'Form' => 'UserDefinedForm',
915         'SendEmailFromField' => 'EditableFormField',
916         'SendEmailToField' => 'EditableFormField'
917     );
918     
919     /**
920      * Return the fields to edit this email. 
921      * @return FieldSet
922      */
923     public function getCMSFields_forPopup() {
924         
925         $fields = new FieldSet(
926             new TextField('EmailSubject', _t('UserDefinedForm.EMAILSUBJECT', 'Email Subject')),
927             new TextField('EmailFrom', _t('UserDefinedForm.FROMADDRESS','Send Email From')),
928             new TextField('EmailAddress', _t('UserDefinedForm.SENDEMAILTO','Send Email To')),
929             new CheckboxField('HideFormData', _t('UserDefinedForm.HIDEFORMDATA', 'Hide Form Data from Email')),
930             new CheckboxField('SendPlain', _t('UserDefinedForm.SENDPLAIN', 'Send Email as Plain Text (HTML will be stripped)')),
931             new TextareaField('EmailBody', _t('UserDefinedForm.EMAILBODY','Body'))
932         );
933         
934         if($this->Form()) {
935             $validEmailFields = DataObject::get("EditableEmailField", "\"ParentID\" = '" . (int)$this->FormID . "'");
936             $multiOptionFields = DataObject::get("EditableMultipleOptionField", "\"ParentID\" = '" . (int)$this->FormID . "'");
937             
938             // if they have email fields then we could send from it
939             if($validEmailFields) {
940                 $fields->insertAfter(new DropdownField('SendEmailFromFieldID', _t('UserDefinedForm.ORSELECTAFIELDTOUSEASFROM', '.. or Select a Form Field to use as the From Address'), $validEmailFields->toDropdownMap('ID', 'Title'), '', null,""), 'EmailFrom');
941             }
942             
943             // if they have multiple options
944             if($multiOptionFields || $validEmailFields) {
945 
946                 if($multiOptionFields && $validEmailFields) {
947                     $multiOptionFields->merge($validEmailFields);
948                     
949                 }
950                 elseif(!$multiOptionFields) {
951                     $multiOptionFields = $validEmailFields; 
952                 }
953                 
954                 $multiOptionFields = $multiOptionFields->toDropdownMap('ID', 'Title');
955                 $fields->insertAfter(new DropdownField('SendEmailToFieldID', _t('UserDefinedForm.ORSELECTAFIELDTOUSEASTO', '.. or Select a Field to use as the To Address'), $multiOptionFields, '', null, ""), 'EmailAddress');
956             }
957         }
958 
959         return $fields;
960     }
961     
962     function canEdit() {
963         return $this->Form()->canEdit();
964     }
965     
966     function canDelete() {
967         return $this->Form()->canEdit();
968     }
969 }
970 
971 /**
972  * Email that gets sent to the people listed in the Email Recipients 
973  * when a submission is made
974  *
975  * @package userforms
976  */
977 
978 class UserDefinedForm_SubmittedFormEmail extends Email {
979     protected $ss_template = "SubmittedFormEmail";
980     protected $data;
981 
982     function __construct() {
983         parent::__construct();
984     }
985 }
986 
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -
Webylon 3.1 API Docs API documentation generated by ApiGen 2.8.0