From c8823c71e81f40b51f32e7d5b7821fd985197d99 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Wed, 22 Feb 2023 16:22:33 +0100 Subject: [PATCH 1/2] Tag Processor: Add Bookmark Invalidation Logic --- .../html-api/class-wp-html-tag-processor.php | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) 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 42675ecd3cf91..eec376f5bcae9 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 @@ -1401,6 +1401,7 @@ private function class_name_updates_to_attributes_updates() { * Applies attribute updates to HTML document. * * @since 6.2.0 + * @since 6.3.0 Invalidate any bookmarks whose targets are overwritten. * * @return void */ @@ -1431,7 +1432,7 @@ private function apply_attributes_updates() { * Adjust bookmark locations to account for how the text * replacements adjust offsets in the input document. */ - foreach ( $this->bookmarks as $bookmark ) { + foreach ( $this->bookmarks as $bookmark_name => $bookmark ) { /* * Each lexical update which appears before the bookmark's endpoints * might shift the offsets for those endpoints. Loop through each change @@ -1442,20 +1443,22 @@ private function apply_attributes_updates() { $tail_delta = 0; foreach ( $this->lexical_updates as $diff ) { - $update_head = $bookmark->start >= $diff->start; - $update_tail = $bookmark->end >= $diff->start; - - if ( ! $update_head && ! $update_tail ) { + if ( $bookmark->start < $diff->start && $bookmark->end < $diff->start ) { break; } + if ( $bookmark->start >= $diff->start && $bookmark->end < $diff->end ) { + $this->release_bookmark( $bookmark_name ); + continue 2; + } + $delta = strlen( $diff->text ) - ( $diff->end - $diff->start ); - if ( $update_head ) { + if ( $bookmark->start >= $diff->start ) { $head_delta += $delta; } - if ( $update_tail ) { + if ( $bookmark->end >= $diff->end ) { $tail_delta += $delta; } } @@ -1467,6 +1470,18 @@ private function apply_attributes_updates() { $this->lexical_updates = array(); } + /** + * Checks whether a bookmark with the given name exists. + * + * @since 6.3.0 + * + * @param string $bookmark_name Name to identify a bookmark that potentially exists. + * @return bool Whether that bookmark exists. + */ + public function has_bookmark( $bookmark_name ) { + return array_key_exists( $bookmark_name, $this->bookmarks ); + } + /** * Move the internal cursor in the Tag Processor to a given bookmark's location. * From 8f43d6e3a57ed4519e632d89b8a6177a5e21f5b9 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Wed, 22 Feb 2023 17:51:04 +0100 Subject: [PATCH 2/2] Add unit tests --- .../html-api/wpHtmlTagProcessor-bookmark.php | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/phpunit/tests/html-api/wpHtmlTagProcessor-bookmark.php b/tests/phpunit/tests/html-api/wpHtmlTagProcessor-bookmark.php index 04a6ae590cd7d..caa631dffa698 100644 --- a/tests/phpunit/tests/html-api/wpHtmlTagProcessor-bookmark.php +++ b/tests/phpunit/tests/html-api/wpHtmlTagProcessor-bookmark.php @@ -40,6 +40,41 @@ public function test_release_bookmark() { $this->assertTrue( $p->release_bookmark( 'first li' ), 'Could not release a bookmark' ); } + /** + * @ticket 57788 + * + * @covers WP_HTML_Tag_Processor::has_bookmark + */ + public function test_has_bookmark_returns_false_if_bookmark_does_not_exist() { + $p = new WP_HTML_Tag_Processor( '
Test
' ); + $this->assertFalse( $p->has_bookmark( 'my-bookmark' ) ); + } + + /** + * @ticket 57788 + * + * @covers WP_HTML_Tag_Processor::has_bookmark + */ + public function test_has_bookmark_returns_true_if_bookmark_exists() { + $p = new WP_HTML_Tag_Processor( '
Test
' ); + $p->next_tag(); + $p->set_bookmark( 'my-bookmark' ); + $this->assertTrue( $p->has_bookmark( 'my-bookmark' ) ); + } + + /** + * @ticket 57788 + * + * @covers WP_HTML_Tag_Processor::has_bookmark + */ + public function test_has_bookmark_returns_false_if_bookmark_has_been_released() { + $p = new WP_HTML_Tag_Processor( '
Test
' ); + $p->next_tag(); + $p->set_bookmark( 'my-bookmark' ); + $p->release_bookmark( 'my-bookmark' ); + $this->assertFalse( $p->has_bookmark( 'my-bookmark' ) ); + } + /** * @ticket 56299 *