diff --git a/lib/experimental/html/class-wp-html-tag-processor.php b/lib/experimental/html/class-wp-html-tag-processor.php index 2cb2b565a654a0..02afdf9ecc005a 100644 --- a/lib/experimental/html/class-wp-html-tag-processor.php +++ b/lib/experimental/html/class-wp-html-tag-processor.php @@ -1221,13 +1221,24 @@ public function remove_class( $class_name ) { /** * Returns the string representation of the HTML Tag Processor. - * It closes the HTML Tag Processor and prevents further lookups and modifications. * * @since 6.2.0 + * @see get_updated_html * * @return string The processed HTML. */ public function __toString() { + return $this->get_updated_html(); + } + + /** + * Returns the string representation of the HTML Tag Processor. + * + * @since 6.2.0 + * + * @return string The processed HTML. + */ + public function get_updated_html() { // Short-circuit if there are no updates to apply. if ( ! count( $this->classname_updates ) && ! count( $this->attribute_updates ) ) { return $this->updated_html . substr( $this->html, $this->updated_bytes ); diff --git a/phpunit/html/wp-html-tag-processor-standalone-test.php b/phpunit/html/wp-html-tag-processor-standalone-test.php index cef9b45f7c5d5e..d5635360e3c907 100644 --- a/phpunit/html/wp-html-tag-processor-standalone-test.php +++ b/phpunit/html/wp-html-tag-processor-standalone-test.php @@ -175,7 +175,27 @@ public function test_attributes_parser_treats_slash_as_attribute_separator() { * * @covers __toString */ - public function test_tostring_applies_the_updates_so_far_and_keeps_the_processor_on_the_current_tag() { + public function tostring_returns_updated_html() { + $p = new WP_HTML_Tag_Processor( '
Test
' ); + $p->next_tag(); + $p->remove_attribute( 'id' ); + + $p->next_tag(); + $p->set_attribute( 'id', 'div-id-1' ); + $p->add_class( 'new_class_1' ); + + $this->assertEquals( + $p->get_updated_html(), + (string) $p + ); + } + + /** + * @ticket 56299 + * + * @covers get_updated_html + */ + public function test_get_updated_html_applies_the_updates_so_far_and_keeps_the_processor_on_the_current_tag() { $p = new WP_HTML_Tag_Processor( '
Test
' ); $p->next_tag(); $p->remove_attribute( 'id' ); @@ -185,24 +205,24 @@ public function test_tostring_applies_the_updates_so_far_and_keeps_the_processor $p->add_class( 'new_class_1' ); $this->assertSame( '
Test
', - (string) $p, - 'Calling __toString after updating the attributes of the second tag returned different HTML than expected' + $p->get_updated_html(), + 'Calling get_updated_html after updating the attributes of the second tag returned different HTML than expected' ); $p->set_attribute( 'id', 'div-id-2' ); $p->add_class( 'new_class_2' ); $this->assertSame( '
Test
', - (string) $p, - 'Calling __toString after updating the attributes of the second tag for the second time returned different HTML than expected' + $p->get_updated_html(), + 'Calling get_updated_html after updating the attributes of the second tag for the second time returned different HTML than expected' ); $p->next_tag(); $p->remove_attribute( 'id' ); $this->assertSame( '
Test
', - (string) $p, - 'Calling __toString after removing the id attribute of the third tag returned different HTML than expected' + $p->get_updated_html(), + 'Calling get_updated_html after removing the id attribute of the third tag returned different HTML than expected' ); } @@ -210,11 +230,11 @@ public function test_tostring_applies_the_updates_so_far_and_keeps_the_processor /** * @ticket 56299 * - * @covers __toString + * @covers get_updated_html */ - public function test_tostring_without_updating_any_attributes_returns_the_original_html() { + public function test_get_updated_html_without_updating_any_attributes_returns_the_original_html() { $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE ); - $this->assertSame( self::HTML_SIMPLE, (string) $p ); + $this->assertSame( self::HTML_SIMPLE, $p->get_updated_html() ); } /** @@ -241,7 +261,7 @@ public function test_next_tag_should_return_false_for_a_non_existing_tag() { * @ticket 56299 * * @covers next_tag - * @covers __toString + * @covers get_updated_html */ public function test_set_attribute_on_a_non_existing_tag_does_not_change_the_markup() { $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE ); @@ -250,8 +270,8 @@ public function test_set_attribute_on_a_non_existing_tag_does_not_change_the_mar $p->set_attribute( 'id', 'primary' ); $this->assertSame( self::HTML_SIMPLE, - (string) $p, - 'Calling __toString after updating a non-existing tag returned an HTML that was different from the original HTML' + $p->get_updated_html(), + 'Calling get_updated_html after updating a non-existing tag returned an HTML that was different from the original HTML' ); } @@ -294,7 +314,7 @@ public function test_set_attribute_prevents_xss( $attribute_value ) { * over the content and because we want to look at the raw values. */ $match = null; - preg_match( '~^
$~', (string) $p, $match ); + preg_match( '~^
$~', $p->get_updated_html(), $match ); list( , $actual_value ) = $match; $this->assertEquals( $actual_value, '"' . esc_attr( $attribute_value ) . '"' ); @@ -321,13 +341,13 @@ public function data_set_attribute_escapable_values() { * @ticket 56299 * * @covers set_attribute - * @covers __toString + * @covers get_updated_html */ public function test_set_attribute_with_a_non_existing_attribute_adds_a_new_attribute_to_the_markup() { $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE ); $p->next_tag(); $p->set_attribute( 'test-attribute', 'test-value' ); - $this->assertSame( '
Text
', (string) $p ); + $this->assertSame( '
Text
', $p->get_updated_html() ); } /** @@ -337,33 +357,33 @@ public function test_set_attribute_with_a_non_existing_attribute_adds_a_new_attr * @ticket 56299 * * @covers set_attribute - * @covers __toString + * @covers get_updated_html */ public function test_update_first_when_duplicated_attribute() { $p = new WP_HTML_Tag_Processor( '
Text
' ); $p->next_tag(); $p->set_attribute( 'id', 'updated-id' ); - $this->assertSame( '
Text
', (string) $p ); + $this->assertSame( '
Text
', $p->get_updated_html() ); } /** * @ticket 56299 * * @covers set_attribute - * @covers __toString + * @covers get_updated_html */ public function test_set_attribute_with_an_existing_attribute_name_updates_its_value_in_the_markup() { $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE ); $p->next_tag(); $p->set_attribute( 'id', 'new-id' ); - $this->assertSame( '
Text
', (string) $p ); + $this->assertSame( '
Text
', $p->get_updated_html() ); } /** * @ticket 56299 * * @covers set_attribute - * @covers __toString + * @covers get_updated_html */ public function test_next_tag_and_set_attribute_in_a_loop_update_all_tags_in_the_markup() { $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE ); @@ -371,7 +391,7 @@ public function test_next_tag_and_set_attribute_in_a_loop_update_all_tags_in_the $p->set_attribute( 'data-foo', 'bar' ); } - $this->assertSame( '
Text
', (string) $p ); + $this->assertSame( '
Text
', $p->get_updated_html() ); } /** @@ -387,86 +407,86 @@ public function test_next_tag_and_set_attribute_in_a_loop_update_all_tags_in_the * @ticket 56299 * * @covers remove_attribute - * @covers __toString + * @covers get_updated_html */ public function test_remove_first_when_duplicated_attribute() { $p = new WP_HTML_Tag_Processor( '
Text
' ); $p->next_tag(); $p->remove_attribute( 'id' ); - $this->assertSame( '
Text
', (string) $p ); + $this->assertSame( '
Text
', $p->get_updated_html() ); } /** * @ticket 56299 * * @covers remove_attribute - * @covers __toString + * @covers get_updated_html */ public function test_remove_attribute_with_an_existing_attribute_name_removes_it_from_the_markup() { $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE ); $p->next_tag(); $p->remove_attribute( 'id' ); - $this->assertSame( '
Text
', (string) $p ); + $this->assertSame( '
Text
', $p->get_updated_html() ); } /** * @ticket 56299 * * @covers remove_attribute - * @covers __toString + * @covers get_updated_html */ public function test_remove_attribute_with_a_non_existing_attribute_name_does_not_change_the_markup() { $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE ); $p->next_tag(); $p->remove_attribute( 'no-such-attribute' ); - $this->assertSame( self::HTML_SIMPLE, (string) $p ); + $this->assertSame( self::HTML_SIMPLE, $p->get_updated_html() ); } /** * @ticket 56299 * * @covers add_class - * @covers __toString + * @covers get_updated_html */ public function test_add_class_creates_a_class_attribute_when_there_is_none() { $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE ); $p->next_tag(); $p->add_class( 'foo-class' ); - $this->assertSame( '
Text
', (string) $p ); + $this->assertSame( '
Text
', $p->get_updated_html() ); } /** * @ticket 56299 * * @covers add_class - * @covers __toString + * @covers get_updated_html */ public function test_calling_add_class_twice_creates_a_class_attribute_with_both_class_names_when_there_is_no_class_attribute() { $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE ); $p->next_tag(); $p->add_class( 'foo-class' ); $p->add_class( 'bar-class' ); - $this->assertSame( '
Text
', (string) $p ); + $this->assertSame( '
Text
', $p->get_updated_html() ); } /** * @ticket 56299 * * @covers remove_class - * @covers __toString + * @covers get_updated_html */ public function test_remove_class_does_not_change_the_markup_when_there_is_no_class_attribute() { $p = new WP_HTML_Tag_Processor( self::HTML_SIMPLE ); $p->next_tag(); $p->remove_class( 'foo-class' ); - $this->assertSame( self::HTML_SIMPLE, (string) $p ); + $this->assertSame( self::HTML_SIMPLE, $p->get_updated_html() ); } /** * @ticket 56299 * * @covers add_class - * @covers __toString + * @covers get_updated_html */ public function test_add_class_appends_class_names_to_the_existing_class_attribute_when_one_already_exists() { $p = new WP_HTML_Tag_Processor( self::HTML_WITH_CLASSES ); @@ -475,7 +495,7 @@ public function test_add_class_appends_class_names_to_the_existing_class_attribu $p->add_class( 'bar-class' ); $this->assertSame( '
Text
', - (string) $p + $p->get_updated_html() ); } @@ -483,7 +503,7 @@ public function test_add_class_appends_class_names_to_the_existing_class_attribu * @ticket 56299 * * @covers remove_class - * @covers __toString + * @covers get_updated_html */ public function test_remove_class_removes_a_single_class_from_the_class_attribute_when_one_exists() { $p = new WP_HTML_Tag_Processor( self::HTML_WITH_CLASSES ); @@ -491,7 +511,7 @@ public function test_remove_class_removes_a_single_class_from_the_class_attribut $p->remove_class( 'main' ); $this->assertSame( '
Text
', - (string) $p + $p->get_updated_html() ); } @@ -499,7 +519,7 @@ public function test_remove_class_removes_a_single_class_from_the_class_attribut * @ticket 56299 * * @covers remove_class - * @covers __toString + * @covers get_updated_html */ public function test_calling_remove_class_with_all_listed_class_names_removes_the_existing_class_attribute_from_the_markup() { $p = new WP_HTML_Tag_Processor( self::HTML_WITH_CLASSES ); @@ -508,7 +528,7 @@ public function test_calling_remove_class_with_all_listed_class_names_removes_th $p->remove_class( 'with-border' ); $this->assertSame( '
Text
', - (string) $p + $p->get_updated_html() ); } @@ -516,7 +536,7 @@ public function test_calling_remove_class_with_all_listed_class_names_removes_th * @ticket 56299 * * @covers add_class - * @covers __toString + * @covers get_updated_html */ public function test_add_class_does_not_add_duplicate_class_names() { $p = new WP_HTML_Tag_Processor( self::HTML_WITH_CLASSES ); @@ -524,7 +544,7 @@ public function test_add_class_does_not_add_duplicate_class_names() { $p->add_class( 'with-border' ); $this->assertSame( '
Text
', - (string) $p + $p->get_updated_html() ); } @@ -532,7 +552,7 @@ public function test_add_class_does_not_add_duplicate_class_names() { * @ticket 56299 * * @covers add_class - * @covers __toString + * @covers get_updated_html */ public function test_add_class_preserves_class_name_order_when_a_duplicate_class_name_is_added() { $p = new WP_HTML_Tag_Processor( self::HTML_WITH_CLASSES ); @@ -540,7 +560,7 @@ public function test_add_class_preserves_class_name_order_when_a_duplicate_class $p->add_class( 'main' ); $this->assertSame( '
Text
', - (string) $p + $p->get_updated_html() ); } @@ -548,7 +568,7 @@ public function test_add_class_preserves_class_name_order_when_a_duplicate_class * @ticket 56299 * * @covers add_class - * @covers __toString + * @covers get_updated_html */ public function test_add_class_when_there_is_a_class_attribute_with_excessive_whitespaces() { $p = new WP_HTML_Tag_Processor( @@ -558,7 +578,7 @@ public function test_add_class_when_there_is_a_class_attribute_with_excessive_wh $p->add_class( 'foo-class' ); $this->assertSame( '
Text
', - (string) $p + $p->get_updated_html() ); } @@ -566,7 +586,7 @@ public function test_add_class_when_there_is_a_class_attribute_with_excessive_wh * @ticket 56299 * * @covers remove_class - * @covers __toString + * @covers get_updated_html */ public function test_remove_class_preserves_whitespaces_when_there_is_a_class_attribute_with_excessive_whitespaces() { $p = new WP_HTML_Tag_Processor( @@ -576,7 +596,7 @@ public function test_remove_class_preserves_whitespaces_when_there_is_a_class_at $p->remove_class( 'with-border' ); $this->assertSame( '
Text
', - (string) $p + $p->get_updated_html() ); } @@ -584,7 +604,7 @@ public function test_remove_class_preserves_whitespaces_when_there_is_a_class_at * @ticket 56299 * * @covers remove_class - * @covers __toString + * @covers get_updated_html */ public function test_removing_all_classes_removes_the_existing_class_attribute_from_the_markup_even_when_excessive_whitespaces_are_present() { $p = new WP_HTML_Tag_Processor( @@ -595,7 +615,7 @@ public function test_removing_all_classes_removes_the_existing_class_attribute_f $p->remove_class( 'with-border' ); $this->assertSame( '
Text
', - (string) $p + $p->get_updated_html() ); } @@ -609,7 +629,7 @@ public function test_removing_all_classes_removes_the_existing_class_attribute_f * * @covers add_class * @covers set_attribute - * @covers __toString + * @covers get_updated_html */ public function test_set_attribute_takes_priority_over_add_class() { $p = new WP_HTML_Tag_Processor( self::HTML_WITH_CLASSES ); @@ -618,8 +638,8 @@ public function test_set_attribute_takes_priority_over_add_class() { $p->set_attribute( 'class', 'set_attribute' ); $this->assertSame( '
Text
', - (string) $p, - 'Calling __toString after updating first tag\'s attributes did not return the expected HTML' + $p->get_updated_html(), + 'Calling get_updated_html after updating first tag\'s attributes did not return the expected HTML' ); $p = new WP_HTML_Tag_Processor( self::HTML_WITH_CLASSES ); @@ -628,8 +648,8 @@ public function test_set_attribute_takes_priority_over_add_class() { $p->add_class( 'add_class' ); $this->assertSame( '
Text
', - (string) $p, - 'Calling __toString after updating second tag\'s attributes did not return the expected HTML' + $p->get_updated_html(), + 'Calling get_updated_html after updating second tag\'s attributes did not return the expected HTML' ); } @@ -640,7 +660,7 @@ public function test_set_attribute_takes_priority_over_add_class() { * @covers remove_attribute * @covers add_class * @covers remove_class - * @covers __toString + * @covers get_updated_html */ public function test_advanced_use_case() { $input = <<remove_attribute( 'class' ); $this->assertFalse( $p->next_tag( 'non-existent' ), 'Querying a non-existing tag did not return false' ); $p->set_attribute( 'class', 'test' ); - $this->assertSame( $expected_output, (string) $p, 'Calling __toString after updating the attributes did not return the expected HTML' ); + $this->assertSame( $expected_output, $p->get_updated_html(), 'Calling get_updated_html after updating the attributes did not return the expected HTML' ); } /** @@ -738,7 +758,7 @@ public function test_advanced_use_case() { * * @covers remove_attribute * @covers set_attribute - * @covers __toString + * @covers get_updated_html */ public function test_correctly_parses_html_attributes_wrapped_in_single_quotation_marks() { $p = new WP_HTML_Tag_Processor( @@ -760,7 +780,7 @@ public function test_correctly_parses_html_attributes_wrapped_in_single_quotatio $p->set_attribute( 'id', 'single-quote' ); $this->assertSame( '
Text
', - (string) $p + $p->get_updated_html() ); } @@ -768,7 +788,7 @@ public function test_correctly_parses_html_attributes_wrapped_in_single_quotatio * @ticket 56299 * * @covers set_attribute - * @covers __toString + * @covers get_updated_html */ public function test_set_attribute_with_value_equals_to_true_adds_a_boolean_html_attribute_with_implicit_value() { $p = new WP_HTML_Tag_Processor( @@ -778,7 +798,7 @@ public function test_set_attribute_with_value_equals_to_true_adds_a_boolean_html $p->set_attribute( 'checked', true ); $this->assertSame( '
', - (string) $p + $p->get_updated_html() ); } @@ -786,7 +806,7 @@ public function test_set_attribute_with_value_equals_to_true_adds_a_boolean_html * @ticket 56299 * * @covers set_attribute - * @covers __toString + * @covers get_updated_html */ public function test_setting_a_boolean_attribute_to_false_removes_it_from_the_markup() { $p = new WP_HTML_Tag_Processor( @@ -796,7 +816,7 @@ public function test_setting_a_boolean_attribute_to_false_removes_it_from_the_ma $p->set_attribute( 'checked', false ); $this->assertSame( '
', - (string) $p + $p->get_updated_html() ); } @@ -804,21 +824,21 @@ public function test_setting_a_boolean_attribute_to_false_removes_it_from_the_ma * @ticket 56299 * * @covers set_attribute - * @covers __toString + * @covers get_updated_html */ public function test_setting_a_missing_attribute_to_false_does_not_change_the_markup() { $html_input = '
'; $p = new WP_HTML_Tag_Processor( $html_input ); $p->next_tag( 'input' ); $p->set_attribute( 'checked', false ); - $this->assertSame( $html_input, (string) $p ); + $this->assertSame( $html_input, $p->get_updated_html() ); } /** * @ticket 56299 * * @covers set_attribute - * @covers __toString + * @covers get_updated_html */ public function test_setting_a_boolean_attribute_to_a_string_value_adds_explicit_value_to_the_markup() { $p = new WP_HTML_Tag_Processor( @@ -828,7 +848,7 @@ public function test_setting_a_boolean_attribute_to_a_string_value_adds_explicit $p->set_attribute( 'checked', 'checked' ); $this->assertSame( '
', - (string) $p + $p->get_updated_html() ); } @@ -986,7 +1006,7 @@ public function data_rcdata_state() { * * @covers next_tag * @covers set_attribute - * @covers __toString + * @covers get_updated_html */ public function test_can_query_and_update_wrongly_nested_tags() { $p = new WP_HTML_Tag_Processor( @@ -998,7 +1018,7 @@ public function test_can_query_and_update_wrongly_nested_tags() { $p->set_attribute( 'class', 'p-class' ); $this->assertSame( '123

456789

', - (string) $p + $p->get_updated_html() ); } @@ -1007,7 +1027,7 @@ public function test_can_query_and_update_wrongly_nested_tags() { * * @covers next_tag * @covers remove_attribute - * @covers __toString + * @covers get_updated_html */ public function test_removing_attributes_works_even_in_malformed_html() { $p = new WP_HTML_Tag_Processor( self::HTML_MALFORMED ); @@ -1015,7 +1035,7 @@ public function test_removing_attributes_works_even_in_malformed_html() { $p->remove_attribute( 'Notifications<' ); $this->assertSame( '
Back to notifications
', - (string) $p + $p->get_updated_html() ); } @@ -1024,7 +1044,7 @@ public function test_removing_attributes_works_even_in_malformed_html() { * * @covers next_Tag * @covers set_attribute - * @covers __toString + * @covers get_updated_html */ public function test_updating_attributes_works_even_in_malformed_html_1() { $p = new WP_HTML_Tag_Processor( self::HTML_MALFORMED ); @@ -1034,7 +1054,7 @@ public function test_updating_attributes_works_even_in_malformed_html_1() { $p->set_attribute( 'id', 'second' ); $this->assertSame( '
Back to notifications
', - (string) $p + $p->get_updated_html() ); } @@ -1044,7 +1064,7 @@ public function test_updating_attributes_works_even_in_malformed_html_1() { * @covers next_tag * @covers set_attribute * @covers add_class - * @covers __toString + * @covers get_updated_html * * @dataProvider data_malformed_tag */ @@ -1057,7 +1077,7 @@ public function test_updating_attributes_works_even_in_malformed_html_2( $html_i $p->add_class( 'secondTag' ); $this->assertSame( $html_expected, - (string) $p + $p->get_updated_html() ); } diff --git a/phpunit/html/wp-html-tag-processor-wp-test.php b/phpunit/html/wp-html-tag-processor-wp-test.php index 6c3a30340b2677..41008800d0b751 100644 --- a/phpunit/html/wp-html-tag-processor-wp-test.php +++ b/phpunit/html/wp-html-tag-processor-wp-test.php @@ -62,7 +62,7 @@ public function test_set_attribute_prevents_xss( $value_to_set, $expected_result * over the content and because we want to look at the raw values. */ $match = null; - preg_match( '~^
$~', (string) $p, $match ); + preg_match( '~^
$~', $p->get_updated_html(), $match ); list( , $actual_value ) = $match; $this->assertEquals( $actual_value, '"' . $expected_result . '"' );