4 +--------------------------------------------------------------------+
5 | Copyright CiviCRM LLC. All rights reserved. |
7 | This work is published under the GNU AGPLv3 license with some |
8 | permitted exceptions and without any warranty. For full license |
9 | and copyright information, see https://civicrm.org/licensing |
10 +--------------------------------------------------------------------+
14 * Class CRM_Mailing_ActionTokens
16 * Generate "action.*" tokens for mailings.
18 * To activate these tokens, the TokenProcessor context must specify:
19 * "mailingJobId" (int)
20 * "mailingActionTarget" (array) with keys:
21 * 'id' => int, event queue ID
22 * 'hash' => string, event queue hash code
23 * 'contact_id' => int, contact_id,
24 * 'email' => string, email
25 * 'phone' => string, phone
27 class CRM_Mailing_ActionTokens
extends \Civi\Token\AbstractTokenSubscriber
{
32 public function __construct() {
33 // TODO: Think about supporting dynamic tokens like "{action.subscribe.\d+}"
34 parent
::__construct('action', [
35 'subscribeUrl' => ts('Subscribe URL (Action)'),
36 'forward' => ts('Forward URL (Action)'),
37 'optOut' => ts('Opt-Out (Action)'),
38 'optOutUrl' => ts('Opt-Out URL (Action)'),
39 'reply' => ts('Reply (Action)'),
40 'unsubscribe' => ts('Unsubscribe (Action)'),
41 'unsubscribeUrl' => ts('Unsubscribe URL (Action)'),
42 'resubscribe' => ts('Resubscribe (Action)'),
43 'resubscribeUrl' => ts('Resubscribe URL (Action)'),
44 'eventQueueId' => ts('Event Queue ID'),
51 public function checkActive(\Civi\Token\TokenProcessor
$processor) {
52 return !empty($processor->context
['mailingId']) ||
!empty($processor->context
['mailing'])
53 ||
in_array('mailingId', $processor->context
['schema']) ||
in_array('mailing', $processor->context
['schema']);
59 public function evaluateToken(
60 \Civi\Token\TokenRow
$row,
65 // Most CiviMail action tokens were implemented via getActionTokenReplacement().
66 // However, {action.subscribeUrl} has a second implementation via
67 // replaceSubscribeInviteTokens(). The two appear mostly the same.
68 // We use getActionTokenReplacement() since it's more consistent. However,
69 // this doesn't provide the dynamic/parameterized tokens of
70 // replaceSubscribeInviteTokens().
72 if (empty($row->context
['mailingJobId']) ||
empty($row->context
['mailingActionTarget']['hash'])) {
73 // Strictly speaking, it doesn't make much sense to generate action-tokens when there's no job ID, but traditional CiviMail
74 // does this in v5.6+ for "Preview" functionality. Relaxing this strictness check ensures parity between newer+older styles.
75 // throw new \CRM_Core_Exception("Error: Cannot use action tokens unless context defines mailingJobId and mailingActionTarget.");
78 if ($field === 'eventQueueId') {
79 $row->format('text/plain')->tokens($entity, $field, $row->context
['mailingActionTarget']['id']);
83 list($verp, $urls) = CRM_Mailing_BAO_Mailing
::getVerpAndUrls(
84 $row->context
['mailingJobId'],
85 $row->context
['mailingActionTarget']['id'] ??
NULL,
86 $row->context
['mailingActionTarget']['hash'] ??
NULL,
87 // Note: Behavior is already undefined for SMS/'phone' mailings...
88 $row->context
['mailingActionTarget']['email'] ??
NULL
91 $row->format('text/plain')->tokens($entity, $field,
92 CRM_Utils_Token
::getActionTokenReplacement(
93 $field, $verp, $urls, FALSE));
94 $row->format('text/html')->tokens($entity, $field,
95 CRM_Utils_Token
::getActionTokenReplacement(
96 $field, $verp, $urls, TRUE));