AdminUserSubscription.php
3 months ago
Blacklist.php
1 year ago
Comment.php
1 week ago
Form.php
1 month ago
Manage.php
1 month ago
ManageSubscriptionFormRenderer.php
2 weeks ago
Pages.php
5 days ago
Registration.php
1 week ago
SubscriptionUrlFactory.php
1 month ago
Throttling.php
3 months ago
index.php
3 years ago
Comment.php
188 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\Entities\SubscriberEntity; |
| 9 | use MailPoet\Settings\SettingsController; |
| 10 | use MailPoet\Subscribers\SubscriberActions; |
| 11 | use MailPoet\Subscribers\TrackingConsentCapture; |
| 12 | use MailPoet\WP\Functions as WPFunctions; |
| 13 | |
| 14 | class Comment { |
| 15 | const SPAM = 'spam'; |
| 16 | const APPROVED = 1; |
| 17 | const PENDING_APPROVAL = 0; |
| 18 | |
| 19 | /** |
| 20 | * Comment meta remembering the tracking-consent choice while a comment waits |
| 21 | * for moderation. The subscribe is deferred to approval, which happens in a |
| 22 | * later request with no POST data, so the choice has to be stored with the |
| 23 | * comment rather than re-read. |
| 24 | */ |
| 25 | const TRACKING_CONSENT_META = 'mailpoet_tracking_consent'; |
| 26 | |
| 27 | /** @var SettingsController */ |
| 28 | private $settings; |
| 29 | |
| 30 | /** @var SubscriberActions */ |
| 31 | private $subscriberActions; |
| 32 | |
| 33 | /** @var TrackingConsentCapture */ |
| 34 | private $trackingConsentCapture; |
| 35 | |
| 36 | public function __construct( |
| 37 | SettingsController $settings, |
| 38 | SubscriberActions $subscriberActions, |
| 39 | TrackingConsentCapture $trackingConsentCapture |
| 40 | ) { |
| 41 | $this->settings = $settings; |
| 42 | $this->subscriberActions = $subscriberActions; |
| 43 | $this->trackingConsentCapture = $trackingConsentCapture; |
| 44 | } |
| 45 | |
| 46 | public function extendLoggedInForm($field) { |
| 47 | $field .= $this->getSubscriptionField(); |
| 48 | return $field; |
| 49 | } |
| 50 | |
| 51 | public function extendLoggedOutForm() { |
| 52 | // The method returns escaped content |
| 53 | // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
| 54 | echo $this->getSubscriptionField(); |
| 55 | } |
| 56 | |
| 57 | /** |
| 58 | * Returns escaped HTML for the subscription field. |
| 59 | * |
| 60 | * @return string |
| 61 | */ |
| 62 | private function getSubscriptionField(): string { |
| 63 | $label = $this->settings->get( |
| 64 | 'subscribe.on_comment.label', |
| 65 | __('Yes, please add me to your mailing list.', 'mailpoet') |
| 66 | ); |
| 67 | |
| 68 | return '<p class="comment-form-mailpoet"> |
| 69 | <label for="mailpoet_subscribe_on_comment"> |
| 70 | <input |
| 71 | type="checkbox" |
| 72 | id="mailpoet_subscribe_on_comment" |
| 73 | value="1" |
| 74 | name="mailpoet[subscribe_on_comment]" |
| 75 | /> ' . esc_html($label) . ' |
| 76 | </label> |
| 77 | </p>' . $this->getTrackingConsentField(); |
| 78 | } |
| 79 | |
| 80 | /** |
| 81 | * A second, independent checkbox. Consent to open and click tracking is never |
| 82 | * inferred from the subscribe box above it, and it is only shown on sites |
| 83 | * that chose to ask. Never pre-ticked: a pre-ticked consent box is not valid |
| 84 | * consent (CJEU Planet49). |
| 85 | */ |
| 86 | private function getTrackingConsentField(): string { |
| 87 | if (!$this->trackingConsentCapture->isCaptureEnabled()) { |
| 88 | return ''; |
| 89 | } |
| 90 | $copy = $this->trackingConsentCapture->getCopy( |
| 91 | SubscriberEntity::TRACKING_CONSENT_METHOD_COMMENT |
| 92 | ); |
| 93 | |
| 94 | return '<p class="comment-form-mailpoet-tracking-consent"> |
| 95 | <label for="mailpoet_tracking_consent"> |
| 96 | <input |
| 97 | type="checkbox" |
| 98 | id="mailpoet_tracking_consent" |
| 99 | value="1" |
| 100 | name="mailpoet[tracking_consent]" |
| 101 | /> ' . esc_html($copy) . ' |
| 102 | </label> |
| 103 | </p>'; |
| 104 | } |
| 105 | |
| 106 | public function onSubmit($commentId, $commentStatus) { |
| 107 | if ($commentStatus === Comment::SPAM) return; |
| 108 | |
| 109 | // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- type narrowing only, value is read as bool |
| 110 | $mailpoetPost = isset($_POST['mailpoet']) && is_array($_POST['mailpoet']) ? $_POST['mailpoet'] : []; |
| 111 | if ( |
| 112 | isset($mailpoetPost['subscribe_on_comment']) |
| 113 | && (bool)$mailpoetPost['subscribe_on_comment'] === true |
| 114 | ) { |
| 115 | $trackingConsent = !empty($mailpoetPost['tracking_consent']); |
| 116 | if ($commentStatus === Comment::PENDING_APPROVAL) { |
| 117 | // add a comment meta to remember to subscribe the user |
| 118 | // once the comment gets approved |
| 119 | WPFunctions::get()->addCommentMeta( |
| 120 | $commentId, |
| 121 | 'mailpoet', |
| 122 | 'subscribe_on_comment', |
| 123 | true |
| 124 | ); |
| 125 | // Approval runs in a later request with no POST data, so the consent |
| 126 | // choice is stored alongside it rather than re-read then. |
| 127 | WPFunctions::get()->addCommentMeta( |
| 128 | $commentId, |
| 129 | self::TRACKING_CONSENT_META, |
| 130 | $trackingConsent ? '1' : '0', |
| 131 | true |
| 132 | ); |
| 133 | } elseif ($commentStatus === Comment::APPROVED) { |
| 134 | $this->subscribeAuthorOfComment($commentId, $trackingConsent); |
| 135 | } |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | public function onStatusUpdate($commentId, $action) { |
| 140 | if ($action === 'approve') { |
| 141 | // check if the comment's author wants to subscribe |
| 142 | $doSubscribe = ( |
| 143 | WPFunctions::get()->getCommentMeta( |
| 144 | $commentId, |
| 145 | 'mailpoet', |
| 146 | true |
| 147 | ) === 'subscribe_on_comment' |
| 148 | ); |
| 149 | |
| 150 | if ($doSubscribe === true) { |
| 151 | $trackingConsent = WPFunctions::get()->getCommentMeta( |
| 152 | $commentId, |
| 153 | self::TRACKING_CONSENT_META, |
| 154 | true |
| 155 | ) === '1'; |
| 156 | $this->subscribeAuthorOfComment($commentId, $trackingConsent); |
| 157 | |
| 158 | WPFunctions::get()->deleteCommentMeta($commentId, 'mailpoet'); |
| 159 | WPFunctions::get()->deleteCommentMeta($commentId, self::TRACKING_CONSENT_META); |
| 160 | } |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | private function subscribeAuthorOfComment($commentId, bool $trackingConsent = false) { |
| 165 | $segmentIds = $this->settings->get('subscribe.on_comment.segments', []); |
| 166 | |
| 167 | if (!empty($segmentIds)) { |
| 168 | $comment = WPFunctions::get()->getComment($commentId); |
| 169 | $email = $comment->comment_author_email; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps |
| 170 | $method = SubscriberEntity::TRACKING_CONSENT_METHOD_COMMENT; |
| 171 | $consentData = $this->trackingConsentCapture->getConsentData( |
| 172 | $trackingConsent, |
| 173 | $method, |
| 174 | $this->trackingConsentCapture->getCopy($method), |
| 175 | $this->trackingConsentCapture->isNewSubscriber($email) |
| 176 | ); |
| 177 | |
| 178 | $this->subscriberActions->subscribe( |
| 179 | array_merge([ |
| 180 | 'email' => $email, |
| 181 | 'first_name' => $comment->comment_author, // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps |
| 182 | ], $consentData), |
| 183 | $segmentIds |
| 184 | ); |
| 185 | } |
| 186 | } |
| 187 | } |
| 188 |