From 15bf1da7d5d26b7e5953c63fd8358562c6a549ab Mon Sep 17 00:00:00 2001 From: Justin Shreve Date: Wed, 5 Apr 2017 14:39:41 -0700 Subject: [PATCH] Call save_meta_data before wp_update_post for data stores that use it, and refresh meta cache after. --- .../abstract-wc-order-data-store-cpt.php | 3 +- .../class-wc-coupon-data-store-cpt.php | 4 ++- .../class-wc-product-data-store-cpt.php | 3 +- ...ss-wc-product-variation-data-store-cpt.php | 3 +- .../helpers/class-wc-helper-product.php | 8 +++++ tests/unit-tests/product/data-store.php | 29 +++++++++++++++++++ 6 files changed, 46 insertions(+), 4 deletions(-) diff --git a/includes/data-stores/abstract-wc-order-data-store-cpt.php b/includes/data-stores/abstract-wc-order-data-store-cpt.php index b876864b2bd..6d353b813b5 100644 --- a/includes/data-stores/abstract-wc-order-data-store-cpt.php +++ b/includes/data-stores/abstract-wc-order-data-store-cpt.php @@ -113,6 +113,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme * @param WC_Order $order */ public function update( &$order ) { + $order->save_meta_data(); $order->set_version( WC_VERSION ); $changes = $order->get_changes(); @@ -129,9 +130,9 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme 'post_modified' => isset( $changes['date_modified'] ) ? gmdate( 'Y-m-d H:i:s', $order->get_date_modified( 'edit' )->getOffsetTimestamp() ) : current_time( 'mysql' ), 'post_modified_gmt' => isset( $changes['date_modified'] ) ? gmdate( 'Y-m-d H:i:s', $order->get_date_modified( 'edit' )->getTimestamp() ) : current_time( 'mysql', 1 ), ) ); + $order->read_meta_data( true ); // Refresh internal meta data, in case things were hooked into `save_post` or another WP hook. } $this->update_post_meta( $order ); - $order->save_meta_data(); $order->apply_changes(); $this->clear_caches( $order ); } diff --git a/includes/data-stores/class-wc-coupon-data-store-cpt.php b/includes/data-stores/class-wc-coupon-data-store-cpt.php index b5543c2d424..226c12d8b27 100644 --- a/includes/data-stores/class-wc-coupon-data-store-cpt.php +++ b/includes/data-stores/class-wc-coupon-data-store-cpt.php @@ -127,14 +127,16 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat * @param WC_Coupon */ public function update( &$coupon ) { + $coupon->save_meta_data(); $post_data = array( 'ID' => $coupon->get_id(), 'post_title' => $coupon->get_code(), 'post_excerpt' => $coupon->get_description(), ); wp_update_post( $post_data ); + $coupon->read_meta_data( true ); // Refresh internal meta data, in case things were hooked into `save_post` or another WP hook. + $this->update_post_meta( $coupon ); - $coupon->save_meta_data(); $coupon->apply_changes(); do_action( 'woocommerce_update_coupon', $coupon->get_id() ); } diff --git a/includes/data-stores/class-wc-product-data-store-cpt.php b/includes/data-stores/class-wc-product-data-store-cpt.php index 1d71e270b7a..65c582fe583 100644 --- a/includes/data-stores/class-wc-product-data-store-cpt.php +++ b/includes/data-stores/class-wc-product-data-store-cpt.php @@ -162,6 +162,7 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da * @param WC_Product */ public function update( &$product ) { + $product->save_meta_data(); $changes = $product->get_changes(); // Only update the post when the post data changes. @@ -189,6 +190,7 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da $post_data['post_modified_gmt'] = current_time( 'mysql', 1 ); } wp_update_post( $post_data ); + $product->read_meta_data( true ); // Refresh internal meta data, in case things were hooked into `save_post` or another WP hook. } $this->update_post_meta( $product ); @@ -198,7 +200,6 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da $this->update_version_and_type( $product ); $this->handle_updated_props( $product ); - $product->save_meta_data(); $product->apply_changes(); $this->clear_caches( $product ); diff --git a/includes/data-stores/class-wc-product-variation-data-store-cpt.php b/includes/data-stores/class-wc-product-variation-data-store-cpt.php index 643a971f654..6129aabe3ab 100644 --- a/includes/data-stores/class-wc-product-variation-data-store-cpt.php +++ b/includes/data-stores/class-wc-product-variation-data-store-cpt.php @@ -136,6 +136,7 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl * @param WC_Product */ public function update( &$product ) { + $product->save_meta_data(); $changes = $product->get_changes(); $title = $this->generate_product_title( $product ); @@ -153,6 +154,7 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl 'post_modified' => isset( $changes['date_modified'] ) ? gmdate( 'Y-m-d H:i:s', $product->get_date_modified( 'edit' )->getOffsetTimestamp() ) : current_time( 'mysql' ), 'post_modified_gmt' => isset( $changes['date_modified'] ) ? gmdate( 'Y-m-d H:i:s', $product->get_date_modified( 'edit' )->getTimestamp() ) : current_time( 'mysql', 1 ), ) ); + $product->read_meta_data( true ); // Refresh internal meta data, in case things were hooked into `save_post` or another WP hook. } $this->update_post_meta( $product ); @@ -160,7 +162,6 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl $this->update_attributes( $product ); $this->handle_updated_props( $product ); - $product->save_meta_data(); $product->apply_changes(); $this->update_version_and_type( $product ); diff --git a/tests/framework/helpers/class-wc-helper-product.php b/tests/framework/helpers/class-wc-helper-product.php index 0b2513cdbed..b62c2c19832 100644 --- a/tests/framework/helpers/class-wc-helper-product.php +++ b/tests/framework/helpers/class-wc-helper-product.php @@ -326,4 +326,12 @@ class WC_Helper_Product { return wp_insert_comment( $data ); } + + /** + * A helper function for hooking into save_post during the test_product_meta_save_post test. + * @since 3.0.1 + */ + public static function save_post_test_update_meta_data_direct( $id ) { + update_post_meta( $id, '_test2', 'world' ); + } } diff --git a/tests/unit-tests/product/data-store.php b/tests/unit-tests/product/data-store.php index 472099228da..7d4016ca745 100644 --- a/tests/unit-tests/product/data-store.php +++ b/tests/unit-tests/product/data-store.php @@ -456,4 +456,33 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case { $loaded_variation = wc_get_product( $variation->get_id() ); $this->assertEquals( "Test Product", $loaded_variation->get_name() ); } + + /** + * Test to make sure meta can still be set while hooked using save_post. + * https://github.com/woocommerce/woocommerce/issues/13960 + * @since 3.0.01 + */ + function test_product_meta_save_post() { + $product = new WC_Product; + $product->set_name( 'Test Product' ); + $product->save(); + update_post_meta( $product->get_id(), '_test2', 'default' ); // this is the value we don't want to get back. + + // This takes place of WC_Meta_Box do_action( 'woocommerce_admin_process_product_object ' ) just adding simple meta. + $product->update_meta_data( '_test', 'hello' ); + $product->set_name( 'Test Product_' ); + + add_action( 'save_post', array( 'WC_Helper_Product', 'save_post_test_update_meta_data_direct' ), 11 ); + $product->save(); + + $test = get_post_meta( $product->get_id(), '_test', true ); + $test2 = get_post_meta( $product->get_id(), '_test2', true ); + + $this->assertEquals( 'hello', $test ); + $this->assertEquals( 'world', $test2 ); // this would be 'default' without the force meta refresh in WC_Product_Data_Store::update(); + $this->assertEquals( 'world', $product->get_meta( '_test2' ) ); + $this->assertEquals( 'Test Product_', $product->get_name() ); + + remove_action( 'save_post', array( 'WC_Helper_Product', 'save_post_test_update_meta_data_direct' ) ); + } }