mirror of
https://github.com/silverstripe/silverstripe-userforms.git
synced 2024-10-22 17:05:42 +02:00
Add custom email templates
- Developers can add email templates via a configurable path. - Content editors can select the email templates via a dropdown. - Content editors can embed HTML content in emails. - Content editors can preview HTML emails. - Content editors can use field values (merge fields) in emails.
This commit is contained in:
parent
494b9e5746
commit
350fdee850
@ -26,6 +26,11 @@ class UserDefinedForm extends Page {
|
||||
'Fields'
|
||||
);
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private static $email_template_directory = 'userforms/templates/email/';
|
||||
|
||||
/**
|
||||
* @var array Fields on the user defined form page.
|
||||
*/
|
||||
@ -110,6 +115,10 @@ class UserDefinedForm extends Page {
|
||||
$emailRecipients->getConfig()->getComponentByType('GridFieldAddNewButton')->setButtonName(
|
||||
_t('UserDefinedForm.ADDEMAILRECIPIENT', 'Add Email Recipient')
|
||||
);
|
||||
$emailRecipients
|
||||
->getConfig()
|
||||
->getComponentByType('GridFieldDetailForm')
|
||||
->setItemRequestClass('UserDefinedForm_EmailRecipient_ItemRequest');
|
||||
|
||||
$fields->addFieldsToTab('Root.FormOptions', $onCompleteFieldSet);
|
||||
$fields->addFieldToTab('Root.FormOptions', $emailRecipients);
|
||||
@ -989,6 +998,7 @@ JS
|
||||
// email users on submit.
|
||||
if($recipients = $this->FilteredEmailRecipients($data, $form)) {
|
||||
$email = new UserDefinedForm_SubmittedFormEmail($submittedFields);
|
||||
$mergeFields = $this->getMergeFieldsMap($emailData['Fields']);
|
||||
|
||||
if($attachments) {
|
||||
foreach($attachments as $file) {
|
||||
@ -1003,10 +1013,16 @@ JS
|
||||
}
|
||||
|
||||
foreach($recipients as $recipient) {
|
||||
$parsedBody = SSViewer::execute_string($recipient->getEmailBodyContent(), $mergeFields);
|
||||
|
||||
if (!$recipient->SendPlain && $recipient->emailTemplateExists()) {
|
||||
$email->setTemplate($recipient->EmailTemplate);
|
||||
}
|
||||
|
||||
$email->populateTemplate($recipient);
|
||||
$email->populateTemplate($emailData);
|
||||
$email->setFrom($recipient->EmailFrom);
|
||||
$email->setBody($recipient->EmailBody);
|
||||
$email->setBody($parsedBody);
|
||||
$email->setTo($recipient->EmailAddress);
|
||||
$email->setSubject($recipient->EmailSubject);
|
||||
|
||||
@ -1043,7 +1059,7 @@ JS
|
||||
$this->extend('updateEmail', $email, $recipient, $emailData);
|
||||
|
||||
if($recipient->SendPlain) {
|
||||
$body = strip_tags($recipient->EmailBody) . "\n";
|
||||
$body = strip_tags($recipient->getEmailBodyContent()) . "\n";
|
||||
if(isset($emailData['Fields']) && !$recipient->HideFormData) {
|
||||
foreach($emailData['Fields'] as $Field) {
|
||||
$body .= $Field->Title .': '. $Field->Value ." \n";
|
||||
@ -1091,6 +1107,22 @@ JS
|
||||
return $this->redirect($this->Link('finished') . $referrer . $this->config()->finished_anchor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the use of field values in email body.
|
||||
*
|
||||
* @param ArrayList fields
|
||||
* @return ViewableData
|
||||
*/
|
||||
private function getMergeFieldsMap($fields = array()) {
|
||||
$data = new ViewableData();
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$data->setField($field->Name, DBField::create_field('Text', $field->Value));
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* This action handles rendering the "finished" message, which is
|
||||
* customizable by editing the ReceivedFormSubmission template.
|
||||
@ -1150,6 +1182,8 @@ class UserDefinedForm_EmailRecipient extends DataObject {
|
||||
'EmailFrom' => 'Varchar(200)',
|
||||
'EmailReplyTo' => 'Varchar(200)',
|
||||
'EmailBody' => 'Text',
|
||||
'EmailBodyHtml' => 'HTMLText',
|
||||
'EmailTemplate' => 'Varchar',
|
||||
'SendPlain' => 'Boolean',
|
||||
'HideFormData' => 'Boolean'
|
||||
);
|
||||
@ -1168,6 +1202,16 @@ class UserDefinedForm_EmailRecipient extends DataObject {
|
||||
*/
|
||||
public function getCMSFields() {
|
||||
|
||||
// Only show the preview link if the recipient has been saved.
|
||||
if (!empty($this->EmailTemplate)) {
|
||||
$translatableKey = 'UserDefinedForm.EMAILPREVIEWAVAILABLE';
|
||||
$previewHTML = '<p><a href="admin/pages/edit/EditForm/field/EmailRecipients/item/' . $this->ID . '/preview" target="_blank" class="ss-ui-button">Preview email</a></p>' .
|
||||
'<em>Note: Unsaved changes will not appear in the preview.</em>';
|
||||
} else {
|
||||
$translatableKey = 'UserDefinedForm.EMAILPREVIEWUNAVAILABLE';
|
||||
$previewHTML = '<em>You can preview this email once you have saved the Recipient.</em>';
|
||||
}
|
||||
|
||||
$fields = new FieldList(
|
||||
new TextField('EmailSubject', _t('UserDefinedForm.EMAILSUBJECT', 'Email subject')),
|
||||
new LiteralField('EmailFromContent', '<p>'._t(
|
||||
@ -1182,7 +1226,10 @@ class UserDefinedForm_EmailRecipient extends DataObject {
|
||||
new TextField('EmailAddress', _t('UserDefinedForm.SENDEMAILTO','Send email to')),
|
||||
new CheckboxField('HideFormData', _t('UserDefinedForm.HIDEFORMDATA', 'Hide form data from email?')),
|
||||
new CheckboxField('SendPlain', _t('UserDefinedForm.SENDPLAIN', 'Send email as plain text? (HTML will be stripped)')),
|
||||
new TextareaField('EmailBody', _t('UserDefinedForm.EMAILBODY','Body'))
|
||||
new DropdownField('EmailTemplate', _t('UserDefinedForm.EMAILTEMPLATE', 'Email template'), $this->getEmailTemplateDropdownValues()),
|
||||
new HTMLEditorField('EmailBodyHtml', _t('UserDefinedForm.EMAILBODYHTML','Body')),
|
||||
new TextareaField('EmailBody', _t('UserDefinedForm.EMAILBODY','Body')),
|
||||
new LiteralField('EmailPreview', '<div id="EmailPreview">' . _t($translatableKey, $previewHTML) . '</div>')
|
||||
);
|
||||
|
||||
$formID = ($this->FormID != 0) ? $this->FormID : Session::get('CMSMain.currentPage');
|
||||
@ -1260,6 +1307,79 @@ class UserDefinedForm_EmailRecipient extends DataObject {
|
||||
public function canDelete($member = null) {
|
||||
return $this->Form()->canDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the email template saved against the recipient exists on the file system.
|
||||
*
|
||||
* @param string
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function emailTemplateExists($template = '') {
|
||||
$t = ($template ? $template : $this->EmailTemplate);
|
||||
|
||||
return in_array($t, $this->getEmailTemplateDropdownValues());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the email body for the current email format
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEmailBodyContent() {
|
||||
return $this->SendPlain ? $this->EmailBody : $this->EmailBodyHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of email templates suitable for populating the email template dropdown.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getEmailTemplateDropdownValues() {
|
||||
$templates = array();
|
||||
|
||||
$finder = new SS_FileFinder();
|
||||
$finder->setOption('name_regex', '/^.*\.ss$/');
|
||||
|
||||
$found = $finder->find(BASE_PATH . '/' . UserDefinedForm::config()->email_template_directory);
|
||||
|
||||
foreach ($found as $key => $value) {
|
||||
$template = pathinfo($value);
|
||||
|
||||
$templates[$template['filename']] = $template['filename'];
|
||||
}
|
||||
|
||||
return $templates;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Controller that handles requests to EmailRecipient's
|
||||
*
|
||||
* @package userforms
|
||||
*/
|
||||
class UserDefinedForm_EmailRecipient_ItemRequest extends GridFieldDetailForm_ItemRequest {
|
||||
|
||||
private static $allowed_actions = array(
|
||||
'edit',
|
||||
'view',
|
||||
'ItemEditForm',
|
||||
'preview'
|
||||
);
|
||||
|
||||
public function edit($request) {
|
||||
Requirements::javascript(USERFORMS_DIR . '/javascript/Recipient.js');
|
||||
return parent::edit($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a preview of the recipient email.
|
||||
*/
|
||||
public function preview() {
|
||||
return $this->customise(new ArrayData(array(
|
||||
'Body' => $this->record->getEmailBodyContent()
|
||||
)))->renderWith($this->record->EmailTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -401,6 +401,16 @@ class EditableFormField extends DataObject {
|
||||
public function getFieldConfiguration() {
|
||||
$extraClass = ($this->getSetting('ExtraClass')) ? $this->getSetting('ExtraClass') : '';
|
||||
|
||||
$mergeFieldName = new LiteralField('MergeFieldName', _t('EditableFormField.MERGEFIELDNAME',
|
||||
'<div class="field">' .
|
||||
'<label class="left" for="Fields-6-CustomSettings-RightTitle">Merge field</label>' .
|
||||
'<div class="middleColumn">' .
|
||||
'<p>$' . $this->Name . '</p>' .
|
||||
'<em>Use this to display the field\'s value in email content.</em>' .
|
||||
'</div>' .
|
||||
'</div>'
|
||||
));
|
||||
|
||||
if (is_array(self::$allowed_css) && !empty(self::$allowed_css)) {
|
||||
foreach(self::$allowed_css as $k => $v) {
|
||||
if (!is_array($v)) $cssList[$k]=$v;
|
||||
@ -429,6 +439,7 @@ class EditableFormField extends DataObject {
|
||||
);
|
||||
|
||||
$fields = FieldList::create(
|
||||
$mergeFieldName,
|
||||
$ec,
|
||||
$right
|
||||
);
|
||||
|
BIN
docs/en/_images/mergefield.png
Normal file
BIN
docs/en/_images/mergefield.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
BIN
docs/en/_images/mergefieldcontent.png
Normal file
BIN
docs/en/_images/mergefieldcontent.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 88 KiB |
@ -16,6 +16,7 @@ and without getting involved in any PHP code.
|
||||
* Construct a form using all major form fields (text, email, dropdown, radio, checkbox..)
|
||||
* Ability to extend userforms from other modules to provide extra fields.
|
||||
* Ability to email multiple people the form submission
|
||||
* Custom email templates
|
||||
* View submitted submissions and export them to CSV
|
||||
* Define custom error messages and validation settings
|
||||
* Optionally display and hide fields using javascript based on users input
|
||||
|
@ -18,3 +18,14 @@ Installation can be done either by composer or by manually downloading a release
|
||||
After installation, make sure you rebuild your database through `dev/build`.
|
||||
|
||||
You should see a new PageType in the CMS 'User Defined Form'. This has a new 'Form' tab which has your form builder.
|
||||
|
||||
### Custom email templates
|
||||
|
||||
If you want to use custom email templates set the following config option.
|
||||
|
||||
````
|
||||
UserDefinedForm:
|
||||
email_template_directory: your/template/path/
|
||||
````
|
||||
|
||||
Any SilverStripe templates placed in your `email_template_directory` directory will be available for use with submission emails.
|
||||
|
@ -174,3 +174,17 @@ to determine the size and the number of rows in a text field.
|
||||
**Or perhaps you'd like to add informational content to your form?**
|
||||
|
||||
* Use [HTML Block](#html-block), with the appropriate level [Heading](#heading).
|
||||
|
||||
## Sending emails
|
||||
|
||||
The UserForms module allows you to email form submissions to multiple people.
|
||||
|
||||
### Using form fields in submission emails
|
||||
|
||||
Each form field has a unique merge field located under the field's options.
|
||||
|
||||
![Merge field option](_images/mergefield.png)
|
||||
|
||||
Simply insert the merge field into the email content, and the field's value will be displayed, when the email is sent.
|
||||
|
||||
![Merge field in content](_images/mergefieldcontent.png)
|
||||
|
44
javascript/Recipient.js
Normal file
44
javascript/Recipient.js
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Email recipient behaviour.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
$(document).ready(function () {
|
||||
|
||||
var recipient = {
|
||||
// Some fields are only visible when HTML email are being sent.
|
||||
updateFormatSpecificFields: function () {
|
||||
var sendPlainChecked = $('#SendPlain').find('input[type="checkbox"]').is(':checked');
|
||||
|
||||
// Hide the preview link when 'SendPlain' is selected.
|
||||
$('#EmailPreview')[sendPlainChecked ? 'hide' : 'show']();
|
||||
|
||||
// Hide the template selector when 'SendPlain' is selected.
|
||||
$('#EmailTemplate')[sendPlainChecked ? 'hide' : 'show']();
|
||||
|
||||
// Hide the HTML editor when 'SendPlain' is selected.
|
||||
$('#EmailBodyHtml')[sendPlainChecked ? 'hide' : 'show']();
|
||||
|
||||
// Show the body teaxtarea when 'SendPlain' is selected.
|
||||
$('#EmailBody')[sendPlainChecked ? 'show' : 'hide']();
|
||||
}
|
||||
};
|
||||
|
||||
$.entwine('udf.recipient', function ($) {
|
||||
$('#Form_ItemEditForm').entwine({
|
||||
onmatch: function () {
|
||||
recipient.updateFormatSpecificFields();
|
||||
},
|
||||
onunmatch: function () {
|
||||
this._super();
|
||||
}
|
||||
});
|
||||
|
||||
$('#SendPlain').entwine({
|
||||
onchange: function () {
|
||||
recipient.updateFormatSpecificFields();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}(jQuery));
|
@ -85,6 +85,51 @@ class UserDefinedFormTest extends FunctionalTest {
|
||||
$popup->delete();
|
||||
}
|
||||
|
||||
function testGetEmailBodyContent() {
|
||||
$recipient = new UserDefinedForm_EmailRecipient();
|
||||
|
||||
$emailBody = 'not html';
|
||||
$emailBodyHtml = '<p>html</p>';
|
||||
|
||||
$recipient->EmailBody = $emailBody;
|
||||
$recipient->EmailBodyHtml = $emailBodyHtml;
|
||||
$recipient->write();
|
||||
|
||||
$this->assertEquals($recipient->SendPlain, 0);
|
||||
$this->assertEquals($recipient->getEmailBodyContent(), $emailBodyHtml);
|
||||
|
||||
$recipient->SendPlain = 1;
|
||||
$recipient->write();
|
||||
|
||||
$this->assertEquals($recipient->getEmailBodyContent(), $emailBody);
|
||||
|
||||
$recipient->delete();
|
||||
}
|
||||
|
||||
function testGetEmailTemplateDropdownValues() {
|
||||
$recipient = new UserDefinedForm_EmailRecipient();
|
||||
|
||||
$defaultValues = array('SubmittedFormEmail' => 'SubmittedFormEmail');
|
||||
|
||||
$this->assertEquals($recipient->getEmailTemplateDropdownValues(), $defaultValues);
|
||||
}
|
||||
|
||||
function testEmailTemplateExists() {
|
||||
$recipient = new UserDefinedForm_EmailRecipient();
|
||||
|
||||
// Set the default template
|
||||
$recipient->EmailTemplate = current(array_keys($recipient->getEmailTemplateDropdownValues()));
|
||||
$recipient->write();
|
||||
|
||||
// The default template exists
|
||||
$this->assertTrue($recipient->emailTemplateExists());
|
||||
|
||||
// A made up template doesn't exists
|
||||
$this->assertFalse($recipient->emailTemplateExists('MyTemplateThatsNotThere'));
|
||||
|
||||
$recipient->delete();
|
||||
}
|
||||
|
||||
function testCanEditAndDeleteRecipient() {
|
||||
$form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user