0

Here is the function I'm using to declare a shortcode [warning] which may take one or two parameters [warning](!parameter1!)(!parameter2!) or [warning](!parameter1!)

function warning($text) {
    return preg_replace_callback('/\[warning\]\s*\(!(.*?)!\)(?:\s*\(!(.+?)!\))?/', 
        function ($m) {
            if (isset($m[2])) {
                return '<div class="alert alert-error"><div class="alert-content"><h2 class="alert-title"> '.$m[1].' </h2><div class="alert-body"><p> '.$m[2].' </p></div></div></div>';
            } else {
                return '<div class="alert alert-error"><div class="alert-content"> '.$m[1].' </div></div>';
            }
        }
        , $text);
}
add_filter('the_content', 'warning');
add_filter( 'the_excerpt', 'warning');

I'm trying to modify this code in order to be able to escape this shortcode so that users in my forum would be able to use it to explain to others how to use this shortcode and here is the way I'm trying to do this (based on an answer to a similiar question with str_replace) knowing that I'm trying to do it with a backslash \[warning](!par1!) or \[warning](!par1!)(!par2!)

function warning($text) {
    $text = preg_replace_callback('/[^\\\\]\[warning\]\s*\(!(.*?)!\)(?:\s*\(!(.+?)!\))?/', 
        function ($m) {
            if (isset($m[2])) {
                return '<div class="alert alert-error"><div class="alert-content"><h2 class="alert-title"> '.$m[1].' </h2><div class="alert-body"><p> '.$m[2].' </p></div></div></div>';
            } else {
                return '<div class="alert alert-error"><div class="alert-content"> '.$m[1].' </div></div>';
            }
        }
        , $text);
    $text = preg_replace_callback('/\\[warning\]\s*\(!(.*?)!\)(?:\s*\(!(.+?)!\))?/', 
        function ($m) {
            if (isset($m[2])) {
                return '[warning](!'.$m[1].'  !)(!' .$m[2]. '!)';
            } else {
                return '[warning](!'.$m[1].'!)';
            }
        }
        , $text); 
    return $text;       
}
add_filter('the_content', 'warning');
add_filter( 'the_excerpt', 'warning');

The first call of preg_replace_callback is to search for all instances not preceeded by \ the second one is to search for ones with \.

I'm using PHP <5.6. So I couldn't use preg_replace_callback_array, even I think that the same correction should work with the two functions.

Any idea?

Hamed
  • 159
  • 8
  • 1
    `I'm using PHP <5.6`... Maybe time to upgrade...? – Justinas Mar 13 '19 at 14:45
  • @Justinas on the live version of my website I'm using PHP>7 and I'm getting an error message when using `preg_replace_callback_arry` of type `Call to undefined function preg_replace_callback_array() in`. – Hamed Mar 13 '19 at 14:49

1 Answers1

0

After analyzing the output, I was able to see the cause of the problem and why the replacement is not well done. It is due to the use of [^\\\\] and \\. The first one was causing an output of this form <p<div class="alert alert-error"> ... the second was not correct for finding the text to replace. So a little modification is done

function warning_f($text) {
    $text = preg_replace_callback('/(?<!\\\\)\[warning\]\s*\(!(.*?)!\)(?:\s*\(!(.+?)!\))?/', 
        function ($m) {
            if (isset($m[2])) {
                return '<div class="alert alert-error"><div class="alert-content"><h2 class="alert-title"> '.$m[1].' </h2><div class="alert-body"><p> '.$m[2].' </p></div></div></div>';
            } else {
                return '<div class="alert alert-error"><div class="alert-content"> '.$m[1].' </div></div>';
            }
        }
        , $text);
    $text = preg_replace_callback('/\\\\\[warning\]\s*\(!(.*?)!\)(?:\s*\(!(.+?)!\))?/', 
        function ($m) {
            if (isset($m[2])) {
                return '[warning](!'.$m[1].'  !)(!' .$m[2]. '!)';
            } else {
                return '[warning](!'.$m[1].'!)';
            }
        }
        , $text); 
    return $text;       
}
add_filter('the_content', 'warning_f');
add_filter( 'the_excerpt', 'warning_f');

After upgrading to php 7.2, I'have use preg_replace_callback_array and here is the corresponding code

function warning_f($text) {
    $text=preg_replace_callback_array(
        [
        '/(?<!\\\\)\[warning\]\s*\(!(.*?)!\)(?:\s*\(!(.+?)!\))?/' 
        => function ($m) {
                return '<div class="alert alert-error"><div class="alert-content"><h2 class="alert-title"> '.$m[1].' </h2><div class="alert-body"><p> '.$m[2].' </p></div></div></div>';
            } else {
                return '<div class="alert alert-error"><div class="alert-content"> '.$m[1].' </div></div>';
            }
        },
        '/\\\\\[warning\]\s*\(!(.*?)!\)(?:\s*\(!(.+?)!\))?/' 
        => function ($m) {
            if (isset($m[2])) {
            return '[warning](!'.$m[1].'  !)(!' .$m[2]. '!)';
            } else {
            return '[warning](!'.$m[1].'!)';
            }
        }
        ],
        $text);
    return $text;
}
add_filter('the_content', 'warning_f');
add_filter( 'the_excerpt', 'warning_f');
Hamed
  • 159
  • 8