diff --git a/lib/Froxlor/Api/Commands/ApiKeys.php b/lib/Froxlor/Api/Commands/ApiKeys.php deleted file mode 100644 index d5180e36..00000000 --- a/lib/Froxlor/Api/Commands/ApiKeys.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 - */ - -namespace Froxlor\Api\Commands; - -use Froxlor\Api\ApiCommand; - -/** - * @since 0.10.0 - */ -class ApiKeys extends ApiCommand -{ - - public function listing() - { - // - } - - public function listingCount() - { - // - } -} diff --git a/lib/Froxlor/Api/Commands/Froxlor.php b/lib/Froxlor/Api/Commands/Froxlor.php index 3cc0fb1e..f2295be1 100644 --- a/lib/Froxlor/Api/Commands/Froxlor.php +++ b/lib/Froxlor/Api/Commands/Froxlor.php @@ -296,6 +296,8 @@ class Froxlor extends ApiCommand * * @param string $module * optional, return list of functions for a specific module + * @param string $function + * optional, return parameter information for a specific module and function * * @access admin, customer * @return string json-encoded array @@ -304,6 +306,7 @@ class Froxlor extends ApiCommand public function listFunctions() { $module = $this->getParam('module', true, ''); + $function = $this->getParam('function', true, ''); $functions = []; if ($module != null) { @@ -313,11 +316,13 @@ class Froxlor extends ApiCommand $reflection = new ReflectionClass(__NAMESPACE__ . '\\' . $module); $_functions = $reflection->getMethods(ReflectionMethod::IS_PUBLIC); foreach ($_functions as $func) { - if ($func->class == __NAMESPACE__ . '\\' . $module && $func->isPublic()) { - array_push($functions, array_merge([ - 'module' => $module, - 'function' => $func->name - ], $this->getParamListFromDoc($module, $func->name))); + if (empty($function) || ($function != null && $func->name == $function)) { + if ($func->class == __NAMESPACE__ . '\\' . $module && $func->isPublic()) { + array_push($functions, array_merge([ + 'module' => $module, + 'function' => $func->name + ], $this->getParamListFromDoc($module, $func->name))); + } } } } else { diff --git a/lib/Froxlor/Cli/RunApiCommand.php b/lib/Froxlor/Cli/RunApiCommand.php index 5dd8b95e..71399aa5 100644 --- a/lib/Froxlor/Cli/RunApiCommand.php +++ b/lib/Froxlor/Cli/RunApiCommand.php @@ -29,7 +29,9 @@ use Exception; use PDO; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; use Froxlor\Database\Database; final class RunApiCommand extends CliCommand @@ -42,6 +44,7 @@ final class RunApiCommand extends CliCommand $this->addArgument('user', InputArgument::REQUIRED, 'Loginname of the user you want to run the command as') ->addArgument('api-command', InputArgument::REQUIRED, 'The command to execute in the form "Module.function"') ->addArgument('parameters', InputArgument::OPTIONAL, 'Paramaters to pass to the command as JSON array'); + $this->addOption('show-params', 's', InputOption::VALUE_NONE, 'Show possible parameters for given api-command (given command will *not* be called)'); } protected function execute(InputInterface $input, OutputInterface $output) @@ -50,26 +53,54 @@ final class RunApiCommand extends CliCommand $result = $this->validateRequirements($input, $output); - try { - $loginname = $input->getArgument('user'); - $userinfo = $this->getUserByName($loginname); - $command = $input->getArgument('api-command'); - $apicmd = $this->validateCommand($command); - $module = "\\Froxlor\\Api\\Commands\\" . $apicmd['class']; - $function = $apicmd['function']; - $params_json = $input->getArgument('parameters'); - $params = json_decode($params_json ?? '', true); - $json_result = $module::getLocal($userinfo, $params)->{$function}(); - $output->write($json_result); - $result = self::SUCCESS; - } catch (Exception $e) { - $output->writeln('' . $e->getMessage() . ''); - $result = self::FAILURE; + if ($result == self::SUCCESS) { + try { + $loginname = $input->getArgument('user'); + $userinfo = $this->getUserByName($loginname); + $command = $input->getArgument('api-command'); + $apicmd = $this->validateCommand($command); + $module = "\\Froxlor\\Api\\Commands\\" . $apicmd['class']; + $function = $apicmd['function']; + if ($input->getOption('show-params') !== false) { + $json_result = \Froxlor\Api\Commands\Froxlor::getLocal($userinfo, ['module' => $apicmd['class'], 'function' => $function])->listFunctions(); + $io = new SymfonyStyle($input, $output); + $result = $this->outputParamsList($json_result, $io); + } else { + $params_json = $input->getArgument('parameters'); + $params = json_decode($params_json ?? '', true); + $json_result = $module::getLocal($userinfo, $params)->{$function}(); + $output->write($json_result); + $result = self::SUCCESS; + } + } catch (Exception $e) { + $output->writeln('' . $e->getMessage() . ''); + $result = self::FAILURE; + } } return $result; } + private function outputParamsList(string $json, SymfonyStyle $io): int + { + $docs = json_decode($json, true); + $docs = array_shift($docs['data']); + if (!isset($docs['params'])) { + $io->warning(($docs['head'] ?? "unknown return")); + return self::INVALID; + } + if (empty($docs['params'])) { + $io->success("No parameters required"); + } else { + $rows = []; + foreach ($docs['params'] as $param) { + $rows[] = [$param['type'], ''.$param['parameter'].'', $param['desc'] ?? ""]; + } + $io->table(['Type', 'Name', 'Description'], $rows); + } + return self::SUCCESS; + } + private function validateCommand(string $command): array { $command = explode(".", $command); diff --git a/lng/de.lng.php b/lng/de.lng.php index 3a089de4..993699d2 100644 --- a/lng/de.lng.php +++ b/lng/de.lng.php @@ -108,6 +108,7 @@ return [ 'skipconfig' => 'Nicht (erneut) konfigurieren', 'recommendednote' => 'Empfohlene/benötigte Dienste anhand der aktuellen Systemeinstellungen', 'selectrecommended' => 'Empfohlene wählen', + 'downloadselected' => 'Auswahl exportieren', ], 'templates' => [ 'templates' => 'E-Mail-Vorlagen', diff --git a/lng/en.lng.php b/lng/en.lng.php index 35885b2c..73292c22 100644 --- a/lng/en.lng.php +++ b/lng/en.lng.php @@ -110,6 +110,7 @@ return [ 'skipconfig' => 'Don\'t (re)configure', 'recommendednote' => 'Recommended/required services based on current system settings', 'selectrecommended' => 'Select recommended', + 'downloadselected' => 'Export selected', ], 'templates' => [ 'templates' => 'Email-templates',