Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace text with hyperlinks where there isn't already one

A better example would be this:

$string = "That is a very nice ford mustang, if only every other ford was quite as nice as this honda";

I want to replace the car names with a link for manufacturer and model if they match, or just manufacturer, but if there is a make and model it puts links within links if you use str replace for example....

$remove = array("ford mustang","ford","honda");
$replaceWith = array("<a href='fordID'>ford</a>","<a href='fordmustangID'>ford mustang</a>","<a href='hondaID'>honda</a>");

This gives the result:

"That is a very nice <a href='<a href='fordmustangID'>ford mustang</a>ID'><a href='fordmustangID'>ford mustang</a></a>, if only every other <a href='fordmustangID'>ford mustang</a> was quite as nice as this <a href='hondaID'>honda</a>"

I only want it to create a hyperlink if there isn't one already like this:

  "That is a very nice <a href='fordmustangID'>ford mustang</a>, if only every other <a href='fordID'>ford</a> was quite as nice as this <a href='hondaID'>honda</a>"
like image 217
Chris Avatar asked Jan 25 '12 16:01

Chris


People also ask

How do I find and replace hyperlinks?

First, press keyboard shortcuts “Alt+ F9”. You can see all hyperlinks turn into their “Link” parts now. Press “Ctrl + H” to open the “Find and Replace” dialog box.


1 Answers

edit:

Took me a good while, but here's what I came up with:

function replaceLinks($replacements, $string){
    foreach($replacements as $key=>$val){
        $key=strtolower((string)$key);
        $newReplacements[$key]=array();
        $newReplacements[$key]['id']=$val;
        //strings to make sure the search isn't in front of
        $newReplacements[$key]['behinds']=array();
        //strings to make sure the search isn't behind
        $newReplacements[$key]['aheads']=array();
        //check for other searches this is a substring of
        foreach($replacements as $key2=>$val2){
            $key2=(string)$key2;
            /* 
            //debugging
            $b = ($key=='11 22'&&$key2=='11 22 33');
            if($b){
                l('strlen $key2: '.strlen($key2));
                l('strlen $key: '.strlen($key));
                l('strpos: '.(strpos($key2,$key)));

            }
            */
            //the second search is longer and the first is a substring of it
            if(strlen($key2)>strlen($key) && ($pos=strpos($key2,$key))!==false){
                //the first search isn't at the start of the second search ('the ford' and 'ford')
                if($pos!=0){
                    $newReplacements[$key]['behinds'][]=substr($key2,0,$pos);
                }
                //it's not at the end ('ford' and 'fords')
                if(($end=$pos+strlen($key))!=strlen($key2)){
                    $newReplacements[$key]['aheads'][]=substr($key2,$end);
                }
            }
        }
    }
    foreach($newReplacements as $key=>$item){
        //negative lookbehind for words or >
        $tmp="/(?<![\w>=])";
        //negative lookbehinds for the beginnings of other searches that this search is a subtring of
        foreach($item['behinds'] as $b){
            $tmp.="(?<!$b)";
        }
        //the actual search
        $tmp.="($key)";
        //negative lookaheads for ends of other searches that this is a substring of.
        foreach($item['aheads'] as $a){
            $tmp.="(?!$a)";
        }
        //case insensitive
        $tmp.='/ie';
        $replacementMatches[]=$tmp;
    }
    return preg_replace($replacementMatches,'"<a href=\"".$newReplacements[strtolower("$1")]["id"]."\">$1</a>"' ,$string);

}

Pass it an array such as the one you were talking about:

$replaceWith = array('ford mustang'=>123,'ford'=>42,'honda'=>324);

and a string:

$string = "That is a very nice ford mustang, if only every other ford was quite as nice as this honda";

echo replaceLinks($replaceWith,$string);

It gives precedence to larger string keys, so if you have ford and ford mustang, it will replace ford mustang with the link.




Not very practical, but might work.

$string = "That is a very nice ford mustang, if only every other ford was quite as nice as this honda";
$remove = array("/(?<![\w>])ford mustang(?![\w<])/",'/(?<![>\w])ford(?! mustang)(?![<\w])/',"/(?<![>\w])honda(?![<\w])/");
$replaceWith = array("<a href='fordmustangID'>ford mustang</a>","<a href='fordID'>ford</a>","<a href='hondaID'>honda</a>");
echo preg_replace($remove, $replaceWith,$string);

I used regular expressions with negative lookaheads and lookbehinds to make sure the portion of the string we're replacing isn't part of an alphanumeric sequence (like 12ford23 or afford) or touching the start or end tag of an element.

like image 73
mowwwalker Avatar answered Nov 12 '22 21:11

mowwwalker