Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Commit

Permalink
Merge branch 'refactor/merge_queries' of https://github.com/woocommer…
Browse files Browse the repository at this point in the history
…ce/woocommerce-blocks into fix/product-query-global-query
  • Loading branch information
gigitux committed Nov 24, 2022
2 parents 6905099 + c8e315c commit e99c466
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 49 deletions.
5 changes: 0 additions & 5 deletions assets/js/blocks/product-query/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,10 @@ export const QUERY_LOOP_ID = 'core/query';
export const DEFAULT_CORE_ALLOWED_CONTROLS = [ 'taxQuery', 'search' ];

export const ALL_PRODUCT_QUERY_CONTROLS = [
<<<<<<< HEAD
'onSale',
'stockStatus',
'wooInherit',
=======
'presets',
'onSale',
'stockStatus',
>>>>>>> 78228fb4323bdec4fccf68ae5ce67e118296dc93
];

export const DEFAULT_ALLOWED_CONTROLS = [
Expand Down
137 changes: 93 additions & 44 deletions src/BlockTypes/ProductQuery.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;

use WP_Query;

// phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_tax_query
// phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_query
// phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_key
Expand Down Expand Up @@ -132,41 +134,105 @@ public function build_query( $query ) {
'tax_query' => array(),
);

$queries_by_attributes = $this->get_queries_by_attributes( $parsed_block );
$queries_by_filters = $this->get_queries_by_applied_filters();
$global_query = $this->get_global_query( $parsed_block );
$orderby_query = $this->get_custom_orderby_query( $query['orderby'] );

$base_query = array_merge(
return $this->merge_queries(
$common_query_values,
$orderby_query
$this->get_global_query( $parsed_block ),
$this->get_custom_orderby_query( $query['orderby'] ),
$this->get_queries_by_attributes( $parsed_block ),
$this->get_queries_by_applied_filters()
);
}

return array_reduce(
array_merge(
$queries_by_attributes,
$queries_by_filters
/**
* Return the product ids based on the attributes.
*
* @param array $parsed_block The block being rendered.
* @return array
*/
private function get_products_ids_by_attributes( $parsed_block ) {
$query = $this->merge_queries(
array(
'post_type' => 'product',
'post__in' => array(),
'post_status' => 'publish',
'posts_per_page' => -1,
'meta_query' => array(),
'tax_query' => array(),
),
function( $acc, $query ) {
return $this->merge_queries( $acc, $query );
},
$base_query
$this->get_queries_by_attributes( $parsed_block )
);

$products = new \WP_Query( $query );
$post_ids = wp_list_pluck( $products->posts, 'ID' );

return $post_ids;
}

/**
* Merge in the first parameter the keys "post_in", "meta_query" and "tax_query" of the second parameter.
*
* @param array $a The first query.
* @param array $b The second query.
* @param array[] ...$queries Query arrays to be merged.
* @return array
*/
private function merge_queries( $a, $b ) {
$a['post__in'] = ( isset( $b['post__in'] ) && ! empty( $b['post__in'] ) ) ? $this->intersect_arrays_when_not_empty( $a['post__in'], $b['post__in'] ) : $a['post__in'];
$a['meta_query'] = ( isset( $b['meta_query'] ) && ! empty( $b['meta_query'] ) ) ? array_merge( $a['meta_query'], array( $b['meta_query'] ) ) : $a['meta_query'];
$a['tax_query'] = ( isset( $b['tax_query'] ) && ! empty( $b['tax_query'] ) ) ? array_merge( $a['tax_query'], array( $b['tax_query'] ) ) : $a['tax_query'];
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(
$queries,
function( $acc, $query ) use ( $valid_query_vars ) {
if ( ! is_array( $query ) ) {
return $acc;
}
if ( empty( array_intersect( $valid_query_vars, array_keys( $query ) ) ) ) {
return $this->merge_queries( $acc, ...array_values( $query ) );
}
return array_merge_recursive( $acc, $query );
},
array()
);

return $a;
/**
* If there are duplicated items in post__in, it means that we need to
* use the intersection of the results, which in this case, are the
* duplicated items.
*/
if (
! empty( $merged_query['post__in'] ) &&
count( $merged_query['post__in'] ) > count( array_unique( $merged_query['post__in'] ) )
) {
$merged_query['post__in'] = array_unique(
array_diff(
$merged_query['post__in'],
array_unique( $merged_query['post__in'] )
)
);
}

return $merged_query;
}

/**
Expand Down Expand Up @@ -267,9 +333,11 @@ private function get_custom_orderby_query( $orderby ) {
private function get_stock_status_query( $stock_statii ) {
return array(
'meta_query' => array(
'key' => '_stock_status',
'value' => (array) $stock_statii,
'compare' => 'IN',
array(
'key' => '_stock_status',
'value' => (array) $stock_statii,
'compare' => 'IN',
),
),
);
}
Expand Down Expand Up @@ -501,25 +569,6 @@ function( $stock_status ) {
);
}

/**
* Intersect arrays neither of them are empty, otherwise merge them.
*
* @param array ...$arrays Arrays.
* @return array
*/
private function intersect_arrays_when_not_empty( ...$arrays ) {
return array_reduce(
$arrays,
function( $acc, $array ) {
if ( ! empty( $array ) && ! empty( $acc ) ) {
return array_intersect( $acc, $array );
}
return array_merge( $acc, $array );
},
array()
);
}

/**
* Get product-related query variables from the global query.
*
Expand Down

0 comments on commit e99c466

Please sign in to comment.