[pmwiki-users] Recipes you use/need to be updated for PHP 5.5

Petko Yotov 5ko at 5ko.fr
Wed Jan 8 16:15:17 CST 2014

John Rankin writes:
> On 8/01/14 12:31 PM, Petko Yotov wrote:
>> Currently the PmWiki core does not restrict you at all to use closures in  
>> your recipes. You can have them, they will only work on PHP 5.3+ sites.
> That works for me :-)
> However, some advice on how best to convert the following case would be  
> helpful. I use some code to extract the text of a link in the form:
> $LinkTidy = array("/reg-exp1/" =>
>      "MakeLink(\$pagename, ... matches ... , '\$LinkText')",
>                   "/reg-exp2/" =>
>      "MakeLink(\$pagename, ... matches ... ,  '\$LinkText')");
> foreach ($LinkTidy as $exp => $repl) {
>     $text = SomeFunction($exp, $repl, $text);
> }
> Currently, SomeFunction is preg_replace, $exp has an e modifier and matches  
> contains '$1', '$2', etc as appropriate to the $exp. In some cases, $exp has  
> no modifier and $repl is simply '$1'.
> What is the best way to convert this? Preferably without a major code re- 
> write, as I use this construct in several places.

For PHP 5.5 you need to create callback functions where your replacement  
requires evaluation.

And, you need to pass the $pagename value to the callback function.

Here is how I would try this:

  $LinkTidy = array(
    "/pattern1/" => PCCF("return MakeLink('$pagename', \$m[1], ...,  
        '\$LinkText');"),          # evaluated: callback, but no /e
    "/pattern2/" => '<em>$0</em>', # not evaluated: string
  $text = PPRA($LinkTidy, $text);

This will work with PHP 4.2 to 5.5.

The function PPRA($array, $text) where $array is array('search'=>'replace')  
and $text is the haystack, performs a regular expression search and replace.  
If the 'replace' part is a callback or any function name, it uses  
preg_replace_callback(), otherwise preg_replace().

The function PCCF("PHP code here") lets you create a callback lambda($m)  
where $m is the array of matches. The argument is the PHP code.

Two changes from your pre-PHP5.5 way:

1. Instead of '$0', '$1', '$2', '$3' ... we have $m[0], $m[1], $m[2], $m[3],  
no single quotes, and as we don't want to expand them when we declare the  
callback, we precede them with backslash:  \$m[0], \$m[1], \$m[2], \$m[3].

2. $pagename is not in the scope of the callback function, so we don't  
prefix it with \ and we wrap it in single quotes :

  "return MakeLink('$pagename',...);"

this will expand $pagename and its "value" will be written as a string into  
the callback. This assumes that at the moment when you define the callback  
you know the value of $pagename, like in your example.

Read the function PCCF(), you can define custom callback templates and thus  
write less code.


More information about the pmwiki-users mailing list