[Product Block Editor]: fallback with random products when no related products (#43584)
* add fallbackToRandomProducts option to getRelatedProducts() * fallback to random when there isn't related products * changelog * update and tweak doc * introduce POSTS_NUMBER_TO_PICK const
This commit is contained in:
parent
c776fb63bc
commit
68fa0dd338
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: update
|
||||
|
||||
[Product Block Editor]: fallback with random products when there isn't related products in the Linked Products tab
|
|
@ -133,9 +133,9 @@ export function LinkedProductListBlockEdit( {
|
|||
},
|
||||
} );
|
||||
|
||||
const relatedProducts = ( await getRelatedProducts(
|
||||
productId
|
||||
) ) as Product[];
|
||||
const relatedProducts = ( await getRelatedProducts( productId, {
|
||||
fallbackToRandomProducts: true,
|
||||
} ) ) as Product[];
|
||||
|
||||
dispatch( {
|
||||
type: 'LOADING_LINKED_PRODUCTS',
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
# Get Related Products
|
||||
|
||||
Helper function to retrieve related products for a given product.
|
||||
|
||||
## Usage
|
||||
|
||||
`getRelatedProducts` is an asynchronous function that returns related products for a specified product ID.
|
||||
If no related products are found, and the `fallbackToRandomProducts` flag is set to `true`, it returns a random set of products.
|
||||
|
||||
### Syntax
|
||||
|
||||
```es6
|
||||
getRelatedProducts( productId, options )
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
- `productId` (number): The ID of the product for which related products are to be fetched.
|
||||
- `options` (Object): An object containing the following property:
|
||||
+ `fallbackToRandomProducts` (boolean): Optional. If set to `true`, the function will return random products if no related products are found. Default is `false`.
|
||||
|
||||
#### Return
|
||||
|
||||
- Promise<Product[] | undefined>: A promise that resolves to an array of related products or `undefined` if none are found and `fallbackToRandomProducts` is `false`.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
import getRelatedProducts from './path-to-getRelatedProducts';
|
||||
|
||||
getRelatedProducts( 123, { fallbackToRandomProducts: true } )
|
||||
.then( relatedProducts => {
|
||||
console.log( relatedProducts );
|
||||
} )
|
||||
.catch( error => {
|
||||
console.error( 'Error fetching related products:', error );
|
||||
} );
|
||||
```
|
|
@ -4,20 +4,66 @@
|
|||
import { select, resolveSelect } from '@wordpress/data';
|
||||
import type { Product } from '@woocommerce/data';
|
||||
|
||||
export default async function getRelatedProducts( productId: number ) {
|
||||
type getRelatedProductsOptions = {
|
||||
// If true, return random products if no related products are found.
|
||||
fallbackToRandomProducts?: boolean;
|
||||
};
|
||||
|
||||
const POSTS_NUMBER_TO_RANDOMIZE = 30;
|
||||
const POSTS_NUMBER_TO_PICK = 5;
|
||||
|
||||
/**
|
||||
* Return related products for a given product ID.
|
||||
* If fallbackToRandomProducts is true,
|
||||
* return random products if no related products are found.
|
||||
*
|
||||
* @param {number} productId - Product ID.
|
||||
* @param {getRelatedProductsOptions} options - Options.
|
||||
* @return {Promise<Product[] | undefined>} Related products.
|
||||
*/
|
||||
export default async function getRelatedProducts(
|
||||
productId: number,
|
||||
options: getRelatedProductsOptions = {}
|
||||
): Promise< Product[] | undefined > {
|
||||
const { getEntityRecord } = select( 'core' );
|
||||
const product = getEntityRecord( 'postType', 'product', productId );
|
||||
if ( ! product ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const relatedProductIds = product?.related_ids;
|
||||
if ( ! relatedProductIds ) {
|
||||
return;
|
||||
let relatedProductIds = product?.related_ids;
|
||||
if ( ! relatedProductIds?.length ) {
|
||||
if ( ! options?.fallbackToRandomProducts ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Pick the last `POSTS_NUMBER_TO_RANDOMIZE` posts
|
||||
const lastPost = ( await resolveSelect( 'core' ).getEntityRecords(
|
||||
'postType',
|
||||
'product',
|
||||
{
|
||||
_fields: [ 'id' ],
|
||||
per_page: POSTS_NUMBER_TO_RANDOMIZE,
|
||||
}
|
||||
) ) as Product[];
|
||||
|
||||
if ( ! lastPost?.length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const lastPostIds = lastPost.map( ( post ) => post.id );
|
||||
|
||||
// Pick POSTS_NUMBER_TO_PICK random post IDs
|
||||
relatedProductIds = lastPostIds
|
||||
.sort( () => Math.random() - 0.5 )
|
||||
.slice( 0, POSTS_NUMBER_TO_PICK );
|
||||
}
|
||||
|
||||
const { getEntityRecords } = resolveSelect( 'core' );
|
||||
return ( await getEntityRecords( 'postType', 'product', {
|
||||
include: relatedProductIds,
|
||||
} ) ) as Product[];
|
||||
return ( await resolveSelect( 'core' ).getEntityRecords(
|
||||
'postType',
|
||||
'product',
|
||||
{
|
||||
include: relatedProductIds,
|
||||
}
|
||||
) ) as Product[];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue