2015-07-24 04:37:48 +02:00
|
|
|
<?php
|
|
|
|
|
2017-08-09 01:55:09 +02:00
|
|
|
namespace SilverStripe\UserForms\Model\Recipient;
|
|
|
|
|
2017-08-11 01:33:06 +02:00
|
|
|
use SilverStripe\Assets\FileFinder;
|
|
|
|
use SilverStripe\CMS\Controllers\CMSMain;
|
|
|
|
use SilverStripe\CMS\Controllers\CMSPageEditController;
|
2018-01-24 03:17:03 +01:00
|
|
|
use SilverStripe\CMS\Model\SiteTree;
|
2017-08-11 01:33:06 +02:00
|
|
|
use SilverStripe\Control\Controller;
|
2017-08-09 01:55:09 +02:00
|
|
|
use SilverStripe\Control\Email\Email;
|
2018-01-24 03:17:03 +01:00
|
|
|
use SilverStripe\Core\Manifest\ModuleResource;
|
|
|
|
use SilverStripe\Core\Manifest\ModuleResourceLoader;
|
2017-08-11 01:33:06 +02:00
|
|
|
use SilverStripe\Forms\CheckboxField;
|
2017-08-09 01:55:09 +02:00
|
|
|
use SilverStripe\Forms\DropdownField;
|
|
|
|
use SilverStripe\Forms\FieldGroup;
|
2017-08-11 01:33:06 +02:00
|
|
|
use SilverStripe\Forms\FieldList;
|
|
|
|
use SilverStripe\Forms\Form;
|
|
|
|
use SilverStripe\Forms\GridField\GridField;
|
|
|
|
use SilverStripe\Forms\GridField\GridFieldButtonRow;
|
|
|
|
use SilverStripe\Forms\GridField\GridFieldConfig;
|
|
|
|
use SilverStripe\Forms\GridField\GridFieldDeleteAction;
|
|
|
|
use SilverStripe\Forms\GridField\GridFieldToolbarHeader;
|
2017-08-09 01:55:09 +02:00
|
|
|
use SilverStripe\Forms\HTMLEditor\HTMLEditorField;
|
|
|
|
use SilverStripe\Forms\LiteralField;
|
2017-08-11 01:33:06 +02:00
|
|
|
use SilverStripe\Forms\TabSet;
|
|
|
|
use SilverStripe\Forms\TextareaField;
|
|
|
|
use SilverStripe\Forms\TextField;
|
|
|
|
use SilverStripe\ORM\ArrayList;
|
2018-02-20 12:29:20 +01:00
|
|
|
use SilverStripe\ORM\DataList;
|
2017-08-09 01:55:09 +02:00
|
|
|
use SilverStripe\ORM\DataObject;
|
2017-10-09 04:05:41 +02:00
|
|
|
use SilverStripe\ORM\DB;
|
2017-08-22 02:15:22 +02:00
|
|
|
use SilverStripe\ORM\FieldType\DBField;
|
2021-02-26 04:13:23 +01:00
|
|
|
use SilverStripe\ORM\HasManyList;
|
2018-02-20 12:29:20 +01:00
|
|
|
use SilverStripe\ORM\ValidationResult;
|
2018-02-20 15:32:14 +01:00
|
|
|
use SilverStripe\Security\Member;
|
2017-08-11 02:36:28 +02:00
|
|
|
use SilverStripe\UserForms\Model\EditableFormField;
|
2018-01-24 03:17:03 +01:00
|
|
|
use SilverStripe\UserForms\Model\EditableFormField\EditableEmailField;
|
2017-08-11 01:33:06 +02:00
|
|
|
use SilverStripe\UserForms\Model\EditableFormField\EditableMultipleOptionField;
|
|
|
|
use SilverStripe\UserForms\Model\EditableFormField\EditableTextField;
|
|
|
|
use SilverStripe\UserForms\Model\UserDefinedForm;
|
2018-02-20 15:32:14 +01:00
|
|
|
use SilverStripe\UserForms\UserForm;
|
2017-08-11 01:33:06 +02:00
|
|
|
use SilverStripe\View\Requirements;
|
|
|
|
use Symbiote\GridFieldExtensions\GridFieldAddNewInlineButton;
|
|
|
|
use Symbiote\GridFieldExtensions\GridFieldEditableColumns;
|
2015-07-24 04:37:48 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A Form can have multiply members / emails to email the submission
|
|
|
|
* to and custom subjects
|
|
|
|
*
|
|
|
|
* @package userforms
|
2021-02-26 04:13:23 +01:00
|
|
|
* @property string $CustomRulesCondition
|
|
|
|
* @property string $EmailAddress
|
|
|
|
* @property string $EmailBody
|
|
|
|
* @property string $EmailBodyHtml
|
|
|
|
* @property string $EmailFrom
|
|
|
|
* @property string $EmailReplyTo
|
|
|
|
* @property string $EmailSubject
|
|
|
|
* @property string $EmailTemplate
|
|
|
|
* @property int $FormID
|
|
|
|
* @property int $HideFromData
|
|
|
|
* @property int $SendPlain
|
|
|
|
* @property int $SendEmailFromFieldID
|
|
|
|
* @property int $SendEmailSubjectFieldID
|
|
|
|
* @property int $SendEmailToFieldID
|
2023-12-15 05:04:35 +01:00
|
|
|
* @method HasManyList<EmailRecipientCondition> CustomRules()
|
2021-02-26 04:13:23 +01:00
|
|
|
* @method DataObject Form()
|
|
|
|
* @method EditableFormField SendEmailFromField()
|
|
|
|
* @method EditableFormField SendEmailSubjectField()
|
|
|
|
* @method EditableFormField SendEmailToField()
|
2015-07-24 04:37:48 +02:00
|
|
|
*/
|
2017-08-11 01:33:06 +02:00
|
|
|
class EmailRecipient extends DataObject
|
2016-07-21 07:53:59 +02:00
|
|
|
{
|
2017-08-11 01:33:06 +02:00
|
|
|
private static $db = [
|
2016-07-21 07:53:59 +02:00
|
|
|
'EmailAddress' => 'Varchar(200)',
|
|
|
|
'EmailSubject' => 'Varchar(200)',
|
|
|
|
'EmailFrom' => 'Varchar(200)',
|
|
|
|
'EmailReplyTo' => 'Varchar(200)',
|
|
|
|
'EmailBody' => 'Text',
|
|
|
|
'EmailBodyHtml' => 'HTMLText',
|
|
|
|
'EmailTemplate' => 'Varchar',
|
|
|
|
'SendPlain' => 'Boolean',
|
|
|
|
'HideFormData' => 'Boolean',
|
2022-03-07 01:02:34 +01:00
|
|
|
'HideInvisibleFields' => 'Boolean',
|
2016-07-21 07:53:59 +02:00
|
|
|
'CustomRulesCondition' => 'Enum("And,Or")'
|
2017-08-11 01:33:06 +02:00
|
|
|
];
|
2016-07-21 07:53:59 +02:00
|
|
|
|
2017-08-11 01:33:06 +02:00
|
|
|
private static $has_one = [
|
2018-02-14 16:02:27 +01:00
|
|
|
'Form' => DataObject::class,
|
2017-08-09 01:55:09 +02:00
|
|
|
'SendEmailFromField' => EditableFormField::class,
|
|
|
|
'SendEmailToField' => EditableFormField::class,
|
|
|
|
'SendEmailSubjectField' => EditableFormField::class
|
2017-08-11 01:33:06 +02:00
|
|
|
];
|
2016-07-21 07:53:59 +02:00
|
|
|
|
2017-08-11 01:33:06 +02:00
|
|
|
private static $has_many = [
|
2017-08-15 05:30:59 +02:00
|
|
|
'CustomRules' => EmailRecipientCondition::class,
|
|
|
|
];
|
|
|
|
|
|
|
|
private static $owns = [
|
|
|
|
'CustomRules',
|
|
|
|
];
|
|
|
|
|
2018-02-20 12:29:20 +01:00
|
|
|
private static $cascade_deletes = [
|
2017-08-15 05:30:59 +02:00
|
|
|
'CustomRules',
|
2017-08-11 01:33:06 +02:00
|
|
|
];
|
2016-07-21 07:53:59 +02:00
|
|
|
|
2017-08-11 01:33:06 +02:00
|
|
|
private static $summary_fields = [
|
2016-07-21 07:53:59 +02:00
|
|
|
'EmailAddress',
|
|
|
|
'EmailSubject',
|
|
|
|
'EmailFrom'
|
2017-08-11 01:33:06 +02:00
|
|
|
];
|
|
|
|
|
|
|
|
private static $table_name = 'UserDefinedForm_EmailRecipient';
|
2016-07-21 07:53:59 +02:00
|
|
|
|
2018-03-22 23:10:13 +01:00
|
|
|
/**
|
|
|
|
* Disable versioned GridField to ensure that it doesn't interfere with {@link UserFormRecipientItemRequest}
|
|
|
|
*
|
|
|
|
* {@inheritDoc}
|
|
|
|
*/
|
|
|
|
private static $versioned_gridfield_extensions = false;
|
|
|
|
|
2016-07-21 07:53:59 +02:00
|
|
|
/**
|
|
|
|
* Setting this to true will allow you to select "risky" fields as
|
|
|
|
* email recipient, such as free-text entry fields.
|
|
|
|
*
|
|
|
|
* It's advisable to leave this off.
|
|
|
|
*
|
|
|
|
* @config
|
|
|
|
* @var bool
|
|
|
|
*/
|
|
|
|
private static $allow_unbound_recipient_fields = false;
|
|
|
|
|
2017-10-09 04:05:41 +02:00
|
|
|
public function requireDefaultRecords()
|
|
|
|
{
|
|
|
|
parent::requireDefaultRecords();
|
|
|
|
|
|
|
|
// make sure to migrate the class across (prior to v5.x)
|
2018-08-21 05:04:51 +02:00
|
|
|
DB::query("UPDATE \"UserDefinedForm_EmailRecipient\" SET \"FormClass\" = 'Page' WHERE \"FormClass\" IS NULL");
|
2017-10-09 04:05:41 +02:00
|
|
|
}
|
|
|
|
|
2020-07-14 06:41:36 +02:00
|
|
|
public function onBeforeWrite()
|
|
|
|
{
|
|
|
|
parent::onBeforeWrite();
|
|
|
|
|
|
|
|
// email addresses have trim() applied to them during validation for a slightly nicer UX
|
|
|
|
// apply trim() here too before saving to the database
|
2022-04-13 03:52:56 +02:00
|
|
|
$this->EmailAddress = trim($this->EmailAddress ?? '');
|
|
|
|
$this->EmailFrom = trim($this->EmailFrom ?? '');
|
|
|
|
$this->EmailReplyTo = trim($this->EmailReplyTo ?? '');
|
2020-07-14 06:41:36 +02:00
|
|
|
}
|
|
|
|
|
2016-07-21 07:53:59 +02:00
|
|
|
public function summaryFields()
|
|
|
|
{
|
|
|
|
$fields = parent::summaryFields();
|
|
|
|
if (isset($fields['EmailAddress'])) {
|
2017-10-25 23:00:02 +02:00
|
|
|
$fields['EmailAddress'] = _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILADDRESS', 'Email');
|
2016-07-21 07:53:59 +02:00
|
|
|
}
|
|
|
|
if (isset($fields['EmailSubject'])) {
|
2017-08-11 01:33:06 +02:00
|
|
|
$fields['EmailSubject'] = _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILSUBJECT', 'Subject');
|
2016-07-21 07:53:59 +02:00
|
|
|
}
|
|
|
|
if (isset($fields['EmailFrom'])) {
|
2017-08-11 01:33:06 +02:00
|
|
|
$fields['EmailFrom'] = _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILFROM', 'From');
|
2016-07-21 07:53:59 +02:00
|
|
|
}
|
|
|
|
return $fields;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-02-20 12:29:20 +01:00
|
|
|
* Get instance of UserForm when editing in getCMSFields
|
2016-07-21 07:53:59 +02:00
|
|
|
*
|
2018-03-19 03:09:13 +01:00
|
|
|
* @return UserDefinedForm|UserForm|null
|
2016-07-21 07:53:59 +02:00
|
|
|
*/
|
|
|
|
protected function getFormParent()
|
|
|
|
{
|
2018-03-19 03:09:13 +01:00
|
|
|
// If polymorphic relationship is actually defined, use it
|
|
|
|
if ($this->FormID && $this->FormClass) {
|
|
|
|
$formClass = $this->FormClass;
|
|
|
|
return $formClass::get()->byID($this->FormID);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Revert to checking for a form from the session
|
2023-10-11 01:02:23 +02:00
|
|
|
// LeftAndMain::sessionNamespace is protected.
|
2018-02-13 15:39:37 +01:00
|
|
|
$sessionNamespace = $this->config()->get('session_namespace') ?: CMSMain::class;
|
2017-09-04 06:56:42 +02:00
|
|
|
|
2018-03-19 03:09:13 +01:00
|
|
|
$formID = Controller::curr()->getRequest()->getSession()->get($sessionNamespace . '.currentPage');
|
|
|
|
if ($formID) {
|
|
|
|
return UserDefinedForm::get()->byID($formID);
|
|
|
|
}
|
2016-07-21 07:53:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function getTitle()
|
|
|
|
{
|
|
|
|
if ($this->EmailAddress) {
|
|
|
|
return $this->EmailAddress;
|
|
|
|
}
|
|
|
|
if ($this->EmailSubject) {
|
|
|
|
return $this->EmailSubject;
|
|
|
|
}
|
|
|
|
return parent::getTitle();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generate a gridfield config for editing filter rules
|
|
|
|
*
|
|
|
|
* @return GridFieldConfig
|
|
|
|
*/
|
|
|
|
protected function getRulesConfig()
|
|
|
|
{
|
2018-02-20 12:29:20 +01:00
|
|
|
if (!$this->getFormParent()) {
|
|
|
|
return null;
|
|
|
|
}
|
2016-07-21 07:53:59 +02:00
|
|
|
$formFields = $this->getFormParent()->Fields();
|
|
|
|
|
|
|
|
$config = GridFieldConfig::create()
|
|
|
|
->addComponents(
|
|
|
|
new GridFieldButtonRow('before'),
|
|
|
|
new GridFieldToolbarHeader(),
|
|
|
|
new GridFieldAddNewInlineButton(),
|
|
|
|
new GridFieldDeleteAction(),
|
|
|
|
$columns = new GridFieldEditableColumns()
|
|
|
|
);
|
|
|
|
|
|
|
|
$columns->setDisplayFields(array(
|
|
|
|
'ConditionFieldID' => function ($record, $column, $grid) use ($formFields) {
|
|
|
|
return DropdownField::create($column, false, $formFields->map('ID', 'Title'));
|
|
|
|
},
|
|
|
|
'ConditionOption' => function ($record, $column, $grid) {
|
2017-08-11 01:33:06 +02:00
|
|
|
$options = EmailRecipientCondition::config()->condition_options;
|
2016-07-21 07:53:59 +02:00
|
|
|
return DropdownField::create($column, false, $options);
|
|
|
|
},
|
|
|
|
'ConditionValue' => function ($record, $column, $grid) {
|
|
|
|
return TextField::create($column);
|
|
|
|
}
|
|
|
|
));
|
|
|
|
|
|
|
|
return $config;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return FieldList
|
|
|
|
*/
|
|
|
|
public function getCMSFields()
|
|
|
|
{
|
2017-10-18 11:02:49 +02:00
|
|
|
Requirements::javascript('silverstripe/userforms:client/dist/js/userforms-cms.js');
|
2016-07-21 07:53:59 +02:00
|
|
|
|
|
|
|
// Build fieldlist
|
|
|
|
$fields = FieldList::create(Tabset::create('Root')->addExtraClass('EmailRecipientForm'));
|
|
|
|
|
2018-02-20 15:32:14 +01:00
|
|
|
if (!$this->getFormParent()) {
|
|
|
|
$fields->addFieldToTab('Root.EmailDetails', $this->getUnsavedFormLiteralField());
|
|
|
|
}
|
|
|
|
|
2016-07-21 07:53:59 +02:00
|
|
|
// Configuration fields
|
2017-08-11 01:33:06 +02:00
|
|
|
$fields->addFieldsToTab('Root.EmailDetails', [
|
2018-02-20 12:29:20 +01:00
|
|
|
$this->getSubjectCMSFields(),
|
|
|
|
$this->getEmailToCMSFields(),
|
|
|
|
$this->getEmailFromCMSFields(),
|
|
|
|
$this->getEmailReplyToCMSFields(),
|
2017-08-11 01:33:06 +02:00
|
|
|
]);
|
2018-02-20 15:32:14 +01:00
|
|
|
|
2018-02-20 12:29:20 +01:00
|
|
|
$fields->fieldByName('Root.EmailDetails')->setTitle(_t(__CLASS__ . '.EMAILDETAILSTAB', 'Email Details'));
|
2016-07-21 07:53:59 +02:00
|
|
|
|
|
|
|
// Only show the preview link if the recipient has been saved.
|
|
|
|
if (!empty($this->EmailTemplate)) {
|
2019-05-17 05:51:11 +02:00
|
|
|
$request = Controller::curr()->getRequest();
|
|
|
|
|
2017-08-24 05:15:36 +02:00
|
|
|
$pageEditController = singleton(CMSPageEditController::class);
|
2019-05-17 05:51:11 +02:00
|
|
|
$pageEditController->getRequest()->setSession($request->getSession());
|
2017-08-24 05:15:36 +02:00
|
|
|
|
2019-05-17 05:51:11 +02:00
|
|
|
$currentUrl = $request->getURL();
|
2018-09-07 10:45:11 +02:00
|
|
|
// If used in a regular page context, will have "/edit" on the end, if used in a trait context
|
2019-05-17 05:51:11 +02:00
|
|
|
// it won't. Strip that off in case. It may also have "ItemEditForm" on the end instead if this is
|
|
|
|
// an AJAX request, e.g. saving a GridFieldDetailForm
|
|
|
|
$remove = ['/edit', '/ItemEditForm'];
|
|
|
|
foreach ($remove as $badSuffix) {
|
2022-04-13 03:52:56 +02:00
|
|
|
$badSuffixLength = strlen($badSuffix ?? '');
|
|
|
|
if (substr($currentUrl ?? '', -$badSuffixLength) === $badSuffix) {
|
|
|
|
$currentUrl = substr($currentUrl ?? '', 0, -$badSuffixLength);
|
2019-05-17 05:51:11 +02:00
|
|
|
}
|
2018-09-07 10:45:11 +02:00
|
|
|
}
|
|
|
|
$previewUrl = Controller::join_links($currentUrl, 'preview');
|
|
|
|
|
2016-07-21 07:53:59 +02:00
|
|
|
$preview = sprintf(
|
2017-08-24 05:17:16 +02:00
|
|
|
'<p><a href="%s" target="_blank" class="btn btn-outline-secondary">%s</a></p><em>%s</em>',
|
2018-09-07 10:45:11 +02:00
|
|
|
$previewUrl,
|
2017-08-11 01:33:06 +02:00
|
|
|
_t('SilverStripe\\UserForms\\Model\\UserDefinedForm.PREVIEW_EMAIL', 'Preview email'),
|
|
|
|
_t(
|
|
|
|
'SilverStripe\\UserForms\\Model\\UserDefinedForm.PREVIEW_EMAIL_DESCRIPTION',
|
|
|
|
'Note: Unsaved changes will not appear in the preview.'
|
|
|
|
)
|
2016-07-21 07:53:59 +02:00
|
|
|
);
|
|
|
|
} else {
|
|
|
|
$preview = sprintf(
|
2018-02-20 15:32:14 +01:00
|
|
|
'<p class="alert alert-warning">%s</p>',
|
2016-07-21 07:53:59 +02:00
|
|
|
_t(
|
2017-08-11 01:33:06 +02:00
|
|
|
'SilverStripe\\UserForms\\Model\\UserDefinedForm.PREVIEW_EMAIL_UNAVAILABLE',
|
2016-07-21 07:53:59 +02:00
|
|
|
'You can preview this email once you have saved the Recipient.'
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Email templates
|
2017-08-11 01:33:06 +02:00
|
|
|
$fields->addFieldsToTab('Root.EmailContent', [
|
|
|
|
CheckboxField::create(
|
|
|
|
'HideFormData',
|
|
|
|
_t('SilverStripe\\UserForms\\Model\\UserDefinedForm.HIDEFORMDATA', 'Hide form data from email?')
|
|
|
|
),
|
2022-03-07 01:02:34 +01:00
|
|
|
CheckboxField::create(
|
|
|
|
'HideInvisibleFields',
|
|
|
|
_t('SilverStripe\\UserForms\\Model\\UserDefinedForm.HIDEINVISIBLEFIELDS', 'Hide invisible fields from email?')
|
|
|
|
),
|
2016-07-21 07:53:59 +02:00
|
|
|
CheckboxField::create(
|
|
|
|
'SendPlain',
|
2017-08-11 01:33:06 +02:00
|
|
|
_t(
|
|
|
|
'SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDPLAIN',
|
|
|
|
'Send email as plain text? (HTML will be stripped)'
|
|
|
|
)
|
2016-07-21 07:53:59 +02:00
|
|
|
),
|
2017-08-11 01:33:06 +02:00
|
|
|
HTMLEditorField::create(
|
|
|
|
'EmailBodyHtml',
|
|
|
|
_t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILBODYHTML', 'Body')
|
|
|
|
)
|
2016-07-21 07:53:59 +02:00
|
|
|
->addExtraClass('toggle-html-only'),
|
2017-08-11 01:33:06 +02:00
|
|
|
TextareaField::create(
|
|
|
|
'EmailBody',
|
|
|
|
_t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILBODY', 'Body')
|
|
|
|
)
|
2016-07-21 07:53:59 +02:00
|
|
|
->addExtraClass('toggle-plain-only'),
|
2017-06-09 01:04:52 +02:00
|
|
|
LiteralField::create('EmailPreview', $preview)
|
2017-08-22 01:30:37 +02:00
|
|
|
]);
|
2017-06-09 00:38:49 +02:00
|
|
|
|
2017-10-21 20:47:17 +02:00
|
|
|
$templates = $this->getEmailTemplateDropdownValues();
|
|
|
|
|
|
|
|
if ($templates) {
|
|
|
|
$fields->insertBefore(
|
2022-11-28 21:36:08 +01:00
|
|
|
'EmailBodyHtml',
|
2017-10-21 20:47:17 +02:00
|
|
|
DropdownField::create(
|
|
|
|
'EmailTemplate',
|
2017-12-04 11:42:58 +01:00
|
|
|
_t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILTEMPLATE', 'Email template'),
|
|
|
|
$templates
|
2022-11-28 21:36:08 +01:00
|
|
|
)->addExtraClass('toggle-html-only')
|
2017-10-21 20:47:17 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-02-20 12:29:20 +01:00
|
|
|
$fields->fieldByName('Root.EmailContent')->setTitle(_t(__CLASS__ . '.EMAILCONTENTTAB', 'Email Content'));
|
2016-07-21 07:53:59 +02:00
|
|
|
|
|
|
|
// Custom rules for sending this field
|
2017-08-11 01:33:06 +02:00
|
|
|
$grid = GridField::create(
|
|
|
|
'CustomRules',
|
|
|
|
_t('SilverStripe\\UserForms\\Model\\EditableFormField.CUSTOMRULES', 'Custom Rules'),
|
2016-07-21 07:53:59 +02:00
|
|
|
$this->CustomRules(),
|
|
|
|
$this->getRulesConfig()
|
|
|
|
);
|
|
|
|
$grid->setDescription(_t(
|
2017-08-11 01:33:06 +02:00
|
|
|
'SilverStripe\\UserForms\\Model\\UserDefinedForm.RulesDescription',
|
2018-02-20 15:32:14 +01:00
|
|
|
'Emails will only be sent to the recipient if the custom rules are met. If no rules are defined, '
|
|
|
|
. 'this recipient will receive notifications for every submission.'
|
2016-07-21 07:53:59 +02:00
|
|
|
));
|
2018-02-20 15:32:14 +01:00
|
|
|
|
2017-08-11 01:33:06 +02:00
|
|
|
$fields->addFieldsToTab('Root.CustomRules', [
|
|
|
|
DropdownField::create(
|
2016-07-21 07:53:59 +02:00
|
|
|
'CustomRulesCondition',
|
2017-08-11 01:33:06 +02:00
|
|
|
_t('SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDIF', 'Send condition'),
|
|
|
|
[
|
2018-02-20 12:29:20 +01:00
|
|
|
'Or' => _t(
|
|
|
|
'SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDIFOR',
|
|
|
|
'Any conditions are true'
|
|
|
|
),
|
|
|
|
'And' => _t(
|
|
|
|
'SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDIFAND',
|
|
|
|
'All conditions are true'
|
|
|
|
)
|
2017-08-11 01:33:06 +02:00
|
|
|
]
|
2016-07-21 07:53:59 +02:00
|
|
|
),
|
|
|
|
$grid
|
2017-08-11 01:33:06 +02:00
|
|
|
]);
|
2017-06-09 00:38:49 +02:00
|
|
|
|
2018-02-20 15:32:14 +01:00
|
|
|
$fields->fieldByName('Root.CustomRules')->setTitle(_t(__CLASS__ . '.CUSTOMRULESTAB', 'Custom Rules'));
|
2016-07-21 07:53:59 +02:00
|
|
|
|
|
|
|
$this->extend('updateCMSFields', $fields);
|
|
|
|
return $fields;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return whether a user can create an object of this type
|
|
|
|
*
|
2015-12-22 23:14:36 +01:00
|
|
|
* @param Member $member
|
|
|
|
* @param array $context Virtual parameter to allow context to be passed in to check
|
2016-07-21 07:53:59 +02:00
|
|
|
* @return bool
|
|
|
|
*/
|
2017-08-11 02:36:28 +02:00
|
|
|
public function canCreate($member = null, $context = [])
|
2016-07-21 07:53:59 +02:00
|
|
|
{
|
|
|
|
// Check parent page
|
2015-12-22 23:14:36 +01:00
|
|
|
$parent = $this->getCanCreateContext(func_get_args());
|
2016-07-21 07:53:59 +02:00
|
|
|
if ($parent) {
|
2015-12-22 23:14:36 +01:00
|
|
|
return $parent->canEdit($member);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fall back to secure admin permissions
|
|
|
|
return parent::canCreate($member);
|
2016-07-21 07:53:59 +02:00
|
|
|
}
|
2015-07-24 04:37:48 +02:00
|
|
|
|
2015-12-22 23:14:36 +01:00
|
|
|
/**
|
|
|
|
* Helper method to check the parent for this object
|
|
|
|
*
|
|
|
|
* @param array $args List of arguments passed to canCreate
|
|
|
|
* @return SiteTree Parent page instance
|
|
|
|
*/
|
2016-07-21 07:53:59 +02:00
|
|
|
protected function getCanCreateContext($args)
|
|
|
|
{
|
2015-12-22 23:14:36 +01:00
|
|
|
// Inspect second parameter to canCreate for a 'Parent' context
|
2017-08-09 01:55:09 +02:00
|
|
|
if (isset($args[1][Form::class])) {
|
|
|
|
return $args[1][Form::class];
|
2015-12-22 23:14:36 +01:00
|
|
|
}
|
|
|
|
// Hack in currently edited page if context is missing
|
2016-07-21 07:53:59 +02:00
|
|
|
if (Controller::has_curr() && Controller::curr() instanceof CMSMain) {
|
2015-12-22 23:14:36 +01:00
|
|
|
return Controller::curr()->currentPage();
|
|
|
|
}
|
|
|
|
|
|
|
|
// No page being edited
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2016-07-21 07:53:59 +02:00
|
|
|
public function canView($member = null)
|
|
|
|
{
|
2018-02-13 15:39:37 +01:00
|
|
|
if ($form = $this->getFormParent()) {
|
2017-10-16 03:24:51 +02:00
|
|
|
return $form->canView($member);
|
|
|
|
}
|
|
|
|
return parent::canView($member);
|
2016-07-21 07:53:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function canEdit($member = null)
|
|
|
|
{
|
2018-02-13 15:39:37 +01:00
|
|
|
if ($form = $this->getFormParent()) {
|
2017-10-16 03:24:51 +02:00
|
|
|
return $form->canEdit($member);
|
|
|
|
}
|
|
|
|
|
|
|
|
return parent::canEdit($member);
|
2016-07-21 07:53:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param Member
|
|
|
|
*
|
|
|
|
* @return boolean
|
|
|
|
*/
|
|
|
|
public function canDelete($member = null)
|
|
|
|
{
|
|
|
|
return $this->canEdit($member);
|
|
|
|
}
|
|
|
|
|
2017-10-16 03:24:51 +02:00
|
|
|
/**
|
2016-07-21 07:53:59 +02:00
|
|
|
* Determine if this recipient may receive notifications for this submission
|
|
|
|
*
|
|
|
|
* @param array $data
|
|
|
|
* @param Form $form
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public function canSend($data, $form)
|
|
|
|
{
|
|
|
|
// Skip if no rules configured
|
|
|
|
$customRules = $this->CustomRules();
|
|
|
|
if (!$customRules->count()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check all rules
|
|
|
|
$isAnd = $this->CustomRulesCondition === 'And';
|
|
|
|
foreach ($customRules as $customRule) {
|
2017-05-15 08:03:51 +02:00
|
|
|
$matches = $customRule->matches($data);
|
2016-07-21 07:53:59 +02:00
|
|
|
if ($isAnd && !$matches) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!$isAnd && $matches) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Once all rules are checked
|
|
|
|
return $isAnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
|
2017-12-04 11:42:58 +01:00
|
|
|
return array_key_exists($t, (array) $this->getEmailTemplateDropdownValues());
|
2016-07-21 07:53:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the email body for the current email format
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function getEmailBodyContent()
|
|
|
|
{
|
2017-06-09 00:38:49 +02:00
|
|
|
if ($this->SendPlain) {
|
2017-08-22 02:15:22 +02:00
|
|
|
return DBField::create_field('HTMLText', $this->EmailBody)->Plain();
|
2017-06-09 00:38:49 +02:00
|
|
|
}
|
2017-08-24 05:15:36 +02:00
|
|
|
return DBField::create_field('HTMLText', $this->EmailBodyHtml);
|
2016-07-21 07:53:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets a list of email templates suitable for populating the email template dropdown.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function getEmailTemplateDropdownValues()
|
|
|
|
{
|
2017-08-11 01:33:06 +02:00
|
|
|
$templates = [];
|
2016-07-21 07:53:59 +02:00
|
|
|
|
2017-08-09 01:55:09 +02:00
|
|
|
$finder = new FileFinder();
|
2016-07-21 07:53:59 +02:00
|
|
|
$finder->setOption('name_regex', '/^.*\.ss$/');
|
|
|
|
|
2017-10-21 20:47:17 +02:00
|
|
|
$parent = $this->getFormParent();
|
|
|
|
|
|
|
|
if (!$parent) {
|
|
|
|
return [];
|
2017-08-16 01:57:50 +02:00
|
|
|
}
|
2017-10-21 20:47:17 +02:00
|
|
|
|
2018-01-24 03:17:03 +01:00
|
|
|
$emailTemplateDirectory = $parent->config()->get('email_template_directory');
|
|
|
|
$templateDirectory = ModuleResourceLoader::resourcePath($emailTemplateDirectory);
|
2017-10-21 20:47:17 +02:00
|
|
|
|
|
|
|
if (!$templateDirectory) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
2017-08-24 05:15:36 +02:00
|
|
|
$found = $finder->find(BASE_PATH . DIRECTORY_SEPARATOR . $templateDirectory);
|
2016-07-21 07:53:59 +02:00
|
|
|
|
|
|
|
foreach ($found as $key => $value) {
|
2022-04-13 03:52:56 +02:00
|
|
|
$template = pathinfo($value ?? '');
|
2018-01-24 03:17:03 +01:00
|
|
|
$absoluteFilename = $template['dirname'] . DIRECTORY_SEPARATOR . $template['filename'];
|
|
|
|
|
|
|
|
// Optionally remove vendor/ path prefixes
|
|
|
|
$resource = ModuleResourceLoader::singleton()->resolveResource($emailTemplateDirectory);
|
|
|
|
if ($resource instanceof ModuleResource && $resource->getModule()) {
|
|
|
|
$prefixToStrip = $resource->getModule()->getPath();
|
|
|
|
} else {
|
|
|
|
$prefixToStrip = BASE_PATH;
|
|
|
|
}
|
2022-04-13 03:52:56 +02:00
|
|
|
$templatePath = substr($absoluteFilename ?? '', strlen($prefixToStrip ?? '') + 1);
|
2018-01-24 03:17:03 +01:00
|
|
|
|
2021-02-09 23:52:15 +01:00
|
|
|
// Optionally remove "templates/" ("templates\" on Windows respectively) prefixes
|
2022-04-13 03:52:56 +02:00
|
|
|
if (preg_match('#(?<=templates' . preg_quote(DIRECTORY_SEPARATOR, '#') . ').*$#', $templatePath ?? '', $matches)) {
|
2018-11-18 02:08:53 +01:00
|
|
|
$templatePath = $matches[0];
|
2018-01-24 03:17:03 +01:00
|
|
|
}
|
2016-07-21 07:53:59 +02:00
|
|
|
|
2017-08-24 05:15:36 +02:00
|
|
|
$templates[$templatePath] = $template['filename'];
|
2016-07-21 07:53:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return $templates;
|
|
|
|
}
|
2017-01-08 23:06:17 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Validate that valid email addresses are being used
|
|
|
|
*
|
|
|
|
* @return ValidationResult
|
|
|
|
*/
|
2017-08-11 02:37:03 +02:00
|
|
|
public function validate()
|
|
|
|
{
|
2017-01-08 23:06:17 +01:00
|
|
|
$result = parent::validate();
|
2017-08-11 01:33:06 +02:00
|
|
|
$checkEmail = [
|
2017-01-08 23:06:17 +01:00
|
|
|
'EmailAddress' => 'EMAILADDRESSINVALID',
|
|
|
|
'EmailFrom' => 'EMAILFROMINVALID',
|
2017-07-20 11:40:34 +02:00
|
|
|
'EmailReplyTo' => 'EMAILREPLYTOINVALID',
|
2017-08-11 01:33:06 +02:00
|
|
|
];
|
2017-01-08 23:06:17 +01:00
|
|
|
foreach ($checkEmail as $check => $translation) {
|
2017-07-20 11:40:34 +02:00
|
|
|
if ($this->$check) {
|
2017-01-08 23:06:17 +01:00
|
|
|
//may be a comma separated list of emails
|
2022-04-13 03:52:56 +02:00
|
|
|
$addresses = explode(',', $this->$check ?? '');
|
2017-01-08 23:06:17 +01:00
|
|
|
foreach ($addresses as $address) {
|
2022-04-13 03:52:56 +02:00
|
|
|
$trimAddress = trim($address ?? '');
|
2017-07-20 11:40:34 +02:00
|
|
|
if ($trimAddress && !Email::is_valid_address($trimAddress)) {
|
2017-08-11 02:37:03 +02:00
|
|
|
$error = _t(
|
2017-08-13 23:26:53 +02:00
|
|
|
__CLASS__.".$translation",
|
2017-08-11 02:37:03 +02:00
|
|
|
"Invalid email address $trimAddress"
|
|
|
|
);
|
2017-08-14 00:52:48 +02:00
|
|
|
$result->addError($error . " ($trimAddress)");
|
2017-01-08 23:06:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-02-13 17:24:53 +01:00
|
|
|
|
|
|
|
// if there is no from address and no fallback, you'll have errors if this isn't defined
|
2018-02-13 18:21:03 +01:00
|
|
|
if (!$this->EmailFrom && empty(Email::getSendAllEmailsFrom()) && empty(Email::config()->get('admin_email'))) {
|
2018-02-13 17:24:53 +01:00
|
|
|
$result->addError(_t(__CLASS__.".EMAILFROMREQUIRED", '"Email From" address is required'));
|
|
|
|
}
|
2019-05-03 05:55:59 +02:00
|
|
|
|
|
|
|
// Sending will also fail if there's no recipient defined
|
|
|
|
if (!$this->EmailAddress && !$this->SendEmailToFieldID) {
|
|
|
|
$result->addError(_t(__CLASS__.".EMAILTOREQUIRED", '"Send email to" address or field is required'));
|
|
|
|
}
|
|
|
|
|
2017-01-08 23:06:17 +01:00
|
|
|
return $result;
|
|
|
|
}
|
2018-02-20 12:29:20 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @return FieldGroup|TextField
|
|
|
|
*/
|
|
|
|
protected function getSubjectCMSFields()
|
|
|
|
{
|
|
|
|
$subjectTextField = TextField::create(
|
|
|
|
'EmailSubject',
|
|
|
|
_t('SilverStripe\\UserForms\\Model\\UserDefinedForm.TYPESUBJECT', 'Type subject')
|
|
|
|
)
|
|
|
|
->setAttribute('style', 'min-width: 400px;');
|
|
|
|
|
|
|
|
if ($this->getFormParent() && $this->getValidSubjectFields()) {
|
|
|
|
return FieldGroup::create(
|
|
|
|
$subjectTextField,
|
|
|
|
DropdownField::create(
|
|
|
|
'SendEmailSubjectFieldID',
|
|
|
|
_t(
|
|
|
|
'SilverStripe\\UserForms\\Model\\UserDefinedForm.SELECTAFIELDTOSETSUBJECT',
|
|
|
|
'.. or select a field to use as the subject'
|
|
|
|
),
|
|
|
|
$this->getValidSubjectFields()->map('ID', 'Title')
|
|
|
|
)->setEmptyString('')
|
|
|
|
)
|
|
|
|
->setTitle(_t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILSUBJECT', 'Email subject'));
|
|
|
|
} else {
|
|
|
|
return $subjectTextField;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return FieldGroup|TextField
|
|
|
|
*/
|
|
|
|
protected function getEmailToCMSFields()
|
|
|
|
{
|
|
|
|
$emailToTextField = TextField::create(
|
|
|
|
'EmailAddress',
|
|
|
|
_t('SilverStripe\\UserForms\\Model\\UserDefinedForm.TYPETO', 'Type to address')
|
|
|
|
)
|
|
|
|
->setAttribute('style', 'min-width: 400px;');
|
|
|
|
|
|
|
|
if ($this->getFormParent() && $this->getValidEmailToFields()) {
|
|
|
|
return FieldGroup::create(
|
|
|
|
$emailToTextField,
|
|
|
|
DropdownField::create(
|
|
|
|
'SendEmailToFieldID',
|
|
|
|
_t(
|
|
|
|
'SilverStripe\\UserForms\\Model\\UserDefinedForm.ORSELECTAFIELDTOUSEASTO',
|
|
|
|
'.. or select a field to use as the to address'
|
|
|
|
),
|
|
|
|
$this->getValidEmailToFields()->map('ID', 'Title')
|
|
|
|
)->setEmptyString(' ')
|
|
|
|
)
|
|
|
|
->setTitle(_t('SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDEMAILTO', 'Send email to'))
|
|
|
|
->setDescription(_t(
|
|
|
|
'SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDEMAILTO_DESCRIPTION',
|
|
|
|
'You may enter multiple email addresses as a comma separated list.'
|
|
|
|
));
|
|
|
|
} else {
|
|
|
|
return $emailToTextField;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return TextField
|
|
|
|
*/
|
|
|
|
protected function getEmailFromCMSFields()
|
|
|
|
{
|
|
|
|
return TextField::create(
|
|
|
|
'EmailFrom',
|
|
|
|
_t('SilverStripe\\UserForms\\Model\\UserDefinedForm.FROMADDRESS', 'Send email from')
|
|
|
|
)
|
|
|
|
->setDescription(_t(
|
|
|
|
'SilverStripe\\UserForms\\Model\\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."
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return FieldGroup|TextField
|
|
|
|
*/
|
|
|
|
protected function getEmailReplyToCMSFields()
|
|
|
|
{
|
|
|
|
$replyToTextField = TextField::create('EmailReplyTo', _t(
|
|
|
|
'SilverStripe\\UserForms\\Model\\UserDefinedForm.TYPEREPLY',
|
|
|
|
'Type reply address'
|
|
|
|
))
|
|
|
|
->setAttribute('style', 'min-width: 400px;');
|
|
|
|
if ($this->getFormParent() && $this->getValidEmailFromFields()) {
|
|
|
|
return FieldGroup::create(
|
|
|
|
$replyToTextField,
|
|
|
|
DropdownField::create(
|
|
|
|
'SendEmailFromFieldID',
|
|
|
|
_t(
|
|
|
|
'SilverStripe\\UserForms\\Model\\UserDefinedForm.ORSELECTAFIELDTOUSEASFROM',
|
|
|
|
'.. or select a field to use as reply to address'
|
|
|
|
),
|
|
|
|
$this->getValidEmailFromFields()->map('ID', 'Title')
|
|
|
|
)->setEmptyString(' ')
|
|
|
|
)
|
|
|
|
->setTitle(_t(
|
|
|
|
'SilverStripe\\UserForms\\Model\\UserDefinedForm.REPLYADDRESS',
|
|
|
|
'Email for reply to'
|
|
|
|
))
|
|
|
|
->setDescription(_t(
|
|
|
|
'SilverStripe\\UserForms\\Model\\UserDefinedForm.REPLYADDRESS_DESCRIPTION',
|
|
|
|
'The email address which the recipient is able to \'reply\' to.'
|
|
|
|
));
|
|
|
|
} else {
|
|
|
|
return $replyToTextField;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-01-18 22:29:08 +01:00
|
|
|
* @return DataList<EditableMultipleOptionField>|null
|
2018-02-20 12:29:20 +01:00
|
|
|
*/
|
|
|
|
protected function getMultiOptionFields()
|
|
|
|
{
|
|
|
|
if (!$form = $this->getFormParent()) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return EditableMultipleOptionField::get()->filter('ParentID', $form->ID);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-01-18 22:29:08 +01:00
|
|
|
* @return ArrayList<EditableFormField>|null
|
2018-02-20 12:29:20 +01:00
|
|
|
*/
|
|
|
|
protected function getValidSubjectFields()
|
|
|
|
{
|
|
|
|
if (!$form = $this->getFormParent()) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
// For the subject, only one-line entry boxes make sense
|
|
|
|
$validSubjectFields = ArrayList::create(
|
|
|
|
EditableTextField::get()
|
|
|
|
->filter('ParentID', $form->ID)
|
|
|
|
->exclude('Rows:GreaterThan', 1)
|
|
|
|
->toArray()
|
|
|
|
);
|
|
|
|
$validSubjectFields->merge($this->getMultiOptionFields());
|
|
|
|
return $validSubjectFields;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-01-18 22:29:08 +01:00
|
|
|
* @return DataList<EditableEmailField>|null
|
2018-02-20 12:29:20 +01:00
|
|
|
*/
|
|
|
|
protected function getValidEmailFromFields()
|
|
|
|
{
|
|
|
|
if (!$form = $this->getFormParent()) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if they have email fields then we could send from it
|
|
|
|
return EditableEmailField::get()->filter('ParentID', $form->ID);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-01-18 22:29:08 +01:00
|
|
|
* @return ArrayList<EditableFormField>|DataList<EditableFormField>|null
|
2018-02-20 12:29:20 +01:00
|
|
|
*/
|
|
|
|
protected function getValidEmailToFields()
|
|
|
|
{
|
2018-02-20 15:32:14 +01:00
|
|
|
if (!$this->getFormParent()) {
|
2018-02-20 12:29:20 +01:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check valid email-recipient fields
|
|
|
|
if ($this->config()->get('allow_unbound_recipient_fields')) {
|
|
|
|
// To address can only be email fields or multi option fields
|
|
|
|
$validEmailToFields = ArrayList::create($this->getValidEmailFromFields()->toArray());
|
|
|
|
$validEmailToFields->merge($this->getMultiOptionFields());
|
|
|
|
return $validEmailToFields;
|
|
|
|
} else {
|
|
|
|
// To address cannot be unbound, so restrict to pre-defined lists
|
|
|
|
return $this->getMultiOptionFields();
|
|
|
|
}
|
|
|
|
}
|
2018-02-20 15:32:14 +01:00
|
|
|
|
|
|
|
protected function getUnsavedFormLiteralField()
|
|
|
|
{
|
|
|
|
return LiteralField::create(
|
|
|
|
'UnsavedFormMessage',
|
|
|
|
sprintf(
|
|
|
|
'<p class="alert alert-warning">%s</p>',
|
|
|
|
_t(
|
|
|
|
'SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAIL_RECIPIENT_UNSAVED_FORM',
|
|
|
|
'You will be able to select from valid form fields after saving this record.'
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
2015-07-24 04:37:48 +02:00
|
|
|
}
|