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
/**
* Prevent translatable module from attepmting to translate FieldEditor
*
* @ var array
* @ config
*/
private static $translate_excluded_fields = array (
'Fields'
);
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' ,
'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 (
2008-09-29 05:18:23 +02:00
" Fields " => " EditableFormField " ,
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
/**
* 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 () {
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.FormContent' , _t ( 'UserDefinedForm.FORM' , 'Form' ));
$fields -> findOrMakeTab ( 'Root.FormOptions' , _t ( 'UserDefinedForm.CONFIGURATION' , 'Configuration' ));
$fields -> findOrMakeTab ( 'Root.Submissions' , _t ( 'UserDefinedForm.SUBMISSIONS' , 'Submissions' ));
// field editor
$fields -> addFieldToTab ( 'Root.FormContent' , new FieldEditor ( 'Fields' , 'Fields' , '' , $self ));
// 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' );
// Set the summary fields of UserDefinedForm_EmailRecipient dynamically via config system
Config :: inst () -> update (
'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' , _t ( 'UserDefinedForm.EMAILRECIPIENTS' , 'Email Recipients' ), $self -> EmailRecipients (), GridFieldConfig_RecordEditor :: create ( 10 ));
$emailRecipients -> getConfig () -> getComponentByType ( 'GridFieldAddNewButton' ) -> setButtonName (
_t ( 'UserDefinedForm.ADDEMAILRECIPIENT' , 'Add Email Recipient' )
);
$fields -> addFieldsToTab ( 'Root.FormOptions' , $onCompleteFieldSet );
$fields -> addFieldToTab ( 'Root.FormOptions' , $emailRecipients );
$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 GridState_Component ());
$config -> addComponent ( new GridFieldDeleteAction ());
$config -> addComponent ( new GridFieldPageCount ( 'toolbar-header-right' ));
$config -> addComponent ( $pagination = new GridFieldPaginator ( 25 ));
$config -> addComponent ( new GridFieldDetailForm ());
$config -> addComponent ( $export = new GridFieldExportButton ());
$config -> addComponent ( $print = new GridFieldPrintButton ());
/**
* 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 ;
}
2009-09-23 00:36:53 +02:00
2009-09-23 05:00:08 +02:00
2009-09-23 00:36:53 +02:00
/**
* When publishing copy the editable form fields to the live database
* Not going to version emails and submissions as they are likely to
2013-01-29 09:44:00 +01:00
* persist over multiple versions .
2009-09-23 00:36:53 +02:00
*
* @ return void
*/
public function doPublish () {
2013-10-17 04:01:41 +02:00
$parentID = ( ! empty ( $this -> ID )) ? $this -> ID : 0 ;
2009-09-23 02:02:50 +02:00
// remove fields on the live table which could have been orphaned.
2013-10-17 04:01:41 +02:00
$live = Versioned :: get_by_stage ( " EditableFormField " , " Live " , " \" EditableFormField \" . \" ParentID \" = $parentID " );
2009-12-07 01:52:00 +01:00
2009-09-23 02:02:50 +02:00
if ( $live ) {
foreach ( $live as $field ) {
2009-12-12 09:59:20 +01:00
$field -> doDeleteFromStage ( 'Live' );
2009-09-23 02:02:50 +02:00
}
}
2010-05-16 05:21:04 +02:00
2009-09-23 02:02:50 +02:00
// publish the draft pages
2009-09-23 00:36:53 +02:00
if ( $this -> Fields ()) {
foreach ( $this -> Fields () as $field ) {
2009-12-12 09:59:20 +01:00
$field -> doPublish ( 'Stage' , 'Live' );
2009-09-23 00:36:53 +02:00
}
}
2009-04-15 01:50:48 +02:00
2009-09-23 00:36:53 +02:00
parent :: doPublish ();
}
2009-04-15 00:59:46 +02:00
/**
2012-10-18 09:01:56 +02:00
* When un - publishing the page it has to remove all the fields from the
* live database table .
2009-09-23 00:36:53 +02:00
*
* @ return void
2009-04-15 00:59:46 +02:00
*/
2009-09-23 00:36:53 +02:00
public function doUnpublish () {
if ( $this -> Fields ()) {
foreach ( $this -> Fields () as $field ) {
2009-12-12 09:59:20 +01:00
$field -> doDeleteFromStage ( 'Live' );
2009-09-23 00:36:53 +02:00
}
2009-04-15 00:59:46 +02:00
}
2009-09-23 00:36:53 +02:00
parent :: doUnpublish ();
2009-04-15 00:59:46 +02:00
}
2009-09-23 00:36:53 +02:00
2009-04-15 00:59:46 +02:00
/**
2010-09-03 07:06:13 +02:00
* Roll back a form to a previous version .
2009-04-15 00:59:46 +02:00
*
2012-10-18 09:01:56 +02:00
* @ param string | int Version to roll back to
2009-04-15 00:59:46 +02:00
*/
2009-09-23 00:36:53 +02:00
public function doRollbackTo ( $version ) {
2010-09-03 07:06:13 +02:00
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 ();
}
}
2009-09-23 00:36:53 +02:00
}
2010-09-03 07:06:13 +02:00
// @todo Emails
2009-09-23 00:36:53 +02:00
}
2010-09-03 07:06:13 +02:00
*/
2009-09-23 00:36:53 +02:00
}
/**
* Revert the draft site to the current live site
*
* @ return void
*/
public function doRevertToLive () {
if ( $this -> Fields ()) {
foreach ( $this -> Fields () as $field ) {
2010-09-03 07:06:13 +02:00
$field -> publish ( " Live " , " Stage " , false );
$field -> writeWithoutVersion ();
2009-09-23 00:36:53 +02:00
}
}
parent :: doRevertToLive ();
2008-09-29 05:18:23 +02:00
}
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 ) {
2012-12-11 05:09:02 +01:00
$recipients = new ArrayList ( $this -> getComponents ( 'EmailRecipients' ) -> toArray ());
2013-09-04 08:32:24 +02:00
$this -> extend ( 'updateFilteredEmailRecipients' , $recipients , $data , $form );
2012-12-11 05:09:02 +01:00
return $recipients ;
}
2013-06-04 11:17:40 +02:00
/**
* Store new and old ids of duplicated fields .
* This method also serves as a hook for descendant classes .
*/
protected function afterDuplicateField ( $page , $fromField , $toField ) {
$this -> fieldsFromTo [ $fromField -> ClassName . $fromField -> ID ] = $toField -> ClassName . $toField -> ID ;
}
2008-09-29 05:18:23 +02:00
/**
* Duplicate this UserDefinedForm page , and its form fields .
* Submissions , on the other hand , won ' t be duplicated .
2009-04-15 00:59:46 +02:00
*
* @ return Page
2008-09-29 05:18:23 +02:00
*/
2013-01-29 09:44:00 +01:00
public function duplicate ( $doWrite = true ) {
2012-05-04 03:39:08 +02:00
$page = parent :: duplicate ( $doWrite );
2010-05-31 11:01:58 +02:00
// the form fields
if ( $this -> Fields ()) {
foreach ( $this -> Fields () as $field ) {
$newField = $field -> duplicate ();
$newField -> ParentID = $page -> ID ;
$newField -> write ();
2013-06-04 11:17:40 +02:00
$this -> afterDuplicateField ( $page , $field , $newField );
2010-05-31 11:01:58 +02:00
}
2008-09-29 05:18:23 +02:00
}
2010-05-31 11:01:58 +02:00
// the emails
if ( $this -> EmailRecipients ()) {
foreach ( $this -> EmailRecipients () as $email ) {
$newEmail = $email -> duplicate ();
$newEmail -> FormID = $page -> ID ;
$newEmail -> write ();
}
}
2013-06-04 11:17:40 +02:00
// Rewrite CustomRules
if ( $page -> Fields ()) {
foreach ( $page -> Fields () as $field ) {
// Rewrite name to make the CustomRules-rewrite below work.
$field -> Name = $field -> ClassName . $field -> ID ;
$rules = unserialize ( $field -> CustomRules );
if ( count ( $rules ) && isset ( $rules [ 0 ][ 'ConditionField' ])) {
$from = $rules [ 0 ][ 'ConditionField' ];
if ( array_key_exists ( $from , $this -> fieldsFromTo )) {
$rules [ 0 ][ 'ConditionField' ] = $this -> fieldsFromTo [ $from ];
$field -> CustomRules = serialize ( $rules );
}
}
$field -> Write ();
}
}
2008-09-29 05:18:23 +02:00
return $page ;
}
2012-12-11 05:09:02 +01:00
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' )),
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
}
2010-05-16 05:21:04 +02:00
/**
* 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
*
2012-10-18 09:01:56 +02:00
* @ return boolean
2010-05-16 05:21:04 +02:00
*/
public function getIsModifiedOnStage () {
2012-10-18 09:01:56 +02:00
// new unsaved pages could be never be published
2013-01-29 09:44:00 +01:00
if ( $this -> isNew ()) {
return false ;
}
2012-10-18 09:01:56 +02:00
$stageVersion = Versioned :: get_versionnumber_by_stage ( 'UserDefinedForm' , 'Stage' , $this -> ID );
2015-04-20 03:58:15 +02:00
$liveVersion = Versioned :: get_versionnumber_by_stage ( 'UserDefinedForm' , 'Live' , $this -> ID );
2012-10-18 09:01:56 +02:00
$isModified = ( $stageVersion && $stageVersion != $liveVersion );
2013-01-29 09:44:00 +01:00
if ( ! $isModified ) {
2012-10-18 09:01:56 +02:00
if ( $this -> Fields ()) {
foreach ( $this -> Fields () as $field ) {
2013-01-29 09:44:00 +01:00
if ( $field -> getIsModifiedOnStage ()) {
$isModified = true ;
break ;
2012-10-18 09:01:56 +02:00
}
}
}
}
return $isModified ;
2010-05-16 05:21:04 +02:00
}
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 ());
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' );
Requirements :: javascript ( USERFORMS_DIR . '/javascript/UserForm_frontend.js' );
Requirements :: javascript (
USERFORMS_DIR . " /thirdparty/jquery-validate/localization/messages_ { $lang } .min.js "
);
Requirements :: javascript (
USERFORMS_DIR . " /thirdparty/jquery-validate/localization/methods_ { $lang } .min.js "
);
if ( $this -> HideFieldLabels ) {
Requirements :: javascript ( USERFORMS_DIR . '/thirdparty/Placeholders.js/Placeholders.min.js' );
}
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 ) {
2011-04-08 19:36:01 +02:00
$content = str_ireplace ( '$UserDefinedForm' , $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
*
2010-12-19 01:40:53 +01:00
* @ return Form | false
2009-04-14 04:06:18 +02:00
*/
2012-05-04 03:39:08 +02:00
public function Form () {
2010-09-03 07:06:13 +02:00
$fields = $this -> getFormFields ();
2012-05-07 12:00:18 +02:00
if ( ! $fields || ! $fields -> exists ()) return false ;
2010-12-19 01:40:53 +01:00
2010-09-03 07:06:13 +02:00
$actions = $this -> getFormActions ();
2010-07-07 11:17:37 +02:00
2010-09-03 07:06:13 +02:00
// get the required fields including the validation
$required = $this -> getRequiredFields ();
2012-04-14 11:59:27 +02:00
2010-09-03 07:06:13 +02:00
// generate the conditional logic
$this -> generateConditionalJavascript ();
2012-05-07 08:10:57 +02:00
2010-09-03 07:06:13 +02:00
$form = new Form ( $this , " Form " , $fields , $actions , $required );
2012-10-14 00:15:26 +02:00
$form -> setRedirectToFormOnValidationError ( true );
2010-09-03 07:06:13 +02:00
2011-04-08 19:36:01 +02:00
$data = Session :: get ( " FormInfo. { $form -> FormName () } .data " );
if ( is_array ( $data )) $form -> loadDataFrom ( $data );
2010-09-03 07:06:13 +02:00
$this -> extend ( 'updateForm' , $form );
2014-07-27 10:51:23 +02:00
if ( $this -> DisableCsrfSecurityToken ) {
$form -> disableSecurityToken ();
}
2010-09-03 07:06:13 +02:00
return $form ;
}
2015-02-10 03:32:44 +01:00
2010-09-03 07:06:13 +02:00
/**
* Get the form fields for the form on this page . Can modify this FieldSet
* by using { @ link updateFormFields ()} on an { @ link Extension } subclass which
2013-01-29 09:44:00 +01:00
* is applied to this controller .
2010-09-03 07:06:13 +02:00
*
2013-01-29 09:44:00 +01:00
* @ return FieldList
2010-09-03 07:06:13 +02:00
*/
2012-05-04 03:39:08 +02:00
public function getFormFields () {
2012-04-22 21:17:42 +02:00
$fields = new FieldList ();
2015-02-10 03:32:44 +01:00
$editableFields = $this -> Fields ();
if ( $editableFields ) foreach ( $editableFields 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' )) {
// Since this field expects raw html, safely escape the user data prior
$field -> setRightTitle ( Convert :: raw2xml ( $right ));
}
// if this field is required add some
if ( $editableField -> Required ) {
$field -> addExtraClass ( 'requiredField' );
if ( $identifier = UserDefinedForm :: config () -> required_identifier ) {
$title = $field -> Title () . " <span class='required-identifier'> " . $identifier . " </span> " ;
$field -> setTitle ( $title );
2012-05-07 08:10:57 +02:00
}
2010-09-03 07:06:13 +02:00
}
2015-02-10 03:32:44 +01:00
// if this field has an extra class
if ( $extraClass = $editableField -> getSetting ( 'ExtraClass' )) {
$field -> addExtraClass ( Convert :: raw2att ( $extraClass ));
}
// set the values passed by the url to the field
$request = $this -> getRequest ();
if ( $value = $request -> getVar ( $field -> getName ())) {
$field -> setValue ( $value );
}
$fields -> push ( $field );
2010-09-03 07:06:13 +02:00
}
$this -> extend ( 'updateFormFields' , $fields );
2012-05-07 08:10:57 +02:00
2010-09-03 07:06:13 +02:00
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 .
*
2013-01-29 09:44:00 +01:00
* @ return FieldList
2010-09-03 07:06:13 +02:00
*/
2012-05-04 03:39:08 +02:00
public function getFormActions () {
2010-09-03 07:06:13 +02:00
$submitText = ( $this -> SubmitButtonText ) ? $this -> SubmitButtonText : _t ( 'UserDefinedForm.SUBMITBUTTON' , 'Submit' );
2013-11-11 14:25:31 +01:00
$clearText = ( $this -> ClearButtonText ) ? $this -> ClearButtonText : _t ( 'UserDefinedForm.CLEARBUTTON' , 'Clear' );
2010-09-03 07:06:13 +02:00
2012-04-22 21:17:42 +02:00
$actions = new FieldList (
2010-09-03 07:06:13 +02:00
new FormAction ( " process " , $submitText )
);
if ( $this -> ShowClearButton ) {
2013-11-11 14:25:31 +01:00
$actions -> push ( new ResetFormAction ( " clearForm " , $clearText ));
2010-09-03 07:06:13 +02:00
}
$this -> extend ( 'updateFormActions' , $actions );
return $actions ;
}
/**
* Get the required form fields for this form . Includes building the jQuery
* validate structure
*
* @ return RequiredFields
*/
2012-05-04 03:39:08 +02:00
public function getRequiredFields () {
2010-12-19 02:19:19 +01:00
2010-09-03 07:06:13 +02:00
// set the custom script for this form
2014-04-16 01:48:10 +02:00
Requirements :: customScript ( $this -> renderWith ( 'ValidationScript' ), 'UserFormsValidation' );
// Generate required field validator
$requiredNames = $this
-> Fields ()
-> filter ( 'Required' , true )
-> column ( 'Name' );
$required = new RequiredFields ( $requiredNames );
2010-09-03 07:06:13 +02:00
$this -> extend ( 'updateRequiredFields' , $required );
return $required ;
}
/**
* 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 ) {
2009-05-08 06:27:49 +02:00
$fieldId = $field -> Name ;
if ( $field -> ClassName == 'EditableFormHeading' ) {
$fieldId = 'Form_Form_' . $field -> Name ;
}
2009-04-24 00:52:08 +02:00
// Is this Field Show by Default
2010-09-03 07:06:13 +02:00
if ( ! $field -> getShowOnLoad ()) {
$default .= " $ ( \" # " . $fieldId . " \" ).hide(); \n " ;
2009-04-24 00:52:08 +02:00
}
// Check for field dependencies / default
if ( $field -> Dependencies ()) {
foreach ( $field -> Dependencies () as $dependency ) {
if ( is_array ( $dependency ) && isset ( $dependency [ 'ConditionField' ]) && $dependency [ 'ConditionField' ] != " " ) {
// get the field which is effected
$formName = Convert :: raw2sql ( $dependency [ 'ConditionField' ]);
2010-04-08 23:18:01 +02:00
$formFieldWatch = DataObject :: get_one ( " EditableFormField " , " \" Name \" = ' $formName ' " );
2009-05-01 06:11:31 +02:00
2009-04-24 00:52:08 +02:00
if ( ! $formFieldWatch ) break ;
2009-05-01 06:11:31 +02:00
// watch out for multiselect options - radios and check boxes
2009-05-07 05:55:04 +02:00
if ( is_a ( $formFieldWatch , 'EditableDropdown' )) {
2015-04-20 03:58:15 +02:00
$fieldToWatch = " $ ( \" select[name=' " . $dependency [ 'ConditionField' ] . " '] \" ) " ;
2012-09-10 22:52:33 +02:00
$fieldToWatchOnLoad = $fieldToWatch ;
2009-05-01 06:11:31 +02:00
}
// watch out for checkboxs as the inputs don't have values but are 'checked
else if ( is_a ( $formFieldWatch , 'EditableCheckboxGroupField' )) {
$fieldToWatch = " $ ( \" input[name=' " . $dependency [ 'ConditionField' ] . " [ " . $dependency [ 'Value' ] . " ]'] \" ) " ;
2012-09-10 22:52:33 +02:00
$fieldToWatchOnLoad = $fieldToWatch ;
}
else if ( is_a ( $formFieldWatch , 'EditableRadioField' )) {
$fieldToWatch = " $ ( \" input[name=' " . $dependency [ 'ConditionField' ] . " '] \" ) " ;
// We only want to trigger on load once for the radio group - hence we focus on the first option only.
$fieldToWatchOnLoad = " $ ( \" input[name=' " . $dependency [ 'ConditionField' ] . " ']:first \" ) " ;
2009-05-01 06:11:31 +02:00
}
else {
2012-09-10 22:52:33 +02:00
$fieldToWatch = " $ ( \" input[name=' " . $dependency [ 'ConditionField' ] . " '] \" ) " ;
$fieldToWatchOnLoad = $fieldToWatch ;
2009-05-01 06:11:31 +02:00
}
2009-04-24 00:52:08 +02:00
// show or hide?
2009-05-06 05:34:40 +02:00
$view = ( isset ( $dependency [ 'Display' ]) && $dependency [ 'Display' ] == " Hide " ) ? " hide " : " show " ;
2009-04-24 00:52:08 +02:00
$opposite = ( $view == " show " ) ? " hide " : " show " ;
2009-05-01 06:11:31 +02:00
2009-05-08 06:27:49 +02:00
// what action do we need to keep track of. Something nicer here maybe?
// @todo encapulsation
$action = " change " ;
2012-09-11 00:26:37 +02:00
if ( $formFieldWatch -> ClassName == " EditableTextField " ) {
2009-05-08 06:27:49 +02:00
$action = " keyup " ;
}
2009-04-24 00:52:08 +02:00
2009-05-06 05:34:40 +02:00
// is this field a special option field
$checkboxField = false ;
2012-09-10 22:52:33 +02:00
$radioField = false ;
2014-12-02 07:49:03 +01:00
2009-05-06 05:34:40 +02:00
if ( in_array ( $formFieldWatch -> ClassName , array ( 'EditableCheckboxGroupField' , 'EditableCheckbox' ))) {
2009-09-16 23:36:02 +02:00
$action = " click " ;
2009-05-06 05:34:40 +02:00
$checkboxField = true ;
}
2012-09-10 22:52:33 +02:00
else if ( $formFieldWatch -> ClassName == " EditableRadioField " ) {
$radioField = true ;
}
2014-12-02 07:49:03 +01:00
2012-09-10 22:52:33 +02:00
// Escape the values.
$dependency [ 'Value' ] = str_replace ( '"' , '\"' , $dependency [ 'Value' ]);
2009-05-01 06:11:31 +02:00
// and what should we evaluate
2009-04-24 00:52:08 +02:00
switch ( $dependency [ 'ConditionOption' ]) {
case 'IsNotBlank' :
2014-12-03 01:59:42 +01:00
$expression = ( $checkboxField || $radioField ) ? '$(this).prop("checked")' : '$(this).val() != ""' ;
2009-05-06 05:34:40 +02:00
2009-04-24 00:52:08 +02:00
break ;
case 'IsBlank' :
2014-12-03 01:59:42 +01:00
$expression = ( $checkboxField || $radioField ) ? '!($(this).prop("checked"))' : '$(this).val() == ""' ;
2009-05-06 05:34:40 +02:00
2009-04-24 00:52:08 +02:00
break ;
case 'HasValue' :
2012-09-10 22:52:33 +02:00
if ( $checkboxField ) {
2014-12-03 01:59:42 +01:00
$expression = '$(this).prop("checked")' ;
2012-09-10 22:52:33 +02:00
} else if ( $radioField ) {
// We cannot simply get the value of the radio group, we need to find the checked option first.
2013-12-03 08:09:34 +01:00
$expression = '$(this).parents(".field, .control-group").find("input:checked").val()=="' . $dependency [ 'Value' ] . '"' ;
2012-09-10 22:52:33 +02:00
} else {
$expression = '$(this).val() == "' . $dependency [ 'Value' ] . '"' ;
}
2009-05-06 05:34:40 +02:00
2009-04-24 00:52:08 +02:00
break ;
2009-11-02 08:22:30 +01:00
case 'ValueLessThan' :
$expression = '$(this).val() < parseFloat("' . $dependency [ 'Value' ] . '")' ;
break ;
case 'ValueLessThanEqual' :
$expression = '$(this).val() <= parseFloat("' . $dependency [ 'Value' ] . '")' ;
break ;
case 'ValueGreaterThan' :
$expression = '$(this).val() > parseFloat("' . $dependency [ 'Value' ] . '")' ;
break ;
case 'ValueGreaterThanEqual' :
$expression = '$(this).val() >= parseFloat("' . $dependency [ 'Value' ] . '")' ;
2015-04-20 03:58:15 +02:00
break ;
2012-09-10 22:52:33 +02:00
default : // ==HasNotValue
if ( $checkboxField ) {
2014-12-03 01:59:42 +01:00
$expression = '!$(this).prop("checked")' ;
2012-09-10 22:52:33 +02:00
} else if ( $radioField ) {
// We cannot simply get the value of the radio group, we need to find the checked option first.
2013-12-03 08:09:34 +01:00
$expression = '$(this).parents(".field, .control-group").find("input:checked").val()!="' . $dependency [ 'Value' ] . '"' ;
2012-09-10 22:52:33 +02:00
} else {
$expression = '$(this).val() != "' . $dependency [ 'Value' ] . '"' ;
}
2009-11-02 08:22:30 +01:00
2009-04-24 00:52:08 +02:00
break ;
}
2013-02-27 04:05:30 +01:00
if ( ! isset ( $watch [ $fieldToWatch ])) {
$watch [ $fieldToWatch ] = array ();
}
2014-12-02 07:49:03 +01:00
2013-02-27 04:05:30 +01:00
$watch [ $fieldToWatch ][] = array (
'expression' => $expression ,
'field_id' => $fieldId ,
'view' => $view ,
2014-12-02 07:49:03 +01:00
'opposite' => $opposite ,
'action' => $action
2013-02-27 04:05:30 +01: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 ) {
// Register conditional behaviour with an element, so it can be triggered from many places.
$logic [] = sprintf (
'if(%s) { $("#%s").%s(); } else { $("#%2$s").%s(); }' ,
$rule [ 'expression' ],
$rule [ 'field_id' ],
$rule [ 'view' ],
$rule [ 'opposite' ]
);
2014-12-02 07:49:03 +01:00
$actions [ $rule [ 'action' ]] = $rule [ 'action' ];
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
}
2009-04-21 05:44:13 +02:00
/**
* Convert a PHP array to a JSON string . We cannot use { @ link Convert :: array2json }
* as it escapes our values with " " which appears to break the validate plugin
*
* @ param Array array to convert
* @ return JSON
*/
2012-05-04 03:39:08 +02:00
public function array2json ( $array ) {
2013-01-29 09:44:00 +01:00
foreach ( $array as $key => $value ) {
2009-04-21 05:44:13 +02:00
if ( is_array ( $value )) {
$result [] = " $key : " . $this -> array2json ( $value );
} else {
2014-07-24 11:37:11 +02:00
$value = ( is_bool ( $value ) || is_numeric ( $value ) ) ? $value : " \" $value\ " " ;
2010-09-03 07:06:13 +02:00
$result [] = " $key : $value " ;
2009-04-21 05:44:13 +02:00
}
2013-01-29 09:44:00 +01:00
}
2010-09-03 07:06:13 +02:00
return ( isset ( $result )) ? " { \n " . implode ( ', ' , $result ) . " \n } \n " : '{}' ;
2009-04-21 05:44:13 +02:00
}
2009-04-14 04:06:18 +02:00
/**
* Process the form that is submitted through the site
*
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 ) {
2015-04-20 03:58:15 +02:00
Session :: set ( " FormInfo. { $form -> FormName () } .data " , $data );
2011-04-08 19:39:05 +02:00
Session :: clear ( " FormInfo. { $form -> FormName () } .errors " );
2012-04-14 11:59:27 +02:00
2011-04-08 19:39:05 +02:00
foreach ( $this -> Fields () as $field ) {
$messages [ $field -> Name ] = $field -> getErrorMessage () -> HTML ();
2014-04-23 01:46:57 +02:00
$formField = $field -> getFormField ();
2012-04-14 11:59:27 +02:00
if ( $field -> Required && $field -> CustomRules () -> Count () == 0 ) {
2014-04-23 01:46:57 +02:00
if ( isset ( $data [ $field -> Name ])) {
$formField -> setValue ( $data [ $field -> Name ]);
}
if (
! isset ( $data [ $field -> Name ]) ||
2011-04-08 19:39:05 +02:00
! $data [ $field -> Name ] ||
2014-04-23 01:46:57 +02:00
! $formField -> validate ( $form -> getValidator ())
) {
$form -> addErrorMessage ( $field -> Name , $field -> getErrorMessage (), 'bad' );
2011-04-08 19:39:05 +02:00
}
2011-04-08 19:36:01 +02:00
}
}
2010-09-03 07:06:13 +02:00
2011-04-08 19:39:05 +02:00
if ( Session :: get ( " FormInfo. { $form -> FormName () } .errors " )){
2012-05-11 01:39:24 +02:00
Controller :: curr () -> redirectBack ();
2013-01-29 09:44:00 +01:00
2011-04-08 19:39:05 +02:00
return ;
}
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 ();
}
2008-09-29 05:18:23 +02:00
$values = array ();
2012-07-17 05:58:24 +02:00
$attachments = array ();
2009-02-27 02:21:10 +01:00
2012-04-22 21:25:26 +02:00
$submittedFields = new ArrayList ();
2009-04-20 01:52:44 +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 ;
}
2009-05-12 08:10:13 +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' );
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
}
}
2010-09-03 07:06:13 +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 ();
}
2011-12-05 11:19:20 +01:00
2009-07-22 06:02:21 +02:00
$submittedFields -> push ( $submittedField );
2010-09-03 07:06:13 +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
);
2014-02-03 00:10:44 +01:00
$this -> extend ( 'updateEmailData' , $emailData , $attachments );
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 )) {
2012-07-17 06:09:31 +02:00
$email = new UserDefinedForm_SubmittedFormEmail ( $submittedFields );
2010-09-03 07:06:13 +02:00
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 ) {
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 );
$email -> setBody ( $recipient -> EmailBody );
$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 ) {
2014-07-12 17:52:16 +02:00
$body = strip_tags ( $recipient -> EmailBody ) . " \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
}
2010-09-03 07:06:13 +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-01-06 03:15:01 +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
}
2014-07-27 10:51:23 +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
}
/**
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
));
}
}
/**
2009-04-14 04:06:18 +02:00
* A Form can have multiply members / emails to email the submission
* to and custom subjects
*
* @ package userforms
*/
class UserDefinedForm_EmailRecipient extends DataObject {
2013-04-03 03:34:43 +02:00
private static $db = array (
2009-04-14 04:06:18 +02:00
'EmailAddress' => 'Varchar(200)' ,
'EmailSubject' => 'Varchar(200)' ,
'EmailFrom' => 'Varchar(200)' ,
2012-09-11 11:22:50 +02:00
'EmailReplyTo' => 'Varchar(200)' ,
2009-06-16 05:13:49 +02:00
'EmailBody' => 'Text' ,
2009-07-27 01:23:45 +02:00
'SendPlain' => 'Boolean' ,
'HideFormData' => 'Boolean'
2009-04-14 04:06:18 +02:00
);
2013-04-03 03:34:43 +02:00
private static $has_one = array (
2009-04-14 05:26:14 +02:00
'Form' => 'UserDefinedForm' ,
2009-07-05 09:14:03 +02:00
'SendEmailFromField' => 'EditableFormField' ,
2014-07-02 13:56:15 +02:00
'SendEmailToField' => 'EditableFormField' ,
'SendEmailSubjectField' => 'EditableFormField'
2009-04-14 04:06:18 +02:00
);
2009-04-14 05:26:14 +02:00
2013-04-03 03:34:43 +02:00
private static $summary_fields = array ();
2009-04-14 05:26:14 +02:00
/**
2013-01-29 09:44:00 +01:00
* @ return FieldList
2009-04-14 05:26:14 +02:00
*/
2012-04-22 21:17:42 +02:00
public function getCMSFields () {
2009-07-17 05:40:18 +02:00
2012-04-22 21:17:42 +02:00
$fields = new FieldList (
2012-09-11 11:22:50 +02:00
new TextField ( 'EmailSubject' , _t ( 'UserDefinedForm.EMAILSUBJECT' , 'Email subject' )),
new LiteralField ( 'EmailFromContent' , '<p>' . _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. "
) . " </p> " ),
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)' )),
2010-09-08 00:48:46 +02:00
new TextareaField ( 'EmailBody' , _t ( 'UserDefinedForm.EMAILBODY' , 'Body' ))
2009-04-14 05:26:14 +02:00
);
2014-12-01 21:46:02 +01:00
$formID = ( $this -> FormID != 0 ) ? $this -> FormID : Session :: get ( 'CMSMain.currentPage' );
$dropdowns = array ();
// if they have email fields then we could send from it
$validEmailFields = EditableEmailField :: get () -> filter ( 'ParentID' , ( int ) $formID );
// for the subject, only one-line entry boxes make sense
$validSubjectFields = EditableTextField :: get () -> filter ( 'ParentID' , ( int ) $formID ) -> filterByCallback ( function ( $item , $list ) { return ( int ) $item -> getSetting ( 'Rows' ) === 1 ; });
// predefined choices are also candidates
$multiOptionFields = EditableMultipleOptionField :: get () -> filter ( 'ParentID' , ( int ) $formID );
$fields -> insertAfter ( $dropdowns [] = new DropdownField (
'SendEmailFromFieldID' ,
_t ( 'UserDefinedForm.ORSELECTAFIELDTOUSEASFROM' , '.. or select a field to use as reply to address' ),
$validEmailFields -> map ( 'ID' , 'Title' )
), 'EmailReplyTo' );
$validEmailFields = new ArrayList ( $validEmailFields -> toArray ());
$validEmailFields -> merge ( $multiOptionFields );
$validSubjectFields -> merge ( $multiOptionFields );
$fields -> insertAfter ( $dropdowns [] = new DropdownField (
'SendEmailToFieldID' ,
_t ( 'UserDefinedForm.ORSELECTAFIELDTOUSEASTO' , '.. or select a field to use as the to address' ),
$validEmailFields -> map ( 'ID' , 'Title' )
), 'EmailAddress' );
$fields -> insertAfter ( $dropdowns [] = new DropdownField (
'SendEmailSubjectFieldID' ,
_t ( 'UserDefinedForm.SELECTAFIELDTOSETSUBJECT' , '.. or select a field to use as the subject' ),
$validSubjectFields -> map ( 'ID' , 'Title' )
), 'EmailSubject' );
foreach ( $dropdowns as $dropdown ) {
$dropdown -> setHasEmptyDefault ( true );
$dropdown -> setEmptyString ( " " );
2009-04-14 05:26:14 +02:00
}
2012-07-17 06:09:31 +02:00
$this -> extend ( 'updateCMSFields' , $fields );
2009-07-17 05:40:18 +02:00
2009-04-14 05:26:14 +02:00
return $fields ;
}
2013-05-13 04:31:25 +02:00
/**
* @ param Member
*
* @ return boolean
*/
public function canCreate ( $member = null ) {
return $this -> Form () -> canCreate ();
}
2013-01-29 09:44:00 +01:00
/**
* @ param Member
*
* @ return boolean
*/
2012-09-24 19:02:33 +02:00
public function canView ( $member = null ) {
return $this -> Form () -> canView ();
}
2013-01-29 09:44:00 +01:00
/**
* @ param Member
*
* @ return boolean
*/
2012-05-04 03:59:10 +02:00
public function canEdit ( $member = null ) {
2009-12-04 01:39:56 +01:00
return $this -> Form () -> canEdit ();
}
2013-01-29 09:44:00 +01:00
/**
* @ param Member
*
* @ return boolean
*/
2012-05-04 03:59:10 +02:00
public function canDelete ( $member = null ) {
2009-12-04 01:39:56 +01:00
return $this -> Form () -> canDelete ();
}
2009-04-14 04:06:18 +02:00
}
2009-12-07 03:04:20 +01:00
2009-04-14 04:06:18 +02:00
/**
2013-01-29 09:44:00 +01:00
* Email that gets sent to the people listed in the Email Recipients when a
* submission is made .
2009-04-14 04:06:18 +02:00
*
* @ package userforms
2008-09-29 05:18:23 +02:00
*/
2009-12-07 03:04:20 +01:00
2008-09-29 05:18:23 +02:00
class UserDefinedForm_SubmittedFormEmail extends Email {
2013-01-29 09:44:00 +01:00
2008-09-29 05:18:23 +02:00
protected $ss_template = " SubmittedFormEmail " ;
2013-01-29 09:44:00 +01:00
2008-09-29 05:18:23 +02:00
protected $data ;
2009-04-14 04:06:18 +02:00
2012-07-17 05:58:24 +02:00
public function __construct ( $submittedFields = null ) {
parent :: __construct ( $submittedFields = null );
2008-09-29 05:18:23 +02:00
}
2013-01-29 10:40:28 +01:00
2015-04-20 03:58:15 +02:00
/**
2013-01-29 10:40:28 +01:00
* Set the " Reply-To " header with an email address rather than append as
* { @ link Email :: replyTo } does .
*
* @ param string $email The email address to set the " Reply-To " header to
*/
public function setReplyTo ( $email ) {
$this -> customHeaders [ 'Reply-To' ] = $email ;
}
2014-07-12 17:52:16 +02:00
}