diff --git a/assets/js/atomic/blocks/product-elements/button/attributes.js b/assets/js/atomic/blocks/product-elements/button/attributes.js index 5bac8820c40..2e6189b1083 100644 --- a/assets/js/atomic/blocks/product-elements/button/attributes.js +++ b/assets/js/atomic/blocks/product-elements/button/attributes.js @@ -3,6 +3,10 @@ export const blockAttributes = { type: 'number', default: 0, }, + isDescendentOfQueryLoop: { + type: 'boolean', + default: false, + }, }; export default blockAttributes; diff --git a/assets/js/atomic/blocks/product-elements/button/edit.js b/assets/js/atomic/blocks/product-elements/button/edit.js index 2f4a7155fea..df93edad8fa 100644 --- a/assets/js/atomic/blocks/product-elements/button/edit.js +++ b/assets/js/atomic/blocks/product-elements/button/edit.js @@ -1,33 +1,30 @@ /** * External dependencies */ -import { __ } from '@wordpress/i18n'; import { Disabled } from '@wordpress/components'; import { useBlockProps } from '@wordpress/block-editor'; +import { useEffect } from 'react'; /** * Internal dependencies */ import Block from './block'; -import withProductSelector from '../shared/with-product-selector'; -import { BLOCK_TITLE, BLOCK_ICON } from './constants'; -const Edit = ( { attributes } ) => { +const Edit = ( { attributes, setAttributes, context } ) => { const blockProps = useBlockProps(); + const isDescendentOfQueryLoop = Number.isFinite( context.queryId ); + + useEffect( + () => setAttributes( { isDescendentOfQueryLoop } ), + [ setAttributes, isDescendentOfQueryLoop ] + ); return (
- +
); }; -export default withProductSelector( { - icon: BLOCK_ICON, - label: BLOCK_TITLE, - description: __( - 'Choose a product to display its add to cart button.', - 'woo-gutenberg-products-block' - ), -} )( Edit ); +export default Edit; diff --git a/assets/js/atomic/blocks/product-elements/button/index.js b/assets/js/atomic/blocks/product-elements/button/index.js index 64e42c82082..a177c1b6c75 100644 --- a/assets/js/atomic/blocks/product-elements/button/index.js +++ b/assets/js/atomic/blocks/product-elements/button/index.js @@ -15,17 +15,22 @@ import { BLOCK_DESCRIPTION as description, } from './constants'; import { supports } from './supports'; -import { Save } from '../title/save'; const blockConfig = { apiVersion: 2, title, description, + parent: [ 'core/group' ], + ancestor: [ + '@woocommerce/all-products', + '@woocommerce/single-product', + 'core/post-template', + ], + usesContext: [ 'query', 'queryId', 'postId' ], icon: { src: icon }, attributes, supports, edit, - save: Save, }; registerBlockType( 'woocommerce/product-button', { diff --git a/assets/js/atomic/blocks/product-elements/button/style.scss b/assets/js/atomic/blocks/product-elements/button/style.scss index c4a28092e7b..f6dc0866f1c 100644 --- a/assets/js/atomic/blocks/product-elements/button/style.scss +++ b/assets/js/atomic/blocks/product-elements/button/style.scss @@ -36,3 +36,7 @@ border-color: var(--button--color-background); } } + +.wp-block-button.wc-block-components-product-button[data-is-descendent-of-query-loop="true"] { + text-align: center; +} diff --git a/src/BlockTypes/ProductButton.php b/src/BlockTypes/ProductButton.php index 033d5334ea5..855ba3618d6 100644 --- a/src/BlockTypes/ProductButton.php +++ b/src/BlockTypes/ProductButton.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 ); + + if ( $product ) { + $cart_redirect_after_add = get_option( 'woocommerce_cart_redirect_after_add' ) === 'yes'; + $html_element = ( ! $product->has_options() && $product->is_purchasable() && $product->is_in_stock() && ! $cart_redirect_after_add ) ? 'button' : 'a'; + $styles_and_classes = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes, array( 'border_radius', 'font_size', 'text_color' ) ); + + return apply_filters( + 'woocommerce_loop_add_to_cart_link', + sprintf( + '
+ <%s href="%s" rel="nofollow" data-product_id="%s" data-product_sku="%s" class="wp-block-button__link %s wc-block-components-product-button__button product_type_%s %s" style="%s">%s +
', + $html_element, + esc_url( $product->add_to_cart_url() ), + esc_attr( $product->get_id() ), + esc_attr( $product->get_sku() ), + $product->is_purchasable() ? 'ajax_add_to_cart add_to_cart_button' : '', + esc_attr( $product->get_type() ), + $styles_and_classes['classes'], + $styles_and_classes['styles'], + esc_html( $product->add_to_cart_text() ), + $html_element + ), + $product + ); + } } }