Question

I'm not sure how to describe this one so I hope the title is appropriate.

I'm using the below PHP code in my WordPress functions.php file to run htmlspecialchars on all content inside my <code></code> tags each time I save a post.

function FilterCodeOnSave( $content, $post_id ) {

// test data
$textToScan = $content;

// the regex pattern (case insensitive & multiline)
$search = "~<code.*?>(.*?)</code>~is";

// first look for all CODE tags and their content
preg_match_all($search, $textToScan, $matches);
//print_r($matches);

// now replace all the CODE tags and their content with a htmlspecialchars() content
foreach($matches[1] as $match){
        $replace = htmlspecialchars($match, ENT_NOQUOTES);
        // now replace the previously found CODE block
        $textToScan = str_replace($match, $replace, $textToScan);
}

// output result
return $textToScan;
}

I have a problem using the above function when the code contained inside my <code></code> tags is PHP, for example <code class="language-php"><?php the_modified_date(); ?></code>.

When I use the above code, any code snippets afterwards are treated differently, for example my function will ignore the paragraph tags inside <code><p>This is a paragraph.</p></code> and return This is a paragraph. instead of <p>This is a paragraph.</p>.

I believe this is something to do with the question mark inside the PHP code contained within the code block. If I remove the question mark from <? php then my paragraph tags will show on the next code block but obviously my PHP code above it won't be correct.

I've read about escaping questions marks in regex but I'm not sure how to achieve this (if that's the solution).

Any help would be appreciated.

Many Thanks, James

Was it helpful?

Solution

You do not need to use preg_match_all before. The best way is to use preg_replace_callback with a pattern that find the content between code tags:

function FilterCodeOnSave($content) {
    return preg_replace_callback('~<code[^>]*>\K.*?(?=</code>)~is',
        function ($m) { return htmlspecialchars($m[0], ENT_NOQUOTES); },
        $content);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top