PHP autolink, если он еще не связан

Мой вопрос аналогичен этому вопросу:

Как имитировать поведение автоматической привязки StackOverflow

Однако это решение не работает для смешанного контента, который уже может содержать ссылки – любые URL-адреса, уже находящиеся внутри тегов A <a href="http://stackoverflow.com">My Link</a> , искажаются в <a href="<a href="http://stackoverflow.com">stackoverflow.com</a>">My Link</a>

Вот желаемое поведение:

До

 https://stackoverflow.com/ is a wonderful URL. <a href="https://stackoverflow.com/">Has already been linked.</a> 

После

 <a href="https://stackoverflow.com/">https://stackoverflow.com/</a> is a wonderful URL. <a href="https://stackoverflow.com/">Has already been linked.</a> 

Загрузите строку в формате HTML в ta DOM parser, перейдите по текстовым узлам и проверьте URL. Убедитесь, что родитель текстового узла не является тегом <a> , поэтому вы знаете, что текст, который вы получаете, еще не находится в ссылке. Теперь найдите все URL-адреса, преобразуйте их в теги <a> и замените их в DOM:

 $doc = new DOMDocument(); $doc->loadHTML( $str); $xpath = new DOMXpath($doc); foreach( $xpath->query('//text()') as $text) { if( !($text->parentNode->tagName == "a")) { $frag = $doc->createDocumentFragment(); $frag->appendXML( preg_replace('#(http://stackoverflow.com/)#', '<a href="$1">$1</a>', $text->data)); $text->parentNode->replaceChild( $frag, $text); } } 

Обратите внимание, что это зависит от регулярного выражения для идентификации URL-адресов, что является сложной задачей. Я предлагаю найти тот, который соответствует вашим потребностям, поскольку в настоящее время он использует:

 #(http://stackoverflow.com/)# 

Однако, учитывая этот ввод:

 http://stackoverflow.com/ is a wonderful URL. <a href="http://stackoverflow.com/">Has already been linked.</a> <a href="http://stackoverflow.com/">http://stackoverflow.com/</a> 

Он производит этот вывод :

 <p><a href="http://stackoverflow.com/">http://stackoverflow.com/</a> is a wonderful URL. <a href="http://stackoverflow.com/">Has already been linked.</a> <a href="http://stackoverflow.com/">http://stackoverflow.com/</a></p>