I'm using an ubb parser to convert several codes within brackets to html codes. I want to use a string replacer aswell to replace some unwanted words.
Now, I'm using this:
foreach($f AS $value) {
$escapeNamesArray[] = '/'.$value['woord'].'/i';
$escapeNamesReplace[] = '<span style="color: gray;">'.$value['vervanging'].'</span>';
}
$string = preg_replace($escapeNamesArray, $escapeNamesReplace, $string);
When I want to replace the word "Hello" to "Hey", everything is working fine. But when I place the word "Hello" between brackets, for example:
[url=http://www.hello.com]kdskdsds[/url]
The word "Hello" is replaced aswell. How can I change the pattern of the preg_replace function to ignore words between brackets?
Thanks for your reply!
I would recommend taking each variable and splitting at the open and close bracket. If it split at the open bracket then you know it contains an opening bracket. Call the replace on the string to the left of the open bracket (call var1). Then call split on the closing bracket and you know that the string to the left is the contents of the bracket so concatenate it to var 1 (called var2). Then call replace to the string to the right of the last split since it must have been outside of the closing bracket and concatenate the result to var2.
Example:
$exampleStr = "[url=http://www.hello.com]kdskdsds[/url]";
$piecesOfString = explode("[", $exampleStr);
// $piecesOfString[0] = "" --> before the opening bracket so if there was anything there you would have to replace
// $piecesOfString[1] = "url=http://www.hello.com]kdskdsds"
// $piecesOfString[2] = "/url]";"
$piecesOfStringSecond = explode("]", $piecesOfString[1]);
// $piecesOfStringSecond[0] = "url=http://www.hello.com" within the brackets so don't replace
// $piecesOfStringSecond[1] = "kdskdsds" //outside bracket so replace
$piecesOfStringSecond = explode("]", $piecesOfString[2]);
// $piecesOfStringSecond[0] = "/url" within the brackets so don't replace
// $piecesOfStringSecond[1] = "" //outside bracket so if length > 0 replace
I haven't checked this and I'm giving you this in pseudocode but:
$exampleStr = "begin[url=http://www.hello.com]kdskdsds[/url]between[url=http://www.second.com]dsfafa[/url]between2[url=http://www.third.com]kjhjkhk[/url]end";
$piecesOfStringOpen = explode("[", $exampleStr); //splits the string at the "["
for integer j = 0 to length of $piecesOfStringOpen {
if (j == 0) { // you know it will be the first part "begin"
// call replace on $piecesOfStringOpen[j] because you know it is outside of brackets
} else {
//this will include:
// $piecesOfStringOpen[1] = "url=http://www.hello.com]kdskdsds"
// $piecesOfStringOpen[2] = "/url]between"
// $piecesOfStringOpen[3] = "url=http://www.second.com]dsfafa"
// etc
$piecesOfStringClose = explode("]", $exampleStr); //splits the string at the "]"
for integer k = 0 to length of $piecesOfStringClose {
//if k == 0 then it was inside bracket, is a url and don't replace
//elsif k == 1 then it was outside bracket and you want to replace
}
}
}
Using preg_replace
in HTMl-ish situations often turns into a mud pit. I highly recommend you find a different solution to this problem.
I'd suggest letting the parser do its work first, turning everything into valid XHTML. Then use something like SimpleXMLElement or DOMDocument to parse the document. You can then traverse the object, replacing bad strings in each element. When you're done, convert it back to an XHTML string.
This solution is a little more involved, but it's more robust and more flexible, especially if you decide to add more filters and replacements later.
Lucas is right, but its just a simple change to your existing code:
You just need to add make sure its ONLY matching words directly in-between [ ]
I have just added [ and ] in your pattern array (you need to escape them as they are normally used for a regex character array). Here is the updated code:
foreach($f AS $value)
{
$escapeNamesArray[] = '/ '.$value['woord'].' /i';
$escapeNamesReplace[] = '<span style="color: gray;">'.$value['vervanging'].'</span>';
}
$string = preg_replace($escapeNamesArray, $escapeNamesReplace, $string);
This is the only actually changed line:
$escapeNamesArray[] = '/ '.$value['woord'].' /i';
This will work with [whatever]
[ whatever]
[whatever ]
but not [ whatever ]
I havent had a chance to test this, but it should work.
EDIT: Change the code slightly, please take another look :o)
You can make use of the BBCode PECL extension to do the heavy lifting for you. Check this out:
<?php
function filterWords($content, $argument) {
$badWordList = array(
'complex',
'regular expressions',
'O(n^2)'
);
return str_ireplace($badWordList, '', $content);
}
$bbcodeParserConfig = array(
'' => array(
'type' => BBCODE_TYPE_ROOT,
'content_handling' => 'filterWords'
),
'url' => array(
'type' => BBCODE_TYPE_OPTARG,
'open_tag' => '<a href="{PARAM}">',
'close_tag' => '</a>',
'default_arg' => '{CONTENT}',
'childs' => ''
)
);
$bbcodeParser = bbcode_create($bbcodeParserConfig);
$content = 'This is a complex url that [url=http://www.example.com]tells you nothing about regular expressions or O(n^2) algorithms[/url] and thankfully so!';
var_dump(bbcode_parse($bbcodeParser, $content));
There is also a BBCode parser written in PHP.