Extract Newsletters::sendPreview() logic to a controller
[MAILPOET-2646]
This commit is contained in:
@ -12,24 +12,21 @@ use MailPoet\Cron\Workers\SendingQueue\Tasks\Newsletter as NewsletterQueueTask;
|
||||
use MailPoet\DI\ContainerWrapper;
|
||||
use MailPoet\Entities\NewsletterEntity;
|
||||
use MailPoet\Listing;
|
||||
use MailPoet\Mailer\Mailer as MailerFactory;
|
||||
use MailPoet\Mailer\MetaInfo;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\NewsletterOption;
|
||||
use MailPoet\Models\NewsletterOptionField;
|
||||
use MailPoet\Models\NewsletterSegment;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Newsletter\Listing\NewsletterListingRepository;
|
||||
use MailPoet\Newsletter\NewslettersRepository;
|
||||
use MailPoet\Newsletter\Renderer\Renderer;
|
||||
use MailPoet\Newsletter\Preview\SendPreviewController;
|
||||
use MailPoet\Newsletter\Preview\SendPreviewException;
|
||||
use MailPoet\Newsletter\Scheduler\PostNotificationScheduler;
|
||||
use MailPoet\Newsletter\Scheduler\Scheduler;
|
||||
use MailPoet\Newsletter\Url as NewsletterUrl;
|
||||
use MailPoet\NewsletterTemplates\NewsletterTemplatesRepository;
|
||||
use MailPoet\Services\AuthorizedEmailsController;
|
||||
use MailPoet\Settings\SettingsController;
|
||||
use MailPoet\Tasks\Sending as SendingTask;
|
||||
use MailPoet\Util\License\Features\Subscribers as SubscribersFeature;
|
||||
use MailPoet\WP\Emoji;
|
||||
use MailPoet\WP\Functions as WPFunctions;
|
||||
@ -71,18 +68,15 @@ class Newsletters extends APIEndpoint {
|
||||
/** @var PostNotificationScheduler */
|
||||
private $postNotificationScheduler;
|
||||
|
||||
/** @var MetaInfo */
|
||||
private $mailerMetaInfo;
|
||||
|
||||
/** @var Emoji */
|
||||
private $emoji;
|
||||
|
||||
/** @var MailerFactory */
|
||||
private $mailer;
|
||||
|
||||
/** @var SubscribersFeature */
|
||||
private $subscribersFeature;
|
||||
|
||||
/** @var SendPreviewController */
|
||||
private $sendPreviewController;
|
||||
|
||||
public function __construct(
|
||||
Listing\BulkActionController $bulkAction,
|
||||
Listing\Handler $listingHandler,
|
||||
@ -94,10 +88,9 @@ class Newsletters extends APIEndpoint {
|
||||
NewsletterListingRepository $newsletterListingRepository,
|
||||
NewslettersResponseBuilder $newslettersResponseBuilder,
|
||||
PostNotificationScheduler $postNotificationScheduler,
|
||||
MailerFactory $mailer,
|
||||
MetaInfo $mailerMetaInfo,
|
||||
Emoji $emoji,
|
||||
SubscribersFeature $subscribersFeature
|
||||
SubscribersFeature $subscribersFeature,
|
||||
SendPreviewController $sendPreviewController
|
||||
) {
|
||||
$this->bulkAction = $bulkAction;
|
||||
$this->listingHandler = $listingHandler;
|
||||
@ -109,10 +102,9 @@ class Newsletters extends APIEndpoint {
|
||||
$this->newsletterListingRepository = $newsletterListingRepository;
|
||||
$this->newslettersResponseBuilder = $newslettersResponseBuilder;
|
||||
$this->postNotificationScheduler = $postNotificationScheduler;
|
||||
$this->mailer = $mailer;
|
||||
$this->mailerMetaInfo = $mailerMetaInfo;
|
||||
$this->emoji = $emoji;
|
||||
$this->subscribersFeature = $subscribersFeature;
|
||||
$this->sendPreviewController = $sendPreviewController;
|
||||
}
|
||||
|
||||
public function get($data = []) {
|
||||
@ -444,66 +436,20 @@ class Newsletters extends APIEndpoint {
|
||||
|
||||
$id = (isset($data['id'])) ? (int)$data['id'] : false;
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
|
||||
if ($newsletter instanceof Newsletter) {
|
||||
$renderer = new Renderer($newsletter, $preview = true);
|
||||
$renderedNewsletter = $renderer->render();
|
||||
$divider = '***MailPoet***';
|
||||
$dataForShortcodes = array_merge(
|
||||
[$newsletter->subject],
|
||||
$renderedNewsletter
|
||||
);
|
||||
|
||||
$body = implode($divider, $dataForShortcodes);
|
||||
|
||||
$subscriber = Subscriber::getCurrentWPUser();
|
||||
$subscriber = ($subscriber) ? $subscriber : false;
|
||||
|
||||
$shortcodes = new \MailPoet\Newsletter\Shortcodes\Shortcodes(
|
||||
$newsletter,
|
||||
$subscriber,
|
||||
$queue = false,
|
||||
$wpUserPreview = true
|
||||
);
|
||||
|
||||
list(
|
||||
$renderedNewsletter['subject'],
|
||||
$renderedNewsletter['body']['html'],
|
||||
$renderedNewsletter['body']['text']
|
||||
) = explode($divider, $shortcodes->replace($body));
|
||||
$renderedNewsletter['id'] = $newsletter->id;
|
||||
|
||||
try {
|
||||
$extraParams = [
|
||||
'unsubscribe_url' => WPFunctions::get()->homeUrl(),
|
||||
'meta' => $this->mailerMetaInfo->getPreviewMetaInfo(),
|
||||
];
|
||||
$result = $this->mailer->send($renderedNewsletter, $data['subscriber'], $extraParams);
|
||||
|
||||
if ($result['response'] === false) {
|
||||
$error = sprintf(
|
||||
__('The email could not be sent: %s', 'mailpoet'),
|
||||
$result['error']->getMessage()
|
||||
);
|
||||
return $this->errorResponse([APIError::BAD_REQUEST => $error]);
|
||||
} else {
|
||||
$newsletter = Newsletter::findOne($newsletter->id);
|
||||
if(!$newsletter instanceof Newsletter) return $this->errorResponse();
|
||||
|
||||
return $this->successResponse(
|
||||
$newsletter->asArray()
|
||||
);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return $this->errorResponse([
|
||||
$e->getCode() => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
if (!$newsletter) {
|
||||
return $this->errorResponse([
|
||||
APIError::NOT_FOUND => __('This email does not exist.', 'mailpoet'),
|
||||
]);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->sendPreviewController->sendPreview($newsletter, $data['subscriber']);
|
||||
} catch (SendPreviewException $e) {
|
||||
return $this->errorResponse([APIError::BAD_REQUEST => $e->getMessage()]);
|
||||
} catch (\Throwable $e) {
|
||||
return $this->errorResponse([$e->getCode() => $e->getMessage()]);
|
||||
}
|
||||
return $this->successResponse($newsletter->asArray());
|
||||
}
|
||||
|
||||
public function listing($data = []) {
|
||||
|
@ -264,6 +264,7 @@ class ContainerConfigurator implements IContainerConfigurator {
|
||||
$container->autowire(\MailPoet\Newsletter\AutomatedLatestContent::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\Newsletter\NewslettersRepository::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\Newsletter\Listing\NewsletterListingRepository::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\Newsletter\Preview\SendPreviewController::class);
|
||||
$container->autowire(\MailPoet\Newsletter\Statistics\NewsletterStatisticsRepository::class);
|
||||
$container->autowire(\MailPoet\Newsletter\Scheduler\WelcomeScheduler::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\Newsletter\Scheduler\PostNotificationScheduler::class);
|
||||
|
73
lib/Newsletter/Preview/SendPreviewController.php
Normal file
73
lib/Newsletter/Preview/SendPreviewController.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\Newsletter\Preview;
|
||||
|
||||
use MailPoet\Mailer\Mailer;
|
||||
use MailPoet\Mailer\MetaInfo;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Newsletter\Renderer\Renderer;
|
||||
use MailPoet\Newsletter\Shortcodes\Shortcodes;
|
||||
use MailPoet\WP\Functions as WPFunctions;
|
||||
|
||||
class SendPreviewController {
|
||||
/** @var Mailer */
|
||||
private $mailer;
|
||||
|
||||
/** @var MetaInfo */
|
||||
private $mailerMetaInfo;
|
||||
|
||||
/** @var WPFunctions */
|
||||
private $wp;
|
||||
|
||||
public function __construct(
|
||||
Mailer $mailer,
|
||||
MetaInfo $mailerMetaInfo,
|
||||
WPFunctions $wp
|
||||
) {
|
||||
$this->mailer = $mailer;
|
||||
$this->mailerMetaInfo = $mailerMetaInfo;
|
||||
$this->wp = $wp;
|
||||
}
|
||||
|
||||
public function sendPreview(Newsletter $newsletter, string $emailAddress) {
|
||||
$renderer = new Renderer($newsletter, $preview = true);
|
||||
$renderedNewsletter = $renderer->render();
|
||||
$divider = '***MailPoet***';
|
||||
$dataForShortcodes = array_merge(
|
||||
[$newsletter->subject],
|
||||
$renderedNewsletter
|
||||
);
|
||||
|
||||
$body = implode($divider, $dataForShortcodes);
|
||||
|
||||
$subscriber = Subscriber::getCurrentWPUser() ?: false;
|
||||
$shortcodes = new Shortcodes(
|
||||
$newsletter,
|
||||
$subscriber,
|
||||
$queue = false,
|
||||
$wpUserPreview = true
|
||||
);
|
||||
|
||||
list(
|
||||
$renderedNewsletter['subject'],
|
||||
$renderedNewsletter['body']['html'],
|
||||
$renderedNewsletter['body']['text']
|
||||
) = explode($divider, $shortcodes->replace($body));
|
||||
$renderedNewsletter['id'] = $newsletter->id;
|
||||
|
||||
$extraParams = [
|
||||
'unsubscribe_url' => $this->wp->homeUrl(),
|
||||
'meta' => $this->mailerMetaInfo->getPreviewMetaInfo(),
|
||||
];
|
||||
|
||||
$result = $this->mailer->send($renderedNewsletter, $emailAddress, $extraParams);
|
||||
if ($result['response'] === false) {
|
||||
$error = sprintf(
|
||||
__('The email could not be sent: %s', 'mailpoet'),
|
||||
$result['error']->getMessage()
|
||||
);
|
||||
throw new SendPreviewException($error);
|
||||
}
|
||||
}
|
||||
}
|
6
lib/Newsletter/Preview/SendPreviewException.php
Normal file
6
lib/Newsletter/Preview/SendPreviewException.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\Newsletter\Preview;
|
||||
|
||||
class SendPreviewException extends \RuntimeException {
|
||||
}
|
@ -13,9 +13,6 @@ use MailPoet\Cron\CronHelper;
|
||||
use MailPoet\DI\ContainerWrapper;
|
||||
use MailPoet\Listing\BulkActionController;
|
||||
use MailPoet\Listing\Handler;
|
||||
use MailPoet\Mailer\Mailer;
|
||||
use MailPoet\Mailer\MailerError;
|
||||
use MailPoet\Mailer\MetaInfo;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\NewsletterOption;
|
||||
use MailPoet\Models\NewsletterOptionField;
|
||||
@ -26,6 +23,8 @@ use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Models\SubscriberSegment;
|
||||
use MailPoet\Newsletter\Listing\NewsletterListingRepository;
|
||||
use MailPoet\Newsletter\NewslettersRepository;
|
||||
use MailPoet\Newsletter\Preview\SendPreviewController;
|
||||
use MailPoet\Newsletter\Preview\SendPreviewException;
|
||||
use MailPoet\Newsletter\Scheduler\PostNotificationScheduler;
|
||||
use MailPoet\Newsletter\Scheduler\Scheduler;
|
||||
use MailPoet\Newsletter\Statistics\NewsletterStatisticsRepository;
|
||||
@ -33,7 +32,6 @@ use MailPoet\Newsletter\Url;
|
||||
use MailPoet\Router\Router;
|
||||
use MailPoet\Services\AuthorizedEmailsController;
|
||||
use MailPoet\Settings\SettingsController;
|
||||
use MailPoet\Subscription\SubscriptionUrlFactory;
|
||||
use MailPoet\Tasks\Sending as SendingTask;
|
||||
use MailPoet\Util\License\Features\Subscribers as SubscribersFeature;
|
||||
use MailPoet\WooCommerce\Helper as WCHelper;
|
||||
@ -49,15 +47,11 @@ class NewslettersTest extends \MailPoetTest {
|
||||
/** @var Newsletters */
|
||||
private $endpoint;
|
||||
|
||||
/** @var SubscriptionUrlFactory */
|
||||
private $subscriptionUrlFactory;
|
||||
|
||||
/** @var CronHelper */
|
||||
private $cronHelper;
|
||||
|
||||
public function _before() {
|
||||
parent::_before();
|
||||
$this->subscriptionUrlFactory = SubscriptionUrlFactory::getInstance();
|
||||
$this->cronHelper = ContainerWrapper::getInstance()->get(CronHelper::class);
|
||||
$this->endpoint = Stub::copy(
|
||||
ContainerWrapper::getInstance()->get(Newsletters::class),
|
||||
@ -836,33 +830,11 @@ class NewslettersTest extends \MailPoetTest {
|
||||
}
|
||||
|
||||
public function testItCanSendAPreview() {
|
||||
|
||||
$subscriber = 'test@subscriber.com';
|
||||
|
||||
|
||||
$endpoint = Stub::copy($this->endpoint, [
|
||||
'mailer' => $this->makeEmpty(
|
||||
Mailer::class,
|
||||
[
|
||||
'send' => function ($newsletter, $subscriber, $extraParams) {
|
||||
$unsubscribeLink = $this->subscriptionUrlFactory->getConfirmUnsubscribeUrl(null);
|
||||
$manageLink = $this->subscriptionUrlFactory->getManageUrl(null);
|
||||
$viewInBrowserLink = Url::getViewInBrowserUrl($this->newsletter);
|
||||
$mailerMetaInfo = new MetaInfo;
|
||||
|
||||
expect(is_array($newsletter))->true();
|
||||
expect($newsletter['body']['text'])->contains('Hello test');
|
||||
expect($subscriber)->equals($subscriber);
|
||||
expect($extraParams['unsubscribe_url'])->equals(home_url());
|
||||
expect($extraParams['meta'])->equals($mailerMetaInfo->getPreviewMetaInfo());
|
||||
// system links are replaced with hashes
|
||||
expect($newsletter['body']['html'])->contains('href="' . $viewInBrowserLink . '">View in browser');
|
||||
expect($newsletter['body']['html'])->contains('href="' . $unsubscribeLink . '">Unsubscribe');
|
||||
expect($newsletter['body']['html'])->contains('href="' . $manageLink . '">Manage subscription');
|
||||
return ['response' => true];
|
||||
},
|
||||
]
|
||||
),
|
||||
$endpoint = $this->createNewslettersEndpointWithMocks([
|
||||
'sendPreviewController' => $this->make(SendPreviewController::class, [
|
||||
'sendPreview' => null,
|
||||
]),
|
||||
]);
|
||||
|
||||
$data = [
|
||||
@ -875,27 +847,12 @@ class NewslettersTest extends \MailPoetTest {
|
||||
|
||||
public function testItReturnsMailerErrorWhenSendingFailed() {
|
||||
$subscriber = 'test@subscriber.com';
|
||||
|
||||
$endpoint = Stub::copy($this->endpoint, [
|
||||
'mailer' => $this->makeEmpty(
|
||||
Mailer::class,
|
||||
[
|
||||
'send' => function ($newsletter, $subscriber) {
|
||||
expect(is_array($newsletter))->true();
|
||||
expect($newsletter['body']['text'])->contains('Hello test');
|
||||
expect($subscriber)->equals($subscriber);
|
||||
return [
|
||||
'response' => false,
|
||||
'error' => $this->make(
|
||||
MailerError::class,
|
||||
[
|
||||
'getMessage' => 'failed',
|
||||
]
|
||||
),
|
||||
];
|
||||
},
|
||||
]
|
||||
),
|
||||
$endpoint = $this->createNewslettersEndpointWithMocks([
|
||||
'sendPreviewController' => $this->make(SendPreviewController::class, [
|
||||
'sendPreview' => Expected::once(function () {
|
||||
throw new SendPreviewException('The email could not be sent: failed');
|
||||
}),
|
||||
]),
|
||||
]);
|
||||
|
||||
$data = [
|
||||
@ -1050,10 +1007,9 @@ class NewslettersTest extends \MailPoetTest {
|
||||
$this->diContainer->get(NewsletterListingRepository::class),
|
||||
$this->diContainer->get(NewslettersResponseBuilder::class),
|
||||
$this->diContainer->get(PostNotificationScheduler::class),
|
||||
$this->diContainer->get(Mailer::class),
|
||||
$this->diContainer->get(MetaInfo::class),
|
||||
$mocks['emoji'] ?? $this->diContainer->get(Emoji::class),
|
||||
$mocks['subscribersFeature'] ?? $this->diContainer->get(SubscribersFeature::class)
|
||||
$mocks['subscribersFeature'] ?? $this->diContainer->get(SubscribersFeature::class),
|
||||
$mocks['sendPreviewController'] ?? $this->diContainer->get(SendPreviewController::class)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,83 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\Newsletter\Preview;
|
||||
|
||||
use Codeception\Stub\Expected;
|
||||
use Codeception\Util\Fixtures;
|
||||
use MailPoet\Mailer\Mailer;
|
||||
use MailPoet\Mailer\MailerError;
|
||||
use MailPoet\Mailer\MetaInfo;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Newsletter\Url;
|
||||
use MailPoet\Subscription\SubscriptionUrlFactory;
|
||||
use MailPoet\WP\Functions as WPFunctions;
|
||||
|
||||
class SendPrevewControllerTest extends \MailPoetTest {
|
||||
/** @var SubscriptionUrlFactory */
|
||||
private $subscriptionUrlFactory;
|
||||
|
||||
/** @var Newsletter */
|
||||
private $newsletter;
|
||||
|
||||
public function _before() {
|
||||
parent::_before();
|
||||
$this->subscriptionUrlFactory = SubscriptionUrlFactory::getInstance();
|
||||
$this->newsletter = Newsletter::createOrUpdate([
|
||||
'subject' => 'My Standard Newsletter',
|
||||
'preheader' => 'preheader',
|
||||
'body' => Fixtures::get('newsletter_body_template'),
|
||||
'type' => Newsletter::TYPE_STANDARD,
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function testItCanSendAPreview() {
|
||||
$mailer = $this->makeEmpty(Mailer::class, [
|
||||
'send' => Expected::once(
|
||||
function ($newsletter, $subscriber, $extraParams) {
|
||||
$unsubscribeLink = $this->subscriptionUrlFactory->getConfirmUnsubscribeUrl(null);
|
||||
$manageLink = $this->subscriptionUrlFactory->getManageUrl(null);
|
||||
$viewInBrowserLink = Url::getViewInBrowserUrl($this->newsletter);
|
||||
$mailerMetaInfo = new MetaInfo;
|
||||
|
||||
expect(is_array($newsletter))->true();
|
||||
expect($newsletter['body']['text'])->contains('Hello test');
|
||||
expect($subscriber)->equals($subscriber);
|
||||
expect($extraParams['unsubscribe_url'])->equals(home_url());
|
||||
expect($extraParams['meta'])->equals($mailerMetaInfo->getPreviewMetaInfo());
|
||||
|
||||
// system links are replaced with hashes
|
||||
expect($newsletter['body']['html'])->contains('href="' . $viewInBrowserLink . '">View in browser');
|
||||
expect($newsletter['body']['html'])->contains('href="' . $unsubscribeLink . '">Unsubscribe');
|
||||
expect($newsletter['body']['html'])->contains('href="' . $manageLink . '">Manage subscription');
|
||||
return ['response' => true];
|
||||
}
|
||||
),
|
||||
]);
|
||||
|
||||
$sendPreviewController = new SendPreviewController($mailer, new MetaInfo(), new WPFunctions());
|
||||
$sendPreviewController->sendPreview($this->newsletter, 'test@subscriber.com');
|
||||
}
|
||||
|
||||
public function testItThrowsWhenSendingFailed() {
|
||||
$mailer = $this->makeEmpty(Mailer::class, [
|
||||
'send' => function ($newsletter, $subscriber) {
|
||||
expect(is_array($newsletter))->true();
|
||||
expect($newsletter['body']['text'])->contains('Hello test');
|
||||
expect($subscriber)->equals($subscriber);
|
||||
return [
|
||||
'response' => false,
|
||||
'error' => $this->make(MailerError::class, [
|
||||
'getMessage' => 'failed',
|
||||
]),
|
||||
];
|
||||
},
|
||||
]);
|
||||
|
||||
$this->expectException(SendPreviewException::class);
|
||||
$this->expectExceptionMessage('The email could not be sent: failed');
|
||||
|
||||
$sendPreviewController = new SendPreviewController($mailer, new MetaInfo(), new WPFunctions());
|
||||
$sendPreviewController->sendPreview($this->newsletter, 'test@subscriber.com');
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user