make_clickable( string $text ): string

Converts plaintext URI to HTML links.

Description

Converts URI, www and ftp, and email addresses. Finishes by fixing links within links.

Parameters

$textstringrequired
Content to convert URIs.

Return

string Content with converted URIs.

More Information

This function can be fed long strings with URIs and email links and will convert them into clickable links. You are not limited to feeding it just the link text itself (see the long string in the example above).

Source

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 paretheses.
				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 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.
			 */

			$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 );
}

Changelog

VersionDescription
0.71Introduced.

User Contributed Notes

  1. Skip to note 3 content

    This example shows how to use make_clickable with a string of text to turn any URLs within into links.

    <?php echo make_clickable( '<p>To find out more about this function, visit this link: https://developer.wordpress.org/reference/functions/make_clickable/</p&gt;' ); ?>

    The result will be:

    <p>To find out more about this function, visit this link: <a href="https://developer.wordpress.org/reference/functions/make_clickable/&quot; rel="nofollow">https://developer.wordpress.org/reference/functions/make_clickable/</a></p&gt;

You must log in before being able to contribute a note or feedback.