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

Product Query: Fix pagination issue #7109

Merged
merged 2 commits into from
Sep 15, 2022
Merged

Product Query: Fix pagination issue #7109

merged 2 commits into from
Sep 15, 2022

Conversation

gigitux
Copy link
Contributor

@gigitux gigitux commented Sep 12, 2022

@sunyatasattva and I worked together on this PR.

During some tests, I noticed that the pagination didn't work for custom queries (for example on sale products filter). The reason is that blocks related to the pagination using gutenberg_build_query_vars_from_query_block where it is applied the filter query_loop_block_query_vars. So, removing the filter isn't the right approach because, in the case of custom query, the blocks related to the pagination have to continue to use the query injected by the filter.

This PR is a follow-up of #6952.

Testing

User Facing Testing

  1. Add a Product Query block.
  2. Add another Product Query block on the same page.
  3. Set the toggle to display “On sale products” .
  4. Set the number of products on a page to 1.
  5. Add a Query Loop block.
  6. Set it to display your posts.
  7. Go to the front-end.
  8. Make sure the three loop blocks show the expected items and the number of pages.
  • Do not include in the Testing Notes

WooCommerce Visibility

  • WooCommerce Core
  • Feature plugin
  • Experimental

Changelog

N/A

@gigitux gigitux added type: bug The issue/PR concerns a confirmed bug. block-type: product-query Issues related to/affecting all product-query variations. labels Sep 12, 2022
@gigitux gigitux self-assigned this Sep 12, 2022
@rubikuserbot rubikuserbot requested review from a team and Aljullu and removed request for a team September 12, 2022 10:11
@gigitux gigitux modified the milestones: 8.5.0, 8.6.0 Sep 12, 2022
@github-actions
Copy link
Contributor

The release ZIP for this PR is accessible via:

https://wcblocks.wpcomstaging.com/wp-content/uploads/woocommerce-gutenberg-products-block-7109.zip

@github-actions
Copy link
Contributor

github-actions bot commented Sep 12, 2022

Size Change: 0 B

Total Size: 874 kB

ℹ️ View Unchanged
Filename Size
build/active-filters-frontend.js 7.62 kB
build/active-filters.js 8.27 kB
build/all-products-frontend.js 18.1 kB
build/all-products.js 33.9 kB
build/all-reviews.js 7.79 kB
build/attribute-filter-frontend.js 22.3 kB
build/attribute-filter.js 13.3 kB
build/blocks-checkout.js 17.4 kB
build/cart-blocks/cart-accepted-payment-methods-frontend.js 1.16 kB
build/cart-blocks/cart-express-payment-frontend.js 5.08 kB
build/cart-blocks/cart-items-frontend.js 299 B
build/cart-blocks/cart-line-items--mini-cart-contents-block/products-table-frontend.js 5.25 kB
build/cart-blocks/cart-line-items-frontend.js 429 B
build/cart-blocks/cart-order-summary-frontend.js 1.11 kB
build/cart-blocks/cart-totals-frontend.js 322 B
build/cart-blocks/empty-cart-frontend.js 346 B
build/cart-blocks/filled-cart-frontend.js 783 B
build/cart-blocks/order-summary-coupon-form-frontend.js 2.64 kB
build/cart-blocks/order-summary-discount-frontend.js 2.15 kB
build/cart-blocks/order-summary-fee-frontend.js 274 B
build/cart-blocks/order-summary-heading-frontend.js 454 B
build/cart-blocks/order-summary-shipping--checkout-blocks/order-summary-shipping-frontend.js 6.37 kB
build/cart-blocks/order-summary-shipping-frontend.js 428 B
build/cart-blocks/order-summary-subtotal-frontend.js 274 B
build/cart-blocks/order-summary-taxes-frontend.js 435 B
build/cart-blocks/proceed-to-checkout-frontend.js 1.15 kB
build/cart-frontend.js 47.1 kB
build/cart.js 41.8 kB
build/checkout-blocks/actions-frontend.js 1.42 kB
build/checkout-blocks/billing-address--checkout-blocks/shipping-address-frontend.js 4.12 kB
build/checkout-blocks/billing-address-frontend.js 888 B
build/checkout-blocks/contact-information-frontend.js 2.84 kB
build/checkout-blocks/express-payment-frontend.js 5.38 kB
build/checkout-blocks/fields-frontend.js 344 B
build/checkout-blocks/order-note-frontend.js 1.08 kB
build/checkout-blocks/order-summary-cart-items-frontend.js 3.64 kB
build/checkout-blocks/order-summary-coupon-form-frontend.js 2.79 kB
build/checkout-blocks/order-summary-discount-frontend.js 2.27 kB
build/checkout-blocks/order-summary-fee-frontend.js 276 B
build/checkout-blocks/order-summary-frontend.js 1.11 kB
build/checkout-blocks/order-summary-shipping-frontend.js 602 B
build/checkout-blocks/order-summary-subtotal-frontend.js 274 B
build/checkout-blocks/order-summary-taxes-frontend.js 434 B
build/checkout-blocks/payment-frontend.js 7.69 kB
build/checkout-blocks/shipping-address-frontend.js 1.03 kB
build/checkout-blocks/shipping-methods-frontend.js 4.74 kB
build/checkout-blocks/terms-frontend.js 1.23 kB
build/checkout-blocks/totals-frontend.js 326 B
build/checkout-frontend.js 49.3 kB
build/checkout.js 43.1 kB
build/featured-category.js 13.2 kB
build/featured-product.js 13.4 kB
build/general-style-rtl.css 1.29 kB
build/general-style.css 1.29 kB
build/handpicked-products.js 7.29 kB
build/legacy-template.js 2.84 kB
build/mini-cart-component-frontend.js 16.8 kB
build/mini-cart-contents-block/empty-cart-frontend.js 366 B
build/mini-cart-contents-block/filled-cart-frontend.js 230 B
build/mini-cart-contents-block/footer--mini-cart-contents-block/products-table-frontend.js 4.69 kB
build/mini-cart-contents-block/footer-frontend.js 6.98 kB
build/mini-cart-contents-block/items-frontend.js 237 B
build/mini-cart-contents-block/products-table-frontend.js 290 B
build/mini-cart-contents-block/shopping-button-frontend.js 288 B
build/mini-cart-contents-block/title-frontend.js 368 B
build/mini-cart-contents.js 22.9 kB
build/mini-cart-frontend.js 1.72 kB
build/mini-cart.js 4.56 kB
build/price-filter-frontend.js 13.4 kB
build/price-filter.js 9.34 kB
build/price-format.js 1.19 kB
build/product-add-to-cart--product-button--product-category-list--product-image--product-price--product-r--a0326d00.js 223 B
build/product-add-to-cart--product-button--product-image--product-title.js 2.66 kB
build/product-add-to-cart-frontend.js 6.95 kB
build/product-add-to-cart.js 6.88 kB
build/product-best-sellers.js 7.62 kB
build/product-button--product-category-list--product-image--product-price--product-rating--product-sale-b--e17c7c01.js 435 B
build/product-button--product-image--product-rating--product-sale-badge--product-title.js 300 B
build/product-button-frontend.js 1.87 kB
build/product-button.js 1.57 kB
build/product-categories.js 2.36 kB
build/product-category-list-frontend.js 883 B
build/product-category-list.js 502 B
build/product-category.js 8.61 kB
build/product-image-frontend.js 1.88 kB
build/product-image.js 1.59 kB
build/product-new.js 7.62 kB
build/product-on-sale.js 7.94 kB
build/product-price-frontend.js 1.9 kB
build/product-price.js 1.51 kB
build/product-query.js 648 B
build/product-rating-frontend.js 1.17 kB
build/product-rating.js 739 B
build/product-sale-badge-frontend.js 1.13 kB
build/product-sale-badge.js 801 B
build/product-search.js 2.62 kB
build/product-sku-frontend.js 380 B
build/product-sku.js 379 B
build/product-stock-indicator-frontend.js 996 B
build/product-stock-indicator.js 623 B
build/product-summary-frontend.js 1.29 kB
build/product-summary.js 920 B
build/product-tag-list-frontend.js 876 B
build/product-tag-list.js 497 B
build/product-tag.js 8 kB
build/product-title-frontend.js 1.31 kB
build/product-title.js 921 B
build/product-top-rated.js 7.86 kB
build/products-by-attribute.js 8.53 kB
build/reviews-by-category.js 11.2 kB
build/reviews-by-product.js 12.3 kB
build/reviews-frontend.js 7.02 kB
build/single-product-frontend.js 21.4 kB
build/single-product.js 10 kB
build/stock-filter-frontend.js 7.62 kB
build/stock-filter.js 7.52 kB
build/vendors--cart-blocks/cart-line-items--cart-blocks/cart-order-summary--cart-blocks/order-summary-shi--c02aad66-frontend.js 5.26 kB
build/vendors--cart-blocks/cart-line-items--checkout-blocks/order-summary-cart-items--mini-cart-contents---233ab542-frontend.js 3.14 kB
build/vendors--cart-blocks/order-summary-shipping--checkout-blocks/billing-address--checkout-blocks/order--5b8feb0b-frontend.js 4.85 kB
build/vendors--cart-blocks/order-summary-shipping--checkout-blocks/billing-address--checkout-blocks/order--decc3dc6-frontend.js 19.1 kB
build/vendors--mini-cart-contents-block/footer-frontend.js 6.86 kB
build/vendors--product-add-to-cart-frontend.js 7.53 kB
build/wc-blocks-data.js 9.87 kB
build/wc-blocks-editor-style-rtl.css 5.1 kB
build/wc-blocks-editor-style.css 5.1 kB
build/wc-blocks-google-analytics.js 1.56 kB
build/wc-blocks-middleware.js 931 B
build/wc-blocks-registry.js 2.7 kB
build/wc-blocks-shared-context.js 1.53 kB
build/wc-blocks-shared-hocs.js 1.71 kB
build/wc-blocks-style-rtl.css 23.8 kB
build/wc-blocks-style.css 23.7 kB
build/wc-blocks-vendors-style-rtl.css 1.95 kB
build/wc-blocks-vendors-style.css 1.95 kB
build/wc-blocks-vendors.js 54.5 kB
build/wc-blocks.js 2.63 kB
build/wc-payment-method-bacs.js 816 B
build/wc-payment-method-cheque.js 811 B
build/wc-payment-method-cod.js 909 B
build/wc-payment-method-paypal.js 837 B
build/wc-settings.js 2.6 kB

compressed-size-action

@gigitux gigitux added the skip-changelog PRs that you don't want to appear in the changelog. label Sep 12, 2022
Copy link
Contributor

@Aljullu Aljullu left a comment

Choose a reason for hiding this comment

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

Confirming it fixes the issue. I left one comment about making the filter inline again, but besides that, LGTM.

if ( isset( $parsed_block['attrs']['__woocommerceVariationProps'] ) ) {
add_filter(
'query_loop_block_query_vars',
array( $this, 'get_query_by_attributes' ),
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we make this method inline? This way we don't need to set $this->parsed_block anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, we shouldn't.

This way we don't need to set $this->parsed_block anymore.

It is still necessary this. If we don't use this anymore, the $parsed_block will always be an instance of our variations (for the check at line 54). This is a problem because, for example, if on the same page, we have:

  • Products Query block.
  • Query Loop block with post type set to Post (so it should render the post on frontend).

The filter injects in the Query Loop block the query used by the Products Query block. Obviously, this is incorrect.

Let me know what you think, and if it makes sense to you, I will merge this PR!

Copy link
Contributor

Choose a reason for hiding this comment

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

Re-reading this code, I wonder… is there any way we can make these lines conditional?

https://github.com/woocommerce/woocommerce-blocks/pull/7109/files#diff-efb947e345af5e501dfaa2980b055b3b31c308b31e8db23049b6b48fecee33d8L31-L36

Like, is there any other filter we can use so that we don't run this on every block? It would be amazing if there ware a filter like rest_{$this->post_type}_query, but with something like pre_render_{$this->block_id}_block. You know what I mean? 🤔

Copy link
Contributor Author

@gigitux gigitux Sep 15, 2022

Choose a reason for hiding this comment

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

Re-reading this code, I wonder… is there any way we can make these lines conditional?

GitHub doesn't highlight the lines. From the URL, it seems that you are referring to these:

image

If yes, we already checked during one of our pair sessions: these lines are executed once: when the class has been instanced.

Like, is there any other filter we can use so that we don't run this on every block? It would be amazing if there ware a filter like rest_{$this->post_type}query, but with something like pre_render{$this->block_id}_block. You know what I mean? 🤔

Yeah, I searched during my exploration, but unfortunately doesn't exist.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oooh, right, thanks for the explanation. Another reason not to use an inline function is to avoid the same filter being added several times.

Copy link
Contributor

Choose a reason for hiding this comment

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

I might have been confused. But with this PR, the filter isn't added for each block instance, that's because we are calling a class method so every time add_filter() is called, it knows it's the same method. But if the function was inline, it would be added as a filter every time it's called. (I might be wrong, though)

Copy link
Contributor

Choose a reason for hiding this comment

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

If yes, we already checked during one of our pair sessions: these lines are executed once: when the class has been instanced.

@gigitux Sorry, I wasn't clear enough. I know these lines get executed once in the sense that the filter is registered only once. But the filter is run on the pre-render of every block. Of course we return early and no harm is done. But I still would have loved if it wasn't like that…

I hope this makes more sense.

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 hope this makes more sense.

It makes sense!

Of course we return early and no harm is done. But I still would have loved if it wasn't like that…
Agree, but it seems that it isn't possible :(

I might have been confused. But with this PR, the filter isn't added for each block instance, that's because we are calling a class method so every time add_filter() is called, it knows it's the same method. But if the function was inline, it would be added as a filter every time it's called. (I might be wrong, though)

The filter query_loop_block_query_vars is added every time that the Product Query variation is rendered.
The reason is that pre_render_block is triggered on the pre-render of every block.

Does it make sense?

cc @sunyatasattva

Copy link
Contributor

Choose a reason for hiding this comment

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

The filter query_loop_block_query_vars is added every time that the Product Query variation is rendered.
The reason is that pre_render_block is triggered on the pre-render of every block.

I think the confusion here comes from what we understand by "the filter is added". It's true that add_filter() is called every time a Product Query variation is rendered. But given that we add a named function (in this case, a class method) filter, once it's added once, it isn't added again every time. Ie: if there are ten Product Query blocks in a page, get_query_by_attributes() won't be called 10 times per block, only 1. But if the filter added an inline function instead of a named function, get_query_by_attributes() would be called 10 times for every block. At least, that's how I understand it works, but I might be wrong.

Copy link
Contributor Author

@gigitux gigitux Sep 15, 2022

Choose a reason for hiding this comment

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

It makes sense! I did a test, and I can confirm what you wrote!
Just to be clear, in our case the function is called 4 times for each block. The reason is that the function gutenberg_build_query_vars_from_query_block (where there is the filter query_loop_block_query_vars) in the hierarchy of the Query Block is called 4 times:

This means that if on the page there are two Product Query blocks, the function get_query_by_attributes() is called 8 times.

Copy link
Contributor

@Aljullu Aljullu left a comment

Choose a reason for hiding this comment

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

LGTM :shipit:

if ( isset( $parsed_block['attrs']['__woocommerceVariationProps'] ) ) {
add_filter(
'query_loop_block_query_vars',
array( $this, 'get_query_by_attributes' ),
Copy link
Contributor

Choose a reason for hiding this comment

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

Oooh, right, thanks for the explanation. Another reason not to use an inline function is to avoid the same filter being added several times.

@gigitux
Copy link
Contributor Author

gigitux commented Sep 15, 2022

I'm merging this PR. Happy to continue the discussion above if you have other thoughts.

Thanks for the review! 🙇

@gigitux gigitux merged commit f43ab74 into trunk Sep 15, 2022
@gigitux gigitux deleted the fix/product-query-update branch September 15, 2022 11:53
senadir pushed a commit to senadir/woocommerce-blocks that referenced this pull request Nov 12, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
block-type: product-query Issues related to/affecting all product-query variations. skip-changelog PRs that you don't want to appear in the changelog. type: bug The issue/PR concerns a confirmed bug.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants