Fixed Error during upgrade from non-php7.4 compatible XF2 on php7.4

Affected version
2.1.10 Patch 2

Xon

Well-known member
On upgrading an older development instance from 2.1.3 => 2.1.10 patch2, I received these errors;

Code:
> php cmd.php xf-upgrade -v
Current version: 2010370
Upgrade target: 2011072 (2.1.10 Patch 2)
Are you sure you want to continue with the upgrade? [y/n] y

Running upgrade to 2.1.10, step 1... done.
All upgrade steps run up to version 2.1.10 Patch 2.

In Fn.php line 7:

  syntax error, unexpected 'Fn' (T_FN), expecting identifier (T_STRING)

In Fn.php line 7:

  [ParseError]
  syntax error, unexpected 'Fn' (T_FN), expecting identifier (T_STRING)


Exception trace:
  at /var/www/html/src/XF/Template/Compiler/Syntax/Fn.php:7
Composer\Autoload\includeFile() at /var/www/html/src/vendor/composer/ClassLoader.php:322
Composer\Autoload\ClassLoader->loadClass() at n/a:n/a
spl_autoload_call() at n/a:n/a
unserialize() at /var/www/html/src/XF/Mvc/Entity/ValueFormatter.php:17
XF\Mvc\Entity\ValueFormatter->decodeValueFromSource() at /var/www/html/src/XF/Mvc/Entity/ValueFormatter.php:59
XF\Mvc\Entity\ValueFormatter->decodeValueFromSourceExtended() at /var/www/html/src/XF/Mvc/Entity/Manager.php:792
XF\Mvc\Entity\Manager->decodeValueFromSourceExtended() at /var/www/html/src/XF/Mvc/Entity/Entity.php:824
XF\Mvc\Entity\Entity->_columnValueIsDifferent() at /var/www/html/src/XF/Mvc/Entity/Entity.php:632
XF\Mvc\Entity\Entity->set() at /var/www/html/src/XF/Mvc/Entity/Entity.php:548
XF\Mvc\Entity\Entity->__set() at /var/www/html/src/XF/Entity/Template.php:173
XF\Entity\Template->verifyTemplate() at /var/www/html/src/XF/Mvc/Entity/Entity.php:768
XF\Mvc\Entity\Entity->_verifyValueCustom() at /var/www/html/src/XF/Mvc/Entity/Entity.php:613
XF\Mvc\Entity\Entity->set() at /var/www/html/src/XF/Mvc/Entity/Entity.php:548
XF\Mvc\Entity\Entity->__set() at /var/www/html/src/XF/AddOn/DataType/BbCodeMediaSite.php:81
XF\AddOn\DataType\BbCodeMediaSite->importAddOnData() at /var/www/html/src/XF/Job/AddOnData.php:106
XF\Job\AddOnData->run() at /var/www/html/src/XF/Job/Atomic.php:38
XF\Job\Atomic->run() at /var/www/html/src/XF/Job/Manager.php:253
XF\Job\Manager->runJobInternal() at /var/www/html/src/XF/Job/Manager.php:195
XF\Job\Manager->runJobEntry() at /var/www/html/src/XF/Job/Manager.php:146
XF\Job\Manager->runUnique() at /var/www/html/src/XF/Cli/Command/JobRunnerTrait.php:30
XF\Cli\Command\Upgrade->runJob() at /var/www/html/src/XF/Cli/Command/Upgrade.php:202
XF\Cli\Command\Upgrade->execute() at /var/www/html/src/vendor/symfony/console/Command/Command.php:255
Symfony\Component\Console\Command\Command->run() at /var/www/html/src/vendor/symfony/console/Application.php:987
Symfony\Component\Console\Application->doRunCommand() at /var/www/html/src/vendor/symfony/console/Application.php:255
Symfony\Component\Console\Application->doRun() at /var/www/html/src/vendor/symfony/console/Application.php:148
Symfony\Component\Console\Application->run() at /var/www/html/src/XF/Cli/Runner.php:63
XF\Cli\Runner->run() at /var/www/html/cmd.php:16

xf:upgrade [--skip-statistics]

Deleting the entire contents of src/XF, and reuploading gives this error;
Code:
> php cmd.php xf-upgrade -v
Current version: 2011072
Upgrade target: 2011072 (2.1.10 Patch 2)
You are already running the latest version. Rebuild the master data? [y/n] y
PHP Fatal error:  XF\Template\Compiler\Syntax\Expression::compile(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "XF\Template\Compiler\Syntax\Fn" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition in /var/www/sites/xf2test.atelieraphelion.com/html/src/XF/Template/Compiler/Syntax/Expression.php on line 22

Fatal error: XF\Template\Compiler\Syntax\Expression::compile(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "XF\Template\Compiler\Syntax\Fn" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition in /var/www/sites/xf2test.atelieraphelion.com/html/src/XF/Template/Compiler/Syntax/Expression.php on line 22

Disabling the caching ($config['cache']['enabled'] = false; in config.php) doesn't help.

The template which is erroring is _media_site_embed_youtube with the contents;
HTML:
<div class="bbMediaWrapper">
        <div class="bbMediaWrapper-inner">
                <iframe src="https://www.youtube.com/embed/{$id}?wmode=opaque&start={$start}"
                                width="560" height="315"
                                frameborder="0" allowfullscreen="true"></iframe>
        </div>
</div>

The problem is due to XF\Mvc\Entity\ValueFormatter::decodeValueFromSource;
PHP:
    public function decodeValueFromSource($type, $value)
    {
        if ($value === null)
        {
            return $value;
        }

        switch ($type)
        {
            case Entity::SERIALIZED:
                return @unserialize($value);

            case Entity::SERIALIZED_ARRAY:
                $result = @unserialize($value);
                if (!is_array($result))
                {
                    $result = [];
                }
                return $result;
....
The @ on unserialize doesn't prevent class name errors from throwing an exception. Catching \Throwable however works, if the files exist, doesn't solve restoring an older XF instance onto php 7.4+ and then trying to update. That error can't be caught

Re-uploading the old Fn files, and patching ValueFormatter to return false if \Throwable is thrown from unserialize gives this error;

Code:
> php cmd.php xf:upgrade -v -n
Current version: 2011072
Upgrade target: 2011072 (2.1.10 Patch 2)
You are already running the latest version. Rebuild the master data? [y/n] y

In Compiler.php line 217:

  [ErrorException]
  Argument 1 passed to XF\Template\Compiler::compileAst() must be an instance of XF\Template\Compiler\Ast, false given, called in /var/www/html/src/XF/Service/Template/Compile.php on line 28


Exception trace:
  at /var/www/html/src/XF/Template/Compiler.php:217
XF\Cli\Runner->run() at /var/www/html/cmd.php:16

In Compiler.php line 217:

  [TypeError]
  Argument 1 passed to XF\Template\Compiler::compileAst() must be an instance of XF\Template\Compiler\Ast, false given, called in /var/www/html/src/XF/Service/Template/Compile.php on line 28


Exception trace:
  at /var/www/html/src/XF/Template/Compiler.php:217
XF\Template\Compiler->compileAst() at /var/www/html/src/XF/Service/Template/Compile.php:28
XF\Service\Template\Compile->recompile() at /var/www/html/src/XF/Service/Phrase/Compile.php:71
XF\Service\Phrase\Compile->recompileIncludeContent() at /var/www/html/src/XF/Entity/Phrase.php:198
XF\Entity\Phrase->_postDelete() at /var/www/html/src/XF/Mvc/Entity/Entity.php:1595
XF\Mvc\Entity\Entity->delete() at /var/www/html/src/XF/AddOn/DataType/AbstractDataType.php:117
XF\AddOn\DataType\AbstractDataType->deleteEntity() at /var/www/html/src/XF/AddOn/DataType/AbstractDataType.php:92
XF\AddOn\DataType\AbstractDataType->deleteOrphanedSimple() at /var/www/html/src/XF/AddOn/DataType/Phrase.php:91
XF\AddOn\DataType\Phrase->deleteOrphanedAddOnData() at /var/www/html/src/XF/Job/AddOnData.php:110
XF\Job\AddOnData->run() at /var/www/html/src/XF/Job/Atomic.php:38
XF\Job\Atomic->run() at /var/www/html/src/XF/Job/Manager.php:253
XF\Job\Manager->runJobInternal() at /var/www/html/src/XF/Job/Manager.php:195
XF\Job\Manager->runJobEntry() at /var/www/html/src/XF/Job/Manager.php:146
XF\Job\Manager->runUnique() at /var/www/html/src/XF/Cli/Command/JobRunnerTrait.php:30
XF\Cli\Command\Upgrade->runJob() at /var/www/html/src/XF/Cli/Command/Upgrade.php:202
XF\Cli\Command\Upgrade->execute() at /var/www/html/src/vendor/symfony/console/Command/Command.php:255
Symfony\Component\Console\Command\Command->run() at /var/www/html/src/vendor/symfony/console/Application.php:987
Symfony\Component\Console\Application->doRunCommand() at /var/www/html/src/vendor/symfony/console/Application.php:255
Symfony\Component\Console\Application->doRun() at /var/www/html/src/vendor/symfony/console/Application.php:148
Symfony\Component\Console\Application->run() at /var/www/html/src/XF/Cli/Runner.php:63
XF\Cli\Runner->run() at /var/www/html/cmd.php:16

xf:upgrade [--skip-statistics]

Patching XF\Service\Template\Compile::recompile to check that $template->template_parsed has content and isn't false/null got the master template rebuild working
 
Last edited:

XF Bug Bot

XenForo bug fixer bot
Staff member
Thank you for reporting this issue, it has now been resolved. We are aiming to include any changes that have been made in a future XF release (2.2.0 Beta 6).

Change log:
Workaround issues when upgrading from older versions of XenForo 2 whilst on PHP 7.4 or greater
There may be a delay before changes are rolled out to the XenForo Community.
 

Mike

XenForo developer
Staff member
Just to give some more specifics here, we've restore the old Fn.php file with a class_alias to the new Func version. It looks like we can instantiate an a no-longer-valid class name from an unserialize via this and it should silently work.
 

PaulB

Active member
Just to give some more specifics here, we've restore the old Fn.php file with a class_alias to the new Func version. It looks like we can instantiate an a no-longer-valid class name from an unserialize via this and it should silently work.
You get points for that workaround. I didn't think there'd be an easy fix for this one.
 
Top