diff --git a/apps/settings/lib/Controller/AppSettingsController.php b/apps/settings/lib/Controller/AppSettingsController.php index a85ee8cc20a..7e1110ed1e6 100644 --- a/apps/settings/lib/Controller/AppSettingsController.php +++ b/apps/settings/lib/Controller/AppSettingsController.php @@ -568,24 +568,18 @@ class AppSettingsController extends Controller { $appId = $this->appManager->cleanAppId($appId); // Check if app is already downloaded - /** @var Installer $installer */ - $installer = Server::get(Installer::class); - $isDownloaded = $installer->isDownloaded($appId); - - if (!$isDownloaded) { - $installer->downloadApp($appId); + if (!$this->installer->isDownloaded($appId)) { + $this->installer->downloadApp($appId); } - $installer->installApp($appId); + $this->installer->installApp($appId); if (count($groups) > 0) { $this->appManager->enableAppForGroups($appId, $this->getGroupList($groups)); } else { $this->appManager->enableApp($appId); } - if (\OC_App::shouldUpgrade($appId)) { - $updateRequired = true; - } + $updateRequired = $updateRequired || $this->appManager->isUpgradeRequired($appId); } return new JSONResponse(['data' => ['update_required' => $updateRequired]]); } catch (\Throwable $e) { diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php index a4a94cdb6a2..6605fc4d8f9 100644 --- a/lib/private/App/AppManager.php +++ b/lib/private/App/AppManager.php @@ -727,7 +727,7 @@ class AppManager implements IAppManager { if ($appDbVersion && isset($appInfo['version']) && version_compare($appInfo['version'], $appDbVersion, '>') - && \OC_App::isAppCompatible($version, $appInfo) + && $this->isAppCompatible($version, $appInfo) ) { $appsToUpgrade[] = $appInfo; } @@ -817,7 +817,7 @@ class AppManager implements IAppManager { $info = $this->getAppInfo($appId); if ($info === null) { $incompatibleApps[] = ['id' => $appId, 'name' => $appId]; - } elseif (!\OC_App::isAppCompatible($version, $info)) { + } elseif (!$this->isAppCompatible($version, $info)) { $incompatibleApps[] = $info; } } @@ -1023,4 +1023,75 @@ class AppManager implements IAppManager { return true; } + + public function isUpgradeRequired(string $appId): bool { + $versions = $this->getAppInstalledVersions(); + $currentVersion = $this->getAppVersion($appId); + if ($currentVersion && isset($versions[$appId])) { + $installedVersion = $versions[$appId]; + if (!version_compare($currentVersion, $installedVersion, '=')) { + return true; + } + } + return false; + } + + public function isAppCompatible(string $serverVersion, array $appInfo, bool $ignoreMax = false): bool { + $requireMin = ''; + $requireMax = ''; + if (isset($appInfo['dependencies']['nextcloud']['@attributes']['min-version'])) { + $requireMin = $appInfo['dependencies']['nextcloud']['@attributes']['min-version']; + } elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['min-version'])) { + $requireMin = $appInfo['dependencies']['owncloud']['@attributes']['min-version']; + } elseif (isset($appInfo['requiremin'])) { + $requireMin = $appInfo['requiremin']; + } elseif (isset($appInfo['require'])) { + $requireMin = $appInfo['require']; + } + + if (isset($appInfo['dependencies']['nextcloud']['@attributes']['max-version'])) { + $requireMax = $appInfo['dependencies']['nextcloud']['@attributes']['max-version']; + } elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['max-version'])) { + $requireMax = $appInfo['dependencies']['owncloud']['@attributes']['max-version']; + } elseif (isset($appInfo['requiremax'])) { + $requireMax = $appInfo['requiremax']; + } + + if (!empty($requireMin) + && version_compare($this->adjustVersionParts($serverVersion, $requireMin), $requireMin, '<') + ) { + return false; + } + + if (!$ignoreMax && !empty($requireMax) + && version_compare($this->adjustVersionParts($serverVersion, $requireMax), $requireMax, '>') + ) { + return false; + } + + return true; + } + + /** + * Adjust the number of version parts of $version1 to match + * the number of version parts of $version2. + * + * @param string $version1 version to adjust + * @param string $version2 version to take the number of parts from + * @return string shortened $version1 + */ + private function adjustVersionParts(string $version1, string $version2): string { + //FIXME Most likely this function is not needed and version_compare directly will work. Should be tested. + $version1 = explode('.', $version1); + $version2 = explode('.', $version2); + // reduce $version1 to match the number of parts in $version2 + while (count($version1) > count($version2)) { + array_pop($version1); + } + // if $version1 does not have enough parts, add some + while (count($version1) < count($version2)) { + $version1[] = '0'; + } + return implode('.', $version1); + } } diff --git a/lib/private/Updater.php b/lib/private/Updater.php index 0b8c6e39cb9..fdbfa9690e5 100644 --- a/lib/private/Updater.php +++ b/lib/private/Updater.php @@ -23,7 +23,6 @@ use OC\Repair\Events\RepairInfoEvent; use OC\Repair\Events\RepairStartEvent; use OC\Repair\Events\RepairStepEvent; use OC\Repair\Events\RepairWarningEvent; -use OC_App; use OCP\App\IAppManager; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventDispatcher; @@ -319,7 +318,7 @@ class Updater extends BasicEmitter { foreach (array_merge($priorityTypes, [$pseudoOtherType]) as $type) { $stack = $stacks[$type]; foreach ($stack as $appId) { - if (\OC_App::shouldUpgrade($appId)) { + if ($this->appManager->isUpgradeRequired($appId)) { $this->emit('\OC\Updater', 'appUpgradeStarted', [$appId, $this->appManager->getAppVersion($appId)]); $this->appManager->upgradeApp($appId); $this->emit('\OC\Updater', 'appUpgrade', [$appId, $this->appManager->getAppVersion($appId)]); @@ -349,7 +348,7 @@ class Updater extends BasicEmitter { foreach ($apps as $app) { // check if the app is compatible with this version of Nextcloud $info = $this->appManager->getAppInfo($app); - if ($info === null || !OC_App::isAppCompatible($version, $info)) { + if ($info === null || !$this->appManager->isAppCompatible($version, $info)) { if ($this->appManager->isShipped($app)) { throw new \UnexpectedValueException('The files of the app "' . $app . '" were not correctly replaced before running the update'); } @@ -359,9 +358,6 @@ class Updater extends BasicEmitter { } } - /** - * @return bool - */ private function isCodeUpgrade(): bool { $installedVersion = $this->config->getSystemValueString('version', '0.0.0'); $currentVersion = implode('.', Util::getVersion()); diff --git a/lib/private/legacy/OC_App.php b/lib/private/legacy/OC_App.php index a37411256c7..6e9c1b8265c 100644 --- a/lib/private/legacy/OC_App.php +++ b/lib/private/legacy/OC_App.php @@ -539,37 +539,7 @@ class OC_App { } public static function shouldUpgrade(string $app): bool { - $versions = self::getAppVersions(); - $currentVersion = Server::get(\OCP\App\IAppManager::class)->getAppVersion($app); - if ($currentVersion && isset($versions[$app])) { - $installedVersion = $versions[$app]; - if (!version_compare($currentVersion, $installedVersion, '=')) { - return true; - } - } - return false; - } - - /** - * Adjust the number of version parts of $version1 to match - * the number of version parts of $version2. - * - * @param string $version1 version to adjust - * @param string $version2 version to take the number of parts from - * @return string shortened $version1 - */ - private static function adjustVersionParts(string $version1, string $version2): string { - $version1 = explode('.', $version1); - $version2 = explode('.', $version2); - // reduce $version1 to match the number of parts in $version2 - while (count($version1) > count($version2)) { - array_pop($version1); - } - // if $version1 does not have enough parts, add some - while (count($version1) < count($version2)) { - $version1[] = '0'; - } - return implode('.', $version1); + return Server::get(\OCP\App\IAppManager::class)->isUpgradeRequired($app); } /** @@ -586,42 +556,10 @@ class OC_App { * @param string $ocVersion Nextcloud version to check against * @param array $appInfo app info (from xml) * - * @return boolean true if compatible, otherwise false + * @return bool true if compatible, otherwise false */ public static function isAppCompatible(string $ocVersion, array $appInfo, bool $ignoreMax = false): bool { - $requireMin = ''; - $requireMax = ''; - if (isset($appInfo['dependencies']['nextcloud']['@attributes']['min-version'])) { - $requireMin = $appInfo['dependencies']['nextcloud']['@attributes']['min-version']; - } elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['min-version'])) { - $requireMin = $appInfo['dependencies']['owncloud']['@attributes']['min-version']; - } elseif (isset($appInfo['requiremin'])) { - $requireMin = $appInfo['requiremin']; - } elseif (isset($appInfo['require'])) { - $requireMin = $appInfo['require']; - } - - if (isset($appInfo['dependencies']['nextcloud']['@attributes']['max-version'])) { - $requireMax = $appInfo['dependencies']['nextcloud']['@attributes']['max-version']; - } elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['max-version'])) { - $requireMax = $appInfo['dependencies']['owncloud']['@attributes']['max-version']; - } elseif (isset($appInfo['requiremax'])) { - $requireMax = $appInfo['requiremax']; - } - - if (!empty($requireMin) - && version_compare(self::adjustVersionParts($ocVersion, $requireMin), $requireMin, '<') - ) { - return false; - } - - if (!$ignoreMax && !empty($requireMax) - && version_compare(self::adjustVersionParts($ocVersion, $requireMax), $requireMax, '>') - ) { - return false; - } - - return true; + return Server::get(\OCP\App\IAppManager::class)->isAppCompatible($ocVersion, $appInfo, $ignoreMax); } /** diff --git a/lib/public/App/IAppManager.php b/lib/public/App/IAppManager.php index 788d810ff22..97acd9af7b1 100644 --- a/lib/public/App/IAppManager.php +++ b/lib/public/App/IAppManager.php @@ -349,4 +349,28 @@ interface IAppManager { * @since 32.0.0 */ public function upgradeApp(string $appId): bool; + + /** + * Check whether the installed version is the same as the version from info.xml + * + * @since 32.0.0 + */ + public function isUpgradeRequired(string $appId): bool; + + /** + * Check whether the current Nextcloud version matches the given + * application's version requirements. + * + * The comparison is made based on the number of parts that the + * app info version has. For example for Nextcloud 26.0.3 if the + * app info version is expecting version 26.0, the comparison is + * made on the first two parts of the Nextcloud version. + * This means that it's possible to specify "requiremin" => 26 + * and "requiremax" => 26 and it will still match Nextcloud 26.0.3. + * + * @param string $serverVersion Nextcloud version to check against + * @param array $appInfo app info (from xml) + * @since 32.0.0 + */ + public function isAppCompatible(string $serverVersion, array $appInfo, bool $ignoreMax = false): bool; }