mirror of
https://github.com/shlinkio/shlink.git
synced 2026-03-10 09:13:11 +08:00
Created command that allows configuring not found redirects for every domain
This commit is contained in:
114
module/CLI/src/Command/Domain/DomainRedirectsCommand.php
Normal file
114
module/CLI/src/Command/Domain/DomainRedirectsCommand.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\CLI\Command\Domain;
|
||||
|
||||
use Shlinkio\Shlink\CLI\Util\ExitCodes;
|
||||
use Shlinkio\Shlink\Core\Config\NotFoundRedirects;
|
||||
use Shlinkio\Shlink\Core\Domain\DomainServiceInterface;
|
||||
use Shlinkio\Shlink\Core\Domain\Model\DomainItem;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
use function Functional\filter;
|
||||
use function Functional\invoke;
|
||||
use function sprintf;
|
||||
use function str_contains;
|
||||
|
||||
class DomainRedirectsCommand extends Command
|
||||
{
|
||||
public const NAME = 'domain:redirects';
|
||||
|
||||
public function __construct(private DomainServiceInterface $domainService)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->setName(self::NAME)
|
||||
->setDescription('Set specific "not found" redirects for individual domains.')
|
||||
->addArgument(
|
||||
'domain',
|
||||
InputArgument::REQUIRED,
|
||||
'The domain authority to which you want to set the specific redirects',
|
||||
);
|
||||
}
|
||||
|
||||
protected function interact(InputInterface $input, OutputInterface $output): void
|
||||
{
|
||||
/** @var string|null $domain */
|
||||
$domain = $input->getArgument('domain');
|
||||
if ($domain !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$askNewDomain = static fn () => $io->ask('Domain authority for which you want to set specific redirects');
|
||||
|
||||
/** @var string[] $availableDomains */
|
||||
$availableDomains = invoke(
|
||||
filter($this->domainService->listDomains(), static fn (DomainItem $item) => ! $item->isDefault()),
|
||||
'toString',
|
||||
);
|
||||
if (empty($availableDomains)) {
|
||||
$input->setArgument('domain', $askNewDomain());
|
||||
return;
|
||||
}
|
||||
|
||||
$selectedOption = $io->choice(
|
||||
'Select the domain to configure',
|
||||
[...$availableDomains, '<options=bold>New domain</>'],
|
||||
);
|
||||
$input->setArgument('domain', str_contains($selectedOption, 'New domain') ? $askNewDomain() : $selectedOption);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): ?int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$domainAuthority = $input->getArgument('domain');
|
||||
$domain = $this->domainService->findByAuthority($domainAuthority);
|
||||
|
||||
$ask = static function (string $message, ?string $current) use ($io): ?string {
|
||||
if ($current === null) {
|
||||
return $io->ask(sprintf('%s (Leave empty for no redirect)', $message));
|
||||
}
|
||||
|
||||
$choice = $io->choice($message, [
|
||||
sprintf('Keep current one: [%s]', $current),
|
||||
'Set new redirect URL',
|
||||
'Remove redirect',
|
||||
]);
|
||||
|
||||
return match ($choice) {
|
||||
'Set new redirect URL' => $io->ask('New redirect URL'),
|
||||
'Remove redirect' => null,
|
||||
default => $current,
|
||||
};
|
||||
};
|
||||
|
||||
$this->domainService->configureNotFoundRedirects($domainAuthority, new NotFoundRedirects(
|
||||
$ask(
|
||||
'URL to redirect to when a user hits this domain\'s base URL',
|
||||
$domain?->baseUrlRedirect(),
|
||||
),
|
||||
$ask(
|
||||
'URL to redirect to when a user hits a not found URL other than an invalid short URL',
|
||||
$domain?->regular404Redirect(),
|
||||
),
|
||||
$ask(
|
||||
'URL to redirect to when a user hits an invalid short URL',
|
||||
$domain?->invalidShortUrlRedirect(),
|
||||
),
|
||||
));
|
||||
|
||||
$io->success(sprintf('"Not found" redirects properly set for "%s"', $domainAuthority));
|
||||
|
||||
return ExitCodes::EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,12 @@ namespace Shlinkio\Shlink\CLI\Command\Domain;
|
||||
|
||||
use Shlinkio\Shlink\CLI\Util\ExitCodes;
|
||||
use Shlinkio\Shlink\CLI\Util\ShlinkTable;
|
||||
use Shlinkio\Shlink\Core\Config\NotFoundRedirectConfigInterface;
|
||||
use Shlinkio\Shlink\Core\Domain\DomainServiceInterface;
|
||||
use Shlinkio\Shlink\Core\Domain\Model\DomainItem;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
use function Functional\map;
|
||||
@@ -27,18 +29,48 @@ class ListDomainsCommand extends Command
|
||||
{
|
||||
$this
|
||||
->setName(self::NAME)
|
||||
->setDescription('List all domains that have been ever used for some short URL');
|
||||
->setDescription('List all domains that have been ever used for some short URL')
|
||||
->addOption(
|
||||
'show-redirects',
|
||||
'r',
|
||||
InputOption::VALUE_NONE,
|
||||
'Will display an extra column with the information of the "not found" redirects for every domain.',
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): ?int
|
||||
{
|
||||
$domains = $this->domainService->listDomains();
|
||||
$showRedirects = $input->getOption('show-redirects');
|
||||
$commonFields = ['Domain', 'Is default'];
|
||||
|
||||
ShlinkTable::fromOutput($output)->render(
|
||||
['Domain', 'Is default'],
|
||||
map($domains, fn (DomainItem $domain) => [$domain->toString(), $domain->isDefault() ? 'Yes' : 'No']),
|
||||
$showRedirects ? [...$commonFields, '"Not found" redirects'] : $commonFields,
|
||||
map($domains, function (DomainItem $domain) use ($showRedirects) {
|
||||
$commonValues = [$domain->toString(), $domain->isDefault() ? 'Yes' : 'No'];
|
||||
|
||||
return $showRedirects
|
||||
? [
|
||||
...$commonValues,
|
||||
$this->notFoundRedirectsToString($domain->notFoundRedirectConfig()),
|
||||
]
|
||||
: $commonValues;
|
||||
}),
|
||||
);
|
||||
|
||||
return ExitCodes::EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
private function notFoundRedirectsToString(NotFoundRedirectConfigInterface $config): string
|
||||
{
|
||||
$baseUrl = $config->baseUrlRedirect() ?? 'N/A';
|
||||
$regular404 = $config->regular404Redirect() ?? 'N/A';
|
||||
$invalidShortUrl = $config->invalidShortUrlRedirect() ?? 'N/A';
|
||||
|
||||
return <<<EOL
|
||||
* Base URL: {$baseUrl}
|
||||
* Regular 404: {$regular404}
|
||||
* Invalid short URL: {$invalidShortUrl}
|
||||
EOL;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user