aboutsummaryrefslogtreecommitdiffstats
path: root/core/Command/Config
diff options
context:
space:
mode:
Diffstat (limited to 'core/Command/Config')
-rw-r--r--core/Command/Config/App/Base.php2
-rw-r--r--core/Command/Config/App/GetConfig.php12
-rw-r--r--core/Command/Config/App/SetConfig.php30
-rw-r--r--core/Command/Config/ListConfigs.php9
-rw-r--r--core/Command/Config/Preset.php71
-rw-r--r--core/Command/Config/System/Base.php1
-rw-r--r--core/Command/Config/System/CastHelper.php76
-rw-r--r--core/Command/Config/System/SetConfig.php77
8 files changed, 181 insertions, 97 deletions
diff --git a/core/Command/Config/App/Base.php b/core/Command/Config/App/Base.php
index 07341c4faf9..e90a8e78f5b 100644
--- a/core/Command/Config/App/Base.php
+++ b/core/Command/Config/App/Base.php
@@ -7,12 +7,14 @@ declare(strict_types=1);
*/
namespace OC\Core\Command\Config\App;
+use OC\Config\ConfigManager;
use OCP\IAppConfig;
use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
abstract class Base extends \OC\Core\Command\Base {
public function __construct(
protected IAppConfig $appConfig,
+ protected readonly ConfigManager $configManager,
) {
parent::__construct();
}
diff --git a/core/Command/Config/App/GetConfig.php b/core/Command/Config/App/GetConfig.php
index b68476a2e91..af0c5648232 100644
--- a/core/Command/Config/App/GetConfig.php
+++ b/core/Command/Config/App/GetConfig.php
@@ -38,6 +38,12 @@ class GetConfig extends Base {
'returns complete details about the app config value'
)
->addOption(
+ '--key-details',
+ null,
+ InputOption::VALUE_NONE,
+ 'returns complete details about the app config key'
+ )
+ ->addOption(
'default-value',
null,
InputOption::VALUE_OPTIONAL,
@@ -66,6 +72,12 @@ class GetConfig extends Base {
return 0;
}
+ if ($input->getOption('key-details')) {
+ $details = $this->appConfig->getKeyDetails($appName, $configName);
+ $this->writeArrayInOutputFormat($input, $output, $details);
+ return 0;
+ }
+
try {
$configValue = $this->appConfig->getDetails($appName, $configName)['value'];
} catch (AppConfigUnknownKeyException $e) {
diff --git a/core/Command/Config/App/SetConfig.php b/core/Command/Config/App/SetConfig.php
index 345067cfd45..c818404fc0e 100644
--- a/core/Command/Config/App/SetConfig.php
+++ b/core/Command/Config/App/SetConfig.php
@@ -9,7 +9,6 @@ declare(strict_types=1);
namespace OC\Core\Command\Config\App;
use OC\AppConfig;
-use OCP\Exceptions\AppConfigIncorrectTypeException;
use OCP\Exceptions\AppConfigUnknownKeyException;
use OCP\IAppConfig;
use Symfony\Component\Console\Helper\QuestionHelper;
@@ -161,7 +160,6 @@ class SetConfig extends Base {
}
$value = (string)$input->getOption('value');
-
switch ($type) {
case IAppConfig::VALUE_MIXED:
$updated = $this->appConfig->setValueMixed($appName, $configName, $value, $lazy, $sensitive);
@@ -172,34 +170,19 @@ class SetConfig extends Base {
break;
case IAppConfig::VALUE_INT:
- if ($value !== ((string)((int)$value))) {
- throw new AppConfigIncorrectTypeException('Value is not an integer');
- }
- $updated = $this->appConfig->setValueInt($appName, $configName, (int)$value, $lazy, $sensitive);
+ $updated = $this->appConfig->setValueInt($appName, $configName, $this->configManager->convertToInt($value), $lazy, $sensitive);
break;
case IAppConfig::VALUE_FLOAT:
- if ($value !== ((string)((float)$value))) {
- throw new AppConfigIncorrectTypeException('Value is not a float');
- }
- $updated = $this->appConfig->setValueFloat($appName, $configName, (float)$value, $lazy, $sensitive);
+ $updated = $this->appConfig->setValueFloat($appName, $configName, $this->configManager->convertToFloat($value), $lazy, $sensitive);
break;
case IAppConfig::VALUE_BOOL:
- if (in_array(strtolower($value), ['true', '1', 'on', 'yes'])) {
- $valueBool = true;
- } elseif (in_array(strtolower($value), ['false', '0', 'off', 'no'])) {
- $valueBool = false;
- } else {
- throw new AppConfigIncorrectTypeException('Value is not a boolean, please use \'true\' or \'false\'');
- }
- $updated = $this->appConfig->setValueBool($appName, $configName, $valueBool, $lazy);
+ $updated = $this->appConfig->setValueBool($appName, $configName, $this->configManager->convertToBool($value), $lazy);
break;
case IAppConfig::VALUE_ARRAY:
- $valueArray = json_decode($value, true, flags: JSON_THROW_ON_ERROR);
- $valueArray = (is_array($valueArray)) ? $valueArray : throw new AppConfigIncorrectTypeException('Value is not an array');
- $updated = $this->appConfig->setValueArray($appName, $configName, $valueArray, $lazy, $sensitive);
+ $updated = $this->appConfig->setValueArray($appName, $configName, $this->configManager->convertToArray($value), $lazy, $sensitive);
break;
}
}
@@ -216,6 +199,11 @@ class SetConfig extends Base {
$current['lazy'] ? 'lazy cache' : 'fast cache'
)
);
+ $keyDetails = $this->appConfig->getKeyDetails($appName, $configName);
+ if (($keyDetails['note'] ?? '') !== '') {
+ $output->writeln('<comment>Note:</comment> ' . $keyDetails['note']);
+ }
+
} else {
$output->writeln('<info>Config value were not updated</info>');
}
diff --git a/core/Command/Config/ListConfigs.php b/core/Command/Config/ListConfigs.php
index 094348dd9ba..a7c195276eb 100644
--- a/core/Command/Config/ListConfigs.php
+++ b/core/Command/Config/ListConfigs.php
@@ -7,6 +7,7 @@
*/
namespace OC\Core\Command\Config;
+use OC\Config\ConfigManager;
use OC\Core\Command\Base;
use OC\SystemConfig;
use OCP\IAppConfig;
@@ -22,6 +23,7 @@ class ListConfigs extends Base {
public function __construct(
protected SystemConfig $systemConfig,
protected IAppConfig $appConfig,
+ protected ConfigManager $configManager,
) {
parent::__construct();
}
@@ -44,6 +46,7 @@ class ListConfigs extends Base {
InputOption::VALUE_NONE,
'Use this option when you want to include sensitive configs like passwords, salts, ...'
)
+ ->addOption('migrate', null, InputOption::VALUE_NONE, 'Rename config keys of all enabled apps, based on ConfigLexicon')
;
}
@@ -51,6 +54,10 @@ class ListConfigs extends Base {
$app = $input->getArgument('app');
$noSensitiveValues = !$input->getOption('private');
+ if ($input->getOption('migrate')) {
+ $this->configManager->migrateConfigLexiconKeys(($app === 'all') ? null : $app);
+ }
+
if (!is_string($app)) {
$output->writeln('<error>Invalid app value given</error>');
return 1;
@@ -118,7 +125,7 @@ class ListConfigs extends Base {
*/
protected function getAppConfigs(string $app, bool $noSensitiveValues) {
if ($noSensitiveValues) {
- return $this->appConfig->getFilteredValues($app, false);
+ return $this->appConfig->getFilteredValues($app);
} else {
return $this->appConfig->getValues($app, false);
}
diff --git a/core/Command/Config/Preset.php b/core/Command/Config/Preset.php
new file mode 100644
index 00000000000..4f0278896db
--- /dev/null
+++ b/core/Command/Config/Preset.php
@@ -0,0 +1,71 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Core\Command\Config;
+
+use OC\Config\ConfigManager;
+use OC\Core\Command\Base;
+use OCP\Config\Lexicon\Preset as ConfigLexiconPreset;
+use OCP\IConfig;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class Preset extends Base {
+ public function __construct(
+ private readonly IConfig $config,
+ private readonly ConfigManager $configManager,
+ ) {
+ parent::__construct();
+ }
+
+ protected function configure() {
+ parent::configure();
+ $this->setName('config:preset')
+ ->setDescription('Select a config preset')
+ ->addArgument('preset', InputArgument::OPTIONAL, 'Preset to use for all unset config values', '')
+ ->addOption('list', '', InputOption::VALUE_NONE, 'display available preset');
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int {
+ if ($input->getOption('list')) {
+ $this->getEnum('', $list);
+ $this->writeArrayInOutputFormat($input, $output, $list);
+ return self::SUCCESS;
+ }
+
+ $presetArg = $input->getArgument('preset');
+ if ($presetArg !== '') {
+ $preset = $this->getEnum($presetArg, $list);
+ if ($preset === null) {
+ $output->writeln('<error>Invalid preset: ' . $presetArg . '</error>');
+ $output->writeln('Available presets: ' . implode(', ', $list));
+ return self::INVALID;
+ }
+
+ $this->configManager->setLexiconPreset($preset);
+ }
+
+ $current = ConfigLexiconPreset::tryFrom($this->config->getSystemValueInt(ConfigManager::PRESET_CONFIGKEY, 0)) ?? ConfigLexiconPreset::NONE;
+ $this->writeArrayInOutputFormat($input, $output, [$current->name], 'current preset: ');
+ return self::SUCCESS;
+ }
+
+ private function getEnum(string $name, ?array &$list = null): ?ConfigLexiconPreset {
+ $list = [];
+ foreach (ConfigLexiconPreset::cases() as $case) {
+ $list[] = $case->name;
+ if (strtolower($case->name) === strtolower($name)) {
+ return $case;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/core/Command/Config/System/Base.php b/core/Command/Config/System/Base.php
index ce39cd4c95b..088d902b4fd 100644
--- a/core/Command/Config/System/Base.php
+++ b/core/Command/Config/System/Base.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/core/Command/Config/System/CastHelper.php b/core/Command/Config/System/CastHelper.php
new file mode 100644
index 00000000000..f2b838bdf9b
--- /dev/null
+++ b/core/Command/Config/System/CastHelper.php
@@ -0,0 +1,76 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\Core\Command\Config\System;
+
+class CastHelper {
+ /**
+ * @return array{value: mixed, readable-value: string}
+ */
+ public function castValue(?string $value, string $type): array {
+ switch ($type) {
+ case 'integer':
+ case 'int':
+ if (!is_numeric($value)) {
+ throw new \InvalidArgumentException('Non-numeric value specified');
+ }
+ return [
+ 'value' => (int)$value,
+ 'readable-value' => 'integer ' . (int)$value,
+ ];
+
+ case 'double':
+ case 'float':
+ if (!is_numeric($value)) {
+ throw new \InvalidArgumentException('Non-numeric value specified');
+ }
+ return [
+ 'value' => (float)$value,
+ 'readable-value' => 'double ' . (float)$value,
+ ];
+
+ case 'boolean':
+ case 'bool':
+ $value = strtolower($value);
+ return match ($value) {
+ 'true' => [
+ 'value' => true,
+ 'readable-value' => 'boolean ' . $value,
+ ],
+ 'false' => [
+ 'value' => false,
+ 'readable-value' => 'boolean ' . $value,
+ ],
+ default => throw new \InvalidArgumentException('Unable to parse value as boolean'),
+ };
+
+ case 'null':
+ return [
+ 'value' => null,
+ 'readable-value' => 'null',
+ ];
+
+ case 'string':
+ $value = (string)$value;
+ return [
+ 'value' => $value,
+ 'readable-value' => ($value === '') ? 'empty string' : 'string ' . $value,
+ ];
+
+ case 'json':
+ $value = json_decode($value, true);
+ return [
+ 'value' => $value,
+ 'readable-value' => 'json ' . json_encode($value),
+ ];
+
+ default:
+ throw new \InvalidArgumentException('Invalid type');
+ }
+ }
+}
diff --git a/core/Command/Config/System/SetConfig.php b/core/Command/Config/System/SetConfig.php
index 62ab7f7120f..1b1bdc66a6e 100644
--- a/core/Command/Config/System/SetConfig.php
+++ b/core/Command/Config/System/SetConfig.php
@@ -17,6 +17,7 @@ use Symfony\Component\Console\Output\OutputInterface;
class SetConfig extends Base {
public function __construct(
SystemConfig $systemConfig,
+ private CastHelper $castHelper,
) {
parent::__construct($systemConfig);
}
@@ -57,7 +58,7 @@ class SetConfig extends Base {
protected function execute(InputInterface $input, OutputInterface $output): int {
$configNames = $input->getArgument('name');
$configName = $configNames[0];
- $configValue = $this->castValue($input->getOption('value'), $input->getOption('type'));
+ $configValue = $this->castHelper->castValue($input->getOption('value'), $input->getOption('type'));
$updateOnly = $input->getOption('update-only');
if (count($configNames) > 1) {
@@ -81,80 +82,6 @@ class SetConfig extends Base {
}
/**
- * @param string $value
- * @param string $type
- * @return mixed
- * @throws \InvalidArgumentException
- */
- protected function castValue($value, $type) {
- switch ($type) {
- case 'integer':
- case 'int':
- if (!is_numeric($value)) {
- throw new \InvalidArgumentException('Non-numeric value specified');
- }
- return [
- 'value' => (int)$value,
- 'readable-value' => 'integer ' . (int)$value,
- ];
-
- case 'double':
- case 'float':
- if (!is_numeric($value)) {
- throw new \InvalidArgumentException('Non-numeric value specified');
- }
- return [
- 'value' => (float)$value,
- 'readable-value' => 'double ' . (float)$value,
- ];
-
- case 'boolean':
- case 'bool':
- $value = strtolower($value);
- switch ($value) {
- case 'true':
- return [
- 'value' => true,
- 'readable-value' => 'boolean ' . $value,
- ];
-
- case 'false':
- return [
- 'value' => false,
- 'readable-value' => 'boolean ' . $value,
- ];
-
- default:
- throw new \InvalidArgumentException('Unable to parse value as boolean');
- }
-
- // no break
- case 'null':
- return [
- 'value' => null,
- 'readable-value' => 'null',
- ];
-
- case 'string':
- $value = (string)$value;
- return [
- 'value' => $value,
- 'readable-value' => ($value === '') ? 'empty string' : 'string ' . $value,
- ];
-
- case 'json':
- $value = json_decode($value, true);
- return [
- 'value' => $value,
- 'readable-value' => 'json ' . json_encode($value),
- ];
-
- default:
- throw new \InvalidArgumentException('Invalid type');
- }
- }
-
- /**
* @param array $configNames
* @param mixed $existingValues
* @param mixed $value