Transformar links como www.example.com e http://twitter.com em links clicáveis. Parece uma tarefa fácil, certo? Vamos lá, existem alguns problemas que podem surgir, especialmente se o texto já estiver formatado em HTML.
Esta função primeiro elimina todos os perigos potenciais, extraindo links e tags e substituindo-os por um espaço reservado. Em seguida, extrai todos os URLs e os substitui por um espaço reservado, armazenando o link HTML completo. No final, ele substitui todos os marcadores de posição pelos links e tags.
<?php
/**
* Turn all URLs in clickable links.
*
* @param string $value
* @param array $protocols http/https, ftp, mail, twitter
* @param array $attributes
* @param string $mode normal or all
* @return string
*/
public function linkify($value, $protocols = array('http', 'mail'), array $attributes = array())
{
// Link attributes
$attr = '';
foreach ($attributes as $key => $val) {
$attr = ' ' . $key . '="' . htmlentities($val) . '"';
}
$links = array();
// Extract existing links and tags
$value = preg_replace_callback('~(<a .*?>.*?</a>|<.*?>)~i', function ($match) use (&$links) { return '<' . array_push($links, $match[1]) . '>'; }, $value);
// Extract text links for each protocol
foreach ((array)$protocols as $protocol) {
switch ($protocol) {
case 'http':
case 'https': $value = preg_replace_callback('~(?:(https?)://([^s<]+)|(www.[^s<]+?.[^s<]+))(?<![.,:])~i', function ($match) use ($protocol, &$links, $attr) { if ($match[1]) $protocol = $match[1]; $link = $match[2] ?: $match[3]; return '<' . array_push($links, "<a $attr href="$protocol://$link"">$link</a>"") . '>'; }