geno/wp-content/plugins/mailpoet/lib/Newsletter/Scheduler/PostNotificationScheduler.php
2024-02-01 11:54:18 +00:00

216 lines
8.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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();
}
}