Reputation: 38318
My question is similar to this question:
How to mimic StackOverflow Auto-Link Behavior
However this solution doesn't work for mixed content that may already contain links - any URLs already inside of A tags <a href="http://stackoverflow.com">My Link</a>
are being mangled into <a href="<a href="http://stackoverflow.com">stackoverflow.com</a>">My Link</a>
Here's the desired behavior:
Before
https://stackoverflow.com/ is a wonderful URL.
<a href="https://stackoverflow.com/">Has already been linked.</a>
After
<a href="https://stackoverflow.com/">https://stackoverflow.com/</a> is a wonderful URL.
<a href="https://stackoverflow.com/">Has already been linked.</a>
Upvotes: 2
Views: 898
Reputation: 59699
Load up the string as HTML in ta DOM parser, iterate over the text nodes, and check for a URL. Make sure the text node's parent isn't an <a>
tag, so you know that the text you're getting is not already in a link. Now, find all of the URLs, convert them to <a>
tags, and replace them in the 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);
}
}
Note that this relies on a regex to identify URLs, which is a difficult task. I suggest finding one that suits your needs, as it is currently using:
#(http://stackoverflow.com/)#
However, given this input:
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>
Upvotes: 2