diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php
index 54883b840d7f4..6b6ebf87450a3 100644
--- a/src/wp-includes/default-filters.php
+++ b/src/wp-includes/default-filters.php
@@ -185,6 +185,11 @@
add_filter( $filter, 'shortcode_unautop' );
}
+// Clickable content filters
+add_filter( 'make_clickable', 'make_url_clickable', 2 );
+add_filter( 'make_clickable', 'make_ftp_clickable', 4 );
+add_filter( 'make_clickable', 'make_email_clickable', 6 );
+
// Format for RSS.
add_filter( 'term_name_rss', 'convert_chars' );
diff --git a/src/wp-includes/formatting.php b/src/wp-includes/formatting.php
index 3ecc352528fec..7d6c65932f3ab 100644
--- a/src/wp-includes/formatting.php
+++ b/src/wp-includes/formatting.php
@@ -3106,31 +3106,7 @@ function make_clickable( $text ) {
}
} else {
$ret = " $piece "; // Pad with whitespace to simplify the regexes.
-
- $url_clickable = '~
- ([\\s(<.,;:!?]) # 1: Leading whitespace, or punctuation.
- ( # 2: URL.
- [\\w]{1,20}+:// # Scheme and hier-part prefix.
- (?=\S{1,2000}\s) # Limit to URLs less than about 2000 characters long.
- [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]*+ # Non-punctuation URL character.
- (?: # Unroll the Loop: Only allow punctuation URL character if followed by a non-punctuation URL character.
- [\'.,;:!?)] # Punctuation URL character.
- [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]++ # Non-punctuation URL character.
- )*
- )
- (\)?) # 3: Trailing closing parenthesis (for parenthesis balancing post processing).
- (\\.\\w{2,6})? # 4: Allowing file extensions (e.g., .jpg, .png).
- ~xS';
- /*
- * The regex is a non-anchored pattern and does not have a single fixed starting character.
- * Tell PCRE to spend more time optimizing since, when used on a page load, it will probably be used several times.
- */
-
- $ret = preg_replace_callback( $url_clickable, '_make_url_clickable_cb', $ret );
-
- $ret = preg_replace_callback( '#([\s>])((www|ftp)\.[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]+)#is', '_make_web_ftp_clickable_cb', $ret );
- $ret = preg_replace_callback( '#([\s>])([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})#i', '_make_email_clickable_cb', $ret );
-
+ $ret = apply_filters( 'make_clickable', $ret );
$ret = substr( $ret, 1, -1 ); // Remove our whitespace padding.
$r .= $ret;
}
@@ -3140,6 +3116,69 @@ function make_clickable( $text ) {
return preg_replace( '#(]+?>|>))]+?>([^>]+?)#i', '$1$3', $r );
}
+/**
+ * Converts URLs in text into clickable links.
+ *
+ * @since 6.8.0
+ * @access private
+ *
+ * @param string $text The text to be processed.
+ * @return string Text with converted URLs.
+ */
+function make_url_clickable( $text ) {
+ $url_clickable = '~
+ ([\\s(<.,;:!?]) # 1: Leading whitespace, or punctuation
+ ( # 2: URL
+ [\\w]{1,20}+:// # Scheme and hier-part prefix
+ (?=\S{1,2000}\s) # Limit to URLs less than about 2000 characters long
+ [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]*+ # Non-punctuation URL character
+ (?: # Unroll the Loop: Only allow puctuation URL character if followed by a non-punctuation URL character
+ [\'.,;:!?)] # Punctuation URL character
+ [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]++ # Non-punctuation URL character
+ )*
+ )
+ (\)?) # 3: Trailing closing parenthesis (for parethesis balancing post processing)
+ ~xS';
+
+ // The regex is a non-anchored pattern and does not have a single fixed starting character.
+ // Tell PCRE to spend more time optimizing since, when used on a page load, it will probably be used several times.
+ return preg_replace_callback( $url_clickable, '_make_url_clickable_cb', $text );
+}
+
+/**
+ * Converts FTP and www addresses in text into clickable links.
+ *
+ * @since 6.8.0
+ * @access private
+ *
+ * @param string $text The text to be processed.
+ * @return string Text with converted FTP and www addresses.
+ */
+function make_ftp_clickable( $text ) {
+ return preg_replace_callback(
+ '#([\s>])((www|ftp)\.[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]+)#is',
+ '_make_web_ftp_clickable_cb',
+ $text
+ );
+}
+
+/**
+ * Converts email addresses in text into clickable links.
+ *
+ * @since 6.8.0
+ * @access private
+ *
+ * @param string $text The text to be processed.
+ * @return string Text with converted email addresses.
+ */
+function make_email_clickable( $text ) {
+ return preg_replace_callback(
+ '#([\s>])([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})#i',
+ '_make_email_clickable_cb',
+ $text
+ );
+}
+
/**
* Breaks a string into chunks by splitting at whitespace characters.
*
diff --git a/tests/phpunit/tests/formatting/makeClickableFilters.php b/tests/phpunit/tests/formatting/makeClickableFilters.php
new file mode 100644
index 0000000000000..63c21a1e15005
--- /dev/null
+++ b/tests/phpunit/tests/formatting/makeClickableFilters.php
@@ -0,0 +1,72 @@
+test@example.com';
+
+ $this->assertSame( $expected, make_clickable( $text ) );
+ }
+
+ /**
+ * @ticket 32787
+ */
+ public function test_remove_email_filter() {
+ remove_filter( 'make_clickable', 'make_email_clickable', 6 );
+
+ $text = 'Visit http://wordpress.org and test@example.com';
+ $expected = 'Visit http://wordpress.org and test@example.com';
+
+ $this->assertSame( $expected, make_clickable( $text ) );
+ }
+
+ /**
+ * @ticket 32787
+ */
+ public function test_remove_ftp_filter() {
+ remove_filter( 'make_clickable', 'make_ftp_clickable', 4 );
+
+ $text = 'Visit ftp.wordpress.org and http://wordpress.org';
+ $expected = 'Visit ftp.wordpress.org and http://wordpress.org';
+
+ $this->assertSame( $expected, make_clickable( $text ) );
+ }
+
+ /**
+ * @ticket 32787
+ */
+ public function test_remove_all_filters() {
+ remove_all_filters( 'make_clickable' );
+
+ $text = 'Visit http://wordpress.org, ftp.wordpress.org and test@example.com';
+ $expected = 'Visit http://wordpress.org, ftp.wordpress.org and test@example.com';
+
+ $this->assertSame( $expected, make_clickable( $text ) );
+ }
+}