Forum Moderators: coopster

Message Too Old, No Replies

Replacing Part of a String with PHP

Help with how to do this

         

Nick_W

1:32 pm on Apr 4, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi all,

Actually, it's not quite as simple as the title suggests....

I have user input with 'bb code' in it and need to run nl2br() over the input but leave certain sections like lists and pre-formatted areas.

Here's how I envision the proceedure:

  • Extract certain elements (like lists [ul])
  • Replace them with place holder
  • Run nl2br() on the remaining data
  • Replace the placeholders with the extracted elements

I'm not sure where to begin? - Can anyone suggest the functions I should be using for this?

Many thanks..

Nick

dmorison

2:16 pm on Apr 4, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi Nick,

Are you sure you need to worry too much?

Using your example of <ul><li> etc. etc., you should find (under the latest!DOCTYPE's) that a single <br> is ignored by browsers that interpret HTML correctly.

If you actually want a break between elements of the list you must supply 2 <br>'s....

Try it and see...

Hope this helps!

andreasfriedrich

2:36 pm on Apr 4, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



preg_split [php.net] your code on the start and end tags of those sections that you want to exclude and have it return the delimiter as well by using the PREG_SPLIT_DELIM_CAPTURE flag and enclosing them in parens. Then loop over the array and check each value whether it starts with a start tag or end tag. Have a variable like $in_list that you increase by one when you encounter a list start tag and decrease when you encounter a list end tag. If $in_list is false, use nl2br [php.net]. If it is true donīt. After you are done simply echo [php.net] the array or implode [php.net] it into a string again.

BTW why not use the code I sent you that creates P [w3.org] elements instead of using simple line breaks?

Andreas

Nick_W

9:50 am on Apr 5, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, I couldn't get it to work. I added a few tags but I'm pretty sure I didn't mess with anything else. It just puts the whole block of input inside one <p></p>

Here it is:

[pre]
function bbcode($data) {
$data = preg_replace(array(
"'\[url=([^]]+?)\]'",
"'\[/url\]'",
"'\[url\]([^[]+?)\[/url\]'",
"'\[code\]'",
"'\[/code\]'",
"'\[q\]'",
"'\[/q\]'",
"'\[ul\]'",
"'\[/ul\]'",
"'\[li\]'",
"'\[/li\]'",
), array(
"<a href=\"\\1\">",
"</a>",
"<a href=\"$1\">\\1</a>",
"<pre><code>",
"</code></pre>",
"<q>",
"</q>",
"<ul>",
"</ul>",
"<li>",
"</li>",
), $data);
foreach(preg_split("/\n+Ķ(\r\n)+/", $data) as $token) {
if(strlen($token) == 0) continue;
if(preg_match("/^<.*>$/", $token)) { $s .= $token; continue; }
$s .= "<p>$token</p>";
}
return $s;
}[/pre]

Nick

andreasfriedrich

10:34 pm on Apr 6, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



From the StickyMail I sent you ;-)

If you add your own style codes make sure that the replacement string for those elements that are block level style elements start with a double newline for start tags and end with a double newline for end tags. That way user input like the following will be handled correctly.

[ ul ] and [ code ] are certainly meant to be block level elements. Yet their replacements do not start with a double newline nor end the end tags with a double newline. Since the preg_split [php.net] will split on a double newline and will turn the elements of the returned array into paragraph elements unless they already are other elements, i.e. they start with some tag and end with some tag.

Andreas

Nick_W

10:35 am on Apr 7, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



AHA!

Solved! ;) Kinda....

The real big problem was the broken pipe in the regex (WebmasterWorld code thing) - Now that's fixed all is almost well...

Is there anyway to remove the <p></p> from lines contained within the code tags?

Many thanks Andreas...

Nick

brotherhood of LAN

12:26 pm on Apr 7, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



>contained within the code tags?

How about some more regex, like preg_replace.

Don't make me quote the manual, I have no auto-linking-proxy ;o)

Nick_W

3:46 pm on Apr 7, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, I think I've done it! - At least it certainly appears to work as intended and is actually a little simpler than the solution you suggested Andreas ;)

Here is the complete function. It now extracts <pre> text, puts in the <p>'s and then put's the <pre> text back in again:

[pre]
function bbcode($data) {

$data = preg_replace(array(
"'\[url=([^]]+?)\]'",
"'\[/url\]'",
"'\[url\]([^[]+?)\[/url\]'",
"'\[code\]'",
"'\[/code\]'",
"'\[q\]'",
"'\[/q\]'",
"'\[ul\]'",
"'\[/ul\]'",
"'\[li\]'",
"'\[/li\]'",
"'\[em\]'",
"'\[/em\]'",
"'\[strong\]'",
"'\[/strong\]'",
), array(
"<a href=\"\\1\">",
"</a>",
"<a href=\"$1\">\\1</a>",
"\n\n<pre><code>",
"</code></pre>\n\n",
"<q>",
"</q>",
"\n\n<ul>",
"</ul>\n\n",
"<li>",
"</li>",
"<em>",
"</em>",
"<strong>",
"</strong>"
), $data);

/* First get all the matches to <pre> text */
preg_match_all("/<pre>.*?<\/pre>/s",$data, $extract);

/* Replace all the <pre> text with a new string */
for($i=0;$i<sizeof($extract[0]); $i++) {
$data=str_replace($extract[0][$i], "REPLACE$i", $data);
}

/* Put in the <p>'s around text and replaced text */
foreach(preg_split("/\n+Ķ(\r\n)+/", $data) as $token) {
if(strlen($token) == 0) continue;
if(preg_match("/^<.*>$/", $token)) { $s .= "\n".$token; continue; }
$s .= "\n<p>$token</p>\n";
}

/* Then swap the replaced text for the original <pre> text */
for($i=0; $i<sizeof($extract[0]); $i++) {
$s=str_replace("REPLACE$i", $extract[0][$i], $s);
}

return $s;
}[/pre]

Many thanks for all the help guys, hope someone get's some use outta this function besides me...

Nick

DrDoc

6:44 pm on Apr 7, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member


Tip:

Instead of using [em] and [strong] as codes, why not use [b] and [i]? Sure, you can still replace them with <em> and <strong>... It will just make it easier for those who know about <b> and <i>, but not <strong> and <em>

Also, don't you want to replace all < and > in your regexp? < to &lt; and > to &gt; :)

Then replace the style codes with tags...

andreasfriedrich

7:05 pm on Apr 7, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member




>>Also, don't you want to replace all < and > in your
>>regexp? < to &lt; and > to &gt; :)

Thatīs done before calling this function, at least in my code where I copied the original function from. Iīm sure Nick did it as well.

Iīd go for [i] and [b] as well. I know this will be a bit unconsistent on a website on proper CSS [w3.org] usage but I think users will appreciate the shorter tags nevertheless :-). If you want to be more consistent use [s] and [e]. Or provide all three ways and everybody can pick his favorite method.

Andreas

DrDoc

7:35 pm on Apr 7, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thatīs done before calling this function, at least in my code where I copied the original function from. Iīm sure Nick did it as well.

Figured as much... Just wanted to make sure ;)

Nick_W

9:09 am on Apr 8, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



>on't you want to replace all < and > in your regexp?

Yep, just get's handled by a generic function 'cos it get's used elsewhere...

Good point about the 'b' and 'i' codes both of you. I think I'll do those aswell as what I have.

Cheers!

Nick