| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- <?php
- namespace MailPoet\Newsletter\Scheduler;
- if (!defined('ABSPATH')) exit;
- use MailPoet\Entities\NewsletterEntity;
- use MailPoet\Entities\NewsletterOptionEntity;
- use MailPoet\Entities\NewsletterOptionFieldEntity;
- use MailPoet\Logging\LoggerFactory;
- use MailPoet\Models\SendingQueue;
- use MailPoet\Newsletter\NewsletterPostsRepository;
- use MailPoet\Newsletter\NewslettersRepository;
- use MailPoet\Newsletter\Options\NewsletterOptionFieldsRepository;
- use MailPoet\Newsletter\Options\NewsletterOptionsRepository;
- use MailPoet\Tasks\Sending as SendingTask;
- use MailPoet\WP\Posts;
- class PostNotificationScheduler {
- 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;
- public function __construct(
- NewslettersRepository $newslettersRepository,
- NewsletterOptionsRepository $newsletterOptionsRepository,
- NewsletterOptionFieldsRepository $newsletterOptionFieldsRepository,
- NewsletterPostsRepository $newsletterPostsRepository
- ) {
- $this->loggerFactory = LoggerFactory::getInstance();
- $this->newslettersRepository = $newslettersRepository;
- $this->newsletterOptionsRepository = $newsletterOptionsRepository;
- $this->newsletterOptionFieldsRepository = $newsletterOptionFieldsRepository;
- $this->newsletterPostsRepository = $newsletterPostsRepository;
- }
- public function transitionHook($newStatus, $oldStatus, $post) {
- $this->loggerFactory->getLogger(LoggerFactory::TOPIC_POST_NOTIFICATIONS)->addInfo(
- '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)->addInfo(
- '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): ?SendingTask {
- $notificationHistory = $this->newslettersRepository->findSendigNotificationHistoryWithPausedTask($newsletter);
- if (count($notificationHistory) > 0) {
- return null;
- }
- $scheduleOption = $newsletter->getOption(NewsletterOptionFieldEntity::NAME_SCHEDULE);
- if (!$scheduleOption) {
- return null;
- }
- $nextRunDate = Scheduler::getNextRunDate($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) {
- return null;
- }
- $sendingTask = SendingTask::create();
- $sendingTask->newsletterId = $newsletter->getId();
- $sendingTask->status = SendingQueue::STATUS_SCHEDULED;
- $sendingTask->scheduledAt = $nextRunDate;
- $sendingTask->save();
- $this->loggerFactory->getLogger(LoggerFactory::TOPIC_POST_NOTIFICATIONS)->addInfo(
- 'schedule post notification',
- ['sending_task' => $sendingTask->id(), 'scheduled_at' => $nextRunDate]
- );
- return $sendingTask;
- }
- 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)$timeOfDayOption->getValue() / self::SECONDS_IN_HOUR : null;
- $weekDayOption = $newsletter->getOption(NewsletterOptionFieldEntity::NAME_WEK_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('0 %s * * *', $hour);
- break;
- case self::INTERVAL_WEEKLY:
- $schedule = sprintf('0 %s * * %s', $hour, $weekDay);
- break;
- case self::INTERVAL_NTHWEEKDAY:
- $schedule = sprintf('0 %s ? * %s%s', $hour, $weekDay, $nthWeekDay);
- break;
- case self::INTERVAL_MONTHLY:
- $schedule = sprintf('0 %s %s * *', $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 doesn’t 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();
- }
- }
|