Commit d2118dd2ab7 for woocommerce

commit d2118dd2ab79c77176d534660107f2323cd7b496
Author: Darren Ethier <darren@roughsmootheng.in>
Date:   Sun Aug 23 09:46:39 2026 -0400

    Prepare the order-item deletion query explicitly (#67932)

diff --git a/plugins/woocommerce/changelog/prepare-order-item-deletion-query b/plugins/woocommerce/changelog/prepare-order-item-deletion-query
new file mode 100644
index 00000000000..e74f7d0e90a
--- /dev/null
+++ b/plugins/woocommerce/changelog/prepare-order-item-deletion-query
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Prepare order-item deletion queries with an integer placeholder.
diff --git a/plugins/woocommerce/includes/class-wc-post-data.php b/plugins/woocommerce/includes/class-wc-post-data.php
index 1aa4c691cb8..9d5e0cc0a66 100644
--- a/plugins/woocommerce/includes/class-wc-post-data.php
+++ b/plugins/woocommerce/includes/class-wc-post-data.php
@@ -608,13 +608,16 @@ class WC_Post_Data {
 			do_action( 'woocommerce_delete_order_items', $postid );

 			$wpdb->query(
-				"
+				$wpdb->prepare(
+					"
 				DELETE {$wpdb->prefix}woocommerce_order_items, {$wpdb->prefix}woocommerce_order_itemmeta
 				FROM {$wpdb->prefix}woocommerce_order_items
 				JOIN {$wpdb->prefix}woocommerce_order_itemmeta ON {$wpdb->prefix}woocommerce_order_items.order_item_id = {$wpdb->prefix}woocommerce_order_itemmeta.order_item_id
-				WHERE {$wpdb->prefix}woocommerce_order_items.order_id = '{$postid}';
-				"
-			); // WPCS: unprepared SQL ok.
+				WHERE {$wpdb->prefix}woocommerce_order_items.order_id = %d;
+					",
+					$postid
+				)
+			);

 			do_action( 'woocommerce_deleted_order_items', $postid );
 		}
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-post-data-test.php b/plugins/woocommerce/tests/php/includes/class-wc-post-data-test.php
index 1c9ba3227b7..24e522b1f56 100644
--- a/plugins/woocommerce/tests/php/includes/class-wc-post-data-test.php
+++ b/plugins/woocommerce/tests/php/includes/class-wc-post-data-test.php
@@ -5,11 +5,34 @@
  * @package WooCommerce\Tests\Post_Data.
  */

+use Automattic\WooCommerce\RestApi\UnitTests\HPOSToggleTrait;
+use Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper;
+use Automattic\WooCommerce\Utilities\OrderUtil;
+
 /**
  * Class WC_Post_Data_Test
  */
 class WC_Post_Data_Test extends \WC_Unit_Test_Case {

+	use HPOSToggleTrait;
+
+	/**
+	 * Ensure the HPOS tables exist before per-test transactions start.
+	 */
+	public static function wpSetUpBeforeClass(): void {
+		$previous_hpos_state = OrderUtil::custom_orders_table_usage_is_enabled();
+		add_filter( 'wc_allow_changing_orders_storage_while_sync_is_pending', '__return_true' );
+
+		try {
+			self::setup_cot_tables();
+			if ( OrderUtil::custom_orders_table_usage_is_enabled() !== $previous_hpos_state ) {
+				OrderHelper::toggle_cot_feature_and_usage( $previous_hpos_state );
+			}
+		} finally {
+			remove_filter( 'wc_allow_changing_orders_storage_while_sync_is_pending', '__return_true' );
+		}
+	}
+
 	/**
 	 * @testdox coupon code should be always sanitized.
 	 */
@@ -34,16 +57,36 @@ class WC_Post_Data_Test extends \WC_Unit_Test_Case {
 	}

 	/**
-	 * Order items should be deleted before deleting order.
+	 * @testdox Should remove order items when permanently deleting an order.
+	 * @testWith [false]
+	 *           [true]
+	 *
+	 * @param bool $hpos_enabled Whether HPOS is enabled.
 	 */
-	public function test_before_delete_order() {
-		$order = \Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper::create_order();
-		$items = $order->get_items();
-		$this->assertNotEmpty( $items );
-
-		WC_Post_Data::before_delete_order( $order->get_id() );
-		$order = wc_get_order( $order->get_id() );
-		$this->assertEmpty( $order->get_items() );
+	public function test_deleting_order_removes_items( bool $hpos_enabled ): void {
+		$previous_hpos_state = OrderUtil::custom_orders_table_usage_is_enabled();
+		add_filter( 'wc_allow_changing_orders_storage_while_sync_is_pending', '__return_true' );
+		remove_filter( 'query', array( $this, '_create_temporary_tables' ) );
+		remove_filter( 'query', array( $this, '_drop_temporary_tables' ) );
+
+		try {
+			$this->toggle_cot_authoritative( $hpos_enabled );
+
+			$order    = OrderHelper::create_order();
+			$item_ids = array_keys( $order->get_items() );
+			$this->assertNotEmpty( $item_ids, 'The order should contain an item' );
+
+			$order->delete( true );
+
+			$this->assertFalse( WC_Order_Factory::get_order_item( reset( $item_ids ) ), 'The deleted order item should no longer be available' );
+		} finally {
+			if ( OrderUtil::custom_orders_table_usage_is_enabled() !== $previous_hpos_state ) {
+				$this->toggle_cot_authoritative( $previous_hpos_state );
+			}
+			add_filter( 'query', array( $this, '_create_temporary_tables' ) );
+			add_filter( 'query', array( $this, '_drop_temporary_tables' ) );
+			remove_filter( 'wc_allow_changing_orders_storage_while_sync_is_pending', '__return_true' );
+		}
 	}

 	/**