You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
5.7 KiB

10 years ago
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Joas Schilling <coding@schilljs.com>
  6. * @author Morris Jobke <hey@morrisjobke.de>
  7. * @author Robin McCorkell <robin@mccorkell.me.uk>
  8. *
  9. * @license AGPL-3.0
  10. *
  11. * This code is free software: you can redistribute it and/or modify
  12. * it under the terms of the GNU Affero General Public License, version 3,
  13. * as published by the Free Software Foundation.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Affero General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Affero General Public License, version 3,
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>
  22. *
  23. */
  24. namespace OC\Core\Command\Config\System;
  25. use OC\SystemConfig;
  26. use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
  27. use Symfony\Component\Console\Input\InputArgument;
  28. use Symfony\Component\Console\Input\InputInterface;
  29. use Symfony\Component\Console\Input\InputOption;
  30. use Symfony\Component\Console\Output\OutputInterface;
  31. class SetConfig extends Base {
  32. /** * @var SystemConfig */
  33. protected $systemConfig;
  34. /**
  35. * @param SystemConfig $systemConfig
  36. */
  37. public function __construct(SystemConfig $systemConfig) {
  38. parent::__construct();
  39. $this->systemConfig = $systemConfig;
  40. }
  41. protected function configure() {
  42. parent::configure();
  43. $this
  44. ->setName('config:system:set')
  45. ->setDescription('Set a system config value')
  46. ->addArgument(
  47. 'name',
  48. InputArgument::REQUIRED | InputArgument::IS_ARRAY,
  49. 'Name of the config parameter, specify multiple for array parameter'
  50. )
  51. ->addOption(
  52. 'type',
  53. null,
  54. InputOption::VALUE_REQUIRED,
  55. 'Value type [string, integer, double, boolean]',
  56. 'string'
  57. )
  58. ->addOption(
  59. 'value',
  60. null,
  61. InputOption::VALUE_REQUIRED,
  62. 'The new value of the config'
  63. )
  64. ->addOption(
  65. 'update-only',
  66. null,
  67. InputOption::VALUE_NONE,
  68. 'Only updates the value, if it is not set before, it is not being added'
  69. )
  70. ;
  71. }
  72. protected function execute(InputInterface $input, OutputInterface $output) {
  73. $configNames = $input->getArgument('name');
  74. $configName = $configNames[0];
  75. $configValue = $this->castValue($input->getOption('value'), $input->getOption('type'));
  76. $updateOnly = $input->getOption('update-only');
  77. if (count($configNames) > 1) {
  78. $existingValue = $this->systemConfig->getValue($configName);
  79. $newValue = $this->mergeArrayValue(
  80. array_slice($configNames, 1), $existingValue, $configValue['value'], $updateOnly
  81. );
  82. $this->systemConfig->setValue($configName, $newValue);
  83. } else {
  84. if ($updateOnly && !in_array($configName, $this->systemConfig->getKeys(), true)) {
  85. throw new \UnexpectedValueException('Config parameter does not exist');
  86. }
  87. $this->systemConfig->setValue($configName, $configValue['value']);
  88. }
  89. $output->writeln('<info>System config value ' . implode(' => ', $configNames) . ' set to ' . $configValue['readable-value'] . '</info>');
  90. return 0;
  91. }
  92. /**
  93. * @param string $value
  94. * @param string $type
  95. * @return mixed
  96. * @throws \InvalidArgumentException
  97. */
  98. protected function castValue($value, $type) {
  99. switch ($type) {
  100. case 'integer':
  101. case 'int':
  102. if (!is_numeric($value)) {
  103. throw new \InvalidArgumentException('Non-numeric value specified');
  104. }
  105. return [
  106. 'value' => (int) $value,
  107. 'readable-value' => 'integer ' . (int) $value,
  108. ];
  109. case 'double':
  110. case 'float':
  111. if (!is_numeric($value)) {
  112. throw new \InvalidArgumentException('Non-numeric value specified');
  113. }
  114. return [
  115. 'value' => (double) $value,
  116. 'readable-value' => 'double ' . (double) $value,
  117. ];
  118. case 'boolean':
  119. case 'bool':
  120. $value = strtolower($value);
  121. switch ($value) {
  122. case 'true':
  123. return [
  124. 'value' => true,
  125. 'readable-value' => 'boolean ' . $value,
  126. ];
  127. case 'false':
  128. return [
  129. 'value' => false,
  130. 'readable-value' => 'boolean ' . $value,
  131. ];
  132. default:
  133. throw new \InvalidArgumentException('Unable to parse value as boolean');
  134. }
  135. // no break
  136. case 'null':
  137. return [
  138. 'value' => null,
  139. 'readable-value' => 'null',
  140. ];
  141. case 'string':
  142. $value = (string) $value;
  143. return [
  144. 'value' => $value,
  145. 'readable-value' => ($value === '') ? 'empty string' : 'string ' . $value,
  146. ];
  147. default:
  148. throw new \InvalidArgumentException('Invalid type');
  149. }
  150. }
  151. /**
  152. * @param array $configNames
  153. * @param mixed $existingValues
  154. * @param mixed $value
  155. * @param bool $updateOnly
  156. * @return array merged value
  157. * @throws \UnexpectedValueException
  158. */
  159. protected function mergeArrayValue(array $configNames, $existingValues, $value, $updateOnly) {
  160. $configName = array_shift($configNames);
  161. if (!is_array($existingValues)) {
  162. $existingValues = [];
  163. }
  164. if (!empty($configNames)) {
  165. if (isset($existingValues[$configName])) {
  166. $existingValue = $existingValues[$configName];
  167. } else {
  168. $existingValue = [];
  169. }
  170. $existingValues[$configName] = $this->mergeArrayValue($configNames, $existingValue, $value, $updateOnly);
  171. } else {
  172. if (!isset($existingValues[$configName]) && $updateOnly) {
  173. throw new \UnexpectedValueException('Config parameter does not exist');
  174. }
  175. $existingValues[$configName] = $value;
  176. }
  177. return $existingValues;
  178. }
  179. /**
  180. * @param string $optionName
  181. * @param CompletionContext $context
  182. * @return string[]
  183. */
  184. public function completeOptionValues($optionName, CompletionContext $context) {
  185. if ($optionName === 'type') {
  186. return ['string', 'integer', 'double', 'boolean'];
  187. }
  188. return parent::completeOptionValues($optionName, $context);
  189. }
  190. }