WC_Coupon_Data_Store_CPT::check_and_hold_coupon()
Check and records coupon usage tentatively for short period of time so that counts validation is correct. Returns early if there is no limit defined for the coupon.
Method of the class: WC_Coupon_Data_Store_CPT{}
Hooks from the method
Return
true|false|Int|String|null
. Returns meta key if coupon was held, null if returned early.
Usage
$WC_Coupon_Data_Store_CPT = new WC_Coupon_Data_Store_CPT(); $WC_Coupon_Data_Store_CPT->check_and_hold_coupon( $coupon );
- $coupon(WC_Coupon) (required)
- Coupon object.
WC_Coupon_Data_Store_CPT::check_and_hold_coupon() WC Coupon Data Store CPT::check and hold coupon code WC 9.4.2
public function check_and_hold_coupon( $coupon ) { global $wpdb; $usage_limit = $coupon->get_usage_limit(); $held_time = $this->get_tentative_held_time(); if ( 0 >= $usage_limit || 0 >= $held_time ) { return null; } if ( ! apply_filters( 'woocommerce_hold_stock_for_checkout', true ) ) { return null; } // Make sure we have usage_count meta key for this coupon because its required for `$query_for_usages`. // We are not directly modifying `$query_for_usages` to allow for `usage_count` not present only keep that query simple. if ( ! metadata_exists( 'post', $coupon->get_id(), 'usage_count' ) ) { $coupon->set_usage_count( $coupon->get_usage_count() ); // Use `get_usage_count` here to write default value, which may changed by a filter. $coupon->save(); } $query_for_usages = $wpdb->prepare( " SELECT meta_value from $wpdb->postmeta WHERE {$wpdb->postmeta}.meta_key = 'usage_count' AND {$wpdb->postmeta}.post_id = %d LIMIT 1 FOR UPDATE ", $coupon->get_id() ); $query_for_tentative_usages = $this->get_tentative_usage_query( $coupon->get_id() ); $db_timestamp = $wpdb->get_var( 'SELECT UNIX_TIMESTAMP() FROM ' . $wpdb->posts . ' LIMIT 1' ); $coupon_usage_key = '_coupon_held_' . ( (int) $db_timestamp + $held_time ) . '_' . wp_generate_password( 6, false ); $insert_statement = $wpdb->prepare( " INSERT INTO $wpdb->postmeta ( post_id, meta_key, meta_value ) SELECT %d, %s, %s FROM $wpdb->posts WHERE ( $query_for_usages ) + ( $query_for_tentative_usages ) < %d LIMIT 1", $coupon->get_id(), $coupon_usage_key, '', $usage_limit ); // WPCS: unprepared SQL ok. /** * In some cases, specifically when there is a combined index on post_id,meta_key, the insert statement above could end up in a deadlock. * We will try to insert 3 times before giving up to recover from deadlock. */ for ( $count = 0; $count < 3; $count++ ) { $result = $wpdb->query( $insert_statement ); // WPCS: unprepared SQL ok. if ( false !== $result ) { // Clear meta cache. $this->refresh_coupon_data( $coupon ); break; } } return $result > 0 ? $coupon_usage_key : $result; }