diff --git a/plugins/woocommerce/changelog/40998-fix-coupon-title-sanitization-39481 b/plugins/woocommerce/changelog/40998-fix-coupon-title-sanitization-39481 new file mode 100644 index 00000000000..832e049de39 --- /dev/null +++ b/plugins/woocommerce/changelog/40998-fix-coupon-title-sanitization-39481 @@ -0,0 +1,4 @@ +Significance: patch +Type: fix + +Fixed coupon errors with coupon codes containing apostrophes. \ No newline at end of file diff --git a/plugins/woocommerce/includes/class-wc-coupon.php b/plugins/woocommerce/includes/class-wc-coupon.php index 85ff11daa8e..6d699a7edb4 100644 --- a/plugins/woocommerce/includes/class-wc-coupon.php +++ b/plugins/woocommerce/includes/class-wc-coupon.php @@ -81,6 +81,15 @@ class WC_Coupon extends WC_Legacy_Coupon { */ protected $cache_group = 'coupons'; + /** + * Sorting. + * + * Used by `get_coupons_from_cart` to sort coupons. + * + * @var int + */ + public $sort = 0; + /** * Coupon constructor. Loads coupon data. * diff --git a/plugins/woocommerce/includes/wc-formatting-functions.php b/plugins/woocommerce/includes/wc-formatting-functions.php index 6a6877827c5..52084b31291 100644 --- a/plugins/woocommerce/includes/wc-formatting-functions.php +++ b/plugins/woocommerce/includes/wc-formatting-functions.php @@ -232,7 +232,7 @@ function wc_trim_zeros( $price ) { * @return float */ function wc_round_tax_total( $value, $precision = null ) { - $precision = is_null( $precision ) ? wc_get_price_decimals() : intval( $precision ); + $precision = is_null( $precision ) ? wc_get_price_decimals() : intval( $precision ); $rounded_tax = NumberUtil::round( $value, $precision, wc_get_tax_rounding_mode() ); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctionParameters.round_modeFound return apply_filters( 'wc_round_tax_total', $rounded_tax, $value, $precision, WC_TAX_ROUNDING_MODE ); @@ -371,15 +371,17 @@ function wc_format_coupon_code( $value ) { /** * Sanitize a coupon code. * - * Uses sanitize_post_field since coupon codes are stored as - * post_titles - the sanitization and escaping must match. + * Uses sanitize_post_field since coupon codes are stored as post_titles - the sanitization and escaping must match. + * + * Due to the unfiltered_html captability that some (admin) users have, we need to account for slashes. * * @since 3.6.0 * @param string $value Coupon code to format. * @return string */ function wc_sanitize_coupon_code( $value ) { - return wp_filter_kses( sanitize_post_field( 'post_title', $value ?? '', 0, 'db' ) ); + $value = wp_kses( sanitize_post_field( 'post_title', $value ?? '', 0, 'db' ), 'entities' ); + return current_user_can( 'unfiltered_html' ) ? $value : stripslashes( $value ); } /** diff --git a/plugins/woocommerce/tests/php/includes/wc-formatting-functions-test.php b/plugins/woocommerce/tests/php/includes/wc-formatting-functions-test.php index 7beda829931..20f380494e1 100644 --- a/plugins/woocommerce/tests/php/includes/wc-formatting-functions-test.php +++ b/plugins/woocommerce/tests/php/includes/wc-formatting-functions-test.php @@ -16,6 +16,7 @@ class WC_Formatting_Functions_Test extends \WC_Unit_Test_Case { 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' ) ); + $this->assertEquals( "test's", wc_sanitize_coupon_code( "test's" ) ); } /**