Big fun with preg_replace_callback

I had a job that required creating a custom input filter for Drupal. It turns out to be pretty easy but I had a heck of a time finding documentation on it that made much sense to me so here’s my explanation of how to do it. The magic is all done by the PHP function preg_replace_callback() which takes as its arguments a regular expression (pattern) to search for, a callback function to take the stuff the expression finds and return you altered text to put in its place, and the big honking block of text to search through. So let’s start simple:

$text = <a href="http://www.php.net/preg_replace_callback">preg_replace_callback</a>('/hello/', '_smallWorld', $text);
function _smallWorld($match){
$world = 'world'; return $world;
}

All this will do is scan through $text and for each instance of hello with world. You can just use preg_replace for that. But it gets a lot more interesting when you start adding options to your regex like the very useful collapsible text module for Drupal:

function collapse_text_process($text) {
$text = <a href="http://www.php.net/preg_replace_callback">preg_replace_callback</a>('/
\[                     # look for an opening bracket collapse # followed by the word `collapse`
(\ collapsed)?         # followed by (optionally) a space and the word `collapsed` (captured)
(?:\ style=([^\] ]*))? # followed by (optionally) a space and a style, consisting of any # characters except a close bracket (captured)
(?:\ title=([^\]]*))?  # followed by (optionally) a space and a title, consisting of any # characters except a close bracket (captured)
\]                     # followed by a closing bracket (.+?)
# then capture as few characters as possible until \[\/collapse\]
# a closing "tag", which is a slash followed by `collapse` in brackets
#and then after the regex delimiter, we'll turn on 3 regex options
#s so dot matches all characters, m to match embedded newlines
#x so we can do free spacing and add these wonderful comments
/smx', "_collapse_text_replace_callback", $text);
return $text;
}

We’ll pause a second to review that regex. What this means is that editors can do all sorts of things from the simple

[collapse] hello world [/collapse]

to the complete

[collapse collapsed style=yellow title=big news]
Hello World [/collapse]

The result is passed to your callback function, _collapse_text_replace_callback as an array. Element 0 is the full match. So

function _collapse_text_replace_callback($matches) {
global $base_url; $collapsed = ($matches[1] == ' collapsed');
$style = <a href="http://www.php.net/trim">trim</a>($matches[2]); $title = <a href="http://www.php.net/trim">trim</a>($matches[3]);
$interior = $matches[4];
//the authors of this module do lots of cool stuff in here, check it out.
return drupal_render($form);
}

So in the simple use case, the first element doesn’t contain collapsed so that’s false so do x. In the more complicated use, it does so do y. Likewise, the more complex use strings for $style, and $title.

This entry was posted in Uncategorized. Bookmark the permalink.

Leave a reply