occ config:system:set can now set other value types
Integers, doubles, booleans and even arrays can now be set, with the --type=... option. Array setting can be specified by passing multiple name arguments, e.g. `./occ config:system:set redis port --value=123 --type=integer`
This commit is contained in:
parent
8f89e3520d
commit
b9d384d837
|
@ -48,8 +48,15 @@ class SetConfig extends Base {
|
|||
->setDescription('Set a system config value')
|
||||
->addArgument(
|
||||
'name',
|
||||
InputArgument::REQUIRED,
|
||||
'Name of the config to set'
|
||||
InputArgument::REQUIRED | InputArgument::IS_ARRAY,
|
||||
'Name of the config parameter, specify multiple for array parameter'
|
||||
)
|
||||
->addOption(
|
||||
'type',
|
||||
null,
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'Value type [string, integer, double, boolean]',
|
||||
'string'
|
||||
)
|
||||
->addOption(
|
||||
'value',
|
||||
|
@ -67,16 +74,119 @@ class SetConfig extends Base {
|
|||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$configName = $input->getArgument('name');
|
||||
$configNames = $input->getArgument('name');
|
||||
$configName = $configNames[0];
|
||||
$configValue = $this->castValue($input->getOption('value'), $input->getOption('type'));
|
||||
$updateOnly = $input->getOption('update-only');
|
||||
|
||||
if (!in_array($configName, $this->systemConfig->getKeys()) && $input->hasParameterOption('--update-only')) {
|
||||
$output->writeln('<comment>Config value ' . $configName . ' not updated, as it has not been set before.</comment>');
|
||||
return 1;
|
||||
if (count($configNames) > 1) {
|
||||
$existingValue = $this->systemConfig->getValue($configName);
|
||||
|
||||
$newValue = $this->mergeArrayValue(
|
||||
array_slice($configNames, 1), $existingValue, $configValue, $updateOnly
|
||||
);
|
||||
|
||||
$this->systemConfig->setValue($configName, $newValue);
|
||||
} else {
|
||||
if ($updateOnly && !in_array($configName, $this->systemConfig->getKeys(), true)) {
|
||||
throw new \UnexpectedValueException('Config parameter does not exist');
|
||||
}
|
||||
|
||||
$this->systemConfig->setValue($configName, $configValue);
|
||||
}
|
||||
$configValue = $input->getOption('value');
|
||||
|
||||
$this->systemConfig->setValue($configName, $configValue);
|
||||
$output->writeln('<info>System config value ' . $configName . ' set to ' . $configValue . '</info>');
|
||||
$output->writeln('<info>System config value ' . implode(' => ', $configNames) . ' set to ' . $configValue . '</info>');
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param string $type
|
||||
* @return mixed
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function castValue($value, $type) {
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$type = strtolower($type);
|
||||
switch ($type) {
|
||||
case 'string':
|
||||
case 'str':
|
||||
case 's':
|
||||
return $value;
|
||||
|
||||
case 'integer':
|
||||
case 'int':
|
||||
case 'i':
|
||||
if (!is_numeric($value)) {
|
||||
throw new \InvalidArgumentException('Non-numeric value specified');
|
||||
}
|
||||
return (int) $value;
|
||||
|
||||
case 'double':
|
||||
case 'd':
|
||||
case 'float':
|
||||
case 'f':
|
||||
if (!is_numeric($value)) {
|
||||
throw new \InvalidArgumentException('Non-numeric value specified');
|
||||
}
|
||||
return (double) $value;
|
||||
|
||||
case 'boolean':
|
||||
case 'bool':
|
||||
case 'b':
|
||||
$value = strtolower($value);
|
||||
switch ($value) {
|
||||
case 'true':
|
||||
case 'yes':
|
||||
case 'y':
|
||||
case '1':
|
||||
return true;
|
||||
|
||||
case 'false':
|
||||
case 'no':
|
||||
case 'n':
|
||||
case '0':
|
||||
return false;
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException('Unable to parse value as boolean');
|
||||
}
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException('Invalid type');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $configNames
|
||||
* @param mixed $existingValues
|
||||
* @param mixed $value
|
||||
* @param bool $updateOnly
|
||||
* @return array merged value
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
protected function mergeArrayValue(array $configNames, $existingValues, $value, $updateOnly) {
|
||||
$configName = array_shift($configNames);
|
||||
if (!is_array($existingValues)) {
|
||||
$existingValues = [];
|
||||
}
|
||||
if (!empty($configNames)) {
|
||||
if (isset($existingValues[$configName])) {
|
||||
$existingValue = $existingValues[$configName];
|
||||
} else {
|
||||
$existingValue = [];
|
||||
}
|
||||
$existingValues[$configName] = $this->mergeArrayValue($configNames, $existingValue, $value, $updateOnly);
|
||||
} else {
|
||||
if (!isset($existingValues[$configName]) && $updateOnly) {
|
||||
throw new \UnexpectedValueException('Config parameter does not exist');
|
||||
}
|
||||
$existingValues[$configName] = $value;
|
||||
}
|
||||
return $existingValues;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -53,63 +53,133 @@ class SetConfigTest extends TestCase {
|
|||
|
||||
public function setData() {
|
||||
return [
|
||||
[
|
||||
'name',
|
||||
'newvalue',
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
'info',
|
||||
],
|
||||
[
|
||||
'name',
|
||||
'newvalue',
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
'comment',
|
||||
],
|
||||
[['name'], 'newvalue', null, 'newvalue'],
|
||||
[['a', 'b', 'c'], 'foobar', null, ['b' => ['c' => 'foobar']]],
|
||||
[['a', 'b', 'c'], 'foobar', ['b' => ['d' => 'barfoo']], ['b' => ['d' => 'barfoo', 'c' => 'foobar']]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider setData
|
||||
*
|
||||
* @param string $configName
|
||||
* @param mixed $newValue
|
||||
* @param bool $configExists
|
||||
* @param bool $updateOnly
|
||||
* @param bool $updated
|
||||
* @param string $expectedMessage
|
||||
* @param array $configNames
|
||||
* @param string $newValue
|
||||
* @param mixed $existingData
|
||||
* @param mixed $expectedValue
|
||||
*/
|
||||
public function testSet($configName, $newValue, $configExists, $updateOnly, $updated, $expectedMessage) {
|
||||
public function testSet($configNames, $newValue, $existingData, $expectedValue) {
|
||||
$this->systemConfig->expects($this->once())
|
||||
->method('getKeys')
|
||||
->willReturn($configExists ? [$configName] : []);
|
||||
|
||||
if ($updated) {
|
||||
$this->systemConfig->expects($this->once())
|
||||
->method('setValue')
|
||||
->with($configName, $newValue);
|
||||
}
|
||||
->method('setValue')
|
||||
->with($configNames[0], $expectedValue);
|
||||
$this->systemConfig->method('getValue')
|
||||
->with($configNames[0])
|
||||
->willReturn($existingData);
|
||||
|
||||
$this->consoleInput->expects($this->once())
|
||||
->method('getArgument')
|
||||
->with('name')
|
||||
->willReturn($configName);
|
||||
$this->consoleInput->expects($this->any())
|
||||
->method('getOption')
|
||||
->with('value')
|
||||
->willReturn($newValue);
|
||||
$this->consoleInput->expects($this->any())
|
||||
->method('hasParameterOption')
|
||||
->with('--update-only')
|
||||
->willReturn($updateOnly);
|
||||
|
||||
$this->consoleOutput->expects($this->any())
|
||||
->method('writeln')
|
||||
->with($this->stringContains($expectedMessage));
|
||||
->willReturn($configNames);
|
||||
$this->consoleInput->method('getOption')
|
||||
->will($this->returnValueMap([
|
||||
['value', $newValue],
|
||||
['type', 'string'],
|
||||
]));
|
||||
|
||||
$this->invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
|
||||
}
|
||||
|
||||
public function setUpdateOnlyProvider() {
|
||||
return [
|
||||
[['name'], null],
|
||||
[['a', 'b', 'c'], null],
|
||||
[['a', 'b', 'c'], ['b' => 'foobar']],
|
||||
[['a', 'b', 'c'], ['b' => ['d' => 'foobar']]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider setUpdateOnlyProvider
|
||||
* @expectedException \UnexpectedValueException
|
||||
*/
|
||||
public function testSetUpdateOnly($configNames, $existingData) {
|
||||
$this->systemConfig->expects($this->never())
|
||||
->method('setValue');
|
||||
$this->systemConfig->method('getValue')
|
||||
->with($configNames[0])
|
||||
->willReturn($existingData);
|
||||
$this->systemConfig->method('getKeys')
|
||||
->willReturn($existingData ? $configNames[0] : []);
|
||||
|
||||
$this->consoleInput->expects($this->once())
|
||||
->method('getArgument')
|
||||
->with('name')
|
||||
->willReturn($configNames);
|
||||
$this->consoleInput->method('getOption')
|
||||
->will($this->returnValueMap([
|
||||
['value', 'foobar'],
|
||||
['type', 'string'],
|
||||
['update-only', true],
|
||||
]));
|
||||
|
||||
$this->invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
|
||||
}
|
||||
|
||||
public function castValueProvider() {
|
||||
return [
|
||||
[null, 'integer', null],
|
||||
[null, 'string', null],
|
||||
|
||||
['abc', 'string', 'abc'],
|
||||
['dEF', 'str', 'dEF'],
|
||||
['123', 's', '123'],
|
||||
|
||||
['123', 'integer', 123],
|
||||
['456', 'int', 456],
|
||||
['-666', 'i', -666],
|
||||
|
||||
// only use powers of 2 to avoid precision errors
|
||||
['2', 'double', 2.0],
|
||||
['0.25', 'd', 0.25],
|
||||
['0.5', 'float', 0.5],
|
||||
['0.125', 'f', 0.125],
|
||||
|
||||
['true', 'boolean', true],
|
||||
['false', 'bool', false],
|
||||
['yes', 'b', true],
|
||||
['no', 'b', false],
|
||||
['y', 'b', true],
|
||||
['n', 'b', false],
|
||||
['1', 'b', true],
|
||||
['0', 'b', false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider castValueProvider
|
||||
*/
|
||||
public function testCastValue($value, $type, $expectedValue) {
|
||||
$this->assertSame($expectedValue,
|
||||
$this->invokePrivate($this->command, 'castValue', [$value, $type])
|
||||
);
|
||||
}
|
||||
|
||||
public function castValueInvalidProvider() {
|
||||
return [
|
||||
['123', 'foobar'],
|
||||
|
||||
['abc', 'integer'],
|
||||
['76ggg', 'double'],
|
||||
['true', 'float'],
|
||||
['foobar', 'boolean'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider castValueInvalidProvider
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testCastValueInvalid($value, $type) {
|
||||
$this->invokePrivate($this->command, 'castValue', [$value, $type]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue