mirror of
https://github.com/shlinkio/shlink.git
synced 2025-02-25 18:45:27 -06:00
156 lines
5.6 KiB
PHP
156 lines
5.6 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;
|
|
|
|
use Cake\Chronos\Chronos;
|
|
use Shlinkio\Shlink\CLI\Util\ExitCodes;
|
|
use Shlinkio\Shlink\Core\Exception\InvalidUrlException;
|
|
use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException;
|
|
use Shlinkio\Shlink\Core\Model\ShortUrlMeta;
|
|
use Shlinkio\Shlink\Core\Service\UrlShortenerInterface;
|
|
use Shlinkio\Shlink\Core\Util\ShortUrlBuilderTrait;
|
|
use Symfony\Component\Console\Command\Command;
|
|
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\Console\Style\SymfonyStyle;
|
|
use Zend\Diactoros\Uri;
|
|
use function array_map;
|
|
use function Functional\curry;
|
|
use function Functional\flatten;
|
|
use function Functional\unique;
|
|
use function sprintf;
|
|
|
|
class GenerateShortUrlCommand extends Command
|
|
{
|
|
use ShortUrlBuilderTrait;
|
|
|
|
public const NAME = 'short-url:generate';
|
|
private const ALIASES = ['shortcode:generate', 'short-code:generate'];
|
|
|
|
/** @var UrlShortenerInterface */
|
|
private $urlShortener;
|
|
/** @var array */
|
|
private $domainConfig;
|
|
|
|
public function __construct(UrlShortenerInterface $urlShortener, array $domainConfig)
|
|
{
|
|
parent::__construct();
|
|
$this->urlShortener = $urlShortener;
|
|
$this->domainConfig = $domainConfig;
|
|
}
|
|
|
|
protected function configure(): void
|
|
{
|
|
$this
|
|
->setName(self::NAME)
|
|
->setAliases(self::ALIASES)
|
|
->setDescription('Generates a short URL for provided long URL and returns it')
|
|
->addArgument('longUrl', InputArgument::REQUIRED, 'The long URL to parse')
|
|
->addOption(
|
|
'tags',
|
|
't',
|
|
InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED,
|
|
'Tags to apply to the new short URL'
|
|
)
|
|
->addOption(
|
|
'validSince',
|
|
's',
|
|
InputOption::VALUE_REQUIRED,
|
|
'The date from which this short URL will be valid. '
|
|
. 'If someone tries to access it before this date, it will not be found.'
|
|
)
|
|
->addOption(
|
|
'validUntil',
|
|
'u',
|
|
InputOption::VALUE_REQUIRED,
|
|
'The date until which this short URL will be valid. '
|
|
. 'If someone tries to access it after this date, it will not be found.'
|
|
)
|
|
->addOption(
|
|
'customSlug',
|
|
'c',
|
|
InputOption::VALUE_REQUIRED,
|
|
'If provided, this slug will be used instead of generating a short code'
|
|
)
|
|
->addOption(
|
|
'maxVisits',
|
|
'm',
|
|
InputOption::VALUE_REQUIRED,
|
|
'This will limit the number of visits for this short URL.'
|
|
)
|
|
->addOption(
|
|
'findIfExists',
|
|
'f',
|
|
InputOption::VALUE_NONE,
|
|
'This will force existing matching URL to be returned if found, instead of creating a new one.'
|
|
);
|
|
}
|
|
|
|
protected function interact(InputInterface $input, OutputInterface $output): void
|
|
{
|
|
$io = new SymfonyStyle($input, $output);
|
|
$longUrl = $input->getArgument('longUrl');
|
|
if (! empty($longUrl)) {
|
|
return;
|
|
}
|
|
|
|
$longUrl = $io->ask('A long URL was not provided. Which URL do you want to be shortened?');
|
|
if (! empty($longUrl)) {
|
|
$input->setArgument('longUrl', $longUrl);
|
|
}
|
|
}
|
|
|
|
protected function execute(InputInterface $input, OutputInterface $output): ?int
|
|
{
|
|
$io = new SymfonyStyle($input, $output);
|
|
$longUrl = $input->getArgument('longUrl');
|
|
if (empty($longUrl)) {
|
|
$io->error('A URL was not provided!');
|
|
return ExitCodes::EXIT_FAILURE;
|
|
}
|
|
|
|
$explodeWithComma = curry('explode')(',');
|
|
$tags = unique(flatten(array_map($explodeWithComma, $input->getOption('tags'))));
|
|
$customSlug = $input->getOption('customSlug');
|
|
$maxVisits = $input->getOption('maxVisits');
|
|
|
|
try {
|
|
$shortCode = $this->urlShortener->urlToShortCode(
|
|
new Uri($longUrl),
|
|
$tags,
|
|
ShortUrlMeta::createFromParams(
|
|
$this->getOptionalDate($input, 'validSince'),
|
|
$this->getOptionalDate($input, 'validUntil'),
|
|
$customSlug,
|
|
$maxVisits !== null ? (int) $maxVisits : null,
|
|
$input->getOption('findIfExists')
|
|
)
|
|
)->getShortCode();
|
|
$shortUrl = $this->buildShortUrl($this->domainConfig, $shortCode);
|
|
|
|
$io->writeln([
|
|
sprintf('Processed long URL: <info>%s</info>', $longUrl),
|
|
sprintf('Generated short URL: <info>%s</info>', $shortUrl),
|
|
]);
|
|
return ExitCodes::EXIT_SUCCESS;
|
|
} catch (InvalidUrlException $e) {
|
|
$io->error(sprintf('Provided URL "%s" is invalid. Try with a different one.', $longUrl));
|
|
return ExitCodes::EXIT_FAILURE;
|
|
} catch (NonUniqueSlugException $e) {
|
|
$io->error(
|
|
sprintf('Provided slug "%s" is already in use by another URL. Try with a different one.', $customSlug)
|
|
);
|
|
return ExitCodes::EXIT_FAILURE;
|
|
}
|
|
}
|
|
|
|
private function getOptionalDate(InputInterface $input, string $fieldName): ?Chronos
|
|
{
|
|
$since = $input->getOption($fieldName);
|
|
return $since !== null ? Chronos::parse($since) : null;
|
|
}
|
|
}
|