diff --git a/lib/Controller/AdminController.php b/lib/Controller/AdminController.php index f1e0bdf9b..ccaab81bf 100644 --- a/lib/Controller/AdminController.php +++ b/lib/Controller/AdminController.php @@ -26,6 +26,7 @@ use OCA\Memories\AppInfo\Application; use OCA\Memories\Exceptions; use OCA\Memories\Service\BinExt; +use OCA\Memories\Settings\SystemConfig; use OCA\Memories\Util; use OCP\AppFramework\Http; use OCP\AppFramework\Http\JSONResponse; @@ -39,7 +40,7 @@ public function getSystemConfig(): Http\Response { return Util::guardEx(function () { $config = []; - foreach (Util::systemConfigDefaults() as $key => $default) { + foreach (SystemConfig::DEFAULTS as $key => $default) { $config[$key] = $this->config->getSystemValue($key, $default); } @@ -59,7 +60,7 @@ public function setSystemConfig(string $key, mixed $value): Http\Response } // Assign config with type checking - Util::setSystemConfig($key, $value); + SystemConfig::set($key, $value); // If changing vod settings, kill any running go-vod instances if (str_starts_with($key, 'memories.vod.')) { @@ -89,7 +90,7 @@ public function getSystemStatus(): Http\Response $status = []; // Check exiftool version - $exiftoolNoLocal = Util::getSystemConfig('memories.exiftool_no_local'); + $exiftoolNoLocal = SystemConfig::get('memories.exiftool_no_local'); $status['exiftool'] = $this->getExecutableStatus( static fn () => BinExt::getExiftoolPBin(), static fn () => BinExt::testExiftool(), @@ -136,23 +137,23 @@ public function getSystemStatus(): Http\Response // Check for FFmpeg for preview generation /** @psalm-suppress ForbiddenCode */ $status['ffmpeg_preview'] = $this->getExecutableStatus( - Util::getSystemConfig('preview_ffmpeg_path') + SystemConfig::get('preview_ffmpeg_path') ?: trim(shell_exec('which ffmpeg') ?: ''), static fn ($p) => BinExt::testFFmpeg($p, 'ffmpeg'), ); // Check ffmpeg and ffprobe binaries for transcoding $status['ffmpeg'] = $this->getExecutableStatus( - Util::getSystemConfig('memories.vod.ffmpeg'), + SystemConfig::get('memories.vod.ffmpeg'), static fn ($p) => BinExt::testFFmpeg($p, 'ffmpeg'), ); $status['ffprobe'] = $this->getExecutableStatus( - Util::getSystemConfig('memories.vod.ffprobe'), + SystemConfig::get('memories.vod.ffprobe'), static fn ($p) => BinExt::testFFmpeg($p, 'ffprobe'), ); // Check go-vod binary - $extGoVod = Util::getSystemConfig('memories.vod.external'); + $extGoVod = SystemConfig::get('memories.vod.external'); $status['govod'] = $this->getExecutableStatus( static fn () => BinExt::getGoVodBin(), static fn () => BinExt::testStartGoVod(), diff --git a/lib/Controller/OtherController.php b/lib/Controller/OtherController.php index 2c662f4a2..93522ab72 100644 --- a/lib/Controller/OtherController.php +++ b/lib/Controller/OtherController.php @@ -25,6 +25,7 @@ use OCA\Memories\AppInfo\Application; use OCA\Memories\Exceptions; +use OCA\Memories\Settings\SystemConfig; use OCA\Memories\Util; use OCP\AppFramework\Http; use OCP\AppFramework\Http\JSONResponse; @@ -85,9 +86,9 @@ public function getUserConfig(): Http\Response return new JSONResponse([ // general stuff 'version' => $version, - 'vod_disable' => Util::getSystemConfig('memories.vod.disable'), - 'video_default_quality' => Util::getSystemConfig('memories.video_default_quality'), - 'places_gis' => Util::getSystemConfig('memories.gis_type'), + 'vod_disable' => SystemConfig::get('memories.vod.disable'), + 'video_default_quality' => SystemConfig::get('memories.video_default_quality'), + 'places_gis' => SystemConfig::get('memories.gis_type'), // enabled apps 'systemtags_enabled' => Util::tagsIsEnabled(), @@ -99,11 +100,11 @@ public function getUserConfig(): Http\Response 'preview_generator_enabled' => Util::previewGeneratorIsEnabled(), // general settings - 'timeline_path' => $getAppConfig('timelinePath', Util::getSystemConfig('memories.timeline.default_path')), + 'timeline_path' => $getAppConfig('timelinePath', SystemConfig::get('memories.timeline.default_path')), 'enable_top_memories' => 'true' === $getAppConfig('enableTopMemories', 'true'), // viewer settings - 'high_res_cond_default' => Util::getSystemConfig('memories.viewer.high_res_cond_default'), + 'high_res_cond_default' => SystemConfig::get('memories.viewer.high_res_cond_default'), 'livephoto_autoplay' => 'true' === $getAppConfig('livephotoAutoplay', 'true'), 'sidebar_filepath' => 'true' === $getAppConfig('sidebarFilepath', false), diff --git a/lib/Cron/IndexJob.php b/lib/Cron/IndexJob.php index c0658e8a1..c059e7d82 100644 --- a/lib/Cron/IndexJob.php +++ b/lib/Cron/IndexJob.php @@ -6,7 +6,7 @@ use OCA\Memories\AppInfo\Application; use OCA\Memories\Service; -use OCA\Memories\Util; +use OCA\Memories\Settings\SystemConfig; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\TimedJob; use OCP\IConfig; @@ -38,7 +38,7 @@ public function __construct( protected function run(mixed $argument): void { // Check if indexing is enabled - if ('0' === Util::getSystemConfig('memories.index.mode')) { + if ('0' === SystemConfig::get('memories.index.mode')) { return; } diff --git a/lib/Service/BinExt.php b/lib/Service/BinExt.php index 9b491f275..82dd0f4fe 100644 --- a/lib/Service/BinExt.php +++ b/lib/Service/BinExt.php @@ -4,7 +4,7 @@ namespace OCA\Memories\Service; -use OCA\Memories\Util; +use OCA\Memories\Settings\SystemConfig; class BinExt { @@ -15,7 +15,7 @@ class BinExt /** Get the path to the temp directory */ public static function getTmpPath(): string { - return Util::getSystemConfig('memories.exiftool.tmp') ?: sys_get_temp_dir(); + return SystemConfig::get('memories.exiftool.tmp') ?: sys_get_temp_dir(); } /** Copy a binary to temp dir for execution */ @@ -56,7 +56,7 @@ public static function getTempBin(string $path, string $name, bool $copy = true) /** Get the name for a binary */ public static function getName(string $name, string $version = ''): string { - $id = Util::getInstanceId(); + $id = SystemConfig::get('instanceid'); return empty($version) ? "{$name}-{$id}" : "{$name}-{$id}-{$version}"; } @@ -105,7 +105,7 @@ public static function testExiftool(): string /** Get path to exiftool binary */ public static function getExiftoolPBin(): string { - $path = Util::getSystemConfig('memories.exiftool'); + $path = SystemConfig::get('memories.exiftool'); return self::getTempBin($path, self::getName('exiftool', self::EXIFTOOL_VER)); } @@ -117,7 +117,7 @@ public static function getExiftoolPBin(): string */ public static function getExiftool(): array { - if (Util::getSystemConfig('memories.exiftool_no_local')) { + if (SystemConfig::get('memories.exiftool_no_local')) { return ['perl', realpath(__DIR__.'/../../bin-ext/exiftool/exiftool')]; } @@ -129,11 +129,11 @@ public static function getExiftool(): array */ public static function detectExiftool(): false|string { - if (!empty($path = Util::getSystemConfig('memories.exiftool')) && file_exists($path)) { + if (!empty($path = SystemConfig::get('memories.exiftool')) && file_exists($path)) { return $path; } - if (Util::getSystemConfig('memories.exiftool_no_local')) { + if (SystemConfig::get('memories.exiftool_no_local')) { return implode(' ', self::getExiftool()); } @@ -148,13 +148,13 @@ public static function detectExiftool(): false|string // make sure it exists if ($path && file_exists($path)) { - Util::setSystemConfig('memories.exiftool', $path); + SystemConfig::set('memories.exiftool', $path); return $path; } } - Util::setSystemConfig('memories.exiftool_no_local', true); + SystemConfig::set('memories.exiftool_no_local', true); return false; } @@ -166,8 +166,8 @@ public static function getGoVodUrl(string $client, string $path, string $profile { $path = rawurlencode($path); - $bind = Util::getSystemConfig('memories.vod.bind'); - $connect = Util::getSystemConfig('memories.vod.connect', $bind); + $bind = SystemConfig::get('memories.vod.bind'); + $connect = SystemConfig::get('memories.vod.connect', $bind); return "http://{$connect}/{$client}{$path}/{$profile}"; } @@ -176,15 +176,15 @@ public static function getGoVodConfig(bool $local = false): array { // Get config from system values $env = [ - 'vaapi' => Util::getSystemConfig('memories.vod.vaapi'), - 'vaapiLowPower' => Util::getSystemConfig('memories.vod.vaapi.low_power'), + 'vaapi' => SystemConfig::get('memories.vod.vaapi'), + 'vaapiLowPower' => SystemConfig::get('memories.vod.vaapi.low_power'), - 'nvenc' => Util::getSystemConfig('memories.vod.nvenc'), - 'nvencTemporalAQ' => Util::getSystemConfig('memories.vod.nvenc.temporal_aq'), - 'nvencScale' => Util::getSystemConfig('memories.vod.nvenc.scale'), + 'nvenc' => SystemConfig::get('memories.vod.nvenc'), + 'nvencTemporalAQ' => SystemConfig::get('memories.vod.nvenc.temporal_aq'), + 'nvencScale' => SystemConfig::get('memories.vod.nvenc.scale'), - 'useTranspose' => Util::getSystemConfig('memories.vod.use_transpose'), - 'useGopSize' => Util::getSystemConfig('memories.vod.use_gop_size'), + 'useTranspose' => SystemConfig::get('memories.vod.use_transpose'), + 'useGopSize' => SystemConfig::get('memories.vod.use_gop_size'), ]; if (!$local) { @@ -192,7 +192,7 @@ public static function getGoVodConfig(bool $local = false): array } // Get temp directory - $tmpPath = Util::getSystemConfig('memories.vod.tempdir', sys_get_temp_dir().'/go-vod/'); + $tmpPath = SystemConfig::get('memories.vod.tempdir', sys_get_temp_dir().'/go-vod/'); // Make sure path ends with slash if ('/' !== substr($tmpPath, -1)) { @@ -200,12 +200,12 @@ public static function getGoVodConfig(bool $local = false): array } // Add instance ID to path - $tmpPath .= Util::getInstanceId(); + $tmpPath .= SystemConfig::get('instanceid'); return array_merge($env, [ - 'bind' => Util::getSystemConfig('memories.vod.bind'), - 'ffmpeg' => Util::getSystemConfig('memories.vod.ffmpeg'), - 'ffprobe' => Util::getSystemConfig('memories.vod.ffprobe'), + 'bind' => SystemConfig::get('memories.vod.bind'), + 'ffmpeg' => SystemConfig::get('memories.vod.ffmpeg'), + 'ffprobe' => SystemConfig::get('memories.vod.ffprobe'), 'tempdir' => $tmpPath, ]); } @@ -215,7 +215,7 @@ public static function getGoVodConfig(bool $local = false): array */ public static function getGoVodBin(): string { - $path = Util::getSystemConfig('memories.vod.path'); + $path = SystemConfig::get('memories.vod.path'); return self::getTempBin($path, self::getName('go-vod', self::GOVOD_VER)); } @@ -227,7 +227,7 @@ public static function getGoVodBin(): string public static function startGoVod(): ?string { // Check if disabled - if (Util::getSystemConfig('memories.vod.disable')) { + if (SystemConfig::get('memories.vod.disable')) { // Make sure it's dead, in case the user just disabled it self::pkill(self::getName('go-vod')); @@ -235,7 +235,7 @@ public static function startGoVod(): ?string } // Check if external - if (Util::getSystemConfig('memories.vod.external')) { + if (SystemConfig::get('memories.vod.external')) { self::configureGoVod(); return null; @@ -306,7 +306,7 @@ public static function testStartGoVod(): string public static function testGoVod(): string { // Check if disabled - if (Util::getSystemConfig('memories.vod.disable')) { + if (SystemConfig::get('memories.vod.disable')) { throw new \Exception('Transcoding is disabled'); } @@ -372,7 +372,7 @@ public static function configureGoVod(): bool */ public static function detectGoVod(): false|string { - $goVodPath = Util::getSystemConfig('memories.vod.path'); + $goVodPath = SystemConfig::get('memories.vod.path'); if (empty($goVodPath) || !file_exists($goVodPath)) { // Detect architecture @@ -385,7 +385,7 @@ public static function detectGoVod(): false|string } // Set config - Util::setSystemConfig('memories.vod.path', $goVodPath); + SystemConfig::set('memories.vod.path', $goVodPath); // Make executable if (!is_executable($goVodPath)) { @@ -398,8 +398,8 @@ public static function detectGoVod(): false|string public static function detectFFmpeg(): ?string { - $ffmpegPath = Util::getSystemConfig('memories.vod.ffmpeg'); - $ffprobePath = Util::getSystemConfig('memories.vod.ffprobe'); + $ffmpegPath = SystemConfig::get('memories.vod.ffmpeg'); + $ffprobePath = SystemConfig::get('memories.vod.ffprobe'); if (empty($ffmpegPath) || !file_exists($ffmpegPath) || empty($ffprobePath) || !file_exists($ffprobePath)) { // Use PATH environment variable to find ffmpeg @@ -418,8 +418,8 @@ public static function detectFFmpeg(): ?string $ffprobePath = trim($ffprobePath); // Set config - Util::setSystemConfig('memories.vod.ffmpeg', $ffmpegPath); - Util::setSystemConfig('memories.vod.ffprobe', $ffprobePath); + SystemConfig::set('memories.vod.ffmpeg', $ffmpegPath); + SystemConfig::set('memories.vod.ffprobe', $ffprobePath); } // Check if executable diff --git a/lib/Service/Index.php b/lib/Service/Index.php index a5d3a60bc..91d480f5e 100644 --- a/lib/Service/Index.php +++ b/lib/Service/Index.php @@ -25,6 +25,7 @@ use OCA\Memories\AppInfo\Application; use OCA\Memories\Db\TimelineWrite; +use OCA\Memories\Settings\SystemConfig; use OCA\Memories\Util; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Files\File; @@ -76,7 +77,7 @@ public function indexUser(string $uid, ?string $folder = null): void $root = $this->rootFolder->getUserFolder($uid); // Get paths of folders to index - $mode = Util::getSystemConfig('memories.index.mode'); + $mode = SystemConfig::get('memories.index.mode'); if (null !== $folder) { $paths = [$folder]; } elseif ('1' === $mode || '0' === $mode) { // everything (or nothing) @@ -84,7 +85,7 @@ public function indexUser(string $uid, ?string $folder = null): void } elseif ('2' === $mode) { // timeline $paths = Util::getTimelinePaths($uid); } elseif ('3' === $mode) { // custom - $paths = [Util::getSystemConfig('memories.index.path')]; + $paths = [SystemConfig::get('memories.index.path')]; } else { throw new \Exception('Invalid index mode'); } diff --git a/lib/Settings/SystemConfig.php b/lib/Settings/SystemConfig.php new file mode 100644 index 000000000..8d364f439 --- /dev/null +++ b/lib/Settings/SystemConfig.php @@ -0,0 +1,159 @@ + '', + + // Do not use packaged binaries of exiftool + // This requires perl to be available + 'memories.exiftool_no_local' => false, + + // Temporary directory for non-php binaries. The directory must be writable + // and the webserver user should be able to create executable binaries in it. + // Note that go-vod temp files are separately configured (see memories.vod.tempdir) + // Defaults to system temp directory if blank + 'memories.exiftool.tmp' => '', + + // How to index user directories + // 0 = auto-index disabled + // 1 = index everything + // 2 = index only user timelines + // 3 = index only configured path + 'memories.index.mode' => '1', + + // Path to index (only used if indexing mode is 3) + 'memories.index.path' => '/', + + // Places database type identifier + 'memories.gis_type' => -1, + + // Default timeline path for all users + // If set to '_empty_', the user is prompted to select a path on first open (default) + 'memories.timeline.default_path' => '_empty_', + + // Default viewer high resolution image loading condition + // Valid values: 'always' | 'zoom' | 'never' + 'memories.viewer.high_res_cond_default' => 'zoom', + + // Disable transcoding + 'memories.vod.disable' => true, + + // VA-API configuration options + 'memories.vod.vaapi' => false, // Transcode with VA-API + 'memories.vod.vaapi.low_power' => false, // Use low_power mode for VA-API + + // NVENC configuration options + 'memories.vod.nvenc' => false, // Transcode with NVIDIA NVENC + 'memories.vod.nvenc.temporal_aq' => false, + 'memories.vod.nvenc.scale' => 'npp', // npp or cuda + + // Extra streaming configuration + 'memories.vod.use_transpose' => false, + 'memories.vod.use_gop_size' => false, + + // Paths to ffmpeg and ffprobe binaries + 'memories.vod.ffmpeg' => '', + 'memories.vod.ffprobe' => '', + + // Path to go-vod binary + 'memories.vod.path' => '', + + // Path to use for transcoded files (/tmp/go-vod/instanceid) + // Make sure this has plenty of space + 'memories.vod.tempdir' => '', + + // Bind address to use when starting the transcoding server + 'memories.vod.bind' => '127.0.0.1:47788', + + // Address used to connect to the transcoding server + // If not specified, the bind address above will be used + 'memories.vod.connect' => '127.0.0.1:47788', + + // Mark go-vod as external. If true, Memories will not attempt to + // start go-vod if it is not running already. + 'memories.vod.external' => false, + + // Set the default video quality for a first time user + // 0 => Auto (default) + // -1 => Original (max quality with transcoding) + // -2 => Direct (disable transcoding) + // 1080 => 1080p (and so on) + 'memories.video_default_quality' => '0', + + // Memories only provides an admin interface for these + // https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/config_sample_php_parameters.html#previews + 'enabledPreviewProviders' => [], + 'preview_max_x' => 4096, + 'preview_max_y' => 4096, + 'preview_max_memory' => 128, + 'preview_max_filesize_image' => 50, + 'preview_ffmpeg_path' => '', + + // Placeholders only; these are not touched by the app + 'instanceid' => 'default', + ]; + + /** + * Get a system config key with the correct default. + * + * @param string $key System config key + * @param mixed $default Default value + */ + public static function get(string $key, mixed $default = null): mixed + { + if (!\array_key_exists($key, self::DEFAULTS)) { + throw new \InvalidArgumentException("Invalid system config key: {$key}"); + } + + return \OC::$server->get(\OCP\IConfig::class) + ->getSystemValue($key, $default ?? self::DEFAULTS[$key]) + ; + } + + /** + * Set a system config key. + * + * @param string $key System config key + * @param mixed $value Value to set + * + * @throws \InvalidArgumentException + */ + public static function set(string $key, mixed $value): void + { + // Check if the key is valid + if (!\array_key_exists($key, self::DEFAULTS)) { + throw new \InvalidArgumentException("Invalid system config key: {$key}"); + } + + // Key belongs to memories namespace + $isAppKey = str_starts_with($key, Application::APPNAME.'.'); + + // Check if the value has the correct type + if (null !== $value && \gettype($value) !== \gettype(self::DEFAULTS[$key])) { + $expected = \gettype(self::DEFAULTS[$key]); + $got = \gettype($value); + + throw new \InvalidArgumentException("Invalid type for system config {$key}, expected {$expected}, got {$got}"); + } + + // Do not allow null for non-app keys + if (!$isAppKey && null === $value) { + throw new \InvalidArgumentException("Invalid value for system config {$key}, null is not allowed"); + } + + $config = \OC::$server->get(\OCP\IConfig::class); + if ($isAppKey && ($value === self::DEFAULTS[$key] || null === $value)) { + $config->deleteSystemValue($key); + } else { + $config->setSystemValue($key, $value); + } + } +} diff --git a/lib/SystemConfigDefault.php b/lib/SystemConfigDefault.php deleted file mode 100644 index 3c46ce5e8..000000000 --- a/lib/SystemConfigDefault.php +++ /dev/null @@ -1,96 +0,0 @@ - '', - - // Do not use packaged binaries of exiftool - // This requires perl to be available - 'memories.exiftool_no_local' => false, - - // Temporary directory for non-php binaries. The directory must be writable - // and the webserver user should be able to create executable binaries in it. - // Note that go-vod temp files are separately configured (see memories.vod.tempdir) - // Defaults to system temp directory if blank - 'memories.exiftool.tmp' => '', - - // How to index user directories - // 0 = auto-index disabled - // 1 = index everything - // 2 = index only user timelines - // 3 = index only configured path - 'memories.index.mode' => '1', - - // Path to index (only used if indexing mode is 3) - 'memories.index.path' => '/', - - // Places database type identifier - 'memories.gis_type' => -1, - - // Default timeline path for all users - // If set to '_empty_', the user is prompted to select a path on first open (default) - 'memories.timeline.default_path' => '_empty_', - - // Default viewer high resolution image loading condition - // Valid values: 'always' | 'zoom' | 'never' - 'memories.viewer.high_res_cond_default' => 'zoom', - - // Disable transcoding - 'memories.vod.disable' => true, - - // VA-API configuration options - 'memories.vod.vaapi' => false, // Transcode with VA-API - 'memories.vod.vaapi.low_power' => false, // Use low_power mode for VA-API - - // NVENC configuration options - 'memories.vod.nvenc' => false, // Transcode with NVIDIA NVENC - 'memories.vod.nvenc.temporal_aq' => false, - 'memories.vod.nvenc.scale' => 'npp', // npp or cuda - - // Extra streaming configuration - 'memories.vod.use_transpose' => false, - 'memories.vod.use_gop_size' => false, - - // Paths to ffmpeg and ffprobe binaries - 'memories.vod.ffmpeg' => '', - 'memories.vod.ffprobe' => '', - - // Path to go-vod binary - 'memories.vod.path' => '', - - // Path to use for transcoded files (/tmp/go-vod/instanceid) - // Make sure this has plenty of space - 'memories.vod.tempdir' => '', - - // Bind address to use when starting the transcoding server - 'memories.vod.bind' => '127.0.0.1:47788', - - // Address used to connect to the transcoding server - // If not specified, the bind address above will be used - 'memories.vod.connect' => '127.0.0.1:47788', - - // Mark go-vod as external. If true, Memories will not attempt to - // start go-vod if it is not running already. - 'memories.vod.external' => false, - - // Set the default video quality for a first time user - // 0 => Auto (default) - // -1 => Original (max quality with transcoding) - // -2 => Direct (disable transcoding) - // 1080 => 1080p (and so on) - 'memories.video_default_quality' => '0', - - // Memories only provides an admin interface for these - // https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/config_sample_php_parameters.html#previews - 'enabledPreviewProviders' => [], - 'preview_max_x' => 4096, - 'preview_max_y' => 4096, - 'preview_max_memory' => 128, - 'preview_max_filesize_image' => 50, - 'preview_ffmpeg_path' => '', - - // Placeholders only; these are not touched by the app - 'instanceid' => 'default', -]; diff --git a/lib/Util.php b/lib/Util.php index 44bef187b..20a903557 100644 --- a/lib/Util.php +++ b/lib/Util.php @@ -8,6 +8,7 @@ use OC\Files\Search\SearchComparison; use OC\Files\Search\SearchQuery; use OCA\Memories\AppInfo\Application; +use OCA\Memories\Settings\SystemConfig; use OCP\App\IAppManager; use OCP\Files\Node; use OCP\Files\Search\ISearchBinaryOperator; @@ -321,7 +322,7 @@ public static function isEncryptionEnabled(): bool */ public static function placesGISType(): int { - return self::getSystemConfig('memories.gis_type'); + return SystemConfig::get('memories.gis_type'); } /** @@ -333,7 +334,7 @@ public static function getTimelinePaths(string $uid): array { $paths = \OC::$server->get(IConfig::class) ->getUserValue($uid, Application::APPNAME, 'timelinePath', null) - ?: self::getSystemConfig('memories.timeline.default_path'); + ?: SystemConfig::get('memories.timeline.default_path'); return array_map( static fn ($path) => self::sanitizePath(trim($path)) @@ -385,76 +386,6 @@ public static function explode_exact(string $delimiter, string $string, int $cou return array_pad(explode($delimiter, $string, $count), $count, ''); } - /** - * Get a system config key with the correct default. - * - * @param string $key System config key - * @param mixed $default Default value - */ - public static function getSystemConfig(string $key, mixed $default = null): mixed - { - $config = \OC::$server->get(\OCP\IConfig::class); - - $defaults = self::systemConfigDefaults(); - if (!\array_key_exists($key, $defaults)) { - throw new \InvalidArgumentException("Invalid system config key: {$key}"); - } - - return $config->getSystemValue($key, $default ?? $defaults[$key]); - } - - /** - * Set a system config key. - * - * @throws \InvalidArgumentException - */ - public static function setSystemConfig(string $key, mixed $value): void - { - $config = \OC::$server->get(\OCP\IConfig::class); - - // Check if the key is valid - $defaults = self::systemConfigDefaults(); - if (!\array_key_exists($key, $defaults)) { - throw new \InvalidArgumentException("Invalid system config key: {$key}"); - } - - // Key belongs to memories namespace - $isAppKey = str_starts_with($key, Application::APPNAME.'.'); - - // Check if the value has the correct type - if (null !== $value && \gettype($value) !== \gettype($defaults[$key])) { - $expected = \gettype($defaults[$key]); - $got = \gettype($value); - - throw new \InvalidArgumentException("Invalid type for system config {$key}, expected {$expected}, got {$got}"); - } - - // Do not allow null for non-app keys - if (!$isAppKey && null === $value) { - throw new \InvalidArgumentException("Invalid value for system config {$key}, null is not allowed"); - } - - if ($isAppKey && ($value === $defaults[$key] || null === $value)) { - $config->deleteSystemValue($key); - } else { - $config->setSystemValue($key, $value); - } - } - - /** Get list of defaults for all system config keys. */ - public static function systemConfigDefaults(): array - { - return require __DIR__.'/SystemConfigDefault.php'; - } - - /** - * Get the instance ID for this instance. - */ - public static function getInstanceId(): string - { - return self::getSystemConfig('instanceid'); - } - /** * Checks if the API call was made from a native interface. */