Merge pull request #22540 from woocommerce/update/price-slider-improvements
Make the price filter widget tax aware redux
This commit is contained in:
commit
95c5d145bb
|
@ -31,8 +31,9 @@ jQuery( function( $ ) {
|
||||||
$( 'input#min_price, input#max_price' ).hide();
|
$( 'input#min_price, input#max_price' ).hide();
|
||||||
$( '.price_slider, .price_label' ).show();
|
$( '.price_slider, .price_label' ).show();
|
||||||
|
|
||||||
var min_price = $( '.price_slider_amount #min_price' ).data( 'min' ),
|
var min_price = $( '.price_slider_amount #min_price' ).data( 'min' ),
|
||||||
max_price = $( '.price_slider_amount #max_price' ).data( 'max' ),
|
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_min_price = $( '.price_slider_amount #min_price' ).val(),
|
||||||
current_max_price = $( '.price_slider_amount #max_price' ).val();
|
current_max_price = $( '.price_slider_amount #max_price' ).val();
|
||||||
|
|
||||||
|
@ -41,6 +42,7 @@ jQuery( function( $ ) {
|
||||||
animate: true,
|
animate: true,
|
||||||
min: min_price,
|
min: min_price,
|
||||||
max: max_price,
|
max: max_price,
|
||||||
|
step: step,
|
||||||
values: [ current_min_price, current_max_price ],
|
values: [ current_min_price, current_max_price ],
|
||||||
create: function() {
|
create: function() {
|
||||||
|
|
||||||
|
|
|
@ -681,7 +681,33 @@ class WC_Query {
|
||||||
*/
|
*/
|
||||||
private function price_filter_meta_query() {
|
private function price_filter_meta_query() {
|
||||||
if ( isset( $_GET['max_price'] ) || isset( $_GET['min_price'] ) ) { // WPCS: input var ok, CSRF ok.
|
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;
|
$meta_query['price_filter'] = true;
|
||||||
|
|
||||||
return $meta_query;
|
return $meta_query;
|
||||||
|
|
|
@ -786,36 +786,14 @@ function wc_get_product_visibility_options() {
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
function wc_get_min_max_price_meta_query( $args ) {
|
function wc_get_min_max_price_meta_query( $args ) {
|
||||||
$min = isset( $args['min_price'] ) ? floatval( $args['min_price'] ) : 0;
|
$current_min_price = isset( $args['min_price'] ) ? floatval( $args['min_price'] ) : 0;
|
||||||
$max = isset( $args['max_price'] ) ? floatval( $args['max_price'] ) : 9999999999;
|
$current_max_price = isset( $args['max_price'] ) ? floatval( $args['max_price'] ) : PHP_INT_MAX;
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return apply_filters(
|
return apply_filters(
|
||||||
'woocommerce_get_min_max_price_meta_query',
|
'woocommerce_get_min_max_price_meta_query',
|
||||||
array(
|
array(
|
||||||
'key' => '_price',
|
'key' => '_price',
|
||||||
'value' => array( $min, $max ),
|
'value' => array( $current_min_price, $current_max_price ),
|
||||||
'compare' => 'BETWEEN',
|
'compare' => 'BETWEEN',
|
||||||
'type' => 'DECIMAL(10,' . wc_get_price_decimals() . ')',
|
'type' => 'DECIMAL(10,' . wc_get_price_decimals() . ')',
|
||||||
),
|
),
|
||||||
|
@ -849,11 +827,14 @@ function wc_get_product_tax_class_options() {
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
function wc_get_product_stock_status_options() {
|
function wc_get_product_stock_status_options() {
|
||||||
return apply_filters( 'woocommerce_product_stock_status_options', array(
|
return apply_filters(
|
||||||
'instock' => __( 'In stock', 'woocommerce' ),
|
'woocommerce_product_stock_status_options',
|
||||||
'outofstock' => __( 'Out of stock', 'woocommerce' ),
|
array(
|
||||||
'onbackorder' => __( 'On backorder', 'woocommerce' ),
|
'instock' => __( 'In stock', 'woocommerce' ),
|
||||||
) );
|
'outofstock' => __( 'Out of stock', 'woocommerce' ),
|
||||||
|
'onbackorder' => __( 'On backorder', 'woocommerce' ),
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -68,23 +68,45 @@ class WC_Widget_Price_Filter extends WC_Widget {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$min_price = isset( $_GET['min_price'] ) ? wc_clean( wp_unslash( $_GET['min_price'] ) ) : null; // WPCS: input var ok, CSRF ok.
|
// If there are not posts and we're not filtering, hide the widget.
|
||||||
$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 && ! isset( $_GET['min_price'] ) && ! isset( $_GET['max_price'] ) ) { // WPCS: input var ok, CSRF ok.
|
||||||
if ( ! wc()->query->get_main_query()->post_count && null === $min_price && null === $max_price ) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wp_enqueue_script( 'wc-price-slider' );
|
wp_enqueue_script( 'wc-price-slider' );
|
||||||
|
|
||||||
// Find min and max price in current result set.
|
// Round values to nearest 10 by default.
|
||||||
$prices = $this->get_filtered_price();
|
$step = max( apply_filters( 'woocommerce_price_filter_widget_step', 10 ), 1 );
|
||||||
$min = floor( $prices->min_price );
|
|
||||||
$max = ceil( $prices->max_price );
|
|
||||||
|
|
||||||
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;
|
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 );
|
$this->widget_start( $args, $instance );
|
||||||
|
|
||||||
if ( '' === get_option( 'permalink_structure' ) ) {
|
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 ) ) );
|
$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 '<form method="get" action="' . esc_url( $form_action ) . '">
|
echo '<form method="get" action="' . esc_url( $form_action ) . '">
|
||||||
<div class="price_slider_wrapper">
|
<div class="price_slider_wrapper">
|
||||||
<div class="price_slider" style="display:none;"></div>
|
<div class="price_slider" style="display:none;"></div>
|
||||||
<div class="price_slider_amount">
|
<div class="price_slider_amount" data-step="' . esc_attr( $step ) . '">
|
||||||
<input type="text" id="min_price" name="min_price" value="' . esc_attr( $min_price ) . '" data-min="' . esc_attr( apply_filters( 'woocommerce_price_filter_widget_min_amount', $min ) ) . '" placeholder="' . esc_attr__( 'Min price', 'woocommerce' ) . '" />
|
<input type="text" id="min_price" name="min_price" value="' . esc_attr( $current_min_price ) . '" data-min="' . esc_attr( $min_price ) . '" placeholder="' . esc_attr__( 'Min price', 'woocommerce' ) . '" />
|
||||||
<input type="text" id="max_price" name="max_price" value="' . esc_attr( $max_price ) . '" data-max="' . esc_attr( apply_filters( 'woocommerce_price_filter_widget_max_amount', $max ) ) . '" placeholder="' . esc_attr__( 'Max price', 'woocommerce' ) . '" />
|
<input type="text" id="max_price" name="max_price" value="' . esc_attr( $current_max_price ) . '" data-max="' . esc_attr( $max_price ) . '" placeholder="' . esc_attr__( 'Max price', 'woocommerce' ) . '" />
|
||||||
<button type="submit" class="button">' . esc_html__( 'Filter', 'woocommerce' ) . '</button>
|
<button type="submit" class="button">' . esc_html__( 'Filter', 'woocommerce' ) . '</button>
|
||||||
<div class="price_label" style="display:none;">
|
<div class="price_label" style="display:none;">
|
||||||
' . esc_html__( 'Price:', 'woocommerce' ) . ' <span class="from"></span> — <span class="to"></span>
|
' . esc_html__( 'Price:', 'woocommerce' ) . ' <span class="from"></span> — <span class="to"></span>
|
||||||
|
|
Loading…
Reference in New Issue