Explorar o código

2297 cli parameters consistency (#6028)

* Updates do-install params

* Adds parseCliParams to _cli.php

* Updates do-install to use parseCliParams

* Updates reconfigure to use parseCliParams

* Fixes bug mail_login => email

* Update create-user to use parseCliParams

* Minor refactor

* Updates update-user to use parseCliParams

* Fix no_default_feeds => no-default-feeds

* Refactors arrays

* Updates CLI Readme

* Adds docblocks to _cli functions

* Sets vars in _cli functions

* Fixes indentation

* Meeting coding standards around colons

* Meeting PHPStan standards

* Removes stray whitespace

* Meeting PHPStan Next Level standards

* More specific typing

* Maintaining types

* Typing around getopt()

* Fixes typo

* Fixes typo perameters -> parameters

* Removes unused variable

* Rewrites deprecation warning message
Kasimir Cash %!s(int64=2) %!d(string=hai) anos
pai
achega
9a80dde238
Modificáronse 7 ficheiros con 333 adicións e 140 borrados
  1. 25 7
      cli/README.md
  2. 106 0
      cli/_cli.php
  3. 38 27
      cli/_update-or-create-user.php
  4. 6 6
      cli/create-user.php
  5. 72 43
      cli/do-install.php
  6. 81 52
      cli/reconfigure.php
  7. 5 5
      cli/update-user.php

+ 25 - 7
cli/README.md

@@ -34,13 +34,22 @@ cd /usr/share/FreshRSS
 ./cli/prepare.php
 # Ensure the needed directories in ./data/
 
-./cli/do-install.php --default_user admin [ --auth_type form --environment production --base_url https://rss.example.net --language en --title FreshRSS --allow_anonymous --api_enabled --db-type mysql --db-host localhost:3306 --db-user freshrss --db-password dbPassword123 --db-base freshrss --db-prefix freshrss ]
-# --auth_type can be: 'form' (default), 'http_auth' (using the Web server access control), 'none' (dangerous)
-# --db-type can be: 'sqlite' (default), 'mysql' (MySQL or MariaDB), 'pgsql' (PostgreSQL)
-# --base_url should be a public (routable) URL if possible, and is used for push (WebSub), for some API functions (e.g. favicons), and external URLs in FreshRSS.
+./cli/do-install.php --default-user admin [ --auth-type form --environment production --base-url https://rss.example.net --language en --title FreshRSS --allow-anonymous --allow-anonymous-refresh --api-enabled --db-type sqlite --db-host localhost:3306 --db-user freshrss --db-password dbPassword123 --db-base freshrss --db-prefix freshrss_ ]
+# --default-user must be alphanumeric and not longer than 38 characters. The default user of this FreshRSS instance, used as the public user for anonymous reading
+# --auth-type can be: 'form' (default), 'http_auth' (using the Web server access control), 'none' (dangerous)
 # --environment can be: 'production' (default), 'development' (for additional log messages)
+# --base-url should be a public (routable) URL if possible, and is used for push (WebSub), for some API functions (e.g. favicons), and external URLs in FreshRSS
 # --language can be: 'en' (default), 'fr', or one of the [supported languages](../app/i18n/)
-# --db-prefix is an optional prefix in front of the names of the tables. We suggest using 'freshrss_'
+# --title web user interface title for this FreshRSS instance
+# --allow-anonymous sets whether non logged-in visitors are permitted to see the default user's feeds
+# --allow-anonymous-refresh sets whether to permit anonymous users to start the refresh process
+# --api-enabled sets whether the API may be used for mobile apps. API passwords must be set for individual users
+# --db-type can be: 'sqlite' (default), 'mysql' (MySQL or MariaDB), 'pgsql' (PostgreSQL)
+# --db-host URL of the database server. Default is 'localhost'
+# --db-user sets database user
+# --db-password sets database password
+# --db-base sets database name
+# --db-prefix is an optional prefix in front of the names of the tables. We suggest using 'freshrss_' (default)
 # This command does not create the default user. Do that with ./cli/create-user.php
 
 ./cli/reconfigure.php
@@ -54,11 +63,20 @@ cd /usr/share/FreshRSS
 ```sh
 cd /usr/share/FreshRSS
 
-./cli/create-user.php --user username [ --password 'password' --api_password 'api_password' --language en --email user@example.net --token 'longRandomString' --no_default_feeds --purge_after_months 3 --feed_min_articles_default 50 --feed_ttl_default 3600 --since_hours_posts_per_rss 168 --max_posts_per_rss 400 ]
+./cli/create-user.php --user username [ --password 'password' --api-password 'api_password' --language en --email user@example.net --token 'longRandomString' --no-default-feeds --purge-after-months 3 --feed-min-articles-default 50 --feed-ttl-default 3600 --since-hours-posts-per-rss 168 --max-posts-per-rss 400 ]
+# --user must be alphanumeric, not longer than 38 characters. The name of the user to be created/updated
+# --password sets the user's password
+# --api-password sets the user's api password
 # --language can be: 'en' (default), 'fr', or one of the [supported languages](../app/i18n/)
+# --email sets an email for the user which will be used email validation if it forced email validation is enabled
+# --no-default-feeds do not add this FreshRSS instance's default feeds to the user during creation
+# --purge-after-months max age an article can reach before being archived. Default is '3'
+# --feed-min-articles-default number of articles in a feed at which archiving will pause. Default is '50'
+# --feed-ttl-default minimum number of seconds to elapse between feed refreshes. Default is '3600'
+# --max-posts-per-rss number of articles in a feed at which an old article will be archived before a new article is added. Default is '200' 
 
 ./cli/update-user.php --user username [ ... ]
-# Same options as create-user.php, except --no_default_feeds which is only available for create-user.php
+# Same options as create-user.php, except --no-default-feeds which is only available for create-user.php
 ```
 
 > ℹ️ More options for [the configuration of users](../config-user.default.php#L3-L5) may be set in `./data/config-user.custom.php` prior to creating new users, or in `./data/users/*/config.php` for existing users.

+ 106 - 0
cli/_cli.php

@@ -75,6 +75,47 @@ function performRequirementCheck(string $databaseType): void {
 	}
 }
 
+/**
+ * Parses parameters used with FreshRSS' CLI commands.
+ * @param array{'valid':array<string,string>,'deprecated':array<string,string>} $parameters An array of 'valid': An
+ * array of parameters as keys and their respective getopt() notations as values. 'deprecated' An array with
+ * replacement parameters as keys and their respective deprecated parameters as values.
+ * @return array{'valid':array<string,string|bool>,'invalid':array<string>} An array of 'valid': an array of all
+ * known parameters used and their respective options and 'invalid': an array of all unknown parameters used.
+ */
+function parseCliParams(array $parameters): array {
+	global $argv;
+	$cliParams = [];
+
+	foreach ($parameters['valid'] as $param => $getopt_val) {
+		$cliParams[] = $param . $getopt_val;
+	}
+	foreach ($parameters['deprecated'] as $param => $deprecatedParam) {
+		$cliParams[] = $deprecatedParam . $parameters['valid'][$param];
+	}
+
+	$opts = getopt('', $cliParams);
+
+	/** @var array<string,string|bool> $valid */
+	$valid = is_array($opts) ? $opts : [];
+
+	array_walk($valid, static fn(&$option) => $option = $option === false ? true : $option);
+
+	if (checkforDeprecatedParameterUse(array_keys($valid), $parameters['deprecated'])) {
+		$valid = updateDeprecatedParameters($valid, $parameters['deprecated']);
+	}
+
+	$invalid = findInvalidOptions(
+		$argv,
+		array_merge(array_keys($parameters['valid']), array_values($parameters['deprecated']))
+	);
+
+	return [
+		'valid' => $valid,
+		'invalid' => $invalid
+	];
+}
+
 /**
  * @param array<string> $options
  * @return array<string>
@@ -104,3 +145,68 @@ function validateOptions(array $input, array $params): bool {
 	fwrite(STDERR, sprintf("FreshRSS error: unknown options: %s\n", implode (', ', $unknownOptions)));
 	return false;
 }
+
+/**
+ * Checks for use of unknown parameters with FreshRSS' CLI commands.
+ * @param array<string> $input An array of parameters to check for validity.
+ * @param array<string> $params An array of valid parameters to check against.
+ * @return array<string> Returns an array of all unknown parameters found.
+ */
+function findInvalidOptions(array $input, array $params): array {
+	$sanitizeInput = getLongOptions($input, REGEX_INPUT_OPTIONS);
+	$unknownOptions = array_diff($sanitizeInput, $params);
+
+	if (0 === count($unknownOptions)) {
+		return [];
+	}
+
+	fwrite(STDERR, sprintf("FreshRSS error: unknown options: %s\n", implode (', ', $unknownOptions)));
+	return $unknownOptions;
+}
+
+/**
+ * Checks for use of deprecated parameters with FreshRSS' CLI commands.
+ * @param array<string> $options User inputs to check for deprecated parameter use.
+ * @param array<string,string> $params An array with replacement parameters as keys and their respective deprecated
+ * parameters as values.
+ * @return bool Returns TRUE and generates a deprecation warning if deprecated parameters
+ * have been used, FALSE otherwise.
+ */
+function checkforDeprecatedParameterUse(array $options, array $params): bool {
+	$deprecatedOptions = array_intersect($options, $params);
+	$replacements = array_map(static fn($option) => array_search($option, $params, true), $deprecatedOptions);
+
+	if (0 === count($deprecatedOptions)) {
+		return false;
+	}
+
+	fwrite(STDERR, "FreshRSS deprecation warning: the CLI option(s): " . implode(', ', $deprecatedOptions) .
+		" are deprecated and will be removed in a future release. Use: "
+		. implode(', ', $replacements) . " instead\n");
+	return true;
+}
+
+/**
+ * Switches all used deprecated parameters to their replacements if they have one.
+ *
+ * @template T
+ *
+ * @param array<string,T> $options User inputs.
+ * @param array<string,string> $params An array with replacement parameters as keys and their respective deprecated
+ * parameters as values.
+ * @return array<string,T>  Returns $options with deprications replaced.
+ */
+function updateDeprecatedParameters(array $options, array $params): array {
+	$updatedOptions = [];
+
+	foreach ($options as $param => $option) {
+		$replacement = array_search($param, $params, true);
+		if (is_string($replacement)) {
+			$updatedOptions[$replacement] = $option;
+		} else {
+			$updatedOptions[$param] = $option;
+		}
+	}
+
+	return $updatedOptions;
+}

+ 38 - 27
cli/_update-or-create-user.php

@@ -4,56 +4,67 @@ require(__DIR__ . '/_cli.php');
 
 performRequirementCheck(FreshRSS_Context::systemConf()->db['type'] ?? '');
 
-$params = array(
-		'user:',
-		'password:',
-		'api_password:',
-		'language:',
-		'email:',
-		'token:',
-		'purge_after_months:',
-		'feed_min_articles_default:',
-		'feed_ttl_default:',
-		'since_hours_posts_per_rss:',
-		'max_posts_per_rss:',
-	);
+$parameters = array(
+	'valid' => array(
+		'user' => ':',
+		'password' => ':',
+		'api-password' => ':',
+		'language' => ':',
+		'email' => ':',
+		'token' => ':',
+		'purge-after-months' => ':',
+		'feed-min-articles-default' => ':',
+		'feed-ttl-default' => ':',
+		'since-hours-posts-per-rss' => ':',
+		'max-posts-per-rss' => ':',
+	),
+	'deprecated' => array(
+		'api-password' => 'api_password',
+		'purge-after-months' => 'purge_after_months',
+		'feed-min-articles-default' => 'feed_min_articles_default',
+		'feed-ttl-default' => 'feed_ttl_default',
+		'since-hours-posts-per-rss' => 'since_hours_posts_per_rss',
+		'max-posts-per-rss' => 'max_posts_per_rss',
+	),
+);
 
 if (!isset($isUpdate)) {
 	$isUpdate = false;
 } elseif (!$isUpdate) {
-	$params[] = 'no_default_feeds';	//Only for creating new users
+	$parameters['valid']['no-default-feeds'] = '';	//Only for creating new users
+	$parameters['deprecated']['no-default-feeds'] = 'no_default_feeds';
 }
 
-$GLOBALS['options'] = getopt('', $params);
+$GLOBALS['options'] = parseCliParams($parameters);
 
-if (!validateOptions($argv, $params) || empty($options['user'])) {
+if (!empty($options['invalid']) || empty($options['valid']['user'])) {
 	fail('Usage: ' . basename($_SERVER['SCRIPT_FILENAME']) .
-		" --user username ( --password 'password' --api_password 'api_password'" .
+		" --user username ( --password 'password' --api-password 'api_password'" .
 		" --language en --email user@example.net --token 'longRandomString'" .
-		($isUpdate ? '' : ' --no_default_feeds') .
-		" --purge_after_months 3 --feed_min_articles_default 50 --feed_ttl_default 3600" .
-		" --since_hours_posts_per_rss 168 --max_posts_per_rss 400 )");
+		($isUpdate ? '' : ' --no-default-feeds') .
+		" --purge-after-months 3 --feed-min-articles-default 50 --feed-ttl-default 3600" .
+		" --since-hours-posts-per-rss 168 --max-posts-per-rss 400 )");
 }
 
 function strParam(string $name): ?string {
 	global $options;
-	return isset($options[$name]) ? strval($options[$name]) : null;
+	return isset($options['valid'][$name]) ? strval($options['valid'][$name]) : null;
 }
 
 function intParam(string $name): ?int {
 	global $options;
-	return isset($options[$name]) && ctype_digit($options[$name]) ? intval($options[$name]) : null;
+	return isset($options['valid'][$name]) && ctype_digit($options['valid'][$name]) ? intval($options['valid'][$name]) : null;
 }
 
 $values = array(
 		'language' => strParam('language'),
 		'mail_login' => strParam('email'),
 		'token' => strParam('token'),
-		'old_entries' => intParam('purge_after_months'),	//TODO: Update with new mechanism
-		'keep_history_default' => intParam('feed_min_articles_default'),	//TODO: Update with new mechanism
-		'ttl_default' => intParam('feed_ttl_default'),
-		'since_hours_posts_per_rss' => intParam('since_hours_posts_per_rss'),
-		'max_posts_per_rss' => intParam('max_posts_per_rss'),
+		'old_entries' => intParam('purge-after-months'),	//TODO: Update with new mechanism
+		'keep_history_default' => intParam('feed-min-articles-default'),	//TODO: Update with new mechanism
+		'ttl_default' => intParam('feed-ttl-default'),
+		'since_hours_posts_per_rss' => intParam('since-hours-posts-per-rss'),
+		'max_posts_per_rss' => intParam('max-posts-per-rss'),
 	);
 
 $values = array_filter($values);

+ 6 - 6
cli/create-user.php

@@ -5,7 +5,7 @@ declare(strict_types=1);
 $isUpdate = false;
 require(__DIR__ . '/_update-or-create-user.php');
 
-$username = $GLOBALS['options']['user'];
+$username = $GLOBALS['options']['valid']['user'];
 if (!FreshRSS_user_Controller::checkUsername($username)) {
 	fail('FreshRSS error: invalid username “' . $username .
 		'”! Must be matching ' . FreshRSS_user_Controller::USERNAME_PATTERN);
@@ -20,19 +20,19 @@ echo 'FreshRSS creating user “', $username, "”…\n";
 
 $ok = FreshRSS_user_Controller::createUser(
 	$username,
-	empty($options['mail_login']) ? '' : $options['mail_login'],
-	empty($options['password']) ? '' : $options['password'],
+	empty($options['valid']['email']) ? '' : $options['valid']['email'],
+	empty($options['valid']['password']) ? '' : $options['valid']['password'],
 	$GLOBALS['values'],
-	!isset($options['no_default_feeds'])
+	!isset($options['valid']['no-default-feeds'])
 );
 
 if (!$ok) {
 	fail('FreshRSS could not create user!');
 }
 
-if (!empty($options['api_password'])) {
+if (!empty($options['valid']['api-password'])) {
 	$username = cliInitUser($username);
-	$error = FreshRSS_api_Controller::updatePassword($options['api_password']);
+	$error = FreshRSS_api_Controller::updatePassword($options['valid']['api-password']);
 	if ($error !== false) {
 		fail($error);
 	}

+ 72 - 43
cli/do-install.php

@@ -7,37 +7,69 @@ if (file_exists(DATA_PATH . '/applied_migrations.txt')) {
 	fail('FreshRSS seems to be already installed!' . "\n" . 'Please use `./cli/reconfigure.php` instead.', EXIT_CODE_ALREADY_EXISTS);
 }
 
-$params = array(
-		'environment:',
-		'base_url:',
-		'language:',
-		'title:',
-		'default_user:',
-		'allow_anonymous',
-		'allow_anonymous_refresh',
-		'auth_type:',
-		'api_enabled',
-		'allow_robots',
-		'disable_update',
-	);
-
-$dBparams = array(
-		'db-type:',
-		'db-host:',
-		'db-user:',
-		'db-password:',
-		'db-base:',
-		'db-prefix::',
-	);
-
-$options = getopt('', array_merge($params, $dBparams));
-
-if (!validateOptions($argv, array_merge($params, $dBparams)) || empty($options['default_user']) || !is_string($options['default_user'])) {
-	fail('Usage: ' . basename(__FILE__) . " --default_user admin ( --auth_type form" .
-		" --environment production --base_url https://rss.example.net --allow_robots" .
-		" --language en --title FreshRSS --allow_anonymous --allow_anonymous_refresh --api_enabled" .
+$parameters = array(
+	'valid' => array(
+		'environment' => ':',
+		'base-url' => ':',
+		'language' => ':',
+		'title' => ':',
+		'default-user' => ':',
+		'allow-anonymous' => '',
+		'allow-anonymous-refresh' => '',
+		'auth-type' => ':',
+		'api-enabled' => '',
+		'allow-robots' => '',
+		'disable-update' => '',
+		'db-type' => ':',
+		'db-host' => ':',
+		'db-user' => ':',
+		'db-password' => ':',
+		'db-base' => ':',
+		'db-prefix' => '::',
+	),
+	'deprecated' => array(
+		'base-url' => 'base_url',
+		'default-user' => 'default_user',
+		'allow-anonymous' => 'allow_anonymous',
+		'allow-anonymous-refresh' => 'allow_anonymous_refresh',
+		'auth-type' => 'auth_type',
+		'api-enabled' => 'api_enabled',
+		'allow-robots' => 'allow_robots',
+		'disable-update' => 'disable_update',
+	),
+);
+
+$configParams = array(
+	'environment' => 'environment',
+	'base-url' => 'base_url',
+	'language' => 'language',
+	'title' => 'title',
+	'default-user' => 'default_user',
+	'allow-anonymous' => 'allow_anonymous',
+	'allow-anonymous-refresh' => 'allow_anonymous_refresh',
+	'auth-type' => 'auth_type',
+	'api-enabled' => 'api_enabled',
+	'allow-robots' => 'allow_robots',
+	'disable-update' => 'disable_update',
+);
+
+$dBconfigParams = array(
+	'db-type' => 'type',
+	'db-host' => 'host',
+	'db-user' => 'user',
+	'db-password' => 'password',
+	'db-base' => 'base',
+	'db-prefix' => 'prefix',
+);
+
+$options = parseCliParams($parameters);
+
+if (!empty($options['invalid']) || empty($options['valid']['default-user']) || !is_string($options['valid']['default-user'])) {
+	fail('Usage: ' . basename(__FILE__) . " --default-user admin ( --auth-type form" .
+		" --environment production --base-url https://rss.example.net --allow-robots" .
+		" --language en --title FreshRSS --allow-anonymous --allow-anonymous-refresh --api-enabled" .
 		" --db-type mysql --db-host localhost:3306 --db-user freshrss --db-password dbPassword123" .
-		" --db-base freshrss --db-prefix freshrss_ --disable_update )");
+		" --db-base freshrss --db-prefix freshrss_ --disable-update )");
 }
 
 fwrite(STDERR, 'FreshRSS install…' . "\n");
@@ -55,10 +87,9 @@ if (file_exists($customConfigPath)) {
 	}
 }
 
-foreach ($params as $param) {
-	$param = rtrim($param, ':');
-	if (isset($options[$param])) {
-		$config[$param] = $options[$param] === false ? true : $options[$param];
+foreach ($configParams as $param => $configParam) {
+	if (isset($options['valid'][$param])) {
+		$config[$configParam] = $options['valid'][$param];
 	}
 }
 
@@ -66,23 +97,21 @@ if ((!empty($config['base_url'])) && is_string($config['base_url']) && Minz_Requ
 	$config['pubsubhubbub_enabled'] = true;
 }
 
-foreach ($dBparams as $dBparam) {
-	$dBparam = rtrim($dBparam, ':');
-	if (isset($options[$dBparam])) {
-		$param = substr($dBparam, strlen('db-'));
-		$config['db'][$param] = $options[$dBparam];
+foreach ($dBconfigParams as $dBparam => $configDbParam) {
+	if (isset($options['valid'][$dBparam])) {
+		$config['db'][$configDbParam] = $options['valid'][$dBparam];
 	}
 }
 
 performRequirementCheck($config['db']['type']);
 
-if (!FreshRSS_user_Controller::checkUsername($options['default_user'])) {
-	fail('FreshRSS error: invalid default username “' . $options['default_user']
+if (!FreshRSS_user_Controller::checkUsername($options['valid']['default-user'])) {
+	fail('FreshRSS error: invalid default username “' . $options['valid']['default-user']
 		. '”! Must be matching ' . FreshRSS_user_Controller::USERNAME_PATTERN);
 }
 
-if (isset($options['auth_type']) && !in_array($options['auth_type'], ['form', 'http_auth', 'none'], true)) {
-	fail('FreshRSS invalid authentication method (auth_type must be one of { form, http_auth, none })');
+if (isset($options['valid']['auth-type']) && !in_array($options['valid']['auth-type'], ['form', 'http_auth', 'none'], true)) {
+	fail('FreshRSS invalid authentication method (auth-type must be one of { form, http_auth, none })');
 }
 
 if (file_put_contents(join_path(DATA_PATH, 'config.php'),

+ 81 - 52
cli/reconfigure.php

@@ -3,99 +3,128 @@
 declare(strict_types=1);
 require(__DIR__ . '/_cli.php');
 
-$params = array(
-		'environment:',
-		'base_url:',
-		'language:',
-		'title:',
-		'default_user:',
-		'allow_anonymous',
-		'allow_anonymous_refresh',
-		'auth_type:',
-		'api_enabled',
-		'allow_robots',
-		'disable_update',
-	);
+$parameters = array(
+	'valid' => array(
+		'environment' => ':',
+		'base-url' => ':',
+		'language' => ':',
+		'title' => ':',
+		'default-user' => ':',
+		'allow-anonymous' => '',
+		'allow-anonymous-refresh' => '',
+		'auth-type' => ':',
+		'api-enabled' => '',
+		'allow-robots' => '',
+		'disable-update' => '',
+		'db-type' => ':',
+		'db-host' => ':',
+		'db-user' => ':',
+		'db-password' => ':',
+		'db-base' => ':',
+		'db-prefix' => '::',
+	),
+	'deprecated' => array(
+		'base-url' => 'base_url',
+		'default-user' => 'default_user',
+		'allow-anonymous' => 'allow_anonymous',
+		'allow-anonymous-refresh' => 'allow_anonymous_refresh',
+		'auth-type' => 'auth_type',
+		'api-enabled' => 'api_enabled',
+		'allow-robots' => 'allow_robots',
+		'disable-update' => 'disable_update',
+	),
+);
 
-$dBparams = array(
-		'db-type:',
-		'db-host:',
-		'db-user:',
-		'db-password:',
-		'db-base:',
-		'db-prefix::',
-	);
+$configParams = array(
+	'environment',
+	'base-url',
+	'language',
+	'title',
+	'default-user',
+	'allow-anonymous',
+	'allow-anonymous-refresh',
+	'auth-type',
+	'api-enabled',
+	'allow-robots',
+	'disable-update',
+);
 
-$options = getopt('', array_merge($params, $dBparams));
+$dBconfigParams = array(
+	'db-type' => 'type',
+	'db-host' => 'host',
+	'db-user' => 'user',
+	'db-password' => 'password',
+	'db-base' => 'base',
+	'db-prefix' => 'prefix',
+);
 
-if (!validateOptions($argv, array_merge($params, $dBparams))) {
-	fail('Usage: ' . basename(__FILE__) . " --default_user admin ( --auth_type form" .
-		" --environment production --base_url https://rss.example.net --allow_robots" .
-		" --language en --title FreshRSS --allow_anonymous --allow_anonymous_refresh --api_enabled" .
+$options = parseCliParams($parameters);
+
+if (!empty($options['invalid'])) {
+	fail('Usage: ' . basename(__FILE__) . " --default-user admin ( --auth-type form" .
+		" --environment production --base-url https://rss.example.net --allow-robots" .
+		" --language en --title FreshRSS --allow-anonymous --allow-anonymous-refresh --api-enabled" .
 		" --db-type mysql --db-host localhost:3306 --db-user freshrss --db-password dbPassword123" .
-		" --db-base freshrss --db-prefix freshrss_ --disable_update )");
+		" --db-base freshrss --db-prefix freshrss_ --disable-update )");
 }
 
 fwrite(STDERR, 'Reconfiguring FreshRSS…' . "\n");
 
-foreach ($params as $param) {
-	$param = rtrim($param, ':');
-	if (isset($options[$param])) {
+foreach ($configParams as $param) {
+	if (isset($options['valid'][$param])) {
 		switch ($param) {
-			case 'allow_anonymous_refresh':
+			case 'allow-anonymous-refresh':
 				FreshRSS_Context::systemConf()->allow_anonymous_refresh = true;
 				break;
-			case 'allow_anonymous':
+			case 'allow-anonymous':
 				FreshRSS_Context::systemConf()->allow_anonymous = true;
 				break;
-			case 'allow_robots':
+			case 'allow-robots':
 				FreshRSS_Context::systemConf()->allow_robots = true;
 				break;
-			case 'api_enabled':
+			case 'api-enabled':
 				FreshRSS_Context::systemConf()->api_enabled = true;
 				break;
-			case 'auth_type':
-				if (in_array($options[$param], ['form', 'http_auth', 'none'], true)) {
-					FreshRSS_Context::systemConf()->auth_type = $options[$param];
+			case 'auth-type':
+				if (in_array($options['valid'][$param], ['form', 'http_auth', 'none'], true)) {
+					FreshRSS_Context::systemConf()->auth_type = $options['valid'][$param];
 				} else {
 					fail('FreshRSS invalid authentication method! auth_type must be one of { form, http_auth, none }');
 				}
 				break;
-			case 'base_url':
-				FreshRSS_Context::systemConf()->base_url = $options[$param];
+			case 'base-url':
+				FreshRSS_Context::systemConf()->base_url = (string) $options['valid'][$param];
 				break;
-			case 'default_user':
-				if (FreshRSS_user_Controller::checkUsername($options[$param])) {
-					FreshRSS_Context::systemConf()->default_user = $options[$param];
+			case 'default-user':
+				if (FreshRSS_user_Controller::checkUsername((string) $options['valid'][$param])) {
+					FreshRSS_Context::systemConf()->default_user = (string) $options['valid'][$param];
 				} else {
 					fail('FreshRSS invalid default username! default_user must be ASCII alphanumeric');
 				}
 				break;
-			case 'disable_update':
+			case 'disable-update':
 				FreshRSS_Context::systemConf()->disable_update = true;
 				break;
 			case 'environment':
-				if (in_array($options[$param], ['development', 'production', 'silent'], true)) {
-					FreshRSS_Context::systemConf()->environment = $options[$param];
+				if (in_array($options['valid'][$param], ['development', 'production', 'silent'], true)) {
+					FreshRSS_Context::systemConf()->environment = $options['valid'][$param];
 				} else {
 					fail('FreshRSS invalid environment! environment must be one of { development, production, silent }');
 				}
 				break;
 			case 'language':
-				FreshRSS_Context::systemConf()->language = $options[$param];
+				FreshRSS_Context::systemConf()->language = (string) $options['valid'][$param];
 				break;
 			case 'title':
-				FreshRSS_Context::systemConf()->title = $options[$param];
+				FreshRSS_Context::systemConf()->title = (string) $options['valid'][$param];
 				break;
 		}
 	}
 }
 $db = FreshRSS_Context::systemConf()->db;
-foreach ($dBparams as $dBparam) {
-	$dBparam = rtrim($dBparam, ':');
-	if (isset($options[$dBparam])) {
-		$param = substr($dBparam, strlen('db-'));
-		$db[$param] = $options[$dBparam];
+foreach ($dBconfigParams as $dBparam => $configDbParam) {
+	if (isset($options['valid'][$dBparam])) {
+		$db[$configDbParam] = $options['valid'][$dBparam];
 	}
 }
 /** @var array{'type':string,'host':string,'user':string,'password':string,'base':string,'prefix':string,

+ 5 - 5
cli/update-user.php

@@ -5,22 +5,22 @@ declare(strict_types=1);
 $isUpdate = true;
 require(__DIR__ . '/_update-or-create-user.php');
 
-$username = cliInitUser($GLOBALS['options']['user']);
+$username = cliInitUser($GLOBALS['options']['valid']['user']);
 
 echo 'FreshRSS updating user “', $username, "”…\n";
 
 $ok = FreshRSS_user_Controller::updateUser(
 	$username,
-	empty($options['mail_login']) ? null : $options['mail_login'],
-	empty($options['password']) ? '' : $options['password'],
+	empty($options['valid']['email']) ? null : $options['valid']['email'],
+	empty($options['valid']['password']) ? '' : $options['valid']['password'],
 	$GLOBALS['values']);
 
 if (!$ok) {
 	fail('FreshRSS could not update user!');
 }
 
-if (!empty($options['api_password'])) {
-	$error = FreshRSS_api_Controller::updatePassword($options['api_password']);
+if (!empty($options['valid']['api_password'])) {
+	$error = FreshRSS_api_Controller::updatePassword($options['valid']['api_password']);
 	if ($error) {
 		fail($error);
 	}