Replace Newsletter model with Doctrine in SendingQueue

[MAILPOET-5737]
This commit is contained in:
Rodrigo Primo
2023-11-23 14:58:12 -03:00
committed by Aschepikov
parent d8973fe925
commit 4fe642916e
4 changed files with 40 additions and 64 deletions

View File

@@ -15,9 +15,7 @@ use MailPoet\InvalidStateException;
use MailPoet\Logging\LoggerFactory; use MailPoet\Logging\LoggerFactory;
use MailPoet\Mailer\MailerLog; use MailPoet\Mailer\MailerLog;
use MailPoet\Mailer\MetaInfo; use MailPoet\Mailer\MetaInfo;
use MailPoet\Models\Newsletter;
use MailPoet\Models\StatisticsNewsletters as StatisticsNewslettersModel; use MailPoet\Models\StatisticsNewsletters as StatisticsNewslettersModel;
use MailPoet\Newsletter\NewslettersRepository;
use MailPoet\Newsletter\Sending\ScheduledTasksRepository; use MailPoet\Newsletter\Sending\ScheduledTasksRepository;
use MailPoet\Newsletter\Sending\ScheduledTaskSubscribersRepository; use MailPoet\Newsletter\Sending\ScheduledTaskSubscribersRepository;
use MailPoet\Newsletter\Sending\SendingQueuesRepository; use MailPoet\Newsletter\Sending\SendingQueuesRepository;
@@ -56,9 +54,6 @@ class SendingQueue {
/** @var LoggerFactory */ /** @var LoggerFactory */
private $loggerFactory; private $loggerFactory;
/** @var NewslettersRepository */
private $newslettersRepository;
/** @var CronHelper */ /** @var CronHelper */
private $cronHelper; private $cronHelper;
@@ -94,7 +89,6 @@ class SendingQueue {
SendingThrottlingHandler $throttlingHandler, SendingThrottlingHandler $throttlingHandler,
StatsNotificationsScheduler $statsNotificationsScheduler, StatsNotificationsScheduler $statsNotificationsScheduler,
LoggerFactory $loggerFactory, LoggerFactory $loggerFactory,
NewslettersRepository $newslettersRepository,
CronHelper $cronHelper, CronHelper $cronHelper,
SubscribersFinder $subscriberFinder, SubscribersFinder $subscriberFinder,
SegmentsRepository $segmentsRepository, SegmentsRepository $segmentsRepository,
@@ -118,7 +112,6 @@ class SendingQueue {
$this->mailerMetaInfo = new MetaInfo; $this->mailerMetaInfo = new MetaInfo;
$this->wp = $wp; $this->wp = $wp;
$this->loggerFactory = $loggerFactory; $this->loggerFactory = $loggerFactory;
$this->newslettersRepository = $newslettersRepository;
$this->cronHelper = $cronHelper; $this->cronHelper = $cronHelper;
$this->links = $links; $this->links = $links;
$this->scheduledTasksRepository = $scheduledTasksRepository; $this->scheduledTasksRepository = $scheduledTasksRepository;
@@ -169,38 +162,30 @@ class SendingQueue {
$this->deleteTaskIfNewsletterDoesNotExist($task); $this->deleteTaskIfNewsletterDoesNotExist($task);
$queue = $task->getSendingQueue(); $queue = $task->getSendingQueue();
$newsletterEntity = $this->newsletterTask->getNewsletterFromQueue($task); $newsletter = $this->newsletterTask->getNewsletterFromQueue($task);
if (!$queue || !$newsletterEntity) { if (!$queue || !$newsletter) {
return; return;
} }
// pre-process newsletter (render, replace shortcodes/links, etc.) // pre-process newsletter (render, replace shortcodes/links, etc.)
$newsletterEntity = $this->newsletterTask->preProcessNewsletter($newsletterEntity, $task); $newsletter = $this->newsletterTask->preProcessNewsletter($newsletter, $task);
if (!$newsletterEntity) { if (!$newsletter) {
$this->deleteTask($task); $this->deleteTask($task);
return; return;
} }
$newsletter = Newsletter::findOne($newsletterEntity->getId()); $isTransactional = in_array($newsletter->getType(), [
if (!$newsletter) {
return;
}
$isTransactional = in_array($newsletter->type, [
NewsletterEntity::TYPE_AUTOMATION_TRANSACTIONAL, NewsletterEntity::TYPE_AUTOMATION_TRANSACTIONAL,
NewsletterEntity::TYPE_WC_TRANSACTIONAL_EMAIL, NewsletterEntity::TYPE_WC_TRANSACTIONAL_EMAIL,
]); ]);
// clone the original object to be used for processing
$_newsletter = (object)$newsletter->asArray();
$_newsletter->options = $newsletterEntity->getOptionsAsArray();
// configure mailer // configure mailer
$this->mailerTask->configureMailer($newsletter); $this->mailerTask->configureMailer($newsletter);
// get newsletter segments // get newsletter segments
$newsletterSegmentsIds = $newsletterEntity->getSegmentIds(); $newsletterSegmentsIds = $newsletter->getSegmentIds();
$segmentIdsToCheck = $newsletterSegmentsIds; $segmentIdsToCheck = $newsletterSegmentsIds;
$filterSegmentId = $newsletterEntity->getFilterSegmentId(); $filterSegmentId = $newsletter->getFilterSegmentId();
if (is_int($filterSegmentId)) { if (is_int($filterSegmentId)) {
$segmentIdsToCheck[] = $filterSegmentId; $segmentIdsToCheck[] = $filterSegmentId;
@@ -214,7 +199,7 @@ class SendingQueue {
); );
$task->setStatus(ScheduledTaskEntity::STATUS_PAUSED); $task->setStatus(ScheduledTaskEntity::STATUS_PAUSED);
$this->scheduledTasksRepository->flush(); $this->scheduledTasksRepository->flush();
$this->wp->setTransient(self::EMAIL_WITH_INVALID_SEGMENT_OPTION, $newsletter->subject); $this->wp->setTransient(self::EMAIL_WITH_INVALID_SEGMENT_OPTION, $newsletter->getSubject());
return; return;
} }
@@ -232,7 +217,7 @@ class SendingQueue {
foreach ($subscriberBatches as $subscribersToProcessIds) { foreach ($subscriberBatches as $subscribersToProcessIds) {
$this->loggerFactory->getLogger(LoggerFactory::TOPIC_NEWSLETTERS)->info( $this->loggerFactory->getLogger(LoggerFactory::TOPIC_NEWSLETTERS)->info(
'subscriber batch processing', 'subscriber batch processing',
['newsletter_id' => $newsletter->id, 'task_id' => $task->getId(), 'subscriber_batch_count' => count($subscribersToProcessIds)] ['newsletter_id' => $newsletter->getId(), 'task_id' => $task->getId(), 'subscriber_batch_count' => count($subscribersToProcessIds)]
); );
if (!empty($newsletterSegmentsIds[0])) { if (!empty($newsletterSegmentsIds[0])) {
// Check that subscribers are in segments // Check that subscribers are in segments
@@ -259,7 +244,7 @@ class SendingQueue {
->setParameter('subscriberIds', $subscribersToProcessIds) ->setParameter('subscriberIds', $subscribersToProcessIds)
->andWhere('s.deletedAt IS NULL'); ->andWhere('s.deletedAt IS NULL');
if ($newsletterEntity->getType() === NewsletterEntity::TYPE_AUTOMATION_TRANSACTIONAL) { if ($newsletter->getType() === NewsletterEntity::TYPE_AUTOMATION_TRANSACTIONAL) {
$queryBuilder->andWhere('s.status != :bouncedStatus') $queryBuilder->andWhere('s.status != :bouncedStatus')
->setParameter('bouncedStatus', SubscriberEntity::STATUS_BOUNCED); ->setParameter('bouncedStatus', SubscriberEntity::STATUS_BOUNCED);
} else { } else {
@@ -285,7 +270,7 @@ class SendingQueue {
$this->sendingQueuesRepository->updateCounts($queue); $this->sendingQueuesRepository->updateCounts($queue);
if (!$queue->getCountToProcess()) { if (!$queue->getCountToProcess()) {
$this->newsletterTask->markNewsletterAsSent($newsletterEntity); $this->newsletterTask->markNewsletterAsSent($newsletter);
continue; continue;
} }
// if there aren't any subscribers to process in batch (e.g. all unsubscribed or were deleted) continue with next batch // if there aren't any subscribers to process in batch (e.g. all unsubscribed or were deleted) continue with next batch
@@ -295,16 +280,16 @@ class SendingQueue {
} }
$this->loggerFactory->getLogger(LoggerFactory::TOPIC_NEWSLETTERS)->info( $this->loggerFactory->getLogger(LoggerFactory::TOPIC_NEWSLETTERS)->info(
'before queue chunk processing', 'before queue chunk processing',
['newsletter_id' => $newsletter->id, 'task_id' => $task->getId(), 'found_subscribers_count' => count($foundSubscribers)] ['newsletter_id' => $newsletter->getId(), 'task_id' => $task->getId(), 'found_subscribers_count' => count($foundSubscribers)]
); );
// reschedule bounce task to run sooner, if needed // reschedule bounce task to run sooner, if needed
$this->reScheduleBounceTask(); $this->reScheduleBounceTask();
if ($newsletterEntity->getStatus() !== NewsletterEntity::STATUS_CORRUPT) { if ($newsletter->getStatus() !== NewsletterEntity::STATUS_CORRUPT) {
$this->processQueue( $this->processQueue(
$task, $task,
$_newsletter, $newsletter,
$foundSubscribers, $foundSubscribers,
$timer $timer
); );
@@ -318,22 +303,22 @@ class SendingQueue {
} }
$this->loggerFactory->getLogger(LoggerFactory::TOPIC_NEWSLETTERS)->info( $this->loggerFactory->getLogger(LoggerFactory::TOPIC_NEWSLETTERS)->info(
'after queue chunk processing', 'after queue chunk processing',
['newsletter_id' => $newsletter->id, 'task_id' => $task->getId()] ['newsletter_id' => $newsletter->getId(), 'task_id' => $task->getId()]
); );
if ($task->getStatus() === ScheduledTaskEntity::STATUS_COMPLETED) { if ($task->getStatus() === ScheduledTaskEntity::STATUS_COMPLETED) {
$this->loggerFactory->getLogger(LoggerFactory::TOPIC_NEWSLETTERS)->info( $this->loggerFactory->getLogger(LoggerFactory::TOPIC_NEWSLETTERS)->info(
'completed newsletter sending', 'completed newsletter sending',
['newsletter_id' => $newsletter->id, 'task_id' => $task->getId()] ['newsletter_id' => $newsletter->getId(), 'task_id' => $task->getId()]
); );
$this->newsletterTask->markNewsletterAsSent($newsletterEntity); $this->newsletterTask->markNewsletterAsSent($newsletter);
$this->statsNotificationsScheduler->schedule($newsletterEntity); $this->statsNotificationsScheduler->schedule($newsletter);
} }
$this->enforceSendingAndExecutionLimits($timer); $this->enforceSendingAndExecutionLimits($timer);
} else { } else {
$this->sendingQueuesRepository->pause($queue); $this->sendingQueuesRepository->pause($queue);
$this->loggerFactory->getLogger(LoggerFactory::TOPIC_NEWSLETTERS)->error( $this->loggerFactory->getLogger(LoggerFactory::TOPIC_NEWSLETTERS)->error(
'Can\'t send corrupt newsletter', 'Can\'t send corrupt newsletter',
['newsletter_id' => $newsletter->id, 'task_id' => $task->getId()] ['newsletter_id' => $newsletter->getId(), 'task_id' => $task->getId()]
); );
} }
} }
@@ -346,7 +331,7 @@ class SendingQueue {
/** /**
* @param SubscriberEntity[] $subscribers * @param SubscriberEntity[] $subscribers
*/ */
public function processQueue(ScheduledTaskEntity $task, $newsletter, array $subscribers, $timer) { public function processQueue(ScheduledTaskEntity $task, NewsletterEntity $newsletter, array $subscribers, $timer) {
// determine if processing is done in bulk or individually // determine if processing is done in bulk or individually
$processingMethod = $this->mailerTask->getProcessingMethod(); $processingMethod = $this->mailerTask->getProcessingMethod();
$preparedNewsletters = []; $preparedNewsletters = [];
@@ -364,16 +349,11 @@ class SendingQueue {
$sendingQueueMeta = $sendingQueueEntity->getMeta() ?? []; $sendingQueueMeta = $sendingQueueEntity->getMeta() ?? [];
$campaignId = $sendingQueueMeta['campaignId'] ?? null; $campaignId = $sendingQueueMeta['campaignId'] ?? null;
$newsletterEntity = $this->newslettersRepository->findOneById($newsletter->id);
if (!$newsletterEntity) {
return;
}
foreach ($subscribers as $subscriber) { foreach ($subscribers as $subscriber) {
// render shortcodes and replace subscriber data in tracked links // render shortcodes and replace subscriber data in tracked links
$preparedNewsletters[] = $preparedNewsletters[] =
$this->newsletterTask->prepareNewsletterForSending( $this->newsletterTask->prepareNewsletterForSending(
$newsletterEntity, $newsletter,
$subscriber, $subscriber,
$sendingQueueEntity $sendingQueueEntity
); );
@@ -386,7 +366,7 @@ class SendingQueue {
$unsubscribeUrls[] = $this->links->getUnsubscribeUrl($sendingQueueEntity->getId(), $subscriber); $unsubscribeUrls[] = $this->links->getUnsubscribeUrl($sendingQueueEntity->getId(), $subscriber);
$oneClickUnsubscribeUrls[] = $this->links->getOneClickUnsubscribeUrl($sendingQueueEntity->getId(), $subscriber); $oneClickUnsubscribeUrls[] = $this->links->getOneClickUnsubscribeUrl($sendingQueueEntity->getId(), $subscriber);
$metasForSubscriber = $this->mailerMetaInfo->getNewsletterMetaInfo($newsletterEntity, $subscriber); $metasForSubscriber = $this->mailerMetaInfo->getNewsletterMetaInfo($newsletter, $subscriber);
if ($campaignId) { if ($campaignId) {
$metasForSubscriber['campaign_id'] = $campaignId; $metasForSubscriber['campaign_id'] = $campaignId;
} }
@@ -394,7 +374,7 @@ class SendingQueue {
// keep track of values for statistics purposes // keep track of values for statistics purposes
$statistics[] = [ $statistics[] = [
'newsletter_id' => $newsletter->id, 'newsletter_id' => $newsletter->getId(),
'subscriber_id' => $subscriber->getId(), 'subscriber_id' => $subscriber->getId(),
'queue_id' => $sendingQueueEntity->getId(), 'queue_id' => $sendingQueueEntity->getId(),
]; ];

View File

@@ -2,6 +2,7 @@
namespace MailPoet\Cron\Workers\SendingQueue\Tasks; namespace MailPoet\Cron\Workers\SendingQueue\Tasks;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\SubscriberEntity; use MailPoet\Entities\SubscriberEntity;
use MailPoet\Mailer\Mailer as MailerInstance; use MailPoet\Mailer\Mailer as MailerInstance;
use MailPoet\Mailer\MailerFactory; use MailPoet\Mailer\MailerFactory;
@@ -23,18 +24,18 @@ class Mailer {
$this->mailer = $this->configureMailer(); $this->mailer = $this->configureMailer();
} }
public function configureMailer($newsletter = null) { public function configureMailer(NewsletterEntity $newsletter = null) {
$sender['address'] = (!empty($newsletter->senderAddress)) ? $sender['address'] = ($newsletter && !empty($newsletter->getSenderAddress())) ?
$newsletter->senderAddress : $newsletter->getSenderAddress() :
null; null;
$sender['name'] = (!empty($newsletter->senderName)) ? $sender['name'] = ($newsletter && !empty($newsletter->getSenderName())) ?
$newsletter->senderName : $newsletter->getSenderName() :
null; null;
$replyTo['address'] = (!empty($newsletter->replyToAddress)) ? $replyTo['address'] = ($newsletter && !empty($newsletter->getReplyToAddress())) ?
$newsletter->replyToAddress : $newsletter->getReplyToAddress() :
null; null;
$replyTo['name'] = (!empty($newsletter->replyToName)) ? $replyTo['name'] = ($newsletter && !empty($newsletter->getReplyToName())) ?
$newsletter->replyToName : $newsletter->getReplyToName() :
null; null;
if (!$sender['address']) { if (!$sender['address']) {
$sender = null; $sender = null;

View File

@@ -206,7 +206,6 @@ class SendingQueueTest extends \MailPoetTest {
$this->sendingThrottlingHandler, $this->sendingThrottlingHandler,
$this->statsNotificationsWorker, $this->statsNotificationsWorker,
$this->loggerFactory, $this->loggerFactory,
$this->newslettersRepository,
$this->cronHelper, $this->cronHelper,
$this->subscribersFinder, $this->subscribersFinder,
$this->segmentsRepository, $this->segmentsRepository,
@@ -238,7 +237,6 @@ class SendingQueueTest extends \MailPoetTest {
$this->sendingThrottlingHandler, $this->sendingThrottlingHandler,
$this->statsNotificationsWorker, $this->statsNotificationsWorker,
$this->loggerFactory, $this->loggerFactory,
$this->makeEmpty(NewslettersRepository::class),
$this->cronHelper, $this->cronHelper,
$this->subscribersFinder, $this->subscribersFinder,
$this->segmentsRepository, $this->segmentsRepository,
@@ -287,7 +285,6 @@ class SendingQueueTest extends \MailPoetTest {
$this->sendingThrottlingHandler, $this->sendingThrottlingHandler,
$this->statsNotificationsWorker, $this->statsNotificationsWorker,
$this->loggerFactory, $this->loggerFactory,
$this->makeEmpty(NewslettersRepository::class),
$this->cronHelper, $this->cronHelper,
$this->subscribersFinder, $this->subscribersFinder,
$this->segmentsRepository, $this->segmentsRepository,
@@ -334,7 +331,6 @@ class SendingQueueTest extends \MailPoetTest {
$this->sendingThrottlingHandler, $this->sendingThrottlingHandler,
$this->statsNotificationsWorker, $this->statsNotificationsWorker,
$this->loggerFactory, $this->loggerFactory,
$this->newslettersRepository,
$this->cronHelper, $this->cronHelper,
$this->subscribersFinder, $this->subscribersFinder,
$this->segmentsRepository, $this->segmentsRepository,
@@ -651,7 +647,6 @@ class SendingQueueTest extends \MailPoetTest {
$this->sendingThrottlingHandler, $this->sendingThrottlingHandler,
$this->statsNotificationsWorker, $this->statsNotificationsWorker,
$this->loggerFactory, $this->loggerFactory,
$this->makeEmpty(NewslettersRepository::class),
$this->cronHelper, $this->cronHelper,
$this->subscribersFinder, $this->subscribersFinder,
$this->segmentsRepository, $this->segmentsRepository,
@@ -1112,7 +1107,6 @@ class SendingQueueTest extends \MailPoetTest {
$this->sendingThrottlingHandler, $this->sendingThrottlingHandler,
$this->statsNotificationsWorker, $this->statsNotificationsWorker,
$this->loggerFactory, $this->loggerFactory,
$this->makeEmpty(NewslettersRepository::class),
$this->cronHelper, $this->cronHelper,
$this->subscribersFinder, $this->subscribersFinder,
$this->segmentsRepository, $this->segmentsRepository,
@@ -1447,7 +1441,6 @@ class SendingQueueTest extends \MailPoetTest {
$this->sendingThrottlingHandler, $this->sendingThrottlingHandler,
$this->statsNotificationsWorker, $this->statsNotificationsWorker,
$this->loggerFactory, $this->loggerFactory,
$this->newslettersRepository,
$this->cronHelper, $this->cronHelper,
$this->subscribersFinder, $this->subscribersFinder,
$this->segmentsRepository, $this->segmentsRepository,

View File

@@ -9,6 +9,7 @@ use MailPoet\Cron\Workers\SendingQueue\Tasks\Mailer as MailerTask;
use MailPoet\Mailer\Mailer; use MailPoet\Mailer\Mailer;
use MailPoet\Mailer\MailerFactory; use MailPoet\Mailer\MailerFactory;
use MailPoet\Settings\SettingsController; use MailPoet\Settings\SettingsController;
use MailPoet\Test\DataFactories\Newsletter as NewsletterFactory;
use MailPoet\Test\DataFactories\Subscriber as SubscriberFactory; use MailPoet\Test\DataFactories\Subscriber as SubscriberFactory;
class MailerTest extends \MailPoetTest { class MailerTest extends \MailPoetTest {
@@ -33,11 +34,12 @@ class MailerTest extends \MailPoetTest {
} }
public function testItCanConfigureMailerWithSenderAndReplyToAddressesFromEmail() { public function testItCanConfigureMailerWithSenderAndReplyToAddressesFromEmail() {
$newsletter = new \stdClass(); $newsletter = (new NewsletterFactory())
$newsletter->senderName = 'Sender'; ->withSenderName('Sender')
$newsletter->senderAddress = 'from@example.com'; ->withSenderAddress('from@example.com')
$newsletter->replyToName = 'Reply-to'; ->withReplyToName('Reply-to')
$newsletter->replyToAddress = 'reply-to@example.com'; ->withReplyToAddress('reply-to@example.com')
->create();
$mailerFactoryMock = $this->createMock(MailerFactory::class); $mailerFactoryMock = $this->createMock(MailerFactory::class);
// First call in constructor // First call in constructor