[Experimental] Add default product attribute pattern to Product Filters template part (#50158)

* fix: always return an object

* tweak: fallback to the default product attribute

* add: default product attribute pattern

* update: use default product attribute pattern in the template part

* chore: changelog

* tweak: escaping

* performance: add in memory cache

* chore: lint and use strtr for readability
This commit is contained in:
Tung Du 2024-08-08 16:47:04 +07:00 committed by GitHub
parent 7b86ec137e
commit 6b4001118e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 78 additions and 23 deletions

View File

@ -0,0 +1,5 @@
Significance: patch
Type: add
Comment: Add default product attribute pattern to dynamically show the default attribute in the Product Filters template part.

View File

@ -31,6 +31,7 @@ final class ProductFilterAttribute extends AbstractBlock {
add_filter( 'collection_filter_query_param_keys', array( $this, 'get_filter_query_param_keys' ), 10, 2 ); add_filter( 'collection_filter_query_param_keys', array( $this, 'get_filter_query_param_keys' ), 10, 2 );
add_filter( 'collection_active_filters_data', array( $this, 'register_active_filters_data' ), 10, 2 ); add_filter( 'collection_active_filters_data', array( $this, 'register_active_filters_data' ), 10, 2 );
add_action( 'deleted_transient', array( $this, 'delete_default_attribute_id_transient' ) ); add_action( 'deleted_transient', array( $this, 'delete_default_attribute_id_transient' ) );
add_action( 'wp_loaded', array( $this, 'register_block_patterns' ) );
} }
/** /**
@ -44,7 +45,7 @@ final class ProductFilterAttribute extends AbstractBlock {
parent::enqueue_data( $attributes ); parent::enqueue_data( $attributes );
if ( is_admin() ) { if ( is_admin() ) {
$this->asset_data_registry->add( 'defaultProductFilterAttribute', $this->get_default_attribute() ); $this->asset_data_registry->add( 'defaultProductFilterAttribute', $this->get_default_product_attribute() );
} }
} }
@ -161,6 +162,11 @@ final class ProductFilterAttribute extends AbstractBlock {
* @return string Rendered block type output. * @return string Rendered block type output.
*/ */
protected function render( $attributes, $content, $block ) { protected function render( $attributes, $content, $block ) {
if ( empty( $attributes['attributeId'] ) ) {
$default_product_attribute = $this->get_default_product_attribute();
$attributes['attributeId'] = $default_product_attribute->attribute_id;
}
// don't render if its admin, or ajax in progress. // don't render if its admin, or ajax in progress.
if ( is_admin() || wp_doing_ajax() || empty( $attributes['attributeId'] ) ) { if ( is_admin() || wp_doing_ajax() || empty( $attributes['attributeId'] ) ) {
return ''; return '';
@ -361,9 +367,17 @@ final class ProductFilterAttribute extends AbstractBlock {
/** /**
* Get the attribute if with most term but closest to 30 terms. * Get the attribute if with most term but closest to 30 terms.
* *
* @return int * @return object
*/ */
private function get_default_attribute() { private function get_default_product_attribute() {
// Cache this variable in memory to prevent repeated database queries to check
// for transient in the same request.
static $cached = null;
if ( $cached ) {
return $cached;
}
$cached = get_transient( 'wc_block_product_filter_attribute_default_attribute' ); $cached = get_transient( 'wc_block_product_filter_attribute_default_attribute' );
if ( $cached ) { if ( $cached ) {
@ -403,9 +417,13 @@ final class ProductFilterAttribute extends AbstractBlock {
} }
} }
$default_attribute = array( $default_attribute = (object) array(
'id' => 0, 'attribute_id' => '0',
'label' => __( 'Attribute', 'woocommerce' ), 'attribute_name' => 'attribute',
'attribute_label' => __( 'Attribute', 'woocommerce' ),
'attribute_type' => 'select',
'attribute_orderby' => 'menu_order',
'attribute_public' => 0,
); );
if ( $attribute_id ) { if ( $attribute_id ) {
@ -416,4 +434,52 @@ final class ProductFilterAttribute extends AbstractBlock {
return $default_attribute; return $default_attribute;
} }
/**
* Register pattern for default product attribute.
*/
public function register_block_patterns() {
$default_attribute = $this->get_default_product_attribute();
register_block_pattern(
'woocommerce/default-attribute-filter',
array(
'title' => '',
'inserter' => false,
'content' => strtr(
'
<!-- wp:woocommerce/product-filter {"filterType":"attribute-filter","attributeId":{{attribute_id}}} -->
<!-- wp:group {"metadata":{"name":"Header"},"style":{"spacing":{"blockGap":"0"}},"layout":{"type":"flex","flexWrap":"nowrap"}} -->
<div class="wp-block-group">
<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">{{attribute_label}}</h3>
<!-- /wp:heading -->
<!-- wp:woocommerce/product-filter-clear-button {"lock":{"remove":true,"move":false}} -->
<!-- wp:buttons {"layout":{"type":"flex"}} -->
<div class="wp-block-buttons">
<!-- wp:button {"className":"wc-block-product-filter-clear-button is-style-outline","style":{"border":{"width":"0px","style":"none"},"typography":{"textDecoration":"underline"},"outline":"none","fontSize":"medium"}} -->
<div
class="wp-block-button wc-block-product-filter-clear-button is-style-outline"
style="text-decoration: underline"
>
<a class="wp-block-button__link wp-element-button" style="border-style: none; border-width: 0px">Clear</a>
</div>
<!-- /wp:button -->
</div>
<!-- /wp:buttons -->
<!-- /wp:woocommerce/product-filter-clear-button -->
</div>
<!-- /wp:group -->
<!-- wp:woocommerce/product-filter-attribute {"attributeId":{{attribute_id}},"lock":{"remove":true}} /-->
<!-- /wp:woocommerce/product-filter -->
',
array(
'{{attribute_id}}' => intval( $default_attribute->attribute_id ),
'{{attribute_label}}' => esc_html( $default_attribute->attribute_label ),
)
),
)
);
}
} }

View File

@ -47,23 +47,7 @@
<!-- wp:woocommerce/product-filter-stock-status {"lock":{"remove":true}} /--> <!-- wp:woocommerce/product-filter-stock-status {"lock":{"remove":true}} /-->
<!-- /wp:woocommerce/product-filter --> <!-- /wp:woocommerce/product-filter -->
<!-- wp:woocommerce/product-filter {"filterType":"attribute-filter","attributeId":0} --> <!-- wp:pattern {"slug":"woocommerce/default-attribute-filter"} /-->
<!-- wp:group {"metadata":{"name":"Header"},"style":{"spacing":{"blockGap":"0"}},"layout":{"type":"flex","flexWrap":"nowrap"}} -->
<div class="wp-block-group"><!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">Attribute</h3>
<!-- /wp:heading -->
<!-- wp:woocommerce/product-filter-clear-button {"lock":{"remove":true,"move":false}} -->
<!-- wp:buttons {"layout":{"type":"flex"}} -->
<div class="wp-block-buttons"><!-- wp:button {"className":"wc-block-product-filter-clear-button is-style-outline","style":{"border":{"width":"0px","style":"none"},"typography":{"textDecoration":"underline"},"outline":"none","fontSize":"medium"}} -->
<div class="wp-block-button wc-block-product-filter-clear-button is-style-outline" style="text-decoration:underline"><a class="wp-block-button__link wp-element-button" style="border-style:none;border-width:0px">Clear</a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->
<!-- /wp:woocommerce/product-filter-clear-button --></div>
<!-- /wp:group -->
<!-- wp:woocommerce/product-filter-attribute {"attributeId":1,"lock":{"remove":true}} /-->
<!-- /wp:woocommerce/product-filter -->
<!-- wp:woocommerce/product-filter {"filterType":"rating-filter","heading":"Rating"} --> <!-- wp:woocommerce/product-filter {"filterType":"rating-filter","heading":"Rating"} -->
<!-- wp:group {"metadata":{"name":"Header"},"style":{"spacing":{"blockGap":"0"}},"layout":{"type":"flex","flexWrap":"nowrap"}} --> <!-- wp:group {"metadata":{"name":"Header"},"style":{"spacing":{"blockGap":"0"}},"layout":{"type":"flex","flexWrap":"nowrap"}} -->