Make coupon metadata read robust against wrongly stored product related metadata (#48362)
Coupon metadata keys `product_ids` and `excluded_product_ids` are stored by WooCommerce as a comma-saparated list of values, but apparently some plugins mistakenly re-store these as serialized arrays. This pull request changes the database metadata read code so that it supports both comma-separated lists and serialized arrays. Fixes #40569
This commit is contained in:
parent
dc5ad32fb7
commit
e64f7b31bc
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: fix
|
||||||
|
|
||||||
|
Make coupon metadata read robust against wrongly stored product related metadata
|
|
@ -118,7 +118,8 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
||||||
throw new Exception( __( 'Invalid coupon.', 'woocommerce' ) );
|
throw new Exception( __( 'Invalid coupon.', 'woocommerce' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
$coupon_id = $coupon->get_id();
|
$coupon_id = $coupon->get_id();
|
||||||
|
$limit_usage_to_x_items = get_post_meta( $coupon_id, 'limit_usage_to_x_items', true );
|
||||||
$coupon->set_props(
|
$coupon->set_props(
|
||||||
array(
|
array(
|
||||||
'code' => $post_object->post_title,
|
'code' => $post_object->post_title,
|
||||||
|
@ -131,11 +132,11 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
||||||
'amount' => get_post_meta( $coupon_id, 'coupon_amount', true ),
|
'amount' => get_post_meta( $coupon_id, 'coupon_amount', true ),
|
||||||
'usage_count' => get_post_meta( $coupon_id, 'usage_count', true ),
|
'usage_count' => get_post_meta( $coupon_id, 'usage_count', true ),
|
||||||
'individual_use' => 'yes' === get_post_meta( $coupon_id, 'individual_use', true ),
|
'individual_use' => 'yes' === get_post_meta( $coupon_id, 'individual_use', true ),
|
||||||
'product_ids' => array_filter( (array) explode( ',', get_post_meta( $coupon_id, 'product_ids', true ) ) ),
|
'product_ids' => $this->get_coupon_meta_as_array( $coupon_id, 'product_ids' ),
|
||||||
'excluded_product_ids' => array_filter( (array) explode( ',', get_post_meta( $coupon_id, 'exclude_product_ids', true ) ) ),
|
'excluded_product_ids' => $this->get_coupon_meta_as_array( $coupon_id, 'exclude_product_ids' ),
|
||||||
'usage_limit' => get_post_meta( $coupon_id, 'usage_limit', true ),
|
'usage_limit' => get_post_meta( $coupon_id, 'usage_limit', true ),
|
||||||
'usage_limit_per_user' => get_post_meta( $coupon_id, 'usage_limit_per_user', true ),
|
'usage_limit_per_user' => get_post_meta( $coupon_id, 'usage_limit_per_user', true ),
|
||||||
'limit_usage_to_x_items' => 0 < get_post_meta( $coupon_id, 'limit_usage_to_x_items', true ) ? get_post_meta( $coupon_id, 'limit_usage_to_x_items', true ) : null,
|
'limit_usage_to_x_items' => $limit_usage_to_x_items > 0 ? $limit_usage_to_x_items : null,
|
||||||
'free_shipping' => 'yes' === get_post_meta( $coupon_id, 'free_shipping', true ),
|
'free_shipping' => 'yes' === get_post_meta( $coupon_id, 'free_shipping', true ),
|
||||||
'product_categories' => array_filter( (array) get_post_meta( $coupon_id, 'product_categories', true ) ),
|
'product_categories' => array_filter( (array) get_post_meta( $coupon_id, 'product_categories', true ) ),
|
||||||
'excluded_product_categories' => array_filter( (array) get_post_meta( $coupon_id, 'exclude_product_categories', true ) ),
|
'excluded_product_categories' => array_filter( (array) get_post_meta( $coupon_id, 'exclude_product_categories', true ) ),
|
||||||
|
@ -151,6 +152,24 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
||||||
do_action( 'woocommerce_coupon_loaded', $coupon );
|
do_action( 'woocommerce_coupon_loaded', $coupon );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a metadata value that is stored as either a string consisting of a comma-separated list of values
|
||||||
|
* or as a serialized array.
|
||||||
|
*
|
||||||
|
* WooCommerce always stores the coupon product ids as a comma-separated string, but it seems that
|
||||||
|
* some plugins mistakenly change these to an array.
|
||||||
|
*
|
||||||
|
* @param int $coupon_id The coupon id.
|
||||||
|
* @param string $meta_key The meta key to get.
|
||||||
|
* @return array The metadata value as an array, with empty values removed.
|
||||||
|
*/
|
||||||
|
private function get_coupon_meta_as_array( $coupon_id, string $meta_key ) {
|
||||||
|
$meta_value = get_post_meta( $coupon_id, $meta_key, true );
|
||||||
|
return array_filter(
|
||||||
|
is_array( $meta_value ) ? $meta_value : explode( ',', $meta_value )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a coupon in the database.
|
* Updates a coupon in the database.
|
||||||
*
|
*
|
||||||
|
@ -446,7 +465,7 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
||||||
*/
|
*/
|
||||||
public function get_usage_by_user_id( &$coupon, $user_id ) {
|
public function get_usage_by_user_id( &$coupon, $user_id ) {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
$usage_count = $wpdb->get_var(
|
$usage_count = $wpdb->get_var(
|
||||||
$wpdb->prepare(
|
$wpdb->prepare(
|
||||||
"SELECT COUNT( meta_id ) FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key = '_used_by' AND meta_value = %s;",
|
"SELECT COUNT( meta_id ) FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key = '_used_by' AND meta_value = %s;",
|
||||||
$coupon->get_id(),
|
$coupon->get_id(),
|
||||||
|
@ -467,7 +486,7 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
||||||
*/
|
*/
|
||||||
public function get_usage_by_email( &$coupon, $email ) {
|
public function get_usage_by_email( &$coupon, $email ) {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
$usage_count = $wpdb->get_var(
|
$usage_count = $wpdb->get_var(
|
||||||
$wpdb->prepare(
|
$wpdb->prepare(
|
||||||
"SELECT COUNT( meta_id ) FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key = '_used_by' AND meta_value = %s;",
|
"SELECT COUNT( meta_id ) FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key = '_used_by' AND meta_value = %s;",
|
||||||
$coupon->get_id(),
|
$coupon->get_id(),
|
||||||
|
@ -491,7 +510,6 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
||||||
return $wpdb->get_var(
|
return $wpdb->get_var(
|
||||||
$this->get_tentative_usage_query_for_user( $coupon_id, $user_aliases )
|
$this->get_tentative_usage_query_for_user( $coupon_id, $user_aliases )
|
||||||
); // WPCS: unprepared SQL ok.
|
); // WPCS: unprepared SQL ok.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -643,8 +661,8 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
||||||
$query_for_tentative_usages = $this->get_tentative_usage_query_for_user( $coupon->get_id(), $user_aliases );
|
$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' );
|
$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 );
|
$coupon_used_by_meta_key = '_maybe_used_by_' . ( (int) $db_timestamp + $held_time ) . '_' . wp_generate_password( 6, false );
|
||||||
$insert_statement = $wpdb->prepare(
|
$insert_statement = $wpdb->prepare(
|
||||||
"
|
"
|
||||||
INSERT INTO $wpdb->postmeta ( post_id, meta_key, meta_value )
|
INSERT INTO $wpdb->postmeta ( post_id, meta_key, meta_value )
|
||||||
SELECT %d, %s, %s FROM $wpdb->posts
|
SELECT %d, %s, %s FROM $wpdb->posts
|
||||||
|
|
Loading…
Reference in New Issue