diff --git a/lib/Config/Initializer.php b/lib/Config/Initializer.php index c563b5fdde..746ceb806f 100644 --- a/lib/Config/Initializer.php +++ b/lib/Config/Initializer.php @@ -5,11 +5,14 @@ namespace MailPoet\Config; use MailPoet\API\JSON\API; use MailPoet\AutomaticEmails\AutomaticEmails; use MailPoet\Cron\CronTrigger; +use MailPoet\Features\FeaturesController; use MailPoet\Router; use MailPoet\Settings\SettingsController; use MailPoet\Util\ConflictResolver; use MailPoet\Util\Helpers; use MailPoet\Util\Notices\PermanentNotices; +use MailPoet\WooCommerce\Helper as WooCommerceHelper; +use MailPoet\WooCommerce\TransactionalEmails as WCTransactionalEmails; use MailPoet\WP\Functions as WPFunctions; use MailPoet\WP\Notice as WPNotice; @@ -36,6 +39,9 @@ class Initializer { /** @var SettingsController */ private $settings; + /** @var FeaturesController */ + private $flags_controller; + /** @var Router\Router */ private $router; @@ -60,6 +66,12 @@ class Initializer { /** @var DatabaseInitializer */ private $database_initializer; + /** @var WCTransactionalEmails */ + private $wc_transactional_emails; + + /** @var WooCommerceHelper */ + private $wc_helper; + const INITIALIZED = 'MAILPOET_INITIALIZED'; function __construct( @@ -75,7 +87,10 @@ class Initializer { CronTrigger $cron_trigger, PermanentNotices $permanent_notices, Shortcodes $shortcodes, - DatabaseInitializer $database_initializer + DatabaseInitializer $database_initializer, + FeaturesController $flags_controller, + WCTransactionalEmails $wc_transactional_emails, + WooCommerceHelper $wc_helper ) { $this->renderer_factory = $renderer_factory; $this->access_control = $access_control; @@ -90,6 +105,9 @@ class Initializer { $this->permanent_notices = $permanent_notices; $this->shortcodes = $shortcodes; $this->database_initializer = $database_initializer; + $this->flags_controller = $flags_controller; + $this->wc_transactional_emails = $wc_transactional_emails; + $this->wc_helper = $wc_helper; } function init() { @@ -172,6 +190,7 @@ class Initializer { $this->renderer = $this->renderer_factory->getRenderer(); $this->setupWidget(); $this->hooks->init(); + $this->setupWoocommerceTransactionalEmails(); } catch (\Exception $e) { $this->handleFailedInitialization($e); } @@ -347,6 +366,15 @@ class Initializer { ); } + private function setupWoocommerceTransactionalEmails() { + $feature_enabled = $this->flags_controller->isSupported(FeaturesController::WC_TRANSACTIONAL_EMAILS_CUSTOMIZER); + $opt_in_enabled = $this->settings->get('woocommerce.use_mailpoet_editor', false); + $wc_enabled = $this->wc_helper->isWooCommerceActive(); + if ($feature_enabled && $wc_enabled && $opt_in_enabled) { + $this->wc_transactional_emails->useTemplateForWoocommerceEmails(); + } + } + function includeAutomaticEmailsData() { $data = [ 'automatic_emails' => $this->automatic_emails, diff --git a/lib/DI/ContainerConfigurator.php b/lib/DI/ContainerConfigurator.php index 400702586c..42c7c30777 100644 --- a/lib/DI/ContainerConfigurator.php +++ b/lib/DI/ContainerConfigurator.php @@ -243,6 +243,7 @@ class ContainerConfigurator implements IContainerConfigurator { $container->autowire(\MailPoet\WooCommerce\Subscription::class)->setPublic(true); $container->autowire(\MailPoet\WooCommerce\TransactionalEmails::class); $container->autowire(\MailPoet\WooCommerce\TransactionalEmails\Template::class); + $container->autowire(\MailPoet\WooCommerce\TransactionalEmails\Renderer::class); // WordPress $container->autowire(\MailPoet\WP\Emoji::class)->setPublic(true); $container->autowire(\MailPoet\WP\Functions::class)->setPublic(true); diff --git a/lib/WooCommerce/TransactionalEmails.php b/lib/WooCommerce/TransactionalEmails.php index 862b45d6a0..0c02d58c19 100644 --- a/lib/WooCommerce/TransactionalEmails.php +++ b/lib/WooCommerce/TransactionalEmails.php @@ -2,9 +2,9 @@ namespace MailPoet\WooCommerce; -use MailPoet\Config\Env; use MailPoet\Models\Newsletter; use MailPoet\Settings\SettingsController; +use MailPoet\WooCommerce\TransactionalEmails\Renderer; use MailPoet\WooCommerce\TransactionalEmails\Template; use MailPoet\WP\Functions as WPFunctions; @@ -20,13 +20,17 @@ class TransactionalEmails { /** @var Template */ private $template; + /** @var Renderer */ + private $renderer; + /** @var array */ private $email_headings; - function __construct(WPFunctions $wp, SettingsController $settings, Template $template) { + function __construct(WPFunctions $wp, SettingsController $settings, Template $template, Renderer $renderer) { $this->wp = $wp; $this->settings = $settings; $this->template = $template; + $this->renderer = $renderer; $this->email_headings = [ 'new_account' => [ 'option_name' => 'woocommerce_new_order_settings', @@ -69,6 +73,21 @@ class TransactionalEmails { return $values; } + public function useTemplateForWoocommerceEmails() { + $this->wp->addAction('woocommerce_init', function() { + $this->wp->removeAction('woocommerce_email_header', [\WC()->mailer(), 'email_header']); + $this->wp->removeAction('woocommerce_email_footer', [\WC()->mailer(), 'email_footer']); + $this->wp->addAction('woocommerce_email_header', function($email_heading) { + $this->renderer->render($this->getNewsletter()); + echo $this->renderer->getHTMLBeforeContent($email_heading); + }); + $this->wp->addAction('woocommerce_email_footer', function() { + echo $this->renderer->getHTMLAfterContent(); + }); + $this->wp->addAction('woocommerce_email_styles', [$this->renderer, 'prefixCss']); + }); + } + private function createNewsletter() { $wc_email_settings = $this->getWCEmailSettings(); return Newsletter::createOrUpdate([ @@ -79,6 +98,10 @@ class TransactionalEmails { ]); } + private function getNewsletter() { + return Newsletter::findOne($this->settings->get(self::SETTING_EMAIL_ID)); + } + private function replacePlaceholders($text) { $title = $this->wp->wpSpecialcharsDecode($this->wp->getOption('blogname'), ENT_QUOTES); $address = $this->wp->wpParseUrl($this->wp->homeUrl(), PHP_URL_HOST); diff --git a/lib/WooCommerce/TransactionalEmails/Template.php b/lib/WooCommerce/TransactionalEmails/Template.php index 4e01fc61bf..d0e1a5c480 100644 --- a/lib/WooCommerce/TransactionalEmails/Template.php +++ b/lib/WooCommerce/TransactionalEmails/Template.php @@ -2,6 +2,8 @@ namespace MailPoet\WooCommerce\TransactionalEmails; +use MailPoet\Config\Env; + class Template { public function create($wc_email_settings) { $social_icon_url = Env::$assets_url . '/img/newsletter_editor/social-icons'; diff --git a/tests/integration/WooCommerce/TransactionalEmailsTest.php b/tests/integration/WooCommerce/TransactionalEmailsTest.php index f8190d4568..bd1d5b8417 100644 --- a/tests/integration/WooCommerce/TransactionalEmailsTest.php +++ b/tests/integration/WooCommerce/TransactionalEmailsTest.php @@ -4,7 +4,10 @@ namespace MailPoet\WooCommerce; use Codeception\Stub; use MailPoet\Models\Newsletter; +use MailPoet\Newsletter\Editor\LayoutHelper as L; use MailPoet\Settings\SettingsController; +use MailPoet\WooCommerce\TransactionalEmails\Renderer; +use MailPoet\WooCommerce\TransactionalEmails\Template; use MailPoet\WP\Functions as WPFunctions; use MailPoetVendor\Idiorm\ORM; @@ -25,7 +28,7 @@ class TransactionalEmailsTest extends \MailPoetTest { $this->wp = new WPFunctions(); $this->settings = SettingsController::getInstance(); $this->original_wc_settings = $this->settings->get('woocommerce'); - $this->transactional_emails = new TransactionalEmails($this->wp, $this->settings); + $this->transactional_emails = new TransactionalEmails($this->wp, $this->settings, new Template, new Renderer); } function testInitCreatesTransactionalEmailAndSavesItsId() { @@ -50,13 +53,76 @@ class TransactionalEmailsTest extends \MailPoetTest { return 'my-awesome-image-url'; } }]); - $transactional_emails = new TransactionalEmails($wp, $this->settings); + $transactional_emails = new TransactionalEmails($wp, $this->settings, new Template, new Renderer); $transactional_emails->init(); $email = Newsletter::where('type', Newsletter::TYPE_WC_TRANSACTIONAL_EMAIL)->findOne(); expect($email)->notEmpty(); expect($email->body)->contains('my-awesome-image-url'); } + function testUseTemplateForWCEmails() { + $added_actions = []; + $removed_actions = []; + $newsletter = Newsletter::createOrUpdate([ + 'type' => Newsletter::TYPE_WC_TRANSACTIONAL_EMAIL, + 'subject' => 'WooCommerce Transactional Email', + 'preheader' => '', + 'body' => json_encode([ + 'content' => L::col([ + L::row([L::col([['type' => 'text', 'text' => 'Some text before heading']])]), + ['type' => 'woocommerceHeading'], + L::row([L::col([['type' => 'text', 'text' => 'Some text between heading and content']])]), + ['type' => 'woocommerceContent'], + L::row([L::col([['type' => 'text', 'text' => 'Some text after content']])]), + ]), + ]), + ]); + $this->settings->set(TransactionalEmails::SETTING_EMAIL_ID, $newsletter->id); + $wp = Stub::make(new WPFunctions, [ + 'getOption' => function($name) { + return ''; + }, + 'addAction' => function ($name, $action) use(&$added_actions) { + $added_actions[$name] = $action; + }, + 'removeAction' => function ($name, $action) use(&$removed_actions) { + $removed_actions[$name] = $action; + }, + ]); + $renderer = Stub::make(Renderer::class, [ + 'render' => function($email) use(&$newsletter) { + expect($email->id)->equals($newsletter->id); + }, + 'getHTMLBeforeContent' => function($heading_text) { + return 'HTML before content with ' . $heading_text; + }, + 'getHTMLAfterContent' => function() { + return 'HTML after content'; + }, + 'prefixCss' => function($css) { + return 'prefixed ' . $css; + }, + ]); + + $transactional_emails = new TransactionalEmails($wp, $this->settings, new Template, $renderer); + $transactional_emails->useTemplateForWoocommerceEmails(); + expect($added_actions)->count(1); + expect($added_actions['woocommerce_init'])->isCallable(); + $added_actions['woocommerce_init'](); + expect($removed_actions)->count(2); + expect($added_actions)->count(4); + expect($added_actions['woocommerce_email_header'])->isCallable(); + ob_start(); + $added_actions['woocommerce_email_header']('heading text'); + expect(ob_get_clean())->equals('HTML before content with heading text'); + expect($added_actions['woocommerce_email_footer'])->isCallable(); + ob_start(); + $added_actions['woocommerce_email_footer'](); + expect(ob_get_clean())->equals('HTML after content'); + expect($added_actions['woocommerce_email_styles'])->isCallable(); + expect($added_actions['woocommerce_email_styles']('some css'))->equals('prefixed some css'); + } + function _after() { ORM::raw_execute('TRUNCATE ' . Newsletter::$_table); $this->settings->set('woocommerce', $this->original_wc_settings); diff --git a/tests/integration/_bootstrap.php b/tests/integration/_bootstrap.php index d2cddbc4f3..9f22938d85 100644 --- a/tests/integration/_bootstrap.php +++ b/tests/integration/_bootstrap.php @@ -216,4 +216,21 @@ if (!class_exists(WC_Session::class)) { } } +if (!function_exists('WC')) { + class WC_Mailer { + function email_header() { + } + function email_footer() { + } + } + class WooCommerce { + function mailer() { + return new WC_Mailer; + } + } + function WC() { + return new WooCommerce; + } +} + include '_fixtures.php'; diff --git a/tests/unit/WooCommerce/TransactionalEmailsTest.php b/tests/unit/WooCommerce/TransactionalEmailsTest.php index 00fd71bdb3..ef086a1432 100644 --- a/tests/unit/WooCommerce/TransactionalEmailsTest.php +++ b/tests/unit/WooCommerce/TransactionalEmailsTest.php @@ -4,6 +4,8 @@ namespace MailPoet\WooCommerce; use Codeception\Stub; use MailPoet\Settings\SettingsController; +use MailPoet\WooCommerce\TransactionalEmails\Renderer; +use MailPoet\WooCommerce\TransactionalEmails\Template; use MailPoet\WP\Functions as WPFunctions; class TransactionalEmailsTest extends \MailPoetUnitTest { @@ -32,7 +34,9 @@ class TransactionalEmailsTest extends \MailPoetUnitTest { }, ]); $settings = Stub::make(SettingsController::class); - $transactional_emails = new TransactionalEmails($wp, $settings); + $template = Stub::make(Template::class); + $renderer = Stub::make(Renderer::class); + $transactional_emails = new TransactionalEmails($wp, $settings, $template, $renderer); expect($transactional_emails->getEmailHeadings())->equals([ 'new_account' => 'Test: New Order: #0001', 'processing_order' => 'Thank you for your order', @@ -40,5 +44,4 @@ class TransactionalEmailsTest extends \MailPoetUnitTest { 'customer_note' => 'Note added to order #0001 - ' . date('Y-m-d'), ]); } - }