geno/wp-content/plugins/mailpoet/lib/Newsletter/Scheduler/PostNotificationScheduler.php

217 lines
8.4 KiB
PHP
Raw Normal View History

2024-02-01 17:24:18 +05:30
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoet\Newsletter\Scheduler;
if (!defined('ABSPATH')) exit;
use MailPoet\Cron\Workers\SendingQueue\SendingQueue;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\NewsletterOptionEntity;
use MailPoet\Entities\NewsletterOptionFieldEntity;
use MailPoet\Entities\ScheduledTaskEntity;
use MailPoet\Entities\SendingQueueEntity;
use MailPoet\Logging\LoggerFactory;
use MailPoet\Newsletter\NewsletterPostsRepository;
use MailPoet\Newsletter\NewslettersRepository;
use MailPoet\Newsletter\Options\NewsletterOptionFieldsRepository;
use MailPoet\Newsletter\Options\NewsletterOptionsRepository;
use MailPoet\Newsletter\Sending\ScheduledTasksRepository;
use MailPoet\Newsletter\Sending\SendingQueuesRepository;
use MailPoet\WP\DateTime;
use MailPoet\WP\Posts;
class PostNotificationScheduler {
const SECONDS_IN_MINUTE = 60;
const SECONDS_IN_HOUR = 3600;
const LAST_WEEKDAY_FORMAT = 'L';
const INTERVAL_DAILY = 'daily';
const INTERVAL_IMMEDIATELY = 'immediately';
const INTERVAL_NTHWEEKDAY = 'nthWeekDay';
const INTERVAL_WEEKLY = 'weekly';
const INTERVAL_IMMEDIATE = 'immediate';
const INTERVAL_MONTHLY = 'monthly';
/** @var LoggerFactory */
private $loggerFactory;
/** @var NewslettersRepository */
private $newslettersRepository;
/** @var NewsletterOptionsRepository */
private $newsletterOptionsRepository;
/** @var NewsletterOptionFieldsRepository */
private $newsletterOptionFieldsRepository;
/** @var NewsletterPostsRepository */
private $newsletterPostsRepository;
/** @var Scheduler */
private $scheduler;
/*** @var ScheduledTasksRepository */
private $scheduledTasksRepository;
/*** @var SendingQueuesRepository */
private $sendingQueuesRepository;
public function __construct(
NewslettersRepository $newslettersRepository,
NewsletterOptionsRepository $newsletterOptionsRepository,
NewsletterOptionFieldsRepository $newsletterOptionFieldsRepository,
NewsletterPostsRepository $newsletterPostsRepository,
Scheduler $scheduler,
ScheduledTasksRepository $scheduledTasksRepository,
SendingQueuesRepository $sendingQueuesRepository
) {
$this->loggerFactory = LoggerFactory::getInstance();
$this->newslettersRepository = $newslettersRepository;
$this->newsletterOptionsRepository = $newsletterOptionsRepository;
$this->newsletterOptionFieldsRepository = $newsletterOptionFieldsRepository;
$this->newsletterPostsRepository = $newsletterPostsRepository;
$this->scheduler = $scheduler;
$this->scheduledTasksRepository = $scheduledTasksRepository;
$this->sendingQueuesRepository = $sendingQueuesRepository;
}
public function transitionHook($newStatus, $oldStatus, $post) {
$this->loggerFactory->getLogger(LoggerFactory::TOPIC_POST_NOTIFICATIONS)->info(
'transition post notification hook initiated',
[
'post_id' => $post->ID,
'new_status' => $newStatus,
'old_status' => $oldStatus,
]
);
$types = Posts::getTypes();
if (($newStatus !== 'publish') || !isset($types[$post->post_type])) { // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
return;
}
$this->schedulePostNotification($post->ID);
}
public function schedulePostNotification($postId) {
$this->loggerFactory->getLogger(LoggerFactory::TOPIC_POST_NOTIFICATIONS)->info(
'schedule post notification hook',
['post_id' => $postId]
);
$newsletters = $this->newslettersRepository->findActiveByTypes([NewsletterEntity::TYPE_NOTIFICATION]);
$this->newslettersRepository->prefetchOptions($newsletters);
if (!count($newsletters)) {
return false;
}
foreach ($newsletters as $newsletter) {
$post = $this->newsletterPostsRepository->findOneBy([
'newsletter' => $newsletter,
'postId' => $postId,
]);
if ($post === null) {
$this->createPostNotificationSendingTask($newsletter);
}
}
}
public function createPostNotificationSendingTask(NewsletterEntity $newsletter): ?ScheduledTaskEntity {
$notificationHistory = $this->newslettersRepository->findSendingNotificationHistoryWithoutPausedTask($newsletter);
if (count($notificationHistory) > 0) {
return null;
}
$scheduleOption = $newsletter->getOption(NewsletterOptionFieldEntity::NAME_SCHEDULE);
if (!$scheduleOption) {
return null;
}
$nextRunDate = $this->scheduler->getNextRunDateTime($scheduleOption->getValue());
if (!$nextRunDate) {
return null;
}
// do not schedule duplicate queues for the same time
$lastQueue = $newsletter->getLatestQueue();
$task = $lastQueue !== null ? $lastQueue->getTask() : null;
$scheduledAt = $task !== null ? $task->getScheduledAt() : null;
if ($scheduledAt && $scheduledAt->format('Y-m-d H:i:s') === $nextRunDate->format('Y-m-d H:i:s')) {
return null;
}
$scheduledTask = new ScheduledTaskEntity();
$scheduledTask->setType(SendingQueue::TASK_TYPE);
$scheduledTask->setStatus(ScheduledTaskEntity::STATUS_SCHEDULED);
$scheduledTask->setScheduledAt($nextRunDate);
$scheduledTask->setPriority(ScheduledTaskEntity::PRIORITY_MEDIUM);
$this->scheduledTasksRepository->persist($scheduledTask);
$this->scheduledTasksRepository->flush();
$sendingQueue = new SendingQueueEntity();
$sendingQueue->setNewsletter($newsletter);
$sendingQueue->setTask($scheduledTask);
$this->sendingQueuesRepository->persist($sendingQueue);
$this->sendingQueuesRepository->flush();
$scheduledTask->setSendingQueue($sendingQueue);
$this->loggerFactory->getLogger(LoggerFactory::TOPIC_POST_NOTIFICATIONS)->info(
'schedule post notification',
[
'sending_task' => $scheduledTask->getId(),
'scheduled_at' => $nextRunDate->format(DateTime::DEFAULT_DATE_TIME_FORMAT),
]
);
return $scheduledTask;
}
public function processPostNotificationSchedule(NewsletterEntity $newsletter) {
$intervalTypeOption = $newsletter->getOption(NewsletterOptionFieldEntity::NAME_INTERVAL_TYPE);
$intervalType = $intervalTypeOption ? $intervalTypeOption->getValue() : null;
$timeOfDayOption = $newsletter->getOption(NewsletterOptionFieldEntity::NAME_TIME_OF_DAY);
$hour = $timeOfDayOption ? (int)floor((int)$timeOfDayOption->getValue() / self::SECONDS_IN_HOUR) : null;
$minute = $timeOfDayOption ? ((int)$timeOfDayOption->getValue() - (int)($hour * self::SECONDS_IN_HOUR)) / self::SECONDS_IN_MINUTE : null;
$weekDayOption = $newsletter->getOption(NewsletterOptionFieldEntity::NAME_WEEK_DAY);
$weekDay = $weekDayOption ? $weekDayOption->getValue() : null;
$monthDayOption = $newsletter->getOption(NewsletterOptionFieldEntity::NAME_MONTH_DAY);
$monthDay = $monthDayOption ? $monthDayOption->getValue() : null;
$nthWeekDayOption = $newsletter->getOption(NewsletterOptionFieldEntity::NAME_NTH_WEEK_DAY);
$nthWeekDay = $nthWeekDayOption ? $nthWeekDayOption->getValue() : null;
$nthWeekDay = ($nthWeekDay === self::LAST_WEEKDAY_FORMAT) ? $nthWeekDay : '#' . $nthWeekDay;
switch ($intervalType) {
case self::INTERVAL_IMMEDIATE:
case self::INTERVAL_DAILY:
$schedule = sprintf('%s %s * * *', $minute, $hour);
break;
case self::INTERVAL_WEEKLY:
$schedule = sprintf('%s %s * * %s', $minute, $hour, $weekDay);
break;
case self::INTERVAL_NTHWEEKDAY:
$schedule = sprintf('%s %s ? * %s%s', $minute, $hour, $weekDay, $nthWeekDay);
break;
case self::INTERVAL_MONTHLY:
$schedule = sprintf('%s %s %s * *', $minute, $hour, $monthDay);
break;
case self::INTERVAL_IMMEDIATELY:
default:
$schedule = '* * * * *';
break;
}
$optionField = $this->newsletterOptionFieldsRepository->findOneBy([
'name' => NewsletterOptionFieldEntity::NAME_SCHEDULE,
]);
if (!$optionField instanceof NewsletterOptionFieldEntity) {
throw new \Exception('NewsletterOptionField for schedule doesnt exist.');
}
$scheduleOption = $newsletter->getOption(NewsletterOptionFieldEntity::NAME_SCHEDULE);
if ($scheduleOption === null) {
$scheduleOption = new NewsletterOptionEntity($newsletter, $optionField);
$newsletter->getOptions()->add($scheduleOption);
}
$scheduleOption->setValue($schedule);
$this->newsletterOptionsRepository->persist($scheduleOption);
$this->newsletterOptionsRepository->flush();
return $scheduleOption->getValue();
}
}