tomusborne / generateblocks

GenerateBlocks is a small collection of lightweight WordPress blocks that can accomplish nearly anything.
https://generateblocks.com
188 stars 18 forks source link

Bug: Query Loop shows wrong number of posts on the front end with sticky posts #1253

Open frzsombor opened 1 week ago

frzsombor commented 1 week ago

Description

On a website I have sticky posts, that I want to show in one Query Loop with the non-sticky posts, together limited to 3 posts. If I set a limit in the Query Loop, the sticky posts are not counted and this causes a problem in the layout. For example, I have 2 sticky posts and 5 non-sticky posts (7 posts all together). If I want to show only 3 posts and I set this limit, 5 posts will be rendered by the Query Loop: the 2 sticky (not counted) and 3 additional non-sticky posts.

Steps to reproduce

  1. Create 3 posts in WP
  2. Set one post to be sticky
  3. Add a query loop on a page and set limit to 1
  4. Block editor will show one post, but on the rendered page there will be two

Expected behavior

When I set a limit on Query Loop, I expect that to be the maximum number of rendered posts.

Actual behavior

Currently sticky posts are not count as posts, so they will always be part of the loop (if not excluded) and limit applies to additional non-sticky posts only.

References

This is a related live issue in Gutenberg here: https://github.com/WordPress/gutenberg/issues/41184 as part of https://github.com/WordPress/gutenberg/issues/41405. However, as this is a very frustrating bug for those who are actually building a blog/news website, I think this could be fixed in GenerateBlock - as it has a custom query loop block anyways. Also Gutenberg has 5K+ open issues so maybe this won't get fixed soon on their end.

Related: #1252


Additional notes: WP Sticky posts are a complete mess. Sticky posts are always loaded with a different query in WP and prepended to the array of the actual query results. This means if we set an offset (like offset:3) and/or any limit, and we also have sticky posts, WP will first load ALL the sticky posts, then run the query on everything else excluding(!) sticky posts and apply the offset and limits on those non-sticky posts. So, we will get all the sticky posts first in the array (no matter what offset/limit we use), then everything else WITH offset and limit.

For example:

Posts [9] [8 sticky] [7] [6] [5 sticky] [4] [3] [2] [1]
Posts rendered [8 sticky] [5 sticky] [9] [7] [6] [4] [3] [2] [1]
Query include sticky, offset 3, limit 4
Expected [7] [6] [4] [3] - stickies and [9] removed by offset, return four(!) results from the remaining
Result [8 sticky] [5 sticky] [4] [3] [2] [1] - stickies still present, [5] and [4] skipped, six(!) results

I think it might be a good idea to completely ignore WP Query sticky handling (run all queries with sticky status ignored) and only when user set sticky:include, handle sticky posts with a custom function or a better query. I've submitted a PR for limiting the number of rendered posts with PHP, because at least that way it won't break the layout if given by a design, we have to work with exactly a maximum number of posts.