2008-09-29 05:18:23 +02:00
< ? php
2010-07-07 11:17:37 +02:00
2008-09-29 05:18:23 +02:00
/**
2009-04-14 04:06:18 +02:00
* @ package userforms
2008-09-29 05:18:23 +02:00
*/
2009-04-14 04:06:18 +02:00
2008-09-29 05:18:23 +02:00
class UserDefinedForm extends Page {
2008-09-29 07:33:43 +02:00
2009-10-15 02:33:13 +02:00
/**
2012-09-11 11:30:40 +02:00
* @ var string
2009-10-15 02:33:13 +02:00
*/
2013-04-10 01:35:58 +02:00
private static $description = 'Adds a customizable form.' ;
2012-09-11 11:30:40 +02:00
/**
* @ var string Required Identifier
*/
2013-04-10 01:35:58 +02:00
private static $required_identifier = null ;
2015-05-29 05:49:36 +02:00
/**
2015-07-24 04:37:48 +02:00
* @ var string
*/
private static $email_template_directory = 'userforms/templates/email/' ;
/**
* Should this module automatically upgrade on dev / build ?
2015-05-29 05:49:36 +02:00
*
* @ config
2015-07-24 04:37:48 +02:00
* @ var bool
2015-05-29 05:49:36 +02:00
*/
2015-07-24 04:37:48 +02:00
private static $upgrade_on_build = true ;
2015-07-16 05:06:53 +02:00
/**
2015-07-24 04:37:48 +02:00
* Built in extensions required by this page
* @ config
* @ var array
2015-07-16 05:06:53 +02:00
*/
2015-07-24 04:37:48 +02:00
private static $extensions = array (
'UserFormFieldEditorExtension'
);
2009-10-15 02:33:13 +02:00
2009-04-14 04:06:18 +02:00
/**
2012-09-11 11:30:40 +02:00
* @ var array Fields on the user defined form page .
2009-04-14 04:06:18 +02:00
*/
2013-04-10 01:35:58 +02:00
private static $db = array (
2008-09-29 05:18:23 +02:00
" SubmitButtonText " => " Varchar " ,
2013-11-11 14:25:31 +01:00
" ClearButtonText " => " Varchar " ,
2009-02-11 03:00:20 +01:00
" OnCompleteMessage " => " HTMLText " ,
2009-07-22 06:02:21 +02:00
" ShowClearButton " => " Boolean " ,
2012-12-06 17:25:25 +01:00
'DisableSaveSubmissions' => 'Boolean' ,
'EnableLiveValidation' => 'Boolean' ,
2014-07-27 10:51:23 +02:00
'HideFieldLabels' => 'Boolean' ,
2015-07-13 00:05:14 +02:00
'DisplayErrorMessagesAtTop' => 'Boolean' ,
2014-07-27 10:51:23 +02:00
'DisableAuthenicatedFinishAction' => 'Boolean' ,
'DisableCsrfSecurityToken' => 'Boolean'
2008-09-29 05:18:23 +02:00
);
2009-04-14 04:06:18 +02:00
/**
2012-09-11 11:30:40 +02:00
* @ var array Default values of variables when this page is created
2009-04-14 04:06:18 +02:00
*/
2013-04-10 01:35:58 +02:00
private static $defaults = array (
2009-04-14 04:06:18 +02:00
'Content' => '$UserDefinedForm' ,
2009-07-22 06:02:21 +02:00
'DisableSaveSubmissions' => 0 ,
2009-04-14 04:06:18 +02:00
'OnCompleteMessage' => '<p>Thanks, we\'ve received your submission.</p>'
2008-09-29 05:18:23 +02:00
);
2009-04-14 04:06:18 +02:00
/**
2013-01-29 09:44:00 +01:00
* @ var array
2009-04-14 04:06:18 +02:00
*/
2013-04-10 01:35:58 +02:00
private static $has_many = array (
2009-04-14 04:06:18 +02:00
" Submissions " => " SubmittedForm " ,
" EmailRecipients " => " UserDefinedForm_EmailRecipient "
2008-09-29 05:18:23 +02:00
);
2013-06-04 11:17:40 +02:00
2015-07-13 00:05:14 +02:00
/**
* @ 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' ;
2013-06-04 11:17:40 +02:00
/**
* Temporary storage of field ids when the form is duplicated .
* Example layout : array ( 'EditableCheckbox3' => 'EditableCheckbox14' )
* @ var array
*/
protected $fieldsFromTo = array ();
2009-04-14 04:06:18 +02:00
/**
2013-01-29 09:44:00 +01:00
* @ return FieldList
2009-04-14 04:06:18 +02:00
*/
2015-04-20 03:58:15 +02:00
public function getCMSFields () {
2015-08-10 07:03:36 +02:00
Requirements :: css ( USERFORMS_DIR . '/css/UserForm_cms.css' );
2009-04-14 04:06:18 +02:00
2015-04-20 03:58:15 +02:00
$self = $this ;
2013-03-04 22:45:54 +01:00
2015-04-20 03:58:15 +02:00
$this -> beforeUpdateCMSFields ( function ( $fields ) use ( $self ) {
// define tabs
$fields -> findOrMakeTab ( 'Root.FormOptions' , _t ( 'UserDefinedForm.CONFIGURATION' , 'Configuration' ));
2015-07-13 05:36:20 +02:00
$fields -> findOrMakeTab ( 'Root.Recipients' , _t ( 'UserDefinedForm.RECIPIENTS' , 'Recipients' ));
2015-04-20 03:58:15 +02:00
$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' );
2015-07-13 05:36:20 +02:00
// Define config for email recipients
$emailRecipientsConfig = GridFieldConfig_RecordEditor :: create ( 10 );
$emailRecipientsConfig -> getComponentByType ( 'GridFieldAddNewButton' )
-> setButtonName (
_t ( 'UserDefinedForm.ADDEMAILRECIPIENT' , 'Add Email Recipient' )
);
2015-04-20 03:58:15 +02:00
// who do we email on submission
2015-07-13 05:36:20 +02:00
$emailRecipients = new GridField (
'EmailRecipients' ,
_t ( 'UserDefinedForm.EMAILRECIPIENTS' , 'Email Recipients' ),
$self -> EmailRecipients (),
$emailRecipientsConfig
2015-04-20 03:58:15 +02:00
);
2015-07-16 05:06:53 +02:00
$emailRecipients
-> getConfig ()
-> getComponentByType ( 'GridFieldDetailForm' )
2015-07-24 04:37:48 +02:00
-> setItemRequestClass ( 'UserFormRecipientItemRequest' );
2015-04-20 03:58:15 +02:00
$fields -> addFieldsToTab ( 'Root.FormOptions' , $onCompleteFieldSet );
2015-07-13 05:36:20 +02:00
$fields -> addFieldToTab ( 'Root.Recipients' , $emailRecipients );
2015-04-20 03:58:15 +02:00
$fields -> addFieldsToTab ( 'Root.FormOptions' , $self -> getFormOptions ());
// 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 )) ? $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
2013-11-13 04:46:13 +01:00
SELECT " Name " , " Title "
FROM " SubmittedFormField "
LEFT JOIN " SubmittedForm " ON " SubmittedForm " . " ID " = " SubmittedFormField " . " ParentID "
WHERE " SubmittedForm " . " ParentID " = '$parentID'
ORDER BY " Title " ASC
SQL ;
2015-04-20 03:58:15 +02:00
$columns = DB :: query ( $columnSQL ) -> map ();
2012-08-13 01:29:42 +02:00
2015-04-20 03:58:15 +02:00
$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 ());
2015-08-21 03:41:00 +02:00
$config -> addComponent ( new GridFieldButtonRow ( 'after' ));
$config -> addComponent ( $export = new GridFieldExportButton ( 'buttons-after-left' ));
$config -> addComponent ( $print = new GridFieldPrintButton ( 'buttons-after-left' ));
2015-04-20 03:58:15 +02:00
/**
* 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 );
// attach every column to the print view form
$columns [ 'Created' ] = 'Created' ;
$filter -> setColumns ( $columns );
// print configuration
$print -> setPrintHasHeader ( true );
$print -> setPrintColumns ( $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' )));
});
$fields = parent :: getCMSFields ();
2013-03-04 22:45:54 +01:00
2008-09-29 05:18:23 +02:00
return $fields ;
}
2012-12-11 05:09:02 +01:00
/**
* 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
*/
2013-09-04 08:32:24 +02:00
public function FilteredEmailRecipients ( $data = null , $form = null ) {
2015-07-13 05:36:20 +02:00
$recipients = new ArrayList ( $this -> EmailRecipients () -> toArray ());
// Filter by rules
$recipients = $recipients -> filterByCallback ( function ( $recipient ) use ( $data , $form ) {
return $recipient -> canSend ( $data , $form );
});
2012-12-11 05:09:02 +01:00
2013-09-04 08:32:24 +02:00
$this -> extend ( 'updateFilteredEmailRecipients' , $recipients , $data , $form );
2012-12-11 05:09:02 +01:00
return $recipients ;
}
2009-09-23 00:36:53 +02:00
/**
2010-09-03 07:06:13 +02:00
* Custom options for the form . You can extend the built in options by
* using { @ link updateFormOptions ()}
2009-09-23 00:36:53 +02:00
*
2012-10-18 09:01:56 +02:00
* @ return FieldList
2009-09-23 00:36:53 +02:00
*/
2012-07-17 06:09:31 +02:00
public function getFormOptions () {
2010-09-03 07:06:13 +02:00
$submit = ( $this -> SubmitButtonText ) ? $this -> SubmitButtonText : _t ( 'UserDefinedForm.SUBMITBUTTON' , 'Submit' );
2013-11-11 14:25:31 +01:00
$clear = ( $this -> ClearButtonText ) ? $this -> ClearButtonText : _t ( 'UserDefinedForm.CLEARBUTTON' , 'Clear' );
2010-09-03 07:06:13 +02:00
2012-04-22 21:17:42 +02:00
$options = new FieldList (
2010-09-03 07:06:13 +02:00
new TextField ( " SubmitButtonText " , _t ( 'UserDefinedForm.TEXTONSUBMIT' , 'Text on submit button:' ), $submit ),
2013-11-11 14:25:31 +01:00
new TextField ( " ClearButtonText " , _t ( 'UserDefinedForm.TEXTONCLEAR' , 'Text on clear button:' ), $clear ),
2012-12-06 17:25:25 +01:00
new CheckboxField ( " ShowClearButton " , _t ( 'UserDefinedForm.SHOWCLEARFORM' , 'Show Clear Form Button' ), $this -> ShowClearButton ),
new CheckboxField ( " EnableLiveValidation " , _t ( 'UserDefinedForm.ENABLELIVEVALIDATION' , 'Enable live validation' )),
2014-07-27 10:51:23 +02:00
new CheckboxField ( " HideFieldLabels " , _t ( 'UserDefinedForm.HIDEFIELDLABELS' , 'Hide field labels' )),
2015-07-13 00:05:14 +02:00
new CheckboxField ( " DisplayErrorMessagesAtTop " , _t ( 'UserDefinedForm.DISPLAYERRORMESSAGESATTOP' , 'Display error messages above the form?' )),
2014-07-27 10:51:23 +02:00
new CheckboxField ( 'DisableCsrfSecurityToken' , _t ( 'UserDefinedForm.DISABLECSRFSECURITYTOKEN' , 'Disable CSRF Token' )),
new CheckboxField ( 'DisableAuthenicatedFinishAction' , _t ( 'UserDefinedForm.DISABLEAUTHENICATEDFINISHACTION' , 'Disable Authenication on finish action' ))
2009-09-23 00:36:53 +02:00
);
2010-09-03 07:06:13 +02:00
$this -> extend ( 'updateFormOptions' , $options );
return $options ;
2009-09-23 00:36:53 +02:00
}
2015-07-13 00:05:14 +02:00
/**
* Get the HTML id of the error container displayed above the form .
*
* @ return string
*/
public function getErrorContainerID () {
return $this -> config () -> error_container_id ;
}
2015-07-24 04:37:48 +02:00
public function requireDefaultRecords () {
parent :: requireDefaultRecords ();
if ( ! $this -> config () -> upgrade_on_build ) {
return ;
}
// Perform migrations
Injector :: inst ()
-> create ( 'UserFormsUpgradeService' )
-> setQuiet ( true )
-> run ();
DB :: alteration_message ( 'Migrated userforms' , 'changed' );
}
2015-08-12 07:18:43 +02:00
/**
* Validate formfields
*/
public function getCMSValidator () {
return new UserFormValidator ();
}
2008-09-29 05:18:23 +02:00
}
/**
* Controller for the { @ link UserDefinedForm } page type .
2009-04-14 04:06:18 +02:00
*
2012-10-18 09:01:56 +02:00
* @ package userforms
2008-09-29 05:18:23 +02:00
*/
2009-04-14 04:06:18 +02:00
2008-09-29 05:18:23 +02:00
class UserDefinedForm_Controller extends Page_Controller {
2014-11-28 06:16:37 +01:00
private static $finished_anchor = '#uff' ;
2013-07-15 10:49:49 +02:00
private static $allowed_actions = array (
2013-07-09 05:20:19 +02:00
'index' ,
'ping' ,
'Form' ,
'finished'
);
2009-04-21 05:44:13 +02:00
public function init () {
2009-12-07 01:37:20 +01:00
parent :: init ();
2009-04-21 05:44:13 +02:00
// load the jquery
2014-04-16 01:48:10 +02:00
$lang = i18n :: get_lang_from_locale ( i18n :: get_locale ());
2015-08-06 04:19:05 +02:00
Requirements :: css ( USERFORMS_DIR . '/css/UserForm.css' );
2012-04-22 21:17:42 +02:00
Requirements :: javascript ( FRAMEWORK_DIR . '/thirdparty/jquery/jquery.js' );
2014-04-16 01:48:10 +02:00
Requirements :: javascript ( USERFORMS_DIR . '/thirdparty/jquery-validate/jquery.validate.min.js' );
Requirements :: add_i18n_javascript ( USERFORMS_DIR . '/javascript/lang' );
2015-08-06 06:06:56 +02:00
Requirements :: javascript ( USERFORMS_DIR . '/javascript/UserForm.js' );
2014-04-16 01:48:10 +02:00
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' );
}
2008-09-29 05:18:23 +02:00
}
2009-04-15 01:50:48 +02:00
/**
* Using $UserDefinedForm in the Content area of the page shows
* where the form should be rendered into . If it does not exist
2013-01-29 09:44:00 +01:00
* then default back to $Form .
2009-04-15 01:50:48 +02:00
*
2013-01-29 09:44:00 +01:00
* @ return array
2009-04-15 01:50:48 +02:00
*/
public function index () {
2011-04-08 19:36:01 +02:00
if ( $this -> Content && $form = $this -> Form ()) {
$hasLocation = stristr ( $this -> Content , '$UserDefinedForm' );
2009-04-15 01:50:48 +02:00
if ( $hasLocation ) {
2015-08-19 04:22:03 +02:00
$content = preg_replace ( '/(<p[^>]*>)?\\$UserDefinedForm(<\\/p>)?/i' , $form -> forTemplate (), $this -> Content );
2009-04-15 01:50:48 +02:00
return array (
2012-04-22 21:25:26 +02:00
'Content' => DBField :: create_field ( 'HTMLText' , $content ),
2009-04-15 01:50:48 +02:00
'Form' => " "
);
}
}
2010-09-03 07:06:13 +02:00
2009-04-15 01:50:48 +02:00
return array (
2012-04-22 21:25:26 +02:00
'Content' => DBField :: create_field ( 'HTMLText' , $this -> Content ),
2010-09-03 07:06:13 +02:00
'Form' => $this -> Form ()
2009-04-15 01:50:48 +02:00
);
}
2009-04-27 08:00:05 +02:00
2012-04-26 02:14:27 +02:00
/**
* Keep the session alive for the user .
2013-01-29 09:44:00 +01:00
*
* @ return int
2012-04-26 02:14:27 +02:00
*/
2013-01-29 09:44:00 +01:00
public function ping () {
2012-04-26 02:14:27 +02:00
return 1 ;
}
2009-04-14 04:06:18 +02:00
/**
2010-09-03 07:06:13 +02:00
* Get the form for the page . Form can be modified by calling { @ link updateForm ()}
2013-01-29 09:44:00 +01:00
* on a UserDefinedForm extension .
2009-04-14 04:06:18 +02:00
*
2015-07-24 04:37:48 +02:00
* @ return Forms
2009-04-14 04:06:18 +02:00
*/
2012-05-04 03:39:08 +02:00
public function Form () {
2015-07-24 04:37:48 +02:00
$form = UserForm :: create ( $this );
2010-09-03 07:06:13 +02:00
$this -> generateConditionalJavascript ();
2015-07-24 04:37:48 +02:00
return $form ;
2010-09-03 07:06:13 +02:00
}
2015-07-13 00:05:14 +02:00
2010-09-03 07:06:13 +02:00
/**
* Generate the javascript for the conditional field show / hiding logic .
2013-01-29 09:44:00 +01:00
*
2010-09-03 07:06:13 +02:00
* @ return void
*/
2012-05-04 03:39:08 +02:00
public function generateConditionalJavascript () {
2010-09-03 07:06:13 +02:00
$default = " " ;
$rules = " " ;
2013-02-27 04:05:30 +01:00
$watch = array ();
$watchLoad = array ();
2010-09-03 07:06:13 +02:00
if ( $this -> Fields ()) {
foreach ( $this -> Fields () as $field ) {
2015-08-13 01:31:37 +02:00
$holderSelector = $field -> getSelectorHolder ();
2015-07-24 04:37:48 +02:00
2009-04-24 00:52:08 +02:00
// Is this Field Show by Default
2015-07-24 04:37:48 +02:00
if ( ! $field -> ShowOnLoad ) {
2015-08-17 00:43:51 +02:00
$default .= " { $holderSelector } .hide().trigger('userform.field.hide'); \n " ;
2009-04-24 00:52:08 +02:00
}
// Check for field dependencies / default
2015-07-24 04:37:48 +02:00
foreach ( $field -> DisplayRules () as $rule ) {
// Get the field which is effected
$formFieldWatch = EditableFormField :: get () -> byId ( $rule -> ConditionFieldID );
2015-08-13 01:31:37 +02:00
$fieldToWatch = $formFieldWatch -> getSelectorField ( $rule );
$fieldToWatchOnLoad = $formFieldWatch -> getSelectorField ( $rule , true );
2015-07-24 04:37:48 +02:00
// 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 " ;
2015-08-13 01:31:37 +02:00
if ( $formFieldWatch instanceof EditableTextField ) {
2015-07-24 04:37:48 +02:00
$action = " keyup " ;
}
// 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 ;
}
// and what should we evaluate
switch ( $rule -> ConditionOption ) {
case 'IsNotBlank' :
2015-08-13 01:31:37 +02:00
$expression = ( $checkboxField || $radioField ) ? '$(this).is(":checked")' : '$(this).val() != ""' ;
2015-07-24 04:37:48 +02:00
break ;
case 'IsBlank' :
2015-08-13 01:31:37 +02:00
$expression = ( $checkboxField || $radioField ) ? '!($(this).is(":checked"))' : '$(this).val() == ""' ;
2009-04-24 00:52:08 +02:00
2015-07-24 04:37:48 +02:00
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 . '"' ;
2009-05-01 06:11:31 +02:00
}
2015-07-24 04:37:48 +02:00
break ;
case 'ValueLessThan' :
$expression = '$(this).val() < parseFloat("' . $rule -> FieldValue . '")' ;
2009-04-24 00:52:08 +02:00
2015-07-24 04:37:48 +02:00
break ;
case 'ValueLessThanEqual' :
$expression = '$(this).val() <= parseFloat("' . $rule -> FieldValue . '")' ;
2009-05-08 06:27:49 +02:00
2015-07-24 04:37:48 +02:00
break ;
case 'ValueGreaterThan' :
$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 . '"' ;
2009-05-08 06:27:49 +02:00
}
2014-12-02 07:49:03 +01:00
2015-07-24 04:37:48 +02:00
break ;
}
2014-12-02 07:49:03 +01:00
2015-07-24 04:37:48 +02:00
if ( ! isset ( $watch [ $fieldToWatch ])) {
$watch [ $fieldToWatch ] = array ();
}
2014-12-02 07:49:03 +01:00
2015-08-11 22:57:19 +02:00
$watch [ $fieldToWatch ][] = array (
2015-07-24 04:37:48 +02:00
'expression' => $expression ,
2015-08-13 01:31:37 +02:00
'holder_selector' => $holderSelector ,
2015-07-24 04:37:48 +02:00
'view' => $view ,
'opposite' => $opposite ,
'action' => $action
);
2013-02-27 04:05:30 +01:00
2015-07-24 04:37:48 +02:00
$watchLoad [ $fieldToWatchOnLoad ] = true ;
2009-04-24 00:52:08 +02:00
}
2009-04-21 05:44:13 +02:00
}
2008-09-29 05:18:23 +02:00
}
2009-04-21 05:44:13 +02:00
2013-02-27 04:05:30 +01:00
if ( $watch ) {
foreach ( $watch as $key => $values ) {
$logic = array ();
2014-12-02 07:49:03 +01:00
$actions = array ();
2013-02-27 04:05:30 +01:00
foreach ( $values as $rule ) {
2015-08-17 00:43:51 +02:00
// Assign action
2014-12-02 07:49:03 +01:00
$actions [ $rule [ 'action' ]] = $rule [ 'action' ];
2015-08-17 00:43:51 +02:00
// 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 }()
. trigger ( 'userform.field.{$view}' );
} else {
{ $holder }
. { $opposite }()
. trigger ( 'userform.field.{$opposite}' );
}
EOS ;
2013-02-27 04:05:30 +01:00
}
$logic = implode ( " \n " , $logic );
$rules .= $key . " .each(function() { \n
$ ( this ) . data ( 'userformConditions' , function () { \n
$logic\n
}); \n
}); \n " ;
2014-12-02 07:49:03 +01:00
foreach ( $actions as $action ) {
$rules .= $key . " . $action (function() {
2013-02-27 04:05:30 +01:00
$ ( this ) . data ( 'userformConditions' ) . call ( this ); \n
}); \n " ;
2014-12-02 07:49:03 +01:00
}
2013-02-27 04:05:30 +01:00
}
}
if ( $watchLoad ) {
foreach ( $watchLoad as $key => $value ) {
$rules .= $key . " .each(function() {
$ ( this ) . data ( 'userformConditions' ) . call ( this ); \n
}); \n " ;
}
}
2012-12-06 17:25:25 +01:00
// Only add customScript if $default or $rules is defined
2013-02-27 04:05:30 +01:00
if ( $default || $rules ) {
2012-12-06 17:25:25 +01:00
Requirements :: customScript ( <<< JS
( function ( $ ) {
$ ( document ) . ready ( function () {
$default
$rules
})
})( jQuery );
2009-04-21 05:44:13 +02:00
JS
2010-09-03 07:06:13 +02:00
, 'UserFormsConditional' );
2012-12-06 17:25:25 +01:00
}
2008-09-29 05:18:23 +02:00
}
2013-01-29 09:44:00 +01:00
2009-04-14 04:06:18 +02:00
/**
* Process the form that is submitted through the site
2015-08-17 07:23:45 +02:00
*
* { @ see UserForm :: validate ()} for validation step prior to processing
*
2013-01-29 09:44:00 +01:00
* @ param array $data
* @ param Form $form
*
2009-04-14 04:06:18 +02:00
* @ return Redirection
*/
2012-05-04 03:39:08 +02:00
public function process ( $data , $form ) {
2010-09-03 07:06:13 +02:00
$submittedForm = Object :: create ( 'SubmittedForm' );
2009-10-27 10:23:42 +01:00
$submittedForm -> SubmittedByID = ( $id = Member :: currentUserID ()) ? $id : 0 ;
2008-09-29 05:18:23 +02:00
$submittedForm -> ParentID = $this -> ID ;
2010-09-03 07:06:13 +02:00
// if saving is not disabled save now to generate the ID
2013-01-29 09:44:00 +01:00
if ( ! $this -> DisableSaveSubmissions ) {
$submittedForm -> write ();
}
2015-07-24 04:37:48 +02:00
2012-07-17 05:58:24 +02:00
$attachments = array ();
2012-04-22 21:25:26 +02:00
$submittedFields = new ArrayList ();
2015-07-24 04:37:48 +02:00
2009-04-14 04:06:18 +02:00
foreach ( $this -> Fields () as $field ) {
2013-01-29 09:44:00 +01:00
if ( ! $field -> showInReports ()) {
continue ;
}
2015-07-24 04:37:48 +02:00
2010-02-14 08:53:16 +01:00
$submittedField = $field -> getSubmittedFormField ();
2008-09-29 05:18:23 +02:00
$submittedField -> ParentID = $submittedForm -> ID ;
$submittedField -> Name = $field -> Name ;
2011-12-05 11:19:20 +01:00
$submittedField -> Title = $field -> getField ( 'Title' );
2015-07-24 04:37:48 +02:00
2010-09-03 07:06:13 +02:00
// save the value from the data
2009-04-27 08:17:02 +02:00
if ( $field -> hasMethod ( 'getValueFromData' )) {
$submittedField -> Value = $field -> getValueFromData ( $data );
2013-01-29 09:44:00 +01:00
} else {
if ( isset ( $data [ $field -> Name ])) {
$submittedField -> Value = $data [ $field -> Name ];
}
2009-04-14 04:06:18 +02:00
}
2009-04-20 01:22:22 +02:00
if ( ! empty ( $data [ $field -> Name ])){
2010-02-14 08:53:16 +01:00
if ( in_array ( " EditableFileField " , $field -> getClassAncestry ())) {
2009-04-28 04:03:13 +02:00
if ( isset ( $_FILES [ $field -> Name ])) {
2013-12-20 09:07:35 +01:00
$foldername = $field -> getFormField () -> getFolderName ();
2009-04-28 04:03:13 +02:00
// create the file from post data
$upload = new Upload ();
$file = new File ();
2011-09-16 01:47:09 +02:00
$file -> ShowInSearch = 0 ;
2012-05-11 01:39:24 +02:00
try {
2013-12-20 09:07:35 +01:00
$upload -> loadIntoFile ( $_FILES [ $field -> Name ], $file , $foldername );
2012-05-11 01:39:24 +02:00
} catch ( ValidationException $e ) {
$validationResult = $e -> getResult ();
$form -> addErrorMessage ( $field -> Name , $validationResult -> message (), 'bad' );
Controller :: curr () -> redirectBack ();
return ;
}
2009-04-20 01:22:22 +02:00
2009-04-28 04:03:13 +02:00
// write file to form field
$submittedField -> UploadedFileID = $file -> ID ;
2010-09-03 07:06:13 +02:00
// attach a file only if lower than 1MB
2009-04-28 04:03:13 +02:00
if ( $file -> getAbsoluteSize () < 1024 * 1024 * 1 ){
$attachments [] = $file ;
}
2015-04-20 03:58:15 +02:00
}
2008-09-29 05:18:23 +02:00
}
}
2015-07-24 04:37:48 +02:00
2014-07-06 07:03:13 +02:00
$submittedField -> extend ( 'onPopulationFromField' , $field );
2013-01-29 09:44:00 +01:00
if ( ! $this -> DisableSaveSubmissions ) {
$submittedField -> write ();
}
2015-07-24 04:37:48 +02:00
2009-07-22 06:02:21 +02:00
$submittedFields -> push ( $submittedField );
2010-09-03 07:06:13 +02:00
}
2015-07-24 04:37:48 +02:00
2009-02-11 03:27:55 +01:00
$emailData = array (
" Sender " => Member :: currentUser (),
2009-07-27 01:23:45 +02:00
" Fields " => $submittedFields
2009-02-11 03:27:55 +01:00
);
2015-07-24 04:37:48 +02:00
2014-02-03 00:10:44 +01:00
$this -> extend ( 'updateEmailData' , $emailData , $attachments );
2015-07-24 04:37:48 +02:00
2010-09-03 07:06:13 +02:00
// email users on submit.
2013-09-04 08:32:24 +02:00
if ( $recipients = $this -> FilteredEmailRecipients ( $data , $form )) {
2015-07-24 04:37:48 +02:00
$email = new UserFormRecipientEmail ( $submittedFields );
2015-07-16 05:06:53 +02:00
$mergeFields = $this -> getMergeFieldsMap ( $emailData [ 'Fields' ]);
2014-02-03 00:10:44 +01:00
if ( $attachments ) {
2013-01-29 09:44:00 +01:00
foreach ( $attachments as $file ) {
2009-04-20 01:22:22 +02:00
if ( $file -> ID != 0 ) {
2013-01-29 09:44:00 +01:00
$email -> attachFile (
$file -> Filename ,
$file -> Filename ,
HTTP :: get_mime_type ( $file -> Filename )
);
2009-04-20 01:22:22 +02:00
}
2008-09-29 05:18:23 +02:00
}
}
2009-04-20 01:22:22 +02:00
2013-09-04 08:32:24 +02:00
foreach ( $recipients as $recipient ) {
2015-07-16 05:06:53 +02:00
$parsedBody = SSViewer :: execute_string ( $recipient -> getEmailBodyContent (), $mergeFields );
if ( ! $recipient -> SendPlain && $recipient -> emailTemplateExists ()) {
$email -> setTemplate ( $recipient -> EmailTemplate );
}
2009-07-27 01:23:45 +02:00
$email -> populateTemplate ( $recipient );
2009-04-14 04:06:18 +02:00
$email -> populateTemplate ( $emailData );
$email -> setFrom ( $recipient -> EmailFrom );
2015-07-16 05:06:53 +02:00
$email -> setBody ( $parsedBody );
2009-04-14 04:06:18 +02:00
$email -> setTo ( $recipient -> EmailAddress );
2014-07-02 13:56:15 +02:00
$email -> setSubject ( $recipient -> EmailSubject );
2009-07-05 09:14:03 +02:00
2012-09-11 11:22:50 +02:00
if ( $recipient -> EmailReplyTo ) {
2013-01-29 10:40:28 +01:00
$email -> setReplyTo ( $recipient -> EmailReplyTo );
2012-09-11 11:22:50 +02:00
}
// check to see if they are a dynamic reply to. eg based on a email field a user selected
2009-07-05 09:14:03 +02:00
if ( $recipient -> SendEmailFromField ()) {
2009-10-27 10:23:42 +01:00
$submittedFormField = $submittedFields -> find ( 'Name' , $recipient -> SendEmailFromField () -> Name );
2012-09-11 11:22:50 +02:00
2012-07-17 05:58:24 +02:00
if ( $submittedFormField && is_string ( $submittedFormField -> Value )) {
2013-01-29 10:40:28 +01:00
$email -> setReplyTo ( $submittedFormField -> Value );
2009-07-05 09:14:03 +02:00
}
}
2009-10-27 10:23:42 +01:00
// check to see if they are a dynamic reciever eg based on a dropdown field a user selected
2009-07-05 09:14:03 +02:00
if ( $recipient -> SendEmailToField ()) {
2009-10-27 10:23:42 +01:00
$submittedFormField = $submittedFields -> find ( 'Name' , $recipient -> SendEmailToField () -> Name );
2009-07-05 09:14:03 +02:00
2012-07-17 05:58:24 +02:00
if ( $submittedFormField && is_string ( $submittedFormField -> Value )) {
2015-04-20 03:58:15 +02:00
$email -> setTo ( $submittedFormField -> Value );
2009-04-14 05:26:14 +02:00
}
}
2009-07-05 09:14:03 +02:00
2014-07-02 13:56:15 +02:00
// 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 );
}
}
2012-07-17 05:58:24 +02:00
$this -> extend ( 'updateEmail' , $email , $recipient , $emailData );
2012-07-17 06:09:31 +02:00
2009-05-12 08:10:13 +02:00
if ( $recipient -> SendPlain ) {
2015-07-16 05:06:53 +02:00
$body = strip_tags ( $recipient -> getEmailBodyContent ()) . " \n " ;
2010-04-26 00:36:09 +02:00
if ( isset ( $emailData [ 'Fields' ]) && ! $recipient -> HideFormData ) {
2009-05-12 08:10:13 +02:00
foreach ( $emailData [ 'Fields' ] as $Field ) {
2015-04-12 01:26:26 +02:00
$body .= $Field -> Title . ': ' . $Field -> Value . " \n " ;
2009-05-12 08:10:13 +02:00
}
}
2012-09-11 11:22:50 +02:00
2009-05-12 08:10:13 +02:00
$email -> setBody ( $body );
$email -> sendPlain ();
}
else {
2015-04-20 03:58:15 +02:00
$email -> send ();
2009-05-12 08:10:13 +02:00
}
2009-04-14 04:06:18 +02:00
}
2009-02-11 03:27:55 +01:00
}
2015-07-24 04:37:48 +02:00
2014-07-09 06:32:10 +02:00
$submittedForm -> extend ( 'updateAfterProcess' );
2014-07-11 23:43:52 +02:00
2011-04-08 19:36:01 +02:00
Session :: clear ( " FormInfo. { $form -> FormName () } .errors " );
Session :: clear ( " FormInfo. { $form -> FormName () } .data " );
2010-09-03 07:06:13 +02:00
$referrer = ( isset ( $data [ 'Referrer' ])) ? '?referrer=' . urlencode ( $data [ 'Referrer' ]) : " " ;
2013-12-19 03:56:10 +01:00
2014-07-27 10:51:23 +02:00
// 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 );
}
2014-02-27 00:34:57 +01:00
}
2014-01-06 03:15:01 +01:00
}
2015-07-24 04:37:48 +02:00
2014-07-11 23:43:52 +02:00
if ( ! $this -> DisableSaveSubmissions ) {
Session :: set ( 'userformssubmission' . $this -> ID , $submittedForm -> ID );
}
2014-11-28 06:16:37 +01:00
return $this -> redirect ( $this -> Link ( 'finished' ) . $referrer . $this -> config () -> finished_anchor );
2008-10-30 04:53:35 +01:00
}
2015-07-16 05:06:53 +02:00
/**
* Allows the use of field values in email body .
*
* @ param ArrayList fields
2015-08-17 03:19:25 +02:00
* @ return ArrayData
2015-07-16 05:06:53 +02:00
*/
private function getMergeFieldsMap ( $fields = array ()) {
2015-08-17 03:19:25 +02:00
$data = new ArrayData ( array ());
2015-07-16 05:06:53 +02:00
foreach ( $fields as $field ) {
$data -> setField ( $field -> Name , DBField :: create_field ( 'Text' , $field -> Value ));
}
return $data ;
}
2008-10-30 04:53:35 +01:00
/**
2013-01-29 09:44:00 +01:00
* This action handles rendering the " finished " message , which is
* customizable by editing the ReceivedFormSubmission template .
2008-10-30 04:53:35 +01:00
*
* @ return ViewableData
*/
2012-05-04 03:39:08 +02:00
public function finished () {
2014-07-11 23:43:52 +02:00
$submission = Session :: get ( 'userformssubmission' . $this -> ID );
if ( $submission ) {
$submission = SubmittedForm :: get () -> byId ( $submission );
}
2014-01-06 03:15:01 +01:00
$referrer = isset ( $_GET [ 'referrer' ]) ? urldecode ( $_GET [ 'referrer' ]) : null ;
2014-07-27 10:51:23 +02:00
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
2014-02-27 00:34:57 +01:00
if ( $formProcessed != $securityID ) {
2014-07-27 10:51:23 +02:00
// they may have disabled tokens on the form
$securityID = md5 ( Session :: get ( 'FormProcessedNum' ));
if ( $formProcessed != $securityID ) {
return $this -> redirect ( $this -> Link () . $referrer );
}
2014-02-27 00:34:57 +01:00
}
2013-12-19 03:56:10 +01:00
}
2014-07-27 10:51:23 +02:00
Session :: clear ( 'FormProcessed' );
2013-12-19 03:56:10 +01:00
}
2009-07-05 09:39:28 +02:00
return $this -> customise ( array (
2014-07-11 23:43:52 +02:00
'Content' => $this -> customise ( array (
'Submission' => $submission ,
'Link' => $referrer
)) -> renderWith ( 'ReceivedFormSubmission' ),
2010-09-03 07:06:13 +02:00
'Form' => '' ,
2008-09-29 05:18:23 +02:00
));
}
}