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

Update the archive templates to use Products block #8308

Merged
merged 12 commits into from
Feb 22, 2023
Merged
9 changes: 8 additions & 1 deletion assets/js/blocks/store-notices/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@
"category": "woocommerce",
"keywords": [ "WooCommerce" ],
"supports": {
"multiple": false
"multiple": false,
"align": [ "wide", "full" ]
},
"attributes": {
"align": {
"type": "string",
"default": "wide"
}
},
"textdomain": "woo-gutenberg-products-block",
"apiVersion": 2,
Expand Down
13 changes: 13 additions & 0 deletions patterns/no-products-found.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php
/**
* Title: No Products Found
* Slug: woocommerce/no-products-found
* Inserter: no
* Categories: WooCommerce
*/
?>
<!-- wp:paragraph -->
<p>
<?php echo esc_html_x( 'No products were found matching your selection.', 'Message explaining that there are no products returned from a search', 'woo-gutenberg-products-block' ); ?>
</p>
<!-- /wp:paragraph -->
9 changes: 9 additions & 0 deletions patterns/product-search-form.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
/**
* Title: Product Search
* Slug: woocommerce/product-search-form
* Inserter: no
* Categories: WooCommerce
*/
?>
<!-- wp:search {"showLabel":false,"placeholder":"<?php echo esc_attr_x( 'Search products…', 'placeholder for search field', 'woo-gutenberg-products-block' ); ?>","query":{"post_type":"product"}} /-->
21 changes: 21 additions & 0 deletions src/BlockTemplatesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ protected function init() {
add_filter( 'get_block_templates', array( $this, 'add_block_templates' ), 10, 3 );
add_filter( 'current_theme_supports-block-templates', array( $this, 'remove_block_template_support_for_shop_page' ) );
add_filter( 'taxonomy_template_hierarchy', array( $this, 'add_archive_product_to_eligible_for_fallback_templates' ), 10, 1 );
add_filter( 'post_type_archive_title', array( $this, 'update_product_archive_title' ), 10, 2 );

if ( $this->package->is_experimental_build() ) {
add_action( 'after_switch_theme', array( $this, 'check_should_use_blockified_product_grid_templates' ), 10, 2 );
Expand Down Expand Up @@ -588,4 +589,24 @@ function_exists( 'wc_get_page_id' ) &&

return $is_support;
}

/**
* Update the product archive title to "Shop".
*
* @param string $post_type_name Post type 'name' label.
* @param string $post_type Post type.
*
* @return string
*/
public function update_product_archive_title( $post_type_name, $post_type ) {
tjcafferkey marked this conversation as resolved.
Show resolved Hide resolved
if (
function_exists( 'is_shop' ) &&
is_shop() &&
'product' === $post_type
) {
return __( 'Shop', 'woo-gutenberg-products-block' );
}

return $post_type_name;
}
}
4 changes: 4 additions & 0 deletions src/BlockTypes/StoreNotices.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ protected function render( $attributes, $content, $block ) {

$classname = isset( $attributes['className'] ) ? $attributes['className'] : '';

if ( isset( $attributes['align'] ) ) {
$classname .= " align{$attributes['align']}";
}

return sprintf(
'<div class="woocommerce wc-block-store-notices %1$s">%2$s</div>',
esc_attr( $classname ),
Expand Down
8 changes: 8 additions & 0 deletions src/Templates/BlockTemplatesCompatibility.php
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,14 @@ protected function set_hook_data() {
'wc_no_products_found' => 10,
),
),
'woocommerce_archive_description' => array(
'block_name' => 'core/term-description',
'position' => 'before',
'hooked' => array(
'woocommerce_taxonomy_archive_description' => 10,
'woocommerce_product_archive_description' => 10,
),
),
);
}

Expand Down
41 changes: 41 additions & 0 deletions src/Utils/BlockTemplateUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,44 @@ public static function inject_theme_attribute_in_content( $template_content ) {
return $template_content;
}

/**
* Remove block from parsed template content.
*
* @param string $template_content serialized wp_template content.
* @param string $block_name Block to be removed.
*
* @return string Updated wp_template content.
*/
private static function remove_block_from_template( $template_content, $block_name ) {
$new_content = '';
$template_blocks = parse_blocks( $template_content );

self::recursive_remove_block( $template_blocks, $block_name );

foreach ( $template_blocks as &$block ) {
$new_content .= serialize_block( $block );
}

return $new_content;
}

/**
* Remove block recursively from block list.
*
* @param array $blocks Parsed blocks array.
* @param string $block_name Block to be removed.
* @return void
*/
private static function recursive_remove_block( &$blocks, $block_name ) {
foreach ( $blocks as $index => &$block ) {
if ( $block_name === $block['blockName'] ) {
unset( $blocks[ $index ] );
} elseif ( ! empty( $block['innerBlocks'] ) ) {
self::recursive_remove_block( $block['innerBlocks'], $block_name );
}
}
}

/**
* Build a unified template object based a post Object.
* Important: This method is an almost identical duplicate from wp-includes/block-template-utils.php as it was not intended for public use. It has been modified to build templates from plugins rather than themes.
Expand Down Expand Up @@ -198,6 +236,9 @@ public static function build_template_result_from_file( $template_file, $templat
$template->id = $template_is_from_theme ? $theme_name . '//' . $template_file->slug : self::PLUGIN_SLUG . '//' . $template_file->slug;
$template->theme = $template_is_from_theme ? $theme_name : self::PLUGIN_SLUG;
$template->content = self::inject_theme_attribute_in_content( $template_content );
if ( 'archive-product' === $template_file->slug ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be great if we could leave a comment here just explaining why we're doing this.

$template->content = self::remove_block_from_template( $template->content, 'core/term-description' );
}
// Plugin was agreed as a valid source value despite existing inline docs at the time of creating: https://github.com/WordPress/gutenberg/issues/36597#issuecomment-976232909.
$template->source = $template_file->source ? $template_file->source : 'plugin';
$template->slug = $template_file->slug;
Expand Down
41 changes: 37 additions & 4 deletions templates/templates/blockified/archive-product.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,41 @@
<!-- wp:template-part {"slug":"header"} /-->
<!-- wp:group {"layout":{"inherit":true}} -->

<!-- wp:group {"layout":{"inherit":true,"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:paragraph -->
<p>Archive product blockified</p>
<!-- /wp:paragraph --></div>
<!-- wp:query {"query":{"perPage":9,"pages":0,"offset":0,"postType":"product","order":"asc","orderBy":"title","author":"","search":"","exclude":[],"sticky":"","inherit":true,"__woocommerceAttributes":[],"__woocommerceStockStatus":["instock","outofstock","onbackorder"]},"displayLayout":{"type":"flex","columns":3},"namespace":"woocommerce/product-query","align":"wide"} -->
<div class="wp-block-query alignwide">
<!-- wp:query-title {"type":"archive","showPrefix":false} /-->

<!-- wp:term-description /-->
Copy link
Contributor

@tjcafferkey tjcafferkey Feb 1, 2023

Choose a reason for hiding this comment

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

For the Product Catalog template there will be no term, or term-description however it is displayed in the Site Editor. Is it possible to conditionally render this if the user is viewing the templates:

  • Products by Category
  • Products by Attribute
  • Products by Tag (which by the way is not displaying the blockified version at this point, is this correct?)

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, good catch.

Is it possible to conditionally render this if the user is viewing the templates:

Currently, all archive templates use the same archive-product.html template (see #7712). I think we can do one of:

  • Create a new archive template with description, fallback all other templates to use the one with description instead of the archive-product.html.
  • Chime in the template parsing process to remove the description block for Product Catalog template.
  • Remove the description block.

@albarin @tjcafferkey what do you think is the best direction here?

Copy link
Contributor

Choose a reason for hiding this comment

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

Chime in the template parsing process to remove the description block for Product Catalog template.

This feels a little bit hacky and we could end up setting a precedent for other people to do the same thing for other template scenarios which might not be ideal. I'm open to people disagreeing though.

Create a new archive template with description, fallback all other templates to use the one with description instead of the archive-product.html.

This feels like a better option but comes with the overhead of maintaining two templates, would that be a problem?

Copy link
Member Author

Choose a reason for hiding this comment

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

You read my mind Tom! If I have to choose one now, that'd be the second direction. But I'm not happy with either of them.

Copy link
Contributor

Choose a reason for hiding this comment

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

I missed this block in template conversion PR. I'll include it there as well for Products by Category, Products by Attribute and Products by Tag

Copy link
Contributor

Choose a reason for hiding this comment

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

Create a new archive template with description, fallback all other templates to use the one with description instead of the archive-product.html.

This feels like a better option but comes with the overhead of maintaining two templates, would that be a problem?

Not completely sure, but I think this would have more implications for the whole fallback system in place. Currently, if you make a modification to the Product Catalog template you should see it on the other three (cat, tag, attr). If we have a separate template with the description I think we'd loose this 🤔

Currently, all archive templates use the same archive-product.html template (see #7712). I think we can do one of:

  • Create a new archive template with description, fallback all other templates to use the one with description instead of the archive-product.html.
  • Chime in the template parsing process to remove the description block for Product Catalog template.
  • Remove the description block.

I'll throw another option there, maybe unpopular 😬 what about just keeping the description block in there?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll throw another option there, maybe unpopular 😬 what about just keeping the description block in there?

@albarin Aha! It's a legit one. Let's consider it also.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'll throw another option there, maybe unpopular 😬 what about just keeping the description block in there?

Definitely an option for now, the only problem is that it does not reflect what users will experience on the frontend. I wonder if its possible to put a note next to these blocks perhaps which explains "On the main Product Catalog page this information will not be visible" etc.

Just cc'ing @vivialice into this incase she has any ideas or would like to weigh in on one of the options.


<!-- wp:woocommerce/store-notices /-->

<!-- wp:group {"layout":{"type":"flex","flexWrap":"nowrap","justifyContent":"space-between"}} -->
<div class="wp-block-group alignwide">
<!-- wp:woocommerce/product-results-count /-->
<!-- wp:woocommerce/catalog-sorting /-->
</div>
<!-- /wp:group -->

<!-- wp:post-template {"__woocommerceNamespace":"woocommerce/product-query/product-template"} -->
<!-- wp:woocommerce/product-image {"isDescendentOfQueryLoop":true} /-->
<!-- wp:post-title {"textAlign":"center","level":3,"fontSize":"medium","__woocommerceNamespace":"woocommerce/product-query/product-title"} /-->
<!-- wp:woocommerce/product-price {"isDescendentOfQueryLoop":true,"textAlign":"center","fontSize":"small","style":{"spacing":{"margin":{"bottom":"1rem"}}}} /-->
<!-- wp:woocommerce/product-button {"isDescendentOfQueryLoop":true,"textAlign":"center","fontSize":"small","style":{"spacing":{"margin":{"bottom":"1rem"}}}} /-->
<!-- /wp:post-template -->

<!-- wp:query-pagination {"layout":{"type":"flex","justifyContent":"center"}} -->
<!-- wp:query-pagination-previous /-->
<!-- wp:query-pagination-numbers /-->
<!-- wp:query-pagination-next /-->
<!-- /wp:query-pagination -->

<!-- wp:query-no-results -->
tjcafferkey marked this conversation as resolved.
Show resolved Hide resolved
<!-- wp:pattern {"slug":"woocommerce/no-products-found"} /-->
<!-- /wp:query-no-results -->
</div>
<!-- /wp:query -->
</div>
<!-- /wp:group -->

<!-- wp:template-part {"slug":"footer"} /-->
40 changes: 36 additions & 4 deletions templates/templates/blockified/product-search-results.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,40 @@
<!-- wp:template-part {"slug":"header"} /-->
<!-- wp:group {"layout":{"inherit":true}} -->

<!-- wp:group {"layout":{"inherit":true,"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:paragraph -->
<p>Product search results blockified</p>
<!-- /wp:paragraph --></div>
<!-- wp:query {"query":{"perPage":9,"pages":0,"offset":0,"postType":"product","order":"asc","orderBy":"title","author":"","search":"","exclude":[],"sticky":"","inherit":true,"__woocommerceAttributes":[],"__woocommerceStockStatus":["instock","outofstock","onbackorder"]},"displayLayout":{"type":"flex","columns":3},"namespace":"woocommerce/product-query","align":"wide"} -->
<div class="wp-block-query alignwide">
<!-- wp:query-title {"type":"search","showPrefix":false} /-->

<!-- wp:woocommerce/store-notices /-->

<!-- wp:group {"layout":{"type":"flex","flexWrap":"nowrap","justifyContent":"space-between"}} -->
<div class="wp-block-group alignwide">
<!-- wp:woocommerce/product-results-count /-->
<!-- wp:woocommerce/catalog-sorting /-->
</div>
<!-- /wp:group -->

<!-- wp:post-template {"__woocommerceNamespace":"woocommerce/product-query/product-template"} -->
<!-- wp:woocommerce/product-image {"isDescendentOfQueryLoop":true} /-->
<!-- wp:post-title {"textAlign":"center","level":3,"fontSize":"medium","__woocommerceNamespace":"woocommerce/product-query/product-title"} /-->
<!-- wp:woocommerce/product-price {"isDescendentOfQueryLoop":true,"textAlign":"center","fontSize":"small","style":{"spacing":{"margin":{"bottom":"1rem"}}}} /-->
<!-- wp:woocommerce/product-button {"isDescendentOfQueryLoop":true,"textAlign":"center","fontSize":"small","style":{"spacing":{"margin":{"bottom":"1rem"}}}} /-->
<!-- /wp:post-template -->

<!-- wp:query-pagination {"layout":{"type":"flex","justifyContent":"center"}} -->
<!-- wp:query-pagination-previous /-->
<!-- wp:query-pagination-numbers /-->
<!-- wp:query-pagination-next /-->
<!-- /wp:query-pagination -->

<!-- wp:query-no-results -->
dinhtungdu marked this conversation as resolved.
Show resolved Hide resolved
<!-- wp:pattern {"slug":"woocommerce/no-products-found"} /-->
<!-- wp:pattern {"slug":"woocommerce/product-search-form"} /-->
<!-- /wp:query-no-results -->
</div>
<!-- /wp:query -->
</div>
<!-- /wp:group -->

<!-- wp:template-part {"slug":"footer"} /-->