diff --git a/README.md b/README.md
index 4330d6c4..4d0c0555 100644
--- a/README.md
+++ b/README.md
@@ -382,6 +382,8 @@ class IndexController extends Controller
# display ratio list
./bin/console tbbc:money:ratio-list
+./bin/console tbbc:money:ratio-list --format=table
+./bin/console tbbc:money:ratio-list --format=json
# fetch all the ratio for all defined currencies from an external API
./bin/console tbbc:money:ratio-fetch
diff --git a/Tests/Command/RatioListCommandTest.php b/Tests/Command/RatioListCommandTest.php
index 538068ff..ab7c5091 100644
--- a/Tests/Command/RatioListCommandTest.php
+++ b/Tests/Command/RatioListCommandTest.php
@@ -27,4 +27,39 @@ public function testCanWriteRatioList(): void
$output = $tester->getDisplay();
self::assertStringContainsString('USD;1.2', $output);
}
+
+ public function testGetRatioListAsTable(): void
+ {
+ $data = ['EUR' => 1.1, 'USD' => 1.2];
+ $pairManager = $this->createMock(PairManagerInterface::class);
+ $pairManager
+ ->expects($this->once())
+ ->method('getRatioList')
+ ->willReturn($data);
+
+ $command = new RatioListCommand($pairManager);
+ $tester = new CommandTester($command);
+ $tester->execute(['--format' => 'table']);
+ self::assertSame(Command::SUCCESS, $tester->getStatusCode());
+ self::assertStringContainsString('EUR | 1.1', $tester->getDisplay());
+ self::assertStringContainsString('USD | 1.2', $tester->getDisplay());
+ }
+
+ public function testGetRatioListAsJson(): void
+ {
+ $data = ['EUR' => 1.1, 'USD' => 1.2];
+ $pairManager = $this->createMock(PairManagerInterface::class);
+ $pairManager
+ ->expects($this->once())
+ ->method('getRatioList')
+ ->willReturn($data);
+
+ $command = new RatioListCommand($pairManager);
+ $tester = new CommandTester($command);
+ $tester->execute(['--format' => 'json']);
+ self::assertSame(Command::SUCCESS, $tester->getStatusCode());
+ self::assertJson($tester->getDisplay());
+ $output = json_decode($tester->getDisplay(), true);
+ self::assertSame($data, $output);
+ }
}
diff --git a/src/Command/RatioListCommand.php b/src/Command/RatioListCommand.php
index 2117e9fd..d03762a2 100644
--- a/src/Command/RatioListCommand.php
+++ b/src/Command/RatioListCommand.php
@@ -5,15 +5,21 @@
namespace Tbbc\MoneyBundle\Command;
use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Completion\CompletionInput;
+use Symfony\Component\Console\Completion\CompletionSuggestions;
+use Symfony\Component\Console\Completion\Suggestion;
+use Symfony\Component\Console\Exception\InvalidArgumentException;
+use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
use Tbbc\MoneyBundle\Pair\PairManagerInterface;
-/**
- * Class RatioListCommand.
- */
class RatioListCommand extends Command
{
+ private string $format = 'txt';
+
public function __construct(private PairManagerInterface $pairManager)
{
parent::__construct();
@@ -23,21 +29,86 @@ protected function configure(): void
{
$this
->setName('tbbc:money:ratio-list')
+ ->addOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'txt')
->setHelp('The tbbc:money:ratio-list display list of registered ratio')
->setDescription('display list of registered ratio');
}
- protected function execute(InputInterface $input, OutputInterface $output): int
+ /**
+ * @param array $ratioList
+ */
+ protected function displayTxt(array $ratioList, OutputInterface $output, SymfonyStyle $io): int
{
- $ratioList = $this->pairManager->getRatioList();
- $output->writeln('Ratio list');
- /**
- * @var float $ratio
- */
+ $io->writeln('Ratio list');
+
foreach ($ratioList as $currencyCode => $ratio) {
- $output->writeln($currencyCode.';'.(string) $ratio);
+ $io->writeln($currencyCode.';'.(string) $ratio);
+ }
+
+ return Command::SUCCESS;
+ }
+
+ /**
+ * @param array $ratioList
+ */
+ protected function displayTable(array $ratioList, OutputInterface $output, SymfonyStyle $io): int
+ {
+ $table = new Table($io);
+ $table->setHeaderTitle('Ratio list');
+ $table->setHeaders(['Currency', 'Ratio']);
+
+ foreach ($ratioList as $currencyCode => $ratio) {
+ $table->addRow([$currencyCode, $ratio]);
+ }
+
+ $table->render();
+
+ return Command::SUCCESS;
+ }
+
+ /**
+ * @param array $ratioList
+ */
+ protected function displayJson(array $ratioList, OutputInterface $output): int
+ {
+ $output->writeln(json_encode($ratioList, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES));
+
+ return Command::SUCCESS;
+ }
+
+ private function display(OutputInterface $output, SymfonyStyle $io): int
+ {
+ $ratioList = $this->pairManager->getRatioList();
+
+ return match ($this->format) {
+ 'txt' => $this->displayTxt($ratioList, $output, $io),
+ 'json' => $this->displayJson($ratioList, $output),
+ 'table' => $this->displayTable($ratioList, $output, $io),
+ default => throw new InvalidArgumentException(sprintf('Supported formats are "%s".', implode('", "', $this->getAvailableFormatOptions()))),
+ };
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $io = new SymfonyStyle($input, $output);
+
+ /** @var string $format */
+ $format = $input->getOption('format') ?? 'txt';
+ $this->format = $format;
+
+ return $this->display($output, $io);
+ }
+
+ public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
+ {
+ if ($input->mustSuggestOptionValuesFor('format')) {
+ $suggestions->suggestValues($this->getAvailableFormatOptions());
}
+ }
- return 0;
+ /** @return list $values */
+ private function getAvailableFormatOptions(): array
+ {
+ return ['txt', 'json', 'table'];
}
}
diff --git a/src/Pair/PairManagerInterface.php b/src/Pair/PairManagerInterface.php
index 1763a0b0..f360f8b6 100644
--- a/src/Pair/PairManagerInterface.php
+++ b/src/Pair/PairManagerInterface.php
@@ -48,6 +48,8 @@ public function getReferenceCurrencyCode(): string;
/**
* return ratio list for currencies in comparison to reference currency
* array of type array("EUR" => 1, "USD" => 1.25);.
+ *
+ * @return array
*/
public function getRatioList(): array;