*/
public $_templates;
+ /**
+ * Email addresses to send to.
+ *
+ * @var array
+ */
+ protected $emails = [];
+
/**
* Store "to" contact details.
* @var array
*/
public $_toContactIds = [];
- /**
- * Store only "cc" contact ids.
- * @var array
- */
- public $_ccContactIds = [];
-
- /**
- * Store only "bcc" contact ids.
- *
- * @var array
- */
- public $_bccContactIds = [];
-
/**
* Is the form being loaded from a search action.
*
* Call trait preProcess function.
*
* This function exists as a transitional arrangement so classes overriding
- * preProcess can still call it. Ideally it will be melded into preProcess later.
+ * preProcess can still call it. Ideally it will be melded into preProcess
+ * later.
*
- * @throws \CiviCRM_API3_Exception
* @throws \CRM_Core_Exception
+ * @throws \API_Exception
*/
protected function traitPreProcess() {
- CRM_Contact_Form_Task_EmailCommon::preProcessFromAddress($this);
+ $this->preProcessFromAddress();
if ($this->isSearchContext()) {
// Currently only the contact email form is callable outside search context.
parent::preProcess();
}
}
+ /**
+ * Pre Process Form Addresses to be used in Quickform
+ *
+ * @throws \API_Exception
+ * @throws \CRM_Core_Exception
+ */
+ protected function preProcessFromAddress(): void {
+ $form = $this;
+ $form->_emails = [];
+
+ // @TODO remove these line and to it somewhere more appropriate. Currently some classes (e.g Case
+ // are having to re-write contactIds afterwards due to this inappropriate variable setting
+ // If we don't have any contact IDs, use the logged in contact ID
+ $form->_contactIds = $form->_contactIds ?: [CRM_Core_Session::getLoggedInContactID()];
+ }
+
/**
* Build the form object.
*
if ($to->getValue()) {
foreach ($this->getEmails($to) as $value) {
$contactId = $value['contact_id'];
- $email = $value['email'];
if ($contactId) {
$this->_contactIds[] = $this->_toContactIds[] = $contactId;
- $this->_toContactEmails[] = $email;
$this->_allContactIds[] = $contactId;
}
}
$this->add('text', 'subject', ts('Subject'), ['size' => 50, 'maxlength' => 254], TRUE);
- $this->add('select', 'from_email_address', ts('From'), $this->_fromEmails, TRUE);
+ $this->add('select', 'from_email_address', ts('From'), $this->getFromEmails(), TRUE);
CRM_Mailing_BAO_Mailing::commonCompose($this);
if ($this->_single) {
// also fix the user context stack
- if ($this->_caseId) {
+ if ($this->getCaseID()) {
$ccid = CRM_Core_DAO::getFieldValue('CRM_Case_DAO_CaseContact', $this->_caseId,
'contact_id', 'case_id'
);
$url = CRM_Utils_System::url('civicrm/contact/view/case',
- "&reset=1&action=view&cid={$ccid}&id={$this->_caseId}"
+ "&reset=1&action=view&cid={$ccid}&id=" . $this->getCaseID()
);
}
elseif ($this->_context) {
$session = CRM_Core_Session::singleton();
$session->replaceUserContext($url);
- $this->addDefaultButtons(ts('Send Email'), 'upload', 'cancel');
- }
- else {
- $this->addDefaultButtons(ts('Send Email'), 'upload');
}
+ $this->addDefaultButtons(ts('Send Email'), 'upload', 'cancel');
$fields = [
'followup_assignee_contact_id' => [
CRM_Campaign_BAO_Campaign::addCampaign($this);
$this->addFormRule([__CLASS__, 'saveTemplateFormRule'], $this);
+ $this->addFormRule([__CLASS__, 'deprecatedTokensFormRule'], $this);
CRM_Core_Resources::singleton()->addScriptFile('civicrm', 'templates/CRM/Contact/Form/Task/EmailCommon.js', 0, 'html-header');
}
+ /**
+ * Set relevant default values.
+ *
+ * @return array
+ *
+ * @throws \API_Exception
+ * @throws \CRM_Core_Exception
+ */
+ public function setDefaultValues(): array {
+ $defaults = parent::setDefaultValues();
+ $fromEmails = $this->getFromEmails();
+ if (is_numeric(key($fromEmails))) {
+ $emailID = (int) key($fromEmails);
+ $defaults = CRM_Core_BAO_Email::getEmailSignatureDefaults($emailID);
+ }
+ if (!Civi::settings()->get('allow_mail_from_logged_in_contact')) {
+ $defaults['from_email_address'] = current(CRM_Core_BAO_Domain::getNameAndEmail(FALSE, TRUE));
+ }
+ return $defaults;
+ }
+
/**
* Process the form after the input has been submitted and validated.
*
*/
public function postProcess() {
$this->bounceIfSimpleMailLimitExceeded(count($this->_contactIds));
-
- // check and ensure that
$formValues = $this->controller->exportValues($this->getName());
$this->submit($formValues);
}
* @param int $count
* The number of emails the user is attempting to send
*/
- protected function bounceIfSimpleMailLimitExceeded($count) {
+ protected function bounceIfSimpleMailLimitExceeded($count): void {
$limit = Civi::settings()->get('simple_mail_limit');
if ($count > $limit) {
CRM_Core_Error::statusBounce(ts('Please do not use this task to send a lot of emails (greater than %1). Many countries have legal requirements when sending bulk emails and the CiviMail framework has opt out functionality and domain tokens to help meet these.',
* @throws \Civi\API\Exception\UnauthorizedException
* @throws \API_Exception
*/
- public function submit($formValues) {
+ public function submit($formValues): void {
$this->saveMessageTemplate($formValues);
$from = $formValues['from_email_address'] ?? NULL;
if (!isset($this->_contactDetails[$contactId])) {
continue;
}
- $email = $this->_toContactEmails[$key];
+ $email = $this->getEmail($key);
// prevent duplicate emails if same email address is selected CRM-4067
// we should allow same emails for different contacts
$details = $this->_contactDetails[$contactId];
}
// send the mail
- list($sent, $activityIds) = CRM_Activity_BAO_Activity::sendEmail(
+ [$sent, $activityIds] = CRM_Activity_BAO_Activity::sendEmail(
$formattedContactDetails,
$this->getSubject($formValues['subject']),
$formValues['text_message'],
$bcc,
array_keys($this->_toContactDetails),
$additionalDetails,
- $this->getVar('_contributionIds') ?? [],
+ $this->getContributionIDs(),
CRM_Utils_Array::value('campaign_id', $formValues),
- $this->getVar('_caseId')
+ $this->getCaseID()
);
if ($sent) {
* @param string $subject
*
* @return string
+ * @throws \CRM_Core_Exception
*/
protected function getSubject(string $subject):string {
// CRM-5916: prepend case id hash to CiviCase-originating emails’ subjects
- if (isset($this->_caseId) && is_numeric($this->_caseId)) {
- $hash = substr(sha1(CIVICRM_SITE_KEY . $this->_caseId), 0, 7);
+ if ($this->getCaseID()) {
+ $hash = substr(sha1(CIVICRM_SITE_KEY . $this->getCaseID()), 0, 7);
$subject = "[case #$hash] $subject";
}
return $subject;
return empty($errors) ? TRUE : $errors;
}
+ /**
+ * Prevent submission of deprecated tokens.
+ *
+ * @param array $fields
+ *
+ * @return bool|string[]
+ */
+ public static function deprecatedTokensFormRule(array $fields) {
+ $deprecatedTokens = [
+ '{case.status_id}' => '{case.status_id:label}',
+ '{case.case_type_id}' => '{case.case_type_id:label}',
+ ];
+ $tokenErrors = [];
+ foreach ($deprecatedTokens as $token => $replacement) {
+ if (strpos($fields['html_message'], $token) !== FALSE) {
+ $tokenErrors[] = ts('Token %1 is no longer supported - use %2 instead', [$token, $replacement]);
+ }
+ }
+ return empty($tokenErrors) ? TRUE : ['html_message' => implode('<br>', $tokenErrors)];
+ }
+
+ /**
+ * Get selected contribution IDs.
+ *
+ * @return array
+ */
+ protected function getContributionIDs(): array {
+ return [];
+ }
+
+ /**
+ * Get case ID - if any.
+ *
+ * @return int|null
+ *
+ * @throws \CRM_Core_Exception
+ */
+ protected function getCaseID(): ?int {
+ $caseID = CRM_Utils_Request::retrieve('caseid', 'String', $this);
+ if ($caseID) {
+ return (int) $caseID;
+ }
+ return NULL;
+ }
+
+ /**
+ * @return array
+ */
+ protected function getFromEmails(): array {
+ $fromEmailValues = CRM_Core_BAO_Email::getFromEmail();
+
+ if (empty($fromEmailValues)) {
+ CRM_Core_Error::statusBounce(ts('Your user record does not have a valid email address and no from addresses have been configured.'));
+ }
+ return $fromEmailValues;
+ }
+
+ /**
+ * Get the relevant emails.
+ *
+ * @param int $index
+ *
+ * @return string
+ */
+ protected function getEmail(int $index): string {
+ if (empty($this->emails)) {
+ $toEmails = explode(',', $this->getSubmittedValue('to'));
+ foreach ($toEmails as $value) {
+ $parts = explode('::', $value);
+ $this->emails[] = $parts[1];
+ }
+ }
+ return $this->emails[$index];
+ }
+
}