From 4e4b9574b7dba9db6433ccd65bd506bda7f6f6cc Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Tue, 20 Dec 2022 17:50:10 +0100 Subject: [PATCH 1/8] WP_HTML_Tag_Processor: Implement get_attribute_names() --- .../html/class-wp-html-tag-processor.php | 26 +++++++++++++++++++ phpunit/html/wp-html-tag-processor-test.php | 12 +++++++++ 2 files changed, 38 insertions(+) diff --git a/lib/experimental/html/class-wp-html-tag-processor.php b/lib/experimental/html/class-wp-html-tag-processor.php index 0dfa57f30f2aab..7f8286db76654a 100644 --- a/lib/experimental/html/class-wp-html-tag-processor.php +++ b/lib/experimental/html/class-wp-html-tag-processor.php @@ -1412,6 +1412,32 @@ public function get_attribute( $name ) { return html_entity_decode( $raw_value ); } + /** + * Returns the names of all attributes in the currently-opened tag. + * + * Example: + * + * $p = new WP_HTML_Tag_Processor( '
Test
' ); + * $p->next_tag( [ 'class_name' => 'test' ] ) === true; + * $p->get_attribute_names() === array( 'enabled', 'class', 'data-test-id' ); + * + * $p->next_tag( [] ) === false; + * $p->get_attribute_names() === null; + *
+ * + * @since 6.2.0 + * + * @param string $prefix Prefix of attributes whose value is requested. + * @return array|null List of attribute names, or `null` if not at a tag. + */ + function get_attribute_names() { + if ( null === $this->tag_name_starts_at ) { + return null; + } + + return array_keys( $this->attributes ); + } + /** * Returns the lowercase name of the currently-opened tag. * diff --git a/phpunit/html/wp-html-tag-processor-test.php b/phpunit/html/wp-html-tag-processor-test.php index e6b3d4d8071af5..fafd02cc7b15be 100644 --- a/phpunit/html/wp-html-tag-processor-test.php +++ b/phpunit/html/wp-html-tag-processor-test.php @@ -151,6 +151,18 @@ public function test_attributes_parser_treats_slash_as_attribute_separator() { $this->assertSame( 'test', $p->get_attribute( 'e' ), 'Accessing an existing e="test" did not return "test"' ); } + /** + * @covers WP_HTML_Tag_Processor::get_attribute_names + */ + public function test_get_attribute_names() { + $p = new WP_HTML_Tag_Processor( '
Test
' ); + $p->next_tag(); + $this->assertSame( + array( 'enabled', 'class', 'data-test-id' ), + $p->get_attribute_names() + ); + } + /** * @ticket 56299 * From 157301039737f0e1d784ac257f94f00613048db5 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Thu, 22 Dec 2022 11:53:46 +0100 Subject: [PATCH 2/8] Remove superfluous parameter comment --- lib/experimental/html/class-wp-html-tag-processor.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/experimental/html/class-wp-html-tag-processor.php b/lib/experimental/html/class-wp-html-tag-processor.php index 7f8286db76654a..22ff19a5e0f162 100644 --- a/lib/experimental/html/class-wp-html-tag-processor.php +++ b/lib/experimental/html/class-wp-html-tag-processor.php @@ -1427,7 +1427,6 @@ public function get_attribute( $name ) { * * @since 6.2.0 * - * @param string $prefix Prefix of attributes whose value is requested. * @return array|null List of attribute names, or `null` if not at a tag. */ function get_attribute_names() { From 8be4ac9844c350f91cc7486ba4edff4820d6b5b6 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Mon, 2 Jan 2023 14:45:02 +0100 Subject: [PATCH 3/8] Move test down --- phpunit/html/wp-html-tag-processor-test.php | 24 ++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/phpunit/html/wp-html-tag-processor-test.php b/phpunit/html/wp-html-tag-processor-test.php index fafd02cc7b15be..cd59df546ab163 100644 --- a/phpunit/html/wp-html-tag-processor-test.php +++ b/phpunit/html/wp-html-tag-processor-test.php @@ -151,18 +151,6 @@ public function test_attributes_parser_treats_slash_as_attribute_separator() { $this->assertSame( 'test', $p->get_attribute( 'e' ), 'Accessing an existing e="test" did not return "test"' ); } - /** - * @covers WP_HTML_Tag_Processor::get_attribute_names - */ - public function test_get_attribute_names() { - $p = new WP_HTML_Tag_Processor( '
Test
' ); - $p->next_tag(); - $this->assertSame( - array( 'enabled', 'class', 'data-test-id' ), - $p->get_attribute_names() - ); - } - /** * @ticket 56299 * @@ -207,6 +195,18 @@ public function test_set_attribute_is_case_insensitive() { $this->assertEquals( '
Test
', $p->get_updated_html(), 'A case-insensitive set_attribute call did not update the existing attribute.' ); } + /** + * @covers WP_HTML_Tag_Processor::get_attribute_names + */ + public function test_get_attribute_names() { + $p = new WP_HTML_Tag_Processor( '
Test
' ); + $p->next_tag(); + $this->assertSame( + array( 'enabled', 'class', 'data-test-id' ), + $p->get_attribute_names() + ); + } + /** * @ticket 56299 * From 8c51859ddc4eadb1ae483cd692f0b41f966247c6 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Mon, 2 Jan 2023 15:09:12 +0100 Subject: [PATCH 4/8] Add test for get_attribute() when in closing tag --- phpunit/html/wp-html-tag-processor-test.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/phpunit/html/wp-html-tag-processor-test.php b/phpunit/html/wp-html-tag-processor-test.php index cd59df546ab163..6962ed8ddf211b 100644 --- a/phpunit/html/wp-html-tag-processor-test.php +++ b/phpunit/html/wp-html-tag-processor-test.php @@ -74,6 +74,19 @@ public function test_get_attribute_returns_null_when_not_in_open_tag() { $this->assertNull( $p->get_attribute( 'class' ), 'Accessing an attribute of a non-existing tag did not return null' ); } + /** + * @ticket 56299 + * + * @covers next_tag + * @covers get_attribute + */ + public function test_get_attribute_returns_null_when_in_closing_tag() { + $p = new WP_HTML_Tag_Processor( '
Test
' ); + $this->assertTrue( $p->next_tag( 'div' ), 'Querying an existing tag did not return true' ); + $this->assertTrue( $p->next_tag( array( 'tag_closers' => 'visit' ) ), 'Querying an existing closing tag did not return true' ); + $this->assertNull( $p->get_attribute( 'class' ), 'Accessing an attribute of a closing tag did not return null' ); + } + /** * @ticket 56299 * From ca06c6483a8a9399f401f5bf5a35bc4c463e2382 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Mon, 2 Jan 2023 15:20:44 +0100 Subject: [PATCH 5/8] Add more get_attribute_names tests() --- phpunit/html/wp-html-tag-processor-test.php | 50 ++++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/phpunit/html/wp-html-tag-processor-test.php b/phpunit/html/wp-html-tag-processor-test.php index 6962ed8ddf211b..eddfc68fbe8453 100644 --- a/phpunit/html/wp-html-tag-processor-test.php +++ b/phpunit/html/wp-html-tag-processor-test.php @@ -209,9 +209,55 @@ public function test_set_attribute_is_case_insensitive() { } /** - * @covers WP_HTML_Tag_Processor::get_attribute_names + * @ticket 56299 + * + * @covers get_attribute_names + */ + public function test_get_attribute_names_returns_null_before_finding_tags() { + $p = new WP_HTML_Tag_Processor( '
Test
' ); + $this->assertNull( $p->get_attribute_names() ); + } + + /** + * @ticket 56299 + * + * @covers get_attribute + */ + public function test_get_attribute_names_returns_null_when_not_in_open_tag() { + $p = new WP_HTML_Tag_Processor( '
Test
' ); + $p->next_tag( 'p' ); + $this->assertNull( $p->get_attribute_names(), 'Accessing attributes of a non-existing tag did not return null' ); + } + + /** + * @ticket 56299 + * + * @covers get_attribute_names + */ + public function test_get_attribute_names_returns_null_when_in_closing_tag() { + $p = new WP_HTML_Tag_Processor( '
Test
' ); + $p->next_tag( 'div' ); + $p->next_tag( array( 'tag_closers' => 'visit' ) ); + $this->assertNull( $p->get_attribute_names(), 'Accessing attributes of a closing tag did not return null' ); + } + + /** + * @ticket 56299 + * + * @covers get_attribute_names + */ + public function test_get_attribute_names_returns_empty_array_when_no_attributes_present() { + $p = new WP_HTML_Tag_Processor( '
Test
' ); + $p->next_tag( 'div' ); + $this->assertSame( array(), $p->get_attribute_names(), 'Accessing the attributes on a tag without any did not return an empty array' ); + } + + /** + * @ticket 56299 + * + * @covers get_attribute_names */ - public function test_get_attribute_names() { + public function test_get_attribute_names_returns_attribute_names() { $p = new WP_HTML_Tag_Processor( '
Test
' ); $p->next_tag(); $this->assertSame( From 2dbf838a66fdb6a5e67194b2ca277932c5bbd508 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Mon, 2 Jan 2023 15:20:53 +0100 Subject: [PATCH 6/8] Fix implementation --- lib/experimental/html/class-wp-html-tag-processor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/experimental/html/class-wp-html-tag-processor.php b/lib/experimental/html/class-wp-html-tag-processor.php index 22ff19a5e0f162..e50cb3d43f76ea 100644 --- a/lib/experimental/html/class-wp-html-tag-processor.php +++ b/lib/experimental/html/class-wp-html-tag-processor.php @@ -1430,7 +1430,7 @@ public function get_attribute( $name ) { * @return array|null List of attribute names, or `null` if not at a tag. */ function get_attribute_names() { - if ( null === $this->tag_name_starts_at ) { + if ( $this->is_closing_tag || null === $this->tag_name_starts_at ) { return null; } From 5b248c08e6228422f4aefd6bceab5c724c6841f7 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Mon, 2 Jan 2023 15:58:57 +0100 Subject: [PATCH 7/8] Verify that get_attribute_names finds attribute added by set_attribute --- phpunit/html/wp-html-tag-processor-test.php | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/phpunit/html/wp-html-tag-processor-test.php b/phpunit/html/wp-html-tag-processor-test.php index eddfc68fbe8453..56b7f312971cf5 100644 --- a/phpunit/html/wp-html-tag-processor-test.php +++ b/phpunit/html/wp-html-tag-processor-test.php @@ -266,6 +266,29 @@ public function test_get_attribute_names_returns_attribute_names() { ); } + /** + * @ticket 56299 + * + * @covers set_attribute + * @covers get_updated_html + * @covers get_attribute_names + */ + public function test_get_attribute_names_returns_attribute_added_by_set_attribute() { + $p = new WP_HTML_Tag_Processor( '
Test
' ); + $p->next_tag(); + $p->set_attribute( 'test-attribute', 'test-value' ); + $this->assertSame( + '
Test
', + $p->get_updated_html(), + "Updated HTML doesn't include attribute added via set_attribute" + ); + $this->assertSame( + array( 'test-attribute', 'class' ), + $p->get_attribute_names(), + "Accessing attribute names doesn't find attribute added via set_attribute" + ); + } + /** * @ticket 56299 * From 9c3ab7e3997f4e5978c1bbb5762f26437cdb652b Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Mon, 2 Jan 2023 16:40:04 +0100 Subject: [PATCH 8/8] Fix PHPDoc string --- phpunit/html/wp-html-tag-processor-test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit/html/wp-html-tag-processor-test.php b/phpunit/html/wp-html-tag-processor-test.php index 56b7f312971cf5..03bd4914102025 100644 --- a/phpunit/html/wp-html-tag-processor-test.php +++ b/phpunit/html/wp-html-tag-processor-test.php @@ -221,7 +221,7 @@ public function test_get_attribute_names_returns_null_before_finding_tags() { /** * @ticket 56299 * - * @covers get_attribute + * @covers get_attribute_names */ public function test_get_attribute_names_returns_null_when_not_in_open_tag() { $p = new WP_HTML_Tag_Processor( '
Test
' );