From edb18399a1a56a5cf8c4f8c80d3918c830c4832a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jakes=CC=8C?= Date: Thu, 6 Feb 2020 12:24:38 +0100 Subject: [PATCH] Extract view-in-browser logic to a controller [MAILPOET-2430] --- lib/DI/ContainerConfigurator.php | 1 + .../ViewInBrowser/ViewInBrowserController.php | 86 +++++++++++++++++++ lib/Router/Endpoints/ViewInBrowser.php | 82 +++--------------- 3 files changed, 97 insertions(+), 72 deletions(-) create mode 100644 lib/Newsletter/ViewInBrowser/ViewInBrowserController.php diff --git a/lib/DI/ContainerConfigurator.php b/lib/DI/ContainerConfigurator.php index c492d1c278..648d870a14 100644 --- a/lib/DI/ContainerConfigurator.php +++ b/lib/DI/ContainerConfigurator.php @@ -241,6 +241,7 @@ class ContainerConfigurator implements IContainerConfigurator { $container->autowire(\MailPoet\Newsletter\Scheduler\WelcomeScheduler::class); $container->autowire(\MailPoet\Newsletter\Scheduler\PostNotificationScheduler::class); $container->autowire(\MailPoet\Newsletter\ViewInBrowser::class)->setPublic(true); + $container->autowire(\MailPoet\Newsletter\ViewInBrowser\ViewInBrowserController::class)->setPublic(true); // Util $container->autowire(\MailPoet\Util\Cookies::class); $container->autowire(\MailPoet\Util\Url::class)->setPublic(true); diff --git a/lib/Newsletter/ViewInBrowser/ViewInBrowserController.php b/lib/Newsletter/ViewInBrowser/ViewInBrowserController.php new file mode 100644 index 0000000000..1df158ffaa --- /dev/null +++ b/lib/Newsletter/ViewInBrowser/ViewInBrowserController.php @@ -0,0 +1,86 @@ +accessControl = $accessControl; + $this->linkTokens = $linkTokens; + $this->newsletterViewInBrowser = $newsletterViewInBrowser; + } + + public function view(array $data) { + $data = NewsletterUrl::transformUrlDataObject($data); + $isPreview = !empty($data['preview']); + + // newsletter - ID is mandatory hash must be set and valid + $newsletter = empty($data['newsletter_id']) ? null : Newsletter::findOne($data['newsletter_id']); + if (!$newsletter || empty($data['newsletter_hash']) || $data['newsletter_hash'] !== $newsletter->hash) { + throw new \InvalidArgumentException(); + } + + // subscriber is optional; if exists, token must validate + $subscriber = empty($data['subscriber_id']) ? null : Subscriber::findOne($data['subscriber_id']); + $subscriberToken = $data['subscriber_token'] ?? null; + if ($subscriber && (!$subscriberToken || !$this->linkTokens->verifyToken($subscriber, $subscriberToken))) { + throw new \InvalidArgumentException(); + } + + // if this is a preview and subscriber does not exist, + // attempt to set subscriber to the current logged-in WP user + if (!$subscriber && $isPreview) { + $subscriber = Subscriber::getCurrentWPUser(); + } + + // allow users with permission to manage emails to preview any newsletter + $canView = $isPreview && $this->accessControl->validatePermission(AccessControl::PERMISSION_MANAGE_EMAILS); + + // if queue and subscriber exist, subscriber must have received the newsletter + $queue = $this->getQueue($newsletter, $data); + if (!$canView && $queue && $subscriber && !$queue->isSubscriberProcessed($subscriber->id)) { + throw new \InvalidArgumentException(); + } + + return $this->newsletterViewInBrowser->view($isPreview, $newsletter, $subscriber, $queue); + } + + + private function getQueue(Newsletter $newsletter, array $data) { + // queue is optional; try to find it if it's not defined and this is not a welcome email + if ($newsletter->type === Newsletter::TYPE_WELCOME) { + return null; + } + + // reset queue when automatic email is being previewed + if ($newsletter->type === Newsletter::TYPE_AUTOMATIC && !empty($data['preview'])) { + return null; + } + + $queue = !empty($data['queue_id']) + ? SendingQueue::findOne($data['queue_id']) + : SendingQueue::where('newsletter_id', $newsletter->id)->findOne(); + + return $queue ?: null; + } +} diff --git a/lib/Router/Endpoints/ViewInBrowser.php b/lib/Router/Endpoints/ViewInBrowser.php index 7f4fc7ea50..e94bca3da2 100644 --- a/lib/Router/Endpoints/ViewInBrowser.php +++ b/lib/Router/Endpoints/ViewInBrowser.php @@ -3,12 +3,7 @@ namespace MailPoet\Router\Endpoints; use MailPoet\Config\AccessControl; -use MailPoet\Models\Newsletter; -use MailPoet\Models\SendingQueue; -use MailPoet\Models\Subscriber; -use MailPoet\Newsletter\Url as NewsletterUrl; -use MailPoet\Newsletter\ViewInBrowser as NewsletterViewInBrowser; -use MailPoet\Subscribers\LinkTokens; +use MailPoet\Newsletter\ViewInBrowser\ViewInBrowserController; use MailPoet\WP\Functions as WPFunctions; class ViewInBrowser { @@ -20,77 +15,20 @@ class ViewInBrowser { 'global' => AccessControl::NO_ACCESS_RESTRICTION, ]; - /** @var AccessControl */ - private $accessControl; + /** @var ViewInBrowserController */ + private $viewInBrowserController; - /** @var LinkTokens */ - private $linkTokens; - - /** @var NewsletterViewInBrowser */ - private $newsletterViewInBrowser; - - public function __construct( - AccessControl $accessControl, - LinkTokens $linkTokens, - NewsletterViewInBrowser $newsletterViewInBrowser - ) { - $this->accessControl = $accessControl; - $this->linkTokens = $linkTokens; - $this->newsletterViewInBrowser = $newsletterViewInBrowser; + public function __construct(ViewInBrowserController $viewInBrowserController) { + $this->viewInBrowserController = $viewInBrowserController; } public function view(array $data) { - $data = NewsletterUrl::transformUrlDataObject($data); - $isPreview = !empty($data['preview']); - - // newsletter - ID is mandatory hash must be set and valid - $newsletter = empty($data['newsletter_id']) ? null : Newsletter::findOne($data['newsletter_id']); - if (!$newsletter || empty($data['newsletter_hash']) || $data['newsletter_hash'] !== $newsletter->hash) { - return $this->_abort(); + try { + $viewData = $this->viewInBrowserController->view($data); + $this->_displayNewsletter($viewData); + } catch (\InvalidArgumentException $e) { + $this->_abort(); } - - // subscriber is optional; if exists, token must validate - $subscriber = empty($data['subscriber_id']) ? null : Subscriber::findOne($data['subscriber_id']); - $subscriberToken = $data['subscriber_token'] ?? null; - if ($subscriber && (!$subscriberToken || !$this->linkTokens->verifyToken($subscriber, $subscriberToken))) { - return $this->_abort(); - } - - // if this is a preview and subscriber does not exist, - // attempt to set subscriber to the current logged-in WP user - if (!$subscriber && $isPreview) { - $subscriber = Subscriber::getCurrentWPUser(); - } - - // allow users with permission to manage emails to preview any newsletter - $canView = $isPreview && $this->accessControl->validatePermission(AccessControl::PERMISSION_MANAGE_EMAILS); - - // if queue and subscriber exist, subscriber must have received the newsletter - $queue = $this->getQueue($newsletter, $data); - if (!$canView && $queue && $subscriber && !$queue->isSubscriberProcessed($subscriber->id)) { - return $this->_abort(); - } - - $viewData = $this->newsletterViewInBrowser->view($isPreview, $newsletter, $subscriber, $queue); - return $this->_displayNewsletter($viewData); - } - - private function getQueue(Newsletter $newsletter, array $data) { - // queue is optional; try to find it if it's not defined and this is not a welcome email - if ($newsletter->type === Newsletter::TYPE_WELCOME) { - return null; - } - - // reset queue when automatic email is being previewed - if ($newsletter->type === Newsletter::TYPE_AUTOMATIC && !empty($data['preview'])) { - return null; - } - - $queue = !empty($data['queue_id']) - ? SendingQueue::findOne($data['queue_id']) - : SendingQueue::where('newsletter_id', $newsletter->id)->findOne(); - - return $queue ?: null; } public function _displayNewsletter($result) {