2018-04-17 11:25:03 +00:00
|
|
|
|
<?php
|
|
|
|
|
/**
|
|
|
|
|
* Privacy/GDPR related functionality which ties into WordPress functionality.
|
|
|
|
|
*
|
|
|
|
|
* @since 3.4.0
|
|
|
|
|
* @package WooCommerce\Classes
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
defined( 'ABSPATH' ) || exit;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* WC_Privacy Class.
|
|
|
|
|
*/
|
2018-04-25 01:13:59 +00:00
|
|
|
|
class WC_Privacy extends WC_Abstract_Privacy {
|
2018-04-17 11:25:03 +00:00
|
|
|
|
|
2018-04-17 14:21:03 +00:00
|
|
|
|
/**
|
|
|
|
|
* Background process to clean up orders.
|
|
|
|
|
*
|
|
|
|
|
* @var WC_Privacy_Background_Process
|
|
|
|
|
*/
|
2018-04-26 10:29:51 +00:00
|
|
|
|
protected static $background_process;
|
2018-04-17 14:21:03 +00:00
|
|
|
|
|
2018-04-17 11:25:03 +00:00
|
|
|
|
/**
|
|
|
|
|
* Init - hook into events.
|
|
|
|
|
*/
|
2018-04-25 01:13:59 +00:00
|
|
|
|
public function __construct() {
|
2018-05-03 08:47:30 +00:00
|
|
|
|
parent::__construct( __( 'WooCommerce', 'woocommerce' ) );
|
2018-04-25 01:13:59 +00:00
|
|
|
|
|
2018-04-26 10:29:51 +00:00
|
|
|
|
if ( ! self::$background_process ) {
|
|
|
|
|
self::$background_process = new WC_Privacy_Background_Process();
|
|
|
|
|
}
|
2018-04-17 14:21:03 +00:00
|
|
|
|
|
2018-04-20 15:47:58 +00:00
|
|
|
|
// Include supporting classes.
|
|
|
|
|
include_once 'class-wc-privacy-erasers.php';
|
|
|
|
|
include_once 'class-wc-privacy-exporters.php';
|
2018-04-13 17:03:02 +00:00
|
|
|
|
|
|
|
|
|
// This hook registers WooCommerce data exporters.
|
2018-05-03 08:47:30 +00:00
|
|
|
|
$this->add_exporter( 'woocommerce-customer-data', __( 'Customer Data', 'woocommerce' ), array( 'WC_Privacy_Exporters', 'customer_data_exporter' ) );
|
|
|
|
|
$this->add_exporter( 'woocommerce-customer-orders', __( 'Customer Orders', 'woocommerce' ), array( 'WC_Privacy_Exporters', 'order_data_exporter' ) );
|
|
|
|
|
$this->add_exporter( 'woocommerce-customer-downloads', __( 'Customer Downloads', 'woocommerce' ), array( 'WC_Privacy_Exporters', 'download_data_exporter' ) );
|
2018-04-20 15:47:58 +00:00
|
|
|
|
|
|
|
|
|
// This hook registers WooCommerce data erasers.
|
2018-05-03 08:47:30 +00:00
|
|
|
|
$this->add_eraser( 'woocommerce-customer-data', __( 'Customer Data', 'woocommerce' ), array( 'WC_Privacy_Erasers', 'customer_data_eraser' ) );
|
|
|
|
|
$this->add_eraser( 'woocommerce-customer-orders', __( 'Customer Orders', 'woocommerce' ), array( 'WC_Privacy_Erasers', 'order_data_eraser' ) );
|
|
|
|
|
$this->add_eraser( 'woocommerce-customer-downloads', __( 'Customer Downloads', 'woocommerce' ), array( 'WC_Privacy_Erasers', 'download_data_eraser' ) );
|
2018-04-20 15:47:58 +00:00
|
|
|
|
|
|
|
|
|
// Cleanup orders daily - this is a callback on a daily cron event.
|
2018-04-30 14:38:45 +00:00
|
|
|
|
add_action( 'woocommerce_cleanup_personal_data', array( $this, 'queue_cleanup_personal_data' ) );
|
2018-04-13 17:03:02 +00:00
|
|
|
|
|
|
|
|
|
// Handles custom anonomization types not included in core.
|
2018-04-25 01:13:59 +00:00
|
|
|
|
add_filter( 'wp_privacy_anonymize_data', array( $this, 'anonymize_custom_data_types' ), 10, 3 );
|
2018-04-26 10:29:51 +00:00
|
|
|
|
|
|
|
|
|
// When this is fired, data is removed in a given order. Called from bulk actions.
|
|
|
|
|
add_action( 'woocommerce_remove_order_personal_data', array( 'WC_Privacy_Erasers', 'remove_order_personal_data' ) );
|
2018-04-20 15:47:58 +00:00
|
|
|
|
}
|
2018-04-18 16:10:41 +00:00
|
|
|
|
|
2018-04-20 15:47:58 +00:00
|
|
|
|
/**
|
|
|
|
|
* Add privacy policy content for the privacy policy page.
|
|
|
|
|
*
|
|
|
|
|
* @since 3.4.0
|
|
|
|
|
*/
|
2018-04-26 10:29:51 +00:00
|
|
|
|
public function get_privacy_message() {
|
2018-04-20 15:47:58 +00:00
|
|
|
|
$content = wp_kses_post( apply_filters( 'wc_privacy_policy_content', wpautop( __( '
|
2018-05-01 13:36:47 +00:00
|
|
|
|
We collect information about you during the checkout process on our store.
|
2018-04-20 15:47:58 +00:00
|
|
|
|
|
2018-05-01 13:36:47 +00:00
|
|
|
|
<h3>What we collect and store</h3>
|
2018-04-20 15:47:58 +00:00
|
|
|
|
|
2018-05-01 13:36:47 +00:00
|
|
|
|
While you visit our site, we’ll track:
|
2018-04-20 15:47:58 +00:00
|
|
|
|
|
2018-05-01 13:36:47 +00:00
|
|
|
|
<ul>
|
|
|
|
|
<li>Products you’ve viewed: to show you products you’ve recently viewed.</li>
|
|
|
|
|
<li>Location, IP address and browser type: to estimate taxes and shipping.</li>
|
|
|
|
|
<li>Shipping address: we’ll ask you to enter this so we can estimate shipping before you place an order.</li>
|
|
|
|
|
</ul>
|
2018-04-20 15:47:58 +00:00
|
|
|
|
|
2018-05-01 13:36:47 +00:00
|
|
|
|
We’ll also use cookies to keep track of cart contents while you’re browsing our site.
|
|
|
|
|
|
|
|
|
|
When you purchase from us, we’ll ask you to provide information including your name, billing address, shipping address, email address, phone number, credit card/payment details and optional account information like username and password. We’ll use this information to:
|
|
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
|
<li>Send you information about your account and order.</li>
|
|
|
|
|
<li>Respond to your requests, including refunds and complaints.</li>
|
|
|
|
|
<li>Process payments and prevent fraud.</li>
|
|
|
|
|
<li>Set up your account for our store.</li>
|
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
If you create an account, we will store your name, address, email and phone number, which will be used to populate the checkout for future orders.
|
|
|
|
|
|
|
|
|
|
We will store order information for XXX years for tax and accounting purposes. This includes your name, email address and billing and shipping addresses.
|
|
|
|
|
|
|
|
|
|
We will also store comments or reviews, if you chose to leave them.
|
|
|
|
|
|
|
|
|
|
<h3>Who on our team has access</h3>
|
|
|
|
|
|
|
|
|
|
Members of our team have access to the information you provide us. Both Administrators and Shop Managers can access:
|
|
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
|
<li>Order information like what was purchased, when it was purchased and where it should be sent, and</li>
|
|
|
|
|
<li>Customer information like your name, email address, and billing and shipping information.</li>
|
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
Our team members have access to this information to help fulfill orders, process refunds, and support you.
|
|
|
|
|
|
|
|
|
|
<h3>What we share with others</h3>
|
|
|
|
|
|
|
|
|
|
<h4>Payments</h4>
|
|
|
|
|
We accept payments through PayPal. When processing payments, some of your data will be passed to PayPal, including information required to process or support the payment, such as the purchase total and billing information.
|
|
|
|
|
|
|
|
|
|
Please see the <a href="https://www.paypal.com/us/webapps/mpp/ua/privacy-full">PayPal Privacy Policy</a> for more details.
|
2018-04-20 15:47:58 +00:00
|
|
|
|
', 'woocommerce' ) ) ) );
|
|
|
|
|
|
2018-04-25 01:13:59 +00:00
|
|
|
|
return $content;
|
2018-04-17 14:21:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-04-26 10:29:51 +00:00
|
|
|
|
/**
|
|
|
|
|
* Spawn events for order cleanup.
|
|
|
|
|
*/
|
2018-04-30 14:38:45 +00:00
|
|
|
|
public function queue_cleanup_personal_data() {
|
2018-04-26 10:29:51 +00:00
|
|
|
|
self::$background_process->push_to_queue( array( 'task' => 'trash_pending_orders' ) );
|
|
|
|
|
self::$background_process->push_to_queue( array( 'task' => 'trash_failed_orders' ) );
|
|
|
|
|
self::$background_process->push_to_queue( array( 'task' => 'trash_cancelled_orders' ) );
|
|
|
|
|
self::$background_process->push_to_queue( array( 'task' => 'anonymize_completed_orders' ) );
|
2018-04-30 14:38:45 +00:00
|
|
|
|
self::$background_process->push_to_queue( array( 'task' => 'delete_inactive_accounts' ) );
|
2018-04-26 10:29:51 +00:00
|
|
|
|
self::$background_process->save()->dispatch();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Handle some custom types of data and anonymize them.
|
|
|
|
|
*
|
|
|
|
|
* @param string $anonymous Anonymized string.
|
|
|
|
|
* @param string $type Type of data.
|
|
|
|
|
* @param string $data The data being anonymized.
|
|
|
|
|
* @return string Anonymized string.
|
|
|
|
|
*/
|
|
|
|
|
public function anonymize_custom_data_types( $anonymous, $type, $data ) {
|
|
|
|
|
switch ( $type ) {
|
|
|
|
|
case 'address_state':
|
|
|
|
|
case 'address_country':
|
|
|
|
|
$anonymous = ''; // Empty string - we don't want to store anything after removal.
|
|
|
|
|
break;
|
|
|
|
|
case 'phone':
|
|
|
|
|
$anonymous = preg_replace( '/\d/u', '0', $data );
|
|
|
|
|
break;
|
2018-04-26 12:15:14 +00:00
|
|
|
|
case 'numeric_id':
|
|
|
|
|
$anonymous = 0;
|
|
|
|
|
break;
|
2018-04-26 10:29:51 +00:00
|
|
|
|
}
|
|
|
|
|
return $anonymous;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-17 14:21:03 +00:00
|
|
|
|
/**
|
|
|
|
|
* Find and trash old orders.
|
|
|
|
|
*
|
|
|
|
|
* @since 3.4.0
|
|
|
|
|
* @param int $limit Limit orders to process per batch.
|
|
|
|
|
* @return int Number of orders processed.
|
|
|
|
|
*/
|
2018-04-26 10:29:51 +00:00
|
|
|
|
public static function trash_pending_orders( $limit = 20 ) {
|
2018-04-18 10:24:07 +00:00
|
|
|
|
$option = wc_parse_relative_date_option( get_option( 'woocommerce_trash_pending_orders' ) );
|
2018-04-17 14:21:03 +00:00
|
|
|
|
|
2018-04-17 14:33:40 +00:00
|
|
|
|
if ( empty( $option['number'] ) ) {
|
2018-04-17 14:21:03 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-26 10:29:51 +00:00
|
|
|
|
return self::trash_orders_query( array(
|
2018-04-17 14:33:40 +00:00
|
|
|
|
'date_created' => '<' . strtotime( '-' . $option['number'] . ' ' . $option['unit'] ),
|
2018-04-17 14:21:03 +00:00
|
|
|
|
'limit' => $limit, // Batches of 20.
|
|
|
|
|
'status' => 'wc-pending',
|
|
|
|
|
) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Find and trash old orders.
|
|
|
|
|
*
|
|
|
|
|
* @since 3.4.0
|
|
|
|
|
* @param int $limit Limit orders to process per batch.
|
|
|
|
|
* @return int Number of orders processed.
|
|
|
|
|
*/
|
2018-04-26 10:29:51 +00:00
|
|
|
|
public static function trash_failed_orders( $limit = 20 ) {
|
2018-04-18 10:24:07 +00:00
|
|
|
|
$option = wc_parse_relative_date_option( get_option( 'woocommerce_trash_failed_orders' ) );
|
2018-04-17 14:21:03 +00:00
|
|
|
|
|
2018-04-17 14:33:40 +00:00
|
|
|
|
if ( empty( $option['number'] ) ) {
|
2018-04-17 14:21:03 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-26 10:29:51 +00:00
|
|
|
|
return self::trash_orders_query( array(
|
2018-04-17 14:33:40 +00:00
|
|
|
|
'date_created' => '<' . strtotime( '-' . $option['number'] . ' ' . $option['unit'] ),
|
2018-04-17 14:21:03 +00:00
|
|
|
|
'limit' => $limit, // Batches of 20.
|
|
|
|
|
'status' => 'wc-failed',
|
|
|
|
|
) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Find and trash old orders.
|
|
|
|
|
*
|
|
|
|
|
* @since 3.4.0
|
|
|
|
|
* @param int $limit Limit orders to process per batch.
|
|
|
|
|
* @return int Number of orders processed.
|
|
|
|
|
*/
|
2018-04-26 10:29:51 +00:00
|
|
|
|
public static function trash_cancelled_orders( $limit = 20 ) {
|
2018-04-18 10:24:07 +00:00
|
|
|
|
$option = wc_parse_relative_date_option( get_option( 'woocommerce_trash_cancelled_orders' ) );
|
2018-04-17 14:21:03 +00:00
|
|
|
|
|
2018-04-17 14:33:40 +00:00
|
|
|
|
if ( empty( $option['number'] ) ) {
|
2018-04-17 14:21:03 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-26 10:29:51 +00:00
|
|
|
|
return self::trash_orders_query( array(
|
2018-04-17 14:33:40 +00:00
|
|
|
|
'date_created' => '<' . strtotime( '-' . $option['number'] . ' ' . $option['unit'] ),
|
2018-04-17 14:21:03 +00:00
|
|
|
|
'limit' => $limit, // Batches of 20.
|
|
|
|
|
'status' => 'wc-cancelled',
|
|
|
|
|
) );
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-30 14:38:45 +00:00
|
|
|
|
/**
|
|
|
|
|
* For a given query trash all matches.
|
|
|
|
|
*
|
|
|
|
|
* @since 3.4.0
|
|
|
|
|
* @param array $query Query array to pass to wc_get_orders().
|
|
|
|
|
* @return int Count of orders that were trashed.
|
|
|
|
|
*/
|
|
|
|
|
protected static function trash_orders_query( $query ) {
|
|
|
|
|
$orders = wc_get_orders( $query );
|
|
|
|
|
$count = 0;
|
|
|
|
|
|
|
|
|
|
if ( $orders ) {
|
|
|
|
|
foreach ( $orders as $order ) {
|
|
|
|
|
$order->delete( false );
|
|
|
|
|
$count ++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $count;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-17 14:21:03 +00:00
|
|
|
|
/**
|
2018-04-24 15:47:55 +00:00
|
|
|
|
* Anonymize old completed orders.
|
2018-04-17 14:21:03 +00:00
|
|
|
|
*
|
|
|
|
|
* @since 3.4.0
|
|
|
|
|
* @param int $limit Limit orders to process per batch.
|
|
|
|
|
* @return int Number of orders processed.
|
|
|
|
|
*/
|
2018-04-30 14:38:45 +00:00
|
|
|
|
public static function anonymize_completed_orders( $limit = 20 ) {
|
2018-04-17 14:21:03 +00:00
|
|
|
|
$option = wc_parse_relative_date_option( get_option( 'woocommerce_anonymize_completed_orders' ) );
|
|
|
|
|
|
2018-04-17 14:33:40 +00:00
|
|
|
|
if ( empty( $option['number'] ) ) {
|
2018-04-17 14:21:03 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2018-04-17 11:25:03 +00:00
|
|
|
|
|
2018-04-26 10:29:51 +00:00
|
|
|
|
return self::anonymize_orders_query( array(
|
2018-04-17 14:33:40 +00:00
|
|
|
|
'date_created' => '<' . strtotime( '-' . $option['number'] . ' ' . $option['unit'] ),
|
2018-04-17 14:21:03 +00:00
|
|
|
|
'limit' => $limit, // Batches of 20.
|
|
|
|
|
'status' => 'wc-completed',
|
|
|
|
|
'anonymized' => false,
|
|
|
|
|
) );
|
2018-04-17 11:25:03 +00:00
|
|
|
|
}
|
2018-04-30 14:38:45 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* For a given query, anonymize all matches.
|
|
|
|
|
*
|
|
|
|
|
* @since 3.4.0
|
|
|
|
|
* @param array $query Query array to pass to wc_get_orders().
|
|
|
|
|
* @return int Count of orders that were anonymized.
|
|
|
|
|
*/
|
|
|
|
|
protected static function anonymize_orders_query( $query ) {
|
|
|
|
|
$orders = wc_get_orders( $query );
|
|
|
|
|
$count = 0;
|
|
|
|
|
|
|
|
|
|
if ( $orders ) {
|
|
|
|
|
foreach ( $orders as $order ) {
|
|
|
|
|
WC_Privacy_Erasers::remove_order_personal_data( $order );
|
|
|
|
|
$count ++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Delete inactive accounts.
|
|
|
|
|
*
|
|
|
|
|
* @since 3.4.0
|
|
|
|
|
* @param int $limit Limit users to process per batch.
|
|
|
|
|
* @return int Number of users processed.
|
|
|
|
|
*/
|
|
|
|
|
public static function delete_inactive_accounts( $limit = 20 ) {
|
|
|
|
|
$option = wc_parse_relative_date_option( get_option( 'woocommerce_delete_inactive_accounts' ) );
|
|
|
|
|
|
|
|
|
|
if ( empty( $option['number'] ) ) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return self::delete_inactive_accounts_query( strtotime( '-' . $option['number'] . ' ' . $option['unit'] ), $limit );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Delete inactive accounts.
|
|
|
|
|
*
|
|
|
|
|
* @since 3.4.0
|
|
|
|
|
* @param int $timestamp Timestamp to delete customers before.
|
|
|
|
|
* @param int $limit Limit number of users to delete per run.
|
|
|
|
|
* @return int Count of customers that were deleted.
|
|
|
|
|
*/
|
|
|
|
|
protected static function delete_inactive_accounts_query( $timestamp, $limit = 20 ) {
|
|
|
|
|
$count = 0;
|
|
|
|
|
$user_query = new WP_User_Query( array(
|
|
|
|
|
'fields' => 'ID',
|
|
|
|
|
'number' => $limit,
|
|
|
|
|
'role__in' => apply_filters( 'woocommerce_delete_inactive_account_roles', array(
|
|
|
|
|
'Customer',
|
|
|
|
|
'Subscriber',
|
|
|
|
|
) ),
|
|
|
|
|
'meta_query' => array(
|
|
|
|
|
'relation' => 'AND',
|
|
|
|
|
array(
|
|
|
|
|
'key' => 'wc_last_active',
|
|
|
|
|
'value' => (string) $timestamp,
|
|
|
|
|
'compare' => '<',
|
|
|
|
|
'type' => 'NUMERIC',
|
|
|
|
|
),
|
|
|
|
|
array(
|
|
|
|
|
'key' => 'wc_last_active',
|
|
|
|
|
'value' => '0',
|
|
|
|
|
'compare' => '>',
|
|
|
|
|
'type' => 'NUMERIC',
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
) );
|
|
|
|
|
|
|
|
|
|
$user_ids = $user_query->get_results();
|
|
|
|
|
|
|
|
|
|
if ( $user_ids ) {
|
|
|
|
|
foreach ( $user_ids as $user_id ) {
|
|
|
|
|
wp_delete_user( $user_id );
|
|
|
|
|
$count ++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $count;
|
|
|
|
|
}
|
2018-04-17 11:25:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-04-25 01:13:59 +00:00
|
|
|
|
new WC_Privacy();
|