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

Product Collection: Add support for filtering products by featured status #11522

Merged
2 changes: 2 additions & 0 deletions assets/js/blocks/product-collection/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const DEFAULT_QUERY: ProductCollectionQuery = {
inherit: null,
taxQuery: {},
isProductCollectionBlock: true,
featured: false,
woocommerceOnSale: false,
woocommerceStockStatus: getDefaultStockStatuses(),
woocommerceAttributes: [],
Expand Down Expand Up @@ -87,5 +88,6 @@ export const DEFAULT_FILTERS: Partial< ProductCollectionQuery > = {
woocommerceAttributes: [],
taxQuery: DEFAULT_QUERY.taxQuery,
woocommerceHandPickedProducts: [],
featured: DEFAULT_QUERY.featured,
timeFrame: undefined,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import {
BaseControl,
ToggleControl,
// @ts-expect-error Using experimental features
// eslint-disable-next-line @wordpress/no-unsafe-wp-apis
__experimentalToolsPanelItem as ToolsPanelItem,
} from '@wordpress/components';

/**
* Internal dependencies
*/
import { QueryControlProps } from '../types';

const FeaturedProductsControl = ( props: QueryControlProps ) => {
const { query, setQueryAttribute } = props;

return (
<ToolsPanelItem
label={ __( 'Featured', 'woo-gutenberg-products-block' ) }
hasValue={ () => query.featured === true }
onDeselect={ () => {
setQueryAttribute( {
featured: false,
} );
} }
>
<BaseControl
id="product-collection-featured-products-control"
label={ __( 'Featured', 'woo-gutenberg-products-block' ) }
>
<ToggleControl
label={ __(
'Show only featured products',
'woo-gutenberg-products-block'
) }
checked={ query.featured || false }
onChange={ ( featured ) => {
setQueryAttribute( {
featured,
} );
} }
/>
</BaseControl>
</ToolsPanelItem>
);
};

export default FeaturedProductsControl;
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import AttributesControl from './attributes-control';
import TaxonomyControls from './taxonomy-controls';
import HandPickedProductsControl from './hand-picked-products-control';
import LayoutOptionsControl from './layout-options-control';
import FeaturedProductsControl from './featured-products-control';
import CreatedControl from './created-control';

const ProductCollectionInspectorControls = (
Expand Down Expand Up @@ -99,6 +100,7 @@ const ProductCollectionInspectorControls = (
<KeywordControl { ...queryControlProps } />
<AttributesControl { ...queryControlProps } />
<TaxonomyControls { ...queryControlProps } />
<FeaturedProductsControl { ...queryControlProps } />
<CreatedControl { ...queryControlProps } />
</ToolsPanel>
) : null }
Expand Down
4 changes: 4 additions & 0 deletions assets/js/blocks/product-collection/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ export interface ProductCollectionQuery {
postType: string;
search: string;
taxQuery: Record< string, number[] >;
/**
* If true, show only featured products.
*/
featured: boolean;
timeFrame: TimeFrame | undefined;
woocommerceOnSale: boolean;
/**
Expand Down
35 changes: 34 additions & 1 deletion src/BlockTypes/ProductCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ public function update_rest_query_in_editor( $args, $request ): array {
$stock_status = $request->get_param( 'woocommerceStockStatus' );
$product_attributes = $request->get_param( 'woocommerceAttributes' );
$handpicked_products = $request->get_param( 'woocommerceHandPickedProducts' );
$featured = $request->get_param( 'featured' );
$time_frame = $request->get_param( 'timeFrame' );
// This argument is required for the tests to PHP Unit Tests to run correctly.
// Most likely this argument is being accessed in the test environment image.
Expand All @@ -220,6 +221,7 @@ public function update_rest_query_in_editor( $args, $request ): array {
'stock_status' => $stock_status,
'product_attributes' => $product_attributes,
'handpicked_products' => $handpicked_products,
'featured' => $featured,
'timeFrame' => $time_frame,
)
);
Expand Down Expand Up @@ -318,6 +320,7 @@ private function get_final_frontend_query( $query, $page = 1, $is_exclude_applie
'product_attributes' => $product_attributes,
'taxonomies_query' => $taxonomies_query,
'handpicked_products' => $handpicked_products,
'featured' => $query['featured'] ?? false,
'timeFrame' => $time_frame,
),
$is_exclude_applied_filters
Expand All @@ -339,9 +342,10 @@ private function get_final_query_args( $common_query_values, $query, $is_exclude
$on_sale_query = $this->get_on_sale_products_query( $query['on_sale'] );
$stock_query = $this->get_stock_status_query( $query['stock_status'] );
$visibility_query = is_array( $query['stock_status'] ) ? $this->get_product_visibility_query( $stock_query ) : [];
$featured_query = $this->get_featured_query( $query['featured'] ?? false );
$attributes_query = $this->get_product_attributes_query( $query['product_attributes'] );
$taxonomies_query = $query['taxonomies_query'] ?? [];
$tax_query = $this->merge_tax_queries( $visibility_query, $attributes_query, $taxonomies_query );
$tax_query = $this->merge_tax_queries( $visibility_query, $attributes_query, $taxonomies_query, $featured_query );
$date_query = $this->get_date_query( $query['timeFrame'] ?? [] );

// We exclude applied filters to generate product ids for the filter blocks.
Expand Down Expand Up @@ -633,6 +637,35 @@ private function get_product_visibility_query( $stock_query ) {
);
}

/**
* Generates a tax query to filter products based on their "featured" status.
* If the `$featured` parameter is true, the function will return a tax query
* that filters products to only those marked as featured.
* If `$featured` is false, an empty array is returned, meaning no filtering will be applied.
*
* @param bool $featured A flag indicating whether to filter products based on featured status.
*
* @return array A tax query for fetching featured products if `$featured` is true; otherwise, an empty array.
*/
private function get_featured_query( $featured ) {
if ( true !== $featured && 'true' !== $featured ) {
return array();
}

return array(
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
'tax_query' => array(
array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => 'featured',
'operator' => 'IN',
),
),
);
}


/**
* Merge tax_queries from various queries.
*
Expand Down
Loading