Search code examples
phppreg-replacepreg-replace-callback

Applying function on second or third term in preg_replace (preg_replace_callback?)


I have below a simple (BBCode) PHP code for insert code into a comment/post.

function highlight_code($str) {  
    $search = array( 
                   '/\[code=(.*?),(.*?)\](((?R)|.)*?)\[\/code\]/is',
                   '/\[quickcode=(.*?)\](((?R)|.)*?)\[\/quickcode\]/is'
                   );

    $replace = array(  
            '<pre title="$2" class="brush: $1;">$3</pre>',
            '<pre class="brush: $1; gutter: false;">$2</pre>'
            );  

    $str = preg_replace($search, $replace, $str);  
    return $str;  
}  

What I want to be able to do is insert functions at these locations:

    $replace = array(  
            '<pre title="$2" class="brush: $1;">'.myFunction('$3').'</pre>',
                                                       ^here
            '<pre class="brush: $1; gutter: false;">'.myFunction('$2').'</pre>'
                                                           ^here
            );  

From what I've read on SO I may need to use preg_replace_callback() or an e-modifier, but I cannot figure out how to go about doing this; my knowledge with regex is not so good. Would appreciate some help!


Solution

  • You can either use this snippet (e-modifier):

    function highlight_code($str) {  
        $search = array( 
                       '/\[code=(.*?),(.*?)\](((?R)|.)*?)\[\/code\]/ise',
                       '/\[quickcode=(.*?)\](((?R)|.)*?)\[\/quickcode\]/ise'
                       );
        // these replacements will be passed to eval and executed. Note the escaped 
        // single quotes to get a string literal within the eval'd code    
        $replace = array(  
                '\'<pre title="$2" class="brush: $1;">\'.myFunction(\'$3\').\'</pre>\'',
                '\'<pre class="brush: $1; gutter: false;">\'.myFunction(\'$2\').\'</pre>\''
                );  
    
        $str = preg_replace($search, $replace, $str);  
        return $str;  
    } 
    

    or this one (Callback):

    function highlight_code($str) {  
        $search = array( 
                       '/\[code=(.*?),(.*?)\](((?R)|.)*?)\[\/code\]/is',
                       '/\[quickcode=(.*?)\](((?R)|.)*?)\[\/quickcode\]/is'
                       );
    
        // Array of PHP 5.3 Closures
        $replace = array(
                         function ($matches) {
                             return '<pre title="'.$matches[2].'" class="brush: '.$matches[1].';">'.myFunction($matches[3]).'</pre>';
                         },
                         function ($matches) {
                             return '<pre class="brush: '.$matches[1].'; gutter: false">'.myFunction($matches[2]).'</pre>';
                         }
                );  
        // preg_replace_callback does not support array replacements.
        foreach ($search as $key => $regex) {
            $str = preg_replace_callback($search[$key], $replace[$key], $str);
        }
        return $str;  
    }