leepowers
leepowers

Reputation: 38318

PHP autolink if not already linked

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

Answers (1)

nickb
nickb

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>

It produces this output:

<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

Related Questions