diff --git a/plugins/woocommerce-blocks/assets/js/blocks/product-query/variations/related-products.tsx b/plugins/woocommerce-blocks/assets/js/blocks/product-query/variations/related-products.tsx index 4286baeef79..54bed80e29b 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/product-query/variations/related-products.tsx +++ b/plugins/woocommerce-blocks/assets/js/blocks/product-query/variations/related-products.tsx @@ -48,6 +48,13 @@ export const BLOCK_ATTRIBUTES = { }; export const INNER_BLOCKS_TEMPLATE: InnerBlockTemplate[] = [ + [ + 'core/heading', + { + level: 2, + content: __( 'Related products.', 'woo-gutenberg-products-block' ), + }, + ], [ 'core/post-template', { __woocommerceNamespace: PRODUCT_TEMPLATE_ID }, diff --git a/plugins/woocommerce-blocks/src/BlockTypes/RelatedProducts.php b/plugins/woocommerce-blocks/src/BlockTypes/RelatedProducts.php index eaeb5808381..ff3d833a54b 100644 --- a/plugins/woocommerce-blocks/src/BlockTypes/RelatedProducts.php +++ b/plugins/woocommerce-blocks/src/BlockTypes/RelatedProducts.php @@ -34,6 +34,14 @@ class RelatedProducts extends AbstractBlock { 10, 2 ); + + add_filter( + 'render_block', + array( $this, 'render_block' ), + 10, + 2 + ); + } /** @@ -75,16 +83,82 @@ class RelatedProducts extends AbstractBlock { */ public function build_query( $query ) { $parsed_block = $this->parsed_block; - if ( ! ProductQuery::is_woocommerce_variation( $parsed_block ) && 'woocommerce/related-products' !== $parsed_block['attrs']['namespace'] ) { + if ( ! $this->is_related_products_block( $parsed_block ) ) { return $query; } - $product = wc_get_product(); - $related_products = wc_get_related_products( $product->get_id() ); + + $related_products_ids = $this->get_related_products_ids(); + if ( count( $related_products_ids ) < 1 ) { + return array(); + } return array( 'post_type' => 'product', - 'post__in' => $related_products, + 'post__in' => $related_products_ids, 'post_status' => 'publish', ); } + + /** + * If there are no related products, return an empty string. + * + * @param string $content The block content. + * @param array $block The block. + * + * @return string The block content. + */ + public function render_block( string $content, array $block ) { + if ( ! $this->is_related_products_block( $block ) ) { + return $content; + } + + $related_products_ids = $this->get_related_products_ids(); + + if ( count( $related_products_ids ) < 1 ) { + return ''; + } + return $content; + } + + + + /** + * Determines whether the block is a related products block. + * + * @param array $block The block. + * + * @return bool Whether the block is a related products block. + */ + private function is_related_products_block( $block ) { + if ( ProductQuery::is_woocommerce_variation( $block ) && isset( $block['attrs']['namespace'] ) && 'woocommerce/related-products' === $block['attrs']['namespace'] ) { + return true; + } + + return false; + } + + /** + * Get related products ids. + * The logic is copied from the core function woocommerce_related_products. https://github.com/woocommerce/woocommerce/blob/ca49caabcba84ce9f60a03c6d3534ec14b350b80/plugins/woocommerce/includes/wc-template-functions.php/#L2039-L2074 + * + * @return array Products ids. + */ + private function get_related_products_ids() { + global $post; + + $product = wc_get_product( $post->ID ); + + $related_products = array_filter( array_map( 'wc_get_product', wc_get_related_products( $product->get_id(), 5, $product->get_upsell_ids() ) ), 'wc_products_array_filter_visible' ); + $related_products = wc_products_array_orderby( $related_products, 'rand', 'desc' ); + + $related_product_ids = array_map( + function( $product ) { + return $product->get_id(); + }, + $related_products + ); + + return $related_product_ids; + } + }