PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.27.0
MailPoet – Newsletters, Email Marketing, and Automation v5.27.0
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 / Subscribers / EngagementDataBackfiller.php
mailpoet / lib / Subscribers Last commit date
ConfirmationEmailTemplate 3 years ago ImportExport 2 weeks ago Statistics 1 year ago BulkConfirmationEmailResender.php 1 month ago ConfirmationEmailCustomizer.php 1 month ago ConfirmationEmailMailer.php 1 month ago ConfirmationEmailResolver.php 1 month ago EngagementDataBackfiller.php 1 month ago InactiveSubscribersController.php 1 month ago LinkTokens.php 1 month ago NewSubscriberNotificationMailer.php 1 month ago RequiredCustomFieldValidator.php 1 month ago Source.php 3 weeks ago SubscriberActions.php 3 weeks ago SubscriberCustomFieldRepository.php 3 years ago SubscriberIPsRepository.php 2 years ago SubscriberLimitNotificationEvaluator.php 3 weeks ago SubscriberLimitNotificationMailer.php 3 weeks ago SubscriberLimitNotificationScheduler.php 3 weeks ago SubscriberListingRepository.php 1 month ago SubscriberPersonalDataEraser.php 1 month ago SubscriberSaveController.php 3 weeks ago SubscriberSegmentRepository.php 1 month ago SubscriberSubscribeController.php 3 weeks ago SubscriberTagRepository.php 3 years ago SubscribersCountsController.php 1 month ago SubscribersEmailCountsController.php 1 year ago SubscribersRepository.php 3 weeks ago index.php 3 years ago
EngagementDataBackfiller.php
211 lines
1 <?php declare(strict_types = 1);
2
3 namespace MailPoet\Subscribers;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use MailPoet\Entities\StatisticsClickEntity;
9 use MailPoet\Entities\StatisticsNewsletterEntity;
10 use MailPoet\Entities\StatisticsOpenEntity;
11 use MailPoet\Entities\SubscriberEntity;
12 use MailPoet\Segments\DynamicSegments\Filters\FilterHelper;
13 use MailPoet\Segments\DynamicSegments\Filters\WooFilterHelper;
14 use MailPoet\WooCommerce\Helper;
15 use MailPoetVendor\Carbon\Carbon;
16 use MailPoetVendor\Doctrine\DBAL\ArrayParameterType;
17 use MailPoetVendor\Doctrine\DBAL\Result;
18 use MailPoetVendor\Doctrine\ORM\EntityManager;
19
20 class EngagementDataBackfiller {
21 /** @var EntityManager */
22 private $entityManager;
23
24 /** @var Helper */
25 private $wcHelper;
26
27 /** @var WooFilterHelper */
28 private $wooFilterHelper;
29
30 /** @var FilterHelper */
31 private $filterHelper;
32
33 /** @var int */
34 private $lastProcessedSubscriberId = 0;
35
36 public function __construct(
37 EntityManager $entityManager,
38 WooFilterHelper $wooFilterHelper,
39 FilterHelper $filterHelper,
40 Helper $wcHelper
41 ) {
42 $this->entityManager = $entityManager;
43 $this->wcHelper = $wcHelper;
44 $this->wooFilterHelper = $wooFilterHelper;
45 $this->filterHelper = $filterHelper;
46 }
47
48 /**
49 * @return SubscriberEntity[]
50 */
51 public function getBatch(int $lastProcessedId = 0, int $batchSize = 100): array {
52 $subscribers = $this->entityManager->createQueryBuilder()
53 ->select('PARTIAL s.{id, email, lastPurchaseAt, lastClickAt, lastOpenAt, lastSendingAt}')
54 ->from(SubscriberEntity::class, 's')
55 ->where('s.id > :lastProcessedId')
56 ->orderBy('s.id', 'ASC')
57 ->setMaxResults($batchSize)
58 ->setParameter('lastProcessedId', $lastProcessedId)
59 ->getQuery()
60 ->getResult();
61 if (!is_array($subscribers)) {
62 return [];
63 }
64 /** @var SubscriberEntity[] $subscribers */
65 return $subscribers;
66 }
67
68 /**
69 * @param SubscriberEntity[] $subscribers
70 *
71 * @return void
72 */
73 public function updateBatch(array $subscribers): void {
74 $subscriberIds = array_map(function (SubscriberEntity $subscriber) {
75 return $subscriber->getId();
76 }, $subscribers);
77
78 $clickData = $this->getClickDataForBatch($subscriberIds);
79 $openData = $this->getOpenDataForBatch($subscriberIds);
80 $sendingData = $this->getSendingDataForBatch($subscriberIds);
81 $purchaseData = $this->getPurchaseDataForBatch($subscriberIds);
82
83 foreach ($subscribers as $subscriber) {
84 if ($subscriber->getLastPurchaseAt() === null && isset($purchaseData[$subscriber->getId()]['last_purchase_at'])) {
85 $purchaseDate = new Carbon($purchaseData[$subscriber->getId()]['last_purchase_at']);
86 $subscriber->setLastPurchaseAt($purchaseDate);
87 }
88 if ($subscriber->getLastOpenAt() === null && isset($openData[$subscriber->getId()]['last_open_at'])) {
89 $openDate = new Carbon($openData[$subscriber->getId()]['last_open_at']);
90 $subscriber->setLastOpenAt($openDate);
91 }
92 if ($subscriber->getLastClickAt() === null && isset($clickData[$subscriber->getId()]['last_click_at'])) {
93 $clickDate = new Carbon($clickData[$subscriber->getId()]['last_click_at']);
94 $subscriber->setLastClickAt($clickDate);
95 }
96 if ($subscriber->getLastSendingAt() === null && isset($sendingData[$subscriber->getId()]['last_sending_at'])) {
97 $sendingDate = new Carbon($sendingData[$subscriber->getId()]['last_sending_at']);
98 $subscriber->setLastSendingAt($sendingDate);
99 }
100 if (is_int($subscriber->getId())) {
101 $this->lastProcessedSubscriberId = $subscriber->getId();
102 }
103 }
104
105 $this->entityManager->flush();
106 }
107
108 public function getClickDataForBatch(array $subscriberIds): array {
109 $subscribersTable = $this->filterHelper->getSubscribersTable();
110 $clicksTable = $this->filterHelper->getTableForEntity(StatisticsClickEntity::class);
111
112 $query = $this
113 ->entityManager
114 ->getConnection()
115 ->createQueryBuilder()
116 ->select("$subscribersTable.id, MAX(clicks.created_at) as last_click_at")
117 ->from($subscribersTable)
118 ->innerJoin($subscribersTable, $clicksTable, 'clicks', "$subscribersTable.id = clicks.subscriber_id")
119 ->andWhere("$subscribersTable.id IN (:subscriberIds)")
120 ->setParameter('subscriberIds', $subscriberIds, ArrayParameterType::INTEGER)
121 ->groupBy("$subscribersTable.id");
122
123 $result = $query->execute();
124 if ($result instanceof Result) {
125 return $result->fetchAllAssociativeIndexed();
126 }
127 return [];
128 }
129
130 public function getPurchaseDataForBatch(array $subscriberIds): array {
131 if (!$this->wcHelper->isWooCommerceActive()) {
132 return [];
133 }
134
135 $subscribersTable = $this->filterHelper->getSubscribersTable();
136
137 $query = $this
138 ->entityManager
139 ->getConnection()
140 ->createQueryBuilder()
141 // The orderStats alias comes from wooFilterHelper->applyOrderStatusFilter, which calls wooFilterHelper->applyCustomerOrderJoin
142 ->select("$subscribersTable.id, MAX(orderStats.date_created) as last_purchase_at")
143 ->from($subscribersTable)
144 ->andWhere("$subscribersTable.id IN (:subscriberIds)")
145 ->setParameter('subscriberIds', $subscriberIds, ArrayParameterType::INTEGER);
146 $this->wooFilterHelper->applyOrderStatusFilter($query);
147 $query->groupBy("$subscribersTable.id");
148
149 $result = $query->execute();
150 if ($result instanceof Result) {
151 return $result->fetchAllAssociativeIndexed();
152 }
153 return [];
154 }
155
156 public function getOpenDataForBatch(array $subscriberIds): array {
157 $subscribersTable = $this->filterHelper->getSubscribersTable();
158 $opensTable = $this->filterHelper->getTableForEntity(StatisticsOpenEntity::class);
159
160 $query = $this
161 ->entityManager
162 ->getConnection()
163 ->createQueryBuilder()
164 ->select("$subscribersTable.id, MAX(opens.created_at) as last_open_at")
165 ->from($subscribersTable)
166 ->innerJoin($subscribersTable, $opensTable, 'opens', "$subscribersTable.id = opens.subscriber_id")
167 ->andWhere("$subscribersTable.id IN (:subscriberIds)")
168 ->setParameter('subscriberIds', $subscriberIds, ArrayParameterType::INTEGER)
169 ->groupBy("$subscribersTable.id");
170
171 $result = $query->execute();
172 if ($result instanceof Result) {
173 return $result->fetchAllAssociativeIndexed();
174 }
175 return [];
176 }
177
178 public function getSendingDataForBatch(array $subscriberIds): array {
179 $subscribersTable = $this->filterHelper->getSubscribersTable();
180 $sendsTable = $this->filterHelper->getTableForEntity(StatisticsNewsletterEntity::class);
181
182 $query = $this
183 ->entityManager
184 ->getConnection()
185 ->createQueryBuilder()
186 ->select("$subscribersTable.id, MAX(sends.sent_at) as last_sending_at")
187 ->from($subscribersTable)
188 ->innerJoin($subscribersTable, $sendsTable, 'sends', "$subscribersTable.id = sends.subscriber_id")
189 ->andWhere("$subscribersTable.id IN (:subscriberIds)")
190 ->setParameter('subscriberIds', $subscriberIds, ArrayParameterType::INTEGER)
191 ->groupBy("$subscribersTable.id");
192
193 $result = $query->execute();
194 if ($result instanceof Result) {
195 return $result->fetchAllAssociativeIndexed();
196 }
197 return [];
198 }
199
200 /**
201 * @return int
202 */
203 public function getLastProcessedSubscriberId(): int {
204 return $this->lastProcessedSubscriberId;
205 }
206
207 public function setLastProcessedSubscriberId(int $id): void {
208 $this->lastProcessedSubscriberId = $id;
209 }
210 }
211