Reschedule post notifications using Doctrine

[MAILPOET-2900]
This commit is contained in:
Jan Jakeš
2020-05-13 10:52:31 +02:00
committed by Veljko V
parent 86a24ad674
commit 7bea9a03a7
3 changed files with 68 additions and 16 deletions

View File

@ -274,6 +274,7 @@ class ContainerConfigurator implements IContainerConfigurator {
$container->autowire(\MailPoet\Newsletter\Statistics\NewsletterStatisticsRepository::class); $container->autowire(\MailPoet\Newsletter\Statistics\NewsletterStatisticsRepository::class);
$container->autowire(\MailPoet\Newsletter\Scheduler\WelcomeScheduler::class)->setPublic(true); $container->autowire(\MailPoet\Newsletter\Scheduler\WelcomeScheduler::class)->setPublic(true);
$container->autowire(\MailPoet\Newsletter\Scheduler\PostNotificationScheduler::class); $container->autowire(\MailPoet\Newsletter\Scheduler\PostNotificationScheduler::class);
$container->autowire(\MailPoet\Newsletter\Sending\ScheduledTasksRepository::class);
$container->autowire(\MailPoet\Newsletter\Sending\SendingQueuesRepository::class); $container->autowire(\MailPoet\Newsletter\Sending\SendingQueuesRepository::class);
$container->autowire(\MailPoet\Newsletter\ViewInBrowser\ViewInBrowserController::class)->setPublic(true); $container->autowire(\MailPoet\Newsletter\ViewInBrowser\ViewInBrowserController::class)->setPublic(true);
$container->autowire(\MailPoet\Newsletter\ViewInBrowser\ViewInBrowserRenderer::class)->setPublic(true); $container->autowire(\MailPoet\Newsletter\ViewInBrowser\ViewInBrowserRenderer::class)->setPublic(true);

View File

@ -2,19 +2,21 @@
namespace MailPoet\Newsletter; namespace MailPoet\Newsletter;
use Carbon\Carbon;
use MailPoet\Cron\Workers\SendingQueue\Tasks\Newsletter as NewsletterQueueTask; use MailPoet\Cron\Workers\SendingQueue\Tasks\Newsletter as NewsletterQueueTask;
use MailPoet\Entities\NewsletterEntity; use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\NewsletterOptionEntity; use MailPoet\Entities\NewsletterOptionEntity;
use MailPoet\Entities\NewsletterSegmentEntity; use MailPoet\Entities\NewsletterSegmentEntity;
use MailPoet\Entities\ScheduledTaskEntity;
use MailPoet\Entities\SegmentEntity; use MailPoet\Entities\SegmentEntity;
use MailPoet\InvalidStateException; use MailPoet\InvalidStateException;
use MailPoet\Models\Newsletter; use MailPoet\Models\Newsletter;
use MailPoet\Models\SendingQueue;
use MailPoet\Newsletter\Options\NewsletterOptionFieldsRepository; use MailPoet\Newsletter\Options\NewsletterOptionFieldsRepository;
use MailPoet\Newsletter\Options\NewsletterOptionsRepository; use MailPoet\Newsletter\Options\NewsletterOptionsRepository;
use MailPoet\Newsletter\Scheduler\PostNotificationScheduler; use MailPoet\Newsletter\Scheduler\PostNotificationScheduler;
use MailPoet\Newsletter\Scheduler\Scheduler; use MailPoet\Newsletter\Scheduler\Scheduler;
use MailPoet\Newsletter\Segment\NewsletterSegmentRepository; use MailPoet\Newsletter\Segment\NewsletterSegmentRepository;
use MailPoet\Newsletter\Sending\ScheduledTasksRepository;
use MailPoet\Newsletter\Url as NewsletterUrl; use MailPoet\Newsletter\Url as NewsletterUrl;
use MailPoet\NewsletterTemplates\NewsletterTemplatesRepository; use MailPoet\NewsletterTemplates\NewsletterTemplatesRepository;
use MailPoet\NotFoundException; use MailPoet\NotFoundException;
@ -53,6 +55,9 @@ class NewsletterSaveController {
/** @var PostNotificationScheduler */ /** @var PostNotificationScheduler */
private $postNotificationScheduler; private $postNotificationScheduler;
/** @var ScheduledTasksRepository */
private $scheduledTasksRepository;
/** @var SettingsController */ /** @var SettingsController */
private $settings; private $settings;
@ -69,6 +74,7 @@ class NewsletterSaveController {
NewsletterSegmentRepository $newsletterSegmentRepository, NewsletterSegmentRepository $newsletterSegmentRepository,
NewsletterTemplatesRepository $newsletterTemplatesRepository, NewsletterTemplatesRepository $newsletterTemplatesRepository,
PostNotificationScheduler $postNotificationScheduler, PostNotificationScheduler $postNotificationScheduler,
ScheduledTasksRepository $scheduledTasksRepository,
SettingsController $settings, SettingsController $settings,
WPFunctions $wp WPFunctions $wp
) { ) {
@ -81,6 +87,7 @@ class NewsletterSaveController {
$this->newsletterSegmentRepository = $newsletterSegmentRepository; $this->newsletterSegmentRepository = $newsletterSegmentRepository;
$this->newsletterTemplatesRepository = $newsletterTemplatesRepository; $this->newsletterTemplatesRepository = $newsletterTemplatesRepository;
$this->postNotificationScheduler = $postNotificationScheduler; $this->postNotificationScheduler = $postNotificationScheduler;
$this->scheduledTasksRepository = $scheduledTasksRepository;
$this->settings = $settings; $this->settings = $settings;
$this->wp = $wp; $this->wp = $wp;
} }
@ -124,22 +131,9 @@ class NewsletterSaveController {
]); ]);
} }
$options = $data['options'] ?? []; $this->rescheduleIfNeeded($newsletter, $newsletterModel);
if ($options) {
// if this is a post notification, process newsletter options and update its schedule
if ($newsletterModel->type === Newsletter::TYPE_NOTIFICATION) {
// generate the new schedule from options and get the new "next run" date
$newsletterModel->schedule = $this->postNotificationScheduler->processPostNotificationSchedule($newsletterModel);
$nextRunDate = Scheduler::getNextRunDate($newsletterModel->schedule);
// find previously scheduled jobs and reschedule them using the new "next run" date
SendingQueue::findTaskByNewsletterId($newsletterModel->id)
->where('tasks.status', SendingQueue::STATUS_SCHEDULED)
->findResultSet()
->set('scheduled_at', $nextRunDate)
->save();
}
}
$options = $data['options'] ?? [];
$queue = $newsletterModel->getQueue(); $queue = $newsletterModel->getQueue();
if ($queue && !in_array($newsletterModel->type, [Newsletter::TYPE_NOTIFICATION, Newsletter::TYPE_NOTIFICATION_HISTORY])) { if ($queue && !in_array($newsletterModel->type, [Newsletter::TYPE_NOTIFICATION, Newsletter::TYPE_NOTIFICATION_HISTORY])) {
// if newsletter was previously scheduled and is now unscheduled, set its status to DRAFT and delete associated queue record // if newsletter was previously scheduled and is now unscheduled, set its status to DRAFT and delete associated queue record
@ -274,4 +268,27 @@ class NewsletterSaveController {
$this->entityManager->flush(); $this->entityManager->flush();
} }
private function rescheduleIfNeeded(NewsletterEntity $newsletter, Newsletter $newsletterModel) {
if ($newsletter->getType() !== NewsletterEntity::TYPE_NOTIFICATION) {
return;
}
// generate the new schedule from options and get the new "next run" date
$schedule = $this->postNotificationScheduler->processPostNotificationSchedule($newsletterModel);
$nextRunDateString = Scheduler::getNextRunDate($schedule);
$nextRunDate = $nextRunDateString ? Carbon::createFromFormat('Y-m-d H:i:s', $nextRunDateString) : null;
// find previously scheduled jobs and reschedule them
$scheduledTasks = $this->scheduledTasksRepository->findByNewsletterAndStatus($newsletter, ScheduledTaskEntity::STATUS_SCHEDULED);
foreach ($scheduledTasks as $scheduledTask) {
$scheduledTask->setScheduledAt($nextRunDate);
}
$this->entityManager->flush();
// 'processPostNotificationSchedule' modifies newsletter options by old model - let's reload them
foreach ($newsletter->getOptions() as $newsletterOption) {
$this->entityManager->refresh($newsletterOption);
}
}
} }

View File

@ -0,0 +1,34 @@
<?php
namespace MailPoet\Newsletter\Sending;
use MailPoet\Doctrine\Repository;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\ScheduledTaskEntity;
use MailPoet\Entities\SendingQueueEntity;
use MailPoetVendor\Doctrine\ORM\Query\Expr\Join;
/**
* @extends Repository<ScheduledTaskEntity>
*/
class ScheduledTasksRepository extends Repository {
/**
* @param NewsletterEntity $newsletter
* @return ScheduledTaskEntity[]
*/
public function findByNewsletterAndStatus(NewsletterEntity $newsletter, string $status): array {
return $this->doctrineRepository->createQueryBuilder('st')
->select('st')
->join(SendingQueueEntity::class, 'sq', Join::WITH, 'st = sq.task')
->andWhere('st.status = :status')
->andWhere('sq.newsletter = :newsletter')
->setParameter('status', $status)
->setParameter('newsletter', $newsletter)
->getQuery()
->getResult();
}
protected function getEntityClassName() {
return ScheduledTaskEntity::class;
}
}