From 9724b67ab8ae4f27e28042471805a1720e1bcfe3 Mon Sep 17 00:00:00 2001 From: Justin Shreve Date: Thu, 9 Mar 2017 13:36:23 -0800 Subject: [PATCH] Fix order item meta functions cache busting. The cache busting currently in `wc_add_order_item_meta`, `wc_update_order_item_meta`, and `wc_delete_order_item_meta` doesn't actually bust anything. The cache line looks like it is from 2.6. The relevent cache to bust is actually in the `order-items` group and has a different key/prefix. This bug allows your meta to get out of sync if you use these functions and then try to access a value from a CRUD object. You can see this in the `test_wc_order_item_meta_functions` test I've added. If you keep your `wc-order-item-functions.php` as is, the asserts against `$item->get_meta` will fail. To test: * `phpunit --filter=test_wc_order_item_meta_functions`. * Try before applying the `wc-order-item-functions.php` changes and after. --- includes/wc-order-item-functions.php | 12 ++--- tests/unit-tests/order-items/functions.php | 62 ++++++++++++++++++++++ 2 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 tests/unit-tests/order-items/functions.php diff --git a/includes/wc-order-item-functions.php b/includes/wc-order-item-functions.php index 4666541ca4d..368008ed1bb 100644 --- a/includes/wc-order-item-functions.php +++ b/includes/wc-order-item-functions.php @@ -98,8 +98,8 @@ function wc_delete_order_item( $item_id ) { function wc_update_order_item_meta( $item_id, $meta_key, $meta_value, $prev_value = '' ) { $data_store = WC_Data_Store::load( 'order-item' ); if ( $data_store->update_metadata( $item_id, $meta_key, $meta_value, $prev_value ) ) { - $cache_key = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'item_meta_array_' . $item_id; - wp_cache_delete( $cache_key, 'orders' ); + $cache_key = WC_Cache_Helper::get_cache_prefix( 'order-items' ) . 'object_meta_' . $item_id; + wp_cache_delete( $cache_key, 'order-items' ); return true; } return false; @@ -118,8 +118,8 @@ function wc_update_order_item_meta( $item_id, $meta_key, $meta_value, $prev_valu function wc_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique = false ) { $data_store = WC_Data_Store::load( 'order-item' ); if ( $meta_id = $data_store->add_metadata( $item_id, $meta_key, $meta_value, $unique ) ) { - $cache_key = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'item_meta_array_' . $item_id; - wp_cache_delete( $cache_key, 'orders' ); + $cache_key = WC_Cache_Helper::get_cache_prefix( 'order-items' ) . 'object_meta_' . $item_id; + wp_cache_delete( $cache_key, 'order-items' ); return $meta_id; } return 0; @@ -138,8 +138,8 @@ function wc_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique = fal function wc_delete_order_item_meta( $item_id, $meta_key, $meta_value = '', $delete_all = false ) { $data_store = WC_Data_Store::load( 'order-item' ); if ( $data_store->delete_metadata( $item_id, $meta_key, $meta_value, $delete_all ) ) { - $cache_key = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'item_meta_array_' . $item_id; - wp_cache_delete( $cache_key, 'orders' ); + $cache_key = WC_Cache_Helper::get_cache_prefix( 'order-items' ) . 'object_meta_' . $item_id; + wp_cache_delete( $cache_key, 'order-items' ); return true; } return false; diff --git a/tests/unit-tests/order-items/functions.php b/tests/unit-tests/order-items/functions.php new file mode 100644 index 00000000000..f80ae8b7721 --- /dev/null +++ b/tests/unit-tests/order-items/functions.php @@ -0,0 +1,62 @@ +set_props( array( + 'product' => WC_Helper_Product::create_simple_product(), + 'quantity' => 4, + ) ); + $order->add_item( $item_1 ); + $order->save(); + + $item = current( $order->get_items() ); + $item_id = $item->get_id(); + + // Test that the initial key doesn't exist. + $item = new WC_Order_Item_Product( $item_id );; + $this->assertEmpty( $item->get_meta( '_test_key' ) ); + $this->assertEmpty( wc_get_order_item_meta( $item_id, '_test_key' ) ); + + // Test making sure cache is properly busted when adding meta. + wc_add_order_item_meta( $item_id, '_test_key', $meta_value ); + $item = new WC_Order_Item_Product( $item_id ); + $item_meta = $item->get_meta( '_test_key' ); + $this->assertEquals( $meta_value, $item_meta ); + $this->assertEquals( $meta_value, wc_get_order_item_meta( $item_id, '_test_key' ) ); + + // Test making sure cache is properly busted when updating meta. + wc_update_order_item_meta( $item_id, '_test_key', $meta_value2 ); + $item = new WC_Order_Item_Product( $item_id ); + $item_meta = $item->get_meta( '_test_key' ); + $this->assertEquals( $meta_value2, $item_meta ); + $this->assertEquals( $meta_value2, wc_get_order_item_meta( $item_id, '_test_key' ) ); + + // Test making sure cache is properly busted when deleting meta. + wc_delete_order_item_meta( $item_id, '_test_key' ); + $item = new WC_Order_Item_Product( $item_id ); + $item_meta = $item->get_meta( '_test_key' ); + $this->assertEmpty( $item->get_meta( '_test_key' ) ); + $this->assertEmpty( wc_get_order_item_meta( $item_id, '_test_key' ) ); + } + +}