diff --git a/plugins/woocommerce/changelog/46692-fix-86639-delete-order-item-meta-query-hyperdb b/plugins/woocommerce/changelog/46692-fix-86639-delete-order-item-meta-query-hyperdb new file mode 100644 index 00000000000..bf9757fd9b3 --- /dev/null +++ b/plugins/woocommerce/changelog/46692-fix-86639-delete-order-item-meta-query-hyperdb @@ -0,0 +1,4 @@ +Significance: patch +Type: fix + +Update delete item meta query to format supported by wpdb::get_table_from_query() \ No newline at end of file diff --git a/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php b/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php index 5cf6c4344e5..c3d5a36f2e9 100644 --- a/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php +++ b/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php @@ -636,13 +636,15 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme */ public function delete_items( $order, $type = null ) { global $wpdb; + if ( ! empty( $type ) ) { - $wpdb->query( $wpdb->prepare( "DELETE FROM itemmeta USING {$wpdb->prefix}woocommerce_order_itemmeta itemmeta INNER JOIN {$wpdb->prefix}woocommerce_order_items items WHERE itemmeta.order_item_id = items.order_item_id AND items.order_id = %d AND items.order_item_type = %s", $order->get_id(), $type ) ); + $wpdb->query( $wpdb->prepare( "DELETE itemmeta FROM {$wpdb->prefix}woocommerce_order_itemmeta as itemmeta INNER JOIN {$wpdb->prefix}woocommerce_order_items as items WHERE itemmeta.order_item_id = items.order_item_id AND items.order_id = %d AND items.order_item_type = %s", $order->get_id(), $type ) ); $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d AND order_item_type = %s", $order->get_id(), $type ) ); } else { - $wpdb->query( $wpdb->prepare( "DELETE FROM itemmeta USING {$wpdb->prefix}woocommerce_order_itemmeta itemmeta INNER JOIN {$wpdb->prefix}woocommerce_order_items items WHERE itemmeta.order_item_id = items.order_item_id and items.order_id = %d", $order->get_id() ) ); + $wpdb->query( $wpdb->prepare( "DELETE itemmeta FROM {$wpdb->prefix}woocommerce_order_itemmeta as itemmeta INNER JOIN {$wpdb->prefix}woocommerce_order_items as items WHERE itemmeta.order_item_id = items.order_item_id and items.order_id = %d", $order->get_id() ) ); $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d", $order->get_id() ) ); } + $this->clear_caches( $order ); } diff --git a/plugins/woocommerce/tests/php/includes/data-stores/class-wc-order-data-store-cpt-test.php b/plugins/woocommerce/tests/php/includes/data-stores/class-wc-order-data-store-cpt-test.php index 381f63d832f..f7d1f1c0170 100644 --- a/plugins/woocommerce/tests/php/includes/data-stores/class-wc-order-data-store-cpt-test.php +++ b/plugins/woocommerce/tests/php/includes/data-stores/class-wc-order-data-store-cpt-test.php @@ -355,4 +355,87 @@ class WC_Order_Data_Store_CPT_Test extends WC_Unit_Test_Case { $this->assertSame( $order, $order_from_before_delete ); } } + + /** + * @testDox Deleting order items should only delete items of the specified type. + */ + public function test_delete_items() { + $order = WC_Helper_Order::create_order(); + $product = WC_Helper_Product::create_simple_product(); + $product_item = new WC_Order_Item_Product(); + $product_item->set_product( $product ); + $product_item->set_quantity( 1 ); + $product_item->save(); + + $fee_item_1 = new WC_Order_Item_Fee(); + $fee_item_1->set_amount( 20 ); + $fee_item_1->save(); + + $fee_item_2 = new WC_Order_Item_Fee(); + $fee_item_2->set_amount( 30 ); + $fee_item_2->save(); + + $shipping_item = new WC_Order_Item_Shipping(); + $shipping_item->set_name( 'dummy shipping' ); + $shipping_item->set_total( 20 ); + $shipping_item->save(); + + $order->add_item( $product_item ); + $order->add_item( $fee_item_1 ); + $order->add_item( $fee_item_2 ); + $order->add_item( $shipping_item ); + + $order->save(); + + $r_order = wc_get_order( $order->get_id() ); + $this->assertTrue( $r_order->get_item( $fee_item_1->get_id() )->get_id() === $fee_item_1->get_id() ); + $this->assertTrue( $r_order->get_item( $fee_item_2->get_id() )->get_id() === $fee_item_2->get_id() ); + $this->assertTrue( $r_order->get_item( $product_item->get_id() )->get_id() === $product_item->get_id() ); + $this->assertTrue( $r_order->get_item( $shipping_item->get_id() )->get_id() === $shipping_item->get_id() ); + + // Deleting single item type should only delete that item type. + $r_order->get_data_store()->delete_items( $r_order, $fee_item_1->get_type() ); + $this->assertFalse( $r_order->get_item( $fee_item_1->get_id() ) ); + $this->assertFalse( $r_order->get_item( $fee_item_2->get_id() ) ); + $this->assertTrue( $r_order->get_item( $product_item->get_id() )->get_id() === $product_item->get_id() ); + $this->assertTrue( $r_order->get_item( $shipping_item->get_id() )->get_id() === $shipping_item->get_id() ); + + // Deleting all items should all items. + $r_order->get_data_store()->delete_items( $r_order ); + $this->assertFalse( $r_order->get_item( $fee_item_1->get_id() ) ); + $this->assertFalse( $r_order->get_item( $fee_item_2->get_id() ) ); + $this->assertFalse( $r_order->get_item( $product_item->get_id() ) ); + $this->assertFalse( $r_order->get_item( $shipping_item->get_id() ) ); + } + + /** + * @testDox Deleting order item should delete items from only that order. + */ + public function test_delete_items_multi_order() { + $order_1 = WC_Helper_Order::create_order(); + $product = WC_Helper_Product::create_simple_product(); + $product_item_1 = new WC_Order_Item_Product(); + $product_item_1->set_product( $product ); + $product_item_1->set_quantity( 1 ); + $product_item_1->save(); + + $order_2 = WC_Helper_Order::create_order(); + $product_item_2 = new WC_Order_Item_Product(); + $product_item_2->set_product( $product ); + $product_item_2->set_quantity( 1 ); + $product_item_2->save(); + + $order_1->add_item( $product_item_1 ); + $order_1->save(); + $order_2->add_item( $product_item_2 ); + $order_2->save(); + + $this->assertTrue( $order_1->get_item( $product_item_1->get_id() )->get_id() === $product_item_1->get_id() ); + $this->assertTrue( $order_2->get_item( $product_item_2->get_id() )->get_id() === $product_item_2->get_id() ); + + $order_1->get_data_store()->delete_items( $order_1 ); + + $this->assertFalse( $order_1->get_item( $product_item_1->get_id() ) ); + $this->assertTrue( $order_2->get_item( $product_item_2->get_id() )->get_id() === $product_item_2->get_id() ); + } }