Skip to content

Commit 04d5f47

Browse files
MarketSmartzerodoisLuis Rodriguez
authored
1.2 beta (#31)
* Mautic 4 (#28) * feat: ✨ mautic v4 port * Update TemplateProcessor.php bring pixel tracking back * Update EmailSubscriber.php modify content and add pixel tracking back * Update README.md Co-authored-by: zerodois <[email protected]> * Simple bug fixes * logger, lead tags, sms support, update readme * update readme * Update README.md --------- Co-authored-by: zerodois <[email protected]> Co-authored-by: Luis Rodriguez <[email protected]>
1 parent a70b187 commit 04d5f47

File tree

6 files changed

+276
-47
lines changed

6 files changed

+276
-47
lines changed

Config/config.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,24 @@
33
return [
44
'name' => 'Advanced Templates',
55
'description' => 'Plugin extends default email template capabilities with TWIG block so you can use advanced scripting techniques like conditions, loops etc',
6-
'version' => '1.0',
6+
'version' => '1.2',
77
'author' => 'Dmitry Berezovsky',
88
'services' => [
99
'events' => [
1010
// Register any event listeners
1111
'mautic.plugin.advanced_templates.email.subscriber' => [
1212
'class' => \MauticPlugin\MauticAdvancedTemplatesBundle\EventListener\EmailSubscriber::class,
1313
'arguments' => [
14-
'mautic.plugin.advanced_templates.helper.template_processor'
14+
'mautic.plugin.advanced_templates.helper.template_processor',
15+
'mautic.lead.model.lead',
16+
'monolog.logger.mautic',
17+
]
18+
],
19+
'mautic.plugin.advanced_templates.sms.subscriber' => [
20+
'class' => \MauticPlugin\MauticAdvancedTemplatesBundle\EventListener\SmsSubscriber::class,
21+
'arguments' => [
22+
'mautic.plugin.advanced_templates.helper.template_processor',
23+
'monolog.logger.mautic',
1524
]
1625
]
1726
],

EventListener/EmailSubscriber.php

Lines changed: 69 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,47 @@
22

33
namespace MauticPlugin\MauticAdvancedTemplatesBundle\EventListener;
44
use Mautic\CampaignBundle\Entity\Lead;
5-
use Mautic\CoreBundle\EventListener\CommonSubscriber;
5+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
66
use Mautic\EmailBundle\EmailEvents;
77
use Mautic\EmailBundle\Event as Events;
88
use Mautic\EmailBundle\Helper\PlainTextHelper;
99
use Mautic\CoreBundle\Exception as MauticException;
10+
use Mautic\LeadBundle\Model\LeadModel;
1011
use MauticPlugin\MauticAdvancedTemplatesBundle\Helper\TemplateProcessor;
1112
use Psr\Log\LoggerInterface;
13+
use Monolog\Logger;
1214

1315
/**
1416
* Class EmailSubscriber.
1517
*/
16-
class EmailSubscriber extends CommonSubscriber
18+
class EmailSubscriber implements EventSubscriberInterface
1719
{
1820
/**
19-
* @var TokenHelper $tokenHelper ;
21+
* @var LeadModel
22+
*/
23+
private $leadModel;
24+
25+
/**
26+
* @var TemplateProcessor $templateProcessor ;
2027
*/
2128
protected $templateProcessor;
2229

30+
/**
31+
* @var LoggerInterface $logger ;
32+
*/
33+
protected $logger;
34+
2335

2436
/**
2537
* EmailSubscriber constructor.
2638
*
2739
* @param TokenHelper $tokenHelper
2840
*/
29-
public function __construct(TemplateProcessor $templateProcessor)
41+
public function __construct(TemplateProcessor $templateProcessor, LeadModel $leadModel, Logger $logger)
3042
{
3143
$this->templateProcessor = $templateProcessor;
44+
$this->leadModel = $leadModel;
45+
$this->logger = $logger;
3246
}
3347
/**
3448
* @return array
@@ -41,6 +55,40 @@ public static function getSubscribedEvents()
4155
];
4256
}
4357

58+
private function getProperties(Events\EmailSendEvent $event) {
59+
$tokens = [];
60+
61+
if (!$event->getEmail()) {
62+
return [
63+
'subject' => $event->getSubject(),
64+
'content' => $event->getContent(),
65+
'tokens' => $tokens,
66+
];
67+
}
68+
69+
$email = $event->getEmail();
70+
71+
$subject = $email->getSubject();
72+
$content = $email->getCustomHtml();
73+
$dynamic = $email->getDynamicContent();
74+
75+
foreach ($dynamic as $prop) {
76+
$tokens[$prop['tokenName']] = $prop['content'];
77+
}
78+
79+
//Add arbritrary tokens when using the email send api
80+
$originalTokens = $event->getTokens();
81+
foreach($originalTokens as $k => $v) {
82+
$tokens[preg_replace('/^{(.*)}$/', '${1}', $k)] = $v;
83+
}
84+
85+
return [
86+
'subject' => $subject,
87+
'content' => $content,
88+
'tokens' => $tokens,
89+
];
90+
}
91+
4492
/**
4593
* Search and replace tokens with content
4694
*
@@ -53,23 +101,30 @@ public function onEmailGenerate(Events\EmailSendEvent $event)
53101
{
54102
$this->logger->info('onEmailGenerate MauticAdvancedTemplatesBundle\EmailSubscriber');
55103

56-
if ($event->getEmail()) {
57-
$subject = $event->getEmail()->getSubject();
58-
$content = $event->getEmail()->getCustomHtml();
59-
}else{
60-
$subject = $event->getSubject();
61-
$content = $event->getContent();
104+
if ($event->isDynamicContentParsing()) {
105+
return;
62106
}
63107

64-
$subject = $this->templateProcessor->processTemplate($subject, $event->getLead());
108+
$props = $this->getProperties($event);
109+
110+
$lead = $event->getLead();
111+
$leadmodel = $this->leadModel->getEntity($lead['id']);
112+
$lead['tags'] = [];
113+
if ($leadmodel && count($leadmodel->getTags()) > 0) {
114+
foreach ($leadmodel->getTags() as $tag) {
115+
$lead['tags'][] = $tag->getTag();
116+
}
117+
}
118+
119+
$subject = $this->templateProcessor->processTemplate($props['subject'], $lead);
65120
$event->setSubject($subject);
66121

67-
$content = $this->templateProcessor->processTemplate($content, $event->getLead());
122+
$content = $this->templateProcessor->processTemplate($props['content'], $lead, $props['tokens']);
123+
$content = $this->templateProcessor->addTrackingPixel($content);
68124
$event->setContent($content);
69125

70-
71126
if ( empty( trim($event->getPlainText()) ) ) {
72127
$event->setPlainText( (new PlainTextHelper($content))->getText() );
73128
}
74129
}
75-
}
130+
}

EventListener/SmsSubscriber.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
namespace MauticPlugin\MauticAdvancedTemplatesBundle\EventListener;
4+
use Mautic\CampaignBundle\Entity\Lead;
5+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
6+
use Mautic\SmsBundle\SmsEvents;
7+
use Mautic\SmsBundle\Event as Events;
8+
use Mautic\EmailBundle\Helper\PlainTextHelper;
9+
use Mautic\CoreBundle\Exception as MauticException;
10+
use Mautic\LeadBundle\Model\LeadModel;
11+
use MauticPlugin\MauticAdvancedTemplatesBundle\Helper\TemplateProcessor;
12+
use Psr\Log\LoggerInterface;
13+
use Monolog\Logger;
14+
15+
/**
16+
* Class EmailSubscriber.
17+
*/
18+
class SmsSubscriber implements EventSubscriberInterface
19+
{
20+
/**
21+
* @var LeadModel
22+
*/
23+
private $leadModel;
24+
25+
/**
26+
* @var TokenHelper $tokenHelper ;
27+
*/
28+
protected $templateProcessor;
29+
30+
/**
31+
* @var LoggerInterface $logger ;
32+
*/
33+
protected $logger;
34+
35+
/**
36+
* EmailSubscriber constructor.
37+
*
38+
* @param TokenHelper $tokenHelper
39+
*/
40+
public function __construct(TemplateProcessor $templateProcessor, LeadModel $leadModel, Logger $logger)
41+
{
42+
$this->templateProcessor = $templateProcessor;
43+
$this->leadModel = $leadModel;
44+
$this->logger = $logger;
45+
}
46+
/**
47+
* @return array
48+
*/
49+
public static function getSubscribedEvents()
50+
{
51+
return [
52+
SmsEvents::SMS_ON_SEND => ['onSmsGenerate', 300],
53+
// I dont know how to do this without editing core.
54+
// since there does not seem to be a simular way to call it yet.
55+
// SmsEvents::SMS_ON_DISPLAY => ['onSmsGenerate', 0],
56+
];
57+
}
58+
59+
/**
60+
* Search and replace tokens with content
61+
*
62+
* @param Events\SmsSendEvent $event
63+
* @throws \Throwable
64+
* @throws \Twig_Error_Loader
65+
* @throws \Twig_Error_Syntax
66+
*/
67+
public function onSmsGenerate(Events\SmsSendEvent $event)
68+
{
69+
$this->logger->info('onSmsGenerate MauticAdvancedTemplatesBundle\SmsSubscriber');
70+
71+
$content = $event->getContent();
72+
73+
$lead = $event->getLead();
74+
$leadmodel = $this->leadModel->getEntity($lead['id']);
75+
$lead['tags'] = [];
76+
if ($leadmodel && count($leadmodel->getTags()) > 0) {
77+
foreach ($leadmodel->getTags() as $tag) {
78+
$lead['tags'][] = $tag->getTag();
79+
}
80+
}
81+
82+
$content = $this->templateProcessor->processTemplate($content, $lead);
83+
$event->setContent($content);
84+
}
85+
}

Helper/TemplateProcessor.php

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
use MauticPlugin\MauticAdvancedTemplatesBundle\Feed\FeedFactory;
66
use MauticPlugin\MauticCrmBundle\Integration\Salesforce\Object\Lead;
77
use Psr\Log\LoggerInterface;
8+
use Twig\Environment as Twig_Environment;
9+
use Twig\Loader\ChainLoader as Twig_Loader_Chain;
10+
use Twig\Loader\ArrayLoader as Twig_Loader_Array;
11+
use Twig\TwigFilter as Twig_SimpleFilter;
812

913
class TemplateProcessor
1014
{
@@ -15,7 +19,7 @@ class TemplateProcessor
1519
protected $logger;
1620

1721
/**
18-
* @var \Twig_Environment
22+
* @var Twig_Environment
1923
*/
2024
private $twigEnv;
2125
private $twigDynamicContentLoader;
@@ -42,8 +46,8 @@ public function __construct(LoggerInterface $logger, Twig_Loader_DynamicContent
4246
$this->logger = $logger;
4347
$this->twigDynamicContentLoader = $twigDynamicContentLoader;
4448
$logger->debug('TemplateProcessor: created $twigDynamicContentLoader');
45-
$this->twigEnv = new \Twig_Environment(new \Twig_Loader_Chain([
46-
$twigDynamicContentLoader, new \Twig_Loader_Array([])
49+
$this->twigEnv = new Twig_Environment(new Twig_Loader_Chain([
50+
$twigDynamicContentLoader, new Twig_Loader_Array([])
4751
]));
4852
$this->configureTwig($this->twigEnv);
4953
$this->feedFactory = $feedFactory;
@@ -56,43 +60,64 @@ public function __construct(LoggerInterface $logger, Twig_Loader_DynamicContent
5660
* @return string
5761
* @throws \Throwable
5862
*/
59-
public function processTemplate($content, $lead)
63+
public function processTemplate($content, $lead, $tokens = null)
6064
{
6165
$this->logger->debug('TemplateProcessor: Processing template');
62-
$this->logger->debug('LEAD: ' . var_export($lead, true));
66+
// This was causing huge memory usage. Uncomment to debug.
67+
// $this->logger->debug('LEAD: ' . var_export($lead, true));
6368
$content = preg_replace_callback_array([
64-
TemplateProcessor::$matchTwigBlockRegex => $this->processTwigBlock($lead)
69+
TemplateProcessor::$matchTwigBlockRegex => $this->processTwigBlock($lead, $tokens)
6570
], $content);
6671
$this->logger->debug('TemplateProcessor: Template processed');
6772
return $content;
6873
}
6974

70-
protected function configureTwig(\Twig_Environment $twig)
75+
protected function configureTwig(Twig_Environment $twig)
7176
{
7277
// You might want to register some custom TWIG tags or functions here
7378

7479
// TWIG filter json_decode
75-
$twig->addFilter(new \Twig_SimpleFilter('json_decode', function ($string) {
80+
$twig->addFilter(new Twig_SimpleFilter('json_decode', function ($string) {
7681
return json_decode($string, true);
7782
}));
7883

79-
$twig->addFilter(new \Twig_SimpleFilter('rss', function () {
84+
$twig->addFilter(new Twig_SimpleFilter('json_encode', function ($obj) {
85+
return json_encode($obj);
86+
}));
87+
88+
$twig->addFilter(new Twig_SimpleFilter('rss', function () {
8089
return $this->feedFactory->getItems($this->lead['id'], func_get_args());
8190
}));
8291
}
8392

84-
private function processTwigBlock($lead)
93+
private function processTwigBlock($lead, $tokens = null)
8594
{
8695
$this->lead = $lead;
87-
return function ($matches) use ($lead) {
96+
return function ($matches) use ($lead, $tokens) {
8897
$templateSource = $matches[1];
89-
$this->logger->debug('BLOCK SOURCE: ' . var_export($templateSource, true));
98+
// Uncomment to debug. This causes high memory usage with var_export.
99+
// $this->logger->debug('BLOCK SOURCE: ' . var_export($templateSource, true));
90100
$template = $this->twigEnv->createTemplate($templateSource);
91101
$renderedTemplate = $template->render([
92-
'lead' => $lead
102+
'lead' => $lead,
103+
'tokens' => $tokens
93104
]);
94-
$this->logger->debug('RENDERED BLOCK: ' . var_export($renderedTemplate, true));
105+
// Uncomment to debug. This causes high memory usage with var_export.
106+
// $this->logger->debug('RENDERED BLOCK: ' . var_export($renderedTemplate, true));
95107
return $renderedTemplate;
96108
};
97109
}
98-
}
110+
111+
public function addTrackingPixel($content)
112+
{
113+
// Append tracking pixel
114+
$trackingImg = '<img height="1" width="1" src="{tracking_pixel}" alt="" />';
115+
if (strpos($content, '</body>') !== false) {
116+
$content = str_replace('</body>', $trackingImg.'</body>', $content);
117+
} else {
118+
$content .= $trackingImg;
119+
}
120+
121+
return $content;
122+
}
123+
}

0 commit comments

Comments
 (0)