Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Comment Template Block: Set commentId context via filter #50279

Merged
merged 1 commit into from
May 4, 2023

Conversation

ockham
Copy link
Contributor

@ockham ockham commented May 3, 2023

What?

In the Comment Template block's render callback, instead of creating a new WP_Block instance with commentId context set, use the render_block_context filter to set that context and render the existing WP_Block instance.

Why?

This approach arguably follows our established patterns with regard to handling block context better. Notably, with the previous approach, we were only setting block context for the Comment Template block itself. In this PR, we extend it to apply to all child blocks, including ones that are dynamically inserted, e.g. via the render_block filter. This is relevant for Auto-inserting blocks (see #50103).

How?

See "What".

Testing Instructions

Verify that the Comments block (and children) are still working as expected on the frontend:

  1. Use a block theme that uses them (e.g. Twenty Twenty-Three).
  2. On trunk, create a number of comments below a given post, nested at different levels. View that page on the frontend, and take note (and a screenshot) of what the comments look like.
  3. Switch to this branch, and rebuild GB.
  4. Reload the page, and verify that it looks the same as before.

Additionally, you can copy the relevant unit tests file from wordpress-develop, and run it against this branch in GB:

cp ../src/wordpress-develop/tests/phpunit/tests/blocks/renderCommentTemplate.php phpunit/blocks/render-comment-template-test.php
npm run test:unit:php -- --group=blocks

Testing Instructions for Keyboard

N/A.

Screenshots or screencast

N/A.

@ockham ockham added the [Block] Comment Template Affects the Comment Template Block label May 3, 2023
@ockham ockham self-assigned this May 3, 2023
@ockham ockham requested review from gziolo and artemiomorales May 3, 2023 12:38
@ockham ockham marked this pull request as ready for review May 3, 2023 12:38
@ockham ockham requested a review from michalczaplinski as a code owner May 3, 2023 12:38
Copy link
Contributor

@michalczaplinski michalczaplinski left a comment

Choose a reason for hiding this comment

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

LGTM! 👍

@ockham ockham merged commit 4409ba4 into trunk May 4, 2023
@ockham ockham deleted the update/comment-template-render-context branch May 4, 2023 08:52
@github-actions github-actions bot added this to the Gutenberg 15.8 milestone May 4, 2023
ockham added a commit that referenced this pull request May 4, 2023
In the Post Template block's render callback, instead of creating a new `WP_Block` instance with `postId` and `postType` context set, use the `render_block_context` filter to set that context and render the existing `WP_Block` instance.

This approach arguably follows our established patterns with regard to handling block context better. Notably, with the previous approach, we were only setting block context for the Post Template block itself. In this PR, we extend it to apply to all child blocks, including ones that are dynamically inserted, e.g. via the `render_block` filter. This is relevant for Auto-inserting blocks (see #50103).

This follows the precedent of the Comment Template block, see #50279.
@gziolo
Copy link
Member

gziolo commented May 4, 2023

Nice discovery @ockham 💯

Do you think we should apply a similar fix to the Post Template block? It has a very similar logic in place:

$block_content = (
new WP_Block(
$block_instance,
array(
'postType' => get_post_type(),
'postId' => get_the_ID(),
)
)
)->render( array( 'dynamic' => false ) );

@gziolo
Copy link
Member

gziolo commented May 4, 2023

I see #50313 now, I got my answer. Excellent work @ockham 😄

@gziolo gziolo added the [Type] Bug An existing feature does not function as intended label May 4, 2023
@gziolo
Copy link
Member

gziolo commented May 16, 2023

I explored using an alternative approach:

diff --git a/packages/block-library/src/comment-template/index.php b/packages/block-library/src/comment-template/index.php
index 6a8698f60f..4bf8f793b3 100644
--- a/packages/block-library/src/comment-template/index.php
+++ b/packages/block-library/src/comment-template/index.php
@@ -25,14 +25,15 @@ function block_core_comment_template_render_comments( $comments, $block ) {
 
 	$content = '';
 	foreach ( $comments as $comment ) {
-		$comment_id           = $comment->comment_ID;
-		$filter_block_context = static function( $context ) use ( $comment_id ) {
-			$context['commentId'] = $comment_id;
-			return $context;
-		};
-		add_filter( 'render_block_context', $filter_block_context );
-		$block_content = $block->render( array( 'dynamic' => false ) );
-		remove_filter( 'render_block_context', $filter_block_context );
+		$block_content = ( new WP_Block(
+			$block->parsed_block,
+			array_merge(
+				$block->context,
+				array(
+					'commentId' => $comment->comment_ID,
+				),
+			)
+		) )->render( array( 'dynamic' => false ) );
 
 		$children = $comment->get_children();
 

The intriguing discovery is that no place in the code explicitly exposes commentId through providesContext. So it's more of a workaround where the system takes care of it. The other interesting bit is that both approaches are very similar, but there is one slight difference:

  • When using an additional new WP_Block instance, we are able to inject the missing context in the constructor, which ensures that it's propagated to all inner blocks and all the regular mechanisms take effect, this way we are programmatically injecting providesContext for commentId.
  • When calling render on the existing instance of WP_Block (this PR and currently trunk), we can't change the context passed to inner blocks, so it doesn't contain the commentId. That's why the only way to pass this commentId is to go through the filter during rendering. While it works in most cases, it might have some unexpected behaviors when folks try to consume commentId through the passed arguments in filters where it uses the original WP_Block instance with its inner blocks created with the extended context id.

@ockham
Copy link
Contributor Author

ockham commented May 22, 2023

I explored using an alternative approach: [...]

I'm afraid this doesn't fix the issue I was originally seeing in 🙁 #50103. Try applying your patch to the branch from #50103 (and don't forget to rebuild!)

Compare the two following screenshots:

With patch from #50279 (comment) Without patch
image image

With the patch, the auto-inserted Avatar block below the comment once again shows the "incognito person" instead of Wapuu (as it should) 😕

The reason is that the patch only changes the context that is passed to the WP_Block constructor -- but that context isn't passed to the auto-inserted block. I'm afraid that currently, the only way to do so is the render_block_context filter.

The intriguing discovery is that no place in the code explicitly exposes commentId through providesContext.

Yeah -- that's maybe something I should've mentioned in the PR description. The reason is that providesContext simply doesn't support anything else than a block attribute.

[T]he only way to pass this commentId is to go through the filter during rendering. While it works in most cases, it might have some unexpected behaviors when folks try to consume commentId through the passed arguments in filters where it uses the original WP_Block instance with its inner blocks created with the extended context id.

Can you give a concrete example? I'm aware of this issue and the problem with the Post Template block in #50131, but I have a potential solution for the former and a theory that the latter is related to another (somewhat hackish) thing we're doing when rendering that block (and we're not doing anything like that to the Comments Template block). So I'm somewhat optimistic that we'll be able to eschew those problems... 🤞

@ockham
Copy link
Contributor Author

ockham commented May 22, 2023

As a next step, I'd like to explore if this change would fix this behavior (i.e. restore the behavior prior to this PR).

Furthermore, I should probably add test coverage to ensure context is passed correctly to child blocks (as demonstrated e.g. here) to prevent future changes from breaking that behavior.

@ockham
Copy link
Contributor Author

ockham commented May 23, 2023

Furthermore, I should probably add test coverage to ensure context is passed correctly to child blocks (as demonstrated e.g. here) to prevent future changes from breaking that behavior.

#50879

@ockham
Copy link
Contributor Author

ockham commented May 23, 2023

As a next step, I'd like to explore if this change would fix this behavior (i.e. restore the behavior prior to this PR).

Draft PR, currently only containing automated testing (which isn't behaving as expected yet 😕 ): #50883

ockham added a commit that referenced this pull request May 24, 2023
In the Post Template block's render callback, instead of creating a new `WP_Block` instance with `postId` and `postType` context set, use the `render_block_context` filter to set that context and render the existing `WP_Block` instance.

This approach arguably follows our established patterns with regard to handling block context better. Notably, with the previous approach, we were only setting block context for the Post Template block itself. In this PR, we extend it to apply to all child blocks, including ones that are dynamically inserted, e.g. via the `render_block` filter. This is relevant for Auto-inserting blocks (see #50103).

This follows the precedent of the Comment Template block, see #50279.
@ockham
Copy link
Contributor Author

ockham commented May 25, 2023

As a next step, I'd like to explore if this change would fix this behavior (i.e. restore the behavior prior to this PR).

Draft PR, currently only containing automated testing (which isn't behaving as expected yet 😕 ): #50883

Test works now; I've amended the PR to also include the fix for that issue and have opened it for review.

ockham added a commit that referenced this pull request May 30, 2023
* Post Template Block: Set block context via filter

In the Post Template block's render callback, use the `render_block_context` filter to set `postId` and `postType` context, rather than passing that context directly to the `WP_Block` constructor.

This approach arguably follows our established patterns with regard to handling block context better. Notably, with the previous approach, we were only setting block context for the Post Template block itself. In this PR, we extend it to apply to all child blocks, including ones that are dynamically inserted, e.g. via the `render_block` filter. This is relevant for Auto-inserting blocks (see #50103).

This follows the precedent of the Comment Template block, see #50279.

Furthermore, add some test coverage to guard against duplicated block-supports class names, which was an issue in a previous iteration of this PR.
sethrubenstein pushed a commit to pewresearch/gutenberg that referenced this pull request Jul 13, 2023
* Post Template Block: Set block context via filter

In the Post Template block's render callback, use the `render_block_context` filter to set `postId` and `postType` context, rather than passing that context directly to the `WP_Block` constructor.

This approach arguably follows our established patterns with regard to handling block context better. Notably, with the previous approach, we were only setting block context for the Post Template block itself. In this PR, we extend it to apply to all child blocks, including ones that are dynamically inserted, e.g. via the `render_block` filter. This is relevant for Auto-inserting blocks (see WordPress#50103).

This follows the precedent of the Comment Template block, see WordPress#50279.

Furthermore, add some test coverage to guard against duplicated block-supports class names, which was an issue in a previous iteration of this PR.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Comment Template Affects the Comment Template Block [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants