/wp-content/plugins/woocommerce-payments/vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy-background-updater.php

https://gitlab.com/remyvianne/krowkaramel · PHP · 222 lines · 109 code · 35 blank · 78 comment · 14 complexity · 95db2685ac5dedce8d3b3c543a1fb808 MD5 · raw file

  1. <?php
  2. /**
  3. * Privacy Background Updater.
  4. *
  5. * @author Prospress
  6. * @category Class
  7. * @package WooCommerce Subscriptions\Privacy
  8. * @version 2.2.20
  9. */
  10. if ( ! defined( 'ABSPATH' ) ) {
  11. exit; // Exit if accessed directly
  12. }
  13. class WCS_Privacy_Background_Updater {
  14. /**
  15. * @var string The hook used to schedule subscription anonymization.
  16. */
  17. protected $ended_subscription_anonymization_hook = 'woocommerce_subscriptions_privacy_anonymize_ended_subscriptions';
  18. /**
  19. * @var string The hook used to schedule subscription related order anonymization.
  20. */
  21. protected $subscription_orders_anonymization_hook = 'woocommerce_subscriptions_privacy_anonymize_subscription_orders';
  22. /**
  23. * @var string The hook used to schedule individual order anonymization.
  24. */
  25. protected $order_anonymization_hook = 'woocommerce_subscriptions_privacy_anonymize_subscription_order';
  26. /**
  27. * Attach callbacks.
  28. */
  29. public function init() {
  30. add_action( $this->ended_subscription_anonymization_hook, array( $this, 'anonymize_ended_subscriptions' ) );
  31. add_action( $this->subscription_orders_anonymization_hook, array( $this, 'schedule_subscription_orders_anonymization_events' ), 10, 1 );
  32. add_action( $this->order_anonymization_hook, array( $this, 'anonymize_order' ), 10, 1 );
  33. }
  34. /**
  35. * Schedule ended subscription anonymization, if it's not already scheduled.
  36. *
  37. * @since 2.2.20
  38. */
  39. public function schedule_ended_subscription_anonymization() {
  40. if ( false === as_next_scheduled_action( $this->ended_subscription_anonymization_hook ) ) {
  41. as_schedule_single_action( time(), $this->ended_subscription_anonymization_hook );
  42. }
  43. }
  44. /**
  45. * Unschedule the ended subscription anonymization hook.
  46. *
  47. * @since 2.2.20
  48. */
  49. protected function unschedule_ended_subscription_anonymization() {
  50. as_unschedule_action( $this->ended_subscription_anonymization_hook );
  51. }
  52. /**
  53. * Schedule subscription related order anonymization, if it's not already scheduled.
  54. *
  55. * @since 2.2.20
  56. * @param int The subscription ID.
  57. */
  58. protected function schedule_subscription_orders_anonymization( $subscription_id ) {
  59. $action_args = array( 'subscription_id' => intval( $subscription_id ) );
  60. if ( false === as_next_scheduled_action( $this->subscription_orders_anonymization_hook, $action_args ) ) {
  61. as_schedule_single_action( time(), $this->subscription_orders_anonymization_hook, $action_args );
  62. }
  63. }
  64. /**
  65. * Unschedule a specific subscription's related order anonymization hook.
  66. *
  67. * @since 2.2.20
  68. * @param int The subscription ID.
  69. */
  70. protected function unschedule_subscription_orders_anonymization( $subscription_id ) {
  71. as_unschedule_action( $this->subscription_orders_anonymization_hook, array( 'subscription_id' => intval( $subscription_id ) ) );
  72. }
  73. /**
  74. * Schedule a specific order's anonymization action.
  75. *
  76. * @since 2.2.20
  77. * @param int The order ID.
  78. */
  79. protected function schedule_order_anonymization( $order_id ) {
  80. as_schedule_single_action( time(), $this->order_anonymization_hook, array( 'order_id' => intval( $order_id ) ) );
  81. }
  82. /**
  83. * Check if an order has a scheduled anonymization action.
  84. *
  85. * @since 2.2.20
  86. * @param int The order ID.
  87. * @return bool Wether the order has a scheduled anonymization action.
  88. */
  89. protected function order_anonymization_is_scheduled( $order_id ) {
  90. return false !== as_next_scheduled_action( $this->order_anonymization_hook, array( 'order_id' => intval( $order_id ) ) );
  91. }
  92. /**
  93. * Anonymize old ended subscriptions.
  94. *
  95. * @since 2.2.20
  96. */
  97. public function anonymize_ended_subscriptions() {
  98. $option = wc_parse_relative_date_option( get_option( 'woocommerce_anonymize_ended_subscriptions' ) );
  99. if ( empty( $option['number'] ) ) {
  100. return;
  101. }
  102. // Reschedule the cleanup now just in case something goes wrong.
  103. $this->schedule_ended_subscription_anonymization();
  104. $batch_size = 20;
  105. // Get the ended_statuses and removes pending-cancel.
  106. $subscription_ended_statuses = array_diff( wcs_get_subscription_ended_statuses(), array( 'pending-cancel' ) );
  107. $subscriptions = wcs_get_subscriptions( array(
  108. 'subscriptions_per_page' => $batch_size,
  109. 'subscription_status' => $subscription_ended_statuses,
  110. 'meta_query' => array(
  111. array(
  112. 'key' => '_schedule_end',
  113. 'compare' => '<',
  114. 'value' => gmdate( 'Y-m-d H:i:s', wc_string_to_timestamp( '-' . $option['number'] . ' ' . $option['unit'] ) ),
  115. 'type' => 'DATETIME',
  116. ),
  117. array(
  118. 'key' => '_anonymized',
  119. 'compare' => 'NOT EXISTS',
  120. ),
  121. ),
  122. ) );
  123. foreach ( $subscriptions as $subscription ) {
  124. if ( $subscription ) {
  125. $this->schedule_subscription_orders_anonymization( $subscription->get_id() );
  126. WCS_Privacy_Erasers::remove_subscription_personal_data( $subscription );
  127. }
  128. }
  129. // If we haven't processed a full batch, we don't have any more subscriptions to process so there's no need to run any other batches.
  130. if ( count( $subscriptions ) !== $batch_size ) {
  131. $this->unschedule_ended_subscription_anonymization();
  132. }
  133. }
  134. /**
  135. * Schedule related order anonymization events for a specific subscription.
  136. *
  137. * @since 2.2.20
  138. */
  139. public function schedule_subscription_orders_anonymization_events( $subscription_id ) {
  140. $subscription = wcs_get_subscription( $subscription_id );
  141. if ( ! $subscription ) {
  142. return;
  143. }
  144. // Reschedule the cleanup just in case something goes wrong.
  145. $this->schedule_subscription_orders_anonymization( $subscription_id );
  146. $related_orders = $subscription->get_related_orders( 'ids', array( 'parent', 'renewal', 'switch', 'resubscribe' ) );
  147. $count = 0;
  148. $limit = 20;
  149. foreach ( $related_orders as $order_id ) {
  150. // If this order already has an anonymization event scheduled, there's no need to proceed.
  151. if ( $this->order_anonymization_is_scheduled( $order_id ) ) {
  152. continue;
  153. }
  154. $order = wc_get_order( $order_id );
  155. if ( ! is_a( $order, 'WC_Abstract_Order' ) || 'yes' === $order->get_meta( '_anonymized', true ) ) {
  156. continue;
  157. }
  158. // We want to prevent orders being anonymized if there is a related subscription which hasn't been anonymized.
  159. foreach ( wcs_get_subscriptions_for_order( $order, array( 'order_type' => 'any' ) ) as $subscription ) {
  160. if ( 'yes' !== $subscription->get_meta( '_anonymized', true ) ) {
  161. continue 2;
  162. }
  163. }
  164. $this->schedule_order_anonymization( $order_id );
  165. $count++;
  166. if ( $count >= $limit ) {
  167. break;
  168. }
  169. }
  170. // If we haven't processed a full batch, we don't have any more related orders to process so there's no need to run any other batches.
  171. if ( $limit > $count ) {
  172. $this->unschedule_subscription_orders_anonymization( $subscription_id );
  173. }
  174. }
  175. /**
  176. * Anonymize an order.
  177. *
  178. * @param int The ID of the order to be anonymized.
  179. * @since 2.2.20
  180. */
  181. public function anonymize_order( $order_id ) {
  182. $order = wc_get_order( $order_id );
  183. if ( $order ) {
  184. WC_Privacy_Erasers::remove_order_personal_data( $order );
  185. }
  186. }
  187. }