diff --git a/plugins/woocommerce/includes/class-wc-install.php b/plugins/woocommerce/includes/class-wc-install.php index cfee24b3945..08478886a11 100644 --- a/plugins/woocommerce/includes/class-wc-install.php +++ b/plugins/woocommerce/includes/class-wc-install.php @@ -229,6 +229,9 @@ class WC_Install { 'wc_update_750_add_columns_to_order_stats_table', 'wc_update_750_disable_new_product_management_experience', ), + '7.7.0' => array( + 'wc_update_770_delete_stray_order_records' + ) ); /** diff --git a/plugins/woocommerce/includes/wc-update-functions.php b/plugins/woocommerce/includes/wc-update-functions.php index 0fe137d07a1..6c881e9f4bf 100644 --- a/plugins/woocommerce/includes/wc-update-functions.php +++ b/plugins/woocommerce/includes/wc-update-functions.php @@ -21,6 +21,7 @@ defined( 'ABSPATH' ) || exit; use Automattic\WooCommerce\Database\Migrations\MigrationHelper; use Automattic\WooCommerce\Internal\Admin\Marketing\MarketingSpecs; use Automattic\WooCommerce\Internal\AssignDefaultCategory; +use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore; use Automattic\WooCommerce\Internal\ProductAttributesLookup\DataRegenerator; use Automattic\WooCommerce\Internal\ProductAttributesLookup\LookupDataStore; use Automattic\WooCommerce\Internal\ProductDownloads\ApprovedDirectories\Register as Download_Directories; @@ -2594,3 +2595,46 @@ function wc_update_750_disable_new_product_management_experience() { update_option( 'woocommerce_new_product_management_enabled', 'no' ); } } + +/** + * Delete stray order records in both posts table and the orders table: + * + * - Posts of type "shop_order_placeholder" with no matching order in the orders table. + * - Records of type "shop_order_refund" with a zero parent order id in both tables. + * + * @return void + */ +function wc_update_770_delete_stray_order_records() { + global $wpdb; + + $orders_table_name = OrdersTableDataStore::get_orders_table_name(); + + // phpcs:disable WordPress.DB.PreparedSQL + + if ( ! $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $orders_table_name ) ) ) ) { + return; + }; + + $wpdb->query( + $wpdb->prepare( + "DELETE FROM {$wpdb->posts} WHERE post_type = %s AND ID NOT IN (SELECT id FROM $orders_table_name)", + 'shop_order_placehold' + ) + ); + + $wpdb->query( + $wpdb->prepare( + "DELETE FROM {$wpdb->posts} WHERE post_type = %s AND post_parent = 0", + 'shop_order_refund' + ) + ); + + $wpdb->query( + $wpdb->prepare( + "DELETE FROM {$orders_table_name} WHERE type = %s AND (parent_order_id = 0 OR parent_order_id is null)", + 'shop_order_refund' + ) + ); + + // phpcs:enable WordPress.DB.PreparedSQL +}