Merge pull request #13516 from woocommerce/fix-13505
Make increase_usage_count work correctly on concurrent checkout
This commit is contained in:
commit
38afff0031
|
@ -709,8 +709,13 @@ class WC_Coupon extends WC_Legacy_Coupon {
|
|||
*/
|
||||
public function increase_usage_count( $used_by = '' ) {
|
||||
if ( $this->get_id() && $this->data_store ) {
|
||||
$this->set_prop( 'usage_count', ( $this->get_usage_count( 'edit' ) + 1 ) );
|
||||
$this->data_store->increase_usage_count( $this, $used_by );
|
||||
$new_count = $this->data_store->increase_usage_count( $this, $used_by );
|
||||
|
||||
// Bypass set_prop and remove pending changes since the data store saves the count already.
|
||||
$this->data['usage_count'] = $new_count;
|
||||
if ( isset( $this->changes['usage_count'] ) ) {
|
||||
unset( $this->changes['usage_count'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -721,8 +726,13 @@ class WC_Coupon extends WC_Legacy_Coupon {
|
|||
*/
|
||||
public function decrease_usage_count( $used_by = '' ) {
|
||||
if ( $this->get_id() && $this->get_usage_count() > 0 && $this->data_store ) {
|
||||
$this->set_prop( 'usage_count', ( $this->get_usage_count( 'edit' ) - 1 ) );
|
||||
$this->data_store->decrease_usage_count( $this, $used_by );
|
||||
$new_count = $this->data_store->decrease_usage_count( $this, $used_by );
|
||||
|
||||
// Bypass set_prop and remove pending changes since the data store saves the count already.
|
||||
$this->data['usage_count'] = $new_count;
|
||||
if ( isset( $this->changes['usage_count'] ) ) {
|
||||
unset( $this->changes['usage_count'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -228,13 +228,15 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
|||
* @since 2.7.0
|
||||
* @param WC_Coupon
|
||||
* @param string $used_by Either user ID or billing email
|
||||
* @return int New usage count
|
||||
*/
|
||||
public function increase_usage_count( &$coupon, $used_by = '' ) {
|
||||
update_post_meta( $coupon->get_id(), 'usage_count', $coupon->get_usage_count( 'edit' ) );
|
||||
$new_count = $this->update_usage_count_meta( $coupon, 'increase' );
|
||||
if ( $used_by ) {
|
||||
add_post_meta( $coupon->get_id(), '_used_by', strtolower( $used_by ) );
|
||||
$coupon->set_used_by( (array) get_post_meta( $coupon->get_id(), '_used_by' ) );
|
||||
}
|
||||
return $new_count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -243,10 +245,11 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
|||
* @since 2.7.0
|
||||
* @param WC_Coupon
|
||||
* @param string $used_by Either user ID or billing email
|
||||
* @return int New usage count
|
||||
*/
|
||||
public function decrease_usage_count( &$coupon, $used_by = '' ) {
|
||||
global $wpdb;
|
||||
update_post_meta( $coupon->get_id(), 'usage_count', $coupon->get_usage_count() );
|
||||
$new_count = $this->update_usage_count_meta( $coupon, 'decrease' );
|
||||
if ( $used_by ) {
|
||||
/**
|
||||
* We're doing this the long way because `delete_post_meta( $id, $key, $value )` deletes.
|
||||
|
@ -258,6 +261,27 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
|||
$coupon->set_used_by( (array) get_post_meta( $coupon->get_id(), '_used_by' ) );
|
||||
}
|
||||
}
|
||||
return $new_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase or decrease the usage count for a coupon by 1.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Coupon
|
||||
* @param string $operation 'increase' or 'decrease'
|
||||
* @return int New usage count
|
||||
*/
|
||||
private function update_usage_count_meta( &$coupon, $operation = 'increase' ) {
|
||||
global $wpdb;
|
||||
$id = $coupon->get_id();
|
||||
$operator = ( 'increase' === $operation ) ? '+' : '-';
|
||||
|
||||
add_post_meta( $id, 'usage_count', $coupon->get_usage_count( 'edit' ), true );
|
||||
$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->postmeta SET meta_value = meta_value {$operator} 1 WHERE meta_key = 'usage_count' AND post_id = %d;", $id ) );
|
||||
|
||||
// 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 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -816,10 +816,10 @@ function wc_update_coupon_usage_counts( $order_id ) {
|
|||
|
||||
switch ( $action ) {
|
||||
case 'reduce' :
|
||||
$coupon->dcr_usage_count( $used_by );
|
||||
$coupon->decrease_usage_count( $used_by );
|
||||
break;
|
||||
case 'increase' :
|
||||
$coupon->inc_usage_count( $used_by );
|
||||
$coupon->increase_usage_count( $used_by );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,19 +110,19 @@ class WC_Tests_Coupon_Data_Store extends WC_Unit_Test_Case {
|
|||
$this->assertEquals( 0, $coupon->get_usage_count() );
|
||||
$this->assertEmpty( $coupon->get_used_by() );
|
||||
|
||||
$coupon->inc_usage_count( 'woo@woo.local' );
|
||||
$coupon->increase_usage_count( 'woo@woo.local' );
|
||||
|
||||
$this->assertEquals( 1, $coupon->get_usage_count() );
|
||||
$this->assertEquals( array( 'woo@woo.local' ), $coupon->get_used_by() );
|
||||
|
||||
$coupon->inc_usage_count( $user_id );
|
||||
$coupon->inc_usage_count( $user_id );
|
||||
$coupon->increase_usage_count( $user_id );
|
||||
$coupon->increase_usage_count( $user_id );
|
||||
|
||||
$data_store = WC_Data_Store::load( 'coupon' );
|
||||
$this->assertEquals( 2, $data_store->get_usage_by_user_id( $coupon, $user_id ) );
|
||||
|
||||
$coupon->dcr_usage_count( 'woo@woo.local' );
|
||||
$coupon->dcr_usage_count( $user_id );
|
||||
$coupon->decrease_usage_count( 'woo@woo.local' );
|
||||
$coupon->decrease_usage_count( $user_id );
|
||||
$this->assertEquals( 1, $coupon->get_usage_count() );
|
||||
$this->assertEquals( array( 1 ), $coupon->get_used_by() );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue