[Product Query] Add support for the Filter By Price Block (https://github.com/woocommerce/woocommerce-blocks/pull/7162)
* Product Query: Fix pagination issue * Product Query - Add support for the Filter By Price Block woocommerce/woocommerce-blocks#6790 Product Query - Add support for the Filter By Price Block * fix query relation * fix on sale query * fix bugged pagination and on-sale filter after refactor * fix reload page when the Filter By Price block is used with All Products block * use array_intersect instead of array_merge
This commit is contained in:
parent
a97cd87ba1
commit
222407cb93
|
@ -11,5 +11,7 @@ class PriceFilter extends AbstractBlock {
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $block_name = 'price-filter';
|
||||
protected $block_name = 'price-filter';
|
||||
const MIN_PRICE_QUERY_VAR = 'min_price';
|
||||
const MAX_PRICE_QUERY_VAR = 'max_price';
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ class ProductQuery extends AbstractBlock {
|
|||
* - Hook into pre_render_block to update the query.
|
||||
*/
|
||||
protected function initialize() {
|
||||
add_filter( 'query_vars', array( $this, 'set_query_vars' ) );
|
||||
parent::initialize();
|
||||
add_filter(
|
||||
'pre_render_block',
|
||||
|
@ -63,9 +64,12 @@ class ProductQuery extends AbstractBlock {
|
|||
$this->parsed_block = $parsed_block;
|
||||
|
||||
if ( $this->is_woocommerce_variation( $parsed_block ) ) {
|
||||
// Set this so that our product filters can detect if it's a PHP template.
|
||||
$this->asset_data_registry->add( 'has_filterable_products', true, true );
|
||||
$this->asset_data_registry->add( 'is_rendering_php_template', true, true );
|
||||
add_filter(
|
||||
'query_loop_block_query_vars',
|
||||
array( $this, 'get_query_by_attributes' ),
|
||||
array( $this, 'build_query' ),
|
||||
10,
|
||||
1
|
||||
);
|
||||
|
@ -73,12 +77,12 @@ class ProductQuery extends AbstractBlock {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return a custom query based on the attributes.
|
||||
* Return a custom query based on attributes, filters and global WP_Query.
|
||||
*
|
||||
* @param WP_Query $query The WordPress Query.
|
||||
* @return array
|
||||
*/
|
||||
public function get_query_by_attributes( $query ) {
|
||||
public function build_query( $query ) {
|
||||
$parsed_block = $this->parsed_block;
|
||||
if ( ! $this->is_woocommerce_variation( $parsed_block ) ) {
|
||||
return $query;
|
||||
|
@ -90,40 +94,111 @@ class ProductQuery extends AbstractBlock {
|
|||
'posts_per_page' => $query['posts_per_page'],
|
||||
'orderby' => $query['orderby'],
|
||||
'order' => $query['order'],
|
||||
'offset' => $query['offset'],
|
||||
// Ignoring the warning of not using meta queries.
|
||||
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
'meta_query' => array(),
|
||||
);
|
||||
|
||||
do_action( 'qm/debug', $parsed_block );
|
||||
|
||||
$queries_attributes = $this->get_queries_by_attributes( $parsed_block );
|
||||
$queries_filters = $this->get_queries_by_applied_filters();
|
||||
|
||||
return array_reduce(
|
||||
array_merge(
|
||||
$queries_attributes,
|
||||
$queries_filters
|
||||
),
|
||||
function( $acc, $query ) {
|
||||
if ( isset( $query['post__in'] ) ) {
|
||||
$acc['post__in'] = isset( $acc['post__in'] ) ? array_intersect( $acc['post__in'], $query['post__in'] ) : $query['post__in'];
|
||||
}
|
||||
// Ignoring the warning of not using meta queries.
|
||||
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
$acc['meta_query'] = isset( $query['meta_query'] ) ? array_merge( $acc['meta_query'], array( $query['meta_query'] ) ) : $acc['meta_query'];
|
||||
return $acc;
|
||||
},
|
||||
$common_query_values
|
||||
);
|
||||
$on_sale_query = $this->get_on_sale_products_query( $parsed_block['attrs']['query'] );
|
||||
|
||||
return array_merge( $query, $common_query_values, $on_sale_query );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a query for on sale products.
|
||||
*
|
||||
* @param array $query_params Block query parameters.
|
||||
* @return array
|
||||
*/
|
||||
private function get_on_sale_products_query( $query_params ) {
|
||||
if ( ! isset( $query_params['__woocommerceOnSale'] ) || true !== $query_params['__woocommerceOnSale'] ) {
|
||||
return array();
|
||||
}
|
||||
private function get_on_sale_products_query() {
|
||||
return array(
|
||||
'post__in' => wc_get_product_ids_on_sale(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the query vars that are used by filter blocks.
|
||||
*
|
||||
* @param array $qvars Public query vars.
|
||||
* @return array
|
||||
*/
|
||||
public function set_query_vars( $qvars ) {
|
||||
$filter_query_args = array( PriceFilter::MIN_PRICE_QUERY_VAR, PriceFilter::MAX_PRICE_QUERY_VAR );
|
||||
return array_merge( $qvars, $filter_query_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return queries that are generated by query args
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_queries_by_applied_filters() {
|
||||
return array( 'price_filter' => $this->get_filter_by_price_query() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return queries that are generated by attributes
|
||||
*
|
||||
* @param array $parsed_block The Product Query that being rendered.
|
||||
* @return array
|
||||
*/
|
||||
private function get_queries_by_attributes( $parsed_block ) {
|
||||
$on_sale_enabled = isset( $parsed_block['attrs']['query']['__woocommerceOnSale'] ) && true === $parsed_block['attrs']['query']['__woocommerceOnSale'];
|
||||
return array(
|
||||
'on_sale' => ( $on_sale_enabled ? $this->get_on_sale_products_query() : array() ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a query that filters products by price.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_filter_by_price_query() {
|
||||
$min_price = get_query_var( PriceFilter::MIN_PRICE_QUERY_VAR );
|
||||
$max_price = get_query_var( PriceFilter::MAX_PRICE_QUERY_VAR );
|
||||
|
||||
$max_price_query = empty( $max_price ) ? array() : [
|
||||
'key' => '_price',
|
||||
'value' => $max_price,
|
||||
'compare' => '<=',
|
||||
'type' => 'numeric',
|
||||
];
|
||||
|
||||
$min_price_query = empty( $min_price ) ? array() : [
|
||||
'key' => '_price',
|
||||
'value' => $min_price,
|
||||
'compare' => '>=',
|
||||
'type' => 'numeric',
|
||||
];
|
||||
|
||||
return array(
|
||||
// Ignoring the warning of not using meta queries.
|
||||
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
'meta_query' => array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'key' => '_sale_price',
|
||||
'value' => 0,
|
||||
'compare' => '>',
|
||||
'type' => 'numeric',
|
||||
),
|
||||
array(
|
||||
'key' => '_min_variation_sale_price',
|
||||
'value' => 0,
|
||||
'compare' => '>',
|
||||
'type' => 'numeric',
|
||||
),
|
||||
'relation' => 'AND',
|
||||
$max_price_query,
|
||||
$min_price_query,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue