make_clickable() │ WP 0.71
Convert plaintext URI to HTML links.
Converts URI, www and ftp, and email addresses. Finishes by fixing links within links.
1 time — 0.000662 sec (slow) | 50000 times — 6.64 sec (fast) | PHP 7.1.11, WP 4.9.8
No Hooks.
Return
String
. Content with converted URIs.
Usage
make_clickable( $text );
- $text(string) (required)
- Content to convert URIs.
Examples
#1 Turn a link (URL) in the text into a clickable HTML link:
<?php
$ret = "Some text http://example.com/page-108 and some other text.";
echo make_clickable( $ret );
?>
As a result of this example we get:
Some text <a href="http://example.com/page-108" rel="nofollow">http://example.com/page-108</a> and some other text.
#2 Make the links (URLs) clickable and with target blank
Let's turn all URLs in the content to clickable links and with target=_blank attribute (to open the links in a new tab). Use links_add_target().
<?php
$content = "Some text http://example.com/page-108 and some other text";
echo links_add_target( make_clickable( $content ) );
?>
As a result of this example we get:
Some text <a href="http://example.com/page-108" rel="nofollow" target="_blank">http://example.com/page-108</a> and some other text.
Changelog
make_clickable() make clickable code
WP 6.6.2
function make_clickable( $text ) {
$r = '';
$textarr = preg_split( '/(<[^<>]+>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // Split out HTML tags.
$nested_code_pre = 0; // Keep track of how many levels link is nested inside <pre> or <code>.
foreach ( $textarr as $piece ) {
if ( preg_match( '|^<code[\s>]|i', $piece )
|| preg_match( '|^<pre[\s>]|i', $piece )
|| preg_match( '|^<script[\s>]|i', $piece )
|| preg_match( '|^<style[\s>]|i', $piece )
) {
++$nested_code_pre;
} elseif ( $nested_code_pre
&& ( '</code>' === strtolower( $piece )
|| '</pre>' === strtolower( $piece )
|| '</script>' === strtolower( $piece )
|| '</style>' === strtolower( $piece )
)
) {
--$nested_code_pre;
}
if ( $nested_code_pre
|| empty( $piece )
|| ( '<' === $piece[0] && ! preg_match( '|^<\s*[\w]{1,20}+://|', $piece ) )
) {
$r .= $piece;
continue;
}
// Long strings might contain expensive edge cases...
if ( 10000 < strlen( $piece ) ) {
// ...break it up.
foreach ( _split_str_by_whitespace( $piece, 2100 ) as $chunk ) { // 2100: Extra room for scheme and leading and trailing parentheses.
if ( 2101 < strlen( $chunk ) ) {
$r .= $chunk; // Too big, no whitespace: bail.
} else {
$r .= make_clickable( $chunk );
}
}
} 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).
~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 = substr( $ret, 1, -1 ); // Remove our whitespace padding.
$r .= $ret;
}
}
// Cleanup of accidental links within links.
return preg_replace( '#(<a([ \r\n\t]+[^>]+?>|>))<a [^>]+?>([^>]+?)</a></a>#i', '$1$3</a>', $r );
}
Related Functions