From ff0b05ea36b77c534295f19b5f55cd40f4ffc098 Mon Sep 17 00:00:00 2001 From: Manish Menaria Date: Thu, 1 Dec 2022 17:37:41 +0530 Subject: [PATCH] Add product query support for Product Summary block (#7774) * Add product query support for Product Summary block On the client side, when the Product Summary block is used within the product query block, the markup will be rendered on the server side - No javascript related to Product Summary block will be rendered. * Update variable names for clarity & readability * Escape all values in output string * Fix custom style not working More info: https://github.com/woocommerce/woocommerce-blocks/pull/7774#discussion_r1035909243 --- .../product-elements/summary/attributes.ts | 4 ++ .../blocks/product-elements/summary/edit.tsx | 27 ++++++-- .../blocks/product-elements/summary/index.ts | 8 ++- .../blocks/product-elements/summary/save.tsx | 21 ------ .../blocks/product-elements/summary/types.ts | 1 + src/BlockTypes/ProductSummary.php | 68 +++++++++++++++++++ 6 files changed, 100 insertions(+), 29 deletions(-) delete mode 100644 assets/js/atomic/blocks/product-elements/summary/save.tsx diff --git a/assets/js/atomic/blocks/product-elements/summary/attributes.ts b/assets/js/atomic/blocks/product-elements/summary/attributes.ts index 327476c52dc..8b5656d7576 100644 --- a/assets/js/atomic/blocks/product-elements/summary/attributes.ts +++ b/assets/js/atomic/blocks/product-elements/summary/attributes.ts @@ -10,6 +10,10 @@ export const blockAttributes: BlockAttributes = { type: 'number', default: 0, }, + isDescendentOfQueryLoop: { + type: 'boolean', + default: false, + }, }; export default blockAttributes; diff --git a/assets/js/atomic/blocks/product-elements/summary/edit.tsx b/assets/js/atomic/blocks/product-elements/summary/edit.tsx index 7d13625ebc7..2ec7ca50d3f 100644 --- a/assets/js/atomic/blocks/product-elements/summary/edit.tsx +++ b/assets/js/atomic/blocks/product-elements/summary/edit.tsx @@ -2,6 +2,9 @@ * External dependencies */ import { useBlockProps } from '@wordpress/block-editor'; +import type { BlockEditProps } from '@wordpress/blocks'; +import { ProductQueryContext as Context } from '@woocommerce/blocks/product-query/types'; +import { useEffect } from 'react'; /** * Internal dependencies @@ -16,15 +19,27 @@ import { import './editor.scss'; import type { BlockAttributes } from './types'; -interface Props { - attributes: BlockAttributes; -} - -const Edit = ( { attributes }: Props ): JSX.Element => { +const Edit = ( { + attributes, + setAttributes, + context, +}: BlockEditProps< BlockAttributes > & { context: Context } ): JSX.Element => { const blockProps = useBlockProps(); + + const blockAttrs = { + ...attributes, + ...context, + }; + const isDescendentOfQueryLoop = Number.isFinite( context.queryId ); + + useEffect( + () => setAttributes( { isDescendentOfQueryLoop } ), + [ setAttributes, isDescendentOfQueryLoop ] + ); + return (
- +
); }; diff --git a/assets/js/atomic/blocks/product-elements/summary/index.ts b/assets/js/atomic/blocks/product-elements/summary/index.ts index 31bb50ff892..7b2373270df 100644 --- a/assets/js/atomic/blocks/product-elements/summary/index.ts +++ b/assets/js/atomic/blocks/product-elements/summary/index.ts @@ -16,7 +16,6 @@ import { BLOCK_ICON as icon, BLOCK_DESCRIPTION as description, } from './constants'; -import { Save } from './save'; const blockConfig: BlockConfiguration = { ...sharedConfig, @@ -27,7 +26,12 @@ const blockConfig: BlockConfiguration = { attributes, supports, edit, - save: Save, + usesContext: [ 'query', 'queryId', 'postId' ], + ancestor: [ + '@woocommerce/all-products', + '@woocommerce/single-product', + 'core/post-template', + ], }; registerBlockType( 'woocommerce/product-summary', blockConfig ); diff --git a/assets/js/atomic/blocks/product-elements/summary/save.tsx b/assets/js/atomic/blocks/product-elements/summary/save.tsx deleted file mode 100644 index 03a720e27df..00000000000 --- a/assets/js/atomic/blocks/product-elements/summary/save.tsx +++ /dev/null @@ -1,21 +0,0 @@ -/** - * External dependencies - */ -import { useBlockProps } from '@wordpress/block-editor'; -import classnames from 'classnames'; - -type Props = { - attributes: Record< string, unknown > & { - className?: string; - }; -}; - -export const Save = ( { attributes }: Props ): JSX.Element => { - return ( -
- ); -}; diff --git a/assets/js/atomic/blocks/product-elements/summary/types.ts b/assets/js/atomic/blocks/product-elements/summary/types.ts index e64df6f3d4f..b695a3b5f5d 100644 --- a/assets/js/atomic/blocks/product-elements/summary/types.ts +++ b/assets/js/atomic/blocks/product-elements/summary/types.ts @@ -1,3 +1,4 @@ export interface BlockAttributes { productId: number; + isDescendentOfQueryLoop: boolean; } diff --git a/src/BlockTypes/ProductSummary.php b/src/BlockTypes/ProductSummary.php index 0b8824ebda3..58a417c7d76 100644 --- a/src/BlockTypes/ProductSummary.php +++ b/src/BlockTypes/ProductSummary.php @@ -1,6 +1,8 @@ register_chunk_translations( [ $this->block_name ] ); + return null; + } + + /** + * Register the context. + */ + protected function get_block_type_uses_context() { + return [ 'query', 'queryId', 'postId' ]; + } + + /** + * Include and render the block. + * + * @param array $attributes Block attributes. Default empty array. + * @param string $content Block content. Default empty string. + * @param WP_Block $block Block instance. + * @return string Rendered block type output. + */ + protected function render( $attributes, $content, $block ) { + if ( ! empty( $content ) ) { + parent::register_block_type_assets(); + $this->register_chunk_translations( [ $this->block_name ] ); + return $content; + } + + $post_id = $block->context['postId']; + $product = wc_get_product( $post_id ); + $summary_content = self::get_summary_content( $product ); + + if ( ! $summary_content ) { + return ''; + } + + $classes_and_styles = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes ); + $classname = isset( $attributes['className'] ) ? $attributes['className'] : ''; + + $output = '
'; + $output .= '
'; + + return $output; + } + + /** + * Returns summary text for a product. + * + * @param [WC_Product] $product Product to get summary text for. + * @return (string|null) Summary text for the product. + */ + protected function get_summary_content( $product ) { + $short_description = $product->get_short_description(); + $summary_content = $short_description ? $short_description : $product->get_description(); + + if ( ! $summary_content ) { + return null; + } + + $summary = wc_trim_string( $summary_content, 150 ); + return $summary; } }