feat(preset): load apps on new preset

Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
pull/54058/head
Maxence Lange 2025-07-30 10:55:32 +07:00
parent 06aa7035db
commit 9c7ed07571
2 changed files with 90 additions and 1 deletions

@ -8,20 +8,30 @@ declare(strict_types=1);
namespace OC\Config; namespace OC\Config;
use OC\App\AppManager;
use OC\Installer;
use OCP\App\AppPathNotFoundException;
use OCP\App\IAppManager;
use OCP\Config\Lexicon\Preset; use OCP\Config\Lexicon\Preset;
use OCP\IConfig; use OCP\IConfig;
use OCP\Server;
use Psr\Log\LoggerInterface;
/** /**
* tools to maintains configurations * tools to manage the Preset feature
*/ */
class PresetManager { class PresetManager {
private const PRESET_CONFIGKEY = 'config_preset'; private const PRESET_CONFIGKEY = 'config_preset';
private ?AppManager $appManager = null;
private ?Installer $installer = null;
private ?Preset $configLexiconPreset = null; private ?Preset $configLexiconPreset = null;
public function __construct( public function __construct(
private readonly IConfig $config, private readonly IConfig $config,
private readonly ConfigManager $configManager, private readonly ConfigManager $configManager,
private readonly LoggerInterface $logger,
) { ) {
} }
@ -33,6 +43,7 @@ class PresetManager {
$this->config->setSystemValue(self::PRESET_CONFIGKEY, $preset->value); $this->config->setSystemValue(self::PRESET_CONFIGKEY, $preset->value);
$this->configLexiconPreset = $preset; $this->configLexiconPreset = $preset;
$this->configManager->clearConfigCaches(); $this->configManager->clearConfigCaches();
$this->refreshPresetApps();
} }
/** /**
@ -45,4 +56,79 @@ class PresetManager {
return $this->configLexiconPreset; return $this->configLexiconPreset;
} }
/**
* Enable and/or Disable a list of apps based on the currently selected Preset
*/
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);
}
}
/**
* some parts cannot be initiated at __construct() time
*/
private function loadAppManager(): void {
if ($this->appManager === null) {
$this->appManager = Server::get(IAppManager::class);
}
if ($this->installer === null) {
$this->installer = Server::get(Installer::class);
}
}
/**
* download, install and enable app.
* generate warning entry in logs in case of failure.
*/
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::CLUB, Preset::FAMILY, Preset::SCHOOL, Preset::UNIVERSITY, Preset::SMALL, Preset::MEDIUM, Preset::LARGE => ['enabled' => ['user_status', 'intros', 'guests'], 'disabled' => []],
Preset::SHARED => ['enabled' => ['intros', 'external'], 'disabled' => ['user_status']],
default => ['enabled' => [], 'disabled' => []],
};
}
} }

@ -11,6 +11,7 @@ use OC\AppConfig;
use OC\AppFramework\Bootstrap\Coordinator; use OC\AppFramework\Bootstrap\Coordinator;
use OC\Config\ConfigManager; use OC\Config\ConfigManager;
use OC\Config\PresetManager; use OC\Config\PresetManager;
use OCP\App\IAppManager;
use OCP\Config\Exceptions\TypeConflictException; use OCP\Config\Exceptions\TypeConflictException;
use OCP\Config\Exceptions\UnknownKeyException; use OCP\Config\Exceptions\UnknownKeyException;
use OCP\Config\IUserConfig; use OCP\Config\IUserConfig;
@ -34,6 +35,7 @@ class LexiconTest extends TestCase {
private IUserConfig $userConfig; private IUserConfig $userConfig;
private ConfigManager $configManager; private ConfigManager $configManager;
private PresetManager $presetManager; private PresetManager $presetManager;
private IAppManager $appManager;
protected function setUp(): void { protected function setUp(): void {
parent::setUp(); parent::setUp();
@ -48,6 +50,7 @@ class LexiconTest extends TestCase {
$this->userConfig = Server::get(IUserConfig::class); $this->userConfig = Server::get(IUserConfig::class);
$this->configManager = Server::get(ConfigManager::class); $this->configManager = Server::get(ConfigManager::class);
$this->presetManager = Server::get(PresetManager::class); $this->presetManager = Server::get(PresetManager::class);
$this->appManager = Server::get(IAppManager::class);
} }
protected function tearDown(): void { protected function tearDown(): void {