mirror of
https://github.com/shlinkio/shlink.git
synced 2024-11-24 13:49:03 +03:00
Merge pull request #1122 from acelaya-forks/feature/phpstan-level
Feature/phpstan level
This commit is contained in:
commit
32bb66c42b
37 changed files with 131 additions and 77 deletions
|
@ -18,7 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this
|
|||
This behavior needs to be actively opted in, via installer config options or env vars.
|
||||
|
||||
### Changed
|
||||
* *Nothing*
|
||||
* [#1118](https://github.com/shlinkio/shlink/issues/1118) Increased phpstan required level to 8.
|
||||
|
||||
### Deprecated
|
||||
* *Nothing*
|
||||
|
|
7
bin/cli
7
bin/cli
|
@ -3,5 +3,8 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
$run = require __DIR__ . '/../config/run.php';
|
||||
$run(true);
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
/** @var Application $app */
|
||||
$app = require __DIR__ . '/../config/cli-app.php';
|
||||
$app->run();
|
||||
|
|
|
@ -62,18 +62,20 @@
|
|||
},
|
||||
"require-dev": {
|
||||
"devster/ubench": "^2.1",
|
||||
"dms/phpunit-arraysubset-asserts": "^0.2.1",
|
||||
"dms/phpunit-arraysubset-asserts": "^0.3.0",
|
||||
"eaglewu/swoole-ide-helper": "dev-master",
|
||||
"infection/infection": "^0.21.0",
|
||||
"infection/infection": "^0.23.0",
|
||||
"phpspec/prophecy-phpunit": "^2.0",
|
||||
"phpstan/phpstan": "^0.12.64",
|
||||
"phpstan/phpstan": "^0.12.93",
|
||||
"phpstan/phpstan-doctrine": "^0.12.42",
|
||||
"phpstan/phpstan-symfony": "^0.12.41",
|
||||
"phpunit/php-code-coverage": "^9.2",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"roave/security-advisories": "dev-master",
|
||||
"shlinkio/php-coding-standard": "~2.1.1",
|
||||
"shlinkio/shlink-test-utils": "^2.1",
|
||||
"symfony/var-dumper": "^5.2",
|
||||
"veewee/composer-run-parallel": "^0.1.0"
|
||||
"veewee/composer-run-parallel": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
@ -112,7 +114,7 @@
|
|||
],
|
||||
"cs": "phpcs",
|
||||
"cs:fix": "phpcbf",
|
||||
"stan": "phpstan analyse module/*/src/ module/*/config config docker/config data/migrations --level=6",
|
||||
"stan": "APP_ENV=test php vendor/bin/phpstan analyse module/*/src module/*/config config docker/config data/migrations --level=8",
|
||||
"test": [
|
||||
"@test:unit",
|
||||
"@test:db",
|
||||
|
|
12
config/cli-app.php
Normal file
12
config/cli-app.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Component\Console\Application as CliApp;
|
||||
|
||||
return (static function () {
|
||||
/** @var ContainerInterface $container */
|
||||
$container = include __DIR__ . '/container.php';
|
||||
return $container->get(CliApp::class);
|
||||
})();
|
|
@ -4,12 +4,9 @@ declare(strict_types=1);
|
|||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Doctrine\ORM\Tools\Console\ConsoleRunner;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
return (function () {
|
||||
/** @var ContainerInterface $container */
|
||||
$container = include __DIR__ . '/container.php';
|
||||
$em = $container->get(EntityManager::class);
|
||||
|
||||
return (static function () {
|
||||
/** @var EntityManager $em */
|
||||
$em = include __DIR__ . '/entity-manager.php';
|
||||
return ConsoleRunner::createHelperSet($em);
|
||||
})();
|
||||
|
|
12
config/entity-manager.php
Normal file
12
config/entity-manager.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
return (static function () {
|
||||
/** @var ContainerInterface $container */
|
||||
$container = include __DIR__ . '/container.php';
|
||||
return $container->get(EntityManager::class);
|
||||
})();
|
|
@ -4,12 +4,11 @@ declare(strict_types=1);
|
|||
|
||||
use Mezzio\Application;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Component\Console\Application as CliApp;
|
||||
|
||||
return function (bool $isCli = false): void {
|
||||
return static function (): void {
|
||||
/** @var ContainerInterface $container */
|
||||
$container = include __DIR__ . '/container.php';
|
||||
$app = $container->get($isCli ? CliApp::class : Application::class);
|
||||
$app = $container->get(Application::class);
|
||||
|
||||
$app->run();
|
||||
};
|
||||
|
|
|
@ -120,7 +120,7 @@ return [
|
|||
'name' => 'start_collecting_coverage',
|
||||
'path' => '/api-tests/start-coverage',
|
||||
'middleware' => middleware(static function () use (&$coverage) {
|
||||
if ($coverage) {
|
||||
if ($coverage) { // @phpstan-ignore-line
|
||||
$coverage->start('API tests');
|
||||
}
|
||||
return new EmptyResponse();
|
||||
|
@ -131,7 +131,7 @@ return [
|
|||
'name' => 'dump_coverage',
|
||||
'path' => '/api-tests/stop-coverage',
|
||||
'middleware' => middleware(static function () use (&$coverage) {
|
||||
if ($coverage) {
|
||||
if ($coverage) { // @phpstan-ignore-line
|
||||
$basePath = __DIR__ . '/../../build/coverage-api';
|
||||
$coverage->stop();
|
||||
(new PHP())->process($coverage, $basePath . '.cov');
|
||||
|
|
|
@ -8,6 +8,8 @@ use Shlinkio\Shlink\Core\Domain\DomainServiceInterface;
|
|||
use Shlinkio\Shlink\Rest\ApiKey\Model\RoleDefinition;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
use function is_string;
|
||||
|
||||
class RoleResolver implements RoleResolverInterface
|
||||
{
|
||||
public function __construct(private DomainServiceInterface $domainService)
|
||||
|
@ -23,7 +25,7 @@ class RoleResolver implements RoleResolverInterface
|
|||
if ($author) {
|
||||
$roleDefinitions[] = RoleDefinition::forAuthoredShortUrls();
|
||||
}
|
||||
if ($domainAuthority !== null) {
|
||||
if (is_string($domainAuthority)) {
|
||||
$domain = $this->domainService->getOrCreate($domainAuthority);
|
||||
$roleDefinitions[] = RoleDefinition::forDomain($domain);
|
||||
}
|
||||
|
|
|
@ -12,40 +12,36 @@ use function Shlinkio\Shlink\Core\kebabCaseToCamelCase;
|
|||
use function sprintf;
|
||||
use function str_contains;
|
||||
|
||||
/** @deprecated */
|
||||
abstract class BaseCommand extends Command
|
||||
{
|
||||
/**
|
||||
* @param mixed|null $default
|
||||
* @param string|string[]|bool|null $default
|
||||
*/
|
||||
protected function addOptionWithDeprecatedFallback(
|
||||
string $name,
|
||||
?string $shortcut = null,
|
||||
?int $mode = null,
|
||||
string $description = '',
|
||||
$default = null,
|
||||
bool|string|array|null $default = null,
|
||||
): self {
|
||||
$this->addOption($name, $shortcut, $mode, $description, $default);
|
||||
|
||||
if (str_contains($name, '-')) {
|
||||
$camelCaseName = kebabCaseToCamelCase($name);
|
||||
$this->addOption($camelCaseName, null, $mode, sprintf('[DEPRECATED] Same as "%s".', $name), $default);
|
||||
$this->addOption($camelCaseName, null, $mode, sprintf('[DEPRECATED] Alias for "%s".', $name), $default);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|string|string[]|null
|
||||
*/
|
||||
protected function getOptionWithDeprecatedFallback(InputInterface $input, string $name)
|
||||
// @phpstan-ignore-next-line
|
||||
protected function getOptionWithDeprecatedFallback(InputInterface $input, string $name) // phpcs:ignore
|
||||
{
|
||||
$rawInput = method_exists($input, '__toString') ? $input->__toString() : '';
|
||||
$camelCaseName = kebabCaseToCamelCase($name);
|
||||
$resolvedOptionName = str_contains($rawInput, $camelCaseName) ? $camelCaseName : $name;
|
||||
|
||||
if (str_contains($rawInput, $camelCaseName)) {
|
||||
return $input->getOption($camelCaseName);
|
||||
}
|
||||
|
||||
return $input->getOption($name);
|
||||
return $input->getOption($resolvedOptionName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,6 @@ abstract class AbstractDatabaseCommand extends AbstractLockedCommand
|
|||
|
||||
protected function getLockConfig(): LockedCommandConfig
|
||||
{
|
||||
return LockedCommandConfig::blocking($this->getName());
|
||||
return LockedCommandConfig::blocking($this->getName() ?? static::class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ use Symfony\Component\Console\Input\InputOption;
|
|||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Throwable;
|
||||
|
||||
use function is_string;
|
||||
use function sprintf;
|
||||
|
||||
abstract class AbstractWithDateRangeCommand extends BaseCommand
|
||||
|
@ -49,7 +50,7 @@ abstract class AbstractWithDateRangeCommand extends BaseCommand
|
|||
private function getDateOption(InputInterface $input, OutputInterface $output, string $key): ?Chronos
|
||||
{
|
||||
$value = $this->getOptionWithDeprecatedFallback($input, $key);
|
||||
if (empty($value)) {
|
||||
if (empty($value) || ! is_string($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,8 +45,8 @@ class DownloadGeoLiteDbCommand extends Command
|
|||
$io->text(sprintf('<fg=blue>%s GeoLite2 db file...</>', $olderDbExists ? 'Updating' : 'Downloading'));
|
||||
$this->progressBar = new ProgressBar($io);
|
||||
}, function (int $total, int $downloaded): void {
|
||||
$this->progressBar->setMaxSteps($total);
|
||||
$this->progressBar->setProgress($downloaded);
|
||||
$this->progressBar?->setMaxSteps($total);
|
||||
$this->progressBar?->setProgress($downloaded);
|
||||
});
|
||||
|
||||
if ($this->progressBar === null) {
|
||||
|
|
|
@ -139,7 +139,7 @@ class LocateVisitsCommand extends AbstractLockedCommand implements VisitGeolocat
|
|||
throw IpCannotBeLocatedException::forEmptyAddress();
|
||||
}
|
||||
|
||||
$ipAddr = $visit->getRemoteAddr();
|
||||
$ipAddr = $visit->getRemoteAddr() ?? '';
|
||||
$this->io->write(sprintf('Processing IP <fg=blue>%s</>', $ipAddr));
|
||||
if ($ipAddr === IpAddress::LOCALHOST) {
|
||||
$this->io->writeln(' [<comment>Ignored localhost address</comment>]');
|
||||
|
@ -168,7 +168,12 @@ class LocateVisitsCommand extends AbstractLockedCommand implements VisitGeolocat
|
|||
|
||||
private function checkDbUpdate(InputInterface $input): void
|
||||
{
|
||||
$downloadDbCommand = $this->getApplication()->find(DownloadGeoLiteDbCommand::NAME);
|
||||
$cliApp = $this->getApplication();
|
||||
if ($cliApp === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$downloadDbCommand = $cliApp->find(DownloadGeoLiteDbCommand::NAME);
|
||||
$exitCode = $downloadDbCommand->run($input, $this->io);
|
||||
|
||||
if ($exitCode === ExitCodes::EXIT_FAILURE) {
|
||||
|
@ -178,6 +183,6 @@ class LocateVisitsCommand extends AbstractLockedCommand implements VisitGeolocat
|
|||
|
||||
protected function getLockConfig(): LockedCommandConfig
|
||||
{
|
||||
return LockedCommandConfig::nonBlocking($this->getName());
|
||||
return LockedCommandConfig::nonBlocking(self::NAME);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,10 +42,7 @@ class GeolocationDbUpdateFailedException extends RuntimeException implements Exc
|
|||
return $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $buildEpoch
|
||||
*/
|
||||
public static function withInvalidEpochInOldDb($buildEpoch): self
|
||||
public static function withInvalidEpochInOldDb(mixed $buildEpoch): self
|
||||
{
|
||||
$e = new self(sprintf(
|
||||
'Build epoch with value "%s" from existing geolocation database, could not be parsed to integer.',
|
||||
|
|
|
@ -68,6 +68,21 @@ class RoleResolverTest extends TestCase
|
|||
[RoleDefinition::forDomain($domain)],
|
||||
1,
|
||||
];
|
||||
yield 'false domain role' => [
|
||||
$buildInput([RoleResolver::DOMAIN_ONLY_PARAM => false]),
|
||||
[],
|
||||
0,
|
||||
];
|
||||
yield 'true domain role' => [
|
||||
$buildInput([RoleResolver::DOMAIN_ONLY_PARAM => true]),
|
||||
[],
|
||||
0,
|
||||
];
|
||||
yield 'string array domain role' => [
|
||||
$buildInput([RoleResolver::DOMAIN_ONLY_PARAM => ['foo', 'bar']]),
|
||||
[],
|
||||
0,
|
||||
];
|
||||
yield 'author role only' => [
|
||||
$buildInput([RoleResolver::DOMAIN_ONLY_PARAM => null, RoleResolver::AUTHOR_ONLY_PARAM => true]),
|
||||
[RoleDefinition::forAuthoredShortUrls()],
|
||||
|
|
|
@ -23,6 +23,7 @@ class RobotsAction implements RequestHandlerInterface, StatusCodeInterface
|
|||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
// @phpstan-ignore-next-line The "Response" phpdoc is wrong
|
||||
return new Response(self::STATUS_OK, ['Content-type' => 'text/plain'], $this->buildRobots());
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ class DomainService implements DomainServiceInterface
|
|||
public function getOrCreate(string $authority): Domain
|
||||
{
|
||||
$repo = $this->em->getRepository(Domain::class);
|
||||
/** @var Domain|null $domain */
|
||||
$domain = $repo->findOneBy(['authority' => $authority]) ?? new Domain($authority);
|
||||
|
||||
$this->em->persist($domain);
|
||||
|
|
|
@ -26,17 +26,20 @@ class NotFoundRedirectHandler implements MiddlewareInterface
|
|||
$notFoundType = $request->getAttribute(NotFoundType::class);
|
||||
|
||||
if ($notFoundType->isBaseUrl() && $this->redirectOptions->hasBaseUrlRedirect()) {
|
||||
// @phpstan-ignore-next-line Create custom PHPStan rule
|
||||
return $this->redirectResponseHelper->buildRedirectResponse($this->redirectOptions->getBaseUrlRedirect());
|
||||
}
|
||||
|
||||
if ($notFoundType->isRegularNotFound() && $this->redirectOptions->hasRegular404Redirect()) {
|
||||
return $this->redirectResponseHelper->buildRedirectResponse(
|
||||
// @phpstan-ignore-next-line Create custom PHPStan rule
|
||||
$this->redirectOptions->getRegular404Redirect(),
|
||||
);
|
||||
}
|
||||
|
||||
if ($notFoundType->isInvalidShortUrl() && $this->redirectOptions->hasInvalidShortUrlRedirect()) {
|
||||
return $this->redirectResponseHelper->buildRedirectResponse(
|
||||
// @phpstan-ignore-next-line Create custom PHPStan rule
|
||||
$this->redirectOptions->getInvalidShortUrlRedirect(),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ class LocateVisit
|
|||
}
|
||||
|
||||
$isLocatable = $originalIpAddress !== null || $visit->isLocatable();
|
||||
$addr = $originalIpAddress ?? $visit->getRemoteAddr();
|
||||
$addr = $originalIpAddress ?? $visit->getRemoteAddr() ?? '';
|
||||
|
||||
try {
|
||||
$location = $isLocatable ? $this->ipLocationResolver->resolveIpLocation($addr) : Location::emptyInstance();
|
||||
|
|
|
@ -28,7 +28,7 @@ class ImportedLinksProcessor implements ImportedLinksProcessorInterface
|
|||
private ShortCodeHelperInterface $shortCodeHelper,
|
||||
private DoctrineBatchHelperInterface $batchHelper
|
||||
) {
|
||||
$this->shortUrlRepo = $this->em->getRepository(ShortUrl::class); // @phpstan-ignore-line
|
||||
$this->shortUrlRepo = $this->em->getRepository(ShortUrl::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -42,7 +42,7 @@ final class MercureUpdatesGenerator implements MercureUpdatesGeneratorInterface
|
|||
public function newShortUrlVisitUpdate(Visit $visit): Update
|
||||
{
|
||||
$shortUrl = $visit->getShortUrl();
|
||||
$topic = sprintf('%s/%s', self::NEW_VISIT_TOPIC, $shortUrl->getShortCode());
|
||||
$topic = sprintf('%s/%s', self::NEW_VISIT_TOPIC, $shortUrl?->getShortCode());
|
||||
|
||||
return new Update($topic, $this->serialize([
|
||||
'shortUrl' => $this->shortUrlTransformer->transform($shortUrl),
|
||||
|
|
|
@ -49,7 +49,6 @@ final class ShortUrlsOrdering
|
|||
]);
|
||||
}
|
||||
|
||||
/** @var string|array $orderBy */
|
||||
if (! $isArray) {
|
||||
[$field, $dir] = array_pad(explode('-', $orderBy), 2, null);
|
||||
$this->orderField = $field;
|
||||
|
|
|
@ -19,7 +19,7 @@ final class ShortUrlsParams
|
|||
private array $tags;
|
||||
private ShortUrlsOrdering $orderBy;
|
||||
private ?DateRange $dateRange;
|
||||
private ?int $itemsPerPage = null;
|
||||
private int $itemsPerPage;
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
|
|
|
@ -29,13 +29,16 @@ final class Visitor
|
|||
$this->userAgent = $this->cropToLength($userAgent, self::USER_AGENT_MAX_LENGTH);
|
||||
$this->referer = $this->cropToLength($referer, self::REFERER_MAX_LENGTH);
|
||||
$this->visitedUrl = $this->cropToLength($visitedUrl, self::VISITED_URL_MAX_LENGTH);
|
||||
$this->remoteAddress = $this->cropToLength($remoteAddress, self::REMOTE_ADDRESS_MAX_LENGTH);
|
||||
$this->remoteAddress = $remoteAddress === null ? null : $this->cropToLength(
|
||||
$remoteAddress,
|
||||
self::REMOTE_ADDRESS_MAX_LENGTH,
|
||||
);
|
||||
$this->potentialBot = isCrawler($userAgent);
|
||||
}
|
||||
|
||||
private function cropToLength(?string $value, int $length): ?string
|
||||
private function cropToLength(string $value, int $length): string
|
||||
{
|
||||
return $value === null ? null : substr($value, 0, $length);
|
||||
return substr($value, 0, $length);
|
||||
}
|
||||
|
||||
public static function fromRequest(ServerRequestInterface $request): self
|
||||
|
|
|
@ -13,7 +13,7 @@ final class VisitsParams
|
|||
private const FIRST_PAGE = 1;
|
||||
private const ALL_ITEMS = -1;
|
||||
|
||||
private ?DateRange $dateRange;
|
||||
private DateRange $dateRange;
|
||||
private int $itemsPerPage;
|
||||
|
||||
public function __construct(
|
||||
|
|
|
@ -18,7 +18,6 @@ use Shlinkio\Shlink\Core\Model\ShortUrlsOrdering;
|
|||
use Shlinkio\Shlink\Importer\Model\ImportedShlinkUrl;
|
||||
|
||||
use function array_column;
|
||||
use function array_key_exists;
|
||||
use function count;
|
||||
use function Functional\contains;
|
||||
|
||||
|
@ -59,6 +58,7 @@ class ShortUrlRepository extends EntitySpecificationRepository implements ShortU
|
|||
|
||||
// visitsCount and visitCount are deprecated. Only visits should work
|
||||
if (contains(['visits', 'visitsCount', 'visitCount'], $fieldName)) {
|
||||
// FIXME This query is inefficient. Debug it.
|
||||
$qb->addSelect('COUNT(DISTINCT v) AS totalVisits')
|
||||
->leftJoin('s.visits', 'v')
|
||||
->groupBy('s')
|
||||
|
@ -75,9 +75,11 @@ class ShortUrlRepository extends EntitySpecificationRepository implements ShortU
|
|||
'dateCreated' => 'dateCreated',
|
||||
'title' => 'title',
|
||||
];
|
||||
if (array_key_exists($fieldName, $fieldNameMap)) {
|
||||
$qb->orderBy('s.' . $fieldNameMap[$fieldName], $order);
|
||||
$resolvedFieldName = $fieldNameMap[$fieldName] ?? null;
|
||||
if ($resolvedFieldName !== null) {
|
||||
$qb->orderBy('s.' . $resolvedFieldName, $order);
|
||||
}
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
|
@ -194,10 +196,12 @@ class ShortUrlRepository extends EntitySpecificationRepository implements ShortU
|
|||
|
||||
private function doShortCodeIsInUse(ShortUrlIdentifier $identifier, ?Specification $spec, ?int $lockMode): bool
|
||||
{
|
||||
$qb = $this->createFindOneQueryBuilder($identifier, $spec);
|
||||
$qb->select('s.id');
|
||||
$qb = $this->createFindOneQueryBuilder($identifier, $spec)->select('s.id');
|
||||
$query = $qb->getQuery();
|
||||
|
||||
$query = $qb->getQuery()->setLockMode($lockMode);
|
||||
if ($lockMode !== null) {
|
||||
$query = $query->setLockMode($lockMode);
|
||||
}
|
||||
|
||||
return $query->getOneOrNullResult() !== null;
|
||||
}
|
||||
|
|
|
@ -7,8 +7,7 @@ namespace Shlinkio\Shlink\Core\Util;
|
|||
use Cocur\Slugify\SlugifyInterface;
|
||||
use Symfony\Component\String\AbstractUnicodeString;
|
||||
use Symfony\Component\String\Slugger\SluggerInterface;
|
||||
|
||||
use function Symfony\Component\String\s;
|
||||
use Symfony\Component\String\UnicodeString;
|
||||
|
||||
class CocurSymfonySluggerBridge implements SluggerInterface
|
||||
{
|
||||
|
@ -18,6 +17,6 @@ class CocurSymfonySluggerBridge implements SluggerInterface
|
|||
|
||||
public function slug(string $string, string $separator = '-', ?string $locale = null): AbstractUnicodeString
|
||||
{
|
||||
return s($this->slugger->slugify($string, $separator));
|
||||
return new UnicodeString($this->slugger->slugify($string, $separator));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ class EditShortUrlTagsAction extends AbstractRestAction
|
|||
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
/** @var array $bodyParams */
|
||||
$bodyParams = $request->getParsedBody();
|
||||
|
||||
if (! isset($bodyParams['tags'])) {
|
||||
|
|
|
@ -20,15 +20,9 @@ class CreateTagsAction extends AbstractRestAction
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an incoming server request and return a response, optionally delegating
|
||||
* to the next middleware component to create the response.
|
||||
*
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
/** @var array $body */
|
||||
$body = $request->getParsedBody();
|
||||
$tags = $body['tags'] ?? [];
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ class UpdateTagAction extends AbstractRestAction
|
|||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
/** @var array $body */
|
||||
$body = $request->getParsedBody();
|
||||
$apiKey = AuthenticationMiddleware::apiKeyFromRequest($request);
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ class DefaultShortCodesLengthMiddleware implements MiddlewareInterface
|
|||
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
{
|
||||
/** @var array $body */
|
||||
$body = $request->getParsedBody();
|
||||
if (! isset($body[ShortUrlInputFilter::SHORT_CODE_LENGTH])) {
|
||||
$body[ShortUrlInputFilter::SHORT_CODE_LENGTH] = $this->defaultShortCodesLength;
|
||||
|
|
|
@ -17,8 +17,10 @@ class DropDefaultDomainFromRequestMiddleware implements MiddlewareInterface
|
|||
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
{
|
||||
/** @var array $body */
|
||||
$body = $request->getParsedBody();
|
||||
$request = $request->withQueryParams($this->sanitizeDomainFromPayload($request->getQueryParams()))
|
||||
->withParsedBody($this->sanitizeDomainFromPayload($request->getParsedBody()));
|
||||
->withParsedBody($this->sanitizeDomainFromPayload($body));
|
||||
|
||||
return $handler->handle($request);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ class OverrideDomainMiddleware implements MiddlewareInterface
|
|||
$domain = $this->domainService->getDomain($domainId);
|
||||
|
||||
if ($requestMethod === RequestMethodInterface::METHOD_POST) {
|
||||
/** @var array $payload */
|
||||
$payload = $request->getParsedBody();
|
||||
$payload[ShortUrlInputFilter::DOMAIN] = $domain->getAuthority();
|
||||
|
||||
|
|
|
@ -38,12 +38,12 @@ class ApiKeyService implements ApiKeyServiceInterface
|
|||
private function buildApiKeyWithParams(?Chronos $expirationDate, ?string $name): ApiKey
|
||||
{
|
||||
return match (true) {
|
||||
$expirationDate === null && $name === null => ApiKey::create(),
|
||||
$expirationDate !== null && $name !== null => ApiKey::fromMeta(
|
||||
ApiKeyMeta::withNameAndExpirationDate($name, $expirationDate),
|
||||
),
|
||||
$name === null => ApiKey::fromMeta(ApiKeyMeta::withExpirationDate($expirationDate)),
|
||||
default => ApiKey::fromMeta(ApiKeyMeta::withName($name)),
|
||||
$expirationDate !== null => ApiKey::fromMeta(ApiKeyMeta::withExpirationDate($expirationDate)),
|
||||
$name !== null => ApiKey::fromMeta(ApiKeyMeta::withName($name)),
|
||||
default => ApiKey::create(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
10
phpstan.neon
10
phpstan.neon
|
@ -1,5 +1,11 @@
|
|||
includes:
|
||||
- vendor/phpstan/phpstan-doctrine/extension.neon
|
||||
- vendor/phpstan/phpstan-symfony/extension.neon
|
||||
parameters:
|
||||
checkMissingIterableValueType: false
|
||||
checkGenericClassInNonGenericObjectType: false
|
||||
ignoreErrors:
|
||||
- '#If condition is always false#'
|
||||
symfony:
|
||||
console_application_loader: 'config/cli-app.php'
|
||||
doctrine:
|
||||
repositoryClass: Happyr\DoctrineSpecification\Repository\EntitySpecificationRepository
|
||||
objectManagerLoader: 'config/entity-manager.php'
|
||||
|
|
|
@ -2,5 +2,4 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
$run = require __DIR__ . '/../config/run.php';
|
||||
$run();
|
||||
(require __DIR__ . '/../config/run.php')();
|
||||
|
|
Loading…
Reference in a new issue