diff --git a/assets/js/frontend/price-slider.js b/assets/js/frontend/price-slider.js index 682a2255d6f..3b89b117c8b 100644 --- a/assets/js/frontend/price-slider.js +++ b/assets/js/frontend/price-slider.js @@ -31,8 +31,9 @@ jQuery( function( $ ) { $( 'input#min_price, input#max_price' ).hide(); $( '.price_slider, .price_label' ).show(); - var min_price = $( '.price_slider_amount #min_price' ).data( 'min' ), - max_price = $( '.price_slider_amount #max_price' ).data( 'max' ), + var min_price = $( '.price_slider_amount #min_price' ).data( 'min' ), + max_price = $( '.price_slider_amount #max_price' ).data( 'max' ), + step = $( '.price_slider_amount' ).data( 'step' ) || 1, current_min_price = $( '.price_slider_amount #min_price' ).val(), current_max_price = $( '.price_slider_amount #max_price' ).val(); @@ -41,6 +42,7 @@ jQuery( function( $ ) { animate: true, min: min_price, max: max_price, + step: step, values: [ current_min_price, current_max_price ], create: function() { diff --git a/includes/class-wc-query.php b/includes/class-wc-query.php index 3c88200ef9e..6b3b42dd68f 100644 --- a/includes/class-wc-query.php +++ b/includes/class-wc-query.php @@ -681,7 +681,33 @@ class WC_Query { */ private function price_filter_meta_query() { if ( isset( $_GET['max_price'] ) || isset( $_GET['min_price'] ) ) { // WPCS: input var ok, CSRF ok. - $meta_query = wc_get_min_max_price_meta_query( $_GET ); // WPCS: input var ok, CSRF ok. + $current_min_price = isset( $_GET['min_price'] ) ? floatval( wp_unslash( $_GET['min_price'] ) ) : 0; // WPCS: input var ok, CSRF ok. + $current_max_price = isset( $_GET['max_price'] ) ? floatval( wp_unslash( $_GET['max_price'] ) ) : 9999999999; // WPCS: input var ok, CSRF ok. + + /** + * Adjust if the store taxes are not displayed how they are stored. + * Kicks in when prices excluding tax are displayed including tax. + */ + if ( wc_tax_enabled() && 'incl' === get_option( 'woocommerce_tax_display_shop' ) && ! wc_prices_include_tax() ) { + $tax_class = apply_filters( 'woocommerce_price_filter_widget_tax_class', '' ); // Uses standard tax class. + $tax_rates = WC_Tax::get_rates( $tax_class ); + + if ( $tax_rates ) { + $current_min_price -= WC_Tax::get_tax_total( WC_Tax::calc_inclusive_tax( $current_min_price, $tax_rates ) ); + $current_max_price -= WC_Tax::get_tax_total( WC_Tax::calc_inclusive_tax( $current_max_price, $tax_rates ) ); + } + } + + $step = max( apply_filters( 'woocommerce_price_filter_widget_step', 10 ), 1 ); + $current_min_price = floor( $current_min_price / $step ) * $step; + $current_max_price = ceil( $current_max_price / $step ) * $step; + + $meta_query = wc_get_min_max_price_meta_query( + array( + 'min_price' => $current_min_price, + 'max_price' => $current_max_price, + ) + ); // WPCS: input var ok, CSRF ok. $meta_query['price_filter'] = true; return $meta_query; diff --git a/includes/wc-product-functions.php b/includes/wc-product-functions.php index 0d7312f176d..44d6561ee8e 100644 --- a/includes/wc-product-functions.php +++ b/includes/wc-product-functions.php @@ -786,36 +786,14 @@ function wc_get_product_visibility_options() { * @return array */ function wc_get_min_max_price_meta_query( $args ) { - $min = isset( $args['min_price'] ) ? floatval( $args['min_price'] ) : 0; - $max = isset( $args['max_price'] ) ? floatval( $args['max_price'] ) : 9999999999; - - /** - * Adjust if the store taxes are not displayed how they are stored. - * Kicks in when prices excluding tax are displayed including tax. - */ - if ( wc_tax_enabled() && 'incl' === get_option( 'woocommerce_tax_display_shop' ) && ! wc_prices_include_tax() ) { - $tax_classes = array_merge( array( '' ), WC_Tax::get_tax_classes() ); - $class_min = $min; - $class_max = $max; - - foreach ( $tax_classes as $tax_class ) { - $tax_rates = WC_Tax::get_rates( $tax_class ); - - if ( $tax_rates ) { - $class_min = $min + WC_Tax::get_tax_total( WC_Tax::calc_exclusive_tax( $min, $tax_rates ) ); - $class_max = $max - WC_Tax::get_tax_total( WC_Tax::calc_exclusive_tax( $max, $tax_rates ) ); - } - } - - $min = $class_min; - $max = $class_max; - } + $current_min_price = isset( $args['min_price'] ) ? floatval( $args['min_price'] ) : 0; + $current_max_price = isset( $args['max_price'] ) ? floatval( $args['max_price'] ) : PHP_INT_MAX; return apply_filters( 'woocommerce_get_min_max_price_meta_query', array( 'key' => '_price', - 'value' => array( $min, $max ), + 'value' => array( $current_min_price, $current_max_price ), 'compare' => 'BETWEEN', 'type' => 'DECIMAL(10,' . wc_get_price_decimals() . ')', ), @@ -849,11 +827,14 @@ function wc_get_product_tax_class_options() { * @return array */ function wc_get_product_stock_status_options() { - return apply_filters( 'woocommerce_product_stock_status_options', array( - 'instock' => __( 'In stock', 'woocommerce' ), - 'outofstock' => __( 'Out of stock', 'woocommerce' ), - 'onbackorder' => __( 'On backorder', 'woocommerce' ), - ) ); + return apply_filters( + 'woocommerce_product_stock_status_options', + array( + 'instock' => __( 'In stock', 'woocommerce' ), + 'outofstock' => __( 'Out of stock', 'woocommerce' ), + 'onbackorder' => __( 'On backorder', 'woocommerce' ), + ) + ); } /** diff --git a/includes/widgets/class-wc-widget-price-filter.php b/includes/widgets/class-wc-widget-price-filter.php index 6014dad2890..4eb70173547 100644 --- a/includes/widgets/class-wc-widget-price-filter.php +++ b/includes/widgets/class-wc-widget-price-filter.php @@ -68,23 +68,45 @@ class WC_Widget_Price_Filter extends WC_Widget { return; } - $min_price = isset( $_GET['min_price'] ) ? wc_clean( wp_unslash( $_GET['min_price'] ) ) : null; // WPCS: input var ok, CSRF ok. - $max_price = isset( $_GET['max_price'] ) ? wc_clean( wp_unslash( $_GET['max_price'] ) ) : null; // WPCS: input var ok, CSRF ok. - if ( ! wc()->query->get_main_query()->post_count && null === $min_price && null === $max_price ) { + // If there are not posts and we're not filtering, hide the widget. + if ( ! WC()->query->get_main_query()->post_count && ! isset( $_GET['min_price'] ) && ! isset( $_GET['max_price'] ) ) { // WPCS: input var ok, CSRF ok. return; } wp_enqueue_script( 'wc-price-slider' ); - // Find min and max price in current result set. - $prices = $this->get_filtered_price(); - $min = floor( $prices->min_price ); - $max = ceil( $prices->max_price ); + // Round values to nearest 10 by default. + $step = max( apply_filters( 'woocommerce_price_filter_widget_step', 10 ), 1 ); - if ( $min === $max ) { + // Find min and max price in current result set. + $prices = $this->get_filtered_price(); + $min_price = $prices->min_price; + $max_price = $prices->max_price; + + // Check to see if we should add taxes to the prices if store are excl tax but display incl. + $tax_display_mode = get_option( 'woocommerce_tax_display_shop' ); + + if ( wc_tax_enabled() && ! wc_prices_include_tax() && 'incl' === $tax_display_mode ) { + $tax_class = apply_filters( 'woocommerce_price_filter_widget_tax_class', '' ); // Uses standard tax class. + $tax_rates = WC_Tax::get_rates( $tax_class ); + + if ( $tax_rates ) { + $min_price += WC_Tax::get_tax_total( WC_Tax::calc_exclusive_tax( $min_price, $tax_rates ) ); + $max_price += WC_Tax::get_tax_total( WC_Tax::calc_exclusive_tax( $max_price, $tax_rates ) ); + } + } + + $min_price = apply_filters( 'woocommerce_price_filter_widget_min_amount', floor( $min_price / $step ) * $step ); + $max_price = apply_filters( 'woocommerce_price_filter_widget_max_amount', ceil( $max_price / $step ) * $step ); + + // If both min and max are equal, we don't need a slider. + if ( $min_price === $max_price ) { return; } + $current_min_price = isset( $_GET['min_price'] ) ? floor( floatval( wp_unslash( $_GET['min_price'] ) ) / $step ) * $step : $min_price; // WPCS: input var ok, CSRF ok. + $current_max_price = isset( $_GET['max_price'] ) ? ceil( floatval( wp_unslash( $_GET['max_price'] ) ) / $step ) * $step : $max_price; // WPCS: input var ok, CSRF ok. + $this->widget_start( $args, $instance ); if ( '' === get_option( 'permalink_structure' ) ) { @@ -93,15 +115,12 @@ class WC_Widget_Price_Filter extends WC_Widget { $form_action = preg_replace( '%\/page/[0-9]+%', '', home_url( trailingslashit( $wp->request ) ) ); } - $min_price = null !== $min_price ? $min_price : apply_filters( 'woocommerce_price_filter_widget_min_amount', $min ); - $max_price = null !== $max_price ? $max_price : apply_filters( 'woocommerce_price_filter_widget_max_amount', $max ); - echo '
-
- - +
+ +