-
-
Notifications
You must be signed in to change notification settings - Fork 812
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CRM-19690 - CiviMail/FlexMailer - Allow alternative email templating systems #9497
Conversation
c72123c
to
139d6b2
Compare
2cd9e5b
to
1d94567
Compare
We had some discussion on Hangouts/Mattermost about the prospects of backporting this to 4.6. To further reduce change, I've removed some of the smaller cleanups (like fixing weirdly-named variables) and also moved some of the new helpers from Mailing BAO to new classes under Still an open question: whether to move the entire folder
|
294d4d8
to
fa4706e
Compare
This adds the TokenProcessor and associated classes to the container in 4.6. These are not *used* at runtime -- but they're published so that extensions may use them. This folds in a few more recent patches to TokenProcessor subsystem provided by civicrm#9497 and removes the parts defined for scheduled reminders.
I've rebased and done a round of revisions to improve the prospects of backporting to v4.6. Generally, most of these commits should be individually small changes to CiviMail, and the idea is to apply those equally to
|
@@ -156,7 +156,7 @@ | |||
mailings: {include: [], exclude: []} | |||
}, | |||
template_type: "traditional", | |||
template_options: "", | |||
template_options: {nonce: 1}, // Workaround CRM-19756 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the full code standards spec disallows comments at the end of the line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I could put it on the preceding line. I like having the comment adjacent to the code.
fefacb4
to
77b95f7
Compare
Based on discussion with @eileenmcnaughton, I've extracted some smaller PR's from here:
I'm keeping this branch/PR around because it's useful (a) for integration testing, (b) Mosaico development, and (c) remembering what all needs backporting. |
…Hook::mailingTemplateTypes. This adds two new fields to the schema. Template types can be declared (along with preferred editor) using hook_civicrm_mailingTemplateTypes, e.g. ``` function mymod_civicrm_mailingTemplateTypes(&$types) { $types[] = array( 'name' => 'moasico', 'editorUrl' => '~/crmMosaico/EditMailingCtrl/mosaico.html', ); } ``` Note: This only stores data. Other commits will make use of that data in more meaningful ways.
Present API consumers with a consistent, array-based interface for reading and writing properties in a Mailing. Suppose you're submitting a REST request to create a mailing. The REST request as a whole is encoded with JSON. With the default API behavior, you would need to double-encode the `template_options`, e.g. roughly ``` POST rest.php json_encode([ entity => Mailing action => create params => [ template_options => json_encode([...]) ] ]) ``` With this patch, you only need to encode the request once. This parallels the approach used in CaseType API (for the XML `definition` field).
General notes: 1. When creating a mailing, use the path `civicrm/a/#/mailing/new` to create a mailing with the default `template_type` (aka first-preferred, by weight). 2. When creating a mailing, use the path `civicrm/a/#/mailing/new/{template_type}` to create a mailing with a specific `template_type`. 3. When editing a mailing, check the `template_type` and load the appropriate editor. 4. Some of the boilerplate from `2step.html`, `unified.html`, etal has been moved to `base.html`. Note that this breaks a hidden feature -- before, you could switch among a few different layouts (`2step`, `unified`, `unified2`, `wizard`) by manually editing the URL (e.g. `civicrm/a/#/mailing/2/unified`). Now, to change the layout of the traditional-style mailings, you can implement a hook, e.g. ``` function mymod_civicrm_mailingTemplateTypes(&$types) { foreach ($types as &$typeDef) { if ($typeDef['name'] === 'traditional') { $typeDef['editorUrl'] = '~/crmMailing/EditMailingCtrl/unified.html'; } } } ```
… `static` This function is only called once, and it previously lacked test coverage, so the `static` warning previously snuck through. Fix it!
…public These two functions will be useful in FlexMailer's DefaultEngine.
This is more significant with mailing tokens because some of them are fairly sizeable/expensive.
This includes support for both `{mailing.*}` and `{action.*}` tokens used in CiviMail.
If you install an extension under `$cmsRoot/vendor/org.example.foo`, the resulting URL contains an extraneous `/` (eg `http://example.org//vendor/org.example.foo`). (In Windows, I suspect it's even worse because it uses DIRECTORY_SEPARATOR in the URl -- eg `http://example.org/\vendor/org.example.foo`.) This patch checks for and removes the extraneous slash -- and always constructs the URL with the appropriate delimiter (`/`). Problem observed in `dmaster`.
During development of FlexMailer, I flirted with using a special token (e.g. `{actions.trackOpen}`) but ultimately found that was positioned well in the order of operations.
This adds the TokenProcessor and associated classes to the container in 4.6. These are not *used* at runtime -- but they're published so that extensions may use them. This folds in a few more recent patches to TokenProcessor subsystem provided by civicrm#9497 and removes the parts defined for scheduled reminders.
This adds the TokenProcessor and associated classes to the container in 4.6. These are not *used* at runtime -- but they're published so that extensions may use them. This folds in a few more recent patches to TokenProcessor subsystem provided by civicrm#9497 and removes the parts defined for scheduled reminders.
This adds the TokenProcessor and associated classes to the container in 4.6. These are not *used* at runtime -- but they're published so that extensions may use them. This folds in a few more recent patches to TokenProcessor subsystem provided by civicrm#9497 and removes the parts defined for scheduled reminders.
(Note: This PR is still under active development. It may be rebased/squashed without notice.)
CiviMail has traditionally included a templating language and a delivery system. This patch generally aims to open those systems up so that extensions can define better templating processes (e.g. Mosaico) while minimizing changes or risks for existing CiviMail users. It breaks down into three areas:
civicrm_mailing
supports two new fields,template_type
andtemplate_options
(open-ended JSON data).civicrm/a/#/mailing/123
can be overloaded by an extension. This allows them to settemplate_type
andtemplate_options
-- and to display a new user interface.template_type
, an extension can tap into the batching/composition/delivery system.Data Model: template_type and template_options
The
template_type
stores a string, such as "traditional" or "mosaico" or "none" or "twig".The
template_options
stores an open-ended JSON object. The content of this field is not specified by core. Eachtemplate_type
may store any fields it deems useful/necessary.Extending the data-model in this way allows different mailings and systems to coexist. For example, you have may have 3 or 4 CiviMail templates (for newsletters vs event-announcements vs emergency-alerts). You install Mosaico because it seems cool and you went try it for one or two mailings. However, you still have several templates/mailings/people/business-processes based on the old system. That's fine -- because your old-style content and new-style content are stored with different
template_type
s.By default,
template_type
istraditional
, which means that CiviMail should retain current behaviors -- i.e. use the old/current/existing user-interface and use the old/current/existing delivery system.Frontend: CiviMail and Angular layouts
The current CiviMail UI includes a rich-text editor (ckeditor) and a token selector. However, if you have a different content-model, then these elements need to be replaced -- and (depending on how your content model works) you may rethink the general layout/pageflow of the composition screen.
When defining a new
template_type
, you need to provide an Angular*.html
file describing the look-and-feel of the editor. Register this usinghook_civicrm_mailingTemplateTypes
, e.g.Backend: FlexMailer
CiviMail includes a cron task (
Job.process_mailing
API). This has several responsibilities, such as:Most of this logic is handled by a series of coupled functions:
MailingJob::deliver()
,MailingJob::deliverGroup()
,Mailing:compose()
,Mailing::getPreparedTemplates()
, etal.If our goal is to replace the templating system, then we probably want to reuse most of the functionality -- but change small aspects (specifically in composing the message). Unfortunately, this code has (over time) taken on toxic characteristics -- for example, the batching function (
MailingJob::deliver()
) does some of the email composition, and the email composition function (Mailing::compose()
) represents the same data in multiple formats (and converts back/forth multiple times). We could refactor/cleanup this code in place, but there'd be a high-risk of regressions -- and we don't want normal CiviMail users to bear the risk that. Rather, that risk belongs with the early-adopters who choose to use a newer templating system.The resolution: for now, there are two delivery pipelines:
MailingJob::deliver()
(etal) represent the old system. Only a couple lines of this code changes. It is used for any mailing withtemplate_type==traditional
(and specifically any SMS-based mailings).FlexMailer
is a refactored, event-driven version. It is only used on mailings which have a newtemplate_type
. The events are discussed more in the docblocks, and the template-evaluation logic is now shared with the Scheduled Reminders (e.g. viaTokenProcessor
).FlexMailer aims to provide comparable behaviors and features -- much of the code is pilferred from BAOs, and it passes the same test-casess (
api_v3_JobProcessMailingTest
andCRM_Mailing_MailingSystemTest
). However, the test scenarios may not be exhaustive, so it's not enabled by default. (If you'd like to enable it for all mailings, enable the hidden settingexperimentalFlexMailerEngine
.)Note: The main motivation of implementing FlexMailer now is to support new composition/templating logic; however, the architecture allows other changes (such batch-oriented message delivery, alternative tracking logic, or alternative batching/distribution patterns).