233 lines
7.9 KiB
PHP
233 lines
7.9 KiB
PHP
|
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||
|
|
||
|
namespace MailPoet\Subscription;
|
||
|
|
||
|
if (!defined('ABSPATH')) exit;
|
||
|
|
||
|
|
||
|
use MailPoet\CustomFields\CustomFieldsRepository;
|
||
|
use MailPoet\Entities\StatisticsUnsubscribeEntity;
|
||
|
use MailPoet\Entities\SubscriberEntity;
|
||
|
use MailPoet\Entities\SubscriberSegmentEntity;
|
||
|
use MailPoet\Form\Util\FieldNameObfuscator;
|
||
|
use MailPoet\Newsletter\Scheduler\WelcomeScheduler;
|
||
|
use MailPoet\Segments\SegmentsRepository;
|
||
|
use MailPoet\Statistics\Track\Unsubscribes;
|
||
|
use MailPoet\Subscribers\LinkTokens;
|
||
|
use MailPoet\Subscribers\NewSubscriberNotificationMailer;
|
||
|
use MailPoet\Subscribers\SubscriberSaveController;
|
||
|
use MailPoet\Subscribers\SubscriberSegmentRepository;
|
||
|
use MailPoet\Subscribers\SubscribersRepository;
|
||
|
use MailPoet\Util\Url as UrlHelper;
|
||
|
|
||
|
class Manage {
|
||
|
|
||
|
/** @var UrlHelper */
|
||
|
private $urlHelper;
|
||
|
|
||
|
/** @var FieldNameObfuscator */
|
||
|
private $fieldNameObfuscator;
|
||
|
|
||
|
/** @var LinkTokens */
|
||
|
private $linkTokens;
|
||
|
|
||
|
/** @var Unsubscribes */
|
||
|
private $unsubscribesTracker;
|
||
|
|
||
|
/** @var NewSubscriberNotificationMailer */
|
||
|
private $newSubscriberNotificationMailer;
|
||
|
|
||
|
/** @var WelcomeScheduler */
|
||
|
private $welcomeScheduler;
|
||
|
|
||
|
/** @var CustomFieldsRepository */
|
||
|
private $customFieldsRepository;
|
||
|
|
||
|
/** @var SegmentsRepository */
|
||
|
private $segmentsRepository;
|
||
|
|
||
|
/** @var SubscribersRepository */
|
||
|
private $subscribersRepository;
|
||
|
|
||
|
/** @var SubscriberSegmentRepository */
|
||
|
private $subscriberSegmentRepository;
|
||
|
|
||
|
/** @var SubscriberSaveController */
|
||
|
private $subscriberSaveController;
|
||
|
|
||
|
public function __construct(
|
||
|
UrlHelper $urlHelper,
|
||
|
FieldNameObfuscator $fieldNameObfuscator,
|
||
|
LinkTokens $linkTokens,
|
||
|
Unsubscribes $unsubscribesTracker,
|
||
|
NewSubscriberNotificationMailer $newSubscriberNotificationMailer,
|
||
|
WelcomeScheduler $welcomeScheduler,
|
||
|
CustomFieldsRepository $customFieldsRepository,
|
||
|
SegmentsRepository $segmentsRepository,
|
||
|
SubscribersRepository $subscribersRepository,
|
||
|
SubscriberSegmentRepository $subscriberSegmentRepository,
|
||
|
SubscriberSaveController $subscriberSaveController
|
||
|
) {
|
||
|
$this->urlHelper = $urlHelper;
|
||
|
$this->fieldNameObfuscator = $fieldNameObfuscator;
|
||
|
$this->unsubscribesTracker = $unsubscribesTracker;
|
||
|
$this->linkTokens = $linkTokens;
|
||
|
$this->newSubscriberNotificationMailer = $newSubscriberNotificationMailer;
|
||
|
$this->welcomeScheduler = $welcomeScheduler;
|
||
|
$this->segmentsRepository = $segmentsRepository;
|
||
|
$this->subscribersRepository = $subscribersRepository;
|
||
|
$this->subscriberSegmentRepository = $subscriberSegmentRepository;
|
||
|
$this->customFieldsRepository = $customFieldsRepository;
|
||
|
$this->subscriberSaveController = $subscriberSaveController;
|
||
|
}
|
||
|
|
||
|
public function onSave() {
|
||
|
$action = (isset($_POST['action']) ? sanitize_text_field(wp_unslash($_POST['action'])) : '');
|
||
|
$token = (isset($_POST['token']) ? sanitize_text_field(wp_unslash($_POST['token'])) : '');
|
||
|
|
||
|
if ($action !== 'mailpoet_subscription_update' || empty($_POST['data'])) {
|
||
|
$this->urlHelper->redirectBack();
|
||
|
}
|
||
|
|
||
|
$sanitize = function($value) {
|
||
|
if (is_array($value)) {
|
||
|
foreach ($value as $k => $v) {
|
||
|
$value[sanitize_text_field($k)] = sanitize_text_field($v);
|
||
|
}
|
||
|
return $value;
|
||
|
};
|
||
|
return sanitize_text_field($value);
|
||
|
};
|
||
|
|
||
|
// custom sanitization via $sanitize
|
||
|
//phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||
|
$subscriberData = array_map($sanitize, wp_unslash((array)$_POST['data']));
|
||
|
$subscriberData = $this->fieldNameObfuscator->deobfuscateFormPayload($subscriberData);
|
||
|
|
||
|
$result = [];
|
||
|
if (!empty($subscriberData['email'])) {
|
||
|
$subscriber = $this->subscribersRepository->findOneBy(['email' => $subscriberData['email']]);
|
||
|
|
||
|
if (
|
||
|
($subscriberData['status'] === SubscriberEntity::STATUS_UNSUBSCRIBED)
|
||
|
&& ($subscriber instanceof SubscriberEntity)
|
||
|
&& ($subscriber->getStatus() === SubscriberEntity::STATUS_SUBSCRIBED)
|
||
|
) {
|
||
|
$this->unsubscribesTracker->track(
|
||
|
(int)$subscriber->getId(),
|
||
|
StatisticsUnsubscribeEntity::SOURCE_MANAGE
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if ($subscriber && $this->linkTokens->verifyToken($subscriber, $token)) {
|
||
|
if ($subscriberData['email'] !== Pages::DEMO_EMAIL) {
|
||
|
$subscriber = $this->subscriberSaveController->createOrUpdate($subscriberData, $subscriber);
|
||
|
$this->subscriberSaveController->updateCustomFields($this->filterOutEmptyMandatoryFields($subscriberData), $subscriber);
|
||
|
$this->updateSubscriptions($subscriber, $subscriberData);
|
||
|
}
|
||
|
}
|
||
|
$result = ['success' => true];
|
||
|
}
|
||
|
|
||
|
$this->urlHelper->redirectBack($result);
|
||
|
}
|
||
|
|
||
|
private function updateSubscriptions(SubscriberEntity $subscriber, array $subscriberData): void {
|
||
|
$segmentsIds = [];
|
||
|
if (isset($subscriberData['segments']) && is_array($subscriberData['segments'])) {
|
||
|
$segmentsIds = $subscriberData['segments'];
|
||
|
}
|
||
|
|
||
|
// Unsubscribe from all other segments already subscribed to
|
||
|
// but don't change disallowed segments
|
||
|
foreach ($subscriber->getSubscriberSegments() as $subscriberSegment) {
|
||
|
$segment = $subscriberSegment->getSegment();
|
||
|
if (!$segment) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (empty($segment->getDisplayInManageSubscriptionPage())) {
|
||
|
continue;
|
||
|
}
|
||
|
if (!in_array($segment->getId(), $segmentsIds)) {
|
||
|
$this->subscriberSegmentRepository->createOrUpdate(
|
||
|
$subscriber,
|
||
|
$segment,
|
||
|
SubscriberEntity::STATUS_UNSUBSCRIBED
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Store new segments for notifications
|
||
|
$subscriberSegments = $this->subscriberSegmentRepository->findBy([
|
||
|
'status' => SubscriberEntity::STATUS_SUBSCRIBED,
|
||
|
'subscriber' => $subscriber,
|
||
|
]);
|
||
|
$currentSegmentIds = array_filter(array_map(function (SubscriberSegmentEntity $subscriberSegment): ?string {
|
||
|
$segment = $subscriberSegment->getSegment();
|
||
|
return $segment ? (string)$segment->getId() : null;
|
||
|
}, $subscriberSegments));
|
||
|
$newSegmentIds = array_diff($segmentsIds, $currentSegmentIds);
|
||
|
|
||
|
foreach ($segmentsIds as $segmentId) {
|
||
|
$segment = $this->segmentsRepository->findOneById($segmentId);
|
||
|
if (!$segment) {
|
||
|
continue;
|
||
|
}
|
||
|
// Allow subscribing only to allowed segments
|
||
|
if (empty($segment->getDisplayInManageSubscriptionPage())) {
|
||
|
continue;
|
||
|
}
|
||
|
$this->subscriberSegmentRepository->createOrUpdate(
|
||
|
$subscriber,
|
||
|
$segment,
|
||
|
SubscriberEntity::STATUS_SUBSCRIBED
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if ($subscriber->getStatus() === SubscriberEntity::STATUS_SUBSCRIBED && $newSegmentIds) {
|
||
|
$newSegments = $this->segmentsRepository->findBy(['id' => $newSegmentIds]);
|
||
|
$this->newSubscriberNotificationMailer->send($subscriber, $newSegments);
|
||
|
$this->welcomeScheduler->scheduleSubscriberWelcomeNotification(
|
||
|
$subscriber->getId(),
|
||
|
$newSegmentIds
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private function filterOutEmptyMandatoryFields(array $subscriberData): array {
|
||
|
$mandatory = $this->getMandatory();
|
||
|
foreach ($mandatory as $name) {
|
||
|
if (!isset($subscriberData[$name])) {
|
||
|
continue;
|
||
|
}
|
||
|
if (is_array($subscriberData[$name]) && count(array_filter($subscriberData[$name])) === 0) {
|
||
|
unset($subscriberData[$name]);
|
||
|
}
|
||
|
if (is_string($subscriberData[$name]) && strlen(trim($subscriberData[$name])) === 0) {
|
||
|
unset($subscriberData[$name]);
|
||
|
}
|
||
|
}
|
||
|
return $subscriberData;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return string[]
|
||
|
*/
|
||
|
private function getMandatory(): array {
|
||
|
$mandatory = [];
|
||
|
$requiredCustomFields = $this->customFieldsRepository->findAll();
|
||
|
foreach ($requiredCustomFields as $customField) {
|
||
|
$params = $customField->getParams();
|
||
|
if (
|
||
|
is_array($params)
|
||
|
&& isset($params['required'])
|
||
|
&& $params['required']
|
||
|
) {
|
||
|
$mandatory[] = 'cf_' . $customField->getId();
|
||
|
}
|
||
|
}
|
||
|
return $mandatory;
|
||
|
}
|
||
|
}
|