views:

157

answers:

5

Hello to everyone. I need to do this :

when a user insert a BBCode tag, with preg_replace and regex i do some trasformation.

e.g.

function forumBBCode($str){
   $format_search=array(
      '#\[url=(.*?)\](.*?)\[/url\]#i'
   );

   $format_replace=array(
      '<a class="lforum" target="_blank" href="$1">$2</a>'
   );

   $str=preg_replace($format_search, $format_replace, $str);
   $str=nl2br($str);
   return $str;
}

now i want also this : when a user insert a normal text with a link, this must be trasformed too. i can't do this trought preg_replace function, because if i write a code as

$format_search
'#(www\..*?)#i'

$format_replace
'<a class="lforum" target="_blank" href="$1">$1</a>'

it will convert the link 2 time (in the [url] and when the link is without this tag).

so i think to this function :

    function checkLinks($string) {
    $arrelab="";
    $arr=split(' |\r\n', $string);
    for($i=0; $i<sizeof($arr); $i++) {
        echo $i." - ".$arr[$i]."<br/>";
        if ((strpos($arr[$i], 'www.')!==false) or (strpos($arr[$i], 'http://')!==false) or (strpos($arr[$i], 'ftp://')!==false)) {
            if (strpos($arr[$i], '[url=')===false) {
                $arr[$i]='<a class="lforum" target="_blank" href="'.$arr[$i].'">'.$arr[$i].'</a>';
            }
        }

        $arrelab=$arrelab." ".$arr[$i];
    }
    return $arrelab;
}

the problem is that i need a split as for the newline, as for the empty space. any help would be appreciated.

p.s. sorry for my bad english :)

cheers

A: 

Your problem can be identified by reading your title.. parsing in combination with regex

You can't 'parse' html or bb-code with a regular expression because they are not regular languages.

You should write (or find) a bb-code parser instead of using regular expressions.

Google's first result for a BB-code parser is NBBC: The New BBCode Parser. But I've never used it so I can't comment on the quality.

Jacco
A: 

AUTHOR COMMENT

uhm, but for what i must do regex works. that's my whole function :

function forumBBCode($str){
   $format_search=array(
      '#\[b\](.*?)\[/b\]#is',
      '#\[i\](.*?)\[/i\]#is',
      '#\[u\](.*?)\[/u\]#is',
      '#\[s\](.*?)\[/s\]#is',
      '#\[quote=(.*?)\](.*?)\[/quote\]#is',       
      '#\[img\](.*?)\[/img\]#i',
      '#\[url=(.*?)\](.*?)\[/url\]#i',  

      '#(\:acc\:)#i',
      '#(\:bang\:)#i',
      '#(\:haha\:)#i',
      '#(\:nono\:)#i',
      '#(\:plause\:)#i',
      '#(\:rock\:)#i',
      '#(\:roto\:)#i',
      '#(\:sigh\:)#i',
      '#(\:\))#i',
      '#(\:\()#i',
      '#(\:uhm\:)#i',
      '#(\:yeah\:)#i',                                                                                        

      '#\[color=\#?([A-F0-9]{3}|[A-F0-9]{6})\](.*?)\[/color\]#is' // Font color ([color=#00F]text[/color])  
   );

   $format_replace=array(
      '<strong>$1</strong>',
      '<em>$1</em>',
      '<span style="text-decoration: underline;">$1</span>',
      '<span style="text-decoration: line-through;">$1</span>',
      '<blockquote class="quotearea"><i><a class="lblackbu" href="./index.php?status=userview&userv=$1">$1</a> wrote :</i><br />$2</blockquote>',
      '<a href="$1" target="_blank"><img width="200" height="200" src="$1" alt="" /></a>',
      '<a class="lforum" target="_blank" href="$1">$2</a>',

      '<img border="0" alt="" src="./img/smiles/acc.gif" />',
      '<img border="0" alt="" src="./img/smiles/bang.gif" />',
      '<img border="0" alt="" src="./img/smiles/haha.gif" />',
      '<img border="0" alt="" src="./img/smiles/nono.gif" />',
      '<img border="0" alt="" src="./img/smiles/plause.gif" />',
      '<img border="0" alt="" src="./img/smiles/rock.gif" />',
      '<img border="0" alt="" src="./img/smiles/roto.gif" />',
      '<img border="0" alt="" src="./img/smiles/sigh.gif" />',
      '<img border="0" alt="" src="./img/smiles/smile.gif" />',
      '<img border="0" alt="" src="./img/smiles/uff.gif" />',
      '<img border="0" alt="" src="./img/smiles/uhm.gif" />',
      '<img border="0" alt="" src="./img/smiles/yeah.gif" />',                

      '<span style="color: #$1;">$2</span>'
   );

   $str=preg_replace($format_search, $format_replace, $str);
   $str=nl2br($str);
   return $str;
}

it works, expect for this problem (and the recursive quote, that i'll try to solve after this problem)

markzzz
+1  A: 

The easiest option would be to parse the plain-text urls first and ensure they don't come immediately after an equals sign.

Update from Marios:

preg_replace('#(?<![>/"])(((http|https|ftp)://)?www[a-zA-Z0-9\-_\.]+)#im', '<a href="$1">$1</a>'

Aaron Harun
i've tried this, but it doesnt work (it cut the link after the www.)...
markzzz
There I fixed the non greedy option.
Aaron Harun
yeah, it rocks! to be honest, i don't have understand why it work, but i will learn it as exercise for regex! tnx again to you and mario :)
markzzz
A: 

It's easy to workaround with a lookbehind assertion.

preg_replace('#(?<![>/"])((http://)?www.........)#im', '<a href="$1">$1</a>'

Thus the regex will skip any URL enclosed in " or > or preceeded by /
It's a workaround, not a solution.

PS: target="_blank" is user pestering. Cut it out.

mario
uhm, I don't understand what do you mean exactly with that code.if I have a text doesn't enclosed with " or > the expression is not evalutated?should be nice a regex that doesn't evalutate "http://" text if it have the string [url=, but i cannot do it...
markzzz
What this regex does is to ensure that the url is not already enclosed in a link already. Run it *after* the `[url=` regex.
Aaron Harun
ah ok, now i understand what he means :) nice one, it seems to be good :)ps1. if i want "all characters permitted" after www this should be good no? www\..?*but it seems to fault...ps2. if i want both http and ftp? i write (?:http|ftp) instead of (http://) ?
markzzz
No, I edited my answer with the regex you would use. (Accept mario's though if you use it.)
Aaron Harun
tnx mario and aaron :) nice shoot!p.s. why this isn't a solution? just for curiosity...
markzzz
Because it works around the problem rather than directly solving it. Solving it would mean there is no collision in the first place.
Aaron Harun
yeah, but for my problem is enough :) NBBC would be the solution, but i prefeer don't use external libraries :)
markzzz
A: 

There is an easier way to do this. I have created a walk through in the RedBonzai Developers blog. The link to it is here: http://www.redbonzai.com/blog/web-development/how-to-create-a-bb-codes-function-in-php/

Let me know if you have any questions.

RedBonzai

RedBonzai Developers