Convert URLs to Links in a String

Another common function that I get asked for is the ability to highlight links in a block of text that contains urls, but doesn't have them within anchor tags. So, to stop me hearing this question and advising people to 'use Google' here is a function that will do this. It very likely isn't bullet proof (and isn't the most elegant thing I've ever seen), but will hopefully be either good enough or provide inspiration for your own solution.

The function itself is below:

function convert_links($string)
{
	# Temporarily remove existing links
	if(preg_match_all('#<a[^>]*>.*?</a>#si', $string, $matches))
	{
		foreach($matches[0] as $key => $value)
		{
			$string = str_replace($value, '##Link_'.$key.'##', $string);
		}
	}
 
	# Add http:// references to anything that doesn't have a link, but make these removable, because our original didn't have them
	$string = preg_replace('#((?:[a-z0-9_\-]+\.){1,}[a-z0-9_\-]+)#si', '*http://*\1', $string);
	$string = preg_replace('#((?:ht|f)tps?://){1}\*http://\*#si', '\1', $string); // Fix for dual protocol declarations
 
	# Convert the string to contain links
	$string = preg_replace('!(\*)?((?:ht|f)tps?://)(\*)?((?:[a-z0-9_\-]+\.){1,}[a-z0-9_\-]+)([a-z0-9_\-\.\%\&/\?=;\+~#]+)*!si', '<a href="\2\4\5" title="Visit \4">\1\2\3\4\5</a>', $string);
 
	# Remove http:// references from those links that didn't originally start with them
	$string = str_replace('*http://*', '', $string);
 
	# Convert mailto: links
	$string = preg_replace('#([_\.0-9a-z-]+@([0-9a-z][0-9a-z_-]+\.)+[a-z]{2,3})#si', '<a href="mailto:\1" title="Contact \1">\1</a>', $string);
 
	# Reinstate existing links
	if(is_array($matches))
	{
		foreach($matches[0] as $key => $value)
		{
			$string = str_replace('##Link_'.$key.'##', $value, $string);
		}
	}
 
	return $string;
}

And an example of usage is:

$string = '<p>This string contains links that I want to highlight (www.test.co.uk)
 
over a couple of lines and in slightly different formats: http://music-teachers.firsttutors.co.uk/ or just sub.domain.com/folder/folder_links/page.php?test=1&whatever=2 but does not touch existing anchors (e.g. <a href="http://www.blah.co.uk" title="Visit www.blah.co.uk">www.blah.co.uk</a>)
 
It does e-mails too... test@my-domain.com 
 
you get the idea...</p>';
 
echo $string;
echo convert_links($string);

Which produces:

<!-- Original -->
<p>This string contains links that I want to highlight (www.test.co.uk)
 
over a couple of lines and in slightly different formats: http://music-teachers.firsttutors.co.uk/ or just sub.domain.com/folder/folder_links/page.php?test=1&whatever=2 but does not touch existing anchors (e.g. <a href="http://www.blah.co.uk" title="Visit www.blah.co.uk">www.blah.co.uk</a>)
 
It does e-mails too... test@my-domain.com 
 
you get the idea...</p>
 
 
<!-- After the function -->
<p>This string contains links that I want to highlight (<a href="http://www.test.co.uk" title="Visit www.test.co.uk">www.test.co.uk</a>)
 
over a couple of lines and in slightly different formats: <a href="http://music-teachers.firsttutors.co.uk/" title="Visit music-teachers.firsttutors.co.uk">http://music-teachers.firsttutors.co.uk/</a> or just <a href="http://sub.domain.com/folder/folder_links/page.php?test=1&whatever=2" title="Visit sub.domain.com">sub.domain.com/folder/folder_links/page.php?test=1&whatever=2</a> but does not touch existing anchors (e.g. <a href="http://www.blah.co.uk" title="Visit www.blah.co.uk">www.blah.co.uk</a>)
 
It does e-mails too... <a href="mailto:test@my-domain.com" title="Contact test@my-domain.com">test@my-domain.com</a> 
 
you get the idea...</p>

Hope it helps someone!