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 / Router / Endpoints / Subscription.php
mailpoet / lib / Router / Endpoints Last commit date
Captcha.php 4 months ago CronDaemon.php 3 years ago ExportDownload.php 2 months ago FormPreview.php 2 years ago Subscription.php 5 days ago TemplateImage.php 2 months ago Track.php 2 months ago ViewInBrowser.php 1 month ago index.php 3 years ago
Subscription.php
177 lines
1 <?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
2
3 namespace MailPoet\Router\Endpoints;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use MailPoet\Config\AccessControl;
9 use MailPoet\Entities\StatisticsUnsubscribeEntity;
10 use MailPoet\Entities\SubscriberEntity;
11 use MailPoet\Subscription as UserSubscription;
12 use MailPoet\Util\Request;
13 use MailPoet\WP\Functions as WPFunctions;
14
15 class Subscription {
16 const ENDPOINT = 'subscription';
17 const ACTION_CONFIRM = 'confirm';
18 const ACTION_MANAGE = 'manage';
19 const ACTION_UNSUBSCRIBE = 'unsubscribe';
20 const ACTION_UNSUBSCRIBE_REASON = 'unsubscribeReason';
21 const ACTION_CONFIRM_UNSUBSCRIBE = 'confirmUnsubscribe';
22 const ACTION_RE_ENGAGEMENT = 'reEngagement';
23 const ACTION_TRACKING_OPT_OUT = 'trackingOptOut';
24
25 public $allowedActions = [
26 self::ACTION_CONFIRM,
27 self::ACTION_MANAGE,
28 self::ACTION_UNSUBSCRIBE,
29 self::ACTION_UNSUBSCRIBE_REASON,
30 self::ACTION_CONFIRM_UNSUBSCRIBE,
31 self::ACTION_RE_ENGAGEMENT,
32 self::ACTION_TRACKING_OPT_OUT,
33 ];
34
35 public $permissions = [
36 'global' => AccessControl::NO_ACCESS_RESTRICTION,
37 ];
38
39 /** @var UserSubscription\Pages */
40 private $subscriptionPages;
41
42 /** @var WPFunctions */
43 private $wp;
44
45 /*** @var Request */
46 private $request;
47
48 public function __construct(
49 UserSubscription\Pages $subscriptionPages,
50 WPFunctions $wp,
51 Request $request
52 ) {
53 $this->subscriptionPages = $subscriptionPages;
54 $this->wp = $wp;
55 $this->request = $request;
56 }
57
58 public function confirm($data) {
59 $subscription = $this->initSubscriptionPage(UserSubscription\Pages::ACTION_CONFIRM, $data);
60 $subscription->confirm();
61 }
62
63 public function confirmUnsubscribe($data) {
64 $enableUnsubscribeConfirmation = $this->wp->applyFilters('mailpoet_unsubscribe_confirmation_enabled', true);
65 if ($this->isPostRequest()) {
66 $this->performUnsubscribe($data, StatisticsUnsubscribeEntity::METHOD_ONE_CLICK);
67 exit;
68 }
69
70 if ($enableUnsubscribeConfirmation) {
71 $this->initSubscriptionPage(UserSubscription\Pages::ACTION_CONFIRM_UNSUBSCRIBE, $data);
72 } else {
73 $this->performUnsubscribe($data, StatisticsUnsubscribeEntity::METHOD_LINK);
74 }
75 }
76
77 public function manage($data) {
78 $this->initSubscriptionPage(UserSubscription\Pages::ACTION_MANAGE, $data);
79 }
80
81 public function unsubscribe($data) {
82 if ($this->isPostRequest()) {
83 if ($this->request->getStringParam('type') === 'confirmation') {
84 // POST from confirmation page
85 $this->performUnsubscribe($data, StatisticsUnsubscribeEntity::METHOD_LINK);
86 } else {
87 // POST from one click unsubscribe
88 $this->performUnsubscribe($data, StatisticsUnsubscribeEntity::METHOD_ONE_CLICK);
89 exit;
90 }
91 } else {
92 // For GET requests, we render the confirmUnsubscribe page, unless it is preview request of successful unsubscribe
93 // or the subscriber is already unsubscribed.
94 if (isset($data['preview']) && $data['preview'] && !isset($data['token'])) {
95 $this->performUnsubscribe($data, StatisticsUnsubscribeEntity::METHOD_LINK);
96 } elseif ($this->renderUnsubscribePageForAlreadyUnsubscribedSubscriber($data)) {
97 return;
98 } else {
99 $this->confirmUnsubscribe($data);
100 }
101 }
102 }
103
104 public function unsubscribeReason($data) {
105 if (!$this->request->isPost()) {
106 $this->wp->wpSafeRedirect($this->wp->homeUrl());
107 exit;
108 }
109
110 $nonce = $this->request->getStringParam('_wpnonce');
111 if (!$this->wp->wpVerifyNonce($nonce, 'mailpoet_unsubscribe_reason')) {
112 $this->wp->wpDie(__('Security check failed.', 'mailpoet'), '', ['response' => 403]);
113 exit;
114 }
115
116 $subscription = $this->initSubscriptionPage(UserSubscription\Pages::ACTION_UNSUBSCRIBE, $data);
117 $reason = strtolower($this->wp->sanitizeKey((string)$this->request->getStringParam('reason')));
118 $reasonText = $this->request->getTextareaParam('reason_text');
119
120 $saved = $reason !== '' && $subscription->saveUnsubscribeReason($reason, $reasonText);
121 $this->wp->wpSafeRedirect($subscription->getUnsubscribeReasonRedirectUrl($saved));
122 exit;
123 }
124
125 public function reEngagement($data) {
126 $this->initSubscriptionPage(UserSubscription\Pages::ACTION_RE_ENGAGEMENT, $data);
127 }
128
129 public function trackingOptOut($data) {
130 $subscription = $this->initSubscriptionPage(UserSubscription\Pages::ACTION_TRACKING_OPT_OUT, $data);
131 if ($this->isPostRequest()) {
132 $nonce = $this->request->getStringParam('_wpnonce');
133 if (!$this->wp->wpVerifyNonce($nonce, 'mailpoet_tracking_opt_out')) {
134 $this->wp->wpDie(__('Security check failed.', 'mailpoet'), '', ['response' => 403]);
135 exit;
136 }
137 $subscription->trackingOptOut(
138 SubscriberEntity::TRACKING_CONSENT_METHOD_FOOTER_LINK,
139 UserSubscription\Pages::getTrackingOptOutConsentCopy()
140 );
141 }
142 // GET renders the confirmation page; after POST the same page renders
143 // its "done" state via getTrackingOptOutContent().
144 }
145
146 private function initSubscriptionPage($action, $data) {
147 return $this->subscriptionPages->init($action, $data, true, true);
148 }
149
150 private function renderUnsubscribePageForAlreadyUnsubscribedSubscriber($data): bool {
151 $subscription = $this->subscriptionPages->init(UserSubscription\Pages::ACTION_UNSUBSCRIBE, $data, false, false);
152 if (!$subscription->isSubscriberUnsubscribed()) {
153 return false;
154 }
155
156 $this->initSubscriptionPage(UserSubscription\Pages::ACTION_UNSUBSCRIBE, $data);
157 return true;
158 }
159
160 private function performUnsubscribe($data, string $method): void {
161 $subscription = $this->initSubscriptionPage(UserSubscription\Pages::ACTION_UNSUBSCRIBE, $data);
162 $subscription->unsubscribe($method);
163 }
164
165 private function isPostRequest(): bool {
166 if ($this->request->isPost()) {
167 return true;
168 }
169 // For tracking redirects we store original method in the query string
170 $requestMethod = $this->request->getStringParam('request_method');
171 if (!$requestMethod) {
172 return false;
173 }
174 return strtoupper($requestMethod) === 'POST';
175 }
176 }
177