From e026b9e4ef1c93aa897bf8e5530c21aa64dce808 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Mon, 29 Apr 2019 13:35:48 -0700 Subject: [PATCH] CiviMail - Restore support for previewing action-tokens via TokenProcessor/Flexmailer Overview -------- When using `TokenProcessor` to generate a mailing (e.g. as with Flexmailer/Mosaico), the action-tokens (e.g. `{action.optOutUrl}`) are generated via `CRM_Mailing_ActionTokens`. To properly generate them, `CRM_Mailing_ActionTokens` relies on certain information (e.g. mailing/job ID). However, that information is no longer available when performing a "Preview" -- leading to misbehavior in previews. This patch allows Flexmailer to restore parity for previewing those tokens. Before (Pre-5.6) ---------------- * When a user begins composing a mailing, CiviMail creates a draft mailing with a concrete ID (e.g. `mailing #123`). * To preview the mailing, the UI calls `Mailing.preview` API with the ID of the mailing. * Flexmailer/Mosaico generates the preview by calling `TokenProcessor` and therefore `CRM_Mailing_ActionTokens`. * `CRM_Mailing_ActionTokens` has strictness checks. These pass because the ID is available. Before (5.6-5.12) ---------------- As a performance enhancement, CiviCRM 5.6 (PR #12509; [dev/mail#20](https://lab.civicrm.org/dev/mail/issues/20)) revised the signature for `Mailing.preview` API to allow previews *without* having a specific mailing record/job/ID. Consequently: * When a user begins composing a mailing, CiviMail creates a draft mailing with a concrete ID (e.g. `mailing #123`). * To preview the mailing, the UI calls `Mailing.preview` API ~~with~~ **without** the ID of the mailing. * Flexmailer/Mosaico generates the preview by calling `TokenProcessor` and therefore `CRM_Mailing_ActionTokens`. * `CRM_Mailing_ActionTokens` has strictness checks. These ~~pass~~ **fail** because the ID is ~~available~~ **unavailable**. After ---------------- * When a user begins composing a mailing, CiviMail creates a draft mailing with a concrete ID (e.g. `mailing #123`). * To preview the mailing, the UI calls `Mailing.preview` API ~~with~~ **without** the ID of the mailing. * Flexmailer/Mosaico generates the preview by calling `TokenProcessor` and therefore `CRM_Mailing_ActionTokens`. * `CRM_Mailing_ActionTokens` has ~~strictness~~ **less strict** checks. These **pass** because the `context[schema]` hints that a mailing ID *will be available* when needed. --- CRM/Mailing/ActionTokens.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CRM/Mailing/ActionTokens.php b/CRM/Mailing/ActionTokens.php index 85e893ca4d..8e609c0d14 100644 --- a/CRM/Mailing/ActionTokens.php +++ b/CRM/Mailing/ActionTokens.php @@ -65,7 +65,8 @@ class CRM_Mailing_ActionTokens extends \Civi\Token\AbstractTokenSubscriber { * @inheritDoc */ public function checkActive(\Civi\Token\TokenProcessor $processor) { - return !empty($processor->context['mailingId']) || !empty($processor->context['mailing']); + return !empty($processor->context['mailingId']) || !empty($processor->context['mailing']) + || in_array('mailingId', $processor->context['schema']) || in_array('mailing', $processor->context['schema']); } /** @@ -85,7 +86,9 @@ class CRM_Mailing_ActionTokens extends \Civi\Token\AbstractTokenSubscriber { // replaceSubscribeInviteTokens(). if (empty($row->context['mailingJobId']) || empty($row->context['mailingActionTarget']['hash'])) { - throw new \CRM_Core_Exception("Error: Cannot use action tokens unless context defines mailingJobId and mailingActionTarget."); + // Strictly speaking, it doesn't make much sense to generate action-tokens when there's no job ID, but traditional CiviMail + // does this in v5.6+ for "Preview" functionality. Relaxing this strictness check ensures parity between newer+older styles. + // throw new \CRM_Core_Exception("Error: Cannot use action tokens unless context defines mailingJobId and mailingActionTarget."); } if ($field === 'eventQueueId') { -- 2.25.1