diff options
author | Maxence Lange <maxence@artificial-owl.com> | 2025-07-22 11:43:49 -0100 |
---|---|---|
committer | Maxence Lange <maxence@artificial-owl.com> | 2025-07-23 15:20:30 -0100 |
commit | ab5c2145662e505763197a7c30bc24bf47ca1fbd (patch) | |
tree | f2e4b3a7d3620e6802b8be970818a387ee4c4638 | |
parent | 7268525a8a13807441280376f7ec70b6fcad2845 (diff) | |
download | nextcloud-server-feat/preset/load-apps-on-preset.tar.gz nextcloud-server-feat/preset/load-apps-on-preset.zip |
feat(preset): load apps on preset changefeat/preset/load-apps-on-preset
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
-rw-r--r-- | core/Command/Config/Preset.php | 10 | ||||
-rw-r--r-- | lib/private/AppConfig.php | 19 | ||||
-rw-r--r-- | lib/private/Config/ConfigManager.php | 30 | ||||
-rw-r--r-- | lib/private/Config/PresetManager.php | 124 | ||||
-rw-r--r-- | lib/private/Config/UserConfig.php | 18 |
5 files changed, 147 insertions, 54 deletions
diff --git a/core/Command/Config/Preset.php b/core/Command/Config/Preset.php index 9f1424dcc54..e1edfdd4a5f 100644 --- a/core/Command/Config/Preset.php +++ b/core/Command/Config/Preset.php @@ -9,9 +9,8 @@ declare(strict_types=1); namespace OC\Core\Command\Config; use NCU\Config\Lexicon\Preset as ConfigLexiconPreset; -use OC\Config\ConfigManager; +use OC\Config\PresetManager; use OC\Core\Command\Base; -use OCP\IConfig; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -19,8 +18,7 @@ use Symfony\Component\Console\Output\OutputInterface; class Preset extends Base { public function __construct( - private readonly IConfig $config, - private readonly ConfigManager $configManager, + private readonly PresetManager $presetManager, ) { parent::__construct(); } @@ -49,10 +47,10 @@ class Preset extends Base { return self::INVALID; } - $this->configManager->setLexiconPreset($preset); + $this->presetManager->setLexiconPreset($preset); } - $current = ConfigLexiconPreset::tryFrom($this->config->getSystemValueInt(ConfigManager::PRESET_CONFIGKEY, 0)) ?? ConfigLexiconPreset::NONE; + $current = $this->presetManager->getLexiconPreset(); $this->writeArrayInOutputFormat($input, $output, [$current->name], 'current preset: '); return self::SUCCESS; } diff --git a/lib/private/AppConfig.php b/lib/private/AppConfig.php index f050deba1ca..0ef061abed3 100644 --- a/lib/private/AppConfig.php +++ b/lib/private/AppConfig.php @@ -14,9 +14,9 @@ use JsonException; use NCU\Config\Lexicon\ConfigLexiconEntry; use NCU\Config\Lexicon\ConfigLexiconStrictness; use NCU\Config\Lexicon\IConfigLexicon; -use NCU\Config\Lexicon\Preset; use OC\AppFramework\Bootstrap\Coordinator; use OC\Config\ConfigManager; +use OC\Config\PresetManager; use OCP\DB\Exception as DBException; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Exceptions\AppConfigIncorrectTypeException; @@ -65,13 +65,14 @@ class AppConfig implements IAppConfig { /** @var array<string, array{entries: array<string, ConfigLexiconEntry>, aliases: array<string, string>, strictness: ConfigLexiconStrictness}> ['app_id' => ['strictness' => ConfigLexiconStrictness, 'entries' => ['config_key' => ConfigLexiconEntry[]]] */ private array $configLexiconDetails = []; private bool $ignoreLexiconAliases = false; - private ?Preset $configLexiconPreset = null; /** @var ?array<string, string> */ private ?array $appVersionsCache = null; public function __construct( protected IDBConnection $connection, protected IConfig $config, + private readonly ConfigManager $configManager, + private readonly PresetManager $presetManager, protected LoggerInterface $logger, protected ICrypto $crypto, ) { @@ -519,8 +520,7 @@ class AppConfig implements IAppConfig { // interested to check options in case a modification of the value is needed // ie inverting value from previous key when using lexicon option RENAME_INVERT_BOOLEAN if ($origKey !== $key && $type === self::VALUE_BOOL) { - $configManager = Server::get(ConfigManager::class); - $value = ($configManager->convertToBool($value, $this->getLexiconEntry($app, $key))) ? '1' : '0'; + $value = ($this->configManager->convertToBool($value, $this->getLexiconEntry($app, $key))) ? '1' : '0'; } return $value; @@ -1184,7 +1184,6 @@ class AppConfig implements IAppConfig { public function clearCache(bool $reload = false): void { $this->lazyLoaded = $this->fastLoaded = false; $this->lazyCache = $this->fastCache = $this->valueTypes = $this->configLexiconDetails = []; - $this->configLexiconPreset = null; if (!$reload) { return; @@ -1669,7 +1668,7 @@ class AppConfig implements IAppConfig { $lazy = $configValue->isLazy(); // only look for default if needed, default from Lexicon got priority if ($default !== null) { - $default = $configValue->getDefault($this->getLexiconPreset()) ?? $default; + $default = $configValue->getDefault($this->presetManager->getLexiconPreset()) ?? $default; } if ($configValue->isFlagged(self::FLAG_SENSITIVE)) { @@ -1757,14 +1756,6 @@ class AppConfig implements IAppConfig { $this->ignoreLexiconAliases = $ignore; } - private function getLexiconPreset(): Preset { - if ($this->configLexiconPreset === null) { - $this->configLexiconPreset = Preset::tryFrom($this->config->getSystemValueInt(ConfigManager::PRESET_CONFIGKEY, 0)) ?? Preset::NONE; - } - - return $this->configLexiconPreset; - } - /** * Returns the installed versions of all apps * diff --git a/lib/private/Config/ConfigManager.php b/lib/private/Config/ConfigManager.php index 67466617941..9b1e1afae32 100644 --- a/lib/private/Config/ConfigManager.php +++ b/lib/private/Config/ConfigManager.php @@ -9,15 +9,13 @@ declare(strict_types=1); namespace OC\Config; use JsonException; -use NCU\Config\Exceptions\TypeConflictException; -use NCU\Config\IUserConfig; -use NCU\Config\Lexicon\ConfigLexiconEntry; -use NCU\Config\Lexicon\Preset; use NCU\Config\ValueType; use OC\AppConfig; use OCP\App\IAppManager; +use NCU\Config\Exceptions\TypeConflictException; +use NCU\Config\IUserConfig; +use NCU\Config\Lexicon\ConfigLexiconEntry; use OCP\IAppConfig; -use OCP\IConfig; use OCP\Server; use Psr\Log\LoggerInterface; @@ -27,20 +25,23 @@ use Psr\Log\LoggerInterface; * @since 32.0.0 */ class ConfigManager { - /** @since 32.0.0 */ - public const PRESET_CONFIGKEY = 'config_preset'; - /** @var AppConfig|null $appConfig */ private ?IAppConfig $appConfig = null; /** @var UserConfig|null $userConfig */ private ?IUserConfig $userConfig = null; public function __construct( - private readonly IConfig $config, private readonly LoggerInterface $logger, ) { } + public function clearConfigCaches(): void { + $this->loadConfigServices(); + $this->appConfig->clearCache(); + $this->userConfig->clearCacheAll(); + } + + /** * Use the rename values from the list of ConfigLexiconEntry defined in each app ConfigLexicon * to migrate config value to a new config key. @@ -81,17 +82,6 @@ class ConfigManager { } /** - * store in config.php the new preset - * refresh cached preset - */ - public function setLexiconPreset(Preset $preset): void { - $this->config->setSystemValue(self::PRESET_CONFIGKEY, $preset->value); - $this->loadConfigServices(); - $this->appConfig->clearCache(); - $this->userConfig->clearCacheAll(); - } - - /** * config services cannot be load at __construct() or install will fail */ private function loadConfigServices(): void { diff --git a/lib/private/Config/PresetManager.php b/lib/private/Config/PresetManager.php new file mode 100644 index 00000000000..88eb2314e6a --- /dev/null +++ b/lib/private/Config/PresetManager.php @@ -0,0 +1,124 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OC\Config; + +use NCU\Config\Lexicon\Preset; +use OC\App\AppManager; +use OC\Core\Command\App\Install; +use OC\Installer; +use OCP\App\AppPathNotFoundException; +use OCP\App\IAppManager; +use OCP\IConfig; +use Psr\Log\LoggerInterface; + +/** + * tools to maintains configurations + * + * @since 32.0.0 + */ +class PresetManager { + private const PRESET_CONFIGKEY = 'config_preset'; + + private ?AppManager $appManager = null; + private ?Installer $installer = null; + + private ?Preset $configLexiconPreset = null; + + public function __construct( + private readonly IConfig $config, + private readonly ConfigManager $configManager, + private readonly LoggerInterface $logger, + ) { + } + + /** + * store in config.php the new preset + * refresh cached preset + */ + public function setLexiconPreset(Preset $preset): void { + $this->config->setSystemValue(self::PRESET_CONFIGKEY, $preset->value); + $this->configLexiconPreset = $preset; + $this->configManager->clearConfigCaches(); + $this->refreshPresetApps(); + } + + public function getLexiconPreset(): Preset { + if ($this->configLexiconPreset === null) { + $this->configLexiconPreset = Preset::tryFrom($this->config->getSystemValueInt(self::PRESET_CONFIGKEY, 0)) ?? Preset::NONE; + } + + return $this->configLexiconPreset; + } + + public function refreshPresetApps(): void { + $this->loadAppManager(); + + $apps = $this->getPresetApps($this->getLexiconPreset()); + foreach ($apps['disabled'] ?? [] as $app) { + try { + $this->appManager->disableApp($app); + } catch (\Exception $e) { + $this->logger->warning('could not disable app', ['exception' => $e]); + } + } + + foreach ($apps['enabled'] ?? [] as $app) { + $this->installApp($app); + } + } + + private function loadAppManager(): void { + if ($this->appManager === null) { + $this->appManager = \OCP\Server::get(IAppManager::class); + } + if ($this->installer === null) { + $this->installer = \OCP\Server::get(Installer::class); + } + } + + private function installApp(string $appId): void { + $this->loadAppManager(); + if (!$this->installer->isDownloaded($appId)) { + try { + $this->installer->downloadApp($appId); + } catch (\Exception $e) { + $this->logger->warning('could not download app', ['appId' => $appId, 'exception' => $e]); + return; + } + } + + try { + $this->installer->installApp($appId, true); + } catch (\Exception $e) { + $this->logger->warning('could not install app', ['appId' => $appId, 'exception' => $e]); + return; + } + + try { + $this->appManager->enableApp($appId); + } catch (AppPathNotFoundException $e) { + $this->logger->warning('could not enable app', ['appId' => $appId, 'exception' => $e]); + return; + } + } + + /** + * get listing of enabled/disabled app from Preset + * + * @return array{enabled: list<string>, disabled: list<string>} + */ + private function getPresetApps(Preset $preset): array { + return match ($preset) { + Preset::LARGE => ['enabled' => ['globalsiteselector', 'intros'], 'disabled' => []], + Preset::CLUB, Preset::FAMILY, Preset::EDUCATION, Preset::SMALL, Preset::MEDIUM => ['enabled' => ['intros'], 'disabled' => []], + Preset::SHARED => ['enabled' => ['intros', 'external'], 'disabled' => []], + default => ['enabled' => [], 'disabled' => ['intros']], + }; + } +} diff --git a/lib/private/Config/UserConfig.php b/lib/private/Config/UserConfig.php index fb0bf954f57..35fdded7fd1 100644 --- a/lib/private/Config/UserConfig.php +++ b/lib/private/Config/UserConfig.php @@ -17,7 +17,6 @@ use NCU\Config\Exceptions\UnknownKeyException; use NCU\Config\IUserConfig; use NCU\Config\Lexicon\ConfigLexiconEntry; use NCU\Config\Lexicon\ConfigLexiconStrictness; -use NCU\Config\Lexicon\Preset; use NCU\Config\ValueType; use OC\AppFramework\Bootstrap\Coordinator; use OCP\DB\Exception as DBException; @@ -67,11 +66,12 @@ class UserConfig implements IUserConfig { /** @var array<string, array{entries: array<string, ConfigLexiconEntry>, aliases: array<string, string>, strictness: ConfigLexiconStrictness}> ['app_id' => ['strictness' => ConfigLexiconStrictness, 'entries' => ['config_key' => ConfigLexiconEntry[]]] */ private array $configLexiconDetails = []; private bool $ignoreLexiconAliases = false; - private ?Preset $configLexiconPreset = null; public function __construct( protected IDBConnection $connection, protected IConfig $config, + private readonly ConfigManager $configManager, + private readonly ConfigManager $presetManager, protected LoggerInterface $logger, protected ICrypto $crypto, ) { @@ -771,8 +771,7 @@ class UserConfig implements IUserConfig { // interested to check options in case a modification of the value is needed // ie inverting value from previous key when using lexicon option RENAME_INVERT_BOOLEAN if ($origKey !== $key && $type === ValueType::BOOL) { - $configManager = Server::get(ConfigManager::class); - $value = ($configManager->convertToBool($value, $this->getLexiconEntry($app, $key))) ? '1' : '0'; + $value = ($this->configManager->convertToBool($value, $this->getLexiconEntry($app, $key))) ? '1' : '0'; } return $value; @@ -1635,7 +1634,6 @@ class UserConfig implements IUserConfig { public function clearCacheAll(): void { $this->lazyLoaded = $this->fastLoaded = []; $this->lazyCache = $this->fastCache = $this->valueDetails = $this->configLexiconDetails = []; - $this->configLexiconPreset = null; } /** @@ -1936,7 +1934,7 @@ class UserConfig implements IUserConfig { // only look for default if needed, default from Lexicon got priority if not overwritten by admin if ($default !== null) { - $default = $this->getSystemDefault($app, $configValue) ?? $configValue->getDefault($this->getLexiconPreset()) ?? $default; + $default = $this->getSystemDefault($app, $configValue) ?? $configValue->getDefault($this->presetManager->getLexiconPreset()) ?? $default; } // returning false will make get() returning $default and set() not changing value in database @@ -2037,12 +2035,4 @@ class UserConfig implements IUserConfig { public function ignoreLexiconAliases(bool $ignore): void { $this->ignoreLexiconAliases = $ignore; } - - private function getLexiconPreset(): Preset { - if ($this->configLexiconPreset === null) { - $this->configLexiconPreset = Preset::tryFrom($this->config->getSystemValueInt(ConfigManager::PRESET_CONFIGKEY, 0)) ?? Preset::NONE; - } - - return $this->configLexiconPreset; - } } |