View Full Version : How do I change words in post texts?
DonosOdD
01-24-2012, 05:30 AM
Hi everyone,
I wanted to have a wordfilter, to replace a censored word for a word I want, in all forum sections but one specific.
when I was looking online for how to solve this, I've found this link:
https://vborg.vbsupport.ru/showthread.php?t=219968
which contained this code:
$word = array(
'word1',
'word2'
);
$link = array(
'<a href="/forums/link1.php">Word1</a>',
'<a href="/forums/link2.php">Word2</a>'
);
$this->post['message'] = str_ireplace($word, $link, $this->post['message']);
So I changed it to:
$censoredword = array(
'word1',
'word2'
);
$changedword = array(
'word3',
'word4'
);
$this->post['message'] = str_ireplace($censoredword, $changedword, $this->post['message']);
I wonder if this code is right, where should I put it, and how would I make it work for all subforums but one.
Sorry for this silly question, but I don't know PHP.
Thanks in advance!
That code looks right - it will of course replace all occurences of 'word1' and 'word2' even if they are part of another word (or a bbcode, or a link, etc), so you have to be a little careful how it's used.
The linked post says you should create a new plugin using hook location postbit_display_complete and that code.
DonosOdD
01-24-2012, 04:50 PM
Thank you, however, it still tricks me in those 3 points:
1- how do I create a new plugin (and using this hook location)?
2-where is postbit_display_complete? (I haven't found it, so I thought it exists only in previous versions, not vb4)
3-how do I make it work for all forum sections but one? I thought using a simple if statement:
if (forum_id <> protected_id) { php code }
but I do not know what's the name of the forum id variable.
Again, thanks in advance!
Create a new plugin by going to Add New Plugin under Plugins & Products in the adminCP. Choose the hook location from the dropdown menu, enter a title so you'll remember what it does later, and paste the code in the large text area. Click the "Yes" radio button to enable it, and press "Save".
To have one forum be exempt, put this around the code:
if ($forum['forumid'] != X)
{
// insert code here
}
and of course replace X with the forum id.
DonosOdD
01-24-2012, 06:31 PM
I've done it, it was very simple indeed, and worked without problems.
Thank you! Hope this question helps out other people too.
DonosOdD
01-27-2012, 01:00 AM
Hello again
I've tried it and it was fine - until I decided to use the function preg_replace instead of str_replace. And what happened was, all the posts went blank (all characters removed).
I wanted to use preg_replace because it's better for general word replacing.
Any thoughts?
Thanks!
preg_replace returns NULL if there's an error, so my guess would be that you're passing it something that's not a valid pattern.
You could try something like this (for testing only):
$ret = preg_replace($pat, $rep, $this->post['message']);
if ($ret !== NULL)
$this->post['message'] = $ret;
else
$this->post['message'] .= '<BR /><BR />Pattern error: ' . preg_last_error();
DonosOdD
01-27-2012, 05:55 AM
Yeah, tried it and got Pattern Error 0.
This is the code I'm using, trying to simply change "foo" to "boo".
if ($forum['forumid'] != 2)
{
$pat = array(
'/\bfoo\b/i'
);
$rep = array(
' boo'
);
$ret = preg_replace($pat, $rep, $this->post['message']);
if ($ret !== NULL)
$this->post['message'] = $ret;
else
$this->post['message'] .= '<BR /><BR />Pattern error: ' . preg_last_error();
}
I guess the problem is with the preg_replace parameters, I'm passing an array whilst I should have passed an string. Is that it? How do I solve it?
Thanks again!
Well, slightly bad choice of error message wording on my part - 0 is actually 'no error', so it's apparently not a pattern error. But what I don't understand is why you seem to be getting NULL returned if there's no error. (See below)
I tried your code in a test script and it works for me:
<?php
$pat = array(
'/\bfoo\b/i'
);
$rep = array(
' boo'
);
$text = " foo ";
$ret = preg_replace($pat, $rep, $text);
if ($ret !== NULL)
echo "new text :" . $ret;
else
echo ("preg_replace error: " . preg_last_error());
and the output is:
new text : boo
ETA: OK, further testing, that error code returned from preg_last_error isn't very useful - I purposely put in a bad pattern and I got NULL as a return, but 0 from preg_last_error(), just like you did. So I guess you *do* have an error in one of your patterns. I assume what you posted is a simplified version of what you're actually using, so I guess you'll have to look them over carefully to check for bad pattern string syntax.
DonosOdD
02-04-2012, 04:25 AM
Hello again, and sorry for the late response (I haven't worked on the forum for some time).
Your answers were great, and I was able to do this:
if ($forum['forumid'] != 2)
{
$pat = array(
'f1',
'f2',
'f3',
'f4',
'f5',
'f6',
'f7',
'f8',
'f9',
'f10'
);
$rep = array(
'e1',
'e2',
'e3',
'e4',
'e5',
'e6',
'e7',
'e8',
'e9',
'e10'
);
foreach ($pat as &$value) {
$value = "/\b" . $value . "\b/iu" ;
}
$ret = preg_replace($pat, $rep, $this->post['message']);
if ($ret !== NULL)
$this->post['message'] = $ret;
}
And it worked fine. However, my forum is in portuguese, and when I change something to a word with any accentuation, like ? or ?, the code changes nothing at all (I guess ret == null).
I'm bypassing it by writing the words without accentuation.
Any thoughts?
Thanks!
EDIT: It doesn't work. Well, it worked for a while, but after two tests and two F5s, it stopped working. I can't understand why. And I was using this exact code, with this silly words.
Strange. The above works for me, so I'm not sure what to try.
DonosOdD
02-04-2012, 02:28 PM
Strange. The above works for me, so I'm not sure what to try.
Yes, it is very strange.
I deleted the plugin, created another one, copied the same code above, and tested. Doesn't work at all.
EDIT: Changed the preg_replace to str_replace, and it worked (however, without the boundaries). preg_replace is indeed returning null here, and I can't understand why.
--------------- Added 1328410811 at 1328410811 ---------------
Ok, here we have some news:
I was wondering why preg_replace remains returning NULL, even with silly/obvious examples. I changed it to str_replace and it worked. However, I need to manipulate strings in such a way that str_replace can't.
I've searched for the preg_replace returning NULL issue, and found this link:
http://www.pelagodesign.com/blog/2008/01/25/wtf-preg_replace-returns-null/
In PHP 5.2, Perl Compatible Regular Expressions (PCRE) introduced with little fanfare a PHP setting called backtrack_limit, which, for the first time, set a limit on the number of backtracks a regular expression could perform before it stops operating and reports an error. Unfortunately, when PCRE encounters an error of this type, it doesn?t report a notice or warning or error. All it does is return NULL (...)
Then I went to my php.init file, to set a higher backtrack_limit.
After that, in the admincp->maintenance-> PHP Info, I've found this:
Directive Local Value Master Value
pcre.backtrack_limit -1 20000000
pcre.recursion_limit 20000000 20000000
So, what I need now is to change the local value to the master value, which I don't know how to :S
Any ideas?
Thanks in advance!
DonosOdD
02-08-2012, 01:19 AM
Update: it's ok now, I've solved it and it works perfectly.
The problem was indeed that variable, pcre.backtrack_limit. I changed my php.ini file to raise its value, but its local value was still at -1. Then I've found that there's a config file in the vbulletin installation called init.php, which has this line:
@ini_set('pcre.backtrack_limit', -1);
That was keeping the variable so low, and this is why code was always returning NULL.
I commented this line, and it began to work.
Well, guess that's it, hope I'm also able to help someone with this.
Cya!
I guess it worked for me because I don't have 5.3.
Anyway, thanks for posting that.
Emeralda
02-25-2012, 11:10 PM
Uhm... which hook should I chose to limit it to things in postbit?
The above uses hook postbit_display_complete. I should probably have directed you to the thread mentioned in the first post, which is here: https://vborg.vbsupport.ru/showthread.php?t=219968
Emeralda
02-26-2012, 10:25 AM
$censoredword = array(
'word1',
'word2'
);
$changedword = array(
'word3',
'word4'
);
$this->post['message'] = str_ireplace($censoredword, $changedword, $this->post['message']);
And how do the replacement work exactly? Is it something like
$censoredword = array(
'swear word1',
'swear word2'
);
$changedword = array(
'swear word1 change',
'swear word2 change'
);
$this->post['message'] = str_ireplace($censoredword, $changedword, $this->post['message']);
Or
$censoredword = array(
'swear word1',
'swear word2'
);
$changedword = array(
'new word for all swears'
);
$this->post['message'] = str_ireplace($censoredword, $changedword, $this->post['message']);
You can have either one replacement for all words or a separate replacement for each word. But if you only want one replacement I think it might have to be a string instead of an array, like:
$censoredword = array(
'swear word1',
'swear word2'
);
$changedword = 'new word for all swears';
$this->post['message'] = str_ireplace($censoredword, $changedword, $this->post['message']);
Emeralda
02-26-2012, 12:46 PM
None of the two seemed to work >.<
Well, I tried it with exactly the code above and it works, so maybe you have a typo somewhere? I'd suggest you post your code but I suppose it contains bad language. :)
ETA: or maybe it's just not working like you expected? Like Lynne mentioned in the other thread, this only changes it just before a post is displayed, so there are probably some situations where the swear word would be seen (like an RSS feed maybe?). If you want to change it permanently when the post is saved (which is the way the build-in censoring works), I think you could use hook newpost_process and code like this:
$censoredword = array(
'swear word1',
'swear word2'
);
$changedword = 'new word for all swears';
$post['message'] = str_ireplace($censoredword, $changedword, $post['message']);
I suppose a disadvantage to this way is that it won't change any existing swear words.
Emeralda
02-26-2012, 02:20 PM
I tested it with editing an existing post and it was still turning the word into *****
Also, the full phrase I wanted was "I'm a little teapot" but there is that ' thingie.
Maybe try turning off the built-in censoring, it probably changes to *s before your code gets a chance to run.
If you're replacement has a ' then you can put a backslash in front of it, or else use double quotes around the string instead of single.
Emeralda
02-26-2012, 06:36 PM
Oh, yeah, the auto censoring had to be turned off. But it all works now~
Also, the thing with excluding forums, I used it and it works, but if I'd want to add more than one forum, should I just add a comma after the ID?
You could do something like:
if (!in_array($forum['forumid'], array(1, 2, 3)) // exclude forums 1, 2, and 3
{
...
}
or if you'd rather list the forums to be included, remove the ! from in front of in_array.
Emeralda
04-15-2012, 03:50 PM
Uhm, I have a sudden need to apply this for visitor messages and View Conversation (especially links). Which hooks to use for those?
vBulletin® v3.8.12 by vBS, Copyright ©2000-2025, vBulletin Solutions Inc.