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 / Subscription / Manage.php
mailpoet / lib / Subscription Last commit date
AdminUserSubscription.php 4 weeks ago Blacklist.php 1 year ago Comment.php 4 weeks ago Form.php 1 year ago Manage.php 2 weeks ago ManageSubscriptionFormRenderer.php 2 weeks ago Pages.php 2 weeks ago Registration.php 4 weeks ago SubscriptionUrlFactory.php 4 weeks ago Throttling.php 4 weeks ago index.php 3 years ago
Manage.php
468 lines
1 <?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
2
3 namespace MailPoet\Subscription;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use MailPoet\CustomFields\CustomFieldsRepository;
9 use MailPoet\Entities\SegmentEntity;
10 use MailPoet\Entities\StatisticsUnsubscribeEntity;
11 use MailPoet\Entities\SubscriberEntity;
12 use MailPoet\Entities\SubscriberSegmentEntity;
13 use MailPoet\Form\Util\FieldNameObfuscator;
14 use MailPoet\Newsletter\Scheduler\WelcomeScheduler;
15 use MailPoet\Segments\SegmentsRepository;
16 use MailPoet\Statistics\Track\Unsubscribes;
17 use MailPoet\Subscribers\LinkTokens;
18 use MailPoet\Subscribers\NewSubscriberNotificationMailer;
19 use MailPoet\Subscribers\SubscriberSaveController;
20 use MailPoet\Subscribers\SubscriberSegmentRepository;
21 use MailPoet\Subscribers\SubscribersRepository;
22 use MailPoet\Util\Url as UrlHelper;
23 use MailPoetVendor\Doctrine\DBAL\ArrayParameterType;
24
25 class Manage {
26
27 /** @var UrlHelper */
28 private $urlHelper;
29
30 /** @var FieldNameObfuscator */
31 private $fieldNameObfuscator;
32
33 /** @var LinkTokens */
34 private $linkTokens;
35
36 /** @var Unsubscribes */
37 private $unsubscribesTracker;
38
39 /** @var NewSubscriberNotificationMailer */
40 private $newSubscriberNotificationMailer;
41
42 /** @var WelcomeScheduler */
43 private $welcomeScheduler;
44
45 /** @var CustomFieldsRepository */
46 private $customFieldsRepository;
47
48 /** @var SegmentsRepository */
49 private $segmentsRepository;
50
51 /** @var SubscribersRepository */
52 private $subscribersRepository;
53
54 /** @var SubscriberSegmentRepository */
55 private $subscriberSegmentRepository;
56
57 /** @var SubscriberSaveController */
58 private $subscriberSaveController;
59
60 public function __construct(
61 UrlHelper $urlHelper,
62 FieldNameObfuscator $fieldNameObfuscator,
63 LinkTokens $linkTokens,
64 Unsubscribes $unsubscribesTracker,
65 NewSubscriberNotificationMailer $newSubscriberNotificationMailer,
66 WelcomeScheduler $welcomeScheduler,
67 CustomFieldsRepository $customFieldsRepository,
68 SegmentsRepository $segmentsRepository,
69 SubscribersRepository $subscribersRepository,
70 SubscriberSegmentRepository $subscriberSegmentRepository,
71 SubscriberSaveController $subscriberSaveController
72 ) {
73 $this->urlHelper = $urlHelper;
74 $this->fieldNameObfuscator = $fieldNameObfuscator;
75 $this->unsubscribesTracker = $unsubscribesTracker;
76 $this->linkTokens = $linkTokens;
77 $this->newSubscriberNotificationMailer = $newSubscriberNotificationMailer;
78 $this->welcomeScheduler = $welcomeScheduler;
79 $this->segmentsRepository = $segmentsRepository;
80 $this->subscribersRepository = $subscribersRepository;
81 $this->subscriberSegmentRepository = $subscriberSegmentRepository;
82 $this->customFieldsRepository = $customFieldsRepository;
83 $this->subscriberSaveController = $subscriberSaveController;
84 }
85
86 public function onSave() {
87 $action = (isset($_POST['action']) && is_string($_POST['action']) ? sanitize_text_field(wp_unslash($_POST['action'])) : '');
88 $token = (isset($_POST['token']) && is_string($_POST['token']) ? sanitize_text_field(wp_unslash($_POST['token'])) : '');
89
90 if ($action !== 'mailpoet_subscription_update' || empty($_POST['data'])) {
91 $this->urlHelper->redirectBack();
92 return;
93 }
94
95 //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
96 $subscriberData = $this->fieldNameObfuscator->deobfuscateFormPayload(wp_unslash((array)$_POST['data']));
97 $subscriberData = $this->sanitizeFormValue($subscriberData);
98 if (!is_array($subscriberData)) {
99 $subscriberData = [];
100 }
101 if ($this->hasInvalidStatus($subscriberData) || $this->hasMalformedLegacySegmentIds($subscriberData)) {
102 $this->urlHelper->redirectBack(['error' => true]);
103 return;
104 }
105
106 $result = ['error' => true];
107 if (!empty($subscriberData['email'])) {
108 $subscriber = $this->subscribersRepository->findOneBy(['email' => $subscriberData['email']]);
109
110 if ($subscriber && $this->linkTokens->verifyToken($subscriber, $token)) {
111 if ($subscriberData['email'] !== Pages::DEMO_EMAIL) {
112 $previousStatus = $subscriber->getStatus();
113 $shouldTrackUnsubscribe = (
114 ($subscriberData['status'] ?? '') === SubscriberEntity::STATUS_UNSUBSCRIBED
115 && $subscriber instanceof SubscriberEntity
116 && $subscriber->getStatus() === SubscriberEntity::STATUS_SUBSCRIBED
117 );
118 $subscriber = $this->subscriberSaveController->createOrUpdate($subscriberData, $subscriber);
119 if ($shouldTrackUnsubscribe) {
120 $this->unsubscribesTracker->track(
121 (int)$subscriber->getId(),
122 StatisticsUnsubscribeEntity::SOURCE_MANAGE
123 );
124 }
125 $this->subscriberSaveController->updateCustomFields($this->filterOutEmptyMandatoryFields($subscriberData), $subscriber);
126 $this->updateSubscriptions(
127 $subscriber,
128 $subscriberData,
129 $previousStatus !== SubscriberEntity::STATUS_SUBSCRIBED
130 && $subscriber->getStatus() === SubscriberEntity::STATUS_SUBSCRIBED
131 );
132 }
133 $result = ['success' => true];
134 }
135 }
136
137 $this->urlHelper->redirectBack($result);
138 }
139
140 private function updateSubscriptions(
141 SubscriberEntity $subscriber,
142 array $subscriberData,
143 bool $isGlobalResubscribe
144 ): void {
145 if ($subscriber->getStatus() !== SubscriberEntity::STATUS_SUBSCRIBED) {
146 return;
147 }
148
149 if (array_key_exists('segment_choices', $subscriberData)) {
150 $this->updateSubscriptionsFromSegmentChoices(
151 $subscriber,
152 $subscriberData['segment_choices'],
153 $isGlobalResubscribe
154 );
155 return;
156 }
157
158 $segmentsIds = $this->getLegacySegmentIds($subscriberData);
159 $legacySegmentIds = $segmentsIds;
160 $segments = $this->getVisibleDefaultManageSegmentsByIds($legacySegmentIds);
161 $segmentsIds = array_map('intval', array_keys($segments));
162 if ($legacySegmentIds && !$segmentsIds) {
163 return;
164 }
165
166 // Unsubscribe from all other segments already subscribed to
167 // but don't change disallowed segments
168 foreach ($subscriber->getSubscriberSegments() as $subscriberSegment) {
169 $segment = $subscriberSegment->getSegment();
170 if (!$segment) {
171 continue;
172 }
173
174 if (!$this->isVisibleDefaultManageSegment($segment)) {
175 continue;
176 }
177 if (!in_array((int)$segment->getId(), $segmentsIds, true)) {
178 $this->subscriberSegmentRepository->createOrUpdate(
179 $subscriber,
180 $segment,
181 SubscriberEntity::STATUS_UNSUBSCRIBED
182 );
183 }
184 }
185
186 $currentSegmentIds = $this->getCurrentSubscribedSegmentIds($subscriber);
187 $newSegmentIds = array_diff($segmentsIds, $currentSegmentIds);
188
189 foreach ($segmentsIds as $segmentId) {
190 $this->subscriberSegmentRepository->createOrUpdate(
191 $subscriber,
192 $segments[$segmentId],
193 SubscriberEntity::STATUS_SUBSCRIBED
194 );
195 }
196
197 $this->sendNotificationsForNewSegments(
198 $subscriber,
199 $isGlobalResubscribe ? $this->getCurrentSubscribedSegmentIds($subscriber) : $newSegmentIds
200 );
201 }
202
203 /**
204 * @param mixed $segmentChoices
205 */
206 private function updateSubscriptionsFromSegmentChoices(
207 SubscriberEntity $subscriber,
208 $segmentChoices,
209 bool $isGlobalResubscribe
210 ): void {
211 $choices = $this->getSegmentChoices($segmentChoices);
212 $segments = $this->getVisibleDefaultManageSegmentsByIds(array_keys($choices));
213 $subscribeIds = [];
214 $unsubscribeIds = [];
215
216 foreach ($choices as $segmentId => $choice) {
217 if (!isset($segments[$segmentId])) {
218 continue;
219 }
220 if ($choice === 'subscribed') {
221 $subscribeIds[] = $segmentId;
222 } elseif ($choice === 'unsubscribed') {
223 $unsubscribeIds[] = $segmentId;
224 }
225 }
226
227 $currentSegmentIds = $this->getCurrentSubscribedSegmentIds($subscriber);
228
229 foreach ($unsubscribeIds as $segmentId) {
230 $this->subscriberSegmentRepository->createOrUpdate(
231 $subscriber,
232 $segments[$segmentId],
233 SubscriberEntity::STATUS_UNSUBSCRIBED
234 );
235 }
236
237 foreach ($subscribeIds as $segmentId) {
238 $this->subscriberSegmentRepository->createOrUpdate(
239 $subscriber,
240 $segments[$segmentId],
241 SubscriberEntity::STATUS_SUBSCRIBED
242 );
243 }
244
245 $this->sendNotificationsForNewSegments(
246 $subscriber,
247 $isGlobalResubscribe
248 ? $this->getCurrentSubscribedSegmentIds($subscriber)
249 : array_diff($subscribeIds, $currentSegmentIds)
250 );
251 }
252
253 private function hasInvalidStatus(array $subscriberData): bool {
254 if (!isset($subscriberData['status'])) {
255 return false;
256 }
257 return !in_array($subscriberData['status'], [
258 SubscriberEntity::STATUS_SUBSCRIBED,
259 SubscriberEntity::STATUS_UNSUBSCRIBED,
260 ], true);
261 }
262
263 /**
264 * @param mixed $value
265 * @return mixed
266 */
267 private function sanitizeFormValue($value, ?string $parentKey = null) {
268 if (is_array($value)) {
269 $sanitized = [];
270 foreach ($value as $key => $item) {
271 $sanitizedKey = $parentKey === 'segment_choices' ? $key : sanitize_text_field((string)$key);
272 $childParentKey = $parentKey === 'segments' ? 'segments' : (string)$sanitizedKey;
273 $sanitized[$sanitizedKey] = $this->sanitizeFormValue($item, $childParentKey);
274 }
275 return $sanitized;
276 }
277 if ($parentKey === 'segments') {
278 return is_scalar($value) ? (string)$value : '';
279 }
280 return sanitize_text_field(is_scalar($value) ? (string)$value : '');
281 }
282
283 /**
284 * @return int[]
285 */
286 private function getLegacySegmentIds(array $subscriberData): array {
287 if (!isset($subscriberData['segments']) || !is_array($subscriberData['segments'])) {
288 return [];
289 }
290
291 $segmentIds = [];
292 foreach ($subscriberData['segments'] as $segmentId) {
293 $segmentId = $this->normalizePositiveIntegerId($segmentId);
294 if ($segmentId === null) {
295 continue;
296 }
297 $segmentIds[] = $segmentId;
298 }
299 return array_values(array_unique($segmentIds));
300 }
301
302 private function hasMalformedLegacySegmentIds(array $subscriberData): bool {
303 if (!isset($subscriberData['segments'])) {
304 return false;
305 }
306 if ($subscriberData['segments'] === '') {
307 return false;
308 }
309 if (!is_array($subscriberData['segments'])) {
310 return true;
311 }
312
313 foreach ($subscriberData['segments'] as $segmentId) {
314 if ($segmentId === '') {
315 continue;
316 }
317 if ($this->normalizePositiveIntegerId($segmentId) === null) {
318 return true;
319 }
320 }
321 return false;
322 }
323
324 /**
325 * @param mixed $segmentChoices
326 * @return array<int, string>
327 */
328 private function getSegmentChoices($segmentChoices): array {
329 if (!is_array($segmentChoices)) {
330 return [];
331 }
332
333 $choices = [];
334 foreach ($segmentChoices as $segmentId => $choice) {
335 $segmentId = $this->normalizePositiveIntegerId($segmentId);
336 if ($segmentId === null || !is_string($choice)) {
337 continue;
338 }
339 if (!in_array($choice, ['subscribed', 'unsubscribed'], true)) {
340 continue;
341 }
342 $choices[$segmentId] = $choice;
343 }
344 return $choices;
345 }
346
347 /**
348 * @param mixed $segmentId
349 */
350 private function normalizePositiveIntegerId($segmentId): ?int {
351 if (is_int($segmentId)) {
352 return $segmentId > 0 ? $segmentId : null;
353 }
354 if (!is_string($segmentId) || $segmentId === '' || $segmentId[0] === '0' || !ctype_digit($segmentId)) {
355 return null;
356 }
357 $normalized = (int)$segmentId;
358 if ((string)$normalized !== $segmentId || $normalized <= 0) {
359 return null;
360 }
361 return $normalized;
362 }
363
364 /**
365 * @param int[] $segmentIds
366 * @return array<int, SegmentEntity>
367 */
368 private function getVisibleDefaultManageSegmentsByIds(array $segmentIds): array {
369 $segmentIds = array_values(array_unique(array_filter(array_map('intval', $segmentIds))));
370 if (!$segmentIds) {
371 return [];
372 }
373
374 $segments = $this->segmentsRepository->createQueryBuilder('s')
375 ->where('s.id IN (:ids)')
376 ->andWhere('s.type = :type')
377 ->andWhere('s.deletedAt IS NULL')
378 ->andWhere('s.displayInManageSubscriptionPage = :displayInManageSubscriptionPage')
379 ->setParameter('ids', $segmentIds, ArrayParameterType::INTEGER)
380 ->setParameter('type', SegmentEntity::TYPE_DEFAULT)
381 ->setParameter('displayInManageSubscriptionPage', true)
382 ->getQuery()
383 ->getResult();
384
385 $segmentsMap = [];
386 foreach ($segments as $segment) {
387 if ($segment instanceof SegmentEntity && $segment->getId()) {
388 $segmentsMap[(int)$segment->getId()] = $segment;
389 }
390 }
391 return $segmentsMap;
392 }
393
394 private function isVisibleDefaultManageSegment(SegmentEntity $segment): bool {
395 return (
396 $segment->getType() === SegmentEntity::TYPE_DEFAULT
397 && $segment->getDeletedAt() === null
398 && $segment->getDisplayInManageSubscriptionPage()
399 );
400 }
401
402 /**
403 * @return int[]
404 */
405 private function getCurrentSubscribedSegmentIds(SubscriberEntity $subscriber): array {
406 $subscriberSegments = $this->subscriberSegmentRepository->findBy([
407 'status' => SubscriberEntity::STATUS_SUBSCRIBED,
408 'subscriber' => $subscriber,
409 ]);
410 return array_values(array_filter(array_map(function (SubscriberSegmentEntity $subscriberSegment): ?int {
411 $segment = $subscriberSegment->getSegment();
412 return $segment ? (int)$segment->getId() : null;
413 }, $subscriberSegments)));
414 }
415
416 /**
417 * @param int[] $newSegmentIds
418 */
419 private function sendNotificationsForNewSegments(SubscriberEntity $subscriber, array $newSegmentIds): void {
420 $newSegmentIds = array_values(array_unique(array_map('intval', $newSegmentIds)));
421 if ($subscriber->getStatus() !== SubscriberEntity::STATUS_SUBSCRIBED || !$newSegmentIds) {
422 return;
423 }
424
425 $newSegments = $this->segmentsRepository->findByIds($newSegmentIds);
426 $this->newSubscriberNotificationMailer->send($subscriber, $newSegments);
427 $this->welcomeScheduler->scheduleSubscriberWelcomeNotification(
428 $subscriber->getId(),
429 $newSegmentIds
430 );
431 }
432
433 private function filterOutEmptyMandatoryFields(array $subscriberData): array {
434 $mandatory = $this->getMandatory();
435 foreach ($mandatory as $name) {
436 if (!isset($subscriberData[$name])) {
437 continue;
438 }
439 if (is_array($subscriberData[$name]) && count(array_filter($subscriberData[$name])) === 0) {
440 unset($subscriberData[$name]);
441 }
442 if (is_string($subscriberData[$name]) && strlen(trim($subscriberData[$name])) === 0) {
443 unset($subscriberData[$name]);
444 }
445 }
446 return $subscriberData;
447 }
448
449 /**
450 * @return string[]
451 */
452 private function getMandatory(): array {
453 $mandatory = [];
454 $requiredCustomFields = $this->customFieldsRepository->findAllActive();
455 foreach ($requiredCustomFields as $customField) {
456 $params = $customField->getParams();
457 if (
458 is_array($params)
459 && isset($params['required'])
460 && $params['required']
461 ) {
462 $mandatory[] = 'cf_' . $customField->getId();
463 }
464 }
465 return $mandatory;
466 }
467 }
468