Product Collection: add price sorting options (#51670)

Co-authored-by: Manish Menaria <the.manish.menaria@gmail.com>
This commit is contained in:
Tung Du 2024-09-27 12:22:37 +07:00 committed by GitHub
parent 98053269ac
commit 870111d8af
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 74 additions and 3 deletions

View File

@ -37,6 +37,14 @@ const orderOptions = [
label: __( 'Oldest to newest', 'woocommerce' ), label: __( 'Oldest to newest', 'woocommerce' ),
value: 'date/asc', value: 'date/asc',
}, },
{
label: __( 'Price, high to low', 'woocommerce' ),
value: 'price/desc',
},
{
label: __( 'Price, low to high', 'woocommerce' ),
value: 'price/asc',
},
{ {
value: 'popularity/desc', value: 'popularity/desc',
label: __( 'Best Selling', 'woocommerce' ), label: __( 'Best Selling', 'woocommerce' ),

View File

@ -144,6 +144,7 @@ export type TProductCollectionOrderBy =
| 'date' | 'date'
| 'title' | 'title'
| 'popularity' | 'popularity'
| 'price'
| 'rating'; | 'rating';
export type ProductCollectionSetAttributes = ( export type ProductCollectionSetAttributes = (

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Product Collection: add sorting options by price.

View File

@ -53,7 +53,7 @@ class ProductCollection extends AbstractBlock {
* *
* @var array * @var array
*/ */
protected $custom_order_opts = array( 'popularity', 'rating', 'post__in' ); protected $custom_order_opts = array( 'popularity', 'rating', 'post__in', 'price' );
/** /**
@ -706,7 +706,7 @@ class ProductCollection extends AbstractBlock {
return $this->get_preview_query_args( $collection_args, $query, $request ); return $this->get_preview_query_args( $collection_args, $query, $request );
} }
$orderby = $request->get_param( 'orderBy' ); $orderby = $request->get_param( 'orderby' );
$on_sale = $request->get_param( 'woocommerceOnSale' ) === 'true'; $on_sale = $request->get_param( 'woocommerceOnSale' ) === 'true';
$stock_status = $request->get_param( 'woocommerceStockStatus' ); $stock_status = $request->get_param( 'woocommerceStockStatus' );
$product_attributes = $request->get_param( 'woocommerceAttributes' ); $product_attributes = $request->get_param( 'woocommerceAttributes' );
@ -1056,6 +1056,14 @@ class ProductCollection extends AbstractBlock {
return array( 'orderby' => $orderby ); return array( 'orderby' => $orderby );
} }
if ( 'price' === $orderby ) {
add_filter( 'posts_clauses', array( $this, 'add_price_sorting_posts_clauses' ), 10, 2 );
return array(
'isProductCollection' => true,
'orderby' => $orderby,
);
}
$meta_keys = array( $meta_keys = array(
'popularity' => 'total_sales', 'popularity' => 'total_sales',
'rating' => '_wc_average_rating', 'rating' => '_wc_average_rating',
@ -1729,6 +1737,36 @@ class ProductCollection extends AbstractBlock {
return $clauses; return $clauses;
} }
/**
* Add the `posts_clauses` filter to add price-based sorting
*
* @param array $clauses The list of clauses for the query.
* @param WP_Query $query The WP_Query instance.
* @return array Modified list of clauses.
*/
public function add_price_sorting_posts_clauses( $clauses, $query ) {
$query_vars = $query->query_vars;
$is_product_collection_block = $query_vars['isProductCollection'] ?? false;
if ( ! $is_product_collection_block ) {
return $clauses;
}
$orderby = $query_vars['orderby'] ?? null;
if ( 'price' !== $orderby ) {
return $clauses;
}
$clauses['join'] = $this->append_product_sorting_table_join( $clauses['join'] );
$is_ascending_order = 'asc' === strtolower( $query_vars['order'] ?? 'desc' );
$clauses['orderby'] = $is_ascending_order ?
'wc_product_meta_lookup.min_price ASC, wc_product_meta_lookup.product_id ASC' :
'wc_product_meta_lookup.max_price DESC, wc_product_meta_lookup.product_id DESC';
return $clauses;
}
/** /**
* Determines if price filters need adjustment based on the tax display settings. * Determines if price filters need adjustment based on the tax display settings.
* *
@ -1964,7 +2002,7 @@ class ProductCollection extends AbstractBlock {
$product->get_upsell_ids() $product->get_upsell_ids()
); );
}, },
[] array()
); );
// Remove duplicates and product references. We don't want to display // Remove duplicates and product references. We don't want to display

View File

@ -1220,4 +1220,24 @@ class ProductCollection extends \WP_UnitTestCase {
$this->assertEqualsCanonicalizing( $expected_product_ids, $result_frontend['post__in'] ); $this->assertEqualsCanonicalizing( $expected_product_ids, $result_frontend['post__in'] );
$this->assertEqualsCanonicalizing( $expected_product_ids, $result_editor['post__in'] ); $this->assertEqualsCanonicalizing( $expected_product_ids, $result_editor['post__in'] );
} }
/**
* Test the add_price_sorting_posts_clauses method.
*/
public function test_add_price_sorting_posts_clauses() {
$parsed_block = $this->get_base_parsed_block();
$parsed_block['attrs']['query']['orderBy'] = 'price';
$parsed_block['attrs']['query']['order'] = 'asc';
$merged_query = $this->initialize_merged_query( $parsed_block );
$query = new WP_Query( $merged_query );
$this->assertStringContainsString( 'wc_product_meta_lookup.min_price ASC', $query->request );
$parsed_block['attrs']['query']['order'] = 'desc';
$merged_query = $this->initialize_merged_query( $parsed_block );
$query = new WP_Query( $merged_query );
$this->assertStringContainsString( 'wc_product_meta_lookup.max_price DESC', $query->request );
}
} }