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

Add wide and full alignment support for legacy template block #5433

Merged
merged 13 commits into from
Jan 7, 2022

Conversation

gigitux
Copy link
Contributor

@gigitux gigitux commented Dec 21, 2021

This PR adds support for the wide and full alignment for the legacy template block.

Fixes #5229

Screenshots

image
*editor side
image
*frontend side

Testing

Manual Testing

How to test the changes in this Pull Request:

Check out this branch

  1. Open FSE editor.
  2. Edit a legacy template (for example Product Category Page).
  3. Check if you can change the alignment.
  4. Change it.
  5. Check if the changes are also reflected on the frontend side.

You should test at least one between Product Category Page, Product Archive Page and Product Tag Page.
You should test Single Product Page.

Changelog

Add support for the wide and full alignment for the legacy template block.

@gigitux gigitux added focus: global styles Issues that involve styles/css/layout structure. focus: FSE Work related to prepare WooCommerce for FSE. focus: template Related to API powering block template functionality in the Site Editor labels Dec 21, 2021
@gigitux gigitux requested a review from dinhtungdu December 21, 2021 17:18
@gigitux gigitux self-assigned this Dec 21, 2021
@rubikuserbot rubikuserbot requested a review from a team December 21, 2021 17:18
@github-actions
Copy link
Contributor

github-actions bot commented Dec 21, 2021

Size Change: +10 B (0%)

Total Size: 819 kB

Filename Size Change
build/legacy-template.js 2.18 kB +10 B (0%)
ℹ️ View Unchanged
Filename Size
build/active-filters-frontend.js 6.21 kB
build/active-filters.js 7.1 kB
build/all-products-frontend.js 18.6 kB
build/all-products.js 34.4 kB
build/all-reviews.js 8.35 kB
build/atomic-block-components/add-to-cart--atomic-block-components/button--atomic-block-components/image---a7e2bb9b.js 2.76 kB
build/atomic-block-components/add-to-cart--atomic-block-components/button.js 1.48 kB
build/atomic-block-components/add-to-cart-frontend.js 6.87 kB
build/atomic-block-components/add-to-cart.js 6.43 kB
build/atomic-block-components/button-frontend.js 1.48 kB
build/atomic-block-components/button.js 851 B
build/atomic-block-components/category-list-frontend.js 458 B
build/atomic-block-components/category-list.js 458 B
build/atomic-block-components/image-frontend.js 1.37 kB
build/atomic-block-components/image.js 1.05 kB
build/atomic-block-components/price-frontend.js 1.74 kB
build/atomic-block-components/price.js 1.7 kB
build/atomic-block-components/rating-frontend.js 553 B
build/atomic-block-components/rating.js 554 B
build/atomic-block-components/sale-badge-frontend.js 625 B
build/atomic-block-components/sale-badge.js 622 B
build/atomic-block-components/sku-frontend.js 386 B
build/atomic-block-components/sku.js 385 B
build/atomic-block-components/stock-indicator-frontend.js 585 B
build/atomic-block-components/stock-indicator.js 585 B
build/atomic-block-components/summary-frontend.js 874 B
build/atomic-block-components/summary.js 871 B
build/atomic-block-components/tag-list-frontend.js 460 B
build/atomic-block-components/tag-list.js 458 B
build/atomic-block-components/title-frontend.js 1.11 kB
build/atomic-block-components/title.js 1.1 kB
build/attribute-filter-frontend.js 16.3 kB
build/attribute-filter.js 12.6 kB
build/blocks-checkout.js 17.6 kB
build/cart-blocks/accepted-payment-methods-frontend.js 1.15 kB
build/cart-blocks/checkout-button-frontend.js 1.14 kB
build/cart-blocks/empty-cart-frontend.js 345 B
build/cart-blocks/express-payment-frontend.js 4.86 kB
build/cart-blocks/filled-cart-frontend.js 766 B
build/cart-blocks/items-frontend.js 298 B
build/cart-blocks/line-items-frontend.js 5.32 kB
build/cart-blocks/order-summary-frontend.js 8.98 kB
build/cart-blocks/totals-frontend.js 320 B
build/cart-frontend.js 45.4 kB
build/cart.js 44.3 kB
build/checkout-blocks/actions-frontend.js 1.44 kB
build/checkout-blocks/billing-address--checkout-blocks/shipping-address-frontend.js 4.22 kB
build/checkout-blocks/billing-address-frontend.js 884 B
build/checkout-blocks/contact-information-frontend.js 2.94 kB
build/checkout-blocks/express-payment-frontend.js 5.15 kB
build/checkout-blocks/fields-frontend.js 343 B
build/checkout-blocks/order-note-frontend.js 1.13 kB
build/checkout-blocks/order-summary-frontend.js 11.4 kB
build/checkout-blocks/payment-frontend.js 7.4 kB
build/checkout-blocks/shipping-address-frontend.js 971 B
build/checkout-blocks/shipping-methods-frontend.js 4.82 kB
build/checkout-blocks/terms-frontend.js 1.21 kB
build/checkout-blocks/totals-frontend.js 324 B
build/checkout-frontend.js 47.5 kB
build/checkout.js 47.1 kB
build/featured-category.js 8.55 kB
build/featured-product.js 9.91 kB
build/handpicked-products.js 7.33 kB
build/mini-cart-component-frontend.js 14.2 kB
build/mini-cart-contents.js 3.6 kB
build/mini-cart-frontend.js 1.76 kB
build/mini-cart.js 6.46 kB
build/price-filter-frontend.js 12.6 kB
build/price-filter.js 8.77 kB
build/price-format.js 1.18 kB
build/product-best-sellers.js 7.51 kB
build/product-categories.js 3.47 kB
build/product-category.js 8.36 kB
build/product-new.js 7.66 kB
build/product-on-sale.js 8.05 kB
build/product-search.js 2.47 kB
build/product-tag.js 7.76 kB
build/product-top-rated.js 7.63 kB
build/products-by-attribute.js 8.48 kB
build/reviews-by-category.js 11.8 kB
build/reviews-by-product.js 12.9 kB
build/reviews-frontend.js 7.24 kB
build/single-product-frontend.js 22.1 kB
build/single-product.js 10.4 kB
build/stock-filter-frontend.js 6.81 kB
build/stock-filter.js 6.82 kB
build/vendors--atomic-block-components/add-to-cart--cart-blocks/order-summary--checkout-blocks/billing-ad--c5eb4dcd-frontend.js 19 kB
build/vendors--atomic-block-components/add-to-cart-frontend.js 6.82 kB
build/vendors--atomic-block-components/price--cart-blocks/line-items--cart-blocks/order-summary--checkout--8a3571de-frontend.js 5.71 kB
build/vendors--cart-blocks/line-items--checkout-blocks/order-summary-frontend.js 3.14 kB
build/vendors--cart-blocks/order-summary--checkout-blocks/billing-address--checkout-blocks/order-summary---eb4d2cec-frontend.js 4.75 kB
build/wc-blocks-data.js 8.84 kB
build/wc-blocks-editor-style-rtl.css 4.48 kB
build/wc-blocks-editor-style.css 4.49 kB
build/wc-blocks-google-analytics.js 1.56 kB
build/wc-blocks-middleware.js 949 B
build/wc-blocks-registry.js 2.7 kB
build/wc-blocks-shared-context.js 1.51 kB
build/wc-blocks-shared-hocs.js 1.14 kB
build/wc-blocks-style-rtl.css 21.6 kB
build/wc-blocks-style.css 21.6 kB
build/wc-blocks-vendors-style-rtl.css 1.28 kB
build/wc-blocks-vendors-style.css 1.28 kB
build/wc-blocks-vendors.js 65.5 kB
build/wc-blocks.js 2.96 kB
build/wc-payment-method-bacs.js 820 B
build/wc-payment-method-cheque.js 816 B
build/wc-payment-method-cod.js 912 B
build/wc-payment-method-paypal.js 838 B
build/wc-payment-method-stripe.js 11.1 kB
build/wc-settings.js 2.61 kB

compressed-size-action

Copy link
Member

@dinhtungdu dinhtungdu left a comment

Choose a reason for hiding this comment

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

@gigitux The alignment is working on my test 👏🏽 . I got several warnings testing this PR due to the new utility added in this PR, please check my comments for more detail.

*/
public static function get_align_class_and_style( $attributes ) {

$align_attribute = $attributes['align'];
Copy link
Member

Choose a reason for hiding this comment

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

align may not exist in $attributes so we should check for its existence first.

$matches = array();
preg_match( $pattern, $content, $matches );

return preg_replace( $pattern, $matches[0] . ' ' . $align_class['class'], $content, 1 );
Copy link
Member

Choose a reason for hiding this comment

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

$align_class may be null, so we need another check before using it as an array.

Copy link
Member

Choose a reason for hiding this comment

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

I'm still getting a warning on this line:

Warning: Trying to access array offset on value of type null in /Users/tenup/Sites/woofse/app/public/wp-content/plugins/woocommerce-gutenberg-products-block/src/BlockTypes/LegacyTemplate.php on line 213

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Mmm, it is very strange, I can't reproduce the warning

@@ -99,6 +102,7 @@ protected function render_single_product() {
* @return string Rendered block type output.
*/
protected function render_archive_product() {
add_filter( 'render_block', array( $this, 'get_markup_with_classes_by_attributes' ), 10, 2 );
Copy link
Member

Choose a reason for hiding this comment

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

What do you think about calling this add_filter once in the initialize() method? I mean overriding the AbstractBlock::initialize() and adding this filter.

src/Utils/StyleAttributesUtils.php Show resolved Hide resolved
* @return string Rendered block type output.
*/
public function get_markup_with_classes_by_attributes( string $content, array $block ) {
$pattern = '/(?<=class=\")[^"]+(?=\")/';
Copy link
Member

Choose a reason for hiding this comment

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

The global/wrapper-start.php can be overridden in the theme, so the wrapper may not have the class attribute. Although I never see any wrapper element that doesn't have class, it's still a valid case. We don't need to cover that case in our logic, but a note for the theme developer will be nice here.

Copy link
Member

Choose a reason for hiding this comment

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

For example, I modified the markup to simulate a wrapper-start.php template overridden by the theme.

Screen Shot 2021-12-22 at 11 25 37

Copy link
Contributor Author

@gigitux gigitux Dec 22, 2021

Choose a reason for hiding this comment

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

The global/wrapper-start.php can be overridden in the theme, so the wrapper may not have the class attribute.

Great catch! I don't think about this case.

but a note for the theme developer will be nice here.

Do you mean to add a comment or what else?

Copy link
Member

@dinhtungdu dinhtungdu Dec 22, 2021

Choose a reason for hiding this comment

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

We don't need to cover that case in our logic

I want to clarify on this. I meant that we may not need to address that issue in our logic if it takes too much effort because it's a rare case. Personally, I never see any wrapper that doesn't have class. But if you can solve it, go ahead ; ).

Do you mean to add a comment or what else?

I was thinking about adding a comment to your callback get_markup_with_classes_by_attributes.

@gigitux
Copy link
Contributor Author

gigitux commented Dec 22, 2021

Thanks for your great comments! I just update the PR, but I don't understand what do you mean with

but a note for the theme developer will be nice here.

@gigitux gigitux requested a review from dinhtungdu December 22, 2021 08:56
src/BlockTypes/LegacyTemplate.php Outdated Show resolved Hide resolved
$matches = array();
preg_match( $pattern, $content, $matches );

return preg_replace( $pattern, $matches[0] . ' ' . $align_class['class'], $content, 1 );
Copy link
Member

Choose a reason for hiding this comment

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

I'm still getting a warning on this line:

Warning: Trying to access array offset on value of type null in /Users/tenup/Sites/woofse/app/public/wp-content/plugins/woocommerce-gutenberg-products-block/src/BlockTypes/LegacyTemplate.php on line 213

@gigitux gigitux requested a review from dinhtungdu December 23, 2021 09:48
@gigitux gigitux force-pushed the add/5229-add-align-support-legacy-template branch from 274c858 to bb19d24 Compare December 23, 2021 09:53
Comment on lines 209 to 206
if ( ! $this->is_legacy_template( $block ) ) {
return $content;
}
Copy link
Member

Choose a reason for hiding this comment

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

I think we can check for blockName key of the $block here instead of creating a new helper method (which checks for the template attribute).

Screen Shot 2021-12-24 at 11 42 29

* @param array $block Parsed block data.
* @return string Rendered block type output.
*/
public function get_markup_with_classes_by_attributes( string $content, array $block ) {
Copy link
Member

Choose a reason for hiding this comment

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

I think this should be renamed to add_alignment_class_to_wrapper for better expressing what the method does.

return $content;
}

$pattern = '/(?<=class=\")[^"]+(?=\")/';
Copy link
Member

Choose a reason for hiding this comment

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

Looking at the BlockTypesController::add_data_attributes, I notice the ways we target the element there and in this method are different:

  • In BlockTypesController::add_data_attributes, we target only the openning <div>. This may not work for LegacyTemplate with themes that use <section> as the wrapper tag.
  • Here, we target the first element (any element, not limited to <div>) that contain the class attribute.

IMO, we need to use the same mechanism to target wrapper elements in both places. I'm tagging @mikejolley here for more insights because he originally created BlockTypesController::add_data_attributes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, it makes sense!
I agree with you. This regex is not great :D
Let's wait for @mikejolley feedback!

Copy link
Member

Choose a reason for hiding this comment

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

In the case of add_data_attributes we know we're dealing with a div element because thats how the block markup is saved to the post. If the opening element is unknown, your regex is probably better, but I wonder if you can still target only the opening element rather than the first class found which could be deeper? I am not going to pretend to be regex expert, because I am not :D

Copy link
Contributor Author

@gigitux gigitux Dec 29, 2021

Choose a reason for hiding this comment

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

but I wonder if you can still target only the opening element rather than the first class found which could be deeper? I am not going to pretend to be regex expert, because I am not :D

It can be a good idea, but I'm pretty sure that the regex will be hard to write and read. I'm not a fan of complex regex, but if you think that it makes sense to work on it, I can do it!

Copy link
Member

Choose a reason for hiding this comment

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

It might not be desirable to add that class deeper in case it breaks other parts of the layout 👍🏻

Are there any alternatives considered for this additional class inserted by regex? Would it be a disaster to wrap in another div with the class, or does that not work here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are there any alternatives considered for this additional class inserted by regex? Would it be a disaster to wrap in another div with the class, or does that not work here?

It works without problem, but I don't know if we can wrap a block in another div. If we can follow this path, I think that it is the best solution.

image

Copy link
Member

Choose a reason for hiding this comment

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

works without problem, but I don't know if we can wrap a block in another div. If we can follow this path, I think that it is the best solution.

I think wrapping inside another element can make it harder (and confusing) for themes developers to style the page because the opening element now is not the first element in the wrapper-start.php but the alignment div.

Copy link
Contributor Author

@gigitux gigitux Jan 4, 2022

Choose a reason for hiding this comment

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

With f4689e6, I implemented a series of regexes.

First of all, I pick the first tag HTML, after that:

  • if the first tag already has the class attribute, I just add the new class.
  • if the first tag doesn't have the class attribute, I add the class attribute + the new class

Let me know what do you think :D

@tjcafferkey tjcafferkey force-pushed the add/5229-add-align-support-legacy-template branch from 6166306 to b4cf934 Compare January 4, 2022 13:30
…om:woocommerce/woocommerce-gutenberg-products-block into add/5229-add-align-support-legacy-template
@gigitux gigitux requested a review from dinhtungdu January 4, 2022 17:47
@gigitux gigitux force-pushed the add/5229-add-align-support-legacy-template branch from 8723818 to f4689e6 Compare January 4, 2022 17:49
Copy link
Member

@dinhtungdu dinhtungdu left a comment

Choose a reason for hiding this comment

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

@gigitux The updates look good. I have some concerns about the regex, please check the review comments for more detail!

preg_match( $first_tag, $content, $matches );

// If there is a tag, but it doesn't have a class attribute, add the class attribute.
if ( isset( $matches[0] ) && strpos( $matches[0], 'class' ) === false ) {
Copy link
Member

Choose a reason for hiding this comment

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

We should check for the exact class attribute here. Elements can have class as a part of attribute name or attribute value, like: data-class, data-type="class", id="fist-class".

Suggested change
if ( isset( $matches[0] ) && strpos( $matches[0], 'class' ) === false ) {
if ( isset( $matches[0] ) && strpos( $matches[0], ' class=' ) === false ) {

Comment on lines 224 to 225
preg_match( $pattern_before_tag_closing, $content, $matches );
return preg_replace( $pattern_before_tag_closing, $matches[0] . ' class="' . $align_class_and_style['class'] . '"', $content, 1 );
Copy link
Member

Choose a reason for hiding this comment

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

Can we use backreferences in preg_replace? If doing so, we can remove the preg_match above.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think with the current regex.
Because the value of match[0] is a tag element without < and >, for example:

div data-block-name="woocommerce/legacy-template" data-template="taxonomy-product_cat" id="primary" 

But the regex /.+?(?=>)/ match the text before a tag closing >.

Potentially we can use str_replace, in this way:

return str_replace( $matches[0], $matches[0] . ' class="' . $align_class_and_style['class'] . '"', $content );

instead to use regex.

I don't have a strong opinion, what do you think?

Copy link
Member

Choose a reason for hiding this comment

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

Because the value of match[0] is a tag element without < and >, for example:

@gigitux I think we can use the fourth argument of preg_replace to only replace one time, you can check my example using your regex below:

<?php
$re = '/.+?(?=>)/m';
$str = '<div data-block-name="woocommerce/legacy-template" data-template="taxonomy-product_cat" id="primary" ><div class="inner">';
$subst = '$0 class="alignwide"';

$result = preg_replace($re, $subst, $str, 1);

echo "The result of the substitution is <pre>" . htmlspecialchars( $result ) . "</pre>";

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for sharing this!

}

// If there is a tag, and it has a class already, add the class attribute.
$pattern_get_class = '/(?<=class=\")[^"]+(?=\")/';
Copy link
Member

Choose a reason for hiding this comment

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

If the wrapper element uses single quotes for class, this regex will fail.

@gigitux
Copy link
Contributor Author

gigitux commented Jan 5, 2022

Thanks for your great feedback!

I updated the regex. There is just a question, let me know, and I will update the PR!

@gigitux gigitux requested a review from dinhtungdu January 5, 2022 15:30
@tjcafferkey tjcafferkey requested review from tjcafferkey and removed request for tjcafferkey January 6, 2022 13:58
@gigitux gigitux force-pushed the add/5229-add-align-support-legacy-template branch from 97ad7e7 to 0cbf68c Compare January 6, 2022 16:17
@gigitux gigitux force-pushed the add/5229-add-align-support-legacy-template branch from 0cbf68c to 891edf7 Compare January 6, 2022 16:19
Copy link
Member

@dinhtungdu dinhtungdu left a comment

Choose a reason for hiding this comment

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

@gigitux This is working like a charm 🎉 ! I've just left one comment for coding style consistency, otherwise, this is ready to be merged!

Comment on lines 228 to 230
$matches_class = array();
preg_match( $pattern_get_class, $content, $matches_class );
return preg_replace( $pattern_get_class, $matches_class[0] . ' ' . $align_class_and_style['class'], $content, 1 );
Copy link
Member

Choose a reason for hiding this comment

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

I think we can follow the same approach as we use at line 223rd above.

@github-actions github-actions bot added this to the 6.8.0 milestone Jan 7, 2022
@gigitux gigitux merged commit b81c221 into trunk Jan 7, 2022
@gigitux gigitux deleted the add/5229-add-align-support-legacy-template branch January 7, 2022 09:47
@gigitux gigitux added the type: enhancement The issue is a request for an enhancement. label Jan 17, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
focus: FSE Work related to prepare WooCommerce for FSE. focus: global styles Issues that involve styles/css/layout structure. focus: template Related to API powering block template functionality in the Site Editor type: enhancement The issue is a request for an enhancement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Legacy template Block: add alignment support
3 participants