Merge pull request #27140 from woocommerce/fix/23790
Always sanitize coupon code to prevent inconsistent between admins and shop owners
This commit is contained in:
commit
76cf1e4e93
|
@ -1691,7 +1691,7 @@ class WC_Cart extends WC_Legacy_Cart {
|
||||||
*/
|
*/
|
||||||
public function remove_coupon( $coupon_code ) {
|
public function remove_coupon( $coupon_code ) {
|
||||||
$coupon_code = wc_format_coupon_code( $coupon_code );
|
$coupon_code = wc_format_coupon_code( $coupon_code );
|
||||||
$position = array_search( $coupon_code, $this->get_applied_coupons(), true );
|
$position = array_search( $coupon_code, array_map( 'wc_format_coupon_code', $this->get_applied_coupons() ), true );
|
||||||
|
|
||||||
if ( false !== $position ) {
|
if ( false !== $position ) {
|
||||||
unset( $this->applied_coupons[ $position ] );
|
unset( $this->applied_coupons[ $position ] );
|
||||||
|
|
|
@ -153,6 +153,10 @@ class WC_Install {
|
||||||
'wc_update_440_insert_attribute_terms_for_variable_products',
|
'wc_update_440_insert_attribute_terms_for_variable_products',
|
||||||
'wc_update_440_db_version',
|
'wc_update_440_db_version',
|
||||||
),
|
),
|
||||||
|
'4.5.0' => array(
|
||||||
|
'wc_update_450_sanitize_coupons_code',
|
||||||
|
'wc_update_450_db_version',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -255,6 +255,9 @@ class WC_Post_Data {
|
||||||
}
|
}
|
||||||
} elseif ( 'product' === $data['post_type'] && 'auto-draft' === $data['post_status'] ) {
|
} elseif ( 'product' === $data['post_type'] && 'auto-draft' === $data['post_status'] ) {
|
||||||
$data['post_title'] = 'AUTO-DRAFT';
|
$data['post_title'] = 'AUTO-DRAFT';
|
||||||
|
} elseif ( 'shop_coupon' === $data['post_type'] ) {
|
||||||
|
// Coupons should never allow unfiltered HTML.
|
||||||
|
$data['post_title'] = wp_filter_kses( $data['post_title'] );
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
|
|
@ -721,7 +721,7 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
|
||||||
return $wpdb->get_col(
|
return $wpdb->get_col(
|
||||||
$wpdb->prepare(
|
$wpdb->prepare(
|
||||||
"SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' ORDER BY post_date DESC",
|
"SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' ORDER BY post_date DESC",
|
||||||
$code
|
wc_sanitize_coupon_code( $code )
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -375,7 +375,7 @@ function wc_format_coupon_code( $value ) {
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function wc_sanitize_coupon_code( $value ) {
|
function wc_sanitize_coupon_code( $value ) {
|
||||||
return sanitize_post_field( 'post_title', $value, 0, 'db' );
|
return wp_filter_kses( sanitize_post_field( 'post_title', $value, 0, 'db' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2175,3 +2175,70 @@ function wc_update_440_insert_attribute_terms_for_variable_products() {
|
||||||
function wc_update_440_db_version() {
|
function wc_update_440_db_version() {
|
||||||
WC_Install::update_db_version( '4.4.0' );
|
WC_Install::update_db_version( '4.4.0' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update DB version to 4.5.0.
|
||||||
|
*/
|
||||||
|
function wc_update_450_db_version() {
|
||||||
|
WC_Install::update_db_version( '4.5.0' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanitize all coupons code.
|
||||||
|
*
|
||||||
|
* @return bool True to run again, false if completed.
|
||||||
|
*/
|
||||||
|
function wc_update_450_sanitize_coupons_code() {
|
||||||
|
global $wpdb;
|
||||||
|
|
||||||
|
$coupon_id = 0;
|
||||||
|
$last_coupon_id = get_option( 'woocommerce_update_450_last_coupon_id', '0' );
|
||||||
|
|
||||||
|
$coupons = $wpdb->get_results(
|
||||||
|
$wpdb->prepare(
|
||||||
|
"SELECT ID, post_title FROM $wpdb->posts WHERE ID > %d AND post_type = 'shop_coupon' LIMIT 10",
|
||||||
|
$last_coupon_id
|
||||||
|
),
|
||||||
|
ARRAY_A
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( empty( $coupons ) ) {
|
||||||
|
delete_option( 'woocommerce_update_450_last_coupon_id' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ( $coupons as $key => $data ) {
|
||||||
|
$coupon_id = intval( $data['ID'] );
|
||||||
|
$code = trim( wp_filter_kses( $data['post_title'] ) );
|
||||||
|
|
||||||
|
if ( ! empty( $code ) && $data['post_title'] !== $code ) {
|
||||||
|
$wpdb->update(
|
||||||
|
$wpdb->posts,
|
||||||
|
array(
|
||||||
|
'post_title' => $code,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'ID' => $coupon_id,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'%s',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'%d',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Clean cache.
|
||||||
|
clean_post_cache( $coupon_id );
|
||||||
|
wp_cache_delete( WC_Cache_Helper::get_cache_prefix( 'coupons' ) . 'coupon_id_from_code_' . $data['post_title'], 'coupons' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the run again.
|
||||||
|
if ( $coupon_id ) {
|
||||||
|
return update_option( 'woocommerce_update_450_last_coupon_id', $coupon_id );
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_option( 'woocommerce_update_450_last_coupon_id' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -171,9 +171,9 @@ class WC_Unit_Test_Case extends WP_HTTP_TestCase {
|
||||||
*/
|
*/
|
||||||
public function login_as_administrator() {
|
public function login_as_administrator() {
|
||||||
return $this->login_as_role( 'administrator' );
|
return $this->login_as_role( 'administrator' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an instance of a class that has been registered in the dependency injection container.
|
* Get an instance of a class that has been registered in the dependency injection container.
|
||||||
* To get an instance of a legacy class (such as the ones in the 'íncludes' directory) use
|
* To get an instance of a legacy class (such as the ones in the 'íncludes' directory) use
|
||||||
* 'get_legacy_instance_of' instead.
|
* 'get_legacy_instance_of' instead.
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Post data tests
|
||||||
|
*
|
||||||
|
* @package WooCommerce\Tests\Post_Data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class WC_Post_Data_Test
|
||||||
|
*/
|
||||||
|
class WC_Post_Data_Test extends \WC_Unit_Test_Case {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @testdox coupon code should be always sanitized.
|
||||||
|
*/
|
||||||
|
public function test_coupon_code_sanitization() {
|
||||||
|
$this->login_as_role( 'shop_manager' );
|
||||||
|
$coupon = WC_Helper_Coupon::create_coupon( 'a&a' );
|
||||||
|
$post_data = get_post( $coupon->get_id() );
|
||||||
|
$this->assertEquals( 'a&a', $post_data->post_title );
|
||||||
|
$coupon->delete( true );
|
||||||
|
|
||||||
|
$this->login_as_administrator();
|
||||||
|
$coupon = WC_Helper_Coupon::create_coupon( 'b&b' );
|
||||||
|
$post_data = get_post( $coupon->get_id() );
|
||||||
|
$this->assertEquals( 'b&b', $post_data->post_title );
|
||||||
|
$coupon->delete( true );
|
||||||
|
|
||||||
|
wp_set_current_user( 0 );
|
||||||
|
$coupon = WC_Helper_Coupon::create_coupon( 'c&c' );
|
||||||
|
$post_data = get_post( $coupon->get_id() );
|
||||||
|
$this->assertEquals( 'c&c', $post_data->post_title );
|
||||||
|
$coupon->delete( true );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Formatting functions tests
|
||||||
|
*
|
||||||
|
* @package WooCommerce\Tests\Formatting.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class WC_Formatting_Functions_Test
|
||||||
|
*/
|
||||||
|
class WC_Formatting_Functions_Test extends \WC_Unit_Test_Case {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test wc_sanitize_coupon_code() function.
|
||||||
|
*/
|
||||||
|
public function test_wc_sanitize_coupon_code() {
|
||||||
|
$this->assertEquals( 'DUMMYCOUPON', wc_sanitize_coupon_code( 'DUMMYCOUPON' ) );
|
||||||
|
$this->assertEquals( 'a&a', wc_sanitize_coupon_code( 'a&a' ) );
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue