Product Query: Add product visibility query support (https://github.com/woocommerce/woocommerce-blocks/pull/7951)
This commit is contained in:
parent
e22d6e7fcf
commit
b02b7f9348
|
@ -127,8 +127,9 @@ class ProductQuery extends AbstractBlock {
|
||||||
$orderby_query = isset( $orderby ) ? $this->get_custom_orderby_query( $orderby ) : array();
|
$orderby_query = isset( $orderby ) ? $this->get_custom_orderby_query( $orderby ) : array();
|
||||||
$attributes_query = is_array( $woo_attributes ) ? $this->get_product_attributes_query( $woo_attributes ) : array();
|
$attributes_query = is_array( $woo_attributes ) ? $this->get_product_attributes_query( $woo_attributes ) : array();
|
||||||
$stock_query = is_array( $woo_stock_status ) ? $this->get_stock_status_query( $woo_stock_status ) : array();
|
$stock_query = is_array( $woo_stock_status ) ? $this->get_stock_status_query( $woo_stock_status ) : array();
|
||||||
|
$visibility_query = $this->get_product_visibility_query( $stock_query );
|
||||||
|
|
||||||
return array_merge( $args, $on_sale_query, $orderby_query, $attributes_query, $stock_query );
|
return array_merge( $args, $on_sale_query, $orderby_query, $attributes_query, $stock_query, $visibility_query );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -325,6 +326,34 @@ class ProductQuery extends AbstractBlock {
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function get_stock_status_query( $stock_statii ) {
|
private function get_stock_status_query( $stock_statii ) {
|
||||||
|
if ( ! is_array( $stock_statii ) ) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$stock_status_options = array_keys( wc_get_product_stock_status_options() );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If all available stock status are selected, we don't need to add the
|
||||||
|
* meta query for stock status.
|
||||||
|
*/
|
||||||
|
if (
|
||||||
|
count( $stock_statii ) === count( $stock_status_options ) &&
|
||||||
|
array_diff( $stock_statii, $stock_status_options ) === array_diff( $stock_status_options, $stock_statii )
|
||||||
|
) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If all stock statuses are selected except 'outofstock', we use the
|
||||||
|
* product visibility query to filter out out of stock products.
|
||||||
|
*
|
||||||
|
* @see get_product_visibility_query()
|
||||||
|
*/
|
||||||
|
$diff = array_diff( $stock_status_options, $stock_statii );
|
||||||
|
if ( count( $diff ) === 1 && in_array( 'outofstock', $diff, true ) ) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'meta_query' => array(
|
'meta_query' => array(
|
||||||
array(
|
array(
|
||||||
|
@ -336,6 +365,34 @@ class ProductQuery extends AbstractBlock {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a query for product visibility depending on their stock status.
|
||||||
|
*
|
||||||
|
* @param array $stock_query Stock status query.
|
||||||
|
*
|
||||||
|
* @return array Tax query for product visibility.
|
||||||
|
*/
|
||||||
|
private function get_product_visibility_query( $stock_query ) {
|
||||||
|
$product_visibility_terms = wc_get_product_visibility_term_ids();
|
||||||
|
$product_visibility_not_in = array( is_search() ? $product_visibility_terms['exclude-from-search'] : $product_visibility_terms['exclude-from-catalog'] );
|
||||||
|
|
||||||
|
// Hide out of stock products.
|
||||||
|
if ( empty( $stock_query ) && 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) ) {
|
||||||
|
$product_visibility_not_in[] = $product_visibility_terms['outofstock'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'tax_query' => array(
|
||||||
|
array(
|
||||||
|
'taxonomy' => 'product_visibility',
|
||||||
|
'field' => 'term_taxonomy_id',
|
||||||
|
'terms' => $product_visibility_not_in,
|
||||||
|
'operator' => 'NOT IN',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the query vars that are used by filter blocks.
|
* Set the query vars that are used by filter blocks.
|
||||||
*
|
*
|
||||||
|
@ -439,11 +496,13 @@ class ProductQuery extends AbstractBlock {
|
||||||
$on_sale_enabled = isset( $query['__woocommerceOnSale'] ) && true === $query['__woocommerceOnSale'];
|
$on_sale_enabled = isset( $query['__woocommerceOnSale'] ) && true === $query['__woocommerceOnSale'];
|
||||||
$attributes_query = isset( $query['__woocommerceAttributes'] ) ? $this->get_product_attributes_query( $query['__woocommerceAttributes'] ) : array();
|
$attributes_query = isset( $query['__woocommerceAttributes'] ) ? $this->get_product_attributes_query( $query['__woocommerceAttributes'] ) : array();
|
||||||
$stock_query = isset( $query['__woocommerceStockStatus'] ) ? $this->get_stock_status_query( $query['__woocommerceStockStatus'] ) : array();
|
$stock_query = isset( $query['__woocommerceStockStatus'] ) ? $this->get_stock_status_query( $query['__woocommerceStockStatus'] ) : array();
|
||||||
|
$visibility_query = $this->get_product_visibility_query( $stock_query );
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'on_sale' => ( $on_sale_enabled ? $this->get_on_sale_products_query() : array() ),
|
'on_sale' => ( $on_sale_enabled ? $this->get_on_sale_products_query() : array() ),
|
||||||
'attributes' => $attributes_query,
|
'attributes' => $attributes_query,
|
||||||
'stock_status' => $stock_query,
|
'stock_status' => $stock_query,
|
||||||
|
'visibility' => $visibility_query,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,10 @@ class ProductQuery extends \WP_UnitTestCase {
|
||||||
foreach ( $on_sale_product_ids as $id ) {
|
foreach ( $on_sale_product_ids as $id ) {
|
||||||
$this->assertContainsEquals( $id, $merged_query['post__in'] );
|
$this->assertContainsEquals( $id, $merged_query['post__in'] );
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->assertCount( 4, $merged_query['post__in'] );
|
$this->assertCount( 4, $merged_query['post__in'] );
|
||||||
|
|
||||||
|
delete_transient( 'wc_products_onsale' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -112,24 +115,34 @@ class ProductQuery extends \WP_UnitTestCase {
|
||||||
),
|
),
|
||||||
$merged_query['meta_query']
|
$merged_query['meta_query']
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test merging default stock queries that should use product visibility
|
||||||
|
* queries instead of meta query for stock status.
|
||||||
|
*/
|
||||||
|
public function test_merging_default_stock_queries() {
|
||||||
|
$parsed_block = $this->get_base_parsed_block();
|
||||||
|
$parsed_block['attrs']['query']['__woocommerceStockStatus'] = array(
|
||||||
|
'instock',
|
||||||
|
'outofstock',
|
||||||
|
'onbackorder',
|
||||||
|
);
|
||||||
|
|
||||||
|
$merged_query = $this->initialize_merged_query( $parsed_block );
|
||||||
|
|
||||||
|
$this->assertEmpty( $merged_query['meta_query'] );
|
||||||
|
|
||||||
|
// Test with hide out of stock items option enabled.
|
||||||
$parsed_block = $this->get_base_parsed_block();
|
$parsed_block = $this->get_base_parsed_block();
|
||||||
$parsed_block['attrs']['query']['__woocommerceStockStatus'] = array(
|
$parsed_block['attrs']['query']['__woocommerceStockStatus'] = array(
|
||||||
'instock',
|
'instock',
|
||||||
'onbackorder',
|
'onbackorder',
|
||||||
);
|
);
|
||||||
$this->block_instance->set_parsed_block( $parsed_block );
|
|
||||||
|
|
||||||
$merged_query = $this->block_instance->build_query( $parsed_block['attrs']['query'] );
|
$merged_query = $this->initialize_merged_query( $parsed_block );
|
||||||
|
|
||||||
$this->assertContainsEquals(
|
$this->assertEmpty( $merged_query['meta_query'] );
|
||||||
array(
|
|
||||||
'compare' => 'IN',
|
|
||||||
'key' => '_stock_status',
|
|
||||||
'value' => array( 'instock', 'onbackorder' ),
|
|
||||||
),
|
|
||||||
$merged_query['meta_query']
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -201,6 +214,57 @@ class ProductQuery extends \WP_UnitTestCase {
|
||||||
$this->assertEquals( 'total_sales', $merged_query['meta_key'] );
|
$this->assertEquals( 'total_sales', $merged_query['meta_key'] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test product visibility query exist in merged query.
|
||||||
|
*/
|
||||||
|
public function test_product_visibility_query_exist_in_merged_query() {
|
||||||
|
$product_visibility_terms = wc_get_product_visibility_term_ids();
|
||||||
|
$product_visibility_not_in = array( is_search() ? $product_visibility_terms['exclude-from-search'] : $product_visibility_terms['exclude-from-catalog'] );
|
||||||
|
|
||||||
|
$parsed_block = $this->get_base_parsed_block();
|
||||||
|
|
||||||
|
$merged_query = $this->initialize_merged_query( $parsed_block );
|
||||||
|
|
||||||
|
$this->assertContainsEquals(
|
||||||
|
array(
|
||||||
|
'taxonomy' => 'product_visibility',
|
||||||
|
'field' => 'term_taxonomy_id',
|
||||||
|
'terms' => $product_visibility_not_in,
|
||||||
|
'operator' => 'NOT IN',
|
||||||
|
),
|
||||||
|
$merged_query['tax_query']
|
||||||
|
);
|
||||||
|
|
||||||
|
$fn = function() {
|
||||||
|
return 'yes';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test with hide out of stock items option enabled.
|
||||||
|
add_filter(
|
||||||
|
'pre_option_woocommerce_hide_out_of_stock_items',
|
||||||
|
$fn
|
||||||
|
);
|
||||||
|
$product_visibility_not_in[] = $product_visibility_terms['outofstock'];
|
||||||
|
|
||||||
|
$parsed_block = $this->get_base_parsed_block();
|
||||||
|
|
||||||
|
$merged_query = $this->initialize_merged_query( $parsed_block );
|
||||||
|
|
||||||
|
$this->assertContainsEquals(
|
||||||
|
array(
|
||||||
|
'taxonomy' => 'product_visibility',
|
||||||
|
'field' => 'term_taxonomy_id',
|
||||||
|
'terms' => $product_visibility_not_in,
|
||||||
|
'operator' => 'NOT IN',
|
||||||
|
),
|
||||||
|
$merged_query['tax_query']
|
||||||
|
);
|
||||||
|
remove_filter(
|
||||||
|
'pre_option_woocommerce_hide_out_of_stock_items',
|
||||||
|
$fn
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test merging multiple queries.
|
* Test merging multiple queries.
|
||||||
*/
|
*/
|
||||||
|
@ -209,7 +273,7 @@ class ProductQuery extends \WP_UnitTestCase {
|
||||||
$parsed_block['attrs']['query']['orderBy'] = 'rating';
|
$parsed_block['attrs']['query']['orderBy'] = 'rating';
|
||||||
$parsed_block['attrs']['query']['__woocommerceStockStatus'] = array(
|
$parsed_block['attrs']['query']['__woocommerceStockStatus'] = array(
|
||||||
'instock',
|
'instock',
|
||||||
'onbackorder',
|
'outofstock',
|
||||||
);
|
);
|
||||||
$parsed_block['attrs']['query']['__woocommerceAttributes'] = array(
|
$parsed_block['attrs']['query']['__woocommerceAttributes'] = array(
|
||||||
array(
|
array(
|
||||||
|
@ -230,7 +294,7 @@ class ProductQuery extends \WP_UnitTestCase {
|
||||||
array(
|
array(
|
||||||
'compare' => 'IN',
|
'compare' => 'IN',
|
||||||
'key' => '_stock_status',
|
'key' => '_stock_status',
|
||||||
'value' => array( 'instock', 'onbackorder' ),
|
'value' => array( 'instock', 'outofstock' ),
|
||||||
),
|
),
|
||||||
$merged_query['meta_query']
|
$merged_query['meta_query']
|
||||||
);
|
);
|
||||||
|
@ -266,6 +330,7 @@ class ProductQuery extends \WP_UnitTestCase {
|
||||||
),
|
),
|
||||||
$merged_query['meta_query']
|
$merged_query['meta_query']
|
||||||
);
|
);
|
||||||
|
set_query_var( 'max_price', '' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -289,6 +354,7 @@ class ProductQuery extends \WP_UnitTestCase {
|
||||||
),
|
),
|
||||||
$merged_query['meta_query']
|
$merged_query['meta_query']
|
||||||
);
|
);
|
||||||
|
set_query_var( 'min_price', '' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -318,6 +384,9 @@ class ProductQuery extends \WP_UnitTestCase {
|
||||||
),
|
),
|
||||||
$merged_query['meta_query']
|
$merged_query['meta_query']
|
||||||
);
|
);
|
||||||
|
|
||||||
|
set_query_var( 'max_price', '' );
|
||||||
|
set_query_var( 'min_price', '' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -336,6 +405,8 @@ class ProductQuery extends \WP_UnitTestCase {
|
||||||
),
|
),
|
||||||
$merged_query['meta_query']
|
$merged_query['meta_query']
|
||||||
);
|
);
|
||||||
|
|
||||||
|
set_query_var( 'filter_stock_status', '' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -363,8 +434,16 @@ class ProductQuery extends \WP_UnitTestCase {
|
||||||
|
|
||||||
$merged_query = $this->initialize_merged_query();
|
$merged_query = $this->initialize_merged_query();
|
||||||
|
|
||||||
$attribute_tax_query = $merged_query['tax_query'][0];
|
$attribute_tax_query = array();
|
||||||
|
|
||||||
|
foreach ( $merged_query['tax_query'] as $tax_query ) {
|
||||||
|
if ( isset( $tax_query['relation'] ) ) {
|
||||||
|
$attribute_tax_query = $tax_query;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$attribute_tax_query_queries = $attribute_tax_query[0];
|
$attribute_tax_query_queries = $attribute_tax_query[0];
|
||||||
|
|
||||||
$this->assertEquals( 'AND', $attribute_tax_query['relation'] );
|
$this->assertEquals( 'AND', $attribute_tax_query['relation'] );
|
||||||
|
|
||||||
$this->assertContainsEquals(
|
$this->assertContainsEquals(
|
||||||
|
@ -385,6 +464,11 @@ class ProductQuery extends \WP_UnitTestCase {
|
||||||
),
|
),
|
||||||
$attribute_tax_query_queries
|
$attribute_tax_query_queries
|
||||||
);
|
);
|
||||||
|
|
||||||
|
set_query_var( 'filter_color', '' );
|
||||||
|
set_query_var( 'query_type_color', '' );
|
||||||
|
set_query_var( 'filter_size', '' );
|
||||||
|
set_query_var( 'query_type_size', '' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -424,6 +508,10 @@ class ProductQuery extends \WP_UnitTestCase {
|
||||||
),
|
),
|
||||||
$merged_query['meta_query']
|
$merged_query['meta_query']
|
||||||
);
|
);
|
||||||
|
|
||||||
|
set_query_var( 'max_price', '' );
|
||||||
|
set_query_var( 'min_price', '' );
|
||||||
|
set_query_var( 'filter_stock_status', '' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue