From f584ad4027aae6372d17acf3a549059444b0a7e5 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Mon, 1 Jul 2024 16:53:23 +0200 Subject: [PATCH 01/18] Add support for image caption --- src/wp-includes/class-wp-block.php | 41 ++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index c6ca8a3bd42be..44cebdf5be98e 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -246,7 +246,7 @@ private function process_block_bindings() { $supported_block_attributes = array( 'core/paragraph' => array( 'content' ), 'core/heading' => array( 'content' ), - 'core/image' => array( 'id', 'url', 'title', 'alt' ), + 'core/image' => array( 'id', 'url', 'title', 'alt', 'caption' ), 'core/button' => array( 'url', 'text', 'linkTarget', 'rel' ), ); @@ -333,7 +333,44 @@ private function replace_html( string $block_content, string $attribute_name, $s switch ( $block_type->attributes[ $attribute_name ]['source'] ) { case 'html': case 'rich-text': - $block_reader = new WP_HTML_Tag_Processor( $block_content ); + // Create private anonymous class until the HTML API provides `set_inner_html` method. + $block_reader = new class($block_content) extends WP_HTML_Tag_Processor{ + public function set_inner_text( $new_content ) { + $tag_name = $this->get_tag(); + // Get position of the opener tag. + $this->set_bookmark( 'opener_tag' ); + $opener_tag_bookmark = $this->bookmarks['opener_tag']; + + // Visit the closing tag. + if ( ! $this->next_tag( + array( + 'tag_name' => $tag_name, + 'tag_closers' => 'visit', + ) + ) || ! $this->is_tag_closer() ) { + $this->release_bookmark( 'opener_tag' ); + return null; + } + + // Get position of the closer tag. + $this->set_bookmark( 'closer_tag' ); + $closer_tag_bookmark = $this->bookmarks['closer_tag']; + + // Appends the new content. + $after_opener_tag = $opener_tag_bookmark->start + $opener_tag_bookmark->length; + $inner_content_length = $closer_tag_bookmark->start - $after_opener_tag; + $this->lexical_updates[] = new WP_HTML_Text_Replacement( $after_opener_tag, $inner_content_length, $new_content ); + $this->release_bookmark( 'opener_tag' ); + $this->release_bookmark( 'closer_tag' ); + } + }; + + if ( 'core/image' === $this->name && 'caption' === $attribute_name ) { + if ( $block_reader->next_tag( 'figcaption' ) ) { + $block_reader->set_inner_text( wp_kses_post( $source_value ) ); + } + return $block_reader->get_updated_html(); + } // TODO: Support for CSS selectors whenever they are ready in the HTML API. // In the meantime, support comma-separated selectors by exploding them into an array. From 7d7d5c330b7a5590204aa253456e9f0a02e22dbf Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Mon, 1 Jul 2024 16:53:23 +0200 Subject: [PATCH 02/18] Use HTML_Processor instead of HTML_Tag_Processor --- src/wp-includes/class-wp-block.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index 44cebdf5be98e..d530f681fefb3 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -334,12 +334,12 @@ private function replace_html( string $block_content, string $attribute_name, $s case 'html': case 'rich-text': // Create private anonymous class until the HTML API provides `set_inner_html` method. - $block_reader = new class($block_content) extends WP_HTML_Tag_Processor{ + $bindings_processor = new class( $block_content, WP_HTML_Processor::CONSTRUCTOR_UNLOCK_CODE ) extends WP_HTML_Processor { public function set_inner_text( $new_content ) { $tag_name = $this->get_tag(); // Get position of the opener tag. $this->set_bookmark( 'opener_tag' ); - $opener_tag_bookmark = $this->bookmarks['opener_tag']; + $opener_tag_bookmark = $this->bookmarks['_opener_tag']; // Visit the closing tag. if ( ! $this->next_tag( @@ -354,7 +354,7 @@ public function set_inner_text( $new_content ) { // Get position of the closer tag. $this->set_bookmark( 'closer_tag' ); - $closer_tag_bookmark = $this->bookmarks['closer_tag']; + $closer_tag_bookmark = $this->bookmarks['_closer_tag']; // Appends the new content. $after_opener_tag = $opener_tag_bookmark->start + $opener_tag_bookmark->length; @@ -364,6 +364,7 @@ public function set_inner_text( $new_content ) { $this->release_bookmark( 'closer_tag' ); } }; + $block_reader = $bindings_processor::create_fragment( $block_content ); if ( 'core/image' === $this->name && 'caption' === $attribute_name ) { if ( $block_reader->next_tag( 'figcaption' ) ) { From 731d8699c34eef6f141e366c1dcb0300cf1ced56 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Mon, 1 Jul 2024 16:53:23 +0200 Subject: [PATCH 03/18] Move anonymous class inside image conditional --- src/wp-includes/class-wp-block.php | 65 +++++++++++++++--------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index d530f681fefb3..449b9a6084ebb 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -333,46 +333,47 @@ private function replace_html( string $block_content, string $attribute_name, $s switch ( $block_type->attributes[ $attribute_name ]['source'] ) { case 'html': case 'rich-text': - // Create private anonymous class until the HTML API provides `set_inner_html` method. - $bindings_processor = new class( $block_content, WP_HTML_Processor::CONSTRUCTOR_UNLOCK_CODE ) extends WP_HTML_Processor { - public function set_inner_text( $new_content ) { - $tag_name = $this->get_tag(); - // Get position of the opener tag. - $this->set_bookmark( 'opener_tag' ); - $opener_tag_bookmark = $this->bookmarks['_opener_tag']; - - // Visit the closing tag. - if ( ! $this->next_tag( - array( - 'tag_name' => $tag_name, - 'tag_closers' => 'visit', - ) - ) || ! $this->is_tag_closer() ) { - $this->release_bookmark( 'opener_tag' ); - return null; - } - - // Get position of the closer tag. - $this->set_bookmark( 'closer_tag' ); - $closer_tag_bookmark = $this->bookmarks['_closer_tag']; + if ( 'core/image' === $this->name && 'caption' === $attribute_name ) { + // Create private anonymous class until the HTML API provides `set_inner_html` method. + $bindings_processor = new class( $block_content, WP_HTML_Processor::CONSTRUCTOR_UNLOCK_CODE ) extends WP_HTML_Processor { + public function set_inner_text( $new_content ) { + $tag_name = $this->get_tag(); + // Get position of the opener tag. + $this->set_bookmark( 'opener_tag' ); + $opener_tag_bookmark = $this->bookmarks['_opener_tag']; + + // Visit the closing tag. + if ( ! $this->next_tag( + array( + 'tag_name' => $tag_name, + 'tag_closers' => 'visit', + ) + ) || ! $this->is_tag_closer() ) { + $this->release_bookmark( 'opener_tag' ); + return null; + } - // Appends the new content. - $after_opener_tag = $opener_tag_bookmark->start + $opener_tag_bookmark->length; - $inner_content_length = $closer_tag_bookmark->start - $after_opener_tag; - $this->lexical_updates[] = new WP_HTML_Text_Replacement( $after_opener_tag, $inner_content_length, $new_content ); - $this->release_bookmark( 'opener_tag' ); - $this->release_bookmark( 'closer_tag' ); - } - }; - $block_reader = $bindings_processor::create_fragment( $block_content ); + // Get position of the closer tag. + $this->set_bookmark( 'closer_tag' ); + $closer_tag_bookmark = $this->bookmarks['_closer_tag']; - if ( 'core/image' === $this->name && 'caption' === $attribute_name ) { + // Appends the new content. + $after_opener_tag = $opener_tag_bookmark->start + $opener_tag_bookmark->length; + $inner_content_length = $closer_tag_bookmark->start - $after_opener_tag; + $this->lexical_updates[] = new WP_HTML_Text_Replacement( $after_opener_tag, $inner_content_length, $new_content ); + $this->release_bookmark( 'opener_tag' ); + $this->release_bookmark( 'closer_tag' ); + } + }; + $block_reader = $bindings_processor::create_fragment( $block_content ); if ( $block_reader->next_tag( 'figcaption' ) ) { $block_reader->set_inner_text( wp_kses_post( $source_value ) ); } return $block_reader->get_updated_html(); } + $block_reader = new WP_HTML_Tag_Processor( $block_content ); + // TODO: Support for CSS selectors whenever they are ready in the HTML API. // In the meantime, support comma-separated selectors by exploding them into an array. $selectors = explode( ',', $block_type->attributes[ $attribute_name ]['selector'] ); From c360edffd82a356bb25c9c059ae8222450a3650b Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Mon, 1 Jul 2024 16:53:23 +0200 Subject: [PATCH 04/18] Remove release_bookmark calls --- src/wp-includes/class-wp-block.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index 449b9a6084ebb..01ae73d468e1c 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -349,7 +349,6 @@ public function set_inner_text( $new_content ) { 'tag_closers' => 'visit', ) ) || ! $this->is_tag_closer() ) { - $this->release_bookmark( 'opener_tag' ); return null; } @@ -361,8 +360,6 @@ public function set_inner_text( $new_content ) { $after_opener_tag = $opener_tag_bookmark->start + $opener_tag_bookmark->length; $inner_content_length = $closer_tag_bookmark->start - $after_opener_tag; $this->lexical_updates[] = new WP_HTML_Text_Replacement( $after_opener_tag, $inner_content_length, $new_content ); - $this->release_bookmark( 'opener_tag' ); - $this->release_bookmark( 'closer_tag' ); } }; $block_reader = $bindings_processor::create_fragment( $block_content ); From afbf38cd0f786022d8ef0c74ddb55ab371ff943b Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Mon, 1 Jul 2024 16:53:23 +0200 Subject: [PATCH 05/18] Don't grab bookmarks until the end --- src/wp-includes/class-wp-block.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index 01ae73d468e1c..1dd6616f20621 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -338,9 +338,8 @@ private function replace_html( string $block_content, string $attribute_name, $s $bindings_processor = new class( $block_content, WP_HTML_Processor::CONSTRUCTOR_UNLOCK_CODE ) extends WP_HTML_Processor { public function set_inner_text( $new_content ) { $tag_name = $this->get_tag(); - // Get position of the opener tag. + // Set position of the opener tag. $this->set_bookmark( 'opener_tag' ); - $opener_tag_bookmark = $this->bookmarks['_opener_tag']; // Visit the closing tag. if ( ! $this->next_tag( @@ -352,8 +351,11 @@ public function set_inner_text( $new_content ) { return null; } - // Get position of the closer tag. + // Set position of the closer tag. $this->set_bookmark( 'closer_tag' ); + + // Get opener and closer tag bookmarks. + $opener_tag_bookmark = $this->bookmarks['_opener_tag']; $closer_tag_bookmark = $this->bookmarks['_closer_tag']; // Appends the new content. From cbe79ee6d4277883e8eac8a72ad052bc1f4b29c6 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Mon, 1 Jul 2024 16:53:23 +0200 Subject: [PATCH 06/18] Add checks to ensure it doesn't replace unwanted html --- src/wp-includes/class-wp-block.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index 1dd6616f20621..fb236796deaf3 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -337,18 +337,26 @@ private function replace_html( string $block_content, string $attribute_name, $s // Create private anonymous class until the HTML API provides `set_inner_html` method. $bindings_processor = new class( $block_content, WP_HTML_Processor::CONSTRUCTOR_UNLOCK_CODE ) extends WP_HTML_Processor { public function set_inner_text( $new_content ) { - $tag_name = $this->get_tag(); + // Check that the processor is paused on an opener tag. + if ( + WP_HTML_Processor::STATE_MATCHED_TAG !== $this->parser_state || + $this->is_tag_closer() + ) { + return false; + } + // Set position of the opener tag. $this->set_bookmark( 'opener_tag' ); - // Visit the closing tag. + // Visit the closing tag, and check it exists. + $tag_name = $this->get_tag(); if ( ! $this->next_tag( array( 'tag_name' => $tag_name, 'tag_closers' => 'visit', ) ) || ! $this->is_tag_closer() ) { - return null; + return false; } // Set position of the closer tag. From 083c4e2db6cdc4daa0f866ea3c18c7d754bbb626 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Mon, 1 Jul 2024 16:53:23 +0200 Subject: [PATCH 07/18] Add comments to clarify the set_inner_text function --- src/wp-includes/class-wp-block.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index fb236796deaf3..1dfe127e7b7c9 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -336,6 +336,18 @@ private function replace_html( string $block_content, string $attribute_name, $s if ( 'core/image' === $this->name && 'caption' === $attribute_name ) { // Create private anonymous class until the HTML API provides `set_inner_html` method. $bindings_processor = new class( $block_content, WP_HTML_Processor::CONSTRUCTOR_UNLOCK_CODE ) extends WP_HTML_Processor { + /** + * Replace the inner text of an HTML with the passed content. + * + * THIS IS A STOP-GAP MEASURE IN CORE NOT TO BE EMULATED. + * IT IS A TEMPORARY SOLUTION THAT JUST WORKS FOR THIS SPECIFIC + * USE CASE UNTIL THE HTML PROCESSOR PROVIDES ITS OWN METHOD. + * + * @since 6.6.0 + * + * @param string $new_content New text to insert in the HTML element. + * @return bool Whether the inner text was properly replaced. + */ public function set_inner_text( $new_content ) { // Check that the processor is paused on an opener tag. if ( @@ -348,7 +360,10 @@ public function set_inner_text( $new_content ) { // Set position of the opener tag. $this->set_bookmark( 'opener_tag' ); - // Visit the closing tag, and check it exists. + /* + * This is a best-effort guess to visit the closer tag and check it exists. + * In the future, this code should rely on the HTML Processor for this kind of operation. + */ $tag_name = $this->get_tag(); if ( ! $this->next_tag( array( @@ -370,6 +385,7 @@ public function set_inner_text( $new_content ) { $after_opener_tag = $opener_tag_bookmark->start + $opener_tag_bookmark->length; $inner_content_length = $closer_tag_bookmark->start - $after_opener_tag; $this->lexical_updates[] = new WP_HTML_Text_Replacement( $after_opener_tag, $inner_content_length, $new_content ); + return true; } }; $block_reader = $bindings_processor::create_fragment( $block_content ); From 01d0e86a7f4276d34df77601f4617c026c17653c Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Mon, 1 Jul 2024 16:53:23 +0200 Subject: [PATCH 08/18] Clarify comments --- src/wp-includes/class-wp-block.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index 1dfe127e7b7c9..1bfa7c048206c 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -339,7 +339,7 @@ private function replace_html( string $block_content, string $attribute_name, $s /** * Replace the inner text of an HTML with the passed content. * - * THIS IS A STOP-GAP MEASURE IN CORE NOT TO BE EMULATED. + * THIS IS A TEMPORARY SOLUTION IN CORE NOT TO BE EMULATED. * IT IS A TEMPORARY SOLUTION THAT JUST WORKS FOR THIS SPECIFIC * USE CASE UNTIL THE HTML PROCESSOR PROVIDES ITS OWN METHOD. * @@ -349,7 +349,12 @@ private function replace_html( string $block_content, string $attribute_name, $s * @return bool Whether the inner text was properly replaced. */ public function set_inner_text( $new_content ) { - // Check that the processor is paused on an opener tag. + /* + * THIS IS A STOP-GAP MEASURE NOT TO BE EMULATED. + * + * Check that the processor is paused on an opener tag. + * + */ if ( WP_HTML_Processor::STATE_MATCHED_TAG !== $this->parser_state || $this->is_tag_closer() From 632e0154c121fe1ddfe0e611271e3d75f7898a76 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Mon, 1 Jul 2024 16:53:23 +0200 Subject: [PATCH 09/18] Add unit test for processing --- tests/phpunit/tests/block-bindings/render.php | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/phpunit/tests/block-bindings/render.php b/tests/phpunit/tests/block-bindings/render.php index 09c6fb50075fb..6b9139c001b93 100644 --- a/tests/phpunit/tests/block-bindings/render.php +++ b/tests/phpunit/tests/block-bindings/render.php @@ -298,4 +298,41 @@ public function test_default_binding_for_pattern_overrides() { 'The `__default` attribute should be replaced with the real attribute prior to the callback.' ); } + + /** + * Tests that replacing inner text for bound attributes works as expected. + * + * @ticket 61466 + * + * @covers WP_Block::process_block_bindings + */ + public function test_replacing_inner_text_with_block_bindings_value() { + $get_value_callback = function () { + return '$12.50'; + }; + + register_block_bindings_source( + self::SOURCE_NAME, + array( + 'label' => self::SOURCE_LABEL, + 'get_value_callback' => $get_value_callback, + ) + ); + + $block_content = << +
Default value
+ +HTML; + + $parsed_blocks = parse_blocks( $block_content ); + $block = new WP_Block( $parsed_blocks[0] ); + $result = $block->render(); + + $this->assertSame( + '
$12.50
', + trim( $result ), + 'The image caption should be updated with the value returned by the source.' + ); + } } From 79013a97a0e86f445ba419e0ddf0d2c11b21a78a Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Mon, 1 Jul 2024 16:53:23 +0200 Subject: [PATCH 10/18] Restrict method to figcaption Co-authored-by: Luis Herranz --- src/wp-includes/class-wp-block.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index 1bfa7c048206c..f6a771bcb3fab 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -337,7 +337,7 @@ private function replace_html( string $block_content, string $attribute_name, $s // Create private anonymous class until the HTML API provides `set_inner_html` method. $bindings_processor = new class( $block_content, WP_HTML_Processor::CONSTRUCTOR_UNLOCK_CODE ) extends WP_HTML_Processor { /** - * Replace the inner text of an HTML with the passed content. + * Replace the inner content of a figcaption element with the passed content. * * THIS IS A TEMPORARY SOLUTION IN CORE NOT TO BE EMULATED. * IT IS A TEMPORARY SOLUTION THAT JUST WORKS FOR THIS SPECIFIC @@ -345,10 +345,10 @@ private function replace_html( string $block_content, string $attribute_name, $s * * @since 6.6.0 * - * @param string $new_content New text to insert in the HTML element. - * @return bool Whether the inner text was properly replaced. + * @param string $new_content New content to insert in the figcaption element. + * @return bool Whether the inner content was properly replaced. */ - public function set_inner_text( $new_content ) { + public function set_content_between_figcaption_balanced_tags( $new_content ) { /* * THIS IS A STOP-GAP MEASURE NOT TO BE EMULATED. * @@ -357,6 +357,7 @@ public function set_inner_text( $new_content ) { */ if ( WP_HTML_Processor::STATE_MATCHED_TAG !== $this->parser_state || + 'figcaption' !== $this->get_tag() || $this->is_tag_closer() ) { return false; From cf25d7d3f024cf1a8623f4eb1751c011cd727043 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Mon, 1 Jul 2024 16:53:23 +0200 Subject: [PATCH 11/18] Call function properly --- src/wp-includes/class-wp-block.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index f6a771bcb3fab..32b1b50073dff 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -357,7 +357,7 @@ public function set_content_between_figcaption_balanced_tags( $new_content ) { */ if ( WP_HTML_Processor::STATE_MATCHED_TAG !== $this->parser_state || - 'figcaption' !== $this->get_tag() || + 'figcaption' !== $this->get_tag() || $this->is_tag_closer() ) { return false; @@ -396,7 +396,7 @@ public function set_content_between_figcaption_balanced_tags( $new_content ) { }; $block_reader = $bindings_processor::create_fragment( $block_content ); if ( $block_reader->next_tag( 'figcaption' ) ) { - $block_reader->set_inner_text( wp_kses_post( $source_value ) ); + $block_reader->set_content_between_figcaption_balanced_tags( wp_kses_post( $source_value ) ); } return $block_reader->get_updated_html(); } From 88df640c1e22e1a18f1f9fd21438fa74cef074a4 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Mon, 1 Jul 2024 16:53:23 +0200 Subject: [PATCH 12/18] Fix figcaption conditional --- src/wp-includes/class-wp-block.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index 32b1b50073dff..dbc50ecbd42b8 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -357,7 +357,7 @@ public function set_content_between_figcaption_balanced_tags( $new_content ) { */ if ( WP_HTML_Processor::STATE_MATCHED_TAG !== $this->parser_state || - 'figcaption' !== $this->get_tag() || + 'FIGCAPTION' !== $this->get_tag() || $this->is_tag_closer() ) { return false; From 1c4ac7278d9fe57a65d7af4322681e720fb1af1a Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Mon, 1 Jul 2024 16:55:27 +0200 Subject: [PATCH 13/18] Update private method comment --- src/wp-includes/class-wp-block.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index dbc50ecbd42b8..920dae3cdc3e9 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -339,11 +339,11 @@ private function replace_html( string $block_content, string $attribute_name, $s /** * Replace the inner content of a figcaption element with the passed content. * - * THIS IS A TEMPORARY SOLUTION IN CORE NOT TO BE EMULATED. - * IT IS A TEMPORARY SOLUTION THAT JUST WORKS FOR THIS SPECIFIC - * USE CASE UNTIL THE HTML PROCESSOR PROVIDES ITS OWN METHOD. + * DO NOT COPY THIS METHOD. + * THE HTML PROCESSOR WILL HAVE A PROPER METHOD. + * USE IT INSTEAD. * - * @since 6.6.0 + * @since 6.7.0 * * @param string $new_content New content to insert in the figcaption element. * @return bool Whether the inner content was properly replaced. From ac434829403543765ede11db4e56f36a4ef628db Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Mon, 1 Jul 2024 17:15:21 +0200 Subject: [PATCH 14/18] Use alternative method --- src/wp-includes/class-wp-block.php | 60 +++++++------------ .../html-api/class-wp-html-processor.php | 2 +- 2 files changed, 24 insertions(+), 38 deletions(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index 920dae3cdc3e9..8caf9a19fcb75 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -348,55 +348,41 @@ private function replace_html( string $block_content, string $attribute_name, $s * @param string $new_content New content to insert in the figcaption element. * @return bool Whether the inner content was properly replaced. */ - public function set_content_between_figcaption_balanced_tags( $new_content ) { - /* - * THIS IS A STOP-GAP MEASURE NOT TO BE EMULATED. - * - * Check that the processor is paused on an opener tag. - * - */ - if ( - WP_HTML_Processor::STATE_MATCHED_TAG !== $this->parser_state || - 'FIGCAPTION' !== $this->get_tag() || - $this->is_tag_closer() - ) { + public function set_figcaption_inner_text( $new_content ) { + // Check that the processor is paused on an opener tag. + if ( 'FIGCAPTION' !== $this->get_tag() || $this->is_tag_closer() ) { return false; } - // Set position of the opener tag. - $this->set_bookmark( 'opener_tag' ); - - /* - * This is a best-effort guess to visit the closer tag and check it exists. - * In the future, this code should rely on the HTML Processor for this kind of operation. - */ - $tag_name = $this->get_tag(); - if ( ! $this->next_tag( - array( - 'tag_name' => $tag_name, - 'tag_closers' => 'visit', - ) - ) || ! $this->is_tag_closer() ) { + // Once this element closes the depth will be one shallower than it is now. + $depth = $this->get_current_depth(); + while ( $this->next_token() && $this->get_current_depth() >= $depth ) { + // This is inside the FIGCAPTION element. + } + + if ( null !== $this->get_last_error() || $this->paused_at_incomplete_token() ) { return false; } - // Set position of the closer tag. - $this->set_bookmark( 'closer_tag' ); + $this->set_bookmark( 'here' ); - // Get opener and closer tag bookmarks. - $opener_tag_bookmark = $this->bookmarks['_opener_tag']; - $closer_tag_bookmark = $this->bookmarks['_closer_tag']; + $opening = $this->bookmarks[ $this->current_element->token->bookmark_name ]; + $closing = $this->bookmarks['_here']; + $start = $opening->start + $opening->length; + + $this->lexical_updates[] = new WP_HTML_Text_Replacement( + $start, + $closing->start - $start, + wp_kses_post( $new_content ) + ); - // Appends the new content. - $after_opener_tag = $opener_tag_bookmark->start + $opener_tag_bookmark->length; - $inner_content_length = $closer_tag_bookmark->start - $after_opener_tag; - $this->lexical_updates[] = new WP_HTML_Text_Replacement( $after_opener_tag, $inner_content_length, $new_content ); return true; } }; - $block_reader = $bindings_processor::create_fragment( $block_content ); + + $block_reader = $bindings_processor::create_fragment( $block_content ); if ( $block_reader->next_tag( 'figcaption' ) ) { - $block_reader->set_content_between_figcaption_balanced_tags( wp_kses_post( $source_value ) ); + $block_reader->set_figcaption_inner_text( $source_value ); } return $block_reader->get_updated_html(); } diff --git a/src/wp-includes/html-api/class-wp-html-processor.php b/src/wp-includes/html-api/class-wp-html-processor.php index 29f1c7ac6d4cc..24be640cd095d 100644 --- a/src/wp-includes/html-api/class-wp-html-processor.php +++ b/src/wp-includes/html-api/class-wp-html-processor.php @@ -223,7 +223,7 @@ class WP_HTML_Processor extends WP_HTML_Tag_Processor { * * @var ?WP_HTML_Stack_Event */ - private $current_element = null; + public $current_element = null; /** * Context node if created as a fragment parser. From 19465c0a80cc87cf576ed612a54683f182da9e5b Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Tue, 2 Jul 2024 14:30:11 +0200 Subject: [PATCH 15/18] Set opening bookmark --- src/wp-includes/class-wp-block.php | 10 +++++++--- src/wp-includes/html-api/class-wp-html-processor.php | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index 8caf9a19fcb75..ddcb8a90a2663 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -354,6 +354,9 @@ public function set_figcaption_inner_text( $new_content ) { return false; } + // Set position of the opener tag. + $this->set_bookmark( 'opening' ); + // Once this element closes the depth will be one shallower than it is now. $depth = $this->get_current_depth(); while ( $this->next_token() && $this->get_current_depth() >= $depth ) { @@ -364,10 +367,11 @@ public function set_figcaption_inner_text( $new_content ) { return false; } - $this->set_bookmark( 'here' ); + // Set position of the opener tag. + $this->set_bookmark( 'closing' ); - $opening = $this->bookmarks[ $this->current_element->token->bookmark_name ]; - $closing = $this->bookmarks['_here']; + $opening = $this->bookmarks['_opening']; + $closing = $this->bookmarks['_closing']; $start = $opening->start + $opening->length; $this->lexical_updates[] = new WP_HTML_Text_Replacement( diff --git a/src/wp-includes/html-api/class-wp-html-processor.php b/src/wp-includes/html-api/class-wp-html-processor.php index 24be640cd095d..29f1c7ac6d4cc 100644 --- a/src/wp-includes/html-api/class-wp-html-processor.php +++ b/src/wp-includes/html-api/class-wp-html-processor.php @@ -223,7 +223,7 @@ class WP_HTML_Processor extends WP_HTML_Tag_Processor { * * @var ?WP_HTML_Stack_Event */ - public $current_element = null; + private $current_element = null; /** * Context node if created as a fragment parser. From 1855e5dd2f22c6fa88772d101a097d236e1f2212 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Tue, 2 Jul 2024 14:31:23 +0200 Subject: [PATCH 16/18] Change comments --- src/wp-includes/class-wp-block.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index ddcb8a90a2663..5581469051eff 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -354,7 +354,7 @@ public function set_figcaption_inner_text( $new_content ) { return false; } - // Set position of the opener tag. + // Set position of the opening tag. $this->set_bookmark( 'opening' ); // Once this element closes the depth will be one shallower than it is now. @@ -367,7 +367,7 @@ public function set_figcaption_inner_text( $new_content ) { return false; } - // Set position of the opener tag. + // Set position of the closing tag. $this->set_bookmark( 'closing' ); $opening = $this->bookmarks['_opening']; From 4e77262e9da80645e6b86f5746e8dba763735a9c Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Tue, 2 Jul 2024 14:32:37 +0200 Subject: [PATCH 17/18] Change function name --- src/wp-includes/class-wp-block.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index 5581469051eff..afc6c31ff13f1 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -348,7 +348,7 @@ private function replace_html( string $block_content, string $attribute_name, $s * @param string $new_content New content to insert in the figcaption element. * @return bool Whether the inner content was properly replaced. */ - public function set_figcaption_inner_text( $new_content ) { + public function set_figcaption_inner_html( $new_content ) { // Check that the processor is paused on an opener tag. if ( 'FIGCAPTION' !== $this->get_tag() || $this->is_tag_closer() ) { return false; @@ -386,7 +386,7 @@ public function set_figcaption_inner_text( $new_content ) { $block_reader = $bindings_processor::create_fragment( $block_content ); if ( $block_reader->next_tag( 'figcaption' ) ) { - $block_reader->set_figcaption_inner_text( $source_value ); + $block_reader->set_figcaption_inner_html( $source_value ); } return $block_reader->get_updated_html(); } From 825f78effbbe234ef70a3502eeaad78ee833436c Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Wed, 3 Jul 2024 12:33:41 +0200 Subject: [PATCH 18/18] Change processor name and args --- src/wp-includes/class-wp-block.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index afc6c31ff13f1..b6631016b3e9f 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -335,7 +335,10 @@ private function replace_html( string $block_content, string $attribute_name, $s case 'rich-text': if ( 'core/image' === $this->name && 'caption' === $attribute_name ) { // Create private anonymous class until the HTML API provides `set_inner_html` method. - $bindings_processor = new class( $block_content, WP_HTML_Processor::CONSTRUCTOR_UNLOCK_CODE ) extends WP_HTML_Processor { + $bindings_processor_builder = new class( + 'Do not use this, it will not work. It is only here to create a subclass and call the static creator method', + WP_HTML_Processor::CONSTRUCTOR_UNLOCK_CODE + ) extends WP_HTML_Processor { /** * Replace the inner content of a figcaption element with the passed content. * @@ -384,7 +387,7 @@ public function set_figcaption_inner_html( $new_content ) { } }; - $block_reader = $bindings_processor::create_fragment( $block_content ); + $block_reader = $bindings_processor_builder::create_fragment( $block_content ); if ( $block_reader->next_tag( 'figcaption' ) ) { $block_reader->set_figcaption_inner_html( $source_value ); }