213 lines
7.2 KiB
PHP
213 lines
7.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Commands\Config;
|
|
|
|
use App\Command;
|
|
use App\Libs\Attributes\Route\Cli;
|
|
use App\Libs\Config;
|
|
use App\Libs\Exceptions\RuntimeException;
|
|
use App\Libs\Options;
|
|
use Symfony\Component\Console\Completion\CompletionInput;
|
|
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
|
use Symfony\Component\Console\Helper\Table;
|
|
use Symfony\Component\Console\Helper\TableSeparator;
|
|
use Symfony\Component\Console\Input\InputArgument;
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
use Symfony\Component\Console\Input\InputOption;
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
use Symfony\Component\Yaml\Yaml;
|
|
|
|
/**
|
|
* Class ViewCommand
|
|
*
|
|
* This command display all backend's information. User can select and/or filter the displayed information.
|
|
*/
|
|
#[Cli(command: self::ROUTE)]
|
|
final class ViewCommand extends Command
|
|
{
|
|
public const ROUTE = 'config:view';
|
|
|
|
/**
|
|
* @var array Keys to be hidden from general view.
|
|
*/
|
|
private array $hidden = [
|
|
'token',
|
|
'webhook.token',
|
|
'options.' . Options::ADMIN_TOKEN
|
|
];
|
|
|
|
/**
|
|
* Configure the command.
|
|
*/
|
|
protected function configure(): void
|
|
{
|
|
$this->setName(self::ROUTE)
|
|
->setDescription('View Backends settings.')
|
|
->addOption('select-backends', 's', InputOption::VALUE_REQUIRED, 'Select backends. comma , seperated.')
|
|
->addOption('exclude', null, InputOption::VALUE_NONE, 'Inverse --select-backends logic.')
|
|
->addOption('expose', 'x', InputOption::VALUE_NONE, 'Expose the secret tokens in the view.')
|
|
->addArgument(
|
|
'filter',
|
|
InputArgument::OPTIONAL,
|
|
'Can be any key from servers.yaml, use dot notion to access sub keys, for example [webhook.token]'
|
|
)
|
|
->setHelp(
|
|
r(
|
|
<<<HELP
|
|
|
|
This command display all of your backend's information.
|
|
You can select and/or filter the displayed information.
|
|
|
|
-------
|
|
<notice>[ FAQ ]</notice>
|
|
-------
|
|
|
|
<question># How to show one backend information?</question>
|
|
|
|
The flag [<flag>-s, --select-backends</flag>] accept comma seperated list of backends name, Using the flag
|
|
in combination with [<flag>--exclude</flag>] flag will flip the logic to exclude the selected backends
|
|
rather than include them.
|
|
|
|
{cmd} <cmd>{route}</cmd> <flag>--select-backends</flag> <value>my_backend</value>
|
|
|
|
<question># How to show specific <value>key</value>?</question>
|
|
|
|
The key can be any value that already exists in the list. to access sub-keys use dot notation for example,
|
|
To see if the value of <value>import.enabled</value> you would run:
|
|
|
|
{cmd} <cmd>{route}</cmd> -- <value>import.enabled</value>
|
|
|
|
HELP,
|
|
[
|
|
'cmd' => trim(commandContext()),
|
|
'route' => self::ROUTE,
|
|
]
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Run the command.
|
|
*
|
|
* @param InputInterface $input The input object.
|
|
* @param OutputInterface $output The output object.
|
|
*
|
|
* @return int The exit code.
|
|
*/
|
|
protected function runCommand(InputInterface $input, OutputInterface $output): int
|
|
{
|
|
$selectBackends = (string)$input->getOption('select-backends');
|
|
|
|
$list = [];
|
|
$selected = array_map('trim', explode(',', $selectBackends));
|
|
$isCustom = !empty($selectBackends) && count($selected) >= 1;
|
|
$filter = $input->getArgument('filter');
|
|
|
|
foreach (Config::get('servers', []) as $backendName => $backend) {
|
|
if ($isCustom && $input->getOption('exclude') === in_array($backendName, $selected)) {
|
|
$output->writeln(r('Ignoring backend \'{backend}\' as requested by [-s, --select-backends].', [
|
|
'backend' => $backendName
|
|
]), OutputInterface::VERBOSITY_VERY_VERBOSE);
|
|
continue;
|
|
}
|
|
|
|
$list[$backendName] = ['name' => $backendName, ...$backend];
|
|
}
|
|
|
|
if (empty($list)) {
|
|
throw new RuntimeException(
|
|
$isCustom ? '[-s, --select-backends] did not return any backend.' : 'No backends were found.'
|
|
);
|
|
}
|
|
|
|
$x = 0;
|
|
$count = count($list);
|
|
|
|
$rows = [];
|
|
foreach ($list as $backendName => $backend) {
|
|
$x++;
|
|
$rows[] = [
|
|
$backendName,
|
|
$this->filterData($backend, $filter, $input->getOption('expose'))
|
|
];
|
|
|
|
if ($x < $count) {
|
|
$rows[] = new TableSeparator();
|
|
}
|
|
}
|
|
|
|
$mode = $input->getOption('output');
|
|
|
|
if ('table' === $mode) {
|
|
(new Table($output))->setStyle('box')
|
|
->setHeaders(['Backend', 'Data (Filter: ' . (empty($filter) ? 'None' : $filter) . ')']
|
|
)->setRows($rows)
|
|
->render();
|
|
} else {
|
|
$this->displayContent($list, $output, $mode);
|
|
}
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* Completes the suggestion for filter input.
|
|
*
|
|
* @param CompletionInput $input The input for completion.
|
|
* @param CompletionSuggestions $suggestions The completion suggestions.
|
|
*/
|
|
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
|
{
|
|
parent::complete($input, $suggestions);
|
|
|
|
if ($input->mustSuggestArgumentValuesFor('filter')) {
|
|
$currentValue = $input->getCompletionValue();
|
|
|
|
$suggest = [];
|
|
|
|
foreach (require __DIR__ . '/../../../config/backend.spec.php' as $name => $val) {
|
|
if (true === $val && (empty($currentValue) || str_starts_with($name, $currentValue))) {
|
|
$suggest[] = $name;
|
|
}
|
|
}
|
|
|
|
$suggestions->suggestValues($suggest);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Filters the given backend data based on the provided filter and expose parameters.
|
|
*
|
|
* @param array $backend The backend data to filter.
|
|
* @param string|null $filter The filter criteria.
|
|
* @param bool $expose Whether to expose hidden values or not.
|
|
*
|
|
* @return string The filtered data in YAML format.
|
|
*/
|
|
private function filterData(array $backend, string|null $filter = null, bool $expose = false): string
|
|
{
|
|
if (null === $filter && true !== $expose) {
|
|
foreach ($this->hidden as $hideValue) {
|
|
if (true === ag_exists($backend, $hideValue)) {
|
|
$backend = ag_set($backend, $hideValue, '*HIDDEN*');
|
|
}
|
|
}
|
|
}
|
|
|
|
if (null === $filter || false === str_contains($filter, ',')) {
|
|
return trim(Yaml::dump(ag($backend, $filter, 'Not configured, or invalid key.'), 8, 2));
|
|
}
|
|
|
|
$filters = array_map(fn($val) => trim($val), explode(',', $filter));
|
|
$list = [];
|
|
|
|
foreach ($filters as $fil) {
|
|
$list[$fil] = ag($backend, $fil, 'Not configured, or invalid key.');
|
|
}
|
|
|
|
return trim(Yaml::dump($list, 8, 2));
|
|
}
|
|
}
|