Refactor `ProductQuery::merge_queries` to accept multiple queries (https://github.com/woocommerce/woocommerce-blocks/pull/7697)
This commit is contained in:
parent
58423a2025
commit
653e838d79
|
@ -48,6 +48,13 @@ class ProductQuery extends AbstractBlock {
|
||||||
*/
|
*/
|
||||||
protected $is_custom_inherit_global_query_implementation_enabled = false;
|
protected $is_custom_inherit_global_query_implementation_enabled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All query args from WP_Query.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $valid_query_vars;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize this block type.
|
* Initialize this block type.
|
||||||
*
|
*
|
||||||
|
@ -186,42 +193,17 @@ class ProductQuery extends AbstractBlock {
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function merge_queries( ...$queries ) {
|
private function merge_queries( ...$queries ) {
|
||||||
$valid_query_vars = array_keys( ( new WP_Query() )->fill_query_vars( array() ) );
|
|
||||||
$valid_query_vars = array_merge(
|
|
||||||
$valid_query_vars,
|
|
||||||
// fill_query_vars doesn't include these vars so we need to add them manually.
|
|
||||||
array(
|
|
||||||
'date_query',
|
|
||||||
'exact',
|
|
||||||
'ignore_sticky_posts',
|
|
||||||
'lazy_load_term_meta',
|
|
||||||
'meta_compare_key',
|
|
||||||
'meta_compare',
|
|
||||||
'meta_query',
|
|
||||||
'meta_type_key',
|
|
||||||
'meta_type',
|
|
||||||
'nopaging',
|
|
||||||
'offset',
|
|
||||||
'order',
|
|
||||||
'orderby',
|
|
||||||
'page',
|
|
||||||
'post_type',
|
|
||||||
'posts_per_page',
|
|
||||||
'suppress_filters',
|
|
||||||
'tax_query',
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$merged_query = array_reduce(
|
$merged_query = array_reduce(
|
||||||
$queries,
|
$queries,
|
||||||
function( $acc, $query ) use ( $valid_query_vars ) {
|
function( $acc, $query ) {
|
||||||
if ( ! is_array( $query ) ) {
|
if ( ! is_array( $query ) ) {
|
||||||
return $acc;
|
return $acc;
|
||||||
}
|
}
|
||||||
if ( empty( array_intersect( $valid_query_vars, array_keys( $query ) ) ) ) {
|
// If the $query doesn't contain any valid query keys, we unpack/spread it then merge.
|
||||||
|
if ( empty( array_intersect( $this->get_valid_query_vars(), array_keys( $query ) ) ) ) {
|
||||||
return $this->merge_queries( $acc, ...array_values( $query ) );
|
return $this->merge_queries( $acc, ...array_values( $query ) );
|
||||||
}
|
}
|
||||||
return array_merge_recursive( $acc, $query );
|
return $this->array_merge_recursive_replace_non_array_properties( $acc, $query );
|
||||||
},
|
},
|
||||||
array()
|
array()
|
||||||
);
|
);
|
||||||
|
@ -450,10 +432,12 @@ class ProductQuery extends AbstractBlock {
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'meta_query' => array(
|
'meta_query' => array(
|
||||||
|
array(
|
||||||
'relation' => 'AND',
|
'relation' => 'AND',
|
||||||
$max_price_query,
|
$max_price_query,
|
||||||
$min_price_query,
|
$min_price_query,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,9 +483,11 @@ class ProductQuery extends AbstractBlock {
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'tax_query' => array(
|
'tax_query' => array(
|
||||||
|
array(
|
||||||
'relation' => 'AND',
|
'relation' => 'AND',
|
||||||
$queries,
|
$queries,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,6 +528,112 @@ class ProductQuery extends AbstractBlock {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return or initialize $valid_query_vars.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function get_valid_query_vars() {
|
||||||
|
if ( ! empty( $this->valid_query_vars ) ) {
|
||||||
|
return $this->valid_query_vars;
|
||||||
|
}
|
||||||
|
|
||||||
|
$valid_query_vars = array_keys( ( new WP_Query() )->fill_query_vars( array() ) );
|
||||||
|
$this->valid_query_vars = array_merge(
|
||||||
|
$valid_query_vars,
|
||||||
|
// fill_query_vars doesn't include these vars so we need to add them manually.
|
||||||
|
array(
|
||||||
|
'date_query',
|
||||||
|
'exact',
|
||||||
|
'ignore_sticky_posts',
|
||||||
|
'lazy_load_term_meta',
|
||||||
|
'meta_compare_key',
|
||||||
|
'meta_compare',
|
||||||
|
'meta_query',
|
||||||
|
'meta_type_key',
|
||||||
|
'meta_type',
|
||||||
|
'nopaging',
|
||||||
|
'offset',
|
||||||
|
'order',
|
||||||
|
'orderby',
|
||||||
|
'page',
|
||||||
|
'post_type',
|
||||||
|
'posts_per_page',
|
||||||
|
'suppress_filters',
|
||||||
|
'tax_query',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->valid_query_vars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge two array recursively but replace the non-array values instead of
|
||||||
|
* merging them. The merging strategy:
|
||||||
|
*
|
||||||
|
* - If keys from merge array doesn't exist in the base array, create them.
|
||||||
|
* - For array items with numeric keys, we merge them as normal.
|
||||||
|
* - For array items with string keys:
|
||||||
|
*
|
||||||
|
* - If the value isn't array, we'll use the value comming from the merge array.
|
||||||
|
* $base = ['orderby' => 'date']
|
||||||
|
* $new = ['orderby' => 'meta_value_num']
|
||||||
|
* Result: ['orderby' => 'meta_value_num']
|
||||||
|
*
|
||||||
|
* - If the value is array, we'll use recursion to merge each key.
|
||||||
|
* $base = ['meta_query' => [
|
||||||
|
* [
|
||||||
|
* 'key' => '_stock_status',
|
||||||
|
* 'compare' => 'IN'
|
||||||
|
* 'value' => ['instock', 'onbackorder']
|
||||||
|
* ]
|
||||||
|
* ]]
|
||||||
|
* $new = ['meta_query' => [
|
||||||
|
* [
|
||||||
|
* 'relation' => 'AND',
|
||||||
|
* [...<max_price_query>],
|
||||||
|
* [...<min_price_query>],
|
||||||
|
* ]
|
||||||
|
* ]]
|
||||||
|
* Result: ['meta_query' => [
|
||||||
|
* [
|
||||||
|
* 'key' => '_stock_status',
|
||||||
|
* 'compare' => 'IN'
|
||||||
|
* 'value' => ['instock', 'onbackorder']
|
||||||
|
* ],
|
||||||
|
* [
|
||||||
|
* 'relation' => 'AND',
|
||||||
|
* [...<max_price_query>],
|
||||||
|
* [...<min_price_query>],
|
||||||
|
* ]
|
||||||
|
* ]]
|
||||||
|
*
|
||||||
|
* $base = ['post__in' => [1, 2, 3, 4, 5]]
|
||||||
|
* $new = ['post__in' => [3, 4, 5, 6, 7]]
|
||||||
|
* Result: ['post__in' => [1, 2, 3, 4, 5, 3, 4, 5, 6, 7]]
|
||||||
|
*
|
||||||
|
* @param array $base First array.
|
||||||
|
* @param array $new Second array.
|
||||||
|
*/
|
||||||
|
private function array_merge_recursive_replace_non_array_properties( $base, $new ) {
|
||||||
|
foreach ( $new as $key => $value ) {
|
||||||
|
if ( is_numeric( $key ) ) {
|
||||||
|
$base[] = $value;
|
||||||
|
} else {
|
||||||
|
if ( is_array( $value ) ) {
|
||||||
|
if ( ! isset( $base[ $key ] ) ) {
|
||||||
|
$base[ $key ] = array();
|
||||||
|
}
|
||||||
|
$base[ $key ] = $this->array_merge_recursive_replace_non_array_properties( $base[ $key ], $value );
|
||||||
|
} else {
|
||||||
|
$base[ $key ] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $base;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get product-related query variables from the global query.
|
* Get product-related query variables from the global query.
|
||||||
*
|
*
|
||||||
|
@ -582,3 +674,4 @@ class ProductQuery extends AbstractBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue