Merge pull request #22540 from woocommerce/update/price-slider-improvements

Make the price filter widget tax aware redux
This commit is contained in:
Mike Jolley 2019-03-06 16:47:21 +00:00 committed by GitHub
commit 95c5d145bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 47 deletions

View File

@ -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() {

View File

@ -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;

View File

@ -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' ),
)
);
} }
/** /**

View File

@ -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> &mdash; <span class="to"></span> ' . esc_html__( 'Price:', 'woocommerce' ) . ' <span class="from"></span> &mdash; <span class="to"></span>