From 20f70b8b07066cc92f6d065401122211663a2873 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Tue, 3 Aug 2021 10:21:42 +0200 Subject: [PATCH] Created new table with row separators for CLI, to use with multi-line rows --- .../src/Command/Api/GenerateKeyCommand.php | 2 +- .../CLI/src/Command/Api/ListKeysCommand.php | 2 +- .../src/Command/Domain/ListDomainsCommand.php | 3 ++- .../src/Command/ShortUrl/GetVisitsCommand.php | 2 +- .../Command/ShortUrl/ListShortUrlsCommand.php | 2 +- .../CLI/src/Command/Tag/ListTagsCommand.php | 2 +- module/CLI/src/Util/ShlinkTable.php | 22 +++++++++++++++---- .../test/Command/Api/ListKeysCommandTest.php | 11 ++++++++++ .../Command/Domain/ListDomainsCommandTest.php | 2 ++ module/CLI/test/Util/ShlinkTableTest.php | 4 ++-- 10 files changed, 40 insertions(+), 12 deletions(-) diff --git a/module/CLI/src/Command/Api/GenerateKeyCommand.php b/module/CLI/src/Command/Api/GenerateKeyCommand.php index c8f607a4..d39c05fa 100644 --- a/module/CLI/src/Command/Api/GenerateKeyCommand.php +++ b/module/CLI/src/Command/Api/GenerateKeyCommand.php @@ -97,7 +97,7 @@ class GenerateKeyCommand extends BaseCommand $io->success(sprintf('Generated API key: "%s"', $apiKey->toString())); if (! $apiKey->isAdmin()) { - ShlinkTable::fromOutput($io)->render( + ShlinkTable::default($io)->render( ['Role name', 'Role metadata'], $apiKey->mapRoles(fn (string $name, array $meta) => [$name, arrayToString($meta, 0)]), null, diff --git a/module/CLI/src/Command/Api/ListKeysCommand.php b/module/CLI/src/Command/Api/ListKeysCommand.php index f435f1ea..23258993 100644 --- a/module/CLI/src/Command/Api/ListKeysCommand.php +++ b/module/CLI/src/Command/Api/ListKeysCommand.php @@ -69,7 +69,7 @@ class ListKeysCommand extends BaseCommand return $rowData; }); - ShlinkTable::fromOutput($output)->render(array_filter([ + ShlinkTable::withRowSeparators($output)->render(array_filter([ 'Key', 'Name', ! $enabledOnly ? 'Is enabled' : null, diff --git a/module/CLI/src/Command/Domain/ListDomainsCommand.php b/module/CLI/src/Command/Domain/ListDomainsCommand.php index 5e368170..447bf92f 100644 --- a/module/CLI/src/Command/Domain/ListDomainsCommand.php +++ b/module/CLI/src/Command/Domain/ListDomainsCommand.php @@ -43,8 +43,9 @@ class ListDomainsCommand extends Command $domains = $this->domainService->listDomains(); $showRedirects = $input->getOption('show-redirects'); $commonFields = ['Domain', 'Is default']; + $table = $showRedirects ? ShlinkTable::withRowSeparators($output) : ShlinkTable::default($output); - ShlinkTable::fromOutput($output)->render( + $table->render( $showRedirects ? [...$commonFields, '"Not found" redirects'] : $commonFields, map($domains, function (DomainItem $domain) use ($showRedirects) { $commonValues = [$domain->toString(), $domain->isDefault() ? 'Yes' : 'No']; diff --git a/module/CLI/src/Command/ShortUrl/GetVisitsCommand.php b/module/CLI/src/Command/ShortUrl/GetVisitsCommand.php index aac45aff..5113debc 100644 --- a/module/CLI/src/Command/ShortUrl/GetVisitsCommand.php +++ b/module/CLI/src/Command/ShortUrl/GetVisitsCommand.php @@ -81,7 +81,7 @@ class GetVisitsCommand extends AbstractWithDateRangeCommand $rowData['country'] = ($visit->getVisitLocation() ?? new UnknownVisitLocation())->getCountryName(); return select_keys($rowData, ['referer', 'date', 'userAgent', 'country']); }); - ShlinkTable::fromOutput($output)->render(['Referer', 'Date', 'User agent', 'Country'], $rows); + ShlinkTable::default($output)->render(['Referer', 'Date', 'User agent', 'Country'], $rows); return ExitCodes::EXIT_SUCCESS; } diff --git a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php index b5d242dc..ff01030a 100644 --- a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php +++ b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php @@ -164,7 +164,7 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand return map($columnsMap, fn (callable $call) => $call($rawShortUrl, $shortUrl)); }); - ShlinkTable::fromOutput($output)->render( + ShlinkTable::default($output)->render( array_keys($columnsMap), $rows, $all ? null : $this->formatCurrentPageMessage($shortUrls, 'Page %s of %s'), diff --git a/module/CLI/src/Command/Tag/ListTagsCommand.php b/module/CLI/src/Command/Tag/ListTagsCommand.php index 99889fa3..61d4e6e0 100644 --- a/module/CLI/src/Command/Tag/ListTagsCommand.php +++ b/module/CLI/src/Command/Tag/ListTagsCommand.php @@ -32,7 +32,7 @@ class ListTagsCommand extends Command protected function execute(InputInterface $input, OutputInterface $output): ?int { - ShlinkTable::fromOutput($output)->render(['Name', 'URLs amount', 'Visits amount'], $this->getTagsRows()); + ShlinkTable::default($output)->render(['Name', 'URLs amount', 'Visits amount'], $this->getTagsRows()); return ExitCodes::EXIT_SUCCESS; } diff --git a/module/CLI/src/Util/ShlinkTable.php b/module/CLI/src/Util/ShlinkTable.php index 5788ce12..1d4143c1 100644 --- a/module/CLI/src/Util/ShlinkTable.php +++ b/module/CLI/src/Util/ShlinkTable.php @@ -5,20 +5,33 @@ declare(strict_types=1); namespace Shlinkio\Shlink\CLI\Util; use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Helper\TableSeparator; use Symfony\Component\Console\Output\OutputInterface; +use function Functional\intersperse; + final class ShlinkTable { private const DEFAULT_STYLE_NAME = 'default'; private const TABLE_TITLE_STYLE = ' %s '; - public function __construct(private Table $baseTable) + private function __construct(private Table $baseTable, private bool $withRowSeparators) { } - public static function fromOutput(OutputInterface $output): self + public static function default(OutputInterface $output): self { - return new self(new Table($output)); + return new self(new Table($output), false); + } + + public static function withRowSeparators(OutputInterface $output): self + { + return new self(new Table($output), true); + } + + public static function fromBaseTable(Table $baseTable): self + { + return new self($baseTable, false); } public function render(array $headers, array $rows, ?string $footerTitle = null, ?string $headerTitle = null): void @@ -26,11 +39,12 @@ final class ShlinkTable $style = Table::getStyleDefinition(self::DEFAULT_STYLE_NAME); $style->setFooterTitleFormat(self::TABLE_TITLE_STYLE) ->setHeaderTitleFormat(self::TABLE_TITLE_STYLE); + $tableRows = $this->withRowSeparators ? intersperse($rows, new TableSeparator()) : $rows; $table = clone $this->baseTable; $table->setStyle($style) ->setHeaders($headers) - ->setRows($rows) + ->setRows($tableRows) ->setFooterTitle($footerTitle) ->setHeaderTitle($headerTitle) ->render(); diff --git a/module/CLI/test/Command/Api/ListKeysCommandTest.php b/module/CLI/test/Command/Api/ListKeysCommandTest.php index 389c6bbd..a124993f 100644 --- a/module/CLI/test/Command/Api/ListKeysCommandTest.php +++ b/module/CLI/test/Command/Api/ListKeysCommandTest.php @@ -53,7 +53,9 @@ class ListKeysCommandTest extends TestCase | Key | Name | Is enabled | Expiration date | Roles | +--------------------------------------+------+------------+-----------------+-------+ | {$apiKey1} | - | +++ | - | Admin | + +--------------------------------------+------+------------+-----------------+-------+ | {$apiKey2} | - | +++ | - | Admin | + +--------------------------------------+------+------------+-----------------+-------+ | {$apiKey3} | - | +++ | - | Admin | +--------------------------------------+------+------------+-----------------+-------+ @@ -67,6 +69,7 @@ class ListKeysCommandTest extends TestCase | Key | Name | Expiration date | Roles | +--------------------------------------+------+-----------------+-------+ | {$apiKey1} | - | - | Admin | + +--------------------------------------+------+-----------------+-------+ | {$apiKey2} | - | - | Admin | +--------------------------------------+------+-----------------+-------+ @@ -92,11 +95,16 @@ class ListKeysCommandTest extends TestCase | Key | Name | Expiration date | Roles | +--------------------------------------+------+-----------------+--------------------------+ | {$apiKey1} | - | - | Admin | + +--------------------------------------+------+-----------------+--------------------------+ | {$apiKey2} | - | - | Author only | + +--------------------------------------+------+-----------------+--------------------------+ | {$apiKey3} | - | - | Domain only: example.com | + +--------------------------------------+------+-----------------+--------------------------+ | {$apiKey4} | - | - | Admin | + +--------------------------------------+------+-----------------+--------------------------+ | {$apiKey5} | - | - | Author only | | | | | Domain only: example.com | + +--------------------------------------+------+-----------------+--------------------------+ | {$apiKey6} | - | - | Admin | +--------------------------------------+------+-----------------+--------------------------+ @@ -115,8 +123,11 @@ class ListKeysCommandTest extends TestCase | Key | Name | Expiration date | Roles | +--------------------------------------+---------------+-----------------+-------+ | {$apiKey1} | Alice | - | Admin | + +--------------------------------------+---------------+-----------------+-------+ | {$apiKey2} | Alice and Bob | - | Admin | + +--------------------------------------+---------------+-----------------+-------+ | {$apiKey3} | | - | Admin | + +--------------------------------------+---------------+-----------------+-------+ | {$apiKey4} | - | - | Admin | +--------------------------------------+---------------+-----------------+-------+ diff --git a/module/CLI/test/Command/Domain/ListDomainsCommandTest.php b/module/CLI/test/Command/Domain/ListDomainsCommandTest.php index 9f4be920..3f31f7e0 100644 --- a/module/CLI/test/Command/Domain/ListDomainsCommandTest.php +++ b/module/CLI/test/Command/Domain/ListDomainsCommandTest.php @@ -77,9 +77,11 @@ class ListDomainsCommandTest extends TestCase | foo.com | Yes | * Base URL: https://foo.com/default/base | | | | * Regular 404: N/A | | | | * Invalid short URL: https://foo.com/default/invalid | + +---------+------------+---------------------------------------------------------+ | bar.com | No | * Base URL: N/A | | | | * Regular 404: N/A | | | | * Invalid short URL: N/A | + +---------+------------+---------------------------------------------------------+ | baz.com | No | * Base URL: N/A | | | | * Regular 404: https://foo.com/baz-domain/regular | | | | * Invalid short URL: https://foo.com/baz-domain/invalid | diff --git a/module/CLI/test/Util/ShlinkTableTest.php b/module/CLI/test/Util/ShlinkTableTest.php index 71bff82b..1ca612d4 100644 --- a/module/CLI/test/Util/ShlinkTableTest.php +++ b/module/CLI/test/Util/ShlinkTableTest.php @@ -24,7 +24,7 @@ class ShlinkTableTest extends TestCase public function setUp(): void { $this->baseTable = $this->prophesize(Table::class); - $this->shlinkTable = new ShlinkTable($this->baseTable->reveal()); + $this->shlinkTable = ShlinkTable::fromBaseTable($this->baseTable->reveal()); } /** @test */ @@ -57,7 +57,7 @@ class ShlinkTableTest extends TestCase /** @test */ public function newTableIsCreatedForFactoryMethod(): void { - $instance = ShlinkTable::fromOutput($this->prophesize(OutputInterface::class)->reveal()); + $instance = ShlinkTable::default($this->prophesize(OutputInterface::class)->reveal()); $ref = new ReflectionObject($instance); $baseTable = $ref->getProperty('baseTable');