-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Block bindings: Adds a filter to customize the output of a block bindings source. #6839
Block bindings: Adds a filter to customize the output of a block bindings source. #6839
Conversation
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN:
To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
Thanks for working on this! 🙂 I believe something like this could make sense, but I am not sure how it should be structured. Some of the concerns I have at this point:
|
There is already an existing filter in
|
Thinking about this a bit more, I feel more confident that we should probably provide a general filter for bindings that receive the |
@SantosGuillamot Introduced a general filter 'block_bindings_source_value' to allow developers to modify the value returned by any block binding source. Changes Made:
Key Benefits:
|
+1 for this concept. I'll give a real world example and you can tell me if you think this feature would help. I recently wrote a block variation for the image block to pull in the featured image (yes there's a "featured image" block, but the image block has more options, like the lightbox control). I couldn't use the core/postmeta field where the featured image is stored because it returns an attachment ID, not a URL. So I had to create a custom binding source. It'd be much less overhead if I could have modified the value sent to the block binding API to return the URL of the featured image instead of the attachment ID. But now I have a custom binding source for one simple meta field AND there's no editor preview on my variation. Feels like this would be a great example of when this feature would be useful. |
Thanks for making the changes 🙂 I agree it makes sense to have a filter like this. I must say that I had this on my to-do list for a while, but I didn't find time yet with the 6.6 release. I'm really sorry for the wait. I would like to take a deeper look and understand better all the use cases. In the meantime, would it make sense to add some testing? Is this something done for other similar filters?
I'd need to review your implementation, but at first glance, it looks like a good example for this functionality 🙂 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Example of how filters are tested in different places:
wordpress-develop/tests/phpunit/tests/blocks/register.php
Lines 1381 to 1397 in dea027e
/** | |
* @ticket 52138 | |
*/ | |
public function test_filter_block_registration_metadata_settings() { | |
$filter_metadata_registration = static function ( $settings, $metadata ) { | |
$settings['api_version'] = $metadata['apiVersion'] + 1; | |
return $settings; | |
}; | |
add_filter( 'block_type_metadata_settings', $filter_metadata_registration, 10, 2 ); | |
$result = register_block_type_from_metadata( | |
DIR_TESTDATA . '/blocks/notice' | |
); | |
remove_filter( 'block_type_metadata_settings', $filter_metadata_registration ); | |
$this->assertSame( 3, $result->api_version ); | |
} |
This is looking very good and the placement for the filter makes perfect sense. Let's bring it to the finish line.
It seems this is close to being ready. Adding some tests and docs, as suggested below, should be enough to include it in the WordPress 6.7 release. Thanks a lot for working on it @snehapatil2001! Let us know if you'd like some help in that regard 🙂 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left some additional comments clarifying my previous feedback. In addition to that, we still need unit tests to cover the usage as explained in #6839 (review).
/** | ||
* Filters the output of a block bindings source. | ||
* | ||
* @since 6.7.0 | ||
* | ||
* @param mixed $value Value returned by `get_value_callback` after applying the filter. | ||
*/ | ||
$value = call_user_func_array( $this->get_value_callback, array( $source_args, $block_instance, $attribute_name ) ); | ||
return apply_filters( 'block_bindings_source_value', $value, $this->name, $source_args, $block_instance, $attribute_name ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It still needs some further refinements, so it gets correctly recognized by the parser that generates the documentation for all filters:
/** | |
* Filters the output of a block bindings source. | |
* | |
* @since 6.7.0 | |
* | |
* @param mixed $value Value returned by `get_value_callback` after applying the filter. | |
*/ | |
$value = call_user_func_array( $this->get_value_callback, array( $source_args, $block_instance, $attribute_name ) ); | |
return apply_filters( 'block_bindings_source_value', $value, $this->name, $source_args, $block_instance, $attribute_name ); | |
$value = call_user_func_array( $this->get_value_callback, array( $source_args, $block_instance, $attribute_name ) ); | |
/** | |
* Filters the value of a block bindings source. | |
* | |
* @since 6.7.0 | |
* | |
* @param mixed $value The computed value for the source. | |
* @param string $name The name of the source. | |
* @param array $source_args Array containing source arguments used to look up the override value, i.e. { "key": "foo" }. | |
* @param WP_Block $block_instance The block instance. | |
* @param string $attribute_name The name of an attribute. | |
*/ | |
return apply_filters( 'block_bindings_source_value', $value, $this->name, $source_args, $block_instance, $attribute_name ); |
Changes addressed.
|
|
||
public function test_filter_block_bindings_source_value() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: the empty line should get removed.
public function test_filter_block_bindings_source_value() { | |
public function test_filter_block_bindings_source_value() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way, I think this test should be general purpose in the first place as it isn't tied to post meta, so maybe render.php
in the same folder would be a good fit. Having, two tests could work, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll move it to render.php
This is what I tested locally and you don't need to pass a function that returns a function: Index: tests/phpunit/tests/block-bindings/postMetaSource.php
===================================================================
--- tests/phpunit/tests/block-bindings/postMetaSource.php (revision 58970)
+++ tests/phpunit/tests/block-bindings/postMetaSource.php (working copy)
@@ -266,4 +266,41 @@
'The post content should not include the script tag.'
);
}
+
+ /**
+ * Tests that filter `block_bindings_source_value` is applied.
+ *
+ * @ticket 61181
+ */
+ public function test_filter_block_bindings_source_value() {
+ register_meta(
+ 'post',
+ 'tests_filter_field',
+ array(
+ 'show_in_rest' => true,
+ 'single' => true,
+ 'type' => 'string',
+ 'default' => 'Original value',
+ )
+ );
+
+ $filter_value = function ( $value, $source_name, $source_args ) {
+ if ( 'core/post-meta' !== $source_name ) {
+ return $value;
+ }
+ return "Filtered value: {$source_args['key']}";
+ };
+
+ add_filter( 'block_bindings_source_value', $filter_value, 10, 3 );
+
+ $content = $this->get_modified_post_content( '<!-- wp:paragraph {"metadata":{"bindings":{"content":{"source":"core/post-meta","args":{"key":"tests_filter_field"}}}}} --><p>Fallback value</p><!-- /wp:paragraph -->' );
+
+ remove_filter( 'block_bindings_source_value', $filter_value );
+
+ $this->assertSame(
+ '<p>Filtered value: tests_filter_field</p>',
+ $content,
+ 'The post content should show the filtered value.'
+ );
+ }
} I also updated the test to validate that the args get correctly passed. Like I said in #6839 (comment), there should be another test in |
I've been testing it locally and everything seems to be working as expected. Once the changes to the |
Agreed, the existing test for post meta is nice to keep as it covers 3 params ( |
Done! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent, this looks solid!
Committed in https://core.trac.wordpress.org/changeset/58972 |
I wonder if this might be a simple and proper example of how to filter a meta value using this new filter? |
@colorful-tones, it’s correct. The reasoning for this new filter is to allow formatting of the value depending on the context. Some examples:
|
Sure, we can use them for future docs and the dev note. |
Ticket: https://core.trac.wordpress.org/ticket/61181
Description
This PR introduces a filter to the
block_bindings_source_value
to allow developers to modify the value returned by any block binding source.This enhancement provides greater flexibility for developers who need to modify the displayed content of a meta value, such as showing "Free!" when the meta value is
0
or unset.