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

Product Gallery Block > Remove global variable overwrite and keep support for the Single Product Block. #9458

Draft
wants to merge 7 commits into
base: trunk
Choose a base branch
from
9 changes: 2 additions & 7 deletions src/BlockTypes/AddToCartForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,18 @@ class AddToCartForm extends AbstractBlock {
* @return string | void Rendered block output.
*/
protected function render( $attributes, $content, $block ) {
global $product;

$post_id = $block->context['postId'];

if ( ! isset( $post_id ) ) {
return '';
}

$product = wc_get_product( $post_id );
if ( ! $product instanceof \WC_Product ) {
$product = wc_get_product( $post_id );
if ( ! $product instanceof \WC_Product ) {
return '';
}
return '';
}

ob_start();

/**
* Trigger the single product add to cart action for each product type.
*
Expand Down
133 changes: 118 additions & 15 deletions src/BlockTypes/ProductImageGallery.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,39 +28,142 @@ protected function get_block_type_uses_context() {
return [ 'query', 'queryId', 'postId' ];
}

/**
* Based on the single-product/sale-flash.php template from the core of WooCommerce.
*
* @param \WC_Product $product Product instance.
* @param \WP_Post $post Post instance.
*/
private function sale_flash( $product, $post ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$post isn't used by the function.

if ( ! $product->is_on_sale() ) {
return '';
}

ob_start();
echo sprintf( '<span class="onsale">%1$s</span>', esc_html__( 'Sale!', 'woo-gutenberg-products-block' ) );
return ob_get_clean();
Comment on lines +42 to +44
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to use an output buffer here since you have control over the output. Just return it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is a copy of the classic template, it'd be better to pull in the template directly via Woo template functions. That way if the theme has any template override it'll use the override. It's also possible (but rare) that a plugin (or custom code) might be adding a template override.

I'd also want to avoid just copying template code into here (along with the filters) because it gives the impression this will be the long-term version of the block and we're committing to these filters long-term in this context. I'd prefer to leave room for potential iterations that might not/likely won't expose these filters.

}

/**
* Based on the single-product/product-image.php template from the core of WooCommerce.
*
* @param \WC_Product $product Product instance.
* @param \WP_Post $post Post instance.
*
* @return string
*/
private function product_image( $product, $post ) {
Copy link
Contributor

@nerrad nerrad May 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$post isn't used by the function.

/**
* The woocommerce_product_thumbnails_columns filter.
*
* Allow users to modify the number of columns displayed in the product gallery.
*
* @since TBD
*/
$columns = apply_filters( 'woocommerce_product_thumbnails_columns', 4 );
$post_thumbnail_id = $product->get_image_id();
/**
* The woocommerce_single_product_image_gallery_classes filter.
*
* Allow users to modify the class names for the product image gallery.
*
* @since TBD
*/
$wrapper_classes = apply_filters(
'woocommerce_single_product_image_gallery_classes',
array(
'woocommerce-product-gallery',
'woocommerce-product-gallery--' . ( $post_thumbnail_id ? 'with-images' : 'without-images' ),
'woocommerce-product-gallery--columns-' . absint( $columns ),
'images',
)
);

if ( $post_thumbnail_id ) {
$product_image_gallery_placeholder = wc_get_gallery_image_html( $post_thumbnail_id, true );
} else {
$product_image_gallery_placeholder = sprintf(
'<div class="woocommerce-product-gallery__image--placeholder"><img src="%1$s" alt="%2$s" class="wp-post-image" /></div></div>',
esc_url( wc_placeholder_img_src( 'woocommerce_single' ) ),
esc_html__( 'Awaiting product image', 'woo-gutenberg-products-block' )
);
}
/**
* The woocommerce_single_product_image_thumbnail_html filter.
*
* Allow users to modify the product gallery thumbnail html.
*
* @since TBD
*/
$product_image_gallery_placeholder = apply_filters( 'woocommerce_single_product_image_thumbnail_html', $product_image_gallery_placeholder, $post_thumbnail_id );

return sprintf(
'<div class="%1$s" data-columns="%2$s"><div class="woocommerce-product-gallery__wrapper">%3$s %4$s</div></div>',
esc_attr( implode( ' ', array_map( 'sanitize_html_class', $wrapper_classes ) ) ),
esc_attr( $columns ),
$product_image_gallery_placeholder,
$this->product_thumbnails( $product )
);
}

/**
* Based on the single-product/product-thumbnails.php template from the core of WooCommerce.
*
* @param \WC_Product $product Product instance.
*
* @return false|string
*/
private function product_thumbnails( $product ) {
$attachment_ids = $product->get_gallery_image_ids();
if ( ! $attachment_ids || ! $product->get_image_id() ) {
return '';
}

ob_start();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output buffer isn't needed here, just save the output from the loop to a variable and then return it.

foreach ( $attachment_ids as $attachment_id ) {
echo wp_kses_post( wc_get_gallery_image_html( $attachment_id ) );
}
return ob_get_clean();
}

/**
* 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.
* @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 ) {

$post_id = $block->context['postId'];
global $product;
$product = wc_get_product( $post_id );

if ( ! isset( $post_id ) ) {
return '';
}

$single_post = get_post( $post_id );
if ( ! $single_post instanceof \WP_Post ) {
return '';
}
Comment on lines +145 to +148
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Posts with product post_type will be an instance of WP_Post, why return? These conditionals seem unnecessary.


$single_product = wc_get_product( $post_id );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The single prefix on the variable name is redundant. You can still use product.

if ( ! $single_product instanceof \WC_Product ) {
return '';
}

if ( class_exists( 'WC_Frontend_Scripts' ) ) {
$frontend_scripts = new \WC_Frontend_Scripts();
$frontend_scripts::load_scripts();
}

$classname = $attributes['className'] ?? '';
ob_start();
woocommerce_show_product_sale_flash();
$sale_badge_html = ob_get_clean();

ob_start();
woocommerce_show_product_images();
$product_image_gallery_html = ob_get_clean();

return sprintf(
'<div class="wp-block-woocommerce-product-image-gallery %1$s">%2$s %3$s</div>',
esc_attr( $classname ),
$sale_badge_html,
$product_image_gallery_html
$this->sale_flash( $single_product, $single_post ),
$this->product_image( $single_product, $single_post )
);

}
Expand Down