PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.21.2
MailPoet – Newsletters, Email Marketing, and Automation v5.21.2
5.28.1 5.28.0 5.27.0 5.26.0 5.26.1 5.25.0 5.24.0 4.43.0 4.43.1 4.44.0 4.44.1 4.45.0 4.46.0 4.47.0 4.48.0 4.48.1 4.48.2 4.49.0 4.49.1 4.5.0 4.5.1 4.5.2 4.50.0 4.50.1 4.51.0 4.51.1 4.51.2 4.52.0 4.53.0 4.54.0 4.55.0 4.56.0 4.57.0 4.58.0 4.58.1 4.58.2 4.6.0 4.6.1 4.6.2 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 5.0.0 5.0.1 5.0.2 5.1.0 5.1.1 5.10.0 5.10.1 5.11.0 5.12.0 5.12.1 5.12.10 5.12.11 5.12.12 5.12.13 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.12.7 5.12.8 5.12.9 5.13.0 5.13.1 5.13.2 5.14.0 5.14.1 5.14.2 5.14.3 5.15.0 5.15.1 5.16.0 5.16.1 5.16.2 5.16.3 5.16.4 5.17.0 5.17.1 5.17.2 5.17.3 5.17.4 5.17.5 5.17.6 5.18.0 5.19.0 5.2.0 5.2.1 5.2.2 5.2.3 5.20.0 5.21.0 5.21.1 5.21.2 5.21.3 5.22.0 5.22.1 5.22.2 5.22.3 5.22.4 5.23.0 5.23.1 5.23.2 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.4.0 5.4.1 5.4.2 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.6.3 5.6.4 5.7.0 5.7.1 5.8.0 5.8.1 5.9.0 3.0.0-beta.15 3.7.1 3.0.0-beta.16 3.7.2 3.0.0-beta.17 3.7.3 3.0.0-beta.18 3.7.4 3.0.0-beta.19 3.7.5 3.0.0-beta.2 3.7.6 3.0.0-beta.20 3.7.8 3.0.0-beta.21 3.70.0 3.0.0-beta.22 3.71.0 3.0.0-beta.23 3.71.1 3.0.0-beta.23.1 3.71.2 3.0.0-beta.23.2 3.71.3 3.0.0-beta.24 3.72.0 3.0.0-beta.25 3.73.0 3.0.0-beta.26 3.73.1 3.0.0-beta.27 3.73.2 3.0.0-beta.28 3.74.0 3.0.0-beta.29 3.74.1 3.0.0-beta.3 3.74.2 3.0.0-beta.30 3.74.3 3.0.0-beta.31 3.75.0 3.0.0-beta.32 3.75.1 3.0.0-beta.33 3.76.0 3.0.0-beta.33.1 3.77.0 3.0.0-beta.34.0.0 3.77.1 3.0.0-beta.36.0.0 3.78.0 3.0.0-beta.36.0.1 3.79.0 3.0.0-beta.36.2.0 3.8 3.0.0-beta.36.3.0 3.8.1 3.0.0-beta.36.3.1 3.8.2 3.0.0-beta.37.0.0 3.8.3 3.0.0-beta.4 3.8.4 3.0.0-beta.5 3.8.5 3.0.0-beta.6 3.8.6 3.0.0-beta.7 3.80.0 3.0.0-beta.7.1 3.81.0 3.0.0-beta.8 3.82.0 3.0.0-beta.9 3.83.0 3.0.0-rc.1.0.0 3.84.0 3.0.0-rc.1.0.1 3.84.1 3.0.0-rc.1.0.2 3.85.0 3.0.0-rc.1.0.3 3.85.1 3.0.0-rc.1.0.4 3.86.0 3.0.0-rc.2.0.0 3.87.0 3.0.0-rc.2.0.1 3.87.1 3.0.0-rc.2.0.2 3.87.2 3.0.0-rc.2.0.3 3.88.0 3.0.1 3.88.1 3.0.2 3.88.2 3.0.3 3.89.0 3.0.4 3.89.1 3.0.5 3.89.2 3.0.6 3.89.3 3.0.7 3.89.4 3.0.8 3.9.0 3.0.9 3.9.1 3.1.0 3.90.0 3.10 3.90.1 3.10.1 3.90.2 3.100.0 3.91.0 3.100.1 3.91.1 3.100.2 3.92.0 3.101.0 3.92.1 3.101.1 3.93.0 3.102.0 3.93.1 3.102.1 3.94.0 3.103.0 3.95.0 3.103.1 3.95.1 3.11.0 3.96.0 3.11.1 3.96.1 3.11.2 3.97.0 3.11.3 3.98.0 3.11.4 3.98.1 3.11.5 3.99.0 3.12.0 3.99.1 3.12.1 4.0.0 3.13.0 4.0.1 3.14.0 4.1.0 3.14.1 4.1.1 3.15.0 4.10.0 3.16.0 4.11.0 3.16.1 4.11.1 3.16.2 4.12.0 3.16.3 4.12.1 3.17.0 4.12.2 3.17.1 4.13.0 3.17.2 4.14.0 3.18.0 4.15.0 3.18.1 4.16.0 3.18.2 4.17.0 3.19.0 4.17.1 3.19.1 4.18.0 3.19.2 4.18.1 3.19.3 4.19.0 3.2.0 4.2.0 3.2.1 4.20.0 3.2.2 4.20.1 3.2.3 4.20.2 3.2.4 4.21.0 3.2.5 4.22.0 3.20.0 4.22.1 3.21.0 4.22.2 3.21.1 4.23.0 3.22.0 4.24.0 3.23.0 4.25.0 3.23.1 4.26.0 3.23.2 4.26.1 3.24.0 4.27.0 3.25.0 4.28.0 3.25.1 4.29.0 3.26.0 4.3.0 3.26.1 4.3.1 3.27.0 4.30.0 3.28.0 4.31.0 3.29.0 4.31.1 3.3.0 4.32.0 3.3.1 4.33.0 3.3.2 4.34.0 3.3.3 4.35.0 3.3.4 4.35.1 3.3.5 4.36.0 3.3.6 4.37.0 3.30.0 4.38.0 3.31.0 4.39.0 3.31.1 4.4.0 3.32.0 4.40.0 3.32.1 4.41.0 3.32.2 4.41.1 3.33.0 4.41.2 3.34.0 4.41.3 3.34.1 4.42.0 3.34.2 4.42.1 3.34.3 3.34.4 3.35.0 3.35.1 3.35.3 3.35.4 3.36.0 3.37.0 3.37.1 3.37.2 3.37.3 3.38.0 3.38.1 3.39.0 3.39.1 3.39.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.40.0 3.40.1 3.41.0 3.41.1 3.41.2 3.42.0 3.42.1 3.42.2 3.42.3 3.43.0 3.43.1 3.44.0 3.45.0 3.45.1 3.46.0 3.46.1 3.46.10 3.46.11 3.46.12 3.46.13 3.46.14 3.46.2 3.46.3 3.46.4 3.46.5 3.46.6 3.46.7 3.46.8 3.46.9 3.47.0 3.47.1 3.47.10 3.47.11 3.47.2 3.47.3 3.47.5 3.47.6 3.47.7 3.47.9 3.48.0 3.48.1 3.49.0 3.49.1 3.5.0 3.5.1 3.50.0 3.51.0 3.51.1 3.51.2 3.52.0 3.53.0 3.54.0 3.54.1 3.54.2 3.54.3 3.55.0 3.55.1 3.56.0 3.56.1 3.56.2 3.57.0 3.57.1 3.58.0 3.59.0 3.59.1 3.59.2 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.60.0 3.60.1 3.60.10 3.60.11 3.60.12 3.60.2 3.60.3 3.60.4 3.60.6 3.60.7 3.60.8 3.60.9 3.61.0 3.62.0 3.62.1 3.63.0 3.64.0 3.64.1 3.64.2 3.64.3 3.65.0 trunk 3.65.1 3.0.0 3.66.0 3.0.0-beta.1 3.67.0 3.0.0-beta.10 3.67.1 3.0.0-beta.11 3.68.0 3.0.0-beta.12 3.69.0 3.0.0-beta.13 3.69.1 3.0.0-beta.14 3.7.0
mailpoet / lib / Newsletter / Scheduler / AutomaticEmailScheduler.php
mailpoet / lib / Newsletter / Scheduler Last commit date
AutomaticEmailScheduler.php 2 years ago AutomationEmailScheduler.php 1 year ago PostNotificationScheduler.php 2 years ago ReEngagementScheduler.php 1 year ago Scheduler.php 1 year ago WelcomeScheduler.php 2 years ago index.php 3 years ago
AutomaticEmailScheduler.php
196 lines
1 <?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
2
3 namespace MailPoet\Newsletter\Scheduler;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use MailPoet\Cron\Workers\SendingQueue\SendingQueue;
9 use MailPoet\Entities\NewsletterEntity;
10 use MailPoet\Entities\NewsletterOptionFieldEntity;
11 use MailPoet\Entities\ScheduledTaskEntity;
12 use MailPoet\Entities\ScheduledTaskSubscriberEntity;
13 use MailPoet\Entities\SendingQueueEntity;
14 use MailPoet\Entities\SubscriberEntity;
15 use MailPoet\Newsletter\Sending\ScheduledTasksRepository;
16 use MailPoet\Newsletter\Sending\ScheduledTaskSubscribersRepository;
17 use MailPoet\Newsletter\Sending\SendingQueuesRepository;
18
19 class AutomaticEmailScheduler {
20
21 /** @var Scheduler */
22 private $scheduler;
23
24 /** @var ScheduledTasksRepository */
25 private $scheduledTasksRepository;
26
27 /** @var SendingQueuesRepository */
28 private $sendingQueuesRepository;
29
30 /** @var ScheduledTaskSubscribersRepository */
31 private $scheduledTaskSubscribersRepository;
32
33 public function __construct(
34 Scheduler $scheduler,
35 ScheduledTasksRepository $scheduledTasksRepository,
36 ScheduledTaskSubscribersRepository $scheduledTaskSubscribersRepository,
37 SendingQueuesRepository $sendingQueuesRepository
38 ) {
39 $this->scheduler = $scheduler;
40 $this->scheduledTasksRepository = $scheduledTasksRepository;
41 $this->scheduledTaskSubscribersRepository = $scheduledTaskSubscribersRepository;
42 $this->sendingQueuesRepository = $sendingQueuesRepository;
43 }
44
45 public function scheduleAutomaticEmail(
46 string $group,
47 string $event,
48 ?callable $schedulingCondition = null,
49 ?SubscriberEntity $subscriber = null,
50 ?array $meta = null,
51 ?callable $metaModifier = null
52 ) {
53 $newsletters = $this->scheduler->getNewsletters(NewsletterEntity::TYPE_AUTOMATIC, $group);
54 if (empty($newsletters)) return false;
55 foreach ($newsletters as $newsletter) {
56 if ($newsletter->getOptionValue(NewsletterOptionFieldEntity::NAME_EVENT) !== $event) continue;
57 if (is_callable($schedulingCondition) && !$schedulingCondition($newsletter)) continue;
58
59 /**
60 * $meta will be the same for all newsletters by default. If we need to store newsletter-specific meta, the
61 * $metaModifier callback can be used.
62 *
63 * This was introduced because of WooCommerce product purchase automatic emails. We only want to store the
64 * product IDs that specifically triggered a newsletter, but $meta includes ALL the product IDs
65 * or category IDs from an order.
66 */
67 if (is_callable($metaModifier)) {
68 $meta = $metaModifier($newsletter, $meta);
69 }
70 $this->createAutomaticEmailScheduledTask($newsletter, $subscriber, $meta);
71 }
72 }
73
74 public function scheduleOrRescheduleAutomaticEmail(string $group, string $event, SubscriberEntity $subscriber, array $meta): void {
75 $newsletters = $this->scheduler->getNewsletters(NewsletterEntity::TYPE_AUTOMATIC, $group);
76 if (empty($newsletters)) {
77 return;
78 }
79
80 foreach ($newsletters as $newsletter) {
81 if ($newsletter->getOptionValue(NewsletterOptionFieldEntity::NAME_EVENT) !== $event) {
82 continue;
83 }
84
85 // try to find existing scheduled task for given subscriber
86 $task = $this->scheduledTasksRepository->findOneScheduledByNewsletterAndSubscriber($newsletter, $subscriber);
87 if ($task) {
88 $this->rescheduleAutomaticEmailSendingTask($newsletter, $task, $meta);
89 } else {
90 $this->createAutomaticEmailScheduledTask($newsletter, $subscriber, $meta);
91 }
92 }
93 }
94
95 public function rescheduleAutomaticEmail(string $group, string $event, SubscriberEntity $subscriber): void {
96 $newsletters = $this->scheduler->getNewsletters(NewsletterEntity::TYPE_AUTOMATIC, $group);
97 if (empty($newsletters)) {
98 return;
99 }
100
101 foreach ($newsletters as $newsletter) {
102 if ($newsletter->getOptionValue(NewsletterOptionFieldEntity::NAME_EVENT) !== $event) {
103 continue;
104 }
105
106 // try to find existing scheduled task for given subscriber
107 $task = $this->scheduledTasksRepository->findOneScheduledByNewsletterAndSubscriber($newsletter, $subscriber);
108 if ($task) {
109 $this->rescheduleAutomaticEmailSendingTask($newsletter, $task);
110 }
111 }
112 }
113
114 public function cancelAutomaticEmail(string $group, string $event, SubscriberEntity $subscriber): void {
115 $newsletters = $this->scheduler->getNewsletters(NewsletterEntity::TYPE_AUTOMATIC, $group);
116 if (empty($newsletters)) {
117 return;
118 }
119
120 foreach ($newsletters as $newsletter) {
121 if ($newsletter->getOptionValue(NewsletterOptionFieldEntity::NAME_EVENT) !== $event) {
122 continue;
123 }
124
125 // try to find existing scheduled task for given subscriber
126 $task = $this->scheduledTasksRepository->findOneScheduledByNewsletterAndSubscriber($newsletter, $subscriber);
127 if ($task) {
128 $queue = $task->getSendingQueue();
129 if ($queue instanceof SendingQueueEntity) {
130 $this->sendingQueuesRepository->remove($queue);
131 }
132 $this->scheduledTaskSubscribersRepository->deleteByScheduledTask($task);
133 $this->scheduledTasksRepository->remove($task);
134 $this->scheduledTasksRepository->flush();
135 }
136 }
137 }
138
139 public function createAutomaticEmailScheduledTask(NewsletterEntity $newsletter, ?SubscriberEntity $subscriber, ?array $meta = null): ScheduledTaskEntity {
140 $scheduledTask = new ScheduledTaskEntity();
141 $scheduledTask->setType(SendingQueue::TASK_TYPE);
142 $scheduledTask->setStatus(SendingQueueEntity::STATUS_SCHEDULED);
143 $scheduledTask->setPriority(ScheduledTaskEntity::PRIORITY_MEDIUM);
144
145 $scheduledTask->setScheduledAt($this->scheduler->getScheduledTimeWithDelay(
146 $newsletter->getOptionValue(NewsletterOptionFieldEntity::NAME_AFTER_TIME_TYPE),
147 $newsletter->getOptionValue(NewsletterOptionFieldEntity::NAME_AFTER_TIME_NUMBER)
148 ));
149 $this->scheduledTasksRepository->persist($scheduledTask);
150 $this->scheduledTasksRepository->flush();
151
152 $sendingQueue = new SendingQueueEntity();
153 $sendingQueue->setNewsletter($newsletter);
154 $sendingQueue->setTask($scheduledTask);
155 // Because we changed the way how to updateCounts after sending we need to set initial counts
156 $sendingQueue->setCountTotal($subscriber ? 1 : 0);
157 $sendingQueue->setCountToProcess($subscriber ? 1 : 0);
158 $scheduledTask->setSendingQueue($sendingQueue);
159
160 if ($meta) {
161 $scheduledTask->setMeta($meta);
162 $sendingQueue->setMeta($meta);
163 }
164
165 $this->sendingQueuesRepository->persist($sendingQueue);
166 $this->sendingQueuesRepository->flush();
167
168 if ($newsletter->getOptionValue(NewsletterOptionFieldEntity::NAME_SEND_TO) === 'user' && $subscriber) {
169 $scheduledTaskSubscriber = new ScheduledTaskSubscriberEntity($scheduledTask, $subscriber);
170 $this->scheduledTaskSubscribersRepository->persist($scheduledTaskSubscriber);
171 $this->scheduledTaskSubscribersRepository->flush();
172 $scheduledTask->getSubscribers()->add($scheduledTaskSubscriber);
173 }
174
175 return $scheduledTask;
176 }
177
178 private function rescheduleAutomaticEmailSendingTask(NewsletterEntity $newsletter, ScheduledTaskEntity $scheduledTask, ?array $meta = null): void {
179 $sendingQueue = $this->sendingQueuesRepository->findOneBy(['task' => $scheduledTask]);
180 if (!$sendingQueue) {
181 return;
182 }
183
184 if ($meta) {
185 $sendingQueue->setMeta($meta);
186 $scheduledTask->setMeta($meta);
187 }
188 // compute new 'scheduled_at' from now
189 $scheduledTask->setScheduledAt($this->scheduler->getScheduledTimeWithDelay(
190 $newsletter->getOptionValue(NewsletterOptionFieldEntity::NAME_AFTER_TIME_TYPE),
191 $newsletter->getOptionValue(NewsletterOptionFieldEntity::NAME_AFTER_TIME_NUMBER)
192 ));
193 $this->sendingQueuesRepository->flush();
194 }
195 }
196