AdminUserSubscription.php
2 months ago
Blacklist.php
1 year ago
Comment.php
2 months ago
Form.php
2 weeks ago
Manage.php
5 days ago
ManageSubscriptionFormRenderer.php
5 days ago
Pages.php
5 days ago
Registration.php
2 months ago
SubscriptionUrlFactory.php
5 days ago
Throttling.php
2 months ago
index.php
3 years ago
ManageSubscriptionFormRenderer.php
372 lines
| 1 | <?php declare(strict_types = 1); |
| 2 | |
| 3 | namespace MailPoet\Subscription; |
| 4 | |
| 5 | if (!defined('ABSPATH')) exit; |
| 6 | |
| 7 | |
| 8 | use MailPoet\Config\Renderer as TemplateRenderer; |
| 9 | use MailPoet\CustomFields\CustomFieldsRepository; |
| 10 | use MailPoet\Entities\CustomFieldEntity; |
| 11 | use MailPoet\Entities\SegmentEntity; |
| 12 | use MailPoet\Entities\SubscriberEntity; |
| 13 | use MailPoet\Form\Block\Date as FormBlockDate; |
| 14 | use MailPoet\Form\Renderer as FormRenderer; |
| 15 | use MailPoet\Segments\SegmentsRepository; |
| 16 | use MailPoet\Settings\SettingsController; |
| 17 | use MailPoet\Subscribers\LinkTokens; |
| 18 | use MailPoet\Util\Helpers; |
| 19 | use MailPoet\Util\Url as UrlHelper; |
| 20 | use MailPoet\WP\Functions as WPFunctions; |
| 21 | use MailPoetVendor\Doctrine\Common\Collections\Criteria; |
| 22 | |
| 23 | class ManageSubscriptionFormRenderer { |
| 24 | const FORM_STATE_SUCCESS = 'success'; |
| 25 | const FORM_STATE_ERROR = 'error'; |
| 26 | const FORM_STATE_NOT_SUBMITTED = 'not_submitted'; |
| 27 | |
| 28 | /** @var UrlHelper */ |
| 29 | private $urlHelper; |
| 30 | |
| 31 | /** @var WPFunctions */ |
| 32 | private $wp; |
| 33 | |
| 34 | /** @var LinkTokens */ |
| 35 | private $linkTokens; |
| 36 | |
| 37 | /** @var FormRenderer */ |
| 38 | private $formRenderer; |
| 39 | |
| 40 | /** @var FormBlockDate */ |
| 41 | private $dateBlock; |
| 42 | |
| 43 | /** @var TemplateRenderer */ |
| 44 | private $templateRenderer; |
| 45 | |
| 46 | /** @var CustomFieldsRepository */ |
| 47 | private $customFieldsRepository; |
| 48 | |
| 49 | /** @var SegmentsRepository */ |
| 50 | private $segmentsRepository; |
| 51 | |
| 52 | /** @var SettingsController */ |
| 53 | private $settings; |
| 54 | |
| 55 | public function __construct( |
| 56 | WPFunctions $wp, |
| 57 | UrlHelper $urlHelper, |
| 58 | LinkTokens $linkTokens, |
| 59 | FormRenderer $formRenderer, |
| 60 | FormBlockDate $dateBlock, |
| 61 | TemplateRenderer $templateRenderer, |
| 62 | CustomFieldsRepository $customFieldsRepository, |
| 63 | SegmentsRepository $segmentsRepository, |
| 64 | SettingsController $settings |
| 65 | ) { |
| 66 | $this->wp = $wp; |
| 67 | $this->urlHelper = $urlHelper; |
| 68 | $this->linkTokens = $linkTokens; |
| 69 | $this->formRenderer = $formRenderer; |
| 70 | $this->dateBlock = $dateBlock; |
| 71 | $this->templateRenderer = $templateRenderer; |
| 72 | $this->customFieldsRepository = $customFieldsRepository; |
| 73 | $this->segmentsRepository = $segmentsRepository; |
| 74 | $this->settings = $settings; |
| 75 | } |
| 76 | |
| 77 | public function renderForm(SubscriberEntity $subscriber, string $formState = self::FORM_STATE_NOT_SUBMITTED): string { |
| 78 | $isModernStyle = $this->isModernStyle(); |
| 79 | $basicFields = $this->getBasicFields($subscriber, $isModernStyle); |
| 80 | $customFields = $this->getCustomFields($subscriber); |
| 81 | $segmentField = $this->getSegmentField($subscriber, $isModernStyle); |
| 82 | $submitField = [ |
| 83 | 'id' => 'submit', |
| 84 | 'type' => 'submit', |
| 85 | 'params' => [ |
| 86 | 'label' => $isModernStyle ? __('Save changes', 'mailpoet') : __('Save', 'mailpoet'), |
| 87 | ], |
| 88 | ]; |
| 89 | |
| 90 | $form = array_merge( |
| 91 | $basicFields, |
| 92 | $customFields, |
| 93 | [ |
| 94 | $segmentField, |
| 95 | $submitField, |
| 96 | ] |
| 97 | ); |
| 98 | |
| 99 | $filteredForm = $this->wp->applyFilters('mailpoet_manage_subscription_page_form_fields', $form); |
| 100 | if (is_array($filteredForm)) { |
| 101 | $form = $filteredForm; |
| 102 | } |
| 103 | |
| 104 | $templateData = [ |
| 105 | 'actionUrl' => admin_url('admin-post.php'), |
| 106 | 'redirectUrl' => $this->urlHelper->getCurrentUrl(), |
| 107 | 'email' => $subscriber->getEmail(), |
| 108 | 'token' => $this->linkTokens->getToken($subscriber), |
| 109 | 'editEmailInfo' => __('Need to change your email address? Unsubscribe using the form below, then simply sign up again.', 'mailpoet'), |
| 110 | 'isModernStyle' => $isModernStyle, |
| 111 | 'isGloballyUnsubscribed' => $subscriber->getStatus() === SubscriberEntity::STATUS_UNSUBSCRIBED, |
| 112 | 'formState' => $formState, |
| 113 | ]; |
| 114 | |
| 115 | if ($isModernStyle) { |
| 116 | $formSections = $this->splitFormSections($form); |
| 117 | $templateData['identityFieldsHtml'] = $this->formRenderer->renderBlocks($formSections['identityFields'], [], null, $honeypot = false, $captcha = false); |
| 118 | $templateData['additionalIdentityFieldsHtml'] = $this->formRenderer->renderBlocks($formSections['additionalIdentityFields'], [], null, $honeypot = false, $captcha = false); |
| 119 | $templateData['listFieldsHtml'] = $this->formRenderer->renderBlocks($formSections['listFields'], [], null, $honeypot = false, $captcha = false); |
| 120 | $templateData['submitHtml'] = $this->formRenderer->renderBlocks($formSections['submitFields'], [], null, $honeypot = false, $captcha = false); |
| 121 | $templateData['hasVisibleLists'] = $formSections['hasVisibleLists']; |
| 122 | } else { |
| 123 | $templateData['formHtml'] = $this->formRenderer->renderBlocks($form, [], null, $honeypot = false, $captcha = false); |
| 124 | } |
| 125 | |
| 126 | if ($subscriber->isWPUser() || $subscriber->getIsWoocommerceUser()) { |
| 127 | $wpCurrentUser = $this->wp->wpGetCurrentUser(); |
| 128 | if ($wpCurrentUser->user_email === $subscriber->getEmail()) { // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps |
| 129 | $templateData['editEmailInfo'] = Helpers::replaceLinkTags( |
| 130 | __('[link]Edit your profile[/link] to update your email.', 'mailpoet'), |
| 131 | $this->wp->getEditProfileUrl(), |
| 132 | ['target' => '_blank'] |
| 133 | ); |
| 134 | } else { |
| 135 | $templateData['editEmailInfo'] = Helpers::replaceLinkTags( |
| 136 | __('[link]Log in to your account[/link] to update your email.', 'mailpoet'), |
| 137 | $this->wp->wpLoginUrl(), |
| 138 | ['target' => '_blank'] |
| 139 | ); |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | return $this->templateRenderer->render('subscription/manage_subscription.html', $templateData); |
| 144 | } |
| 145 | |
| 146 | private function isModernStyle(): bool { |
| 147 | return $this->settings->get('subscription.manage_subscription_page_style') === SettingsController::MANAGE_SUBSCRIPTION_PAGE_STYLE_MODERN; |
| 148 | } |
| 149 | |
| 150 | private function splitFormSections(array $form): array { |
| 151 | $identityFields = []; |
| 152 | $additionalIdentityFields = []; |
| 153 | $listFields = []; |
| 154 | $submitFields = []; |
| 155 | $hasVisibleLists = false; |
| 156 | $placeAdditionalIdentityFieldsAfterNoListNotice = false; |
| 157 | |
| 158 | foreach ($form as $field) { |
| 159 | if (!is_array($field)) { |
| 160 | continue; |
| 161 | } |
| 162 | $params = isset($field['params']) && is_array($field['params']) ? $field['params'] : []; |
| 163 | |
| 164 | if (($field['type'] ?? null) === 'submit') { |
| 165 | $submitFields[] = $field; |
| 166 | continue; |
| 167 | } |
| 168 | |
| 169 | if (($field['type'] ?? null) === 'segment' && (($params['display_mode'] ?? null) === 'manage_subscription_choices')) { |
| 170 | if (!empty($params['values']) && is_array($params['values'])) { |
| 171 | $hasVisibleLists = true; |
| 172 | $listFields[] = $field; |
| 173 | } |
| 174 | continue; |
| 175 | } |
| 176 | |
| 177 | if ($placeAdditionalIdentityFieldsAfterNoListNotice) { |
| 178 | $additionalIdentityFields[] = $field; |
| 179 | } else { |
| 180 | $identityFields[] = $field; |
| 181 | } |
| 182 | if (($field['id'] ?? null) === 'status') { |
| 183 | $placeAdditionalIdentityFieldsAfterNoListNotice = true; |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | return [ |
| 188 | 'identityFields' => $identityFields, |
| 189 | 'additionalIdentityFields' => $additionalIdentityFields, |
| 190 | 'listFields' => $listFields, |
| 191 | 'submitFields' => $submitFields, |
| 192 | 'hasVisibleLists' => $hasVisibleLists, |
| 193 | ]; |
| 194 | } |
| 195 | |
| 196 | private function getCustomFields(SubscriberEntity $subscriber): array { |
| 197 | $customFieldValues = []; |
| 198 | foreach ($subscriber->getSubscriberCustomFields() as $subscriberCustomField) { |
| 199 | $customField = $subscriberCustomField->getCustomField(); |
| 200 | if (!$customField) continue; |
| 201 | |
| 202 | $customFieldValues[$customField->getId()] = $subscriberCustomField->getValue(); |
| 203 | } |
| 204 | return array_map(function (CustomFieldEntity $customFieldEntity) use ($customFieldValues) { |
| 205 | $customField = [ |
| 206 | 'id' => 'cf_' . $customFieldEntity->getId(), |
| 207 | 'name' => $customFieldEntity->getName(), |
| 208 | 'type' => $customFieldEntity->getType(), |
| 209 | 'params' => $customFieldEntity->getParams(), |
| 210 | ]; |
| 211 | |
| 212 | $customField['params']['value'] = $customFieldValues[$customFieldEntity->getId()] ?? null; |
| 213 | |
| 214 | if ($customField['type'] === 'date') { |
| 215 | $dateFormats = $this->dateBlock->getDateFormats(); |
| 216 | $customField['params']['date_format'] = array_shift( |
| 217 | $dateFormats[$customField['params']['date_type']] |
| 218 | ); |
| 219 | } |
| 220 | if (!isset($customField['params']['label'])) { |
| 221 | $customField['params']['label'] = $customField['name']; |
| 222 | } |
| 223 | |
| 224 | return $customField; |
| 225 | }, $this->customFieldsRepository->findAllActive()); |
| 226 | } |
| 227 | |
| 228 | public static function getTrackingConsentCopy(): string { |
| 229 | return __('Allow tracking of email opens and link clicks', 'mailpoet'); |
| 230 | } |
| 231 | |
| 232 | private function getBasicFields(SubscriberEntity $subscriber, bool $isModernStyle): array { |
| 233 | $statusParams = [ |
| 234 | 'required' => true, |
| 235 | 'label' => $isModernStyle ? __('Email subscription status', 'mailpoet') : __('Status', 'mailpoet'), |
| 236 | 'values' => [ |
| 237 | [ |
| 238 | 'value' => [ |
| 239 | SubscriberEntity::STATUS_SUBSCRIBED => __('Subscribed', 'mailpoet'), |
| 240 | ], |
| 241 | 'is_checked' => ( |
| 242 | $subscriber->getStatus() === SubscriberEntity::STATUS_SUBSCRIBED |
| 243 | ), |
| 244 | ], |
| 245 | [ |
| 246 | 'value' => [ |
| 247 | SubscriberEntity::STATUS_UNSUBSCRIBED => __('Unsubscribed', 'mailpoet'), |
| 248 | ], |
| 249 | 'is_checked' => ( |
| 250 | $subscriber->getStatus() === SubscriberEntity::STATUS_UNSUBSCRIBED |
| 251 | ), |
| 252 | ], |
| 253 | [ |
| 254 | 'value' => [ |
| 255 | SubscriberEntity::STATUS_BOUNCED => __('Bounced', 'mailpoet'), |
| 256 | ], |
| 257 | 'is_checked' => ( |
| 258 | $subscriber->getStatus() === SubscriberEntity::STATUS_BOUNCED |
| 259 | ), |
| 260 | 'is_disabled' => true, |
| 261 | 'is_hidden' => ( |
| 262 | $subscriber->getStatus() !== SubscriberEntity::STATUS_BOUNCED |
| 263 | ), |
| 264 | ], |
| 265 | [ |
| 266 | 'value' => [ |
| 267 | SubscriberEntity::STATUS_INACTIVE => __('Inactive', 'mailpoet'), |
| 268 | ], |
| 269 | 'is_checked' => ( |
| 270 | $subscriber->getStatus() === SubscriberEntity::STATUS_INACTIVE |
| 271 | ), |
| 272 | 'is_hidden' => ( |
| 273 | $subscriber->getStatus() !== SubscriberEntity::STATUS_INACTIVE |
| 274 | ), |
| 275 | ], |
| 276 | ], |
| 277 | ]; |
| 278 | if ($isModernStyle) { |
| 279 | $statusParams['description'] = __('This controls whether you receive emails overall. Your list choices below control which public lists you receive.', 'mailpoet'); |
| 280 | $statusParams['class_name'] = 'mailpoet-manage-subscription-status'; |
| 281 | $statusParams['input_id'] = 'mailpoet_manage_subscription_status'; |
| 282 | } |
| 283 | |
| 284 | return [ |
| 285 | [ |
| 286 | 'id' => 'first_name', |
| 287 | 'type' => 'text', |
| 288 | 'params' => [ |
| 289 | 'label' => __('First name', 'mailpoet'), |
| 290 | 'value' => $subscriber->getFirstName(), |
| 291 | 'disabled' => ($subscriber->isWPUser() || $subscriber->getIsWoocommerceUser()), |
| 292 | ], |
| 293 | ], |
| 294 | [ |
| 295 | 'id' => 'last_name', |
| 296 | 'type' => 'text', |
| 297 | 'params' => [ |
| 298 | 'label' => __('Last name', 'mailpoet'), |
| 299 | 'value' => $subscriber->getLastName(), |
| 300 | 'disabled' => ($subscriber->isWPUser() || $subscriber->getIsWoocommerceUser()), |
| 301 | ], |
| 302 | ], |
| 303 | [ |
| 304 | 'id' => 'status', |
| 305 | 'type' => 'select', |
| 306 | 'params' => $statusParams, |
| 307 | ], |
| 308 | [ |
| 309 | 'id' => 'tracking_consent', |
| 310 | 'type' => 'checkbox', |
| 311 | 'params' => [ |
| 312 | 'label' => __('Email activity tracking', 'mailpoet'), |
| 313 | 'values' => [ |
| 314 | [ |
| 315 | 'value' => self::getTrackingConsentCopy(), |
| 316 | 'is_checked' => $subscriber->getTrackingConsent() === SubscriberEntity::TRACKING_CONSENT_GRANTED, |
| 317 | ], |
| 318 | ], |
| 319 | ], |
| 320 | ], |
| 321 | ]; |
| 322 | } |
| 323 | |
| 324 | private function getSegmentField(SubscriberEntity $subscriber, bool $isModernStyle): array { |
| 325 | // Get default segments |
| 326 | $criteria = [ |
| 327 | 'type' => SegmentEntity::TYPE_DEFAULT, |
| 328 | 'deletedAt' => null, |
| 329 | 'displayInManageSubscriptionPage' => true, |
| 330 | ]; |
| 331 | $segments = $this->segmentsRepository->findBy($criteria, ['name' => Criteria::ASC]); |
| 332 | |
| 333 | $subscribedSegmentIds = []; |
| 334 | foreach ($subscriber->getSubscriberSegments() as $subscriberSegment) { |
| 335 | $segment = $subscriberSegment->getSegment(); |
| 336 | if (!$segment) continue; |
| 337 | |
| 338 | if ($subscriberSegment->getStatus() === SubscriberEntity::STATUS_SUBSCRIBED) { |
| 339 | $subscribedSegmentIds[] = $segment->getId(); |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | $segments = array_map(function (SegmentEntity $segment) use ($subscribedSegmentIds, $isModernStyle) { |
| 344 | $segmentData = [ |
| 345 | 'id' => $segment->getId(), |
| 346 | 'name' => $segment->getName(), |
| 347 | 'is_checked' => in_array($segment->getId(), $subscribedSegmentIds), |
| 348 | ]; |
| 349 | if ($isModernStyle) { |
| 350 | $segmentData['public_description'] = $segment->getPublicDescription(); |
| 351 | } |
| 352 | return $segmentData; |
| 353 | }, $segments); |
| 354 | |
| 355 | $params = [ |
| 356 | 'label' => __('Your lists', 'mailpoet'), |
| 357 | 'class_name' => 'mailpoet-manage-subscription-list-fields', |
| 358 | 'values' => $segments, |
| 359 | ]; |
| 360 | if ($isModernStyle) { |
| 361 | $params['description'] = __('Choose Yes for lists you want to receive and No for lists you do not want to receive.', 'mailpoet'); |
| 362 | $params['display_mode'] = 'manage_subscription_choices'; |
| 363 | } |
| 364 | |
| 365 | return [ |
| 366 | 'id' => 'segments', |
| 367 | 'type' => 'segment', |
| 368 | 'params' => $params, |
| 369 | ]; |
| 370 | } |
| 371 | } |
| 372 |