Addon Templates Still Render While Addon Disabled

pegasus

Well-known member
Affected version
2.2.11
At first glance, maybe this doesn't sound like a big issue, but let's start off with the first point: inconsistency. When an add-on is disabled, its event listeners and template modifications are also disabled, meaning that code is not run. If we are in the habit of not running an add-on's code while it's disabled, why not include template code in that?

As a coder myself, this inconsistency has been documented in bug reports for my add-ons to lead to fatal errors. Here's how:

XenForo allows for add-ons to implement something called "template functions", which can be added to \XF\Template\Templater using event listeners (calling $templater->addFunctions in event templater_setup) and/or applying class extensions to \XF\Template\Templater. Add-ons can then use these template functions that they've created within their own templates.

But if the add-on is disabled, XenForo disables the event listeners and class extensions that setup the custom template functions.
Meanwhile, it is still possible to render a template that calls such a template function.
Most egregious is when a custom template function has been used in an add-on's .less template. In this case, XenForo's guest cache (and other server side caches) caches HTML responses that include calls to css.php which use the .less template, while the add-on is disabled, and while the code setting up the template functions is disabled. This leads to \XF\Template\Templater throwing:
Code:
trigger_error("Function $name is unknown", E_USER_WARNING);

This is not limited to just CSS output. It may be typical for multiple add-ons by a single developer, or multiple add-ons that simply have support for each other's features, to attempt to render the template of another add-on, while one add-on is disabled and the other is not. Then we have the same problem.

It seems close to impossible for an add-on developer to resolve this situation on their own (any code trying to implement a workaround would also just be disabled when the add-on is disabled). While XenForo also provides the template function is_addon_active, it seems unreasonable to have to use this in a conditional around every potential usage of a template function.

There are a number of ways for XenForo devs to resolve this design issue and ideally the solution is some combination of these:

#1 Do NOT trigger_error for a missing template function unless the forum is in development mode, AND the add-on for the containing template is also enabled.

#2 Automatically clear the XenForo guest cache when an add-on's active state is changed.

#3 Do NOT render a template if the template is provided by a disabled add-on. This requires a number of modifications to \XF\Template\Compiler and how it is implemented:
  • A new setAddonId method:
    Code:
    public function setAddonId($addonId)
    {
        $this->addonId = $addonId;
    }
    With appropriate code added to the "reset" method.
    Implemented by \XF\Service\Template\Compile::recompile:
    Code:
    $compiler->reset();
    $compiler->setAddonId($template->addon_id);
  • New code in the getCompletedTemplateCode method:
    Code:
    $parts[] = "'addon_id' => {$this->addonId}";
  • Finally, apply a test in \XF\Template\Templater::renderTemplate against $data['addon_id'] and only render an empty string if the add-on is disabled.
 
Last edited:
Related to https://xenforo.com/community/threads/css-for-disabled-styles-can-be-accessed-by-everyone.208910

While I understant that this behaviour can be a PITA, I don't think there is an easy solution.

Do NOT trigger_error for a missing template function unless the forum is in development mode, AND the add-on for the containing template is also enabled.
This could cause issues to go unnoticed for a long time; personally I'd still want to be informed that templates / ads / etc. need to be updated even if development mode is not enabled.

Automatically clear the XenForo guest cache when an add-on's active state is changed
This might partly work around issues with less templates, but wouldn't fix all of them.
It would also needlessly invalidate the whole guest page cache even if no relevant changes have occured.

Do NOT render a template if the template is provided by a disabled add-on.
Should probably be done, but also doesn't entriely fix the issue as custom templater function could be used in any template, not just in templated belonging to the Add-on that defines them.
 
This also happens when then an add-on upgrade is in progress. During an upgrade, the add-on is in a zombie state.

It is technically active, but all the class extensions and code events are disabled.
 
Top Bottom