StripWords with Multiple Replacements

In the previous article, we looked at a custom output modifier (and plugMODX logoin) to remove or replace unwanted words or phrases from a web page. The output modifier ccould be used with any tag in MODX revolution.

In this article we’ll see how to allow a different replacement string for each problem word or phrase. We’ll also take a look at techniques for parsing strings.

 

Multiple Replacements

Suppose that you want to do multiple replacements to text on your site. The PHP str_replace() function will take an array for both its first and second argument (lets call the two arrays $find and $replace). The function replaces the first value in the $find array with the first value in the $replace array. Then it replaces the second value in the $find array with the second value in the $replace array — and so on through the arrays. It’s important that the two arrays are exactly the same length.

In the previous example, we used a chunk to hold the strings. We’ll do that here too.

We could put two separate lines in the chunk, one for the ‘find’ array and one for the ‘replace’ array. It’s more convenient, though to create a single line with pairs of find/replace entries. It’s also a little easier to parse them that way. Here’s the conventional format for the wordsToReplace chunk:

[code language=”html”]
hell:heck,damn:darn,MODx:MODX
[/code]

In our snippet, we need to process that string to create our two arrays. The first step is to initialize our two arrays, get the chunk’s content, and split it at the commas to get each pair (find/replace):

[code language=”php”]
$find = array();
$replace = array();

$line = $modx->getChunk(‘wordsToStrip’);
$pairs = array_map(‘trim’, explode(‘,’, $line));
[/code]

Using array_map and trim makes sure that there are no leading or trailing spaces, tabs, or linefeeds, in case the user has mis-entered the values. At this point, the $pairs array looks like this:

[code language=”php”]
array(
[0] => ‘hell:heck’
[1] => ‘damn:darn’
[2] => ‘MODx:MODX’
)
[/code]

Next, we need to walk through that array, adding the appropriate values to our two arrays. We’ll add a sanity check to make sure each member of the $pairs array has a colon:

[code language=”php”]
foreach($pairs as $pair) {
if (strpos($pair, ‘:’) === false) {
// $modx->log(modX::LOG_LEVEL_ERROR, ‘[stripWords] Parse error – missing colon’);
/* add a colon to prevent null entries */
$pair = $pair . ‘:’;
}
$couple = array_map(‘trim’, explode(‘:’, $pair));
$find[] = $couple[0];
$replace[] = $couple[1];
}
[code]

<p>The modx log line is optional. It will report missing colons, but you may not want to treat that as an error. for entries with a missing colon, the word will be replace with nothing, which you might want. For example, you might want to remove some entries and replace others bu using a string like this in the chunk:</p>

[code language="html"]
hell,damn,MODx:MODX
[/code]

With that string, the first two would be removed and ‘MODx’ would be replaced with ‘MODX’.

Finally, we need to use a slight modification to our output modifier to use the two arrays:

[code language=”php”]
return = str_replace($find, $replace , $input);
[/code]

 

The Full Code

Putting it all together, here’s the full code of our stripWords output modifier:

[code language=”php”]
$find = array();
$replace = array();

$line = $modx->getChunk(‘wordsToStrip’);
$pairs = array_map(‘trim’, explode(‘,’, $line));
foreach($pairs as $pair) {
if (strpos($pair, ‘:’) === false) {
// $modx->log(modX::LOG_LEVEL_ERROR, ‘[stripWords] Parse error – missing colon’);
/* add a colon to prevent null entries */
$pair = $pair . ‘:’;
}
$couple = array_map(‘trim’, explode(‘:’, $pair));
$find[] = $couple[0];
$replace[] = $couple[1];
}
return = str_replace($find, $replace , $input);
[/code]

 

Speed Considerations

If page-load speed are critical for you, especially if the cache if often cleared, you can speed things up very slightly by doing the replacements in a plugin attached to the OnWebPagePrerender System Event. The only change to the code would be using $modx->resource->_output for the content instead of $input, so the last line of the code would be replaced by this:

[code language=”php”]
$modx->resource->_output = str_replace($find, $replace , $modx->resource->_output);
return ”;
[/code]

The speed improvement would be very insignificant, however. It would only effect pages that are not cached and would only cut out the tiny amount of time necessary for MODX to identify the output modifier. Since it’s not a conditional modifier and there are no arguments to parse, that would probably take just a few milliseconds.

Another possible way to speed things up would be to use strpos() on each word to be replaced and return without calling str_replace() if none of them are present in the content. The effects of this would also be minimal, and depending on the number of words involved, it might actually slow things down. You’d have to benchmark it to be sure.

Coming Up

Sometimes, creating two separate arrays for str_replace() is inconvenient and can lead to errors where the strings to be replaced don’t line up with the replacements. It works very well for this use case, but in the next article, we’ll look at a way to do replacements with a single associative array of keys and values.

 


For more information on how to use MODX to create a web site, see my web site Bob’s Guides, or
better yet, buy my book: MODX: The Official Guide.

Looking for quality MODX Web Hosting? Look no further than <a
href=”http://bit.ly/YgFGHl”>Arvixe Web Hosting!

Tags: , , , | Posted under MODX, MODX | RSS 2.0

Author Spotlight

Bob Ray

Bob Ray is the author of MODX: The Official Guide and over 30 MODX add-on components. He hosts Bob's Guides, a source of valuable information for MODX users, and has been very active in the MODX Forums with over 19,000 posts.

Leave a Reply

Your email address will not be published. Required fields are marked *