3

I'm trying to parse BBCode in my script. Now, it works seamelessly, until I try to indent BBCode that's more than just bold or underline - such as spoiler, url, font size, etc. - then it screws up. Here's my code:

function parse_bbcode($text) {
    global $db;
    $oldtext = $text;
    $bbcodes = $db->select('*', 'bbcodes');
    foreach ($bbcodes as $bbcode) {
        switch ($bbcode->type) {
            case 'simple': {
                $find = '{content}';
                $replace = '${1}';
                $text = preg_replace(
                    '/\['.$bbcode->tag.'\](.+)\[\/'.$bbcode->tag.'\]/i',
                    str_replace($find, $replace, $bbcode->html),
                    $text);
                    break;
            }
            case 'property':
            case 'options': {
                $find = array ( '{property}', '{content}' );
                $replace = array ( '${1}', '${2}' );
                $text = preg_replace(
                    '/\['.$bbcode->tag.'\=(.[^\"]*)\](.+)\[\/'.$bbcode->tag.'\]/i',
                    str_replace($find, $replace, $bbcode->html),
                    $text);
                    break;
            }
        }
    }
    return $text;
}

Now my guess is that the RegEx doesn't like the recursiveness in the pattern. How can I improve it? A sample $bbcode object is as such:

stdClass::__set_state(array(
   'id' => '2',
   'name' => 'Italic',
   'type' => 'simple',
   'tag' => 'i',
   'button_image' => NULL,
   'button_text' => '<i>I</i>',
   'options' => '',
   'prompt' => NULL,
   'html' => '<i>{content}</i>',
   'order' => '1',
))
stdClass::__set_state(array(
   'id' => '3',
   'name' => 'URL',
   'type' => 'property',
   'tag' => 'url',
   'button_image' => NULL,
   'button_text' => 'http://',
   'options' => '',
   'prompt' => 'URL address',
   'html' => '<a href="{property}">{content}</a>',
   'order' => '4',
))
4
  • 9
    PHP has a BBCode parser, so no reason to reinvent the wheel Commented Jul 21, 2011 at 8:25
  • No shit. I didn't know that. How about making this an answer so I can mark it Commented Jul 21, 2011 at 8:27
  • I added a few links to Clement's answer below. Feel free to accept that instead :) Commented Jul 21, 2011 at 8:38
  • For anyone looking, I'd like to add the library I wrote that is currently the best of those I was able to find: github.com/thunderer/Shortcode Commented Dec 29, 2015 at 13:53

2 Answers 2

7

As gordon said in comments PHP has a BBCode parser, so no reason to reinvent the wheel.

The native parser is a PECL package though, so you will have to install it. If that's not an option (for instance due to shared hosting), there is also a PEAR package: http://pear.php.net/package/HTML_BBCodeParser

In addition to those, you can take a look at forums using BB code source code, and either use their parser, or improve it. There is also several PHP implementations listed at http://www.bbcode.org/implementations.php

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

1 Comment

The PECL package seems awesome, but I can't install it... The PEAR one is lame :/
0

Correctly parsing BBcode using regex is non-trival. The codes may be nested. CODE tags may contain BBCodes which must be ignored by the parser. Certain tags may not appear inside of other tags. etc. However, it can be done. I recently overhauled the BBCode parser for the FluxBB open source forum software. You may want to check it out in action:

New 2011 FluxBB Parser

Note that this new parser has not yet been incorporated into the FluxBB codebase.

4 Comments

Is this fully operational? And how easily can I add my own BBCode?
Yes it is operational (the link above is a test forum which uses this parser). This is not a generic parser - Its designed specifically to work with FluxBB. You'll need to read the documentation and the source code. I assume you are a PHP programmer and are familiar with regular expressions. As I said, parsing BBCode is non-trivial.
Yeah I'm familiar with PHP and RegEx (see question), but BBCode is simple enough to parse -- until it gets recursive
@OhMrBigshot: The complexity of the problem is not limited to just recursion but in how the tags nest inside each other. e.g. Will you allow a URL tag inside an IMG tag? Or how about allowing a QUOTE tag inside an I tag? You need to set up a system of rules (which parallel HTML) that define what is allowed to nest inside each tag. Also, there needs to be rules for allowable parent tags, e.g. A LI (or *) tag may only appear inside a LIST tag.

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.