diff --git a/src/wp-includes/html-api/class-wp-html-tag-processor.php b/src/wp-includes/html-api/class-wp-html-tag-processor.php index fcf418e856d5e..0ff2cdc4dd10d 100644 --- a/src/wp-includes/html-api/class-wp-html-tag-processor.php +++ b/src/wp-includes/html-api/class-wp-html-tag-processor.php @@ -614,7 +614,7 @@ class WP_HTML_Tag_Processor { * * @since 6.5.0 * - * @var string + * @var int */ private $text_length; @@ -2894,11 +2894,13 @@ public function get_comment_type(): ?string { * @return string */ public function get_modifiable_text(): string { - if ( null === $this->text_starts_at || 0 === $this->text_length ) { + $has_enqueued_update = isset( $this->lexical_updates['modifiable text'] ); + + if ( ! $has_enqueued_update && ( null === $this->text_starts_at || 0 === $this->text_length ) ) { return ''; } - $text = isset( $this->lexical_updates['modifiable text'] ) + $text = $has_enqueued_update ? $this->lexical_updates['modifiable text']->text : substr( $this->html, $this->text_starts_at, $this->text_length ); diff --git a/tests/phpunit/tests/html-api/wpHtmlTagProcessorModifiableText.php b/tests/phpunit/tests/html-api/wpHtmlTagProcessorModifiableText.php index 717d061016a2d..03c65321e34bd 100644 --- a/tests/phpunit/tests/html-api/wpHtmlTagProcessorModifiableText.php +++ b/tests/phpunit/tests/html-api/wpHtmlTagProcessorModifiableText.php @@ -39,6 +39,83 @@ public function test_get_modifiable_text_is_idempotent() { } } + /** + * Ensures that `get_modifiable_text()` reads enqueued updates when read + * from after writing; guarantees consistency through writes. + * + * @ticket 61617 + */ + public function test_get_modifiable_text_is_consistent_after_writes() { + $before = 'just some text'; + $after = 'different text'; + $processor = new WP_HTML_Tag_Processor( $before ); + $processor->next_token(); + + $this->assertSame( + '#text', + $processor->get_token_name(), + "Should have found text node but found '{$processor->get_token_name()}' instead: check test setup." + ); + + $this->assertSame( + $before, + $processor->get_modifiable_text(), + 'Should have found initial test text: check test setup.' + ); + + $processor->set_modifiable_text( $after ); + $this->assertSame( + $after, + $processor->get_modifiable_text(), + 'Should have found enqueued updated text.' + ); + + $processor->get_updated_html(); + $this->assertSame( + $after, + $processor->get_modifiable_text(), + 'Should have found updated text.' + ); + } + + /** + * Ensures that `get_modifiable_text()` reads enqueued updates when read from after + * writing when starting from an empty text; guarantees consistency through writes. + * + * @ticket 61617 + */ + public function test_get_modifiable_text_is_consistent_after_writes_to_empty_text() { + $after = 'different text'; + $processor = new WP_HTML_Tag_Processor( '' ); + $processor->next_token(); + + $this->assertSame( + 'SCRIPT', + $processor->get_token_name(), + "Should have found text node but found '{$processor->get_token_name()}' instead: check test setup." + ); + + $this->assertSame( + '', + $processor->get_modifiable_text(), + 'Should have found initial test text: check test setup.' + ); + + $processor->set_modifiable_text( $after ); + $this->assertSame( + $after, + $processor->get_modifiable_text(), + 'Should have found enqueued updated text.' + ); + + $processor->get_updated_html(); + $this->assertSame( + $after, + $processor->get_modifiable_text(), + 'Should have found updated text.' + ); + } + /** * Ensures that updates to modifiable text that are shorter than the * original text do not cause the parser to lose its orientation.