XF 2.2 Correct usage of addClassExtension to extend Templater class to support both XF2.1 and XF2.2?

mazzly

Well-known member
Hi,

We recently started seeing a compatibility problem with our own addon related to some AddonFlare addons, and the "workaround" at the moment is for our addon to set a higher execution order for the Templater extension. This doesn't feel like the correct solution...

I also have a feeling that this was not a problem before we added XF2.1 support to our addon by overriding the class extension in the app_setup event.

The errors can be seen here and here

Okay, so we have:

The class extension is setup normally as XF\Template\Templater -> MaZ\AMP\XF\Template\Templater under Development settings

Templater.php:
PHP:
class Templater extends XFCP_Templater
{
    // All the common functions for XF2.1 / XF2.2 
}

Templater21.php:
PHP:
class Templater21 extends Templater
{
    public function renderTemplate($template, array $params = [], $addDefaultParams = true)
    {
        // Same code as in Templater22, but with different func signature
    }
}
}

Templater22.php:
PHP:
class Templater22 extends Templater
{
    public function renderTemplate($template, array $params = [], $addDefaultParams = true, ExtensionSet $extensionOverrides = null)
    {
        // Same code as in Templater21, but with different func signature
    }
}
}

if our event listeners we have:
PHP:
public static function app_setup(\XF\App $app)
{
    if (\XF::$versionId < 2020000) {
        $templater_class = '\MaZ\AMP\XF\Template\Templater21';
    } else {
        $templater_class = '\MaZ\AMP\XF\Template\Templater22';
    }
    $app->extension()->addClassExtension('\XF\Template\Templater', $templater_class);
}

Questions:
1. Is app_setup the correct event to do the class extension "override"
2. Is $app->extension()->addClassExtension() the correct way to override the extension "during runtime"
3. Is there some better way to extend the class differently to support XF2.1 / XF2.2 at the same time without needing 2 differently released packages.
 
Last edited:

Chris D

XenForo developer
Staff member
There is no reason to continue supporting XF 2.1 at this point. We don’t and many customers aren’t using it anymore. We don’t recommend trying to support both.
 

mazzly

Well-known member
There is no reason to continue supporting XF 2.1 at this point. We don’t and many customers aren’t using it anymore. We don’t recommend trying to support both.
Sure I understand that, and probably at some point we will cut off as we also like to use the "bleeding edge". But saying that the previous version shouldn't be supported at all is a bit naive I think :)

Could you give some insight into my above questions though? (I feel like the questions are being dodged with the above answer)
For example what happens when 2.3 is released and it has another change in some Templater's function signature, should we just then say "nope 2.2 is old news", or is there some recommended way where we can set that changed function to be handled correctly across the 2.2/2.3 version?
 

Chris D

XenForo developer
Staff member
Well, we don't support it and we no longer recommend customers who are using 2.1 to remain on it because if they need support, it simply won't be provided and we will no longer be providing updates for it. That's not naive, that's just a fact. 2.2 is not "bleeding edge" it is currently the only supported, stable version of the software.

If it's an existing add-on, then you already have a version that is compatible with XF 2.1. That should be the last version that is compatible with XF 2.1 and the next version should be compatible with only XF 2.2.

That's how we approach our add-on versioning, and it's how most developers are approaching their add-on versioning.

And, yes, the same applies in the future for any method signature changes.

As for whether your proposed solution would work, the answer is: I don't know. In theory, it should work and if it does then app_setup would be the code event to work with as that's the first one that fires. If it doesn't work, there's likely nothing more you can do.
 

mazzly

Well-known member
Well, we don't support it and we no longer recommend customers who are using 2.1 to remain on it because if they need support, it simply won't be provided and we will no longer be providing updates for it. That's not naive, that's just a fact. 2.2 is not "bleeding edge" it is currently the only supported, stable version of the software.

If it's an existing add-on, then you already have a version that is compatible with XF 2.1. That should be the last version that is compatible with XF 2.1 and the next version should be compatible with only XF 2.2.

That's how we approach our add-on versioning, and it's how most developers are approaching their add-on versioning.

And, yes, the same applies in the future for any method signature changes.

As for whether your proposed solution would work, the answer is: I don't know. In theory, it should work and if it does then app_setup would be the code event to work with as that's the first one that fires. If it doesn't work, there's likely nothing more you can do.
Okay thanks! :)

Well to report: it "kinda works" at the moment, just seems to be problematic if our execution order is lower than some other addon that extends the Templater class... (and AddonFlare seems to set a crazy high 99999999 number there)

Going forward we will probably also do the "new version will get updates"-route, and old version at best will get some security fix :)
 

Chris D

XenForo developer
Staff member
One other approach, and I’m not certain if it would work or not as I’m just theorising would be to have both of the template mods disabled and then enable the correct one on post upgrade via your setup script. Would definitely need some testing before going down that route though.
 

Xon

Well-known member
I use a different approach, I've written an aliasClass function which lets me generate a shim class, and redirect to which version I need to support. This is compatible with XFCP and functions which resolve back to the base class so I can do something like this;

Example; UserAlert.php;
PHP:
<?php

namespace SV\UserMentionsImprovements\XF\Repository;

\SV\StandardLib\Helper::repo()->aliasClass(
    'SV\UserMentionsImprovements\XF\Repository\UserAlert',
    \XF::$versionId < 2020000
        ? 'SV\UserMentionsImprovements\XF\Repository\XF2\UserAlert'
        : 'SV\UserMentionsImprovements\XF\Repository\XF22\UserAlert'
);

I use this pattern to support various XF versions and add-on which would normally break backwards compatibility
 

mazzly

Well-known member
Okay, so it seems I have found the issue.

Problem was that Templater21 and Templater22 inherited from Templater, which inherits from XFCP_Templater.
(I'm guessing the XFCP system won't be able to "extend" the classes that are not directly inheriting from XFCP_Foo ?)

What I did now to get it working:
  • Rename and move the Templater21 into XF21\Templater and have it inherit from XFCP_Templater
  • Rename and move the Templater22 into XF22\Templater and have it inherit from XFCP_Templater
  • Extend with those classes inside app_setup-event
I also have a Templater-class for the common things, which is always loaded by default with a class Extension set in the admin development settings.

Structure now looks like:
1613052151616.png

And now after the fix, the execution order doesn't matter anymore (which it shouldn't for my our needs)

Thanks @Chris D and @Xon for the insights :) 👍
 
Top