From d657613888faa409942c3d5f882d152122089396 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Thu, 9 Jan 2020 09:07:16 -0400 Subject: [PATCH] add privacy erasure via woocommerce hook (https://github.com/woocommerce/woocommerce-admin/pull/3511) * add privacy erasure via woocommerce hook Co-Authored-By: Joshua T Flowers --- .../src/Schedulers/CustomersScheduler.php | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/plugins/woocommerce-admin/src/Schedulers/CustomersScheduler.php b/plugins/woocommerce-admin/src/Schedulers/CustomersScheduler.php index ab7125de505..a7bab832e01 100644 --- a/plugins/woocommerce-admin/src/Schedulers/CustomersScheduler.php +++ b/plugins/woocommerce-admin/src/Schedulers/CustomersScheduler.php @@ -9,6 +9,7 @@ namespace Automattic\WooCommerce\Admin\Schedulers; defined( 'ABSPATH' ) || exit; +use \Automattic\WooCommerce\Admin\API\Reports\Cache as ReportsCache; use \Automattic\WooCommerce\Admin\API\Reports\Customers\DataStore as CustomersDataStore; use \Automattic\WooCommerce\Admin\Schedulers\OrdersScheduler; @@ -29,6 +30,7 @@ class CustomersScheduler extends ImportScheduler { public static function init() { add_action( 'woocommerce_new_customer', array( __CLASS__, 'schedule_import' ) ); add_action( 'woocommerce_update_customer', array( __CLASS__, 'schedule_import' ) ); + add_action( 'woocommerce_privacy_remove_order_personal_data', array( __CLASS__, 'schedule_anonymize' ) ); CustomersDataStore::init(); parent::init(); @@ -42,6 +44,7 @@ class CustomersScheduler extends ImportScheduler { public static function get_dependencies() { return array( 'delete_batch_init' => OrdersScheduler::get_action( 'delete_batch_init' ), + 'anonymize' => self::get_action( 'import' ), ); } @@ -110,6 +113,18 @@ class CustomersScheduler extends ImportScheduler { return $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}wc_customer_lookup" ); } + /** + * Get all available scheduling actions. + * Used to determine action hook names and clear events. + * + * @return array + */ + public static function get_scheduler_actions() { + $actions = parent::get_scheduler_actions(); + $actions['anonymize'] = 'wc-admin_anonymize_' . static::$name; + return $actions; + } + /** * Schedule import. * @@ -120,6 +135,19 @@ class CustomersScheduler extends ImportScheduler { self::schedule_action( 'import', array( $user_id ) ); } + /** + * Schedule an action to anonymize a single Order. + * + * @param WC_Order $order Order object. + * @return void + */ + public static function schedule_anonymize( $order ) { + if ( is_a( $order, 'WC_Order' ) ) { + // Postpone until any pending updates are completed. + self::schedule_action( 'anonymize', array( $order->get_id() ) ); + } + } + /** * Imports a single customer. * @@ -150,4 +178,56 @@ class CustomersScheduler extends ImportScheduler { CustomersDataStore::delete_customer( $customer_id ); } } + + /** + * Anonymize the customer data for a single order. + * + * @param int $order_id Order id. + * @return void + */ + public static function anonymize( $order_id ) { + global $wpdb; + + $customer_id = $wpdb->get_var( + $wpdb->prepare( "SELECT customer_id FROM {$wpdb->prefix}wc_order_stats WHERE order_id = %d", $order_id ) + ); + + if ( ! $customer_id ) { + return; + } + + // Long form query because $wpdb->update rejects [deleted]. + $deleted_text = __( '[deleted]', 'woocommerce-admin' ); + $updated = $wpdb->query( + $wpdb->prepare( + "UPDATE {$wpdb->prefix}wc_customer_lookup + SET + user_id = NULL, + username = %s, + first_name = %s, + last_name = %s, + email = %s, + country = '', + postcode = %s, + city = %s, + state = %s + WHERE + customer_id = %d", + array( + $deleted_text, + $deleted_text, + $deleted_text, + 'deleted@site.invalid', + $deleted_text, + $deleted_text, + $deleted_text, + $customer_id, + ) + ) + ); + // If the customer row was anonymized, flush the cache. + if ( $updated ) { + ReportsCache::invalidate(); + } + } }