diff --git a/module/CLI/config/cli.config.php b/module/CLI/config/cli.config.php
index 7629d855..012c6800 100644
--- a/module/CLI/config/cli.config.php
+++ b/module/CLI/config/cli.config.php
@@ -13,6 +13,7 @@ return [
Command\ShortUrl\ListShortUrlsCommand::NAME => Command\ShortUrl\ListShortUrlsCommand::class,
Command\ShortUrl\GetShortUrlVisitsCommand::NAME => Command\ShortUrl\GetShortUrlVisitsCommand::class,
Command\ShortUrl\DeleteShortUrlCommand::NAME => Command\ShortUrl\DeleteShortUrlCommand::class,
+ Command\ShortUrl\DeleteShortUrlVisitsCommand::NAME => Command\ShortUrl\DeleteShortUrlVisitsCommand::class,
Command\Visit\LocateVisitsCommand::NAME => Command\Visit\LocateVisitsCommand::class,
Command\Visit\DownloadGeoLiteDbCommand::NAME => Command\Visit\DownloadGeoLiteDbCommand::class,
diff --git a/module/CLI/config/dependencies.config.php b/module/CLI/config/dependencies.config.php
index e5176f42..384df91d 100644
--- a/module/CLI/config/dependencies.config.php
+++ b/module/CLI/config/dependencies.config.php
@@ -42,6 +42,7 @@ return [
Command\ShortUrl\ListShortUrlsCommand::class => ConfigAbstractFactory::class,
Command\ShortUrl\GetShortUrlVisitsCommand::class => ConfigAbstractFactory::class,
Command\ShortUrl\DeleteShortUrlCommand::class => ConfigAbstractFactory::class,
+ Command\ShortUrl\DeleteShortUrlVisitsCommand::class => ConfigAbstractFactory::class,
Command\Visit\DownloadGeoLiteDbCommand::class => ConfigAbstractFactory::class,
Command\Visit\LocateVisitsCommand::class => ConfigAbstractFactory::class,
@@ -88,6 +89,7 @@ return [
],
Command\ShortUrl\GetShortUrlVisitsCommand::class => [Visit\VisitsStatsHelper::class],
Command\ShortUrl\DeleteShortUrlCommand::class => [ShortUrl\DeleteShortUrlService::class],
+ Command\ShortUrl\DeleteShortUrlVisitsCommand::class => [ShortUrl\ShortUrlVisitsDeleter::class],
Command\Visit\DownloadGeoLiteDbCommand::class => [GeoLite\GeolocationDbUpdater::class],
Command\Visit\LocateVisitsCommand::class => [
diff --git a/module/CLI/src/Command/Api/DisableKeyCommand.php b/module/CLI/src/Command/Api/DisableKeyCommand.php
index 7296632a..4844121e 100644
--- a/module/CLI/src/Command/Api/DisableKeyCommand.php
+++ b/module/CLI/src/Command/Api/DisableKeyCommand.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Api;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\Common\Exception\InvalidArgumentException;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
use Symfony\Component\Console\Command\Command;
@@ -39,10 +39,10 @@ class DisableKeyCommand extends Command
try {
$this->apiKeyService->disable($apiKey);
$io->success(sprintf('API key "%s" properly disabled', $apiKey));
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
} catch (InvalidArgumentException $e) {
$io->error($e->getMessage());
- return ExitCodes::EXIT_FAILURE;
+ return ExitCode::EXIT_FAILURE;
}
}
}
diff --git a/module/CLI/src/Command/Api/GenerateKeyCommand.php b/module/CLI/src/Command/Api/GenerateKeyCommand.php
index c89c4fbf..c2d6cf10 100644
--- a/module/CLI/src/Command/Api/GenerateKeyCommand.php
+++ b/module/CLI/src/Command/Api/GenerateKeyCommand.php
@@ -6,7 +6,7 @@ namespace Shlinkio\Shlink\CLI\Command\Api;
use Cake\Chronos\Chronos;
use Shlinkio\Shlink\CLI\ApiKey\RoleResolverInterface;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\CLI\Util\ShlinkTable;
use Shlinkio\Shlink\Rest\ApiKey\Role;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
@@ -109,6 +109,6 @@ class GenerateKeyCommand extends Command
);
}
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
}
}
diff --git a/module/CLI/src/Command/Api/ListKeysCommand.php b/module/CLI/src/Command/Api/ListKeysCommand.php
index c7e31819..87b239b7 100644
--- a/module/CLI/src/Command/Api/ListKeysCommand.php
+++ b/module/CLI/src/Command/Api/ListKeysCommand.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Api;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\CLI\Util\ShlinkTable;
use Shlinkio\Shlink\Rest\ApiKey\Role;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
@@ -77,7 +77,7 @@ class ListKeysCommand extends Command
'Roles',
]), $rows);
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
}
private function determineMessagePattern(ApiKey $apiKey): string
diff --git a/module/CLI/src/Command/Db/CreateDatabaseCommand.php b/module/CLI/src/Command/Db/CreateDatabaseCommand.php
index 95b08da2..f6df9b04 100644
--- a/module/CLI/src/Command/Db/CreateDatabaseCommand.php
+++ b/module/CLI/src/Command/Db/CreateDatabaseCommand.php
@@ -8,7 +8,7 @@ use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\CLI\Util\ProcessRunnerInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -57,7 +57,7 @@ class CreateDatabaseCommand extends AbstractDatabaseCommand
if ($this->schemaExists()) {
$io->success('Database already exists. Run "db:migrate" command to make sure it is up to date.');
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
}
// Create database
@@ -65,7 +65,7 @@ class CreateDatabaseCommand extends AbstractDatabaseCommand
$this->runPhpCommand($output, [self::DOCTRINE_SCRIPT, self::DOCTRINE_CREATE_SCHEMA_COMMAND]);
$io->success('Database properly created!');
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
}
private function checkDbExists(): void
diff --git a/module/CLI/src/Command/Db/MigrateDatabaseCommand.php b/module/CLI/src/Command/Db/MigrateDatabaseCommand.php
index 379e57e0..a912cf24 100644
--- a/module/CLI/src/Command/Db/MigrateDatabaseCommand.php
+++ b/module/CLI/src/Command/Db/MigrateDatabaseCommand.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Db;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
@@ -31,6 +31,6 @@ class MigrateDatabaseCommand extends AbstractDatabaseCommand
$this->runPhpCommand($output, [self::DOCTRINE_MIGRATIONS_SCRIPT, self::DOCTRINE_MIGRATE_COMMAND]);
$io->success('Database properly migrated!');
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
}
}
diff --git a/module/CLI/src/Command/Domain/DomainRedirectsCommand.php b/module/CLI/src/Command/Domain/DomainRedirectsCommand.php
index c546fd5b..4a3f8062 100644
--- a/module/CLI/src/Command/Domain/DomainRedirectsCommand.php
+++ b/module/CLI/src/Command/Domain/DomainRedirectsCommand.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Domain;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\Core\Config\NotFoundRedirects;
use Shlinkio\Shlink\Core\Domain\DomainServiceInterface;
use Shlinkio\Shlink\Core\Domain\Model\DomainItem;
@@ -109,6 +109,6 @@ class DomainRedirectsCommand extends Command
$io->success(sprintf('"Not found" redirects properly set for "%s"', $domainAuthority));
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
}
}
diff --git a/module/CLI/src/Command/Domain/ListDomainsCommand.php b/module/CLI/src/Command/Domain/ListDomainsCommand.php
index 8f2ee22c..11a0f5b9 100644
--- a/module/CLI/src/Command/Domain/ListDomainsCommand.php
+++ b/module/CLI/src/Command/Domain/ListDomainsCommand.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Domain;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\CLI\Util\ShlinkTable;
use Shlinkio\Shlink\Core\Config\NotFoundRedirectConfigInterface;
use Shlinkio\Shlink\Core\Domain\DomainServiceInterface;
@@ -59,7 +59,7 @@ class ListDomainsCommand extends Command
}),
);
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
}
private function notFoundRedirectsToString(NotFoundRedirectConfigInterface $config): string
diff --git a/module/CLI/src/Command/ShortUrl/CreateShortUrlCommand.php b/module/CLI/src/Command/ShortUrl/CreateShortUrlCommand.php
index a998a677..f55f247d 100644
--- a/module/CLI/src/Command/ShortUrl/CreateShortUrlCommand.php
+++ b/module/CLI/src/Command/ShortUrl/CreateShortUrlCommand.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\Core\Exception\InvalidUrlException;
use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException;
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
@@ -141,7 +141,7 @@ class CreateShortUrlCommand extends Command
$longUrl = $input->getArgument('longUrl');
if (empty($longUrl)) {
$io->error('A URL was not provided!');
- return ExitCodes::EXIT_FAILURE;
+ return ExitCode::EXIT_FAILURE;
}
$explodeWithComma = curry(explode(...))(',');
@@ -176,10 +176,10 @@ class CreateShortUrlCommand extends Command
sprintf('Processed long URL: %s', $longUrl),
sprintf('Generated short URL: %s', $this->stringifier->stringify($result->shortUrl)),
]);
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
} catch (InvalidUrlException | NonUniqueSlugException $e) {
$io->error($e->getMessage());
- return ExitCodes::EXIT_FAILURE;
+ return ExitCode::EXIT_FAILURE;
}
}
diff --git a/module/CLI/src/Command/ShortUrl/DeleteShortUrlCommand.php b/module/CLI/src/Command/ShortUrl/DeleteShortUrlCommand.php
index 1db5b1f6..11cfa270 100644
--- a/module/CLI/src/Command/ShortUrl/DeleteShortUrlCommand.php
+++ b/module/CLI/src/Command/ShortUrl/DeleteShortUrlCommand.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\Core\Exception;
use Shlinkio\Shlink\Core\ShortUrl\DeleteShortUrlServiceInterface;
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier;
@@ -55,10 +55,10 @@ class DeleteShortUrlCommand extends Command
try {
$this->runDelete($io, $identifier, $ignoreThreshold);
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
} catch (Exception\ShortUrlNotFoundException $e) {
$io->error($e->getMessage());
- return ExitCodes::EXIT_FAILURE;
+ return ExitCode::EXIT_FAILURE;
} catch (Exception\DeleteShortUrlException $e) {
return $this->retry($io, $identifier, $e->getMessage());
}
@@ -75,7 +75,7 @@ class DeleteShortUrlCommand extends Command
$io->warning('Short URL was not deleted.');
}
- return $forceDelete ? ExitCodes::EXIT_SUCCESS : ExitCodes::EXIT_WARNING;
+ return $forceDelete ? ExitCode::EXIT_SUCCESS : ExitCode::EXIT_WARNING;
}
private function runDelete(SymfonyStyle $io, ShortUrlIdentifier $identifier, bool $ignoreThreshold): void
diff --git a/module/CLI/src/Command/ShortUrl/DeleteShortUrlVisitsCommand.php b/module/CLI/src/Command/ShortUrl/DeleteShortUrlVisitsCommand.php
new file mode 100644
index 00000000..fa7a8ee6
--- /dev/null
+++ b/module/CLI/src/Command/ShortUrl/DeleteShortUrlVisitsCommand.php
@@ -0,0 +1,72 @@
+setName(self::NAME)
+ ->setDescription('Deletes visits from a short URL')
+ ->addArgument(
+ 'shortCode',
+ InputArgument::REQUIRED,
+ 'The short code for the short URL which visits will be deleted',
+ )
+ ->addOption(
+ 'domain',
+ 'd',
+ InputOption::VALUE_REQUIRED,
+ 'The domain if the short code does not belong to the default one',
+ );
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): ?int
+ {
+ $identifier = ShortUrlIdentifier::fromCli($input);
+ $io = new SymfonyStyle($input, $output);
+ if (! $this->confirm($io)) {
+ $io->info('Operation aborted');
+ return ExitCode::EXIT_SUCCESS;
+ }
+
+ try {
+ $result = $this->deleter->deleteShortUrlVisits($identifier);
+ $io->success(sprintf('Successfully deleted %s visits', $result->affectedItems));
+
+ return ExitCode::EXIT_SUCCESS;
+ } catch (ShortUrlNotFoundException) {
+ $io->warning(sprintf('Short URL not found for "%s"', $identifier->__toString()));
+ return ExitCode::EXIT_WARNING;
+ }
+ }
+
+ private function confirm(SymfonyStyle $io): bool
+ {
+ $io->warning('You are about to delete all visits for a short URL. This operation cannot be undone.');
+ return $io->confirm('Continue deleting visits?', false);
+ }
+}
diff --git a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php
index f31de184..14ea1851 100644
--- a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php
+++ b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php
@@ -6,7 +6,7 @@ namespace Shlinkio\Shlink\CLI\Command\ShortUrl;
use Shlinkio\Shlink\CLI\Input\EndDateOption;
use Shlinkio\Shlink\CLI\Input\StartDateOption;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\CLI\Util\ShlinkTable;
use Shlinkio\Shlink\Common\Paginator\Paginator;
use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtilsTrait;
@@ -173,7 +173,7 @@ class ListShortUrlsCommand extends Command
$io->newLine();
$io->success('Short URLs properly listed');
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
}
private function renderPage(
diff --git a/module/CLI/src/Command/ShortUrl/ResolveUrlCommand.php b/module/CLI/src/Command/ShortUrl/ResolveUrlCommand.php
index 8d54edd2..aec0a843 100644
--- a/module/CLI/src/Command/ShortUrl/ResolveUrlCommand.php
+++ b/module/CLI/src/Command/ShortUrl/ResolveUrlCommand.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier;
use Shlinkio\Shlink\Core\ShortUrl\ShortUrlResolverInterface;
@@ -56,10 +56,10 @@ class ResolveUrlCommand extends Command
try {
$url = $this->urlResolver->resolveShortUrl(ShortUrlIdentifier::fromCli($input));
$output->writeln(sprintf('Long URL: %s', $url->getLongUrl()));
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
} catch (ShortUrlNotFoundException $e) {
$io->error($e->getMessage());
- return ExitCodes::EXIT_FAILURE;
+ return ExitCode::EXIT_FAILURE;
}
}
}
diff --git a/module/CLI/src/Command/Tag/DeleteTagsCommand.php b/module/CLI/src/Command/Tag/DeleteTagsCommand.php
index 5a4f81ac..151c5892 100644
--- a/module/CLI/src/Command/Tag/DeleteTagsCommand.php
+++ b/module/CLI/src/Command/Tag/DeleteTagsCommand.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Tag;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\Core\Tag\TagServiceInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
@@ -41,11 +41,11 @@ class DeleteTagsCommand extends Command
if (empty($tagNames)) {
$io->warning('You have to provide at least one tag name');
- return ExitCodes::EXIT_WARNING;
+ return ExitCode::EXIT_WARNING;
}
$this->tagService->deleteTags($tagNames);
$io->success('Tags properly deleted');
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
}
}
diff --git a/module/CLI/src/Command/Tag/ListTagsCommand.php b/module/CLI/src/Command/Tag/ListTagsCommand.php
index 02116d79..41ca9b60 100644
--- a/module/CLI/src/Command/Tag/ListTagsCommand.php
+++ b/module/CLI/src/Command/Tag/ListTagsCommand.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Tag;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\CLI\Util\ShlinkTable;
use Shlinkio\Shlink\Core\Tag\Model\TagInfo;
use Shlinkio\Shlink\Core\Tag\Model\TagsParams;
@@ -34,7 +34,7 @@ class ListTagsCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output): ?int
{
ShlinkTable::default($output)->render(['Name', 'URLs amount', 'Visits amount'], $this->getTagsRows());
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
}
private function getTagsRows(): array
diff --git a/module/CLI/src/Command/Tag/RenameTagCommand.php b/module/CLI/src/Command/Tag/RenameTagCommand.php
index 85377a18..1da3b983 100644
--- a/module/CLI/src/Command/Tag/RenameTagCommand.php
+++ b/module/CLI/src/Command/Tag/RenameTagCommand.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Tag;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\Core\Exception\TagConflictException;
use Shlinkio\Shlink\Core\Exception\TagNotFoundException;
use Shlinkio\Shlink\Core\Tag\Model\TagRenaming;
@@ -42,10 +42,10 @@ class RenameTagCommand extends Command
try {
$this->tagService->renameTag(TagRenaming::fromNames($oldName, $newName));
$io->success('Tag properly renamed.');
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
} catch (TagNotFoundException | TagConflictException $e) {
$io->error($e->getMessage());
- return ExitCodes::EXIT_FAILURE;
+ return ExitCode::EXIT_FAILURE;
}
}
}
diff --git a/module/CLI/src/Command/Util/AbstractLockedCommand.php b/module/CLI/src/Command/Util/AbstractLockedCommand.php
index d1e45fd8..ae930496 100644
--- a/module/CLI/src/Command/Util/AbstractLockedCommand.php
+++ b/module/CLI/src/Command/Util/AbstractLockedCommand.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Util;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -28,7 +28,7 @@ abstract class AbstractLockedCommand extends Command
$output->writeln(
sprintf('Command "%s" is already in progress. Skipping.', $lockConfig->lockName),
);
- return ExitCodes::EXIT_WARNING;
+ return ExitCode::EXIT_WARNING;
}
try {
diff --git a/module/CLI/src/Command/Visit/AbstractVisitsListCommand.php b/module/CLI/src/Command/Visit/AbstractVisitsListCommand.php
index 2cd9c0c8..ba518656 100644
--- a/module/CLI/src/Command/Visit/AbstractVisitsListCommand.php
+++ b/module/CLI/src/Command/Visit/AbstractVisitsListCommand.php
@@ -6,7 +6,7 @@ namespace Shlinkio\Shlink\CLI\Command\Visit;
use Shlinkio\Shlink\CLI\Input\EndDateOption;
use Shlinkio\Shlink\CLI\Input\StartDateOption;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\CLI\Util\ShlinkTable;
use Shlinkio\Shlink\Common\Paginator\Paginator;
use Shlinkio\Shlink\Common\Util\DateRange;
@@ -43,7 +43,7 @@ abstract class AbstractVisitsListCommand extends Command
ShlinkTable::default($output)->render($headers, $rows);
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
}
private function resolveRowsAndHeaders(Paginator $paginator): array
diff --git a/module/CLI/src/Command/Visit/DownloadGeoLiteDbCommand.php b/module/CLI/src/Command/Visit/DownloadGeoLiteDbCommand.php
index c4384d33..23600530 100644
--- a/module/CLI/src/Command/Visit/DownloadGeoLiteDbCommand.php
+++ b/module/CLI/src/Command/Visit/DownloadGeoLiteDbCommand.php
@@ -6,7 +6,7 @@ namespace Shlinkio\Shlink\CLI\Command\Visit;
use Shlinkio\Shlink\CLI\Exception\GeolocationDbUpdateFailedException;
use Shlinkio\Shlink\CLI\GeoLite\GeolocationDbUpdaterInterface;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputInterface;
@@ -56,7 +56,7 @@ class DownloadGeoLiteDbCommand extends Command
$io->success('GeoLite2 db file properly downloaded.');
}
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
} catch (GeolocationDbUpdateFailedException $e) {
$olderDbExists = $e->olderDbExists();
@@ -72,7 +72,7 @@ class DownloadGeoLiteDbCommand extends Command
$this->getApplication()?->renderThrowable($e, $io);
}
- return $olderDbExists ? ExitCodes::EXIT_WARNING : ExitCodes::EXIT_FAILURE;
+ return $olderDbExists ? ExitCode::EXIT_WARNING : ExitCode::EXIT_FAILURE;
}
}
}
diff --git a/module/CLI/src/Command/Visit/LocateVisitsCommand.php b/module/CLI/src/Command/Visit/LocateVisitsCommand.php
index d83c91e0..09e53556 100644
--- a/module/CLI/src/Command/Visit/LocateVisitsCommand.php
+++ b/module/CLI/src/Command/Visit/LocateVisitsCommand.php
@@ -6,7 +6,7 @@ namespace Shlinkio\Shlink\CLI\Command\Visit;
use Shlinkio\Shlink\CLI\Command\Util\AbstractLockedCommand;
use Shlinkio\Shlink\CLI\Command\Util\LockedCommandConfig;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\Common\Util\IpAddress;
use Shlinkio\Shlink\Core\Exception\IpCannotBeLocatedException;
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
@@ -116,14 +116,14 @@ class LocateVisitsCommand extends AbstractLockedCommand implements VisitGeolocat
}
$this->io->success('Finished locating visits');
- return ExitCodes::EXIT_SUCCESS;
+ return ExitCode::EXIT_SUCCESS;
} catch (Throwable $e) {
$this->io->error($e->getMessage());
if ($this->io->isVerbose()) {
$this->getApplication()?->renderThrowable($e, $this->io);
}
- return ExitCodes::EXIT_FAILURE;
+ return ExitCode::EXIT_FAILURE;
}
}
@@ -171,7 +171,7 @@ class LocateVisitsCommand extends AbstractLockedCommand implements VisitGeolocat
$downloadDbCommand = $cliApp->find(DownloadGeoLiteDbCommand::NAME);
$exitCode = $downloadDbCommand->run(new ArrayInput([]), $this->io);
- if ($exitCode === ExitCodes::EXIT_FAILURE) {
+ if ($exitCode === ExitCode::EXIT_FAILURE) {
throw new RuntimeException('It is not possible to locate visits without a GeoLite2 db file.');
}
}
diff --git a/module/CLI/src/Util/ExitCodes.php b/module/CLI/src/Util/ExitCode.php
similarity index 89%
rename from module/CLI/src/Util/ExitCodes.php
rename to module/CLI/src/Util/ExitCode.php
index d915796a..128b9f52 100644
--- a/module/CLI/src/Util/ExitCodes.php
+++ b/module/CLI/src/Util/ExitCode.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Util;
-final class ExitCodes
+final class ExitCode
{
public const EXIT_SUCCESS = 0;
public const EXIT_FAILURE = -1;
diff --git a/module/CLI/test-cli/Command/CreateShortUrlTest.php b/module/CLI/test-cli/Command/CreateShortUrlTest.php
index d4d8a583..c2e96611 100644
--- a/module/CLI/test-cli/Command/CreateShortUrlTest.php
+++ b/module/CLI/test-cli/Command/CreateShortUrlTest.php
@@ -7,7 +7,7 @@ namespace ShlinkioCliTest\Shlink\CLI\Command;
use PHPUnit\Framework\Attributes\Test;
use Shlinkio\Shlink\CLI\Command\ShortUrl\CreateShortUrlCommand;
use Shlinkio\Shlink\CLI\Command\ShortUrl\ListShortUrlsCommand;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\TestUtils\CliTest\CliTestCase;
class CreateShortUrlTest extends CliTestCase
@@ -22,7 +22,7 @@ class CreateShortUrlTest extends CliTestCase
[CreateShortUrlCommand::NAME, 'https://example.com', '--domain', $defaultDomain, '--custom-slug', $slug],
);
- self::assertEquals(ExitCodes::EXIT_SUCCESS, $exitCode);
+ self::assertEquals(ExitCode::EXIT_SUCCESS, $exitCode);
self::assertStringContainsString('Generated short URL: http://' . $defaultDomain . '/' . $slug, $output);
[$listOutput] = $this->exec([ListShortUrlsCommand::NAME, '--show-domain', '--search-term', $slug]);
diff --git a/module/CLI/test-cli/Command/GenerateApiKeyTest.php b/module/CLI/test-cli/Command/GenerateApiKeyTest.php
index c98dc237..7d90c336 100644
--- a/module/CLI/test-cli/Command/GenerateApiKeyTest.php
+++ b/module/CLI/test-cli/Command/GenerateApiKeyTest.php
@@ -6,7 +6,7 @@ namespace ShlinkioCliTest\Shlink\CLI\Command;
use PHPUnit\Framework\Attributes\Test;
use Shlinkio\Shlink\CLI\Command\Api\GenerateKeyCommand;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\TestUtils\CliTest\CliTestCase;
class GenerateApiKeyTest extends CliTestCase
@@ -17,6 +17,6 @@ class GenerateApiKeyTest extends CliTestCase
[$output, $exitCode] = $this->exec([GenerateKeyCommand::NAME]);
self::assertStringContainsString('[OK] Generated API key', $output);
- self::assertEquals(ExitCodes::EXIT_SUCCESS, $exitCode);
+ self::assertEquals(ExitCode::EXIT_SUCCESS, $exitCode);
}
}
diff --git a/module/CLI/test-cli/Command/ListApiKeysTest.php b/module/CLI/test-cli/Command/ListApiKeysTest.php
index 80a1134d..f8781d54 100644
--- a/module/CLI/test-cli/Command/ListApiKeysTest.php
+++ b/module/CLI/test-cli/Command/ListApiKeysTest.php
@@ -8,7 +8,7 @@ use Cake\Chronos\Chronos;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Shlinkio\Shlink\CLI\Command\Api\ListKeysCommand;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\TestUtils\CliTest\CliTestCase;
class ListApiKeysTest extends CliTestCase
@@ -19,7 +19,7 @@ class ListApiKeysTest extends CliTestCase
[$output, $exitCode] = $this->exec([ListKeysCommand::NAME, ...$flags]);
self::assertEquals($expectedOutput, $output);
- self::assertEquals(ExitCodes::EXIT_SUCCESS, $exitCode);
+ self::assertEquals(ExitCode::EXIT_SUCCESS, $exitCode);
}
public static function provideFlags(): iterable
diff --git a/module/CLI/test/Command/Domain/ListDomainsCommandTest.php b/module/CLI/test/Command/Domain/ListDomainsCommandTest.php
index ad31d86d..05cc95eb 100644
--- a/module/CLI/test/Command/Domain/ListDomainsCommandTest.php
+++ b/module/CLI/test/Command/Domain/ListDomainsCommandTest.php
@@ -9,7 +9,7 @@ use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\CLI\Command\Domain\ListDomainsCommand;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\Core\Config\NotFoundRedirects;
use Shlinkio\Shlink\Core\Domain\DomainServiceInterface;
use Shlinkio\Shlink\Core\Domain\Entity\Domain;
@@ -53,7 +53,7 @@ class ListDomainsCommandTest extends TestCase
$this->commandTester->execute($input);
self::assertEquals($expectedOutput, $this->commandTester->getDisplay());
- self::assertEquals(ExitCodes::EXIT_SUCCESS, $this->commandTester->getStatusCode());
+ self::assertEquals(ExitCode::EXIT_SUCCESS, $this->commandTester->getStatusCode());
}
public static function provideInputsAndOutputs(): iterable
diff --git a/module/CLI/test/Command/ShortUrl/CreateShortUrlCommandTest.php b/module/CLI/test/Command/ShortUrl/CreateShortUrlCommandTest.php
index 60482138..46063485 100644
--- a/module/CLI/test/Command/ShortUrl/CreateShortUrlCommandTest.php
+++ b/module/CLI/test/Command/ShortUrl/CreateShortUrlCommandTest.php
@@ -11,7 +11,7 @@ use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\CLI\Command\ShortUrl\CreateShortUrlCommand;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\Core\Exception\InvalidUrlException;
use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException;
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
@@ -65,7 +65,7 @@ class CreateShortUrlCommandTest extends TestCase
], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE]);
$output = $this->commandTester->getDisplay();
- self::assertEquals(ExitCodes::EXIT_SUCCESS, $this->commandTester->getStatusCode());
+ self::assertEquals(ExitCode::EXIT_SUCCESS, $this->commandTester->getStatusCode());
self::assertStringContainsString('stringified_short_url', $output);
self::assertStringNotContainsString('but the real-time updates cannot', $output);
}
@@ -82,7 +82,7 @@ class CreateShortUrlCommandTest extends TestCase
$this->commandTester->execute(['longUrl' => $url]);
$output = $this->commandTester->getDisplay();
- self::assertEquals(ExitCodes::EXIT_FAILURE, $this->commandTester->getStatusCode());
+ self::assertEquals(ExitCode::EXIT_FAILURE, $this->commandTester->getStatusCode());
self::assertStringContainsString('Provided URL http://domain.com/invalid is invalid.', $output);
}
@@ -97,7 +97,7 @@ class CreateShortUrlCommandTest extends TestCase
$this->commandTester->execute(['longUrl' => 'http://domain.com/invalid', '--custom-slug' => 'my-slug']);
$output = $this->commandTester->getDisplay();
- self::assertEquals(ExitCodes::EXIT_FAILURE, $this->commandTester->getStatusCode());
+ self::assertEquals(ExitCode::EXIT_FAILURE, $this->commandTester->getStatusCode());
self::assertStringContainsString('Provided slug "my-slug" is already in use', $output);
}
@@ -121,7 +121,7 @@ class CreateShortUrlCommandTest extends TestCase
]);
$output = $this->commandTester->getDisplay();
- self::assertEquals(ExitCodes::EXIT_SUCCESS, $this->commandTester->getStatusCode());
+ self::assertEquals(ExitCode::EXIT_SUCCESS, $this->commandTester->getStatusCode());
self::assertStringContainsString('stringified_short_url', $output);
}
@@ -139,7 +139,7 @@ class CreateShortUrlCommandTest extends TestCase
$input['longUrl'] = 'http://domain.com/foo/bar';
$this->commandTester->execute($input);
- self::assertEquals(ExitCodes::EXIT_SUCCESS, $this->commandTester->getStatusCode());
+ self::assertEquals(ExitCode::EXIT_SUCCESS, $this->commandTester->getStatusCode());
}
public static function provideDomains(): iterable
diff --git a/module/CLI/test/Command/Visit/DownloadGeoLiteDbCommandTest.php b/module/CLI/test/Command/Visit/DownloadGeoLiteDbCommandTest.php
index 7f2cb3ac..7e904caa 100644
--- a/module/CLI/test/Command/Visit/DownloadGeoLiteDbCommandTest.php
+++ b/module/CLI/test/Command/Visit/DownloadGeoLiteDbCommandTest.php
@@ -12,7 +12,7 @@ use Shlinkio\Shlink\CLI\Command\Visit\DownloadGeoLiteDbCommand;
use Shlinkio\Shlink\CLI\Exception\GeolocationDbUpdateFailedException;
use Shlinkio\Shlink\CLI\GeoLite\GeolocationDbUpdaterInterface;
use Shlinkio\Shlink\CLI\GeoLite\GeolocationResult;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use Symfony\Component\Console\Tester\CommandTester;
@@ -65,12 +65,12 @@ class DownloadGeoLiteDbCommandTest extends TestCase
yield 'existing db' => [
true,
'[WARNING] GeoLite2 db file update failed. Visits will continue to be located',
- ExitCodes::EXIT_WARNING,
+ ExitCode::EXIT_WARNING,
];
yield 'not existing db' => [
false,
'[ERROR] GeoLite2 db file download failed. It will not be possible to locate',
- ExitCodes::EXIT_FAILURE,
+ ExitCode::EXIT_FAILURE,
];
}
@@ -86,7 +86,7 @@ class DownloadGeoLiteDbCommandTest extends TestCase
$exitCode = $this->commandTester->getStatusCode();
self::assertStringContainsString($expectedMessage, $output);
- self::assertSame(ExitCodes::EXIT_SUCCESS, $exitCode);
+ self::assertSame(ExitCode::EXIT_SUCCESS, $exitCode);
}
public static function provideSuccessParams(): iterable
diff --git a/module/CLI/test/Command/Visit/LocateVisitsCommandTest.php b/module/CLI/test/Command/Visit/LocateVisitsCommandTest.php
index aa775a24..6ff8c242 100644
--- a/module/CLI/test/Command/Visit/LocateVisitsCommandTest.php
+++ b/module/CLI/test/Command/Visit/LocateVisitsCommandTest.php
@@ -10,7 +10,7 @@ use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\CLI\Command\Visit\DownloadGeoLiteDbCommand;
use Shlinkio\Shlink\CLI\Command\Visit\LocateVisitsCommand;
-use Shlinkio\Shlink\CLI\Util\ExitCodes;
+use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\Core\Exception\IpCannotBeLocatedException;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
@@ -85,7 +85,7 @@ class LocateVisitsCommandTest extends TestCase
$this->visitToLocation->expects(
$this->exactly($expectedUnlocatedCalls + $expectedEmptyCalls + $expectedAllCalls),
)->method('resolveVisitLocation')->withAnyParameters()->willReturn(Location::emptyInstance());
- $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS);
+ $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCode::EXIT_SUCCESS);
$this->commandTester->setInputs(['y']);
$this->commandTester->execute($args);
@@ -118,7 +118,7 @@ class LocateVisitsCommandTest extends TestCase
->withAnyParameters()
->willReturnCallback($this->invokeHelperMethods($visit, $location));
$this->visitToLocation->expects($this->once())->method('resolveVisitLocation')->willThrowException($e);
- $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS);
+ $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCode::EXIT_SUCCESS);
$this->commandTester->execute([], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE]);
@@ -147,7 +147,7 @@ class LocateVisitsCommandTest extends TestCase
$this->visitToLocation->expects($this->once())->method('resolveVisitLocation')->willThrowException(
IpCannotBeLocatedException::forError(WrongIpException::fromIpAddress('1.2.3.4')),
);
- $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS);
+ $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCode::EXIT_SUCCESS);
$this->commandTester->execute([], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE]);
@@ -171,7 +171,7 @@ class LocateVisitsCommandTest extends TestCase
$this->visitService->expects($this->never())->method('locateUnlocatedVisits');
$this->visitToLocation->expects($this->never())->method('resolveVisitLocation');
- $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS);
+ $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCode::EXIT_SUCCESS);
$this->commandTester->execute([], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE]);
$output = $this->commandTester->getDisplay();
@@ -186,7 +186,7 @@ class LocateVisitsCommandTest extends TestCase
public function showsProperMessageWhenGeoLiteUpdateFails(): void
{
$this->lock->method('acquire')->with($this->isFalse())->willReturn(true);
- $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_FAILURE);
+ $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCode::EXIT_FAILURE);
$this->visitService->expects($this->never())->method('locateUnlocatedVisits');
$this->commandTester->execute([]);
@@ -199,7 +199,7 @@ class LocateVisitsCommandTest extends TestCase
public function providingAllFlagOnItsOwnDisplaysNotice(): void
{
$this->lock->method('acquire')->with($this->isFalse())->willReturn(true);
- $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS);
+ $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCode::EXIT_SUCCESS);
$this->commandTester->execute(['--all' => true]);
$output = $this->commandTester->getDisplay();
@@ -210,7 +210,7 @@ class LocateVisitsCommandTest extends TestCase
#[Test, DataProvider('provideAbortInputs')]
public function processingAllCancelsCommandIfUserDoesNotActivelyAgreeToConfirmation(array $inputs): void
{
- $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS);
+ $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCode::EXIT_SUCCESS);
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('Execution aborted');
diff --git a/module/Core/src/ShortUrl/Model/ShortUrlIdentifier.php b/module/Core/src/ShortUrl/Model/ShortUrlIdentifier.php
index bb3b4af6..78becbed 100644
--- a/module/Core/src/ShortUrl/Model/ShortUrlIdentifier.php
+++ b/module/Core/src/ShortUrl/Model/ShortUrlIdentifier.php
@@ -8,6 +8,8 @@ use Psr\Http\Message\ServerRequestInterface;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
use Symfony\Component\Console\Input\InputInterface;
+use function sprintf;
+
final class ShortUrlIdentifier
{
private function __construct(public readonly string $shortCode, public readonly ?string $domain = null)
@@ -54,4 +56,13 @@ final class ShortUrlIdentifier
{
return new self($shortCode, $domain);
}
+
+ public function __toString(): string
+ {
+ if ($this->domain === null) {
+ return $this->shortCode;
+ }
+
+ return sprintf('%s/%s', $this->domain, $this->shortCode);
+ }
}
diff --git a/module/Core/src/ShortUrl/ShortUrlVisitsDeleter.php b/module/Core/src/ShortUrl/ShortUrlVisitsDeleter.php
index c202c5c2..8ad6713f 100644
--- a/module/Core/src/ShortUrl/ShortUrlVisitsDeleter.php
+++ b/module/Core/src/ShortUrl/ShortUrlVisitsDeleter.php
@@ -21,7 +21,7 @@ class ShortUrlVisitsDeleter implements ShortUrlVisitsDeleterInterface
/**
* @throws ShortUrlNotFoundException
*/
- public function deleteShortUrlVisits(ShortUrlIdentifier $identifier, ?ApiKey $apiKey): BulkDeleteResult
+ public function deleteShortUrlVisits(ShortUrlIdentifier $identifier, ?ApiKey $apiKey = null): BulkDeleteResult
{
$shortUrl = $this->resolver->resolveShortUrl($identifier, $apiKey);
return new BulkDeleteResult($this->repository->deleteShortUrlVisits($shortUrl));
diff --git a/module/Core/src/ShortUrl/ShortUrlVisitsDeleterInterface.php b/module/Core/src/ShortUrl/ShortUrlVisitsDeleterInterface.php
index b0ac0e6a..46e9fde5 100644
--- a/module/Core/src/ShortUrl/ShortUrlVisitsDeleterInterface.php
+++ b/module/Core/src/ShortUrl/ShortUrlVisitsDeleterInterface.php
@@ -14,5 +14,5 @@ interface ShortUrlVisitsDeleterInterface
/**
* @throws ShortUrlNotFoundException
*/
- public function deleteShortUrlVisits(ShortUrlIdentifier $identifier, ?ApiKey $apiKey): BulkDeleteResult;
+ public function deleteShortUrlVisits(ShortUrlIdentifier $identifier, ?ApiKey $apiKey = null): BulkDeleteResult;
}
diff --git a/module/Core/test-db/Visit/Repository/VisitDeleterRepositoryTest.php b/module/Core/test-db/Visit/Repository/VisitDeleterRepositoryTest.php
index 1598fc94..53b1585f 100644
--- a/module/Core/test-db/Visit/Repository/VisitDeleterRepositoryTest.php
+++ b/module/Core/test-db/Visit/Repository/VisitDeleterRepositoryTest.php
@@ -52,7 +52,6 @@ class VisitDeleterRepositoryTest extends DatabaseTestCase
$this->getEntityManager()->flush();
- self::assertEquals(0, $this->repo->deleteShortUrlVisits(ShortUrl::withLongUrl('https://invalid')->setId('99')));
self::assertEquals(2, $this->repo->deleteShortUrlVisits($shortUrl1));
self::assertEquals(0, $this->repo->deleteShortUrlVisits($shortUrl1));
self::assertEquals(4, $this->repo->deleteShortUrlVisits($shortUrl2));
diff --git a/module/Rest/test-api/Action/CreateShortUrlTest.php b/module/Rest/test-api/Action/CreateShortUrlTest.php
index 54d1d45a..dfdd170e 100644
--- a/module/Rest/test-api/Action/CreateShortUrlTest.php
+++ b/module/Rest/test-api/Action/CreateShortUrlTest.php
@@ -320,27 +320,6 @@ class CreateShortUrlTest extends ApiTestCase
yield 'example domain' => ['example.com'];
}
- #[Test, DataProvider('provideTwitterUrls')]
- public function urlsWithBotProtectionCanBeShortenedWithUrlValidationEnabled(string $longUrl): void
- {
- // Requests to Twitter are randomly failing from GitHub actions. Let's skip this test there.
- // This is a deprecated and low-used feature anyway.
- if (env('CI', false)) {
- $this->markTestSkipped();
- }
-
- [$statusCode] = $this->createShortUrl(['longUrl' => $longUrl, 'validateUrl' => true]);
- self::assertEquals(self::STATUS_OK, $statusCode);
- }
-
- public static function provideTwitterUrls(): iterable
- {
- yield ['https://twitter.com/shlinkio'];
- yield ['https://mobile.twitter.com/shlinkio'];
- yield ['https://twitter.com/shlinkio/status/1360637738421268481'];
- yield ['https://mobile.twitter.com/shlinkio/status/1360637738421268481'];
- }
-
#[Test]
public function canCreateShortUrlsWithEmojis(): void
{