PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.34.2
MailPoet – Newsletters, Email Marketing, and Automation v5.34.2
5.34.2 5.34.1 5.34.0 5.33.1 5.33.0 5.32.0 5.31.0 5.30.0 5.29.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 / SubscriberActions.php
mailpoet / lib / Subscribers Last commit date
ConfirmationEmailTemplate 1 month ago ImportExport 2 weeks ago RestApi 3 days ago Statistics 1 month ago BulkActionController.php 3 days ago BulkActionException.php 1 month ago BulkConfirmationEmailResender.php 2 months ago ConfirmationEmailCustomizer.php 2 months ago ConfirmationEmailMailer.php 2 months ago ConfirmationEmailResolver.php 2 months ago EngagementDataBackfiller.php 2 months ago InactiveSubscribersController.php 4 days ago LinkTokens.php 2 months ago NewSubscriberNotificationMailer.php 2 months ago RequiredCustomFieldValidator.php 2 months ago SegmentsCountRecalculator.php 2 weeks ago Source.php 2 months ago SubscriberActions.php 2 months ago SubscriberCustomFieldRepository.php 3 years ago SubscriberIPsRepository.php 2 years ago SubscriberLimitNotificationEvaluator.php 2 months ago SubscriberLimitNotificationMailer.php 2 months ago SubscriberLimitNotificationScheduler.php 2 months ago SubscriberListingRepository.php 2 weeks ago SubscriberPersonalDataEraser.php 2 months ago SubscriberSaveController.php 3 days ago SubscriberSegmentRepository.php 2 weeks ago SubscriberSubscribeController.php 2 weeks ago SubscriberTagRepository.php 4 years ago SubscribersCountsController.php 2 weeks ago SubscribersEmailCountsController.php 2 weeks ago SubscribersRepository.php 3 days ago TrackingConsentController.php 4 days ago index.php 3 years ago
SubscriberActions.php
168 lines
1 <?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
2
3 namespace MailPoet\Subscribers;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use MailPoet\Entities\SubscriberEntity;
9 use MailPoet\Newsletter\Scheduler\WelcomeScheduler;
10 use MailPoet\Segments\SegmentsRepository;
11 use MailPoet\Settings\SettingsController;
12 use MailPoet\Subscribers\ConfirmationEmailResolver;
13 use MailPoet\Util\Helpers;
14 use MailPoetVendor\Carbon\Carbon;
15
16 class SubscriberActions {
17 /** @var SettingsController */
18 private $settings;
19
20 /** @var NewSubscriberNotificationMailer */
21 private $newSubscriberNotificationMailer;
22
23 /** @var ConfirmationEmailMailer */
24 private $confirmationEmailMailer;
25
26 /** @var WelcomeScheduler */
27 private $welcomeScheduler;
28
29 /** @var SubscriberSaveController */
30 private $subscriberSaveController;
31
32 /** @var SubscribersRepository */
33 private $subscribersRepository;
34
35 /** @var SubscriberSegmentRepository */
36 private $subscriberSegmentRepository;
37
38 /** @var SegmentsRepository */
39 private $segmentsRepository;
40
41 /** @var ConfirmationEmailResolver */
42 private $confirmationEmailResolver;
43
44 public function __construct(
45 SettingsController $settings,
46 NewSubscriberNotificationMailer $newSubscriberNotificationMailer,
47 ConfirmationEmailMailer $confirmationEmailMailer,
48 WelcomeScheduler $welcomeScheduler,
49 SegmentsRepository $segmentsRepository,
50 SubscriberSaveController $subscriberSaveController,
51 SubscribersRepository $subscribersRepository,
52 SubscriberSegmentRepository $subscriberSegmentRepository,
53 ConfirmationEmailResolver $confirmationEmailResolver
54 ) {
55 $this->settings = $settings;
56 $this->newSubscriberNotificationMailer = $newSubscriberNotificationMailer;
57 $this->confirmationEmailMailer = $confirmationEmailMailer;
58 $this->welcomeScheduler = $welcomeScheduler;
59 $this->subscriberSaveController = $subscriberSaveController;
60 $this->subscribersRepository = $subscribersRepository;
61 $this->subscriberSegmentRepository = $subscriberSegmentRepository;
62 $this->segmentsRepository = $segmentsRepository;
63 $this->confirmationEmailResolver = $confirmationEmailResolver;
64 }
65
66 /**
67 * Returns SubscriberEntity and associative array with some metadata related to the subscription (e.g. ['confirmationEmailResult' => $exception])
68 * @param array $subscriberData Subscriber data (email, first_name, last_name, etc.)
69 * @param array $segmentIds IDs of segments to subscribe to
70 * @return array{0: SubscriberEntity, 1: array{confirmationEmailResult: bool|\Exception, error?: string}}
71 */
72 public function subscribe($subscriberData = [], $segmentIds = []): array {
73 // filter out keys from the subscriber_data array
74 // that should not be editable when subscribing
75 $subscriberData = $this->subscriberSaveController->filterOutReservedColumns($subscriberData);
76
77 $signupConfirmationEnabled = (bool)$this->settings->get(
78 'signup_confirmation.enabled'
79 );
80
81 $subscriberData['subscribed_ip'] = Helpers::getIP();
82
83 $subscriber = $this->subscribersRepository->findOneBy(['email' => $subscriberData['email']]);
84 $previousStatus = $subscriber instanceof SubscriberEntity ? $subscriber->getStatus() : null;
85 $wasAlreadySubscribed = $previousStatus === SubscriberEntity::STATUS_SUBSCRIBED;
86 $isUnconfirmedResubscription = (
87 $subscriber instanceof SubscriberEntity
88 && $subscriber->getStatus() === SubscriberEntity::STATUS_UNCONFIRMED
89 );
90 if (!$subscriber && !isset($subscriberData['source'])) {
91 $subscriberData['source'] = Source::FORM;
92 }
93
94 if (!$subscriber || !$signupConfirmationEnabled) {
95 // create new subscriber or update if no confirmation is required
96 $subscriber = $this->subscriberSaveController->createOrUpdate($subscriberData, $subscriber);
97 // custom fields should use the same approach as the subscriber main data that means to wait on confirmation
98 $this->subscriberSaveController->updateCustomFields($subscriberData, $subscriber);
99 } else if ($wasAlreadySubscribed) {
100 $subscriber->setUnconfirmedData(null);
101 } else {
102 // store subscriber data to be updated after confirmation
103 $unconfirmedData = $this->subscriberSaveController->filterOutReservedColumns($subscriberData);
104 $unconfirmedData = json_encode($unconfirmedData);
105 $subscriber->setUnconfirmedData($unconfirmedData ?: null);
106 }
107
108 // restore trashed subscriber
109 if ($subscriber->getDeletedAt()) {
110 $subscriber->setDeletedAt(null);
111 }
112
113 // set status depending on signup confirmation setting
114 if ($subscriber->getStatus() !== SubscriberEntity::STATUS_SUBSCRIBED) {
115 if ($signupConfirmationEnabled === true) {
116 $subscriber->setStatus(SubscriberEntity::STATUS_UNCONFIRMED);
117 if ($previousStatus !== SubscriberEntity::STATUS_UNCONFIRMED) {
118 $subscriber->setConfirmationsCount(0);
119 $subscriber->setLastConfirmationEmailSentAt(null);
120 $subscriber->setLastSubscribedAt(Carbon::now()->millisecond(0));
121 }
122 } else {
123 $subscriber->setStatus(SubscriberEntity::STATUS_SUBSCRIBED);
124 }
125 }
126
127 $this->subscribersRepository->flush();
128
129 $metaData = ['confirmationEmailResult' => false];
130 // link subscriber to segments
131 $segments = $this->segmentsRepository->findByIds($segmentIds);
132 $this->subscriberSegmentRepository->subscribeToSegments($subscriber, $segments);
133
134 // resolve confirmation settings from segment-level overrides
135 [$confirmationEmailId, $confirmationPageId] = $this->confirmationEmailResolver->resolveFromSegments($segments);
136
137 try {
138 if (
139 $signupConfirmationEnabled
140 && $isUnconfirmedResubscription
141 && $subscriber->getConfirmationsCount() >= ConfirmationEmailMailer::MAX_CONFIRMATION_EMAILS
142 ) {
143 $metaData['error'] = $this->getMaxConfirmationEmailsReachedError();
144 } else if (!$wasAlreadySubscribed) {
145 $metaData['confirmationEmailResult'] = $this->confirmationEmailMailer->sendConfirmationEmailOnce($subscriber, $confirmationEmailId, $confirmationPageId, true);
146 }
147 } catch (\Exception $e) {
148 $metaData['confirmationEmailResult'] = $e;
149 }
150
151 // We want to send the notification on subscribe only when signupConfirmation is disabled
152 if ($signupConfirmationEnabled === false && $subscriber->getStatus() === SubscriberEntity::STATUS_SUBSCRIBED) {
153 $this->newSubscriberNotificationMailer->send($subscriber, $this->segmentsRepository->findByIds($segmentIds));
154
155 $this->welcomeScheduler->scheduleSubscriberWelcomeNotification(
156 $subscriber->getId(),
157 $segmentIds
158 );
159 }
160
161 return [$subscriber, $metaData];
162 }
163
164 private function getMaxConfirmationEmailsReachedError(): string {
165 return __('We\'ve already sent you a confirmation email. Please check your inbox or spam folder.', 'mailpoet');
166 }
167 }
168