Skip to content

Commit

Permalink
1.2 beta (#31)
Browse files Browse the repository at this point in the history
* 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 <felipelopesrita@gmail.com>

* Simple bug fixes

* logger, lead tags, sms support, update readme

* update readme

* Update README.md

---------

Co-authored-by: zerodois <felipelopesrita@gmail.com>
Co-authored-by: Luis Rodriguez <luisrodriguez@msadmins-MacBook-Pro.local>
  • Loading branch information
3 people committed Mar 14, 2023
1 parent a70b187 commit 04d5f47
Show file tree
Hide file tree
Showing 6 changed files with 276 additions and 47 deletions.
13 changes: 11 additions & 2 deletions Config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,24 @@
return [
'name' => 'Advanced Templates',
'description' => 'Plugin extends default email template capabilities with TWIG block so you can use advanced scripting techniques like conditions, loops etc',
'version' => '1.0',
'version' => '1.2',
'author' => 'Dmitry Berezovsky',
'services' => [
'events' => [
// Register any event listeners
'mautic.plugin.advanced_templates.email.subscriber' => [
'class' => \MauticPlugin\MauticAdvancedTemplatesBundle\EventListener\EmailSubscriber::class,
'arguments' => [
'mautic.plugin.advanced_templates.helper.template_processor'
'mautic.plugin.advanced_templates.helper.template_processor',
'mautic.lead.model.lead',
'monolog.logger.mautic',
]
],
'mautic.plugin.advanced_templates.sms.subscriber' => [
'class' => \MauticPlugin\MauticAdvancedTemplatesBundle\EventListener\SmsSubscriber::class,
'arguments' => [
'mautic.plugin.advanced_templates.helper.template_processor',
'monolog.logger.mautic',
]
]
],
Expand Down
83 changes: 69 additions & 14 deletions EventListener/EmailSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,47 @@

namespace MauticPlugin\MauticAdvancedTemplatesBundle\EventListener;
use Mautic\CampaignBundle\Entity\Lead;
use Mautic\CoreBundle\EventListener\CommonSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Mautic\EmailBundle\EmailEvents;
use Mautic\EmailBundle\Event as Events;
use Mautic\EmailBundle\Helper\PlainTextHelper;
use Mautic\CoreBundle\Exception as MauticException;
use Mautic\LeadBundle\Model\LeadModel;
use MauticPlugin\MauticAdvancedTemplatesBundle\Helper\TemplateProcessor;
use Psr\Log\LoggerInterface;
use Monolog\Logger;

/**
* Class EmailSubscriber.
*/
class EmailSubscriber extends CommonSubscriber
class EmailSubscriber implements EventSubscriberInterface
{
/**
* @var TokenHelper $tokenHelper ;
* @var LeadModel
*/
private $leadModel;

/**
* @var TemplateProcessor $templateProcessor ;
*/
protected $templateProcessor;

/**
* @var LoggerInterface $logger ;
*/
protected $logger;


/**
* EmailSubscriber constructor.
*
* @param TokenHelper $tokenHelper
*/
public function __construct(TemplateProcessor $templateProcessor)
public function __construct(TemplateProcessor $templateProcessor, LeadModel $leadModel, Logger $logger)
{
$this->templateProcessor = $templateProcessor;
$this->leadModel = $leadModel;
$this->logger = $logger;
}
/**
* @return array
Expand All @@ -41,6 +55,40 @@ public static function getSubscribedEvents()
];
}

private function getProperties(Events\EmailSendEvent $event) {
$tokens = [];

if (!$event->getEmail()) {
return [
'subject' => $event->getSubject(),
'content' => $event->getContent(),
'tokens' => $tokens,
];
}

$email = $event->getEmail();

$subject = $email->getSubject();
$content = $email->getCustomHtml();
$dynamic = $email->getDynamicContent();

foreach ($dynamic as $prop) {
$tokens[$prop['tokenName']] = $prop['content'];
}

//Add arbritrary tokens when using the email send api
$originalTokens = $event->getTokens();
foreach($originalTokens as $k => $v) {
$tokens[preg_replace('/^{(.*)}$/', '${1}', $k)] = $v;
}

return [
'subject' => $subject,
'content' => $content,
'tokens' => $tokens,
];
}

/**
* Search and replace tokens with content
*
Expand All @@ -53,23 +101,30 @@ public function onEmailGenerate(Events\EmailSendEvent $event)
{
$this->logger->info('onEmailGenerate MauticAdvancedTemplatesBundle\EmailSubscriber');

if ($event->getEmail()) {
$subject = $event->getEmail()->getSubject();
$content = $event->getEmail()->getCustomHtml();
}else{
$subject = $event->getSubject();
$content = $event->getContent();
if ($event->isDynamicContentParsing()) {
return;
}

$subject = $this->templateProcessor->processTemplate($subject, $event->getLead());
$props = $this->getProperties($event);

$lead = $event->getLead();
$leadmodel = $this->leadModel->getEntity($lead['id']);
$lead['tags'] = [];
if ($leadmodel && count($leadmodel->getTags()) > 0) {
foreach ($leadmodel->getTags() as $tag) {
$lead['tags'][] = $tag->getTag();
}
}

$subject = $this->templateProcessor->processTemplate($props['subject'], $lead);
$event->setSubject($subject);

$content = $this->templateProcessor->processTemplate($content, $event->getLead());
$content = $this->templateProcessor->processTemplate($props['content'], $lead, $props['tokens']);
$content = $this->templateProcessor->addTrackingPixel($content);
$event->setContent($content);


if ( empty( trim($event->getPlainText()) ) ) {
$event->setPlainText( (new PlainTextHelper($content))->getText() );
}
}
}
}
85 changes: 85 additions & 0 deletions EventListener/SmsSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

namespace MauticPlugin\MauticAdvancedTemplatesBundle\EventListener;
use Mautic\CampaignBundle\Entity\Lead;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Mautic\SmsBundle\SmsEvents;
use Mautic\SmsBundle\Event as Events;
use Mautic\EmailBundle\Helper\PlainTextHelper;
use Mautic\CoreBundle\Exception as MauticException;
use Mautic\LeadBundle\Model\LeadModel;
use MauticPlugin\MauticAdvancedTemplatesBundle\Helper\TemplateProcessor;
use Psr\Log\LoggerInterface;
use Monolog\Logger;

/**
* Class EmailSubscriber.
*/
class SmsSubscriber implements EventSubscriberInterface
{
/**
* @var LeadModel
*/
private $leadModel;

/**
* @var TokenHelper $tokenHelper ;
*/
protected $templateProcessor;

/**
* @var LoggerInterface $logger ;
*/
protected $logger;

/**
* EmailSubscriber constructor.
*
* @param TokenHelper $tokenHelper
*/
public function __construct(TemplateProcessor $templateProcessor, LeadModel $leadModel, Logger $logger)
{
$this->templateProcessor = $templateProcessor;
$this->leadModel = $leadModel;
$this->logger = $logger;
}
/**
* @return array
*/
public static function getSubscribedEvents()
{
return [
SmsEvents::SMS_ON_SEND => ['onSmsGenerate', 300],
// I dont know how to do this without editing core.
// since there does not seem to be a simular way to call it yet.
// SmsEvents::SMS_ON_DISPLAY => ['onSmsGenerate', 0],
];
}

/**
* Search and replace tokens with content
*
* @param Events\SmsSendEvent $event
* @throws \Throwable
* @throws \Twig_Error_Loader
* @throws \Twig_Error_Syntax
*/
public function onSmsGenerate(Events\SmsSendEvent $event)
{
$this->logger->info('onSmsGenerate MauticAdvancedTemplatesBundle\SmsSubscriber');

$content = $event->getContent();

$lead = $event->getLead();
$leadmodel = $this->leadModel->getEntity($lead['id']);
$lead['tags'] = [];
if ($leadmodel && count($leadmodel->getTags()) > 0) {
foreach ($leadmodel->getTags() as $tag) {
$lead['tags'][] = $tag->getTag();
}
}

$content = $this->templateProcessor->processTemplate($content, $lead);
$event->setContent($content);
}
}
55 changes: 40 additions & 15 deletions Helper/TemplateProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
use MauticPlugin\MauticAdvancedTemplatesBundle\Feed\FeedFactory;
use MauticPlugin\MauticCrmBundle\Integration\Salesforce\Object\Lead;
use Psr\Log\LoggerInterface;
use Twig\Environment as Twig_Environment;
use Twig\Loader\ChainLoader as Twig_Loader_Chain;
use Twig\Loader\ArrayLoader as Twig_Loader_Array;
use Twig\TwigFilter as Twig_SimpleFilter;

class TemplateProcessor
{
Expand All @@ -15,7 +19,7 @@ class TemplateProcessor
protected $logger;

/**
* @var \Twig_Environment
* @var Twig_Environment
*/
private $twigEnv;
private $twigDynamicContentLoader;
Expand All @@ -42,8 +46,8 @@ public function __construct(LoggerInterface $logger, Twig_Loader_DynamicContent
$this->logger = $logger;
$this->twigDynamicContentLoader = $twigDynamicContentLoader;
$logger->debug('TemplateProcessor: created $twigDynamicContentLoader');
$this->twigEnv = new \Twig_Environment(new \Twig_Loader_Chain([
$twigDynamicContentLoader, new \Twig_Loader_Array([])
$this->twigEnv = new Twig_Environment(new Twig_Loader_Chain([
$twigDynamicContentLoader, new Twig_Loader_Array([])
]));
$this->configureTwig($this->twigEnv);
$this->feedFactory = $feedFactory;
Expand All @@ -56,43 +60,64 @@ public function __construct(LoggerInterface $logger, Twig_Loader_DynamicContent
* @return string
* @throws \Throwable
*/
public function processTemplate($content, $lead)
public function processTemplate($content, $lead, $tokens = null)
{
$this->logger->debug('TemplateProcessor: Processing template');
$this->logger->debug('LEAD: ' . var_export($lead, true));
// This was causing huge memory usage. Uncomment to debug.
// $this->logger->debug('LEAD: ' . var_export($lead, true));
$content = preg_replace_callback_array([
TemplateProcessor::$matchTwigBlockRegex => $this->processTwigBlock($lead)
TemplateProcessor::$matchTwigBlockRegex => $this->processTwigBlock($lead, $tokens)
], $content);
$this->logger->debug('TemplateProcessor: Template processed');
return $content;
}

protected function configureTwig(\Twig_Environment $twig)
protected function configureTwig(Twig_Environment $twig)
{
// You might want to register some custom TWIG tags or functions here

// TWIG filter json_decode
$twig->addFilter(new \Twig_SimpleFilter('json_decode', function ($string) {
$twig->addFilter(new Twig_SimpleFilter('json_decode', function ($string) {
return json_decode($string, true);
}));

$twig->addFilter(new \Twig_SimpleFilter('rss', function () {
$twig->addFilter(new Twig_SimpleFilter('json_encode', function ($obj) {
return json_encode($obj);
}));

$twig->addFilter(new Twig_SimpleFilter('rss', function () {
return $this->feedFactory->getItems($this->lead['id'], func_get_args());
}));
}

private function processTwigBlock($lead)
private function processTwigBlock($lead, $tokens = null)
{
$this->lead = $lead;
return function ($matches) use ($lead) {
return function ($matches) use ($lead, $tokens) {
$templateSource = $matches[1];
$this->logger->debug('BLOCK SOURCE: ' . var_export($templateSource, true));
// Uncomment to debug. This causes high memory usage with var_export.
// $this->logger->debug('BLOCK SOURCE: ' . var_export($templateSource, true));
$template = $this->twigEnv->createTemplate($templateSource);
$renderedTemplate = $template->render([
'lead' => $lead
'lead' => $lead,
'tokens' => $tokens
]);
$this->logger->debug('RENDERED BLOCK: ' . var_export($renderedTemplate, true));
// Uncomment to debug. This causes high memory usage with var_export.
// $this->logger->debug('RENDERED BLOCK: ' . var_export($renderedTemplate, true));
return $renderedTemplate;
};
}
}

public function addTrackingPixel($content)
{
// Append tracking pixel
$trackingImg = '<img height="1" width="1" src="{tracking_pixel}" alt="" />';
if (strpos($content, '</body>') !== false) {
$content = str_replace('</body>', $trackingImg.'</body>', $content);
} else {
$content .= $trackingImg;
}

return $content;
}
}
Loading

0 comments on commit 04d5f47

Please sign in to comment.