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: Can not access current post or postId from shortcodes in Query Loop Post Template #1256

Open frzsombor opened 1 week ago

frzsombor commented 1 week ago

Description

If I'm using a shortcode in a Query Loop Post Template, the current post ($post or $postId) to which the shortcode belongs is not available in the shortcode itself, only the post id of the page I'm using it on. As with GenerateBlocks we have a whole plugin, we have full control over the blocks and the backend, and even more things. Given this, we should solve this issue with GenerateBlocks.

The issue is, that in the render_block() function we do have the correct postId, but the shortcodes are not executed during block rendering (which takes place before outputting the whole page content), they are only put into the rendered code of a block as they are, and they got executed during outputting the page content, which result in getting wrong/global post ids. (more detailed cause of the problem is at the end of this issue)

This issue has been discussed many times at many places before, but doesn't have an active, open issue in GitHub. I'm creating this issue to track related process here, because currently, only workarounds exist and related discussions were marked as resolved after providing only a workaround for a specific use-case. The issue is also related to WordPress core, these issues are also linked in References.

Possible solutions without verifying that they are adaptable or if they even work:

Steps to reproduce

  1. Create a page
  2. Insert a Query Loop block
  3. In Post Template, use a shortcode that tries to access data of each specific "current" post.

Expected behavior

I expect the shortcode to access $post or $postId of the current post in the loop, that actually renders it

Actual behavior

The $post or $postId is refering to the page in which the shortcode is inserted in.

References:

https://github.com/WordPress/gutenberg/issues/43053 https://github.com/WordPress/gutenberg/issues/35676

https://generatepress.com/forums/topic/guidance-for-how-query-loop-block-treats-ids-for-custom-shortcode/ https://generatepress.com/forums/topic/getting-current-post-in-a-hook-inside-query-loop-in-generateblocks/

https://wordpress.org/support/topic/cant-get-post-data-id-custom-fields-with-shortcode-inside-query-loop-block/ https://wordpress.org/support/topic/custom-field-via-shortcode-inside-query-loop-block/ https://wordpress.org/support/topic/get-postid-of-posts-included-in-query-loop/ https://wordpress.org/support/topic/shortcodes-and-processing-dynamic-data/


Edit, for future reference: 1) Block render_block() functions To understand the issue better, take a look at this code part, which is the main loop in render_block function of Query Loop. If we insert echo 'post id: '.get_the_ID(); right AFTER the first $the_query->the_post(); line of the while loop, we will get the post ids correctly, BUT they will be written right next to each other as the FIRST lines of the page content. This means block render_block() functions and their loops run before actually outputting related page content. However, in the loop we have the correct page ids each loop cycle. 2) WP_Block->render() functions Calling the actual block rendering function in the loop also makes it "render" the block output (without printing it) BEFORE printing the page output. It will still have the correct post, however the actual problem is that, WP doesn't execute shortcodes in it's render function, they are only executed while outputting the full page content (made of rendered blocks). So by the time the shortcode is executed during printing of the whole page, the $post, $postId, the_post(), etc. will refer to the the last post, which is the page.

frzsombor commented 1 week ago

I'm happy to share my solution for the issue! I was looking for a solution that doesn't require "hacking" the core of WordPress, is lightweight, universal, easy to use, configurable, and relies solely on native approaches while ensuring everything works as originally intended where this solution isn't needed. The solution is also versatile enough that it works with both the original WordPress loop and the GenerateBlocks loop, regardless of which one is used.

I suggest integrating a slightly modified version into GenerateBlocks (which simply ensures that, in addition to the basic text-type blocks, it is also enabled for GenerateBlocks Headings) until there is progress from the WordPress side. This could be an additional feature in GenerateBlocks that makes its use even more beneficial.

All details can be found here: https://gist.github.com/frzsombor/c53446050ee0bb5017e29b9afb039309


image