diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php
index f5002a45de1e8..80880c3121a0b 100644
--- a/src/wp-includes/functions.php
+++ b/src/wp-includes/functions.php
@@ -7679,7 +7679,7 @@ function get_tag_regex( $tag ) {
if ( empty( $tag ) ) {
return '';
}
- return sprintf( '<%1$s[^<]*(?:>[\s\S]*<\/%1$s>|\s*\/>)', tag_escape( $tag ) );
+ return sprintf( '<%1$s[^<]*?(?:>[\s\S]*?<\/%1$s>|\s*\/>)', tag_escape( $tag ) );
}
/**
diff --git a/tests/phpunit/tests/functions/getTagRegex.php b/tests/phpunit/tests/functions/getTagRegex.php
new file mode 100644
index 0000000000000..e8e1893e4c4c1
--- /dev/null
+++ b/tests/phpunit/tests/functions/getTagRegex.php
@@ -0,0 +1,113 @@
+assertSame( $expected, $matches[0] );
+ }
+
+ /**
+ * Data provider.
+ *
+ * @since 7.2.0
+ *
+ * @return array[]
+ */
+ public function data_get_tag_regex_matches() {
+ // Each case embeds the element(s) within surrounding HTML, mirroring the
+ // original usage in get_media_embedded_in_content(), which is passed a
+ // string of HTML that may contain media elements rather than the bare
+ // element on its own.
+ return array(
+ 'a single tag with a body' => array(
+ 'iframe',
+ '
Before.
After.
',
+ array( '' ),
+ ),
+
+ // The regression: a greedy match ran from the first opening tag to
+ // the last closing tag, merging both embeds and the text between
+ // them into a single match. See #26674.
+ 'two adjacent tags are matched separately' => array(
+ 'iframe',
+ '
Intro.
text
Outro.
',
+ array(
+ '',
+ '',
+ ),
+ ),
+
+ // A self-closing void element (an iframe cannot self-close), matched
+ // both with and without the space before the slash (comment:16).
+ 'a self-closing tag with a space' => array(
+ 'input',
+ '
A form field: and more text.
',
+ array( '' ),
+ ),
+
+ 'a self-closing tag without a space' => array(
+ 'input',
+ '
A form field: and more text.
',
+ array( '' ),
+ ),
+
+ 'a tag with a multiline body' => array(
+ 'video',
+ "
Watch:
\n\n
End.
",
+ array( "" ),
+ ),
+
+ 'no match when the tag is absent' => array(
+ 'iframe',
+ '
No embeds here.
',
+ array(),
+ ),
+ );
+ }
+
+ /**
+ * Tests that calling get_tag_regex() with an empty tag name returns an empty string.
+ *
+ * @ticket 26674
+ *
+ * @since 7.2.0
+ */
+ public function test_get_tag_regex_returns_empty_string_for_empty_tag() {
+ $this->assertSame( '', get_tag_regex( '' ) );
+ }
+
+ /**
+ * Tests that the tag name is passed through tag_escape(), so casing and
+ * invalid characters do not change the generated pattern.
+ *
+ * @ticket 26674
+ *
+ * @since 7.2.0
+ */
+ public function test_get_tag_regex_escapes_the_tag_name() {
+ $this->assertSame( get_tag_regex( 'iframe' ), get_tag_regex( 'IFRAME' ) );
+ }
+}