diff --git a/apps/settings/lib/Controller/AppSettingsController.php b/apps/settings/lib/Controller/AppSettingsController.php
index a27de4e96730a..f8f35760e94a3 100644
--- a/apps/settings/lib/Controller/AppSettingsController.php
+++ b/apps/settings/lib/Controller/AppSettingsController.php
@@ -581,7 +581,11 @@ public function uninstallApp(string $appId): JSONResponse {
$appId = $this->appManager->cleanAppId($appId);
$result = $this->installer->removeApp($appId);
if ($result !== false) {
- $this->appManager->clearAppsCache();
+ /** @var \OC\App\AppManager $appManager */
+ $appManager = $this->appManager;
+ // If this app was force enabled, remove the force-enabled-state
+ $appManager->removeOverwriteNextcloudRequirement($appId);
+ $appManager->clearAppsCache();
return new JSONResponse(['data' => ['appid' => $appId]]);
}
return new JSONResponse(['data' => ['message' => $this->l10n->t('Could not remove app.')]], Http::STATUS_INTERNAL_SERVER_ERROR);
@@ -619,8 +623,11 @@ private function sortApps($a, $b) {
}
public function force(string $appId): JSONResponse {
- $appId = $this->appManager->cleanAppId($appId);
- $this->appManager->ignoreNextcloudRequirementForApp($appId);
+ /** @var \OC\App\AppManager $appManager */
+ $appManager = $this->appManager;
+
+ $appId = $appManager->cleanAppId($appId);
+ $appManager->overwriteNextcloudRequirement($appId);
return new JSONResponse();
}
}
diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml
index 824431c46a522..06f99aaa0218a 100644
--- a/build/psalm-baseline.xml
+++ b/build/psalm-baseline.xml
@@ -1029,6 +1029,7 @@
+
diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php
index 2b6d2a2700bc4..b2836bd504297 100644
--- a/lib/private/App/AppManager.php
+++ b/lib/private/App/AppManager.php
@@ -200,10 +200,6 @@ public function getEnabledAppsForUser(IUser $user) {
return array_keys($appsForUser);
}
- /**
- * @param IGroup $group
- * @return array
- */
public function getEnabledAppsForGroup(IGroup $group): array {
$apps = $this->getInstalledAppsValues();
$appsForGroups = array_filter($apps, function ($enabled) use ($group) {
@@ -304,10 +300,6 @@ public function getAutoDisabledApps(): array {
return $this->autoDisabledApps;
}
- /**
- * @param string $appId
- * @return array
- */
public function getAppRestriction(string $appId): array {
$values = $this->getInstalledAppsValues();
@@ -321,7 +313,6 @@ public function getAppRestriction(string $appId): array {
return json_decode($values[$appId], true);
}
-
/**
* Check if an app is enabled for user
*
@@ -410,12 +401,25 @@ public function isInstalled($appId) {
return isset($installedApps[$appId]);
}
- public function ignoreNextcloudRequirementForApp(string $appId): void {
+ /**
+ * Overwrite the `max-version` requirement for this app.
+ */
+ public function overwriteNextcloudRequirement(string $appId): void {
$ignoreMaxApps = $this->config->getSystemValue('app_install_overwrite', []);
if (!in_array($appId, $ignoreMaxApps, true)) {
$ignoreMaxApps[] = $appId;
- $this->config->setSystemValue('app_install_overwrite', $ignoreMaxApps);
}
+ $this->config->setSystemValue('app_install_overwrite', $ignoreMaxApps);
+ }
+
+ /**
+ * Remove the `max-version` overwrite for this app.
+ * This means this app now again can not be enabled if the `max-version` is smaller than the current Nextcloud version.
+ */
+ public function removeOverwriteNextcloudRequirement(string $appId): void {
+ $ignoreMaxApps = $this->config->getSystemValue('app_install_overwrite', []);
+ $ignoreMaxApps = array_filter($ignoreMaxApps, fn (string $id) => $id !== $appId);
+ $this->config->setSystemValue('app_install_overwrite', $ignoreMaxApps);
}
public function loadApp(string $app): void {
@@ -646,7 +650,7 @@ public function enableAppForGroups(string $appId, array $groups, bool $forceEnab
* @param bool $automaticDisabled
* @throws \Exception if app can't be disabled
*/
- public function disableApp($appId, $automaticDisabled = false) {
+ public function disableApp($appId, $automaticDisabled = false): void {
if ($this->isAlwaysEnabled($appId)) {
throw new \Exception("$appId can't be disabled.");
}
@@ -706,7 +710,7 @@ public function getAppWebPath(string $appId): string {
/**
* Clear the cached list of apps when enabling/disabling an app
*/
- public function clearAppsCache() {
+ public function clearAppsCache(): void {
$this->appInfos = [];
}
diff --git a/lib/public/App/IAppManager.php b/lib/public/App/IAppManager.php
index 0af7cdfc49530..110bcacf396be 100644
--- a/lib/public/App/IAppManager.php
+++ b/lib/public/App/IAppManager.php
@@ -144,7 +144,7 @@ public function enableAppForGroups(string $appId, array $groups, bool $forceEnab
* @param bool $automaticDisabled
* @since 8.0.0
*/
- public function disableApp($appId, $automaticDisabled = false);
+ public function disableApp($appId, $automaticDisabled = false): void;
/**
* Get the directory for the given app.
@@ -185,7 +185,7 @@ public function getInstalledApps();
* Clear the cached list of apps when enabling/disabling an app
* @since 8.1.0
*/
- public function clearAppsCache();
+ public function clearAppsCache(): void;
/**
* @param string $appId
@@ -201,7 +201,7 @@ public function isShipped($appId);
* @return bool
*
* This function walks through the Nextcloud directory and loads all apps
- * it can find. A directory contains an app if the file /appinfo/info.xml
+ * it can find. A directory contains an app if the file `/appinfo/info.xml`
* exists.
*
* if $types is set to non-empty array, only apps of those types will be loaded
@@ -271,7 +271,7 @@ public function getDefaultApps(): array;
/**
* Set the global default apps with fallbacks
*
- * @param string[] $appId
+ * @param string[] $defaultApps
* @throws \InvalidArgumentException If any of the apps is not installed
* @since 28.0.0
* @deprecated 31.0.0