2

Okay, so I'm trying to replace really long quotes in my websites comments section that uses bbcode, what I'm trying to do is encase long quotes in a collapse I already have coded in js and css.

My problem is that it will do the first quote, then any other quotes vanish. I'm obviously missing something, but this is my first time using callbacks like this.

Here's my php code right now to do this:

$body = preg_replace_callback("/\[quote\](.*?)\[\/quote\]/is",
function($matches)
{
    if (strlen($matches[1]) >= '1000')
    {
        $matches[0] = str_replace($matches[0], '<div class="box"><div class="collapse_container"><div class="collapse_header"><span>Long quote, click to expand</span></div><div class="collapse_content">' . $matches[1] . '</div></div></div>', $matches[0]);
        return $matches[0];
    }
}, $body);

Some example text:

[quote]aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa[/quote]

[quote]booohoo[/quote]

[quote]new quoting[/quote]

[b]test[/b]
2
  • Just move the return $matches[0]; outside the ìfblock. Commented Nov 14, 2015 at 18:43
  • @Liam Dawe I'm an author of the library designed to handle shortcodes and BBCodes of any kind. Please take a look, it'll definitely help your use case: github.com/thunderer/Shortcode . If you need any help, just open an issue and I'll give you a hand. Commented Nov 18, 2015 at 20:18

2 Answers 2

3

You need to move the return $matches[0] code outside the if block:

function($matches)
{
    if (strlen($matches[1]) >= '1000') {
        $matches[0] = str_replace($matches[0], '<div class="box"><div class="collapse_container"><div class="collapse_header"><span>Long quote, click to expand</span></div><div class="collapse_content">' . $matches[1] . '</div></div></div>', $matches[0]);
    }
    return $matches[0];
}

Also, I advise to unroll your lazy matching regex as follows:

'~\[quote\]([^[]*(?:\[(?!/quote\])[^[]*)*)\[/quote\]~i'

See my regex demo (30 steps) and your regex demo (2025 steps).

See IDEONE demo

Sign up to request clarification or add additional context in comments.

Comments

0

Phps preg* functions are acting greedy by default. They will match the longest possible string described by your regex. In your case the regex mathces everything from the first [quote] to the very last [/quote]. To turn this behavior of you have to use the "U" modifier:

$body = preg_replace_callback("/\[quote\](.*?)\[\/quote\]/isU",...);

For a list of modifiers see http://php.net/manual/en/reference.pcre.pattern.modifiers.php

2 Comments

That doesn't work, as then it matches the first [quote] to the very last [/quote] in the entire text.
You are misreading what that U modifier does. PHP regexs aren't "greedy" by default; .* is greedy by default, the ? makes it lazy. The U inverts the * and the *? pairing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.