Açıklama Yok

Subscription.php 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <?php
  2. namespace MailPoet\WooCommerce;
  3. if (!defined('ABSPATH')) exit;
  4. use MailPoet\Entities\StatisticsUnsubscribeEntity;
  5. use MailPoet\Entities\SubscriberEntity;
  6. use MailPoet\Models\Segment;
  7. use MailPoet\Models\Subscriber;
  8. use MailPoet\Models\SubscriberSegment;
  9. use MailPoet\Settings\SettingsController;
  10. use MailPoet\Statistics\Track\Unsubscribes;
  11. use MailPoet\Subscribers\ConfirmationEmailMailer;
  12. use MailPoet\Subscribers\Source;
  13. use MailPoet\Subscribers\SubscribersRepository;
  14. use MailPoet\Util\Helpers;
  15. use MailPoet\WP\Functions as WPFunctions;
  16. class Subscription {
  17. const CHECKOUT_OPTIN_INPUT_NAME = 'mailpoet_woocommerce_checkout_optin';
  18. const CHECKOUT_OPTIN_PRESENCE_CHECK_INPUT_NAME = 'mailpoet_woocommerce_checkout_optin_present';
  19. const OPTIN_ENABLED_SETTING_NAME = 'woocommerce.optin_on_checkout.enabled';
  20. const OPTIN_SEGMENTS_SETTING_NAME = 'woocommerce.optin_on_checkout.segments';
  21. const OPTIN_MESSAGE_SETTING_NAME = 'woocommerce.optin_on_checkout.message';
  22. /** @var SettingsController */
  23. private $settings;
  24. /** @var WPFunctions */
  25. private $wp;
  26. /** @var Helper */
  27. private $wcHelper;
  28. /** @var ConfirmationEmailMailer */
  29. private $confirmationEmailMailer;
  30. /** @var SubscribersRepository */
  31. private $subscribersRepository;
  32. /** @var Unsubscribes */
  33. private $unsubscribesTracker;
  34. public function __construct(
  35. SettingsController $settings,
  36. ConfirmationEmailMailer $confirmationEmailMailer,
  37. WPFunctions $wp,
  38. Helper $wcHelper,
  39. SubscribersRepository $subscribersRepository,
  40. Unsubscribes $unsubscribesTracker
  41. ) {
  42. $this->settings = $settings;
  43. $this->wp = $wp;
  44. $this->wcHelper = $wcHelper;
  45. $this->confirmationEmailMailer = $confirmationEmailMailer;
  46. $this->subscribersRepository = $subscribersRepository;
  47. $this->unsubscribesTracker = $unsubscribesTracker;
  48. }
  49. public function extendWooCommerceCheckoutForm() {
  50. $inputName = self::CHECKOUT_OPTIN_INPUT_NAME;
  51. $checked = $this->isCurrentUserSubscribed();
  52. if (!empty($_POST[self::CHECKOUT_OPTIN_INPUT_NAME])) {
  53. $checked = true;
  54. }
  55. $labelString = $this->settings->get(self::OPTIN_MESSAGE_SETTING_NAME);
  56. $template = $this->wp->applyFilters(
  57. 'mailpoet_woocommerce_checkout_optin_template',
  58. $this->getSubscriptionField($inputName, $checked, $labelString),
  59. $inputName,
  60. $checked,
  61. $labelString
  62. );
  63. echo $template;
  64. if ($template) {
  65. echo $this->getSubscriptionPresenceCheckField();
  66. }
  67. }
  68. private function getSubscriptionField($inputName, $checked, $labelString) {
  69. return $this->wcHelper->woocommerceFormField(
  70. $this->wp->escAttr($inputName),
  71. [
  72. 'type' => 'checkbox',
  73. 'label' => $this->wp->escHtml($labelString),
  74. 'input_class' => ['woocommerce-form__input', 'woocommerce-form__input-checkbox', 'input-checkbox'],
  75. 'label_class' => ['woocommerce-form__label', 'woocommerce-form__label-for-checkbox', 'checkbox'],
  76. 'custom_attributes' => ['data-automation-id' => 'woo-commerce-subscription-opt-in'],
  77. 'return' => true,
  78. ],
  79. $checked ? '1' : '0'
  80. );
  81. }
  82. private function getSubscriptionPresenceCheckField() {
  83. $field = $this->wcHelper->woocommerceFormField(
  84. self::CHECKOUT_OPTIN_PRESENCE_CHECK_INPUT_NAME,
  85. [
  86. 'type' => 'hidden',
  87. 'return' => true,
  88. ],
  89. 1
  90. );
  91. if ($field) {
  92. return $field;
  93. }
  94. // Workaround for older WooCommerce versions (below 4.6.0) that don't support hidden fields
  95. // We can remove it after we drop support of older WooCommerce
  96. $field = $this->wcHelper->woocommerceFormField(
  97. self::CHECKOUT_OPTIN_PRESENCE_CHECK_INPUT_NAME,
  98. [
  99. 'type' => 'text',
  100. 'return' => true,
  101. ],
  102. 1
  103. );
  104. return str_replace('type="text', 'type="hidden"', $field);
  105. }
  106. private function isCurrentUserSubscribed() {
  107. $subscriber = $this->subscribersRepository->getCurrentWPUser();
  108. if (!$subscriber instanceof SubscriberEntity) {
  109. return false;
  110. }
  111. $wcSegment = Segment::getWooCommerceSegment();
  112. $subscriberSegment = SubscriberSegment::where('subscriber_id', $subscriber->getId())
  113. ->where('segment_id', $wcSegment->id)
  114. ->findOne();
  115. return $subscriberSegment instanceof SubscriberSegment
  116. && $subscriberSegment->status === Subscriber::STATUS_SUBSCRIBED;
  117. }
  118. public function subscribeOnCheckout($orderId, $data) {
  119. if (empty($data['billing_email'])) {
  120. // no email in posted order data
  121. return null;
  122. }
  123. $subscriber = Subscriber::where('email', $data['billing_email'])
  124. ->where('is_woocommerce_user', 1)
  125. ->findOne();
  126. if (!$subscriber) {
  127. // no subscriber: WooCommerce sync didn't work
  128. return null;
  129. }
  130. $checkoutOptinEnabled = (bool)$this->settings->get(self::OPTIN_ENABLED_SETTING_NAME);
  131. $wcSegment = Segment::getWooCommerceSegment();
  132. $moreSegmentsToSubscribe = (array)$this->settings->get(self::OPTIN_SEGMENTS_SETTING_NAME, []);
  133. if (!$checkoutOptinEnabled || empty($_POST[self::CHECKOUT_OPTIN_INPUT_NAME])) {
  134. // Opt-in is disabled or checkbox is unchecked
  135. SubscriberSegment::unsubscribeFromSegments(
  136. $subscriber,
  137. [$wcSegment->id]
  138. );
  139. if ($checkoutOptinEnabled) {
  140. $this->updateSubscriberStatus($subscriber);
  141. }
  142. return false;
  143. }
  144. $subscriber->source = Source::WOOCOMMERCE_CHECKOUT;
  145. $signupConfirmation = $this->settings->get('signup_confirmation');
  146. // checkbox is checked
  147. if (
  148. ($subscriber->status === Subscriber::STATUS_SUBSCRIBED)
  149. || ((bool)$signupConfirmation['enabled'] === false)
  150. ) {
  151. $this->subscribe($subscriber);
  152. } else {
  153. $this->requireSubscriptionConfirmation($subscriber);
  154. }
  155. SubscriberSegment::subscribeToSegments(
  156. $subscriber,
  157. array_merge([$wcSegment->id], $moreSegmentsToSubscribe)
  158. );
  159. return true;
  160. }
  161. private function subscribe(Subscriber $subscriber) {
  162. $subscriber->status = Subscriber::STATUS_SUBSCRIBED;
  163. if (empty($subscriber->confirmedIp) && empty($subscriber->confirmedAt)) {
  164. $subscriber->confirmedIp = Helpers::getIP();
  165. $subscriber->setExpr('confirmed_at', 'NOW()');
  166. }
  167. $subscriber->save();
  168. }
  169. private function requireSubscriptionConfirmation(Subscriber $subscriber) {
  170. $subscriber->status = Subscriber::STATUS_UNCONFIRMED;
  171. $subscriber->save();
  172. $this->confirmationEmailMailer->sendConfirmationEmailOnce($subscriber);
  173. }
  174. private function updateSubscriberStatus(Subscriber $subscriber) {
  175. $ss = Subscriber::findOne($subscriber->id);
  176. $segmentsCount = $ss->segments()->count();
  177. if (!$segmentsCount) {
  178. $subscriber->status = Subscriber::STATUS_UNSUBSCRIBED;
  179. $subscriber->save();
  180. $this->unsubscribesTracker->track($subscriber->id, StatisticsUnsubscribeEntity::SOURCE_ORDER_CHECKOUT);
  181. }
  182. }
  183. }