Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Deleted WooCommerce orders, subscriptions, and customers based on the IP address used to order.
<?php
/**
* This script will delete all `on-hold` subscriptions and their orders and users.
* It will delete all subscriptions based on IP.
*
* wp eval-file delete-fraud-activity-by-ip.php 127.0.0.1
*
* Dry run:
* wp eval-file delete-fraud-activity-by-ip 127.0.0.1 dry
*
*/
if ( ! isset( $args[0] ) ) {
WP_CLI::error( 'Please enter user IP.' );
die();
}
$ip = trim( $args[0] );
$filename = str_replace( '.', '', $ip ) . '-output.txt';
$dry_run = isset( $args[1] ) && 'dry' === $args[1];
$resources['orders'] = 0;
$resources['subscriptions'] = 0;
$resources['users'] = 0;
global $wpdb;
$sql = "SELECT post_id FROM {$wpdb->prefix}postmeta WHERE meta_id > 180000000 AND meta_key = '_customer_ip_address' AND meta_value = '{$ip}'";
$user_order_ids = $wpdb->get_results( $sql, ARRAY_A );
$total = count( $user_order_ids );
WP_CLI::log( "Found {$total} meta keys with matching IP {$ip}" );
foreach ( $user_order_ids as $user_order_id ) {
$order = wc_get_order( $user_order_id['post_id'] );
if ( ! $order ) {
continue;
}
// Meta query will also pull subscriptions, so we'll skip those.
if ( 'shop_order' !== $order->order_type ) {
continue;
}
// Only delete orders that have status failed or cancelled.
if ( ! $order->has_status( array( 'failed', 'cancelled' ) ) ) {
WP_CLI::log( "Order {$user_order_id['post_id']} not in status failed or cancelled. Skipping." );
continue;
}
if ( $order->get_date_created()->getTimestamp() < strtotime( '-30 days' ) ) {
WP_CLI::log( "Order {$order->get_id()} was created more than 30 days ago. Skipping." );
continue;
}
$user_id = $order->get_customer_id();
$name = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
$email = $order->get_billing_email();
$subscriptions = wcs_get_subscriptions_for_order( $order );
if ( $subscriptions ) {
$subscription = reset( $subscriptions );
$subscription_id = $subscription->get_id();
} else {
$subscription_id = 'null';
}
WP_CLI::log( '' );
WP_CLI::log( "Processing order: {$order->get_id()}" );
WP_CLI::log( "Customer: $name" );
WP_CLI::log( "Email: $email " );
WP_CLI::log( "Subscription: $subscription_id" );
WP_CLI::log( '' );
log_output(
[
'user_id' => $user_id,
'name' => $name,
'email' => $email,
'order_id' => $order->get_id(),
'subscription_id' => $subscription_id
],
$filename
);
if ( ! $dry_run && $subscription ) {
$subscription->remove_order_items();
wp_delete_post( $subscription->get_id(), true );
}
if ( $subscription ) {
$resources['subscriptions']++;
WP_CLI::success( "Deleted subscription: {$subscription->get_id()}." );
}
if ( ! $dry_run ) {
$order->remove_order_items();
wp_delete_post( $order->get_id(), true );
}
$resources['orders']++;
WP_CLI::success( "Deleted order: {$order->get_id()}." );
if ( ! $dry_run ) {
wpcli_delete_user( $user_id );
$resources['users']++;
}
WP_CLI::success( "Deleted user: $user_id with email $email." );
}
WP_CLI::log( '' );
WP_CLI::success( 'Finished!' );
WP_CLI::log( '' );
WP_CLI::log( "Orders deleted: {$resources['orders']}" );
WP_CLI::log( "Subscriptions deleted: {$resources['subscriptions']}" );
WP_CLI::log( "Users deleted: {$resources['users']}" );
WP_CLI::log( '' );
function log_output( $data, $filename ) {
$file = fopen( $filename, 'a' );
fputcsv( $file, $data );
fclose( $file );
}
/**
* Deletes a user.
* More efficient than wp_delete_user.
*
* @return void
*/
function wpcli_delete_user( $id ) {
global $wpdb;
// Deletes all user meta data.
$wpdb->query( "DELETE FROM $wpdb->usermeta WHERE user_id = $id" );
// Deletes user.
$wpdb->query( "DELETE FROM $wpdb->users WHERE ID = $id" );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment