XF 2.2 Allowing BBCode/complex text inside BBCodes made with PHP callback

Eternity7

Member
I have the following PHP that works as intended with one line text but BBCodes and newlines inside it is parsed as HTML.

PHP:
<?php
 
    namespace custom_addons;

    class box {

        public static function box($tagChildren, $tagOption, $tag, array $options, \XF\BbCode\Renderer\AbstractRenderer $renderer)
        {
            $res = $renderer->renderSubTree($tagChildren, $options);
            $toptions = trim(strip_tags($tag['option']));
            $toptions = preg_split("|\||", $toptions, -1, PREG_SPLIT_NO_EMPTY);

            @list($style, $bd, $brad1, $brad2) = $toptions;
            if ($tmp = trim($style)) {
                $style = "$tmp";
            }
            if ($tmp = trim($bd)) {
                $bd = "$tmp";
            }
            if ($tmp = trim($brad1)) {
                $brad1 = "$tmp";
            }
            if ($tmp = trim($brad2)) {
                $brad2 = "$tmp";
            }
            
            $templater = $renderer->getTemplater();
            $customTemplate = $templater->renderTemplate('public:custom_addons_box', [
                'style' => $style,
                'bd' => $bd,
                'brad1' => $brad1,
                'brad2' => $brad2,
                'res' => $res,
            ], true);

            return $customTemplate;
        }

    }
?>

Code:
<div style="background:{$style}; border: {$bd}px solid ; border-radius: {$brad1}px {$brad2}px;">{$res}</div>

Input:
1616945955488.png

Result:
1616945988162.png
I'd appreciate your help for this. Thank you.
 

Lukas W.

Well-known member
Use {$res|raw} in your template to render html content inside the string, otherwise XF will escape it. The BB Code renderer will already have escaped any html the user tried to insert at this point, so it'll still be escaped.
 

Eternity7

Member
You're a godsend, it worked.

Although when I tried it with a custom table and it did not, {$res} is throw above of the actual template.

PHP:
<?php
 
    namespace custom_addons;

    class table2 {

        public static function table2($tagChildren, $tagOption, $tag, array $options, \XF\BbCode\Renderer\AbstractRenderer $renderer)
        {
            $res = $renderer->renderSubTree($tagChildren, $options);
            $toptions = trim(strip_tags($tag['option']));
            $toptions = preg_split("|\||", $toptions, -1, PREG_SPLIT_NO_EMPTY);

            @list($class, $id, $frame) = $toptions;
            if ($tmp = trim($class)) {
                $class = "$tmp";
            }
            if ($tmp = trim($id)) {
                $id = "$tmp";
            }
            if ($tmp = trim($frame)) {
                $frame = "$tmp";
            }
            
            $templater = $renderer->getTemplater();
            $customTemplate = $templater->renderTemplate('public:custom_addons_table2', [
                'class' => $class,
                'id' => $id,
                'frame' => $frame,
                'res' => $res,
            ], true);

            return $customTemplate;
        }

    }
?>

Code:
<div class="bbTable">
    <table class="{$class}" id="{$id}" frame="{$frame}">
        <tbody>
            <tr>
                <td>1</td>
                <td>2</td>
            </tr>
            <tr>
                <td>3</td>
                <td>4</td>
            </tr>
            {$res|raw}
        </tbody>
    </table>
</div>

1617397296351.png

1617397311296.png

1617397360887.png
 

Lukas W.

Well-known member
That's normal browser behavior. Anything that doesn't belong into the table syntax will be pushed to the top or bottom. If you inspect the page source you'll see it is located correctly. You'll have to parse the TR and TD elements in your code to HTML first
 

Eternity7

Member
That's normal browser behavior. Anything that doesn't belong into the table syntax will be pushed to the top or bottom. If you inspect the page source you'll see it is located correctly. You'll have to parse the TR and TD elements in your code to HTML first

Sorry I don't know how to parse the TR and TD elements in my code to HTML first, do you mind pointing it out?
 

Eternity7

Member
You can reference the built-in table BB code in \XF\BbCode\Renderer\Html Line 1478-1515

Unfortunately I don't understand the code.

PHP:
public function renderTagTable(array $children, $option, array $tag, array $options)
    {
        $rows = [];
        $columnCounts = [];
        $lostAndFound = [];
        foreach ($children as $child)
        {
            if (is_array($child))
            {
                if ($child['tag'] === 'tr')
                {
                    $rows[] = $this->renderTableRow($child, $options, $columnCount, $lostAndFound);
                    $columnCounts[] = $columnCount;
                }
                else
                {
                    $lostAndFound[] = $this->renderSubTree([$child], $options);
                }
            }
            else if (trim($child) !== '')
            {
                $lostAndFound[] = $this->renderSubTree([$child], $options);
            }
        }

        $maxColumnCount = max($columnCounts ?: [0]);
        foreach ($columnCounts as $i => $columnCount)
        {
            if ($columnCount < $maxColumnCount)
            {
                $td = strpos($rows[$i], '<th') !== false ? 'th' : 'td';
                $filler = str_repeat("<$td></$td>", $maxColumnCount - $columnCount);
                $rows[$i] = preg_replace('#</tr>$#', "$filler\0", $rows[$i]);
            }
        }

        return $this->renderFinalTableHtml(implode('', $rows), $option, implode("\n", $lostAndFound));
    }

Ultimately, what I'm trying to go for is a BBCode of this sort:

Rich (BB code):
[table2]
|-
|row 1 col 1
|row 1 col 2
|row 1 col 3
|-
|row 2 col 1
|row 2 col 2
|row 2 col 3
[/table2]

Rich (BB code):
[table2=!attribute !style]
|-!attribute !style]
|row 1 col 1
|row 1 col 2
|row 1 col 3
|-
|row 2 col 1
|!attribute !style]row 2 col 2
|row 2 col 3
[/table2]

where it only accepts a few specific attributes like rules, frame, colspan, rowspan, etc - for example:

Rich (BB code):
[table2=!rules=rows align=center !background: purple;]
|-
|row 1 col 1
|row 1 col 2
|row 1 col 3
|-
|row 2 col 1
|!colspan=2 ! color:green; font-size: 13px;]row 2 col 2 & col 3
[/table2]

Is it possible?
 
Top