## III. Using NBBC

[ Previous: E. Adding Enhanced Tags | Next: G. Supporting Wiki-Links ]

### F. Adding Callback Tags

There are circumstances where enhanced tags will not be capable enough to handle your needs, and for those, NBBC supports callback tags --- tags that call a function you provide to perform their validation and formatting.

So let's look at how to add a simple callback tag: Even though we can do `[border]` as an enhanced tag, let's look now at how to implement it as a callback tag instead.

First, you'll need to alter the rule definition. Start with the same basic definition we've used before, but use `BBCODE_MODE_CALLBACK` and add a 'method' parameter:

Code:

        $bbcode->AddRule('border',  Array(
            'mode' => BBCODE_MODE_CALLBACK,
            'method' => 'MyBorderFunction',
            'class' => 'block',
            'allow_in' => Array('listitem', 'block', 'columns'),
        ));

Somewhere else in your code, you'll need to provide the callback function itself, which, in this case, is named "`MyBorderFunction`":

Code:

    function MyBorderFunction($bbcode, $action, $name,
        $default, $params, $content) {
        ....
    }

*
Tech Tip

NBBC uses PHP's `call_user_func()` function to call your function, so it doesn't need to be just a function name: If you want NBBC to call a method of an object of a particular class, you can supply an array instead of a string, like this (where `$obj` contains an object with a member function named "`MyMethod`"):

`'method' => Array($obj, 'MyMethod'),`

Let's look at how the callback function works. First, these are its parameters:

- `$bbcode` - The `BBCode` object that is currently doing the parsing.
- `$action` - Always one of `BBCODE_CHECK` or `BBCODE_OUTPUT`, provided to indicate why this function was called and what it should return.
- `$name` - The tag name: In the `[border]` example, this would contain the string "`border`".
- `$default` - The default value of the tag. If the user were to type `[border=1 color=red]`, the default value would be "`1`".
- `$params` - The parameters of the tag, some given by the user, some generated by NBBC, stored in an array of key => value pairs. In the example of `[border=1 color=red]Hello[/border]`, this array might contain:
  - '`_name`' => '`border`'
  - '`_default`' => '`1`'
  - '`color`' => '`red`'
  A full list of the values NBBC adds to the tag parameters is included in the Appendix.
- `$content` - Only valid when `$action` is `BBCODE_OUTPUT`, this is the content (body) of the tag, already converted to valid HTML. In the example of `[border=1 color=red]Hello[/border]`, `$content` would contain the string "`Hello`".

The callback function is called in two stages. First, after the start tag has been read by the parser, the callback function is called immediately with `$action` set to `BBCODE_CHECK`. This gives the tag the opportunity to decide whether the parameters the user provides make any sense; and this is when we would reject bad sizes and colors in our `[border]` example:

Code:

    function MyBorderFunction($bbcode, $action, $name,
        $default, $params, $content) {
        if ($action == BBCODE_CHECK) {
            if (isset($params['color'])
                && !preg_match('/^#[0-9a-fA-F]+|[a-zA-Z]+$/', $params['color']))
                return false;
            if (isset($params['size'])
                && !preg_match('/^[1-9][0-9]*$/', $params['size']))
                return false;
            return true;
        }
    }

A call with `$action == BBCODE_CHECK` must return either `true` or `false`: If it returns `true`, NBBC will assume the tag is acceptable; if it returns `false`, NBBC will assume that the tag is unacceptable and will not treat it as a tag or evaluate it further.

The second time the function is called is with `$action` set to `BBCODE_OUTPUT`. If `$action` is `BBCODE_OUTPUT`, NBBC is asking the function to generate HTML from its inputs. The return value must be a string, and must contain HTML or plain text: No BBCode tags. A typical implementation for our `[border]` example might look like this:

Code:

    function MyBorderFunction($bbcode, $action, $name,
        $default, $params, $content) {
        if ($action == BBCODE_CHECK) {
            if (isset($params['color'])
                && !preg_match('/^#[0-9a-fA-F]+|[a-zA-Z]+$/', $params['color']))
                return false;
            if (isset($params['size'])
                && !preg_match('/^[1-9][0-9]*$/', $params['size']))
                return false;
            return true;
        }

        $color = isset($params['color']) ? $params['color'] : "blue";
        $size = isset($params['size']) ? $params['size'] : 1;
        return "<div style=\"border: {$size}px solid $color\">$content</div>";
    }

*
Tech Tip

When you implement a callback function, take special care to note which parameters are validated and which parameters are not:

- `$default` contains exactly what the user typed, and has not been passed through `htmlspecialchars()` or `htmlentities()` or any other cleanup function. If you output this value, you should clean it up before outputting it.
- `$params` all contain exactly what the user typed, and none of them have been passed through `htmlspecialchars()` or `htmlentities()` or any other cleanup function. If you output this value, you should clean it up before outputting it.
- `$content` is always pure, clean output HTML, or pure, clean output plaintext, depending on whether it's outputting in HTML or plaintext mode.
- Your callback function's return value must always be pure, clean output HTML, or pure, clean output plaintext, depending on whether it's outputting in HTML or plaintext mode.
- None of the input parameters to this function will contain any BBCode tags.

[ Previous: E. Adding Enhanced Tags | Next: G. Supporting Wiki-Links ]

Copyright © 2010, the Phantom Inker. All rights reserved.