diff --git a/composer.json b/composer.json
index ad597380..ed431a24 100644
--- a/composer.json
+++ b/composer.json
@@ -54,7 +54,7 @@
"doctrine/data-fixtures": "^1.3",
"filp/whoops": "^2.0",
"infection/infection": "^0.12.2",
- "phpstan/phpstan": "^0.10.8",
+ "phpstan/phpstan": "^0.11.2",
"phpunit/phpcov": "^6.0@dev || ^5.0",
"phpunit/phpunit": "^8.0 || ^7.5",
"roave/security-advisories": "dev-master",
diff --git a/module/CLI/src/Command/Api/DisableKeyCommand.php b/module/CLI/src/Command/Api/DisableKeyCommand.php
index e869d985..4d945c48 100644
--- a/module/CLI/src/Command/Api/DisableKeyCommand.php
+++ b/module/CLI/src/Command/Api/DisableKeyCommand.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Api;
use InvalidArgumentException;
+use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
@@ -40,10 +41,10 @@ class DisableKeyCommand extends Command
try {
$this->apiKeyService->disable($apiKey);
$io->success(sprintf('API key "%s" properly disabled', $apiKey));
- return 0;
+ return ExitCodes::EXIT_SUCCESS;
} catch (InvalidArgumentException $e) {
$io->error(sprintf('API key "%s" does not exist.', $apiKey));
- return -1;
+ return ExitCodes::EXIT_FAILURE;
}
}
}
diff --git a/module/CLI/src/Command/Api/GenerateKeyCommand.php b/module/CLI/src/Command/Api/GenerateKeyCommand.php
index ae55060a..bba8ace6 100644
--- a/module/CLI/src/Command/Api/GenerateKeyCommand.php
+++ b/module/CLI/src/Command/Api/GenerateKeyCommand.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Api;
use Cake\Chronos\Chronos;
+use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
@@ -44,6 +45,6 @@ class GenerateKeyCommand extends Command
$apiKey = $this->apiKeyService->create(isset($expirationDate) ? Chronos::parse($expirationDate) : null);
(new SymfonyStyle($input, $output))->success(sprintf('Generated API key: "%s"', $apiKey));
- return 0;
+ return ExitCodes::EXIT_SUCCESS;
}
}
diff --git a/module/CLI/src/Command/Api/ListKeysCommand.php b/module/CLI/src/Command/Api/ListKeysCommand.php
index 7acdcc03..710c22c8 100644
--- a/module/CLI/src/Command/Api/ListKeysCommand.php
+++ b/module/CLI/src/Command/Api/ListKeysCommand.php
@@ -3,6 +3,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Api;
+use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Common\Console\ShlinkTable;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
@@ -66,7 +67,7 @@ class ListKeysCommand extends Command
! $enabledOnly ? 'Is enabled' : null,
'Expiration date',
]), $rows);
- return 0;
+ return ExitCodes::EXIT_SUCCESS;
}
private function determineMessagePattern(ApiKey $apiKey): string
diff --git a/module/CLI/src/Command/Config/GenerateCharsetCommand.php b/module/CLI/src/Command/Config/GenerateCharsetCommand.php
index 01a95036..0fab6336 100644
--- a/module/CLI/src/Command/Config/GenerateCharsetCommand.php
+++ b/module/CLI/src/Command/Config/GenerateCharsetCommand.php
@@ -3,6 +3,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Config;
+use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
@@ -32,6 +33,6 @@ class GenerateCharsetCommand extends Command
{
$charSet = str_shuffle(UrlShortenerOptions::DEFAULT_CHARS);
(new SymfonyStyle($input, $output))->success(sprintf('Character set: "%s"', $charSet));
- return 0;
+ return ExitCodes::EXIT_SUCCESS;
}
}
diff --git a/module/CLI/src/Command/Config/GenerateSecretCommand.php b/module/CLI/src/Command/Config/GenerateSecretCommand.php
index 73cc98e1..8a194bd7 100644
--- a/module/CLI/src/Command/Config/GenerateSecretCommand.php
+++ b/module/CLI/src/Command/Config/GenerateSecretCommand.php
@@ -3,6 +3,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Config;
+use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Common\Util\StringUtilsTrait;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
@@ -31,6 +32,6 @@ class GenerateSecretCommand extends Command
{
$secret = $this->generateRandomString(32);
(new SymfonyStyle($input, $output))->success(sprintf('Secret key: "%s"', $secret));
- return 0;
+ return ExitCodes::EXIT_SUCCESS;
}
}
diff --git a/module/CLI/src/Command/ShortUrl/DeleteShortUrlCommand.php b/module/CLI/src/Command/ShortUrl/DeleteShortUrlCommand.php
index e60fa6d8..0bc2a5fb 100644
--- a/module/CLI/src/Command/ShortUrl/DeleteShortUrlCommand.php
+++ b/module/CLI/src/Command/ShortUrl/DeleteShortUrlCommand.php
@@ -3,6 +3,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;
+use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Core\Exception;
use Shlinkio\Shlink\Core\Service\ShortUrl\DeleteShortUrlServiceInterface;
use Symfony\Component\Console\Command\Command;
@@ -51,10 +52,10 @@ class DeleteShortUrlCommand extends Command
try {
$this->runDelete($io, $shortCode, $ignoreThreshold);
- return 0;
+ return ExitCodes::EXIT_SUCCESS;
} catch (Exception\InvalidShortCodeException $e) {
$io->error(sprintf('Provided short code "%s" could not be found.', $shortCode));
- return -1;
+ return ExitCodes::EXIT_FAILURE;
} catch (Exception\DeleteShortUrlException $e) {
return $this->retry($io, $shortCode, $e);
}
@@ -76,7 +77,7 @@ class DeleteShortUrlCommand extends Command
$io->warning('Short URL was not deleted.');
}
- return $forceDelete ? 0 : 1;
+ return $forceDelete ? ExitCodes::EXIT_SUCCESS : ExitCodes::EXIT_WARNING;
}
private function runDelete(SymfonyStyle $io, string $shortCode, bool $ignoreThreshold): void
diff --git a/module/CLI/src/Command/ShortUrl/GeneratePreviewCommand.php b/module/CLI/src/Command/ShortUrl/GeneratePreviewCommand.php
index 4abaa62b..0a769553 100644
--- a/module/CLI/src/Command/ShortUrl/GeneratePreviewCommand.php
+++ b/module/CLI/src/Command/ShortUrl/GeneratePreviewCommand.php
@@ -3,6 +3,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;
+use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Common\Exception\PreviewGenerationException;
use Shlinkio\Shlink\Common\Service\PreviewGeneratorInterface;
use Shlinkio\Shlink\Core\Service\ShortUrlServiceInterface;
@@ -52,7 +53,7 @@ class GeneratePreviewCommand extends Command
} while ($page <= $shortUrls->count());
(new SymfonyStyle($input, $output))->success('Finished processing all URLs');
- return 0;
+ return ExitCodes::EXIT_SUCCESS;
}
private function processUrl($url, OutputInterface $output): void
diff --git a/module/CLI/src/Command/ShortUrl/GenerateShortUrlCommand.php b/module/CLI/src/Command/ShortUrl/GenerateShortUrlCommand.php
index 81c577a5..192c7049 100644
--- a/module/CLI/src/Command/ShortUrl/GenerateShortUrlCommand.php
+++ b/module/CLI/src/Command/ShortUrl/GenerateShortUrlCommand.php
@@ -4,6 +4,7 @@ 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;
@@ -108,7 +109,7 @@ class GenerateShortUrlCommand extends Command
$longUrl = $input->getArgument('longUrl');
if (empty($longUrl)) {
$io->error('A URL was not provided!');
- return -1;
+ return ExitCodes::EXIT_FAILURE;
}
$explodeWithComma = curry('explode')(',');
@@ -134,15 +135,15 @@ class GenerateShortUrlCommand extends Command
sprintf('Processed long URL: %s', $longUrl),
sprintf('Generated short URL: %s', $shortUrl),
]);
- return 0;
+ return ExitCodes::EXIT_SUCCESS;
} catch (InvalidUrlException $e) {
$io->error(sprintf('Provided URL "%s" is invalid. Try with a different one.', $longUrl));
- return -1;
+ 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 -1;
+ return ExitCodes::EXIT_FAILURE;
}
}
diff --git a/module/CLI/src/Command/ShortUrl/GetVisitsCommand.php b/module/CLI/src/Command/ShortUrl/GetVisitsCommand.php
index d4aedf52..85258c16 100644
--- a/module/CLI/src/Command/ShortUrl/GetVisitsCommand.php
+++ b/module/CLI/src/Command/ShortUrl/GetVisitsCommand.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;
use Cake\Chronos\Chronos;
+use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Common\Console\ShlinkTable;
use Shlinkio\Shlink\Common\Util\DateRange;
use Shlinkio\Shlink\Core\Entity\Visit;
@@ -83,7 +84,7 @@ class GetVisitsCommand extends Command
return select_keys($rowData, ['referer', 'date', 'userAgent', 'country']);
}, $visits);
ShlinkTable::fromOutput($output)->render(['Referer', 'Date', 'User agent', 'Country'], $rows);
- return 0;
+ return ExitCodes::EXIT_SUCCESS;
}
private function getDateOption(InputInterface $input, $key)
diff --git a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php
index 6a0884a8..47afc208 100644
--- a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php
+++ b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php
@@ -3,6 +3,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;
+use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Common\Console\ShlinkTable;
use Shlinkio\Shlink\Common\Paginator\Adapter\PaginableRepositoryAdapter;
use Shlinkio\Shlink\Common\Paginator\Util\PaginatorUtilsTrait;
@@ -95,7 +96,7 @@ class ListShortUrlsCommand extends Command
$io->newLine();
$io->success('Short URLs properly listed');
- return 0;
+ return ExitCodes::EXIT_SUCCESS;
}
private function renderPage(
diff --git a/module/CLI/src/Command/ShortUrl/ResolveUrlCommand.php b/module/CLI/src/Command/ShortUrl/ResolveUrlCommand.php
index 4fd0b1fb..e2d72d44 100644
--- a/module/CLI/src/Command/ShortUrl/ResolveUrlCommand.php
+++ b/module/CLI/src/Command/ShortUrl/ResolveUrlCommand.php
@@ -3,6 +3,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;
+use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException;
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
use Shlinkio\Shlink\Core\Service\UrlShortenerInterface;
@@ -58,13 +59,13 @@ class ResolveUrlCommand extends Command
try {
$url = $this->urlShortener->shortCodeToUrl($shortCode);
$output->writeln(sprintf('Long URL: %s', $url->getLongUrl()));
- return 0;
+ return ExitCodes::EXIT_SUCCESS;
} catch (InvalidShortCodeException $e) {
$io->error(sprintf('Provided short code "%s" has an invalid format.', $shortCode));
- return -1;
+ return ExitCodes::EXIT_FAILURE;
} catch (EntityDoesNotExistException $e) {
$io->error(sprintf('Provided short code "%s" could not be found.', $shortCode));
- return -1;
+ return ExitCodes::EXIT_FAILURE;
}
}
}
diff --git a/module/CLI/src/Command/Tag/CreateTagCommand.php b/module/CLI/src/Command/Tag/CreateTagCommand.php
index 57323d69..371337d7 100644
--- a/module/CLI/src/Command/Tag/CreateTagCommand.php
+++ b/module/CLI/src/Command/Tag/CreateTagCommand.php
@@ -3,6 +3,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Tag;
+use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Core\Service\Tag\TagServiceInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
@@ -43,11 +44,11 @@ class CreateTagCommand extends Command
if (empty($tagNames)) {
$io->warning('You have to provide at least one tag name');
- return 1;
+ return ExitCodes::EXIT_WARNING;
}
$this->tagService->createTags($tagNames);
$io->success('Tags properly created');
- return 0;
+ return ExitCodes::EXIT_SUCCESS;
}
}
diff --git a/module/CLI/src/Command/Tag/DeleteTagsCommand.php b/module/CLI/src/Command/Tag/DeleteTagsCommand.php
index 327c21e3..02f542fd 100644
--- a/module/CLI/src/Command/Tag/DeleteTagsCommand.php
+++ b/module/CLI/src/Command/Tag/DeleteTagsCommand.php
@@ -3,6 +3,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Tag;
+use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Core\Service\Tag\TagServiceInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
@@ -43,11 +44,11 @@ class DeleteTagsCommand extends Command
if (empty($tagNames)) {
$io->warning('You have to provide at least one tag name');
- return 1;
+ return ExitCodes::EXIT_WARNING;
}
$this->tagService->deleteTags($tagNames);
$io->success('Tags properly deleted');
- return 0;
+ return ExitCodes::EXIT_SUCCESS;
}
}
diff --git a/module/CLI/src/Command/Tag/ListTagsCommand.php b/module/CLI/src/Command/Tag/ListTagsCommand.php
index 0866445c..02a7a831 100644
--- a/module/CLI/src/Command/Tag/ListTagsCommand.php
+++ b/module/CLI/src/Command/Tag/ListTagsCommand.php
@@ -3,6 +3,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Tag;
+use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Common\Console\ShlinkTable;
use Shlinkio\Shlink\Core\Entity\Tag;
use Shlinkio\Shlink\Core\Service\Tag\TagServiceInterface;
@@ -34,7 +35,7 @@ class ListTagsCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output): ?int
{
ShlinkTable::fromOutput($output)->render(['Name'], $this->getTagsRows());
- return 0;
+ return ExitCodes::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 69cf0a07..2875761d 100644
--- a/module/CLI/src/Command/Tag/RenameTagCommand.php
+++ b/module/CLI/src/Command/Tag/RenameTagCommand.php
@@ -3,6 +3,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Tag;
+use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException;
use Shlinkio\Shlink\Core\Service\Tag\TagServiceInterface;
use Symfony\Component\Console\Command\Command;
@@ -43,10 +44,10 @@ class RenameTagCommand extends Command
try {
$this->tagService->renameTag($oldName, $newName);
$io->success('Tag properly renamed.');
- return 0;
+ return ExitCodes::EXIT_SUCCESS;
} catch (EntityDoesNotExistException $e) {
$io->error(sprintf('A tag with name "%s" was not found', $oldName));
- return -1;
+ return ExitCodes::EXIT_FAILURE;
}
}
}
diff --git a/module/CLI/src/Command/Visit/ProcessVisitsCommand.php b/module/CLI/src/Command/Visit/ProcessVisitsCommand.php
index 7c51c020..848a540c 100644
--- a/module/CLI/src/Command/Visit/ProcessVisitsCommand.php
+++ b/module/CLI/src/Command/Visit/ProcessVisitsCommand.php
@@ -3,6 +3,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Visit;
+use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Common\Exception\WrongIpException;
use Shlinkio\Shlink\Common\IpGeolocation\IpLocationResolverInterface;
use Shlinkio\Shlink\Common\Util\IpAddress;
@@ -56,7 +57,7 @@ class ProcessVisitsCommand extends Command
$lock = $this->locker->createLock(self::NAME);
if (! $lock->acquire()) {
$io->warning(sprintf('There is already an instance of the "%s" command in execution', self::NAME));
- return 1;
+ return ExitCodes::EXIT_WARNING;
}
try {
@@ -70,7 +71,7 @@ class ProcessVisitsCommand extends Command
$io->success('Finished processing all IPs');
} finally {
$lock->release();
- return 0;
+ return ExitCodes::EXIT_SUCCESS;
}
}
diff --git a/module/CLI/src/Command/Visit/UpdateDbCommand.php b/module/CLI/src/Command/Visit/UpdateDbCommand.php
index b4554e66..35389260 100644
--- a/module/CLI/src/Command/Visit/UpdateDbCommand.php
+++ b/module/CLI/src/Command/Visit/UpdateDbCommand.php
@@ -3,6 +3,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Visit;
+use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Common\Exception\RuntimeException;
use Shlinkio\Shlink\Common\IpGeolocation\GeoLite2\DbUpdaterInterface;
use Symfony\Component\Console\Command\Command;
@@ -51,7 +52,7 @@ class UpdateDbCommand extends Command
$io->writeln('');
$io->success('GeoLite2 database properly updated');
- return 0;
+ return ExitCodes::EXIT_SUCCESS;
} catch (RuntimeException $e) {
$progressBar->finish();
$io->writeln('');
@@ -60,7 +61,7 @@ class UpdateDbCommand extends Command
if ($io->isVerbose()) {
$this->getApplication()->renderException($e, $output);
}
- return -1;
+ return ExitCodes::EXIT_FAILURE;
}
}
}
diff --git a/module/CLI/src/Util/ExitCodes.php b/module/CLI/src/Util/ExitCodes.php
new file mode 100644
index 00000000..f62e14fc
--- /dev/null
+++ b/module/CLI/src/Util/ExitCodes.php
@@ -0,0 +1,11 @@
+