XF 2.2 Getting the post author user_id in a custom bbcode with Callback

Lee

Well-known member
I have the following code:

PHP:
public static function renderChar(array $children, $option, array $tag, array $options, AbstractRenderer $renderer)
    {
        $output = trim($renderer->renderSubTree($children, $options));

        $charCode = \XF::visitor()->Profile->custom_fields->CharCode;

            return $renderer->wrapHtml(
            '<div style="color: ' . $charCode . '">',
            $output,
            '</div>'
        );
    }

I am looking to get the user entity of the user who is posting the message so I can load their custom_field "CharCode". At the moment I am loading the visitors value, which is not the outcome I want.

I guess I need to load the user entity by doing something like:
PHP:
$userId = $attributes;

$user = \XF::em()->find('XF:User', $userId);

to make this data available, but how do I get the user ID of the posting user to get the right entity?

Thanks :)
 
This is sadly more complex than you think, as XenForo doesn't actually have the concept of an "owner" for content.

In my Advanced bbcodes pack add-on, I've got "moderator only" bb-code which needs todo the following sort of hoop jumping to extract the owning user:
PHP:
protected function populateRenderState(array $options, \XF\Entity\User &$user = null)
{
    $helperRepo = \SV\StandardLib\Helper::repo();
    $entity = $options['entity'] ?? null;
    if ($entity instanceof \XF\Mvc\Entity\Entity)
    {
...
        $user = $helperRepo->getUserEntity($entity);
        if ($user !== null && ($entity->isValidGetter('Content') || $entity->isValidRelation('Content')))
        {
            $user = $helperRepo->getUserEntity($entity->get('Content'));
        }
        // XFRM support, as it doesn't have a User/Content relationship...
        if ($user !== null && ($entity->isValidGetter('Resource') || $entity->isValidRelation('Resource')))
        {
            $user = $helperRepo->getUserEntity($entity->get('Resource'));
        }
    }
    else if ($this->renderer->getRules()->getSubContext() === 'preview')
    {
        $user = $options['user'] ?? null;
        if ($user !== null)
        {
            $user = $helperRepo->getUserEntity($user);
        }
    }
}

getUserEntity is from my (free) StandardLib addon
(I probably should move the "Content" and "Resource" checking code into it, but haven't gotten around to that yet.
 
Last edited:
You should also make sure $charCode is escaped when rendering:
PHP:
$charCode = \XF::visitor()->Profile->custom_fields->CharCode;
$charCode = htmlspecialchars($charCode);

    return $renderer->wrapHtml(
    '<div style="color: ' . $charCode  . '">',
    $output,
    '</div>'
);
 
You should also make sure $charCode is escaped when rendering:
PHP:
$charCode = \XF::visitor()->Profile->custom_fields->CharCode;
$charCode = htmlspecialchars($charCode);

    return $renderer->wrapHtml(
    '<div style="color: ' . $charCode  . '">',
    $output,
    '</div>'
);
Thanks @Xon - is this to ensure nobody can run any harmful code?
 
It is to avoid the custom field's data potentially escaping the HTML attribute and becoming a persistent HTML/javascript injection. You might have validation on data being set, but that doesn't apply to any existing data
 
  • Like
Reactions: Lee
It is to avoid the custom field's data potentially escaping the HTML attribute and becoming a persistent HTML/javascript injection. You might have validation on data being set, but that doesn't apply to any existing data
Thanks Xon. Appreciate your help.
 
  • Like
Reactions: Xon
That would require extending XF\BbCode\Renderer\Html and extending the getRenderedQuote method.

You can extract the user id with $source['id'] ?? $attributes['member'] null (recommend you double check, was just a quick look!) and then fetch the user and extract the custom field and push back into the $attributes argument to get passed to the template. Then use a template modification on the public:bb_code_tag_quote to inject the relevant css/html as required.

You might be able to get away with wrapping the entire results if required, but I think you'ld need to modify the bb_code_tag_quote template
 
Top Bottom