From 105ffe1efc24d8387234f9d2a4c43a1e0757bf1b Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Wed, 28 Feb 2024 11:32:34 +0100 Subject: [PATCH 01/23] Check if the meta field is protected --- src/wp-includes/block-bindings/post-meta.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/wp-includes/block-bindings/post-meta.php b/src/wp-includes/block-bindings/post-meta.php index 5aa6bf048d07d..c3af3f0c4f7e3 100644 --- a/src/wp-includes/block-bindings/post-meta.php +++ b/src/wp-includes/block-bindings/post-meta.php @@ -34,6 +34,11 @@ function _block_bindings_post_meta_get_value( array $source_args, $block_instanc return null; } + // Check if the meta field is protected. + if ( is_protected_meta( $source_attrs['key'], 'post' ) ) { + return null; + } + return get_post_meta( $post_id, $source_args['key'], true ); } From 00b4d659368195e34dc0c67324746dc4ba8a8344 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Wed, 28 Feb 2024 11:32:52 +0100 Subject: [PATCH 02/23] Check if the meta field is available in the REST API --- src/wp-includes/block-bindings/post-meta.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/wp-includes/block-bindings/post-meta.php b/src/wp-includes/block-bindings/post-meta.php index c3af3f0c4f7e3..0104430f16c4b 100644 --- a/src/wp-includes/block-bindings/post-meta.php +++ b/src/wp-includes/block-bindings/post-meta.php @@ -39,6 +39,14 @@ function _block_bindings_post_meta_get_value( array $source_args, $block_instanc return null; } + // Check if the meta field is registered to be shown in REST. + $meta_keys = get_registered_meta_keys( 'post', $block_instance->context['postType'] ); + // Add fields registered for all subtypes. + $meta_keys = array_merge( $meta_keys, get_registered_meta_keys( 'post', '' ) ); + if ( empty( $meta_keys[ $source_attrs['key'] ]['show_in_rest'] ) || false === $meta_keys[ $source_attrs['key'] ]['show_in_rest'] ) { + return null; + } + return get_post_meta( $post_id, $source_args['key'], true ); } From 46a29e4d6ceff99e9185e4448c1683561b344ff4 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 28 Feb 2024 12:57:55 +0100 Subject: [PATCH 03/23] Remove unnecessary `show_in_rest` conditional Co-authored-by: Pascal Birchler --- src/wp-includes/block-bindings/post-meta.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/block-bindings/post-meta.php b/src/wp-includes/block-bindings/post-meta.php index 0104430f16c4b..b1947335efb6c 100644 --- a/src/wp-includes/block-bindings/post-meta.php +++ b/src/wp-includes/block-bindings/post-meta.php @@ -43,7 +43,7 @@ function _block_bindings_post_meta_get_value( array $source_args, $block_instanc $meta_keys = get_registered_meta_keys( 'post', $block_instance->context['postType'] ); // Add fields registered for all subtypes. $meta_keys = array_merge( $meta_keys, get_registered_meta_keys( 'post', '' ) ); - if ( empty( $meta_keys[ $source_attrs['key'] ]['show_in_rest'] ) || false === $meta_keys[ $source_attrs['key'] ]['show_in_rest'] ) { + if ( empty( $meta_keys[ $source_attrs['key'] ]['show_in_rest'] ) ) { return null; } From 0b106f9b63d382a82b419369249128bb61af1821 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Wed, 28 Feb 2024 16:35:44 +0100 Subject: [PATCH 04/23] Use `source_args` instead of `source_attrs` --- src/wp-includes/block-bindings/post-meta.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/block-bindings/post-meta.php b/src/wp-includes/block-bindings/post-meta.php index b1947335efb6c..75062f5ca3ea9 100644 --- a/src/wp-includes/block-bindings/post-meta.php +++ b/src/wp-includes/block-bindings/post-meta.php @@ -35,7 +35,7 @@ function _block_bindings_post_meta_get_value( array $source_args, $block_instanc } // Check if the meta field is protected. - if ( is_protected_meta( $source_attrs['key'], 'post' ) ) { + if ( is_protected_meta( $source_args['key'], 'post' ) ) { return null; } @@ -43,7 +43,7 @@ function _block_bindings_post_meta_get_value( array $source_args, $block_instanc $meta_keys = get_registered_meta_keys( 'post', $block_instance->context['postType'] ); // Add fields registered for all subtypes. $meta_keys = array_merge( $meta_keys, get_registered_meta_keys( 'post', '' ) ); - if ( empty( $meta_keys[ $source_attrs['key'] ]['show_in_rest'] ) ) { + if ( empty( $meta_keys[ $source_args['key'] ]['show_in_rest'] ) ) { return null; } From 1736c839baa0e5cd40f077e8ad93474030733fa7 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Wed, 28 Feb 2024 16:55:10 +0100 Subject: [PATCH 05/23] Add post meta bindings source tests --- .../tests/block-bindings/postMetaSource.php | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 tests/phpunit/tests/block-bindings/postMetaSource.php diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php new file mode 100644 index 0000000000000..d10b93310fe70 --- /dev/null +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -0,0 +1,131 @@ +post->create_and_get( array() ); + setup_postdata( $post ); + } + + /** + * Tear down each test method. + */ + public function tear_down() { + // Removes custom fields registered by test cases. + $meta_keys = get_registered_meta_keys( 'post', '' ); + foreach ( $meta_keys as $meta_key_name => $meta_key_value ) { + unregister_meta_key( 'post', $meta_key_name ); + } + + parent::tear_down(); + } + + /** + * Tests that a block connected to a custom field renders its value. + * + * @ticket 60651 + */ + public function test_custom_field_value_is_rendered() { + register_meta( + 'post', + 'custom_field', + array( + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', + 'default' => 'Custom field value', + ) + ); + + $content = apply_filters( 'the_content', '

Fallback value

' ); + + $this->assertSame( + '

Custom field value

', + trim( $content ), + 'The post content should show the value of the custom field.' + ); + } + + /** + * Tests that a block connected without specifying the custom field renders the fallback. + * + * @ticket 60651 + */ + public function test_binding_without_key_renders_the_fallback() { + $content = apply_filters( 'the_content', '

Fallback value

' ); + + $this->assertSame( + '

Fallback value

', + trim( $content ), + 'The post content should show the fallback value.' + ); + } + + /** + * Tests that a block connected to a protected field doesn't show the value. + * + * @ticket 60651 + */ + public function test_protected_field_value_is_not_shown() { + register_meta( + 'post', + '_protected_field', + array( + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', + 'default' => 'Protected value', + ) + ); + + $content = apply_filters( 'the_content', '

Fallback value

' ); + + $this->assertSame( + '

Fallback value

', + trim( $content ), + 'The post content should show the fallback value instead of the protected value.' + ); + } + + /** + * Tests that a block connected to a field not exposed in the REST API doesn't show the value. + * + * @ticket 60651 + */ + public function test_custom_field_not_exposed_in_rest_api_is_not_shown() { + register_meta( + 'post', + 'show_in_rest_false_field', + array( + 'show_in_rest' => false, + 'single' => true, + 'type' => 'string', + 'default' => 'Protected value', + ) + ); + + $content = apply_filters( 'the_content', '

Fallback value

' ); + + $this->assertSame( + '

Fallback value

', + trim( $content ), + 'The post content should show the fallback value instead of the protected value.' + ); + } +} From 1fb2c47758c6deff8342b85b20d7ccaf15dd865c Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Wed, 28 Feb 2024 18:08:28 +0100 Subject: [PATCH 06/23] Unregister only the meta fields containing "tests" --- .../tests/block-bindings/postMetaSource.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index d10b93310fe70..de1c69775ecb9 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -30,7 +30,9 @@ public function tear_down() { // Removes custom fields registered by test cases. $meta_keys = get_registered_meta_keys( 'post', '' ); foreach ( $meta_keys as $meta_key_name => $meta_key_value ) { - unregister_meta_key( 'post', $meta_key_name ); + if ( str_contains( $meta_key_name, 'tests' ) ) { + unregister_meta_key( 'post', $meta_key_name ); + } } parent::tear_down(); @@ -44,7 +46,7 @@ public function tear_down() { public function test_custom_field_value_is_rendered() { register_meta( 'post', - 'custom_field', + 'tests_custom_field', array( 'show_in_rest' => true, 'single' => true, @@ -53,7 +55,7 @@ public function test_custom_field_value_is_rendered() { ) ); - $content = apply_filters( 'the_content', '

Fallback value

' ); + $content = apply_filters( 'the_content', '

Fallback value

' ); $this->assertSame( '

Custom field value

', @@ -85,7 +87,7 @@ public function test_binding_without_key_renders_the_fallback() { public function test_protected_field_value_is_not_shown() { register_meta( 'post', - '_protected_field', + '_tests_protected_field', array( 'show_in_rest' => true, 'single' => true, @@ -94,7 +96,7 @@ public function test_protected_field_value_is_not_shown() { ) ); - $content = apply_filters( 'the_content', '

Fallback value

' ); + $content = apply_filters( 'the_content', '

Fallback value

' ); $this->assertSame( '

Fallback value

', @@ -111,7 +113,7 @@ public function test_protected_field_value_is_not_shown() { public function test_custom_field_not_exposed_in_rest_api_is_not_shown() { register_meta( 'post', - 'show_in_rest_false_field', + 'tests_show_in_rest_false_field', array( 'show_in_rest' => false, 'single' => true, @@ -120,7 +122,7 @@ public function test_custom_field_not_exposed_in_rest_api_is_not_shown() { ) ); - $content = apply_filters( 'the_content', '

Fallback value

' ); + $content = apply_filters( 'the_content', '

Fallback value

' ); $this->assertSame( '

Fallback value

', From 81d4e34b0ba73a9ace90cabf44b81296d1aff677 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Wed, 28 Feb 2024 18:42:25 +0100 Subject: [PATCH 07/23] Add test for password protected posts --- .../tests/block-bindings/postMetaSource.php | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index de1c69775ecb9..f0976a09c615a 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -64,6 +64,39 @@ public function test_custom_field_value_is_rendered() { ); } + /** + * Tests that a blocks connected in a password protected post don't render the value. + * + * @ticket 60651 + */ + public function test_custom_field_value_is_not_shown_in_password_protected_posts() { + register_meta( + 'post', + 'tests_custom_field', + array( + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', + 'default' => 'Custom field value', + ) + ); + + add_filter( + 'post_password_required', + function () { + return true; + } + ); + + $content = apply_filters( 'the_content', '

Fallback value

' ); + + $this->assertSame( + '

Fallback value

', + trim( $content ), + 'The post content should show the fallback value instead of the custom field value.' + ); + } + /** * Tests that a block connected without specifying the custom field renders the fallback. * From 8d0a0be3330450607c5b68f5cb19d8ee6b459d01 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Wed, 28 Feb 2024 18:42:56 +0100 Subject: [PATCH 08/23] Add test for posts that are not viewable --- .../tests/block-bindings/postMetaSource.php | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index f0976a09c615a..dbd096e38f7ee 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -97,6 +97,39 @@ function () { ); } + /** + * Tests that a blocks connected in a post that is not publicly viewable don't render the value. + * + * @ticket 60651 + */ + public function test_custom_field_value_is_not_shown_in_non_viewable_posts() { + register_meta( + 'post', + 'tests_custom_field', + array( + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', + 'default' => 'Custom field value', + ) + ); + + add_filter( + 'is_post_status_viewable', + function () { + return false; + } + ); + + $content = apply_filters( 'the_content', '

Fallback value

' ); + + $this->assertSame( + '

Fallback value

', + trim( $content ), + 'The post content should show the fallback value instead of the custom field value.' + ); + } + /** * Tests that a block connected without specifying the custom field renders the fallback. * From ce4aa0c78e953e4c2be1d285851f0585eda8e311 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 29 Feb 2024 09:13:43 +0100 Subject: [PATCH 09/23] Move set up tp `wpSetUpBeforeClass` --- .../tests/block-bindings/postMetaSource.php | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index dbd096e38f7ee..181ccc6b2dd00 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -10,32 +10,22 @@ * @group block-bindings */ class Tests_Block_Bindings_Post_Meta_Source extends WP_UnitTestCase { + protected static $wp_meta_keys_saved; /** - * Sets up each test method. + * Set up for every method. */ - public function set_up() { + public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { global $post; - - parent::set_up(); - - $post = self::factory()->post->create_and_get( array() ); - setup_postdata( $post ); + $post = $factory->post->create_and_get(); + self::$wp_meta_keys_saved = isset( $GLOBALS['wp_meta_keys'] ) ? $GLOBALS['wp_meta_keys'] : array(); } /** - * Tear down each test method. + * Tear down for every method. */ - public function tear_down() { - // Removes custom fields registered by test cases. - $meta_keys = get_registered_meta_keys( 'post', '' ); - foreach ( $meta_keys as $meta_key_name => $meta_key_value ) { - if ( str_contains( $meta_key_name, 'tests' ) ) { - unregister_meta_key( 'post', $meta_key_name ); - } - } - - parent::tear_down(); + public static function wpTearDownAfterClass() { + $GLOBALS['wp_meta_keys'] = self::$wp_meta_keys_saved; } /** From f1655d673b72a0d985322ed1a6a04f84d78dc360 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 29 Feb 2024 09:20:52 +0100 Subject: [PATCH 10/23] Add test for non existing meta key --- .../tests/block-bindings/postMetaSource.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index 181ccc6b2dd00..d678f9820b4c9 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -120,6 +120,21 @@ function () { ); } + /** + * Tests that a block connected to a meta key that doesn't exist renders the fallback. + * + * @ticket 60651 + */ + public function test_binding_to_non_existing_meta_key() { + $content = apply_filters( 'the_content', '

Fallback value

' ); + + $this->assertSame( + '

Fallback value

', + trim( $content ), + 'The post content should show the fallback value.' + ); + } + /** * Tests that a block connected without specifying the custom field renders the fallback. * From 01d45e5b489dd9d6d4ed79d4f46aed11961e6ddc Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 29 Feb 2024 09:23:50 +0100 Subject: [PATCH 11/23] Remove filters in tests --- .../tests/block-bindings/postMetaSource.php | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index d678f9820b4c9..2b6da9a1be0ca 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -71,11 +71,13 @@ public function test_custom_field_value_is_not_shown_in_password_protected_posts ) ); + function wp_tests_require_post_password() { + return true; + } + add_filter( 'post_password_required', - function () { - return true; - } + 'wp_tests_require_post_password' ); $content = apply_filters( 'the_content', '

Fallback value

' ); @@ -85,6 +87,11 @@ function () { trim( $content ), 'The post content should show the fallback value instead of the custom field value.' ); + + remove_filter( + 'post_password_required', + 'wp_tests_post_password_required' + ); } /** @@ -104,11 +111,13 @@ public function test_custom_field_value_is_not_shown_in_non_viewable_posts() { ) ); + function wp_tests_make_post_status_not_viewable() { + return false; + } + add_filter( 'is_post_status_viewable', - function () { - return false; - } + 'wp_tests_make_post_status_not_viewable' ); $content = apply_filters( 'the_content', '

Fallback value

' ); @@ -118,6 +127,11 @@ function () { trim( $content ), 'The post content should show the fallback value instead of the custom field value.' ); + + remove_filter( + 'is_post_status_viewable', + 'wp_tests_make_post_status_not_viewable' + ); } /** From 7d253024900d285c4bef5117255bcc78724098b3 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 29 Feb 2024 10:58:03 +0100 Subject: [PATCH 12/23] Refactor the way post content is modified --- .../tests/block-bindings/postMetaSource.php | 57 ++++++++++++------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index 2b6da9a1be0ca..bca3118e767f3 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -10,14 +10,34 @@ * @group block-bindings */ class Tests_Block_Bindings_Post_Meta_Source extends WP_UnitTestCase { + protected static $post; protected static $wp_meta_keys_saved; + /** + * Modify the post content. + * + * @param string $content The new content. + */ + private function getModifiedPostContent( $content ) { + self::$post->post_content = $content; + // Update the global $post variable to ensure all tests get the correct $post context. + $this->updateGlobalPost(); + return apply_filters( 'the_content', self::$post->post_content ); + } + + /** + * Update the global $post variable. + */ + private function updateGlobalPost() { + global $post; + $post = self::$post; + } + /** * Set up for every method. */ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { - global $post; - $post = $factory->post->create_and_get(); + self::$post = $factory->post->create_and_get(); self::$wp_meta_keys_saved = isset( $GLOBALS['wp_meta_keys'] ) ? $GLOBALS['wp_meta_keys'] : array(); } @@ -45,12 +65,11 @@ public function test_custom_field_value_is_rendered() { ) ); - $content = apply_filters( 'the_content', '

Fallback value

' ); - + $content = $this->getModifiedPostContent( '

Fallback value

' ); $this->assertSame( '

Custom field value

', - trim( $content ), - 'The post content should show the value of the custom field.' + $content, + 'The post content should show the value of the custom field . ' ); } @@ -80,11 +99,10 @@ function wp_tests_require_post_password() { 'wp_tests_require_post_password' ); - $content = apply_filters( 'the_content', '

Fallback value

' ); - + $content = $this->getModifiedPostContent( '

Fallback value

' ); $this->assertSame( '

Fallback value

', - trim( $content ), + $content, 'The post content should show the fallback value instead of the custom field value.' ); @@ -120,11 +138,10 @@ function wp_tests_make_post_status_not_viewable() { 'wp_tests_make_post_status_not_viewable' ); - $content = apply_filters( 'the_content', '

Fallback value

' ); - + $content = $this->getModifiedPostContent( '

Fallback value

' ); $this->assertSame( '

Fallback value

', - trim( $content ), + $content, 'The post content should show the fallback value instead of the custom field value.' ); @@ -140,11 +157,11 @@ function wp_tests_make_post_status_not_viewable() { * @ticket 60651 */ public function test_binding_to_non_existing_meta_key() { - $content = apply_filters( 'the_content', '

Fallback value

' ); + $content = $this->getModifiedPostContent( '

Fallback value

' ); $this->assertSame( '

Fallback value

', - trim( $content ), + $content, 'The post content should show the fallback value.' ); } @@ -155,11 +172,11 @@ public function test_binding_to_non_existing_meta_key() { * @ticket 60651 */ public function test_binding_without_key_renders_the_fallback() { - $content = apply_filters( 'the_content', '

Fallback value

' ); + $content = $this->getModifiedPostContent( '

Fallback value

' ); $this->assertSame( '

Fallback value

', - trim( $content ), + $content, 'The post content should show the fallback value.' ); } @@ -181,11 +198,11 @@ public function test_protected_field_value_is_not_shown() { ) ); - $content = apply_filters( 'the_content', '

Fallback value

' ); + $content = $this->getModifiedPostContent( '

Fallback value

' ); $this->assertSame( '

Fallback value

', - trim( $content ), + $content, 'The post content should show the fallback value instead of the protected value.' ); } @@ -207,11 +224,11 @@ public function test_custom_field_not_exposed_in_rest_api_is_not_shown() { ) ); - $content = apply_filters( 'the_content', '

Fallback value

' ); + $content = $this->getModifiedPostContent( '

Fallback value

' ); $this->assertSame( '

Fallback value

', - trim( $content ), + $content, 'The post content should show the fallback value instead of the protected value.' ); } From dfe02a5b177792f4b881423ccb03f08a077d484f Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 29 Feb 2024 11:05:01 +0100 Subject: [PATCH 13/23] Add test to check unsafe html is sanitized --- .../tests/block-bindings/postMetaSource.php | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index bca3118e767f3..7ac803485b3c5 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -100,16 +100,17 @@ function wp_tests_require_post_password() { ); $content = $this->getModifiedPostContent( '

Fallback value

' ); - $this->assertSame( - '

Fallback value

', - $content, - 'The post content should show the fallback value instead of the custom field value.' - ); remove_filter( 'post_password_required', 'wp_tests_post_password_required' ); + + $this->assertSame( + '

Fallback value

', + $content, + 'The post content should show the fallback value instead of the custom field value.' + ); } /** @@ -139,16 +140,17 @@ function wp_tests_make_post_status_not_viewable() { ); $content = $this->getModifiedPostContent( '

Fallback value

' ); - $this->assertSame( - '

Fallback value

', - $content, - 'The post content should show the fallback value instead of the custom field value.' - ); remove_filter( 'is_post_status_viewable', 'wp_tests_make_post_status_not_viewable' ); + + $this->assertSame( + '

Fallback value

', + $content, + 'The post content should show the fallback value instead of the custom field value.' + ); } /** @@ -232,4 +234,30 @@ public function test_custom_field_not_exposed_in_rest_api_is_not_shown() { 'The post content should show the fallback value instead of the protected value.' ); } + + /** + * Tests that meta key with unsafe HTML is sanitized. + * + * @ticket 60651 + */ + public function test_custom_field_with_unsafe_html_is_sanitized() { + register_meta( + 'post', + 'tests_unsafe_html_field', + array( + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', + 'default' => '', + ) + ); + + $content = $this->getModifiedPostContent( '

Fallback value

' ); + + $this->assertSame( + '

alert(“Unsafe HTML”)

', + $content, + 'The post content should not include the script tag.' + ); + } } From 6414a972113b884220806f58613aa37be382e329 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 29 Feb 2024 11:25:25 +0100 Subject: [PATCH 14/23] Move unsafe html test to render bindings --- .../tests/block-bindings/postMetaSource.php | 26 -------------- tests/phpunit/tests/block-bindings/render.php | 36 +++++++++++++++++++ 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index 7ac803485b3c5..9ef6d9062d00d 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -234,30 +234,4 @@ public function test_custom_field_not_exposed_in_rest_api_is_not_shown() { 'The post content should show the fallback value instead of the protected value.' ); } - - /** - * Tests that meta key with unsafe HTML is sanitized. - * - * @ticket 60651 - */ - public function test_custom_field_with_unsafe_html_is_sanitized() { - register_meta( - 'post', - 'tests_unsafe_html_field', - array( - 'show_in_rest' => true, - 'single' => true, - 'type' => 'string', - 'default' => '', - ) - ); - - $content = $this->getModifiedPostContent( '

Fallback value

' ); - - $this->assertSame( - '

alert(“Unsafe HTML”)

', - $content, - 'The post content should not include the script tag.' - ); - } } diff --git a/tests/phpunit/tests/block-bindings/render.php b/tests/phpunit/tests/block-bindings/render.php index 03da454e87b3d..aac4c417fd43f 100644 --- a/tests/phpunit/tests/block-bindings/render.php +++ b/tests/phpunit/tests/block-bindings/render.php @@ -198,4 +198,40 @@ public function test_update_block_with_value_from_source_image_placeholder() { 'The block content should be updated with the value returned by the source.' ); } + + /** + * Tests if the block content is sanitized when unsafe HTML is passed. + * + * @ticket 60651 + * + * @covers ::register_block_bindings_source + */ + public function test_source_value_with_unsafe_html_is_sanitized() { + $get_value_callback = function () { + return ''; + }; + + register_block_bindings_source( + self::SOURCE_NAME, + array( + 'label' => self::SOURCE_LABEL, + 'get_value_callback' => $get_value_callback, + ) + ); + + $block_content = << +

This should not appear

+ +HTML; + $parsed_blocks = parse_blocks( $block_content ); + $block = new WP_Block( $parsed_blocks[0] ); + $result = $block->render(); + + $this->assertSame( + '

alert("Unsafe HTML")

', + trim( $result ), + 'The block content should be updated with the value returned by the source.' + ); + } } From 193131fc0c3e6c69cfc4b3646f61b5e9878e51df Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 29 Feb 2024 11:32:24 +0100 Subject: [PATCH 15/23] Add post meta unsafe html test again --- .../tests/block-bindings/postMetaSource.php | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index 9ef6d9062d00d..7ac803485b3c5 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -234,4 +234,30 @@ public function test_custom_field_not_exposed_in_rest_api_is_not_shown() { 'The post content should show the fallback value instead of the protected value.' ); } + + /** + * Tests that meta key with unsafe HTML is sanitized. + * + * @ticket 60651 + */ + public function test_custom_field_with_unsafe_html_is_sanitized() { + register_meta( + 'post', + 'tests_unsafe_html_field', + array( + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', + 'default' => '', + ) + ); + + $content = $this->getModifiedPostContent( '

Fallback value

' ); + + $this->assertSame( + '

alert(“Unsafe HTML”)

', + $content, + 'The post content should not include the script tag.' + ); + } } From a0b761b8d30ba55a6d4c63ace1cb7496e99c2e9a Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 29 Feb 2024 12:12:36 +0100 Subject: [PATCH 16/23] Change how we modify the global $post variable --- .../tests/block-bindings/postMetaSource.php | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index 7ac803485b3c5..7fa8728064f8e 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -19,18 +19,8 @@ class Tests_Block_Bindings_Post_Meta_Source extends WP_UnitTestCase { * @param string $content The new content. */ private function getModifiedPostContent( $content ) { - self::$post->post_content = $content; - // Update the global $post variable to ensure all tests get the correct $post context. - $this->updateGlobalPost(); - return apply_filters( 'the_content', self::$post->post_content ); - } - - /** - * Update the global $post variable. - */ - private function updateGlobalPost() { - global $post; - $post = self::$post; + $GLOBALS['post']->post_content = $content; + return apply_filters( 'the_content', $GLOBALS['post']->post_content ); } /** @@ -48,6 +38,17 @@ public static function wpTearDownAfterClass() { $GLOBALS['wp_meta_keys'] = self::$wp_meta_keys_saved; } + /** + * Set up before each test. + * + * @since 6.5.0 + */ + public function set_up() { + parent::set_up(); + // This seems to be needed to ensure that $GLOBALS['post'] is not null in all the tests. + $GLOBALS['post'] = self::$post; + } + /** * Tests that a block connected to a custom field renders its value. * From 4cdf2419df23567913499d0d8dd82216dde49df8 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 29 Feb 2024 12:13:10 +0100 Subject: [PATCH 17/23] Use snake_case --- .../tests/block-bindings/postMetaSource.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index 7fa8728064f8e..f4779e6b4595d 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -18,7 +18,7 @@ class Tests_Block_Bindings_Post_Meta_Source extends WP_UnitTestCase { * * @param string $content The new content. */ - private function getModifiedPostContent( $content ) { + private function get_modified_post_content( $content ) { $GLOBALS['post']->post_content = $content; return apply_filters( 'the_content', $GLOBALS['post']->post_content ); } @@ -66,7 +66,7 @@ public function test_custom_field_value_is_rendered() { ) ); - $content = $this->getModifiedPostContent( '

Fallback value

' ); + $content = $this->get_modified_post_content( '

Fallback value

' ); $this->assertSame( '

Custom field value

', $content, @@ -100,7 +100,7 @@ function wp_tests_require_post_password() { 'wp_tests_require_post_password' ); - $content = $this->getModifiedPostContent( '

Fallback value

' ); + $content = $this->get_modified_post_content( '

Fallback value

' ); remove_filter( 'post_password_required', @@ -140,7 +140,7 @@ function wp_tests_make_post_status_not_viewable() { 'wp_tests_make_post_status_not_viewable' ); - $content = $this->getModifiedPostContent( '

Fallback value

' ); + $content = $this->get_modified_post_content( '

Fallback value

' ); remove_filter( 'is_post_status_viewable', @@ -160,7 +160,7 @@ function wp_tests_make_post_status_not_viewable() { * @ticket 60651 */ public function test_binding_to_non_existing_meta_key() { - $content = $this->getModifiedPostContent( '

Fallback value

' ); + $content = $this->get_modified_post_content( '

Fallback value

' ); $this->assertSame( '

Fallback value

', @@ -175,7 +175,7 @@ public function test_binding_to_non_existing_meta_key() { * @ticket 60651 */ public function test_binding_without_key_renders_the_fallback() { - $content = $this->getModifiedPostContent( '

Fallback value

' ); + $content = $this->get_modified_post_content( '

Fallback value

' ); $this->assertSame( '

Fallback value

', @@ -201,7 +201,7 @@ public function test_protected_field_value_is_not_shown() { ) ); - $content = $this->getModifiedPostContent( '

Fallback value

' ); + $content = $this->get_modified_post_content( '

Fallback value

' ); $this->assertSame( '

Fallback value

', @@ -227,7 +227,7 @@ public function test_custom_field_not_exposed_in_rest_api_is_not_shown() { ) ); - $content = $this->getModifiedPostContent( '

Fallback value

' ); + $content = $this->get_modified_post_content( '

Fallback value

' ); $this->assertSame( '

Fallback value

', @@ -253,7 +253,7 @@ public function test_custom_field_with_unsafe_html_is_sanitized() { ) ); - $content = $this->getModifiedPostContent( '

Fallback value

' ); + $content = $this->get_modified_post_content( '

Fallback value

' ); $this->assertSame( '

alert(“Unsafe HTML”)

', From 6e37a4c72e2dc5bd5271835dc340c95958653e78 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 29 Feb 2024 12:25:51 +0100 Subject: [PATCH 18/23] Use hooks helper function > > Co-authored-by: Pascal Birchler --- .../tests/block-bindings/postMetaSource.php | 24 ++++--------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index f4779e6b4595d..bfc93e3751758 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -91,21 +91,11 @@ public function test_custom_field_value_is_not_shown_in_password_protected_posts ) ); - function wp_tests_require_post_password() { - return true; - } - - add_filter( - 'post_password_required', - 'wp_tests_require_post_password' - ); + add_filter( 'post_password_required', '__return_true' ); $content = $this->get_modified_post_content( '

Fallback value

' ); - remove_filter( - 'post_password_required', - 'wp_tests_post_password_required' - ); + remove_filter( 'post_password_required', '__return_true' ); $this->assertSame( '

Fallback value

', @@ -135,17 +125,11 @@ function wp_tests_make_post_status_not_viewable() { return false; } - add_filter( - 'is_post_status_viewable', - 'wp_tests_make_post_status_not_viewable' - ); + add_filter( 'is_post_status_viewable', '__return_false' ); $content = $this->get_modified_post_content( '

Fallback value

' ); - remove_filter( - 'is_post_status_viewable', - 'wp_tests_make_post_status_not_viewable' - ); + remove_filter( 'is_post_status_viewable', '__return_false' ); $this->assertSame( '

Fallback value

', From 838927087f985c2da877f1b3f2ebc6d19cd8217b Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 29 Feb 2024 12:28:44 +0100 Subject: [PATCH 19/23] Remove outdated function --- tests/phpunit/tests/block-bindings/postMetaSource.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index bfc93e3751758..88d93120d7318 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -121,10 +121,6 @@ public function test_custom_field_value_is_not_shown_in_non_viewable_posts() { ) ); - function wp_tests_make_post_status_not_viewable() { - return false; - } - add_filter( 'is_post_status_viewable', '__return_false' ); $content = $this->get_modified_post_content( '

Fallback value

' ); From 953058daa19e6d26e0e7e8694b0e003a7190bd80 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Thu, 29 Feb 2024 12:32:13 +0100 Subject: [PATCH 20/23] Update class methods descriptions Co-authored-by: Pascal Birchler --- tests/phpunit/tests/block-bindings/postMetaSource.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index 88d93120d7318..8d8bd79fd1468 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -24,7 +24,7 @@ private function get_modified_post_content( $content ) { } /** - * Set up for every method. + * Sets up shared fixtures. */ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { self::$post = $factory->post->create_and_get(); @@ -32,7 +32,7 @@ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { } /** - * Tear down for every method. + * Tear down after class. */ public static function wpTearDownAfterClass() { $GLOBALS['wp_meta_keys'] = self::$wp_meta_keys_saved; From bc81da448e1cad32ed6581d7d22f55b4307d745b Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Thu, 29 Feb 2024 12:34:05 +0100 Subject: [PATCH 21/23] Unset global post variable after class Co-authored-by: Pascal Birchler --- tests/phpunit/tests/block-bindings/postMetaSource.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index 8d8bd79fd1468..0653ba7b00053 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -36,6 +36,7 @@ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { */ public static function wpTearDownAfterClass() { $GLOBALS['wp_meta_keys'] = self::$wp_meta_keys_saved; + unset( $GLOBALS['post'] ); } /** From 64f07843259ee9e184669060ea5d9ded422b4a68 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 29 Feb 2024 14:10:45 +0100 Subject: [PATCH 22/23] Add tests for bindings modifying html attribute --- .../tests/block-bindings/postMetaSource.php | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index 0653ba7b00053..d80aec07e9648 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -75,6 +75,31 @@ public function test_custom_field_value_is_rendered() { ); } + /** + * Tests that an html attribute connected to a custom field renders its value. + * + * @ticket 60651 + */ + public function test_html_attribute_connected_to_custom_field_value_is_rendered() { + register_meta( + 'post', + 'tests_url_custom_field', + array( + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', + 'default' => 'https://example.com/foo.png', + ) + ); + + $content = $this->get_modified_post_content( '
' ); + $this->assertSame( + '
', + $content, + 'The image src should point to the value of the custom field . ' + ); + } + /** * Tests that a blocks connected in a password protected post don't render the value. * From 56beecc567c502eb9b3c395c4685e9252b4dda1d Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sat, 2 Mar 2024 13:12:55 +0100 Subject: [PATCH 23/23] Apply suggestions from code review --- tests/phpunit/tests/block-bindings/postMetaSource.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/phpunit/tests/block-bindings/postMetaSource.php b/tests/phpunit/tests/block-bindings/postMetaSource.php index d80aec07e9648..81a8a5861adc3 100644 --- a/tests/phpunit/tests/block-bindings/postMetaSource.php +++ b/tests/phpunit/tests/block-bindings/postMetaSource.php @@ -36,7 +36,6 @@ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { */ public static function wpTearDownAfterClass() { $GLOBALS['wp_meta_keys'] = self::$wp_meta_keys_saved; - unset( $GLOBALS['post'] ); } /** @@ -46,7 +45,7 @@ public static function wpTearDownAfterClass() { */ public function set_up() { parent::set_up(); - // This seems to be needed to ensure that $GLOBALS['post'] is not null in all the tests. + // Needed because tear_down() will reset it between tests. $GLOBALS['post'] = self::$post; }