diff --git a/plugins/woocommerce/changelog/fix-50207 b/plugins/woocommerce/changelog/fix-50207 new file mode 100644 index 00000000000..b20874ec6a2 --- /dev/null +++ b/plugins/woocommerce/changelog/fix-50207 @@ -0,0 +1,4 @@ +Significance: patch +Type: fix + +Bust WC object cache on direct post meta update to prevent stale cache read. diff --git a/plugins/woocommerce/includes/class-wc-post-data.php b/plugins/woocommerce/includes/class-wc-post-data.php index f1563c5d976..56e826b34c5 100644 --- a/plugins/woocommerce/includes/class-wc-post-data.php +++ b/plugins/woocommerce/includes/class-wc-post-data.php @@ -58,6 +58,8 @@ class WC_Post_Data { // Meta cache flushing. add_action( 'updated_post_meta', array( __CLASS__, 'flush_object_meta_cache' ), 10, 4 ); + add_action( 'added_post_meta', array( __CLASS__, 'flush_object_meta_cache' ), 10, 4 ); + add_action( 'deleted_post_meta', array( __CLASS__, 'flush_object_meta_cache' ), 10, 4 ); add_action( 'updated_order_item_meta', array( __CLASS__, 'flush_object_meta_cache' ), 10, 4 ); } diff --git a/plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-data-store-cpt-test.php b/plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-data-store-cpt-test.php index 9b98872ab31..b8d3e97fdf8 100644 --- a/plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-data-store-cpt-test.php +++ b/plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-data-store-cpt-test.php @@ -114,4 +114,67 @@ class WC_Product_Data_Store_CPT_Test extends WC_Unit_Test_Case { $product2->save(); $product3->save(); } + + /** + * @testDox Test that meta cache key is changed on direct post meta add. + */ + public function test_get_meta_data_is_busted_on_post_meta_add() { + $product = new WC_Product(); + $product->save(); + + // Set the cache. + $product->get_meta_data(); + + $object_id_cache_key = WC_Cache_Helper::get_cache_prefix( 'object_' . $product->get_id() ); + add_post_meta( $product->get_id(), 'test', 'value' ); + + $r_object_id_cache_key = WC_Cache_Helper::get_cache_prefix( 'object_' . $product->get_id() ); + $this->assertNotEquals( $object_id_cache_key, $r_object_id_cache_key ); + + $product = wc_get_product( $product->get_id() ); + $this->assertEquals( 'value', $product->get_meta( 'test', true ) ); + } + + + /** + * @testDox Test that meta cache key is changed on direct post meta update. + */ + public function test_get_meta_data_is_busted_on_post_meta_update() { + $product = new WC_Product(); + $product->add_meta_data( 'test', 'value' ); + $product->save(); + + // Set the cache. + $product->get_meta_data(); + + $object_id_cache_key = WC_Cache_Helper::get_cache_prefix( 'object_' . $product->get_id() ); + update_post_meta( $product->get_id(), 'test', 'value2' ); + + $r_object_id_cache_key = WC_Cache_Helper::get_cache_prefix( 'object_' . $product->get_id() ); + $this->assertNotEquals( $object_id_cache_key, $r_object_id_cache_key ); + + $product = wc_get_product( $product->get_id() ); + $this->assertEquals( 'value2', $product->get_meta( 'test', true ) ); + } + + /** + * @testDox Test that meta cache key is changed on direct post meta delete. + */ + public function test_get_meta_data_is_busted_on_post_meta_delete() { + $product = new WC_Product(); + $product->add_meta_data( 'test', 'value' ); + $product->save(); + + // Set the cache. + $product->get_meta_data(); + + $object_id_cache_key = WC_Cache_Helper::get_cache_prefix( 'object_' . $product->get_id() ); + delete_post_meta( $product->get_id(), 'test' ); + + $r_object_id_cache_key = WC_Cache_Helper::get_cache_prefix( 'object_' . $product->get_id() ); + $this->assertNotEquals( $object_id_cache_key, $r_object_id_cache_key ); + + $product = wc_get_product( $product->get_id() ); + $this->assertEmpty( $product->get_meta( 'test', true ) ); + } }