From 2ba063f64a314172b27a6b1a20f342a2f2c21b65 Mon Sep 17 00:00:00 2001 From: Adam Cassis Date: Wed, 10 Apr 2024 10:31:55 +0200 Subject: [PATCH 1/4] feat: handle user deletion event on the network --- includes/class-accepted-actions.php | 2 + includes/class-data-listeners.php | 21 ++++++ .../incoming-events/class-user-deleted.php | 74 +++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 includes/incoming-events/class-user-deleted.php diff --git a/includes/class-accepted-actions.php b/includes/class-accepted-actions.php index bf4071d8..3457883a 100644 --- a/includes/class-accepted-actions.php +++ b/includes/class-accepted-actions.php @@ -35,6 +35,7 @@ class Accepted_Actions { 'donation_new' => 'Donation_New', 'donation_subscription_cancelled' => 'Donation_Subscription_Cancelled', 'network_user_updated' => 'User_Updated', + 'network_user_deleted' => 'User_Deleted', 'newspack_network_woo_membership_updated' => 'Woocommerce_Membership_Updated', 'network_manual_sync_user' => 'User_Manually_Synced', 'network_nodes_synced' => 'Nodes_Synced', @@ -53,6 +54,7 @@ class Accepted_Actions { 'donation_new', 'donation_subscription_cancelled', 'network_user_updated', + 'network_user_deleted', 'newspack_network_woo_membership_updated', 'network_manual_sync_user', 'network_nodes_synced', diff --git a/includes/class-data-listeners.php b/includes/class-data-listeners.php index 6468c612..64cb0b86 100644 --- a/includes/class-data-listeners.php +++ b/includes/class-data-listeners.php @@ -36,6 +36,7 @@ public static function register_listeners() { Data_Events::register_listener( 'woocommerce_subscription_status_changed', 'newspack_node_subscription_changed', [ __CLASS__, 'item_changed' ] ); Data_Events::register_listener( 'woocommerce_order_status_changed', 'newspack_node_order_changed', [ __CLASS__, 'item_changed' ] ); Data_Events::register_listener( 'newspack_network_user_updated', 'network_user_updated', [ __CLASS__, 'user_updated' ] ); + Data_Events::register_listener( 'delete_user', 'network_user_deleted', [ __CLASS__, 'user_deleted' ] ); Data_Events::register_listener( 'newspack_network_nodes_synced', 'network_nodes_synced', [ __CLASS__, 'nodes_synced' ] ); } @@ -87,6 +88,26 @@ public static function user_updated( $user_data ) { return $user_data; } + /** + * Filters the user data for the event being triggered + * + * @param int $id ID of the user to delete. + * @param int|null $reassign ID of the user to reassign posts and links to. + * Default null, for no reassignment. + * @param WP_User $user WP_User object of the user to delete. + * @return array + */ + public static function user_deleted( $id, $reassign, $user ) { + $should_delete = apply_filters( 'newspack_network_process_user_deleted', true, $user->user_email ); + if ( ! $should_delete ) { + Debugger::log( 'User deletion with email: ' . $user->user_email . ' was skipped due to filter use.' ); + return; + } + return [ + 'email' => $user->user_email, + ]; + } + /** * Filters the nodes data for the event being triggered * diff --git a/includes/incoming-events/class-user-deleted.php b/includes/incoming-events/class-user-deleted.php new file mode 100644 index 00000000..b5005807 --- /dev/null +++ b/includes/incoming-events/class-user-deleted.php @@ -0,0 +1,74 @@ +process_user_deleted(); + } + + /** + * Process event in Node + * + * @return void + */ + public function process_in_node() { + $this->process_user_deleted(); + } + + /** + * Process user deleted + * + * @return void + */ + public function process_user_deleted() { + $email = $this->get_email(); + Debugger::log( 'Processing user deletion with email: ' . $email ); + if ( ! $email ) { + return; + } + $user = get_user_by( 'email', $email ); + if ( ! $user ) { + Debugger::log( sprintf( 'User to be deleted not found by email: %s, skipping.', $email ) ); + return; + } + + // Ensure this is a network reader. + $userdata = get_userdata( $user->ID ); + if ( [ NEWSPACK_NETWORK_READER_ROLE ] !== $userdata->roles ) { + Debugger::log( sprintf( 'User %s is not only or not a network reader, skipping deletion.', $email ) ); + return; + } + + /** Make sure `wp_delete_user()` is available. */ + require_once ABSPATH . 'wp-admin/includes/user.php'; + + // Don't broadcast this deletion on the network. + add_filter( 'newspack_network_process_user_deleted', '__return_false' ); + // Delete the user. + $result = \wp_delete_user( $user->ID ); + remove_filter( 'newspack_network_process_user_deleted', '__return_false' ); + + if ( $result ) { + Debugger::log( sprintf( 'User %s deleted.', $email ) ); + } else { + Debugger::log( sprintf( 'User %s could not be deleted.', $email ) ); + } + } +} From 1d6ff1c63fa324c6ac1788ca75a7cee2a48e78ae Mon Sep 17 00:00:00 2001 From: Adam Cassis Date: Thu, 25 Apr 2024 10:04:33 +0200 Subject: [PATCH 2/4] fix: prevent user deletion from triggering user update events --- includes/class-data-listeners.php | 2 ++ includes/incoming-events/class-user-deleted.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/includes/class-data-listeners.php b/includes/class-data-listeners.php index 64cb0b86..e4d31079 100644 --- a/includes/class-data-listeners.php +++ b/includes/class-data-listeners.php @@ -103,6 +103,8 @@ public static function user_deleted( $id, $reassign, $user ) { Debugger::log( 'User deletion with email: ' . $user->user_email . ' was skipped due to filter use.' ); return; } + // Prevent deletion-related changes triggering a 'network_user_updated' event. + User_Update_Watcher::$enabled = false; return [ 'email' => $user->user_email, ]; diff --git a/includes/incoming-events/class-user-deleted.php b/includes/incoming-events/class-user-deleted.php index b5005807..974d692e 100644 --- a/includes/incoming-events/class-user-deleted.php +++ b/includes/incoming-events/class-user-deleted.php @@ -61,6 +61,8 @@ public function process_user_deleted() { // Don't broadcast this deletion on the network. add_filter( 'newspack_network_process_user_deleted', '__return_false' ); + // Prevent deletion-related changes triggering a 'network_user_updated' event. + \Newspack_Network\User_Update_Watcher::$enabled = false; // Delete the user. $result = \wp_delete_user( $user->ID ); remove_filter( 'newspack_network_process_user_deleted', '__return_false' ); From 998b4fd53075b638c4312f291943ef24371ea0c3 Mon Sep 17 00:00:00 2001 From: Adam Cassis Date: Thu, 25 Apr 2024 10:10:42 +0200 Subject: [PATCH 3/4] fix: handle deletion of any reader --- includes/incoming-events/class-user-deleted.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/includes/incoming-events/class-user-deleted.php b/includes/incoming-events/class-user-deleted.php index 974d692e..91fdf224 100644 --- a/includes/incoming-events/class-user-deleted.php +++ b/includes/incoming-events/class-user-deleted.php @@ -49,10 +49,9 @@ public function process_user_deleted() { return; } - // Ensure this is a network reader. - $userdata = get_userdata( $user->ID ); - if ( [ NEWSPACK_NETWORK_READER_ROLE ] !== $userdata->roles ) { - Debugger::log( sprintf( 'User %s is not only or not a network reader, skipping deletion.', $email ) ); + // Ensure this is a reader. + if (!\Newspack\Reader_Activation::is_user_reader( $user )) { + Debugger::log( sprintf( 'User %s is not a reader, skipping deletion.', $email ) ); return; } From cf74f84cf02ef05ebfbaa0b6a659d44cbb2f8493 Mon Sep 17 00:00:00 2001 From: Adam Cassis Date: Thu, 25 Apr 2024 10:12:52 +0200 Subject: [PATCH 4/4] chore: lint --- includes/incoming-events/class-user-deleted.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/incoming-events/class-user-deleted.php b/includes/incoming-events/class-user-deleted.php index 91fdf224..64de6a12 100644 --- a/includes/incoming-events/class-user-deleted.php +++ b/includes/incoming-events/class-user-deleted.php @@ -50,7 +50,7 @@ public function process_user_deleted() { } // Ensure this is a reader. - if (!\Newspack\Reader_Activation::is_user_reader( $user )) { + if ( ! \Newspack\Reader_Activation::is_user_reader( $user ) ) { Debugger::log( sprintf( 'User %s is not a reader, skipping deletion.', $email ) ); return; }