Invalidate coupon cache after hold/usage data is modified in datastore via SQL (#41538)
* Invalidate coupon cache after direct SQL queries * Add changelog * Add unit test * Address feedback
This commit is contained in:
parent
00e1a29194
commit
1d00e76fda
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: fix
|
||||
|
||||
Fixes an issue where coupon usage is not correctly recorded when HPOS is active.
|
|
@ -347,6 +347,8 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
|||
} else {
|
||||
add_post_meta( $coupon->get_id(), '_used_by', strtolower( $used_by ) );
|
||||
}
|
||||
|
||||
$this->refresh_coupon_data( $coupon );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -375,6 +377,7 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
|||
if ( $meta_id ) {
|
||||
delete_metadata_by_mid( 'post', $meta_id );
|
||||
$coupon->set_used_by( (array) get_post_meta( $coupon->get_id(), '_used_by' ) );
|
||||
$this->refresh_coupon_data( $coupon );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,6 +408,8 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
|||
)
|
||||
);
|
||||
|
||||
$this->refresh_coupon_data( $coupon );
|
||||
|
||||
// Get the latest value direct from the DB, instead of possibly the WP meta cache.
|
||||
return (int) $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM $wpdb->postmeta WHERE meta_key = 'usage_count' AND post_id = %d;", $id ) );
|
||||
}
|
||||
|
@ -556,7 +561,7 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
|||
$result = $wpdb->query( $insert_statement ); // WPCS: unprepared SQL ok.
|
||||
if ( false !== $result ) {
|
||||
// Clear meta cache.
|
||||
wp_cache_delete( WC_Coupon::generate_meta_cache_key( $coupon->get_id(), 'coupons' ), 'coupons' );
|
||||
$this->refresh_coupon_data( $coupon );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -651,7 +656,7 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
|||
$result = $wpdb->query( $insert_statement ); // WPCS: unprepared SQL ok.
|
||||
if ( false !== $result ) {
|
||||
// Clear meta cache.
|
||||
wp_cache_delete( WC_Coupon::generate_meta_cache_key( $coupon->get_id(), 'coupons' ), 'coupons' );
|
||||
$this->refresh_coupon_data( $coupon );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -693,6 +698,18 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
|||
); // WPCS: unprepared SQL ok.
|
||||
}
|
||||
|
||||
/**
|
||||
* This function clears coupon data from the WP cache after certain operations which, for performance reasons,
|
||||
* are done via SQL queries.
|
||||
*
|
||||
* @param \WC_Coupon $coupon The coupon object.
|
||||
* @return void
|
||||
*/
|
||||
private function refresh_coupon_data( &$coupon ) {
|
||||
wp_cache_delete( $coupon->get_meta_cache_key(), 'coupons' );
|
||||
wp_cache_delete( $coupon->get_id(), 'post_meta' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a coupon code for a specific ID.
|
||||
*
|
||||
|
|
|
@ -3198,4 +3198,45 @@ class OrdersTableDataStoreTests extends HposTestCase {
|
|||
remove_all_actions( 'woocommerce_webhook_process_delivery' );
|
||||
remove_all_actions( 'woocommerce_webhook_should_deliver' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @testDox Check that functions in the datastore correctly hold and release coupons from the order.
|
||||
*/
|
||||
public function test_datastore_coupon_methods() {
|
||||
$this->toggle_cot_authoritative( true );
|
||||
|
||||
$coupon = new \WC_Coupon();
|
||||
$coupon->set_code( '10off' );
|
||||
$coupon->set_discount_type( 'percent' );
|
||||
$coupon->set_amount( 10.0 );
|
||||
$coupon->set_usage_limit_per_user( 2 );
|
||||
$coupon->save();
|
||||
|
||||
$product = WC_Helper_Product::create_simple_product( true );
|
||||
|
||||
WC()->cart->add_to_cart( $product->get_id(), 1 );
|
||||
WC()->cart->add_discount( $coupon->get_code() );
|
||||
|
||||
$this->assertEquals( 0, $coupon->get_data_store()->get_usage_by_email( $coupon, 'user@woo.test' ) );
|
||||
|
||||
$order_id = WC()->checkout->create_order(
|
||||
array(
|
||||
'billing_email' => 'user@woo.test',
|
||||
'payment_method' => 'dummy',
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertEquals( 1, $coupon->get_data_store()->get_tentative_usages_for_user( $coupon->get_id(), array( 'user@woo.test' ) ) );
|
||||
$this->assertEquals( 1, $coupon->get_data_store()->get_usage_by_email( $coupon, 'user@woo.test' ) );
|
||||
|
||||
wc_get_order( $order_id )->payment_complete();
|
||||
|
||||
$this->assertEquals( 0, $coupon->get_data_store()->get_tentative_usages_for_user( $coupon->get_id(), array( 'user@woo.test' ) ) );
|
||||
$this->assertEquals( 1, $coupon->get_data_store()->get_usage_by_email( $coupon, 'user@woo.test' ) );
|
||||
|
||||
// Load a fresh copy of the coupon and make sure things look ok.
|
||||
$coupon = new \WC_Coupon( $coupon->get_id() );
|
||||
$this->assertContains( 'user@woo.test', $coupon->get_used_by( 'edit' ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue