| <?php |
|
|
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\Plugins\CoreAdminHome\Commands; |
|
|
| use Piwik\Config; |
| use Piwik\Plugin\ConsoleCommand; |
| use Piwik\Settings\FieldConfig; |
| use Piwik\Settings\Plugin\SystemConfigSetting; |
| use Spyc; |
|
|
| class ConfigGet extends ConsoleCommand |
| { |
| |
| private const NO_SETTING_NAME_FOUND_PLACEHOLDER = 'ConfigGet_FAKE_SETTING_NAME'; |
| |
| public const OUTPUT_FORMATS = ['json', 'yaml', 'text']; |
| |
| public const OUTPUT_FORMAT_DEFAULT = 'json'; |
| |
| private const MSG_NOTHING_FOUND = 'Nothing found'; |
|
|
| protected function configure() |
| { |
| $this->setName('config:get'); |
| $this->setDescription('Get a config value or section'); |
| $this->addOptionalArgument( |
| 'argument', |
| "A config setting in the format Section.key or Section.array_key[], e.g. 'Database.username' or 'PluginsInstalled'" |
| ); |
| $this->addRequiredValueOption('section', 's', 'The section the INI config setting belongs to.'); |
| $this->addRequiredValueOption('key', 'k', 'The name of the INI config setting.'); |
| $this->addOptionalValueOption('format', 'f', 'Format the output as ' . json_encode(self::OUTPUT_FORMATS) . '; Default is ' . self::OUTPUT_FORMAT_DEFAULT, self::OUTPUT_FORMAT_DEFAULT); |
|
|
| $this->setHelp("This command can be used to get a INI config setting or a whole section of settings on a Piwik instance. |
| |
| You can get config values per the two sections below, where: |
| - [Section] is the name of the section, e.g. database or General. |
| - [config_setting_name] the name of the setting, e.g. username. |
| |
| (1) By settings options --section=[Section] and --key=[config_setting_name]. The option --section is required. Examples: |
| #Return all settings in this section. |
| $ ./console %command.name% --section=database |
| #Return only this setting. |
| $ ./console %command.name% --section=database --key=username |
| |
| OR |
| |
| (2) By using a command argument in the format [Section].[config_setting_name]. Examples: |
| #Return all settings in this section. |
| $ ./console %command.name% 'database' |
| #Return all settings in this array; square brackets are optional. |
| $ ./console %command.name% 'PluginsInstalled.PluginsInstalled' |
| $ ./console %command.name% 'PluginsInstalled.PluginsInstalled[]' |
| #Return only this setting. |
| $ ./console %command.name% 'database.username' |
| |
| NOTES: |
| - Section and key names are case-sensitive; so e.g. --section=Database fails but --section=database works. Look in global.ini.php for the proper case. |
| - If no matching section/setting is found, the string \"" . self::MSG_NOTHING_FOUND . "\" shows. |
| - Else the output will be shown JSON-encoded. You can use something like https://stedolan.github.io/jq to parse it. |
| - If you ask for 'PluginsInstalled.PluginsInstalled[\"some_array_item\"]', it will ignore the array key (\"some_array_item\") and you will get back the whole array of values (e.g. all PluginsInstalled[] values). |
| "); |
| } |
|
|
| protected function doExecute(): int |
| { |
| $input = $this->getInput(); |
| $output = $this->getOutput(); |
|
|
| |
| $options = array_filter([ |
| 'section' => $input->getOption('section'), |
| 'key' => $input->getOption('key'), |
| ]); |
|
|
| |
| $format = $input->getOption('format'); |
| if (empty($format) || !in_array($format, self::OUTPUT_FORMATS, true)) { |
| $format = self::OUTPUT_FORMAT_DEFAULT; |
| } |
|
|
| $argument = trim($input->getArgument('argument') ?? ''); |
|
|
| |
| $argument = array_slice(explode(' ', $argument), -1)[0]; |
|
|
| |
| switch (true) { |
| case empty($argument) && empty($options): |
| throw new \InvalidArgumentException('You must set either an argument or set options --section and optional --key'); |
| case (!empty($argument) && !empty($options)): |
| throw new \InvalidArgumentException('You cannot set both an argument (' . serialize($argument) . ') and options (' . serialize($argument) . ')'); |
| case empty($argument) && (!isset($options['section']) || empty($options['section'])): |
| throw new \InvalidArgumentException('When using options, the --section value must be set'); |
| case (!empty($argument)): |
| $settingStr = $argument; |
| break; |
| case (!empty($options)): |
| $settingStr = implode('.', $options); |
| break; |
| default: |
| |
| throw new \Exception('Some unexpected error occurred in ' . __FUNCTION__ . ' at line ' . __LINE__); |
| } |
|
|
| |
| $setting = self::parseSettingStr($settingStr); |
|
|
| $result = $this->getConfigValue(Config::getInstance(), $setting); |
|
|
| if (empty($result)) { |
| $output->writeln(self::wrapInTag('comment', self::MSG_NOTHING_FOUND)); |
| } else { |
| $output->writeln($this->formatVariableForOutput($setting, $result, $format)); |
| } |
|
|
| return self::SUCCESS; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| private function getConfigValue(Config $config, SystemConfigSetting $setting) |
| { |
|
|
| |
| if (empty($sectionName = $setting->getConfigSectionName())) { |
| throw new \InvalidArgumentException('A section name must be specified'); |
| } |
| if (empty($section = $config->__get($sectionName))) { |
| return null; |
| } |
|
|
| |
| $section = (object) $section; |
|
|
| |
| $settingName = $setting->getName(); |
|
|
| |
| |
| if (empty($settingName) || $settingName === self::NO_SETTING_NAME_FOUND_PLACEHOLDER) { |
| $sectionContents = $section; |
| return (array) $sectionContents; |
| } |
|
|
|
|
| switch (true) { |
| case (!isset($section->$settingName)): |
| $settingValue = null; |
| break; |
| case is_array($settingValue = $section->$settingName): |
| break; |
| default: |
| $settingValue = $setting->getValue(); |
| } |
|
|
| return $settingValue; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public static function parseSettingStr(string $settingStr): SystemConfigSetting |
| { |
|
|
| $matches = []; |
| if (!preg_match('/^([a-zA-Z0-9_]+)(?:\.([a-zA-Z0-9_]+))?(\[\])?/', $settingStr, $matches) || empty($matches[1])) { |
| throw new \InvalidArgumentException("Invalid input string='{$settingStr}' =expected section.name or section.name[]"); |
| } |
|
|
|
|
| return new SystemConfigSetting( |
| |
| $matches[2] ?? self::NO_SETTING_NAME_FOUND_PLACEHOLDER, |
| |
| '', |
| |
| FieldConfig::TYPE_STRING, |
| |
| 'core', |
| |
| $matches[1] |
| ); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| private function formatVariableForOutput(SystemConfigSetting $setting, $var, string $format = self::OUTPUT_FORMAT_DEFAULT): string |
| { |
|
|
| switch ($format) { |
| case 'json': |
| return $this->toJson($var); |
| case 'yaml': |
| return $this->toYaml($var); |
| case 'text': |
| return $this->toText($setting, $var); |
| default: |
| throw new \InvalidArgumentException('Unsupported output format'); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| private function toYaml($var): string |
| { |
|
|
| |
| return trim(ltrim(Spyc::YAMLDump($var, 2, 0, true), '-')); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| private function toJson($var): string |
| { |
| $result = json_encode($var, JSON_UNESCAPED_SLASHES); |
| if ($result === false) { |
| throw new \Exception('Failed to json_encode'); |
| } |
|
|
| return $result; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| private function toText(SystemConfigSetting $setting, $var): string |
| { |
|
|
| |
| $settingName = $setting->getName() === self::NO_SETTING_NAME_FOUND_PLACEHOLDER ? '' : $setting->getName(); |
| $sectionAndSettingName = implode('.', array_filter([$setting->getConfigSectionName(), $settingName])); |
|
|
| $output = ''; |
|
|
| switch (true) { |
| case is_array($var): |
| $output .= $this->wrapInTag('info', ($settingName ? $sectionAndSettingName : "[{$sectionAndSettingName}]") . PHP_EOL); |
| $output .= $this->wrapInTag('info', '--' . PHP_EOL); |
| foreach ($var as $thisSettingName => &$val) { |
| if (is_array($val)) { |
| foreach ($val as &$arrayVal) { |
| $output .= $this->wrapInTag('info', "{$thisSettingName}[] = " . $this->wrapInTag('comment', $arrayVal)) . PHP_EOL; |
| } |
| } else { |
| $output .= $this->wrapInTag('info', $thisSettingName . ' = ' . $this->wrapInTag('comment', $val)) . PHP_EOL; |
| } |
| } |
| $output .= $this->wrapInTag('info', '--' . PHP_EOL); |
| break; |
| case is_scalar($var): |
| $output .= $this->wrapInTag('info', $sectionAndSettingName . ' = ' . $this->wrapInTag('comment', $var)); |
| break; |
| default: |
| throw new \InvalidArgumentException('Cannot output unknown type'); |
| } |
|
|
| return $output; |
| } |
| } |
|
|