Merge pull request #16368 from owncloud/occ-config-commands

Add "occ config:*" to manage config values
This commit is contained in:
Vincent Petry 2015-07-07 14:49:31 +02:00
commit d3e26a3127
20 changed files with 2203 additions and 19 deletions

View File

@ -43,8 +43,9 @@ class Base extends Command {
* @param InputInterface $input
* @param OutputInterface $output
* @param array $items
* @param string $prefix
*/
protected function writeArrayInOutputFormat(InputInterface $input, OutputInterface $output, $items) {
protected function writeArrayInOutputFormat(InputInterface $input, OutputInterface $output, $items, $prefix = ' - ') {
switch ($input->getOption('output')) {
case 'json':
$output->writeln(json_encode($items));
@ -54,28 +55,57 @@ class Base extends Command {
break;
default:
foreach ($items as $key => $item) {
if (is_array($item)) {
$output->writeln($prefix . $key . ':');
$this->writeArrayInOutputFormat($input, $output, $item, ' ' . $prefix);
continue;
}
if (!is_int($key)) {
$value = $this->valueToString($item);
if (!is_null($value)) {
$output->writeln(' - ' . $key . ': ' . $value);
$output->writeln($prefix . $key . ': ' . $value);
} else {
$output->writeln(' - ' . $key);
$output->writeln($prefix . $key);
}
} else {
$output->writeln(' - ' . $this->valueToString($item));
$output->writeln($prefix . $this->valueToString($item));
}
}
break;
}
}
protected function valueToString($value) {
/**
* @param InputInterface $input
* @param OutputInterface $output
* @param mixed $item
*/
protected function writeMixedInOutputFormat(InputInterface $input, OutputInterface $output, $item) {
if (is_array($item)) {
$this->writeArrayInOutputFormat($input, $output, $item, '');
return;
}
switch ($input->getOption('output')) {
case 'json':
$output->writeln(json_encode($item));
break;
case 'json_pretty':
$output->writeln(json_encode($item, JSON_PRETTY_PRINT));
break;
default:
$output->writeln($this->valueToString($item, false));
break;
}
}
protected function valueToString($value, $returnNull = true) {
if ($value === false) {
return 'false';
} else if ($value === true) {
return 'true';
} else if ($value === null) {
null;
return ($returnNull) ? null : 'null';
} else {
return $value;
}

View File

@ -0,0 +1,81 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Core\Command\Config\App;
use OC\Core\Command\Base;
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 DeleteConfig extends Base {
/** * @var IConfig */
protected $config;
/**
* @param IConfig $config
*/
public function __construct(IConfig $config) {
parent::__construct();
$this->config = $config;
}
protected function configure() {
parent::configure();
$this
->setName('config:app:delete')
->setDescription('Delete an app config value')
->addArgument(
'app',
InputArgument::REQUIRED,
'Name of the app'
)
->addArgument(
'name',
InputArgument::REQUIRED,
'Name of the config to delete'
)
->addOption(
'error-if-not-exists',
null,
InputOption::VALUE_NONE,
'Checks whether the config exists before deleting it'
)
;
}
protected function execute(InputInterface $input, OutputInterface $output) {
$appName = $input->getArgument('app');
$configName = $input->getArgument('name');
if ($input->hasParameterOption('--error-if-not-exists') && !in_array($configName, $this->config->getAppKeys($appName))) {
$output->writeln('<error>Config ' . $configName . ' could not be deleted because it did not exist</error>');
return 1;
}
$this->config->deleteAppValue($appName, $configName);
$output->writeln('<info>System config value ' . $configName . ' deleted</info>');
return 0;
}
}

View File

@ -0,0 +1,93 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Core\Command\Config\App;
use OC\Core\Command\Base;
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 GetConfig extends Base {
/** * @var IConfig */
protected $config;
/**
* @param IConfig $config
*/
public function __construct(IConfig $config) {
parent::__construct();
$this->config = $config;
}
protected function configure() {
parent::configure();
$this
->setName('config:app:get')
->setDescription('Get an app config value')
->addArgument(
'app',
InputArgument::REQUIRED,
'Name of the app'
)
->addArgument(
'name',
InputArgument::REQUIRED,
'Name of the config to get'
)
->addOption(
'default-value',
null,
InputOption::VALUE_OPTIONAL,
'If no default value is set and the config does not exist, the command will exit with 1'
)
;
}
/**
* Executes the current command.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
* @return null|int null or 0 if everything went fine, or an error code
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$appName = $input->getArgument('app');
$configName = $input->getArgument('name');
$defaultValue = $input->getOption('default-value');
if (!in_array($configName, $this->config->getAppKeys($appName)) && !$input->hasParameterOption('--default-value')) {
return 1;
}
if (!in_array($configName, $this->config->getAppKeys($appName))) {
$configValue = $defaultValue;
} else {
$configValue = $this->config->getAppValue($appName, $configName);
}
$this->writeMixedInOutputFormat($input, $output, $configValue);
return 0;
}
}

View File

@ -0,0 +1,89 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Core\Command\Config\App;
use OC\Core\Command\Base;
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 SetConfig extends Base {
/** * @var IConfig */
protected $config;
/**
* @param IConfig $config
*/
public function __construct(IConfig $config) {
parent::__construct();
$this->config = $config;
}
protected function configure() {
parent::configure();
$this
->setName('config:app:set')
->setDescription('Set an app config value')
->addArgument(
'app',
InputArgument::REQUIRED,
'Name of the app'
)
->addArgument(
'name',
InputArgument::REQUIRED,
'Name of the config to set'
)
->addOption(
'value',
null,
InputOption::VALUE_REQUIRED,
'The new value of the config'
)
->addOption(
'update-only',
null,
InputOption::VALUE_NONE,
'Only updates the value, if it is not set before, it is not being added'
)
;
}
protected function execute(InputInterface $input, OutputInterface $output) {
$appName = $input->getArgument('app');
$configName = $input->getArgument('name');
if (!in_array($configName, $this->config->getAppKeys($appName)) && $input->hasParameterOption('--update-only')) {
$output->writeln('<comment>Value not updated, as it has not been set before.</comment>');
return 1;
}
$configValue = $input->getOption('value');
$this->config->setAppValue($appName, $configName, $configValue);
$output->writeln('<info>Config value ' . $configName . ' for app ' . $appName . ' set to ' . $configValue . '</info>');
return 0;
}
}

View File

@ -0,0 +1,195 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Core\Command\Config;
use OCP\IConfig;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class Import extends Command {
protected $validRootKeys = ['system', 'apps'];
/** @var IConfig */
protected $config;
/**
* @param IConfig $config
*/
public function __construct(IConfig $config) {
parent::__construct();
$this->config = $config;
}
protected function configure() {
$this
->setName('config:import')
->setDescription('Import a list of configs')
->addArgument(
'file',
InputArgument::OPTIONAL,
'File with the json array to import'
)
;
}
protected function execute(InputInterface $input, OutputInterface $output) {
$importFile = $input->getArgument('file');
if ($importFile !== null) {
$content = $this->getArrayFromFile($importFile);
} else {
$content = $this->getArrayFromStdin();
}
try {
$configs = $this->validateFileContent($content);
} catch (\UnexpectedValueException $e) {
$output->writeln('<error>' . $e->getMessage(). '</error>');
return;
}
if (!empty($configs['system'])) {
$this->config->setSystemValues($configs['system']);
}
if (!empty($configs['apps'])) {
foreach ($configs['apps'] as $app => $appConfigs) {
foreach ($appConfigs as $key => $value) {
if ($value === null) {
$this->config->deleteAppValue($app, $key);
} else {
$this->config->setAppValue($app, $key, $value);
}
}
}
}
$output->writeln('<info>Config successfully imported from: ' . $importFile . '</info>');
}
/**
* Get the content from stdin ("config:import < file.json")
*
* @return string
*/
protected function getArrayFromStdin() {
// Read from stdin. stream_set_blocking is used to prevent blocking
// when nothing is passed via stdin.
stream_set_blocking(STDIN, 0);
$content = file_get_contents('php://stdin');
stream_set_blocking(STDIN, 1);
return $content;
}
/**
* Get the content of the specified file ("config:import file.json")
*
* @param string $importFile
* @return string
*/
protected function getArrayFromFile($importFile) {
$content = file_get_contents($importFile);
return $content;
}
/**
* @param string $content
* @return array
* @throws \UnexpectedValueException when the array is invalid
*/
protected function validateFileContent($content) {
$decodedContent = json_decode($content, true);
if (!is_array($decodedContent) || empty($decodedContent)) {
throw new \UnexpectedValueException('The file must contain a valid json array');
}
$this->validateArray($decodedContent);
return $decodedContent;
}
/**
* Validates that the array only contains `system` and `apps`
*
* @param array $array
*/
protected function validateArray($array) {
$arrayKeys = array_keys($array);
$additionalKeys = array_diff($arrayKeys, $this->validRootKeys);
$commonKeys = array_intersect($arrayKeys, $this->validRootKeys);
if (!empty($additionalKeys)) {
throw new \UnexpectedValueException('Found invalid entries in root: ' . implode(', ', $additionalKeys));
}
if (empty($commonKeys)) {
throw new \UnexpectedValueException('At least one key of the following is expected: ' . implode(', ', $this->validRootKeys));
}
if (isset($array['system'])) {
if (is_array($array['system'])) {
foreach ($array['system'] as $name => $value) {
$this->checkTypeRecursively($value, $name);
}
} else {
throw new \UnexpectedValueException('The system config array is not an array');
}
}
if (isset($array['apps'])) {
if (is_array($array['apps'])) {
$this->validateAppsArray($array['apps']);
} else {
throw new \UnexpectedValueException('The apps config array is not an array');
}
}
}
/**
* @param mixed $configValue
* @param string $configName
*/
protected function checkTypeRecursively($configValue, $configName) {
if (!is_array($configValue) && !is_bool($configValue) && !is_int($configValue) && !is_string($configValue) && !is_null($configValue)) {
throw new \UnexpectedValueException('Invalid system config value for "' . $configName . '". Only arrays, bools, integers, strings and null (delete) are allowed.');
}
if (is_array($configValue)) {
foreach ($configValue as $key => $value) {
$this->checkTypeRecursively($value, $configName);
}
}
}
/**
* Validates that app configs are only integers and strings
*
* @param array $array
*/
protected function validateAppsArray($array) {
foreach ($array as $app => $configs) {
foreach ($configs as $name => $value) {
if (!is_int($value) && !is_string($value) && !is_null($value)) {
throw new \UnexpectedValueException('Invalid app config value for "' . $app . '":"' . $name . '". Only integers, strings and null (delete) are allowed.');
}
}
}
}
}

View File

@ -0,0 +1,141 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Core\Command\Config;
use OC\Core\Command\Base;
use OC\SystemConfig;
use OCP\IAppConfig;
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 ListConfigs extends Base {
/** @var array */
protected $sensitiveValues = [
'dbpassword',
'dbuser',
'mail_smtpname',
'mail_smtppassword',
'passwordsalt',
'secret',
];
/** * @var SystemConfig */
protected $systemConfig;
/** @var IAppConfig */
protected $appConfig;
/**
* @param SystemConfig $systemConfig
* @param IAppConfig $appConfig
*/
public function __construct(SystemConfig $systemConfig, IAppConfig $appConfig) {
parent::__construct();
$this->systemConfig = $systemConfig;
$this->appConfig = $appConfig;
}
protected function configure() {
parent::configure();
$this
->setName('config:list')
->setDescription('List all configs')
->addArgument(
'app',
InputArgument::OPTIONAL,
'Name of the app ("system" to get the config.php values, "all" for all apps and system)',
'all'
)
->addOption(
'private',
null,
InputOption::VALUE_NONE,
'Use this option when you want to include sensitive configs like passwords, salts, ...'
)
;
}
protected function execute(InputInterface $input, OutputInterface $output) {
$app = $input->getArgument('app');
$noSensitiveValues = !$input->getOption('private');
if ($noSensitiveValues && !$input->hasParameterOption('--output')) {
// If you post this publicly we prefer the json format
$input->setOption('output', 'json_pretty');
}
switch ($app) {
case 'system':
$configs = [
'system' => $this->getSystemConfigs($noSensitiveValues),
];
break;
case 'all':
$apps = $this->appConfig->getApps();
$configs = [
'system' => $this->getSystemConfigs($noSensitiveValues),
'apps' => [],
];
foreach ($apps as $appName) {
$configs['apps'][$appName] = $this->appConfig->getValues($appName, false);
}
break;
default:
$configs = [
'apps' => [
$app => $this->appConfig->getValues($app, false),
],
];
}
$this->writeArrayInOutputFormat($input, $output, $configs);
}
/**
* Get the system configs
*
* @param bool $noSensitiveValues
* @return array
*/
protected function getSystemConfigs($noSensitiveValues) {
$keys = $this->systemConfig->getKeys();
$configs = [];
foreach ($keys as $key) {
if ($noSensitiveValues && in_array($key, $this->sensitiveValues)) {
continue;
}
$value = $this->systemConfig->getValue($key, serialize(null));
if ($value !== 'N;') {
$configs[$key] = $value;
}
}
return $configs;
}
}

View File

@ -0,0 +1,75 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Core\Command\Config\System;
use OC\Core\Command\Base;
use OC\SystemConfig;
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 DeleteConfig extends Base {
/** * @var SystemConfig */
protected $systemConfig;
/**
* @param SystemConfig $systemConfig
*/
public function __construct(SystemConfig $systemConfig) {
parent::__construct();
$this->systemConfig = $systemConfig;
}
protected function configure() {
parent::configure();
$this
->setName('config:system:delete')
->setDescription('Delete a system config value')
->addArgument(
'name',
InputArgument::REQUIRED,
'Name of the config to delete'
)
->addOption(
'error-if-not-exists',
null,
InputOption::VALUE_NONE,
'Checks whether the config exists before deleting it'
)
;
}
protected function execute(InputInterface $input, OutputInterface $output) {
$configName = $input->getArgument('name');
if ($input->hasParameterOption('--error-if-not-exists') && !in_array($configName, $this->systemConfig->getKeys())) {
$output->writeln('<error>Config ' . $configName . ' could not be deleted because it did not exist</error>');
return 1;
}
$this->systemConfig->deleteValue($configName);
$output->writeln('<info>System config value ' . $configName . ' deleted</info>');
return 0;
}
}

View File

@ -0,0 +1,87 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Core\Command\Config\System;
use OC\Core\Command\Base;
use OC\SystemConfig;
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 GetConfig extends Base {
/** * @var SystemConfig */
protected $systemConfig;
/**
* @param SystemConfig $systemConfig
*/
public function __construct(SystemConfig $systemConfig) {
parent::__construct();
$this->systemConfig = $systemConfig;
}
protected function configure() {
parent::configure();
$this
->setName('config:system:get')
->setDescription('Get a system config value')
->addArgument(
'name',
InputArgument::REQUIRED,
'Name of the config to get'
)
->addOption(
'default-value',
null,
InputOption::VALUE_OPTIONAL,
'If no default value is set and the config does not exist, the command will exit with 1'
)
;
}
/**
* Executes the current command.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
* @return null|int null or 0 if everything went fine, or an error code
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$configName = $input->getArgument('name');
$defaultValue = $input->getOption('default-value');
if (!in_array($configName, $this->systemConfig->getKeys()) && !$input->hasParameterOption('--default-value')) {
return 1;
}
if (!in_array($configName, $this->systemConfig->getKeys())) {
$configValue = $defaultValue;
} else {
$configValue = $this->systemConfig->getValue($configName);
}
$this->writeMixedInOutputFormat($input, $output, $configValue);
return 0;
}
}

View File

@ -0,0 +1,82 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Core\Command\Config\System;
use OC\Core\Command\Base;
use OC\SystemConfig;
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 SetConfig extends Base {
/** * @var SystemConfig */
protected $systemConfig;
/**
* @param SystemConfig $systemConfig
*/
public function __construct(SystemConfig $systemConfig) {
parent::__construct();
$this->systemConfig = $systemConfig;
}
protected function configure() {
parent::configure();
$this
->setName('config:system:set')
->setDescription('Set a system config value')
->addArgument(
'name',
InputArgument::REQUIRED,
'Name of the config to set'
)
->addOption(
'value',
null,
InputOption::VALUE_REQUIRED,
'The new value of the config'
)
->addOption(
'update-only',
null,
InputOption::VALUE_NONE,
'Only updates the value, if it is not set before, it is not being added'
)
;
}
protected function execute(InputInterface $input, OutputInterface $output) {
$configName = $input->getArgument('name');
if (!in_array($configName, $this->systemConfig->getKeys()) && $input->hasParameterOption('--update-only')) {
$output->writeln('<comment>Value not updated, as it has not been set before.</comment>');
return 1;
}
$configValue = $input->getOption('value');
$this->systemConfig->setValue($configName, $configValue);
$output->writeln('<info>System config value ' . $configName . ' set to ' . $configValue . '</info>');
return 0;
}
}

View File

@ -32,31 +32,44 @@ $application->add(new OC\Core\Command\App\CheckCode());
$application->add(new OC\Core\Command\L10n\CreateJs());
if (\OC::$server->getConfig()->getSystemValue('installed', false)) {
$repair = new \OC\Repair(\OC\Repair::getRepairSteps());
$application->add(new OC\Core\Command\Db\GenerateChangeScript());
$application->add(new OC\Core\Command\Db\ConvertType(\OC::$server->getConfig(), new \OC\DB\ConnectionFactory()));
$application->add(new OC\Core\Command\Upgrade(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Maintenance\SingleUser());
$application->add(new OC\Core\Command\Maintenance\Mode(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\App\Disable());
$application->add(new OC\Core\Command\App\Enable());
$application->add(new OC\Core\Command\App\ListApps());
$application->add(new OC\Core\Command\Maintenance\Repair($repair, \OC::$server->getConfig()));
$application->add(new OC\Core\Command\User\Add(\OC::$server->getUserManager(), \OC::$server->getGroupManager()));
$application->add(new OC\Core\Command\User\Delete(\OC::$server->getUserManager()));
$application->add(new OC\Core\Command\User\LastSeen(\OC::$server->getUserManager()));
$application->add(new OC\Core\Command\User\Report(\OC::$server->getUserManager()));
$application->add(new OC\Core\Command\User\ResetPassword(\OC::$server->getUserManager()));
$application->add(new OC\Core\Command\Background\Cron(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Background\WebCron(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Background\Ajax(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Config\App\DeleteConfig(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Config\App\GetConfig(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Config\App\SetConfig(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Config\Import(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Config\ListConfigs(\OC::$server->getSystemConfig(), \OC::$server->getAppConfig()));
$application->add(new OC\Core\Command\Config\System\DeleteConfig(\OC::$server->getSystemConfig()));
$application->add(new OC\Core\Command\Config\System\GetConfig(\OC::$server->getSystemConfig()));
$application->add(new OC\Core\Command\Config\System\SetConfig(\OC::$server->getSystemConfig()));
$application->add(new OC\Core\Command\Db\GenerateChangeScript());
$application->add(new OC\Core\Command\Db\ConvertType(\OC::$server->getConfig(), new \OC\DB\ConnectionFactory()));
$application->add(new OC\Core\Command\Encryption\Disable(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Encryption\Enable(\OC::$server->getConfig(), \OC::$server->getEncryptionManager()));
$application->add(new OC\Core\Command\Encryption\ListModules(\OC::$server->getEncryptionManager()));
$application->add(new OC\Core\Command\Encryption\SetDefaultModule(\OC::$server->getEncryptionManager()));
$application->add(new OC\Core\Command\Encryption\Status(\OC::$server->getEncryptionManager()));
$application->add(new OC\Core\Command\Maintenance\MimeTypesJS());
$application->add(new OC\Core\Command\Maintenance\Mode(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Maintenance\Repair(new \OC\Repair(\OC\Repair::getRepairSteps()), \OC::$server->getConfig()));
$application->add(new OC\Core\Command\Maintenance\SingleUser());
$application->add(new OC\Core\Command\Upgrade(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\User\Add(\OC::$server->getUserManager(), \OC::$server->getGroupManager()));
$application->add(new OC\Core\Command\User\Delete(\OC::$server->getUserManager()));
$application->add(new OC\Core\Command\User\LastSeen(\OC::$server->getUserManager()));
$application->add(new OC\Core\Command\User\Report(\OC::$server->getUserManager()));
$application->add(new OC\Core\Command\User\ResetPassword(\OC::$server->getUserManager()));
} else {
$application->add(new OC\Core\Command\Maintenance\Install(\OC::$server->getConfig()));
}

View File

@ -33,6 +33,12 @@ from within your ownCloud installation folder
**The content of config/config.php:**
```
If you have access to your command line run e.g.:
sudo -u www-data php occ config:list system --public
from within your ownCloud installation folder
or
Insert your config.php content here
(Without the database password, passwordsalt and secret)
```

View File

@ -28,6 +28,14 @@ namespace OC;
* fixes cyclic DI: AllConfig needs AppConfig needs Database needs AllConfig
*/
class SystemConfig {
/**
* Lists all available config keys
* @return array an array of key names
*/
public function getKeys() {
return \OC_Config::getKeys();
}
/**
* Sets a new system wide value
*

View File

@ -0,0 +1,123 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace Tests\Core\Command\Config\App;
use OC\Core\Command\Config\App\DeleteConfig;
use Test\TestCase;
class DeleteConfigTest extends TestCase {
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $config;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $consoleInput;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $consoleOutput;
/** @var \Symfony\Component\Console\Command\Command */
protected $command;
protected function setUp() {
parent::setUp();
$config = $this->config = $this->getMockBuilder('OCP\IConfig')
->disableOriginalConstructor()
->getMock();
$this->consoleInput = $this->getMock('Symfony\Component\Console\Input\InputInterface');
$this->consoleOutput = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
/** @var \OCP\IConfig $config */
$this->command = new DeleteConfig($config);
}
public function deleteData() {
return [
[
'name',
true,
true,
0,
'info',
],
[
'name',
true,
false,
0,
'info',
],
[
'name',
false,
false,
0,
'info',
],
[
'name',
false,
true,
1,
'error',
],
];
}
/**
* @dataProvider deleteData
*
* @param string $configName
* @param bool $configExists
* @param bool $checkIfExists
* @param int $expectedReturn
* @param string $expectedMessage
*/
public function testDelete($configName, $configExists, $checkIfExists, $expectedReturn, $expectedMessage) {
$this->config->expects(($checkIfExists) ? $this->once() : $this->never())
->method('getAppKeys')
->with('app-name')
->willReturn($configExists ? [$configName] : []);
$this->config->expects(($expectedReturn === 0) ? $this->once() : $this->never())
->method('deleteAppValue')
->with('app-name', $configName);
$this->consoleInput->expects($this->exactly(2))
->method('getArgument')
->willReturnMap([
['app', 'app-name'],
['name', $configName],
]);
$this->consoleInput->expects($this->any())
->method('hasParameterOption')
->with('--error-if-not-exists')
->willReturn($checkIfExists);
$this->consoleOutput->expects($this->any())
->method('writeln')
->with($this->stringContains($expectedMessage));
$this->assertSame($expectedReturn, $this->invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]));
}
}

View File

@ -0,0 +1,163 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace Tests\Core\Command\Config\App;
use OC\Core\Command\Config\App\GetConfig;
use Test\TestCase;
class GetConfigTest extends TestCase {
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $config;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $consoleInput;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $consoleOutput;
/** @var \Symfony\Component\Console\Command\Command */
protected $command;
protected function setUp() {
parent::setUp();
$config = $this->config = $this->getMockBuilder('OCP\IConfig')
->disableOriginalConstructor()
->getMock();
$this->consoleInput = $this->getMock('Symfony\Component\Console\Input\InputInterface');
$this->consoleOutput = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
/** @var \OCP\IConfig $config */
$this->command = new GetConfig($config);
}
public function getData() {
return [
// String output as json
['name', 'newvalue', true, null, false, 'json', 0, json_encode('newvalue')],
// String output as plain text
['name', 'newvalue', true, null, false, 'plain', 0, 'newvalue'],
// String falling back to default output as json
['name', null, false, 'newvalue', true, 'json', 0, json_encode('newvalue')],
// String falling back without default: error
['name', null, false, null, false, 'json', 1, null],
// Int "0" output as json/plain
['name', 0, true, null, false, 'json', 0, json_encode(0)],
['name', 0, true, null, false, 'plain', 0, '0'],
// Int "1" output as json/plain
['name', 1, true, null, false, 'json', 0, json_encode(1)],
['name', 1, true, null, false, 'plain', 0, '1'],
// Bool "true" output as json/plain
['name', true, true, null, false, 'json', 0, json_encode(true)],
['name', true, true, null, false, 'plain', 0, 'true'],
// Bool "false" output as json/plain
['name', false, true, null, false, 'json', 0, json_encode(false)],
['name', false, true, null, false, 'plain', 0, 'false'],
// Null output as json/plain
['name', null, true, null, false, 'json', 0, json_encode(null)],
['name', null, true, null, false, 'plain', 0, 'null'],
// Array output as json/plain
['name', ['a', 'b'], true, null, false, 'json', 0, json_encode(['a', 'b'])],
['name', ['a', 'b'], true, null, false, 'plain', 0, "a\nb"],
// Key array output as json/plain
['name', [0 => 'a', 1 => 'b'], true, null, false, 'json', 0, json_encode(['a', 'b'])],
['name', [0 => 'a', 1 => 'b'], true, null, false, 'plain', 0, "a\nb"],
// Associative array output as json/plain
['name', ['a' => 1, 'b' => 2], true, null, false, 'json', 0, json_encode(['a' => 1, 'b' => 2])],
['name', ['a' => 1, 'b' => 2], true, null, false, 'plain', 0, "a: 1\nb: 2"],
];
}
/**
* @dataProvider getData
*
* @param string $configName
* @param mixed $value
* @param bool $configExists
* @param mixed $defaultValue
* @param bool $hasDefault
* @param string $outputFormat
* @param int $expectedReturn
* @param string $expectedMessage
*/
public function testGet($configName, $value, $configExists, $defaultValue, $hasDefault, $outputFormat, $expectedReturn, $expectedMessage) {
$this->config->expects($this->atLeastOnce())
->method('getAppKeys')
->with('app-name')
->willReturn($configExists ? [$configName] : []);
if (!$expectedReturn) {
if ($configExists) {
$this->config->expects($this->once())
->method('getAppValue')
->with('app-name', $configName)
->willReturn($value);
}
}
$this->consoleInput->expects($this->exactly(2))
->method('getArgument')
->willReturnMap([
['app', 'app-name'],
['name', $configName],
]);
$this->consoleInput->expects($this->any())
->method('getOption')
->willReturnMap([
['default-value', $defaultValue],
['output', $outputFormat],
]);
$this->consoleInput->expects($this->any())
->method('hasParameterOption')
->willReturnMap([
['--output', true],
['--default-value', $hasDefault],
]);
if ($expectedMessage !== null) {
global $output;
$output = '';
$this->consoleOutput->expects($this->any())
->method('writeln')
->willReturnCallback(function($value) {
global $output;
$output .= $value . "\n";
return $output;
});
}
$this->assertSame($expectedReturn, $this->invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]));
if ($expectedMessage !== null) {
global $output;
// Remove the trailing newline
$this->assertSame($expectedMessage, substr($output, 0, -1));
}
}
}

View File

@ -0,0 +1,118 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace Tests\Core\Command\Config\App;
use OC\Core\Command\Config\App\SetConfig;
use Test\TestCase;
class SetConfigTest extends TestCase {
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $config;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $consoleInput;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $consoleOutput;
/** @var \Symfony\Component\Console\Command\Command */
protected $command;
protected function setUp() {
parent::setUp();
$config = $this->config = $this->getMockBuilder('OCP\IConfig')
->disableOriginalConstructor()
->getMock();
$this->consoleInput = $this->getMock('Symfony\Component\Console\Input\InputInterface');
$this->consoleOutput = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
/** @var \OCP\IConfig $config */
$this->command = new SetConfig($config);
}
public function setData() {
return [
[
'name',
'newvalue',
true,
true,
true,
'info',
],
[
'name',
'newvalue',
false,
true,
false,
'comment',
],
];
}
/**
* @dataProvider setData
*
* @param string $configName
* @param mixed $newValue
* @param bool $configExists
* @param bool $updateOnly
* @param bool $updated
* @param string $expectedMessage
*/
public function testSet($configName, $newValue, $configExists, $updateOnly, $updated, $expectedMessage) {
$this->config->expects($this->once())
->method('getAppKeys')
->with('app-name')
->willReturn($configExists ? [$configName] : []);
if ($updated) {
$this->config->expects($this->once())
->method('setAppValue')
->with('app-name', $configName, $newValue);
}
$this->consoleInput->expects($this->exactly(2))
->method('getArgument')
->willReturnMap([
['app', 'app-name'],
['name', $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));
$this->invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
}
}

View File

@ -0,0 +1,185 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace Tests\Core\Command\Config;
use OC\Core\Command\Config\Import;
use Test\TestCase;
class ImportTest extends TestCase {
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $config;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $consoleInput;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $consoleOutput;
/** @var \Symfony\Component\Console\Command\Command */
protected $command;
protected function setUp() {
parent::setUp();
$config = $this->config = $this->getMockBuilder('OCP\IConfig')
->disableOriginalConstructor()
->getMock();
$this->consoleInput = $this->getMock('Symfony\Component\Console\Input\InputInterface');
$this->consoleOutput = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
/** @var \OCP\IConfig $config */
$this->command = new Import($config);
}
public function validateAppsArrayData() {
return [
[0],
[1],
[null],
['new \Exception()'],
[json_encode([])],
];
}
/**
* @dataProvider validateAppsArrayData
*
* @param mixed $configValue
*/
public function testValidateAppsArray($configValue) {
$this->invokePrivate($this->command, 'validateAppsArray', [['app' => ['name' => $configValue]]]);
$this->assertTrue(true, 'Asserting that no exception is thrown');
}
public function validateAppsArrayThrowsData() {
return [
[false],
[true],
[[]],
[new \Exception()],
];
}
/**
* @dataProvider validateAppsArrayThrowsData
*
* @param mixed $configValue
*/
public function testValidateAppsArrayThrows($configValue) {
try {
$this->invokePrivate($this->command, 'validateAppsArray', [['app' => ['name' => $configValue]]]);
$this->fail('Did not throw expected UnexpectedValueException');
} catch (\UnexpectedValueException $e) {
$this->assertStringStartsWith('Invalid app config value for "app":"name".', $e->getMessage());
}
}
public function checkTypeRecursivelyData() {
return [
[0],
[1],
[null],
['new \Exception()'],
[json_encode([])],
[false],
[true],
[[]],
[['string']],
[['test' => 'string']],
[['test' => ['sub' => 'string']]],
];
}
/**
* @dataProvider checkTypeRecursivelyData
*
* @param mixed $configValue
*/
public function testCheckTypeRecursively($configValue) {
$this->invokePrivate($this->command, 'checkTypeRecursively', [$configValue, 'name']);
$this->assertTrue(true, 'Asserting that no exception is thrown');
}
public function checkTypeRecursivelyThrowsData() {
return [
[new \Exception()],
[[new \Exception()]],
[['test' => new \Exception()]],
[['test' => ['sub' => new \Exception()]]],
];
}
/**
* @dataProvider checkTypeRecursivelyThrowsData
*
* @param mixed $configValue
*/
public function testCheckTypeRecursivelyThrows($configValue) {
try {
$this->invokePrivate($this->command, 'checkTypeRecursively', [$configValue, 'name']);
$this->fail('Did not throw expected UnexpectedValueException');
} catch (\UnexpectedValueException $e) {
$this->assertStringStartsWith('Invalid system config value for "name"', $e->getMessage());
}
}
public function validateArrayData() {
return [
[['system' => []]],
[['apps' => []]],
[['system' => [], 'apps' => []]],
];
}
/**
* @dataProvider validateArrayData
*
* @param array $configArray
*/
public function testValidateArray($configArray) {
$this->invokePrivate($this->command, 'validateArray', [$configArray]);
$this->assertTrue(true, 'Asserting that no exception is thrown');
}
public function validateArrayThrowsData() {
return [
[[], 'At least one key of the following is expected:'],
[[0 => []], 'Found invalid entries in root'],
[['string' => []], 'Found invalid entries in root'],
];
}
/**
* @dataProvider validateArrayThrowsData
*
* @param mixed $configArray
* @param string $expectedException
*/
public function testValidateArrayThrows($configArray, $expectedException) {
try {
$this->invokePrivate($this->command, 'validateArray', [$configArray]);
$this->fail('Did not throw expected UnexpectedValueException');
} catch (\UnexpectedValueException $e) {
$this->assertStringStartsWith($expectedException, $e->getMessage());
}
}
}

View File

@ -0,0 +1,300 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace Tests\Core\Command\Config;
use OC\Core\Command\Config\ListConfigs;
use Test\TestCase;
class ListConfigsTest extends TestCase {
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $appConfig;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $systemConfig;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $consoleInput;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $consoleOutput;
/** @var \Symfony\Component\Console\Command\Command */
protected $command;
protected function setUp() {
parent::setUp();
$systemConfig = $this->systemConfig = $this->getMockBuilder('OC\SystemConfig')
->disableOriginalConstructor()
->getMock();
$appConfig = $this->appConfig = $this->getMockBuilder('OCP\IAppConfig')
->disableOriginalConstructor()
->getMock();
$this->consoleInput = $this->getMock('Symfony\Component\Console\Input\InputInterface');
$this->consoleOutput = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
/** @var \OC\SystemConfig $systemConfig */
/** @var \OCP\IAppConfig $appConfig */
$this->command = new ListConfigs($systemConfig, $appConfig);
}
public function listData() {
return [
[
'all',
// config.php
[
'secret',
'overwrite.cli.url',
],
[
['secret', 'N;', 'my secret'],
['overwrite.cli.url', 'N;', 'http://localhost'],
],
// app config
[
['files', false, [
'enabled' => 'yes',
]],
['core', false, [
'global_cache_gc_lastrun' => '1430388388',
]],
],
false,
json_encode([
'system' => [
'overwrite.cli.url' => 'http://localhost',
],
'apps' => [
'core' => [
'global_cache_gc_lastrun' => '1430388388',
],
'files' => [
'enabled' => 'yes',
],
],
]),
],
[
'all',
// config.php
[
'secret',
'overwrite.cli.url',
],
[
['secret', 'N;', 'my secret'],
['overwrite.cli.url', 'N;', 'http://localhost'],
],
// app config
[
['files', false, [
'enabled' => 'yes',
]],
['core', false, [
'global_cache_gc_lastrun' => '1430388388',
]],
],
true,
json_encode([
'system' => [
'secret' => 'my secret',
'overwrite.cli.url' => 'http://localhost',
],
'apps' => [
'core' => [
'global_cache_gc_lastrun' => '1430388388',
],
'files' => [
'enabled' => 'yes',
],
],
]),
],
[
'system',
// config.php
[
'secret',
'overwrite.cli.url',
],
[
['secret', 'N;', 'my secret'],
['overwrite.cli.url', 'N;', 'http://localhost'],
],
// app config
[
['files', false, [
'enabled' => 'yes',
]],
['core', false, [
'global_cache_gc_lastrun' => '1430388388',
]],
],
false,
json_encode([
'system' => [
'overwrite.cli.url' => 'http://localhost',
],
]),
],
[
'system',
// config.php
[
'secret',
'overwrite.cli.url',
],
[
['secret', 'N;', 'my secret'],
['overwrite.cli.url', 'N;', 'http://localhost'],
],
// app config
[
['files', false, [
'enabled' => 'yes',
]],
['core', false, [
'global_cache_gc_lastrun' => '1430388388',
]],
],
true,
json_encode([
'system' => [
'secret' => 'my secret',
'overwrite.cli.url' => 'http://localhost',
],
]),
],
[
'files',
// config.php
[
'secret',
'overwrite.cli.url',
],
[
['secret', 'N;', 'my secret'],
['overwrite.cli.url', 'N;', 'http://localhost'],
],
// app config
[
['files', false, [
'enabled' => 'yes',
]],
['core', false, [
'global_cache_gc_lastrun' => '1430388388',
]],
],
false,
json_encode([
'apps' => [
'files' => [
'enabled' => 'yes',
],
],
]),
],
[
'files',
// config.php
[
'secret',
'overwrite.cli.url',
],
[
['secret', 'N;', 'my secret'],
['overwrite.cli.url', 'N;', 'http://localhost'],
],
// app config
[
['files', false, [
'enabled' => 'yes',
]],
['core', false, [
'global_cache_gc_lastrun' => '1430388388',
]],
],
true,
json_encode([
'apps' => [
'files' => [
'enabled' => 'yes',
],
],
]),
],
];
}
/**
* @dataProvider listData
*
* @param string $app
* @param array $systemConfigs
* @param array $systemConfigMap
* @param array $appConfig
* @param bool $private
* @param string $expected
*/
public function testList($app, $systemConfigs, $systemConfigMap, $appConfig, $private, $expected) {
$this->systemConfig->expects($this->any())
->method('getKeys')
->willReturn($systemConfigs);
$this->systemConfig->expects($this->any())
->method('getValue')
->willReturnMap($systemConfigMap);
$this->appConfig->expects($this->any())
->method('getApps')
->willReturn(['core', 'files']);
$this->appConfig->expects($this->any())
->method('getValues')
->willReturnMap($appConfig);
$this->consoleInput->expects($this->once())
->method('getArgument')
->with('app')
->willReturn($app);
$this->consoleInput->expects($this->any())
->method('getOption')
->willReturnMap([
['output', 'json'],
['private', $private],
]);
global $output;
$output = '';
$this->consoleOutput->expects($this->any())
->method('writeln')
->willReturnCallback(function($value) {
global $output;
$output .= $value . "\n";
return $output;
});
$this->invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
$this->assertEquals($expected, trim($output, "\n"));
}
}

View File

@ -0,0 +1,120 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace Tests\Core\Command\Config\System;
use OC\Core\Command\Config\System\DeleteConfig;
use Test\TestCase;
class DeleteConfigTest extends TestCase {
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $systemConfig;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $consoleInput;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $consoleOutput;
/** @var \Symfony\Component\Console\Command\Command */
protected $command;
protected function setUp() {
parent::setUp();
$systemConfig = $this->systemConfig = $this->getMockBuilder('OC\SystemConfig')
->disableOriginalConstructor()
->getMock();
$this->consoleInput = $this->getMock('Symfony\Component\Console\Input\InputInterface');
$this->consoleOutput = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
/** @var \OC\SystemConfig $systemConfig */
$this->command = new DeleteConfig($systemConfig);
}
public function deleteData() {
return [
[
'name',
true,
true,
0,
'info',
],
[
'name',
true,
false,
0,
'info',
],
[
'name',
false,
false,
0,
'info',
],
[
'name',
false,
true,
1,
'error',
],
];
}
/**
* @dataProvider deleteData
*
* @param string $configName
* @param bool $configExists
* @param bool $checkIfExists
* @param int $expectedReturn
* @param string $expectedMessage
*/
public function testDelete($configName, $configExists, $checkIfExists, $expectedReturn, $expectedMessage) {
$this->systemConfig->expects(($checkIfExists) ? $this->once() : $this->never())
->method('getKeys')
->willReturn($configExists ? [$configName] : []);
$this->systemConfig->expects(($expectedReturn === 0) ? $this->once() : $this->never())
->method('deleteValue')
->with($configName);
$this->consoleInput->expects($this->once())
->method('getArgument')
->with('name')
->willReturn($configName);
$this->consoleInput->expects($this->any())
->method('hasParameterOption')
->with('--error-if-not-exists')
->willReturn($checkIfExists);
$this->consoleOutput->expects($this->any())
->method('writeln')
->with($this->stringContains($expectedMessage));
$this->assertSame($expectedReturn, $this->invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]));
}
}

View File

@ -0,0 +1,160 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace Tests\Core\Command\Config\System;
use OC\Core\Command\Config\System\GetConfig;
use Test\TestCase;
class GetConfigTest extends TestCase {
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $systemConfig;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $consoleInput;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $consoleOutput;
/** @var \Symfony\Component\Console\Command\Command */
protected $command;
protected function setUp() {
parent::setUp();
$systemConfig = $this->systemConfig = $this->getMockBuilder('OC\SystemConfig')
->disableOriginalConstructor()
->getMock();
$this->consoleInput = $this->getMock('Symfony\Component\Console\Input\InputInterface');
$this->consoleOutput = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
/** @var \OC\SystemConfig $systemConfig */
$this->command = new GetConfig($systemConfig);
}
public function getData() {
return [
// String output as json
['name', 'newvalue', true, null, false, 'json', 0, json_encode('newvalue')],
// String output as plain text
['name', 'newvalue', true, null, false, 'plain', 0, 'newvalue'],
// String falling back to default output as json
['name', null, false, 'newvalue', true, 'json', 0, json_encode('newvalue')],
// String falling back without default: error
['name', null, false, null, false, 'json', 1, null],
// Int "0" output as json/plain
['name', 0, true, null, false, 'json', 0, json_encode(0)],
['name', 0, true, null, false, 'plain', 0, '0'],
// Int "1" output as json/plain
['name', 1, true, null, false, 'json', 0, json_encode(1)],
['name', 1, true, null, false, 'plain', 0, '1'],
// Bool "true" output as json/plain
['name', true, true, null, false, 'json', 0, json_encode(true)],
['name', true, true, null, false, 'plain', 0, 'true'],
// Bool "false" output as json/plain
['name', false, true, null, false, 'json', 0, json_encode(false)],
['name', false, true, null, false, 'plain', 0, 'false'],
// Null output as json/plain
['name', null, true, null, false, 'json', 0, json_encode(null)],
['name', null, true, null, false, 'plain', 0, 'null'],
// Array output as json/plain
['name', ['a', 'b'], true, null, false, 'json', 0, json_encode(['a', 'b'])],
['name', ['a', 'b'], true, null, false, 'plain', 0, "a\nb"],
// Key array output as json/plain
['name', [0 => 'a', 1 => 'b'], true, null, false, 'json', 0, json_encode(['a', 'b'])],
['name', [0 => 'a', 1 => 'b'], true, null, false, 'plain', 0, "a\nb"],
// Associative array output as json/plain
['name', ['a' => 1, 'b' => 2], true, null, false, 'json', 0, json_encode(['a' => 1, 'b' => 2])],
['name', ['a' => 1, 'b' => 2], true, null, false, 'plain', 0, "a: 1\nb: 2"],
];
}
/**
* @dataProvider getData
*
* @param string $configName
* @param mixed $value
* @param bool $configExists
* @param mixed $defaultValue
* @param bool $hasDefault
* @param string $outputFormat
* @param int $expectedReturn
* @param string $expectedMessage
*/
public function testGet($configName, $value, $configExists, $defaultValue, $hasDefault, $outputFormat, $expectedReturn, $expectedMessage) {
$this->systemConfig->expects($this->atLeastOnce())
->method('getKeys')
->willReturn($configExists ? [$configName] : []);
if (!$expectedReturn) {
if ($configExists) {
$this->systemConfig->expects($this->once())
->method('getValue')
->with($configName)
->willReturn($value);
}
}
$this->consoleInput->expects($this->once())
->method('getArgument')
->with('name')
->willReturn($configName);
$this->consoleInput->expects($this->any())
->method('getOption')
->willReturnMap([
['default-value', $defaultValue],
['output', $outputFormat],
]);
$this->consoleInput->expects($this->any())
->method('hasParameterOption')
->willReturnMap([
['--output', true],
['--default-value', $hasDefault],
]);
if ($expectedMessage !== null) {
global $output;
$output = '';
$this->consoleOutput->expects($this->any())
->method('writeln')
->willReturnCallback(function($value) {
global $output;
$output .= $value . "\n";
return $output;
});
}
$this->assertSame($expectedReturn, $this->invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]));
if ($expectedMessage !== null) {
global $output;
// Remove the trailing newline
$this->assertSame($expectedMessage, substr($output, 0, -1));
}
}
}

View File

@ -0,0 +1,115 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace Tests\Core\Command\Config\System;
use OC\Core\Command\Config\System\SetConfig;
use Test\TestCase;
class SetConfigTest extends TestCase {
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $systemConfig;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $consoleInput;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $consoleOutput;
/** @var \Symfony\Component\Console\Command\Command */
protected $command;
protected function setUp() {
parent::setUp();
$systemConfig = $this->systemConfig = $this->getMockBuilder('OC\SystemConfig')
->disableOriginalConstructor()
->getMock();
$this->consoleInput = $this->getMock('Symfony\Component\Console\Input\InputInterface');
$this->consoleOutput = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
/** @var \OC\SystemConfig $systemConfig */
$this->command = new SetConfig($systemConfig);
}
public function setData() {
return [
[
'name',
'newvalue',
true,
true,
true,
'info',
],
[
'name',
'newvalue',
false,
true,
false,
'comment',
],
];
}
/**
* @dataProvider setData
*
* @param string $configName
* @param mixed $newValue
* @param bool $configExists
* @param bool $updateOnly
* @param bool $updated
* @param string $expectedMessage
*/
public function testSet($configName, $newValue, $configExists, $updateOnly, $updated, $expectedMessage) {
$this->systemConfig->expects($this->once())
->method('getKeys')
->willReturn($configExists ? [$configName] : []);
if ($updated) {
$this->systemConfig->expects($this->once())
->method('setValue')
->with($configName, $newValue);
}
$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));
$this->invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
}
}