From 7c79c22cb75279018124c9f265848e14f31f976a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 28 Jun 2021 16:44:53 +0200 Subject: [PATCH] Add support for version upgrades (#4160) * Add WCF::AVAILABLE_UPGRADE_VERSION * Expose the available upgrade version to packageList.tpl * Show notice in packageList if an upgrade is available * Add upgrade override support to PackageUpdateServer * Show notice about enabled upgrade override in packageList and packageUpdateServerList * Add PackageEnableUpgradeOverrideForm * Support disabling the upgrade override if there are issues * Add version checks from update_com.woltlab.wcf_5.4_checkSystemRequirements.php to PackageEnableUpgradeOverrideForm * Add language items for WoltLab Suite upgrades * Clear package lists when toggling the upgrade override * Add requested-woltlab-suite-version header to package list requests * Improved the messages and restrict the upgrade to the maintenance mode * Restrict the experimental upgrade to the maintenance mode * Removed the upgrade notice from the package server list Co-authored-by: Alexander Ebert --- .../packageEnableUpgradeOverride.tpl | 20 +++ .../packageEnableUpgradeOverrideIssues.tpl | 5 + .../files/acp/templates/packageList.tpl | 10 ++ ...PackageEnableUpgradeOverrideForm.class.php | 162 ++++++++++++++++++ .../lib/acp/page/PackageListPage.class.php | 13 +- .../server/PackageUpdateServer.class.php | 48 +++++- .../install/files/lib/system/WCF.class.php | 6 + .../package/PackageUpdateDispatcher.class.php | 10 ++ wcfsetup/install/lang/de.xml | 8 + wcfsetup/install/lang/en.xml | 8 + 10 files changed, 284 insertions(+), 6 deletions(-) create mode 100644 wcfsetup/install/files/acp/templates/packageEnableUpgradeOverride.tpl create mode 100644 wcfsetup/install/files/acp/templates/packageEnableUpgradeOverrideIssues.tpl create mode 100644 wcfsetup/install/files/lib/acp/form/PackageEnableUpgradeOverrideForm.class.php diff --git a/wcfsetup/install/files/acp/templates/packageEnableUpgradeOverride.tpl b/wcfsetup/install/files/acp/templates/packageEnableUpgradeOverride.tpl new file mode 100644 index 0000000000..735be3917f --- /dev/null +++ b/wcfsetup/install/files/acp/templates/packageEnableUpgradeOverride.tpl @@ -0,0 +1,20 @@ +{capture assign='pageTitle'}{lang version=$availableUpgradeVersion}wcf.acp.package.enableUpgradeOverride{/lang}{/capture} +{include file='header' pageTitle=$pageTitle} + +
+
+

{$pageTitle}

+
+ + +
+ +{@$form->getHtml()} + +{include file='footer'} diff --git a/wcfsetup/install/files/acp/templates/packageEnableUpgradeOverrideIssues.tpl b/wcfsetup/install/files/acp/templates/packageEnableUpgradeOverrideIssues.tpl new file mode 100644 index 0000000000..7600da03e3 --- /dev/null +++ b/wcfsetup/install/files/acp/templates/packageEnableUpgradeOverrideIssues.tpl @@ -0,0 +1,5 @@ + diff --git a/wcfsetup/install/files/acp/templates/packageList.tpl b/wcfsetup/install/files/acp/templates/packageList.tpl index 29a593c175..32d3ad28af 100644 --- a/wcfsetup/install/files/acp/templates/packageList.tpl +++ b/wcfsetup/install/files/acp/templates/packageList.tpl @@ -62,6 +62,16 @@

{lang}wcf.acp.language.item.hasRecentlyDisabledCustomValues{/lang}

{/if} +{if $__wcf->session->getPermission('admin.configuration.package.canUpdatePackage')} + {if $availableUpgradeVersion !== null} + {if $upgradeOverrideEnabled} +

{lang version=$availableUpgradeVersion}wcf.acp.package.upgradeOverrideEnabled{/lang}

+ {else} +

{lang version=$availableUpgradeVersion}wcf.acp.package.availableUpgradeVersion{/lang}

+ {/if} + {/if} +{/if} + {hascontent}
{content}{pages print=true assign=pagesLinks controller='PackageList' link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder"}{/content} diff --git a/wcfsetup/install/files/lib/acp/form/PackageEnableUpgradeOverrideForm.class.php b/wcfsetup/install/files/lib/acp/form/PackageEnableUpgradeOverrideForm.class.php new file mode 100644 index 0000000000..7f52e7071c --- /dev/null +++ b/wcfsetup/install/files/lib/acp/form/PackageEnableUpgradeOverrideForm.class.php @@ -0,0 +1,162 @@ + + * @package WoltLabSuite\Core\Acp\Form + * @since 5.3 + */ +final class PackageEnableUpgradeOverrideForm extends AbstractFormBuilderForm { + /** + * @inheritDoc + */ + public $formAction = 'enable'; + + /** + * @inheritDoc + */ + public $activeMenuItem = 'wcf.acp.menu.link.package.list'; + + /** + * @inheritDoc + */ + public $neededPermissions = ['admin.configuration.package.canUpdatePackage']; + + /** + * @inheritDoc + */ + protected function createForm() { + parent::createForm(); + + $issues = $this->getIssuesPreventingUpgrade(); + + if (empty($issues)) { + $this->form->appendChildren([ + BooleanFormField::create('enable') + ->label('wcf.acp.package.enableUpgradeOverride.enable') + ->value(PackageUpdateServer::isUpgradeOverrideEnabled()) + ]); + } + else { + $this->form->addDefaultButton(false); + $this->form->appendChildren([ + TemplateFormNode::create('issues') + ->templateName('packageEnableUpgradeOverrideIssues') + ->variables([ + 'issues' => $issues + ]), + new class extends AbstractFormField { + // TODO: Replace this with RejectEverythingFormField in 5.4+. + public function __construct() { + $this->id('rejectEverything'); + } + + public function getFieldHtml() { + return ''; + } + + public function getHtml() { + return ''; + } + + public function readValue() { + return $this; + } + + public function validate() { + $this->addValidationError(new FormFieldValidationError('rejectEverything')); + } + } + ]); + } + } + + private function getIssuesPreventingUpgrade() { + $issues = []; + + $phpVersion = \PHP_VERSION; + $neededPhpVersion = '7.2.24'; + if (!\version_compare($phpVersion, $neededPhpVersion, '>=')) { + if (WCF::getLanguage()->getFixedLanguageCode() === 'de') { + $message = "Ihre PHP-Version '{$phpVersion}' ist unzureichend für die Installation dieser Software. PHP-Version {$neededPhpVersion} oder höher wird benötigt."; + } + else { + $message = "Your PHP version '{$phpVersion}' is insufficient for installation of this software. PHP version {$neededPhpVersion} or greater is required."; + } + + $issues[] = $message; + } + + $sqlVersion = WCF::getDB()->getVersion(); + $compareSQLVersion = \preg_replace('/^(\d+\.\d+\.\d+).*$/', '\\1', $sqlVersion); + if (\stripos($sqlVersion, 'MariaDB') !== false) { + $neededSqlVersion = '10.1.44'; + $sqlFork = 'MariaDB'; + } + else { + $sqlFork = 'MySQL'; + if ($compareSQLVersion[0] === '5') { + $neededSqlVersion = '5.7.31'; + } + else { + $neededSqlVersion = '8.0.19'; + } + } + + if (!\version_compare($compareSQLVersion, $neededSqlVersion, '>=')) { + if (WCF::getLanguage()->getFixedLanguageCode() === 'de') { + $message = "Ihre {$sqlFork}-Version '{$sqlVersion}' ist unzureichend für die Installation dieser Software. {$sqlFork}-Version {$neededSqlVersion} oder höher wird benötigt."; + } else { + $message = "Your {$sqlFork} version '{$sqlVersion}' is insufficient for installation of this software. {$sqlFork} version {$neededSqlVersion} or greater is required."; + } + + $issues[] = $message; + } + + return $issues; + } + + /** + * @inheritDoc + */ + public function save() { + AbstractForm::save(); + + $formData = $this->form->getData(); + if ($formData['data']['enable']) { + RegistryHandler::getInstance()->set('com.woltlab.wcf', PackageUpdateServer::class . "\0upgradeOverride", \TIME_NOW); + } + else { + RegistryHandler::getInstance()->delete('com.woltlab.wcf', PackageUpdateServer::class . "\0upgradeOverride"); + } + + PackageUpdateServer::resetAll(); + + $this->saved(); + } + + /** + * @inheritDoc + */ + public function assignVariables() { + parent::assignVariables(); + + WCF::getTPL()->assign([ + 'availableUpgradeVersion' => WCF::AVAILABLE_UPGRADE_VERSION, + ]); + } +} diff --git a/wcfsetup/install/files/lib/acp/page/PackageListPage.class.php b/wcfsetup/install/files/lib/acp/page/PackageListPage.class.php index b06da25f87..07ee233434 100644 --- a/wcfsetup/install/files/lib/acp/page/PackageListPage.class.php +++ b/wcfsetup/install/files/lib/acp/page/PackageListPage.class.php @@ -1,6 +1,7 @@ assign([ 'recentlyDisabledCustomValues' => LanguageFactory::getInstance()->countRecentlyDisabledCustomValues(), - 'packageID' => $this->packageID + 'packageID' => $this->packageID, + 'availableUpgradeVersion' => $availableUpgradeVersion, + 'upgradeOverrideEnabled' => PackageUpdateServer::isUpgradeOverrideEnabled(), ]); } diff --git a/wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServer.class.php b/wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServer.class.php index bc00b3e095..aff51d81ce 100644 --- a/wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServer.class.php +++ b/wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServer.class.php @@ -4,6 +4,7 @@ use wcf\data\DatabaseObject; use wcf\system\cache\builder\PackageUpdateCacheBuilder; use wcf\system\io\RemoteFile; use wcf\system\Regex; +use wcf\system\registry\RegistryHandler; use wcf\system\WCF; use wcf\util\FileUtil; use wcf\util\Url; @@ -54,11 +55,16 @@ class PackageUpdateServer extends DatabaseObject { parent::handleData($data); $prefix = ENABLE_ENTERPRISE_MODE ? 'cloud/' : ''; + $officialPath = \wcf\getMinorVersion(); + if (self::isUpgradeOverrideEnabled()) { + $officialPath = WCF::AVAILABLE_UPGRADE_VERSION; + } + if ($this->isWoltLabUpdateServer()) { - $this->data['serverURL'] = 'http://update.woltlab.com/'.$prefix.\wcf\getMinorVersion().'/'; + $this->data['serverURL'] = "http://update.woltlab.com/{$prefix}{$officialPath}/"; } if ($this->isWoltLabStoreServer()) { - $this->data['serverURL'] = 'http://store.woltlab.com/'.$prefix.\wcf\getMinorVersion().'/'; + $this->data['serverURL'] = "http://store.woltlab.com/{$prefix}{$officialPath}/"; } if ($this->isWoltLabUpdateServer() || $this->isWoltLabStoreServer()) { $this->data['isDisabled'] = 0; @@ -96,15 +102,20 @@ class PackageUpdateServer extends DatabaseObject { $results[$packageServer->packageUpdateServerID] = $packageServer; } + $officialPath = \wcf\getMinorVersion(); + if (self::isUpgradeOverrideEnabled()) { + $officialPath = WCF::AVAILABLE_UPGRADE_VERSION; + } + if (!$woltlabUpdateServer) { $packageServer = PackageUpdateServerEditor::create([ - 'serverURL' => 'http://update.woltlab.com/'.\wcf\getMinorVersion().'/', + 'serverURL' => "http://update.woltlab.com/{$officialPath}/", ]); $results[$packageServer->packageUpdateServerID] = $packageServer; } if (!$woltlabStoreServer) { $packageServer = PackageUpdateServerEditor::create([ - 'serverURL' => 'http://store.woltlab.com/'.\wcf\getMinorVersion().'/', + 'serverURL' => "http://store.woltlab.com/{$officialPath}/", ]); $results[$packageServer->packageUpdateServerID] = $packageServer; } @@ -345,6 +356,35 @@ class PackageUpdateServer extends DatabaseObject { return false; } + + /** + * Returns whether the official update servers will point to WCF::AVAILABLE_UPGRADE_VERSION. + * + * @return bool + * @since 5.3 + */ + public static final function isUpgradeOverrideEnabled() { + if (WCF::AVAILABLE_UPGRADE_VERSION === null) { + return false; + } + + $override = RegistryHandler::getInstance()->get('com.woltlab.wcf', self::class . "\0upgradeOverride"); + + if (!$override) { + return false; + } + + if ($override < TIME_NOW - 86400) { + RegistryHandler::getInstance()->delete('com.woltlab.wcf', self::class . "\0upgradeOverride"); + + // Clear package list cache to actually stop the upgrade from happening. + self::resetAll(); + + return false; + } + + return true; + } /** * Resets all update servers into their original state and purges diff --git a/wcfsetup/install/files/lib/system/WCF.class.php b/wcfsetup/install/files/lib/system/WCF.class.php index c8631c0dea..a8be9b2e33 100644 --- a/wcfsetup/install/files/lib/system/WCF.class.php +++ b/wcfsetup/install/files/lib/system/WCF.class.php @@ -76,6 +76,12 @@ if (!defined('NO_IMPORTS')) { * @package WoltLabSuite\Core\System */ class WCF { + /** + * @var ?string + * @since 5.3 + */ + const AVAILABLE_UPGRADE_VERSION = '5.4'; + /** * list of supported legacy API versions * @var integer[] diff --git a/wcfsetup/install/files/lib/system/package/PackageUpdateDispatcher.class.php b/wcfsetup/install/files/lib/system/package/PackageUpdateDispatcher.class.php index 742e3e6858..549d4e844d 100644 --- a/wcfsetup/install/files/lib/system/package/PackageUpdateDispatcher.class.php +++ b/wcfsetup/install/files/lib/system/package/PackageUpdateDispatcher.class.php @@ -153,6 +153,16 @@ class PackageUpdateDispatcher extends SingletonFactory { $request = new HTTPRequest($updateServer->getListURL($forceHTTP), $settings); + $requestedVersion = \wcf\getMinorVersion(); + if (PackageUpdateServer::isUpgradeOverrideEnabled()) { + $requestedVersion = WCF::AVAILABLE_UPGRADE_VERSION; + } + + $request->addHeader( + 'requested-woltlab-suite-version', + $requestedVersion + ); + $apiVersion = $updateServer->apiVersion; if (in_array($apiVersion, ['2.1', '3.1'])) { // skip etag check for WoltLab servers when an auth code is provided diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml index 11c1e96ea9..4e71905956 100644 --- a/wcfsetup/install/lang/de.xml +++ b/wcfsetup/install/lang/de.xml @@ -1991,6 +1991,14 @@ Die Datenbestände werden sorgfältig gepflegt, aber es ist nicht ausgeschlossen Unbekannter Fehler. {/if} {/implode}]]> + + + +
+Systemvoraussetzungen prüfen, um das Upgrade freizugeben]]>
+ +
+Upgrade abbrechen]]>
diff --git a/wcfsetup/install/lang/en.xml b/wcfsetup/install/lang/en.xml index 5363b3acec..cc13375921 100644 --- a/wcfsetup/install/lang/en.xml +++ b/wcfsetup/install/lang/en.xml @@ -1975,6 +1975,14 @@ If you have already bought the licenses for the listed apps, th Unknown error. {/if} {/implode}]]> + + + +
+Validate the system requirements to begin the upgrade]]>
+ +
+Cancel the upgrade]]>
-- 2.20.1