Skip to content

Instantly share code, notes, and snippets.

@devinsays
Created January 13, 2024 19:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devinsays/73a5755fdeea252ba0a6b01573b50ea8 to your computer and use it in GitHub Desktop.
Save devinsays/73a5755fdeea252ba0a6b01573b50ea8 to your computer and use it in GitHub Desktop.
Deletes users with customer role in WooCommerce that do not have orders.
<?php
/**
* Deletes customers without orders
*
* To run the script:
* wp eval-file delete-customers-without-orders.php
*/
// Query for customers registered since this date.
$date_after = '2000-01-01';
// Don't delete accounts that have been created in the last 30 days.
$timeframe = strtotime( '-30 seconds', time() );
$date_before = date( 'Y-m-d', $timeframe );
WP_CLI::log( "Finding all users registered between {$date_after} and {$date_before}." );
WP_CLI::log( ' ' );
$customer_ids = find_customer_ids_registered( $date_after, $date_before );
WP_CLI::success( 'Found ' . count( $customer_ids ) . ' customer accounts to verify.' );
WP_CLI::log( '' );
foreach ( $customer_ids as $customer_id ) {
$user = get_user_by( 'id', $customer_id );
$role_eligble_for_deletion = user_role_eligible_for_delete( $user );
if ( ! $role_eligble_for_deletion ) {
WP_CLI::log( "Customer ID: {$customer_id} has a role that is not eligible for deletion." );
continue;
}
$user_has_posts = customer_has_posts( $customer_id );
if ( $user_has_posts ) {
WP_CLI::log( "Customer ID: {$customer_id} has posts." );
continue;
}
$user_has_order_postmeta = user_has_order_postmeta( $customer_id );
if ( $user_has_order_postmeta ) {
WP_CLI::log( "Customer ID: {$customer_id} has order postmeta." );
continue;
}
if ( wpcli_is_hpos_enabled() ) {
$user_has_order_meta = user_has_orders_meta( $customer_id );
if ( $user_has_order_meta ) {
WP_CLI::log( "Customer ID: {$customer_id} has order meta." );
continue;
}
}
// Any other checks you need to do?
// Need to check for reviews or comments?
WP_CLI::log( "Deleting customer: {$customer_id}" );
delete_customer( $customer_id );
WP_CLI::success( "Customer deleted: {$customer_id}" );
}
/**
* Return Customer IDs registered before a date and from a date.
*
* @param string $date_after Find after this date (including the date).
* @param string $date_before Find before this date (including the date).
*
* @return array|object|\stdClass[]|null
*/
function find_customer_ids_registered( string $date_after = '', string $date_before = '' ) {
global $wpdb;
$query = "SELECT DISTINCT users.ID FROM {$wpdb->users} users
WHERE users.user_registered <= %s
";
$datetime = strtotime( $date_before );
$date_before = date( 'Y-m-d 23:59:59', $datetime );
$prepared_arguments = [ $date_before ];
if ( $date_after ) {
$datetime_after = strtotime( $date_after );
$date_after = date( 'Y-m-d 23:59:59', $datetime_after );
$query .= ' AND users.user_registered >= %s';
$prepared_arguments[] = $date_after;
}
$query = $wpdb->prepare(
$query,
$prepared_arguments
);
return $wpdb->get_col( $query );
}
/**
* Check if customer has a role.
*
* @param object $user
* @return bool
*/
function user_role_eligible_for_delete( $user ) {
$can_delete = true;
// Customer does not have any roles set, so we can delete.
if ( ! $user->roles ) {
return true;
}
// This covers the case where customer may have multiple roles.
// If any of the roles is not subscriber or customer, we cannot delete.
foreach ( $user->roles as $role ) {
if ( ! in_array( $role, [ 'subscriber', 'customer' ], true ) ) {
$can_delete = false;
}
}
return $can_delete;
}
/**
* Check if user has posts.
*
* @return bool
*/
function customer_has_posts( $user_id ) {
global $wpdb;
$posts = $wpdb->get_col( "SELECT ID FROM {$wpdb->posts} WHERE post_author = $user_id LIMIT 1" );
if ( $posts ) {
return true;
}
return false;
}
/**
* User has a postmeta key assigned for _customer_user.
*
* @param int $user_id
* @return bool
*/
function user_has_order_postmeta( $user_id ) {
global $wpdb;
$meta = $wpdb->get_col( "SELECT ID FROM {$wpdb->postmeta} WHERE meta_key = '_customer_user' AND meta_value = $user_id LIMIT 1" );
if ( $meta ) {
return true;
}
return false;
}
/**
* User has a ordermeta key assigned for _customer_user.
*
* @param int $user_id
* @return bool
*/
function user_has_orders_meta( $user_id ) {
global $wpdb;
$meta = $wpdb->get_col( "SELECT ID FROM {$wpdb->orders_meta} WHERE meta_key = '_customer_user' AND meta_value = $user_id LIMIT 1" );
if ( $meta ) {
return true;
}
return false;
}
/**
* Checks if HPOS is enabled.
*
* @return bool
*/
function wpcli_is_hpos_enabled() {
return class_exists( OrderUtil::class ) && OrderUtil::custom_orders_table_usage_is_enabled();
}
/**
* Does a direct SQL query to delete the customer.
* This is much faster than wp_delete_user().
*
* @param integer $customer_id Customer ID.
*/
function delete_customer( $customer_id ) {
global $wpdb;
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}usermeta WHERE user_id = %d", $customer_id ) );
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}users WHERE ID = %d", $customer_id ) );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment