WC_Coupon_Data_Store_CPT::check_and_hold_coupon_for_user()publicWC 1.0

Check and records coupon usage tentatively for passed user aliases for short period of time so that counts validation is correct. Returns early if there is no limit per user for the coupon.

Метод класса: WC_Coupon_Data_Store_CPT{}

Хуки из метода

Возвращает

null|false|int.

Использование

$WC_Coupon_Data_Store_CPT = new WC_Coupon_Data_Store_CPT();
$WC_Coupon_Data_Store_CPT->check_and_hold_coupon_for_user( $coupon, $user_aliases, $user_alias );
$coupon(WC_Coupon) (обязательный)
Coupon object.
$user_aliases(массив) (обязательный)
Emails or Ids to check for user.
$user_alias(строка) (обязательный)
Email/ID to use as used_by value.

Код WC_Coupon_Data_Store_CPT::check_and_hold_coupon_for_user() WC 8.7.0

public function check_and_hold_coupon_for_user( $coupon, $user_aliases, $user_alias ) {
	global $wpdb;
	$limit_per_user = $coupon->get_usage_limit_per_user();
	$held_time      = $this->get_tentative_held_time();

	if ( 0 >= $limit_per_user || 0 >= $held_time ) {
		// This coupon do not have any restriction for usage per customer. No need to check further, lets bail.
		return null;
	}

	if ( ! apply_filters( 'woocommerce_hold_stock_for_checkout', true ) ) {
		return null;
	}

	$format = implode( "','", array_fill( 0, count( $user_aliases ), '%s' ) );

	$query_for_usages = $wpdb->prepare(
		"
			SELECT COUNT(*) FROM $wpdb->postmeta
			WHERE {$wpdb->postmeta}.meta_key = '_used_by'
			AND {$wpdb->postmeta}.meta_value IN ('$format')
			AND {$wpdb->postmeta}.post_id = %d
			FOR UPDATE
			",
		array_merge(
			$user_aliases,
			array( $coupon->get_id() )
		)
	); // WPCS: unprepared SQL ok.

	$query_for_tentative_usages = $this->get_tentative_usage_query_for_user( $coupon->get_id(), $user_aliases );
	$db_timestamp               = $wpdb->get_var( 'SELECT UNIX_TIMESTAMP() FROM ' . $wpdb->posts . ' LIMIT 1' );

	$coupon_used_by_meta_key    = '_maybe_used_by_' . ( (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_used_by_meta_key,
		$user_alias,
		$limit_per_user
	); // WPCS: unprepared SQL ok.

	// This query can potentially be deadlocked if a combined index on post_id and meta_key is present and there is
	// high concurrency, in which case DB will abort the query which has done less work to resolve deadlock.
	// We will try up to 3 times before giving up.
	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_used_by_meta_key : $result;
}