diff --git a/admin_configfiles.php b/admin_configfiles.php
index 85c16933..2742c43a 100644
--- a/admin_configfiles.php
+++ b/admin_configfiles.php
@@ -43,6 +43,11 @@ if ($userinfo['change_serversettings'] == '1') {
// get distro from URL param
$distribution = Request::get('distribution');
+ // check for possible setting
+ if (empty($distribution)) {
+ $distribution = Settings::Get('system.distribution') ?? "";
+ }
+
$distributions_select = [];
$services = [];
@@ -53,6 +58,11 @@ if ($userinfo['change_serversettings'] == '1') {
Response::dynamicError("Unknown distribution");
}
+ // update setting if different
+ if ($distribution != Settings::Get('system.distribution')) {
+ Settings::Set('system.distribution', $distribution);
+ }
+
// create configparser object
$configfiles = new ConfigParser($config_dir . '/' . $distribution . ".xml");
diff --git a/install/froxlor.sql.php b/install/froxlor.sql.php
index 51f177e2..7ccb1407 100644
--- a/install/froxlor.sql.php
+++ b/install/froxlor.sql.php
@@ -699,6 +699,7 @@ opcache.validate_timestamps'),
('system', 'froxlorusergroup', ''),
('system', 'froxlorusergroup_gid', ''),
('system', 'acmeshpath', '/root/.acme.sh/acme.sh'),
+ ('system', 'distribution', ''),
('api', 'enabled', '0'),
('2fa', 'enabled', '1'),
('panel', 'decimal_places', '4'),
diff --git a/install/updates/froxlor/0.11/update_0.11.inc.php b/install/updates/froxlor/0.11/update_0.11.inc.php
index 82712c91..ef7c5c0e 100644
--- a/install/updates/froxlor/0.11/update_0.11.inc.php
+++ b/install/updates/froxlor/0.11/update_0.11.inc.php
@@ -126,6 +126,8 @@ if (Froxlor::isFroxlorVersion('0.10.99')) {
Update::showUpdateStep("Adding new settings");
$panel_settings_mode = isset($_POST['panel_settings_mode']) ? (int) $_POST['panel_settings_mode'] : 0;
Settings::AddNew("panel.settings_mode", $panel_settings_mode);
+ $system_distribution = isset($_POST['system_distribution']) ? $_POST['system_distribution'] : '';
+ Settings::AddNew("system.distribution", $system_distribution);
Update::lastStepStatus(0);
Update::showUpdateStep("Adjusting existing settings");
diff --git a/install/updates/preconfig/0.11/preconfig_0.11.inc.php b/install/updates/preconfig/0.11/preconfig_0.11.inc.php
index c86d8bb2..e9a7f959 100644
--- a/install/updates/preconfig/0.11/preconfig_0.11.inc.php
+++ b/install/updates/preconfig/0.11/preconfig_0.11.inc.php
@@ -15,6 +15,10 @@
*
*/
+use Froxlor\Froxlor;
+use Froxlor\FileDir;
+use Froxlor\Config\ConfigParser;
+
/**
* checks if the new-version has some updating to do
*
@@ -29,7 +33,6 @@
*/
function parseAndOutputPreconfig011(&$has_preconfig, &$return, $current_version, $current_db_version)
{
- global $lng;
if (versionInUpdate($current_version, '0.10.99')) {
$has_preconfig = true;
@@ -45,5 +48,28 @@ function parseAndOutputPreconfig011(&$has_preconfig, &$return, $current_version,
'selected' => 1,
'label' => $question
];
+
+ $description = 'The configuration page now can preselect a distribution, please select your current distribution';
+ $return['system_distribution_note'] = ['type' => 'infotext', 'value' => $description];
+ $question = 'Select distribution';
+ $config_dir = FileDir::makeCorrectDir(Froxlor::getInstallDir() . '/lib/configfiles/');
+ // show list of available distro's
+ $distros = glob($config_dir . '*.xml');
+ $distributions_select[''] = '-';
+ // read in all the distros
+ foreach ($distros as $_distribution) {
+ // get configparser object
+ $dist = new ConfigParser($_distribution);
+ // store in tmp array
+ $distributions_select[str_replace(".xml", "", strtolower(basename($_distribution)))] = $dist->getCompleteDistroName();
+ }
+ // sort by distribution name
+ asort($distributions_select);
+ $return['system_distribution'] = [
+ 'type' => 'select',
+ 'select_var' => $distributions_select,
+ 'selected' => '',
+ 'label' => $question
+ ];
}
}
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..8efcd223 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..3aee9789 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',
@@ -1353,6 +1354,9 @@ Yours sincerely, your administrator',
'maintitle' => 'PHP Configurations',
'fpmdaemons' => 'PHP-FPM versions',
],
+ 'logger' => [
+ 'logger' => 'System log',
+ ],
],
'message' => [
'norecipients' => 'No e-mail has been sent because there are no recipients in the database',