Added property types to some classes

This commit is contained in:
Alejandro Celaya 2019-12-29 22:27:00 +01:00
parent 050050a9eb
commit b904c6d00d
86 changed files with 218 additions and 457 deletions

View file

@ -60,7 +60,7 @@
"devster/ubench": "^2.0",
"eaglewu/swoole-ide-helper": "dev-master",
"infection/infection": "^0.15.0",
"phpstan/phpstan-shim": "^0.11.16",
"phpstan/phpstan": "^0.12.3",
"phpunit/phpunit": "^8.3",
"roave/security-advisories": "dev-master",
"shlinkio/php-coding-standard": "~2.0.0",

View file

@ -19,8 +19,7 @@ class DisableKeyCommand extends Command
{
public const NAME = 'api-key:disable';
/** @var ApiKeyServiceInterface */
private $apiKeyService;
private ApiKeyServiceInterface $apiKeyService;
public function __construct(ApiKeyServiceInterface $apiKeyService)
{

View file

@ -19,8 +19,7 @@ class GenerateKeyCommand extends Command
{
public const NAME = 'api-key:generate';
/** @var ApiKeyServiceInterface */
private $apiKeyService;
private ApiKeyServiceInterface $apiKeyService;
public function __construct(ApiKeyServiceInterface $apiKeyService)
{

View file

@ -25,8 +25,7 @@ class ListKeysCommand extends Command
public const NAME = 'api-key:list';
/** @var ApiKeyServiceInterface */
private $apiKeyService;
private ApiKeyServiceInterface $apiKeyService;
public function __construct(ApiKeyServiceInterface $apiKeyService)
{

View file

@ -15,10 +15,8 @@ use function array_unshift;
abstract class AbstractDatabaseCommand extends AbstractLockedCommand
{
/** @var ProcessHelper */
private $processHelper;
/** @var string */
private $phpBinary;
private ProcessHelper $processHelper;
private string $phpBinary;
public function __construct(LockFactory $locker, ProcessHelper $processHelper, PhpExecutableFinder $phpFinder)
{

View file

@ -21,10 +21,8 @@ class CreateDatabaseCommand extends AbstractDatabaseCommand
public const DOCTRINE_SCRIPT = 'vendor/doctrine/orm/bin/doctrine.php';
public const DOCTRINE_CREATE_SCHEMA_COMMAND = 'orm:schema-tool:create';
/** @var Connection */
private $regularConn;
/** @var Connection */
private $noDbNameConn;
private Connection $regularConn;
private Connection $noDbNameConn;
public function __construct(
LockFactory $locker,

View file

@ -21,8 +21,7 @@ class DeleteShortUrlCommand extends Command
public const NAME = 'short-url:delete';
private const ALIASES = ['short-code:delete'];
/** @var DeleteShortUrlServiceInterface */
private $deleteShortUrlService;
private DeleteShortUrlServiceInterface $deleteShortUrlService;
public function __construct(DeleteShortUrlServiceInterface $deleteShortUrlService)
{

View file

@ -28,10 +28,8 @@ class GenerateShortUrlCommand extends Command
public const NAME = 'short-url:generate';
private const ALIASES = ['shortcode:generate', 'short-code:generate'];
/** @var UrlShortenerInterface */
private $urlShortener;
/** @var array */
private $domainConfig;
private UrlShortenerInterface $urlShortener;
private array $domainConfig;
public function __construct(UrlShortenerInterface $urlShortener, array $domainConfig)
{

View file

@ -24,8 +24,7 @@ class GetVisitsCommand extends AbstractWithDateRangeCommand
public const NAME = 'short-url:visits';
private const ALIASES = ['shortcode:visits', 'short-code:visits'];
/** @var VisitsTrackerInterface */
private $visitsTracker;
private VisitsTrackerInterface $visitsTracker;
public function __construct(VisitsTrackerInterface $visitsTracker)
{

View file

@ -42,10 +42,8 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand
'tags',
];
/** @var ShortUrlServiceInterface */
private $shortUrlService;
/** @var ShortUrlDataTransformer */
private $transformer;
private ShortUrlServiceInterface $shortUrlService;
private ShortUrlDataTransformer $transformer;
public function __construct(ShortUrlServiceInterface $shortUrlService, array $domainConfig)
{

View file

@ -21,8 +21,7 @@ class ResolveUrlCommand extends Command
public const NAME = 'short-url:parse';
private const ALIASES = ['shortcode:parse', 'short-code:parse'];
/** @var UrlShortenerInterface */
private $urlShortener;
private UrlShortenerInterface $urlShortener;
public function __construct(UrlShortenerInterface $urlShortener)
{

View file

@ -16,8 +16,7 @@ class CreateTagCommand extends Command
{
public const NAME = 'tag:create';
/** @var TagServiceInterface */
private $tagService;
private TagServiceInterface $tagService;
public function __construct(TagServiceInterface $tagService)
{

View file

@ -16,8 +16,7 @@ class DeleteTagsCommand extends Command
{
public const NAME = 'tag:delete';
/** @var TagServiceInterface */
private $tagService;
private TagServiceInterface $tagService;
public function __construct(TagServiceInterface $tagService)
{

View file

@ -18,8 +18,7 @@ class ListTagsCommand extends Command
{
public const NAME = 'tag:list';
/** @var TagServiceInterface */
private $tagService;
private TagServiceInterface $tagService;
public function __construct(TagServiceInterface $tagService)
{

View file

@ -18,8 +18,7 @@ class RenameTagCommand extends Command
{
public const NAME = 'tag:rename';
/** @var TagServiceInterface */
private $tagService;
private TagServiceInterface $tagService;
public function __construct(TagServiceInterface $tagService)
{

View file

@ -14,8 +14,7 @@ use function sprintf;
abstract class AbstractLockedCommand extends Command
{
/** @var LockFactory */
private $locker;
private LockFactory $locker;
public function __construct(LockFactory $locker)
{

View file

@ -8,12 +8,9 @@ final class LockedCommandConfig
{
private const DEFAULT_TTL = 90.0; // 1.5 minutes
/** @var string */
private $lockName;
/** @var bool */
private $isBlocking;
/** @var float */
private $ttl;
private string $lockName;
private bool $isBlocking;
private float $ttl;
public function __construct(string $lockName, bool $isBlocking = false, float $ttl = self::DEFAULT_TTL)
{

View file

@ -32,17 +32,12 @@ class LocateVisitsCommand extends AbstractLockedCommand
public const NAME = 'visit:locate';
public const ALIASES = ['visit:process'];
/** @var VisitServiceInterface */
private $visitService;
/** @var IpLocationResolverInterface */
private $ipLocationResolver;
/** @var GeolocationDbUpdaterInterface */
private $dbUpdater;
private VisitServiceInterface $visitService;
private IpLocationResolverInterface $ipLocationResolver;
private GeolocationDbUpdaterInterface $dbUpdater;
/** @var SymfonyStyle */
private $io;
/** @var ProgressBar */
private $progressBar;
private SymfonyStyle $io;
private ?ProgressBar $progressBar = null;
public function __construct(
VisitServiceInterface $visitService,

View file

@ -9,8 +9,7 @@ use Throwable;
class GeolocationDbUpdateFailedException extends RuntimeException implements ExceptionInterface
{
/** @var bool */
private $olderDbExists;
private bool $olderDbExists;
public static function create(bool $olderDbExists, ?Throwable $prev = null): self
{

View file

@ -15,12 +15,9 @@ class GeolocationDbUpdater implements GeolocationDbUpdaterInterface
{
private const LOCK_NAME = 'geolocation-db-update';
/** @var DbUpdaterInterface */
private $dbUpdater;
/** @var Reader */
private $geoLiteDbReader;
/** @var LockFactory */
private $locker;
private DbUpdaterInterface $dbUpdater;
private Reader $geoLiteDbReader;
private LockFactory $locker;
public function __construct(DbUpdaterInterface $dbUpdater, Reader $geoLiteDbReader, LockFactory $locker)
{

View file

@ -12,8 +12,7 @@ final class ShlinkTable
private const DEFAULT_STYLE_NAME = 'default';
private const TABLE_TITLE_STYLE = '<options=bold> %s </>';
/** @var Table|null */
private $baseTable;
private ?Table $baseTable;
public function __construct(Table $baseTable)
{

View file

@ -8,20 +8,18 @@ use PHPUnit\Framework\TestCase;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Api\DisableKeyCommand;
use Shlinkio\Shlink\Common\Exception\InvalidArgumentException;
use Shlinkio\Shlink\Rest\Service\ApiKeyService;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
class DisableKeyCommandTest extends TestCase
{
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $apiKeyService;
private CommandTester $commandTester;
private ObjectProphecy $apiKeyService;
public function setUp(): void
{
$this->apiKeyService = $this->prophesize(ApiKeyService::class);
$this->apiKeyService = $this->prophesize(ApiKeyServiceInterface::class);
$command = new DisableKeyCommand($this->apiKeyService->reveal());
$app = new Application();
$app->add($command);

View file

@ -10,20 +10,18 @@ use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Api\GenerateKeyCommand;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
use Shlinkio\Shlink\Rest\Service\ApiKeyService;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
class GenerateKeyCommandTest extends TestCase
{
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $apiKeyService;
private CommandTester $commandTester;
private ObjectProphecy $apiKeyService;
public function setUp(): void
{
$this->apiKeyService = $this->prophesize(ApiKeyService::class);
$this->apiKeyService = $this->prophesize(ApiKeyServiceInterface::class);
$command = new GenerateKeyCommand($this->apiKeyService->reveal());
$app = new Application();
$app->add($command);

View file

@ -8,20 +8,18 @@ use PHPUnit\Framework\TestCase;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Api\ListKeysCommand;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
use Shlinkio\Shlink\Rest\Service\ApiKeyService;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
class ListKeysCommandTest extends TestCase
{
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $apiKeyService;
private CommandTester $commandTester;
private ObjectProphecy $apiKeyService;
public function setUp(): void
{
$this->apiKeyService = $this->prophesize(ApiKeyService::class);
$this->apiKeyService = $this->prophesize(ApiKeyServiceInterface::class);
$command = new ListKeysCommand($this->apiKeyService->reveal());
$app = new Application();
$app->add($command);

View file

@ -15,8 +15,7 @@ use function str_split;
class GenerateCharsetCommandTest extends TestCase
{
/** @var CommandTester */
private $commandTester;
private CommandTester $commandTester;
public function setUp(): void
{

View file

@ -21,18 +21,12 @@ use Symfony\Component\Process\PhpExecutableFinder;
class CreateDatabaseCommandTest extends TestCase
{
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $processHelper;
/** @var ObjectProphecy */
private $regularConn;
/** @var ObjectProphecy */
private $noDbNameConn;
/** @var ObjectProphecy */
private $schemaManager;
/** @var ObjectProphecy */
private $databasePlatform;
private CommandTester $commandTester;
private ObjectProphecy $processHelper;
private ObjectProphecy $regularConn;
private ObjectProphecy $noDbNameConn;
private ObjectProphecy $schemaManager;
private ObjectProphecy $databasePlatform;
public function setUp(): void
{

View file

@ -18,10 +18,8 @@ use Symfony\Component\Process\PhpExecutableFinder;
class MigrateDatabaseCommandTest extends TestCase
{
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $processHelper;
private CommandTester $commandTester;
private ObjectProphecy $processHelper;
public function setUp(): void
{

View file

@ -20,10 +20,8 @@ use const PHP_EOL;
class DeleteShortUrlCommandTest extends TestCase
{
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $service;
private CommandTester $commandTester;
private ObjectProphecy $service;
public function setUp(): void
{

View file

@ -22,12 +22,9 @@ use function substr_count;
class GeneratePreviewCommandTest extends TestCase
{
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $previewGenerator;
/** @var ObjectProphecy */
private $shortUrlService;
private CommandTester $commandTester;
private ObjectProphecy $previewGenerator;
private ObjectProphecy $shortUrlService;
public function setUp(): void
{

View file

@ -25,10 +25,8 @@ class GenerateShortUrlCommandTest extends TestCase
'hostname' => 'foo.com',
];
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $urlShortener;
private CommandTester $commandTester;
private ObjectProphecy $urlShortener;
public function setUp(): void
{

View file

@ -26,10 +26,8 @@ use function sprintf;
class GetVisitsCommandTest extends TestCase
{
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $visitsTracker;
private CommandTester $commandTester;
private ObjectProphecy $visitsTracker;
public function setUp(): void
{

View file

@ -21,10 +21,8 @@ use function explode;
class ListShortUrlsCommandTest extends TestCase
{
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $shortUrlService;
private CommandTester $commandTester;
private ObjectProphecy $shortUrlService;
public function setUp(): void
{

View file

@ -19,10 +19,8 @@ use const PHP_EOL;
class ResolveUrlCommandTest extends TestCase
{
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $urlShortener;
private CommandTester $commandTester;
private ObjectProphecy $urlShortener;
public function setUp(): void
{

View file

@ -14,10 +14,8 @@ use Symfony\Component\Console\Tester\CommandTester;
class CreateTagCommandTest extends TestCase
{
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $tagService;
private CommandTester $commandTester;
private ObjectProphecy $tagService;
public function setUp(): void
{
@ -31,7 +29,7 @@ class CreateTagCommandTest extends TestCase
}
/** @test */
public function errorIsReturnedWhenNoTagsAreProvided()
public function errorIsReturnedWhenNoTagsAreProvided(): void
{
$this->commandTester->execute([]);
@ -40,7 +38,7 @@ class CreateTagCommandTest extends TestCase
}
/** @test */
public function serviceIsInvokedOnSuccess()
public function serviceIsInvokedOnSuccess(): void
{
$tagNames = ['foo', 'bar'];
$createTags = $this->tagService->createTags($tagNames)->willReturn(new ArrayCollection());

View file

@ -13,12 +13,8 @@ use Symfony\Component\Console\Tester\CommandTester;
class DeleteTagsCommandTest extends TestCase
{
/** @var DeleteTagsCommand */
private $command;
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $tagService;
private CommandTester $commandTester;
private ObjectProphecy $tagService;
public function setUp(): void
{
@ -32,7 +28,7 @@ class DeleteTagsCommandTest extends TestCase
}
/** @test */
public function errorIsReturnedWhenNoTagsAreProvided()
public function errorIsReturnedWhenNoTagsAreProvided(): void
{
$this->commandTester->execute([]);
@ -41,7 +37,7 @@ class DeleteTagsCommandTest extends TestCase
}
/** @test */
public function serviceIsInvokedOnSuccess()
public function serviceIsInvokedOnSuccess(): void
{
$tagNames = ['foo', 'bar'];
$deleteTags = $this->tagService->deleteTags($tagNames)->will(function () {

View file

@ -14,12 +14,8 @@ use Symfony\Component\Console\Tester\CommandTester;
class ListTagsCommandTest extends TestCase
{
/** @var ListTagsCommand */
private $command;
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $tagService;
private CommandTester $commandTester;
private ObjectProphecy $tagService;
public function setUp(): void
{
@ -33,7 +29,7 @@ class ListTagsCommandTest extends TestCase
}
/** @test */
public function noTagsPrintsEmptyMessage()
public function noTagsPrintsEmptyMessage(): void
{
$listTags = $this->tagService->listTags()->willReturn([]);
@ -45,7 +41,7 @@ class ListTagsCommandTest extends TestCase
}
/** @test */
public function listOfTagsIsPrinted()
public function listOfTagsIsPrinted(): void
{
$listTags = $this->tagService->listTags()->willReturn([
new Tag('foo'),

View file

@ -15,12 +15,8 @@ use Symfony\Component\Console\Tester\CommandTester;
class RenameTagCommandTest extends TestCase
{
/** @var RenameTagCommand */
private $command;
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $tagService;
private CommandTester $commandTester;
private ObjectProphecy $tagService;
public function setUp(): void
{

View file

@ -29,18 +29,12 @@ use function sprintf;
class LocateVisitsCommandTest extends TestCase
{
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $visitService;
/** @var ObjectProphecy */
private $ipResolver;
/** @var ObjectProphecy */
private $locker;
/** @var ObjectProphecy */
private $lock;
/** @var ObjectProphecy */
private $dbUpdater;
private CommandTester $commandTester;
private ObjectProphecy $visitService;
private ObjectProphecy $ipResolver;
private ObjectProphecy $locker;
private ObjectProphecy $lock;
private ObjectProphecy $dbUpdater;
public function setUp(): void
{

View file

@ -16,10 +16,8 @@ use Symfony\Component\Console\Tester\CommandTester;
class UpdateDbCommandTest extends TestCase
{
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
private $dbUpdater;
private CommandTester $commandTester;
private ObjectProphecy $dbUpdater;
public function setUp(): void
{

View file

@ -9,8 +9,7 @@ use Shlinkio\Shlink\CLI\ConfigProvider;
class ConfigProviderTest extends TestCase
{
/** @var ConfigProvider */
private $configProvider;
private ConfigProvider $configProvider;
public function setUp(): void
{

View file

@ -15,8 +15,7 @@ use Zend\ServiceManager\ServiceManager;
class ApplicationFactoryTest extends TestCase
{
/** @var ApplicationFactory */
private $factory;
private ApplicationFactory $factory;
public function setUp(): void
{
@ -36,7 +35,6 @@ class ApplicationFactoryTest extends TestCase
$sm->setService('foo', $this->createCommandMock('foo')->reveal());
$sm->setService('bar', $this->createCommandMock('bar')->reveal());
/** @var Application $instance */
$instance = ($this->factory)($sm);
$this->assertTrue($instance->has('foo'));

View file

@ -22,16 +22,11 @@ use function range;
class GeolocationDbUpdaterTest extends TestCase
{
/** @var GeolocationDbUpdater */
private $geolocationDbUpdater;
/** @var ObjectProphecy */
private $dbUpdater;
/** @var ObjectProphecy */
private $geoLiteDbReader;
/** @var ObjectProphecy */
private $locker;
/** @var ObjectProphecy */
private $lock;
private GeolocationDbUpdater $geolocationDbUpdater;
private ObjectProphecy $dbUpdater;
private ObjectProphecy $geoLiteDbReader;
private ObjectProphecy $locker;
private ObjectProphecy $lock;
public function setUp(): void
{

View file

@ -15,10 +15,8 @@ use Symfony\Component\Console\Output\OutputInterface;
class ShlinkTableTest extends TestCase
{
/** @var ShlinkTable */
private $shlinkTable;
/** @var ObjectProphecy */
private $baseTable;
private ShlinkTable $shlinkTable;
private ObjectProphecy $baseTable;
public function setUp(): void
{

View file

@ -25,14 +25,10 @@ use function http_build_query;
abstract class AbstractTrackingAction implements MiddlewareInterface
{
/** @var UrlShortenerInterface */
private $urlShortener;
/** @var VisitsTrackerInterface */
private $visitTracker;
/** @var AppOptions */
private $appOptions;
/** @var LoggerInterface */
private $logger;
private UrlShortenerInterface $urlShortener;
private VisitsTrackerInterface $visitTracker;
private AppOptions $appOptions;
private LoggerInterface $logger;
public function __construct(
UrlShortenerInterface $urlShortener,

View file

@ -23,12 +23,9 @@ class QrCodeAction implements MiddlewareInterface
private const MIN_SIZE = 50;
private const MAX_SIZE = 1000;
/** @var RouterInterface */
private $router;
/** @var UrlShortenerInterface */
private $urlShortener;
/** @var LoggerInterface */
private $logger;
private RouterInterface $router;
private UrlShortenerInterface $urlShortener;
private LoggerInterface $logger;
public function __construct(
RouterInterface $router,

View file

@ -9,8 +9,7 @@ use Shlinkio\Shlink\Core\Entity\Domain;
class PersistenceDomainResolver implements DomainResolverInterface
{
/** @var EntityManagerInterface */
private $em;
private EntityManagerInterface $em;
public function __construct(EntityManagerInterface $em)
{

View file

@ -8,8 +8,7 @@ use Shlinkio\Shlink\Common\Entity\AbstractEntity;
class Domain extends AbstractEntity
{
/** @var string */
private $authority;
private string $authority;
public function __construct(string $authority)
{

View file

@ -22,26 +22,18 @@ use function Shlinkio\Shlink\Core\generateRandomShortCode;
class ShortUrl extends AbstractEntity
{
/** @var string */
private $longUrl;
/** @var string */
private $shortCode;
/** @var Chronos */
private $dateCreated;
private string $longUrl;
private string $shortCode;
private Chronos $dateCreated;
/** @var Collection|Visit[] */
private $visits;
private Collection $visits;
/** @var Collection|Tag[] */
private $tags;
/** @var Chronos|null */
private $validSince;
/** @var Chronos|null */
private $validUntil;
/** @var integer|null */
private $maxVisits;
/** @var Domain|null */
private $domain;
/** @var bool */
private $customSlugWasProvided;
private Collection $tags;
private ?Chronos $validSince;
private ?Chronos $validUntil;
private ?int $maxVisits;
private ?Domain $domain;
private bool $customSlugWasProvided;
public function __construct(
string $longUrl,

View file

@ -9,8 +9,7 @@ use Shlinkio\Shlink\Common\Entity\AbstractEntity;
class Tag extends AbstractEntity implements JsonSerializable
{
/** @var string */
private $name;
private string $name;
public function __construct(string $name)
{

View file

@ -15,18 +15,12 @@ use Shlinkio\Shlink\Core\Visit\Model\VisitLocationInterface;
class Visit extends AbstractEntity implements JsonSerializable
{
/** @var string */
private $referer;
/** @var Chronos */
private $date;
/** @var string|null */
private $remoteAddr;
/** @var string */
private $userAgent;
/** @var ShortUrl */
private $shortUrl;
/** @var VisitLocation */
private $visitLocation;
private string $referer;
private Chronos $date;
private ?string $remoteAddr;
private string $userAgent;
private ShortUrl $shortUrl;
private ?VisitLocation $visitLocation = null;
public function __construct(ShortUrl $shortUrl, Visitor $visitor, ?Chronos $date = null)
{

View file

@ -10,20 +10,13 @@ use Shlinkio\Shlink\IpGeolocation\Model\Location;
class VisitLocation extends AbstractEntity implements VisitLocationInterface
{
/** @var string */
private $countryCode;
/** @var string */
private $countryName;
/** @var string */
private $regionName;
/** @var string */
private $cityName;
/** @var string */
private $latitude;
/** @var string */
private $longitude;
/** @var string */
private $timezone;
private string $countryCode;
private string $countryName;
private string $regionName;
private string $cityName;
private string $latitude; // FIXME Should be float
private string $longitude; // FIXME Should be float
private string $timezone;
public function __construct(Location $location)
{

View file

@ -18,10 +18,8 @@ use function rtrim;
class NotFoundRedirectHandler implements MiddlewareInterface
{
/** @var NotFoundRedirectOptions */
private $redirectOptions;
/** @var string */
private $shlinkBasePath;
private NotFoundRedirectOptions $redirectOptions;
private string $shlinkBasePath;
public function __construct(NotFoundRedirectOptions $redirectOptions, string $shlinkBasePath)
{

View file

@ -18,8 +18,7 @@ class NotFoundTemplateHandler implements RequestHandlerInterface
public const NOT_FOUND_TEMPLATE = 'ShlinkCore::error/404';
public const INVALID_SHORT_CODE_TEMPLATE = 'ShlinkCore::invalid-short-code';
/** @var TemplateRendererInterface */
private $renderer;
private TemplateRendererInterface $renderer;
public function __construct(TemplateRendererInterface $renderer)
{

View file

@ -19,16 +19,11 @@ use function sprintf;
class LocateShortUrlVisit
{
/** @var IpLocationResolverInterface */
private $ipLocationResolver;
/** @var EntityManagerInterface */
private $em;
/** @var LoggerInterface */
private $logger;
/** @var GeolocationDbUpdaterInterface */
private $dbUpdater;
/** @var EventDispatcherInterface */
private $eventDispatcher;
private IpLocationResolverInterface $ipLocationResolver;
private EntityManagerInterface $em;
private LoggerInterface $logger;
private GeolocationDbUpdaterInterface $dbUpdater;
private EventDispatcherInterface $eventDispatcher;
public function __construct(
IpLocationResolverInterface $ipLocationResolver,

View file

@ -22,18 +22,13 @@ use function GuzzleHttp\Promise\settle;
class NotifyVisitToWebHooks
{
/** @var ClientInterface */
private $httpClient;
/** @var EntityManagerInterface */
private $em;
/** @var LoggerInterface */
private $logger;
/** @var array */
private $webhooks;
/** @var ShortUrlDataTransformer */
private $transformer;
/** @var AppOptions */
private $appOptions;
private ClientInterface $httpClient;
private EntityManagerInterface $em;
private LoggerInterface $logger;
/** @var string[] */
private array $webhooks;
private ShortUrlDataTransformer $transformer;
private AppOptions $appOptions;
public function __construct(
ClientInterface $httpClient,

View file

@ -8,8 +8,7 @@ use JsonSerializable;
final class ShortUrlVisited implements JsonSerializable
{
/** @var string */
private $visitId;
private string $visitId;
public function __construct(string $visitId)
{

View file

@ -8,8 +8,7 @@ use JsonSerializable;
final class VisitLocated implements JsonSerializable
{
/** @var string */
private $visitId;
private string $visitId;
public function __construct(string $visitId)
{

View file

@ -8,32 +8,24 @@ use Throwable;
class IpCannotBeLocatedException extends RuntimeException
{
/** @var bool */
private $isNonLocatableAddress;
public function __construct(
bool $isNonLocatableAddress,
string $message,
int $code = 0,
?Throwable $previous = null
) {
$this->isNonLocatableAddress = $isNonLocatableAddress;
parent::__construct($message, $code, $previous);
}
private bool $isNonLocatableAddress = true;
public static function forEmptyAddress(): self
{
return new self(true, 'Ignored visit with no IP address');
return new self('Ignored visit with no IP address');
}
public static function forLocalhost(): self
{
return new self(true, 'Ignored localhost address');
return new self('Ignored localhost address');
}
public static function forError(Throwable $e): self
{
return new self(false, 'An error occurred while locating IP', $e->getCode(), $e);
$e = new self('An error occurred while locating IP', $e->getCode(), $e);
$e->isNonLocatableAddress = false;
return $e;
}
/**

View file

@ -25,8 +25,7 @@ class ValidationException extends InvalidArgumentException implements ProblemDet
private const TITLE = 'Invalid data';
private const TYPE = 'INVALID_ARGUMENT';
/** @var array */
private $invalidElements;
private array $invalidElements;
public static function fromInputFilter(InputFilterInterface $inputFilter, ?Throwable $prev = null): self
{

View file

@ -13,8 +13,7 @@ use Zend\Diactoros\Response as DiactResp;
class QrCodeCacheMiddleware implements MiddlewareInterface
{
/** @var Cache */
private $cache;
private Cache $cache;
public function __construct(Cache $cache)
{

View file

@ -8,12 +8,9 @@ use Psr\Http\Message\UriInterface;
final class CreateShortUrlData
{
/** @var UriInterface */
private $longUrl;
/** @var array */
private $tags;
/** @var ShortUrlMeta */
private $meta;
private UriInterface $longUrl;
private array $tags;
private ShortUrlMeta $meta;
public function __construct(
UriInterface $longUrl,

View file

@ -11,18 +11,12 @@ use Shlinkio\Shlink\Core\Validation\ShortUrlMetaInputFilter;
final class ShortUrlMeta
{
/** @var Chronos|null */
private $validSince;
/** @var Chronos|null */
private $validUntil;
/** @var string|null */
private $customSlug;
/** @var int|null */
private $maxVisits;
/** @var bool|null */
private $findIfExists;
/** @var string|null */
private $domain;
private ?Chronos $validSince = null;
private ?Chronos $validUntil = null;
private ?string $customSlug = null;
private ?int $maxVisits = null;
private ?bool $findIfExists = null;
private ?string $domain = null;
// Force named constructors
private function __construct()
@ -90,8 +84,8 @@ final class ShortUrlMeta
$this->validSince = $this->parseDateField($inputFilter->getValue(ShortUrlMetaInputFilter::VALID_SINCE));
$this->validUntil = $this->parseDateField($inputFilter->getValue(ShortUrlMetaInputFilter::VALID_UNTIL));
$this->customSlug = $inputFilter->getValue(ShortUrlMetaInputFilter::CUSTOM_SLUG);
$this->maxVisits = $inputFilter->getValue(ShortUrlMetaInputFilter::MAX_VISITS);
$this->maxVisits = $this->maxVisits !== null ? (int) $this->maxVisits : null;
$maxVisits = $inputFilter->getValue(ShortUrlMetaInputFilter::MAX_VISITS);
$this->maxVisits = $maxVisits !== null ? (int) $maxVisits : null;
$this->findIfExists = $inputFilter->getValue(ShortUrlMetaInputFilter::FIND_IF_EXISTS);
$this->domain = $inputFilter->getValue(ShortUrlMetaInputFilter::DOMAIN);
}

View file

@ -15,12 +15,9 @@ final class Visitor
public const REFERER_MAX_LENGTH = 1024;
public const REMOTE_ADDRESS_MAX_LENGTH = 256;
/** @var string */
private $userAgent;
/** @var string */
private $referer;
/** @var string|null */
private $remoteAddress;
private string $userAgent;
private string $referer;
private ?string $remoteAddress;
public function __construct(string $userAgent, string $referer, ?string $remoteAddress)
{

View file

@ -12,12 +12,9 @@ final class VisitsParams
private const FIRST_PAGE = 1;
private const ALL_ITEMS = -1;
/** @var null|DateRange */
private $dateRange;
/** @var int */
private $page;
/** @var int */
private $itemsPerPage;
private ?DateRange $dateRange;
private int $page;
private int $itemsPerPage;
public function __construct(?DateRange $dateRange = null, int $page = self::FIRST_PAGE, ?int $itemsPerPage = null)
{

View file

@ -13,17 +13,11 @@ class AppOptions extends AbstractOptions
{
use StringUtilsTrait;
/** @var string */
private $name = '';
/** @var string */
private $version = '1.0';
/**
* @var string
* @deprecated
*/
private $secretKey = '';
/** @var string|null */
private $disableTrackParam;
private string $name = '';
private string $version = '1.0';
/** @deprecated */
private string $secretKey = '';
private ?string $disableTrackParam = null;
public function getName(): string
{

View file

@ -8,12 +8,9 @@ use Zend\Stdlib\AbstractOptions;
class NotFoundRedirectOptions extends AbstractOptions
{
/** @var string|null */
private $invalidShortUrl;
/** @var string|null */
private $regular404;
/** @var string|null */
private $baseUrl;
private ?string $invalidShortUrl = null;
private ?string $regular404 = null;
private ?string $baseUrl = null;
public function getInvalidShortUrlRedirect(): ?string
{

View file

@ -15,16 +15,12 @@ class ShortUrlRepositoryAdapter implements AdapterInterface
{
public const ITEMS_PER_PAGE = 10;
/** @var ShortUrlRepositoryInterface */
private $repository;
/** @var null|string */
private $searchTerm;
private ShortUrlRepositoryInterface $repository;
private ?string $searchTerm;
/** @var null|array|string */
private $orderBy;
/** @var array */
private $tags;
/** @var DateRange|null */
private $dateRange;
private array $tags;
private ?DateRange $dateRange;
public function __construct(
ShortUrlRepositoryInterface $repository,

View file

@ -10,12 +10,9 @@ use Zend\Paginator\Adapter\AdapterInterface;
class VisitsPaginatorAdapter implements AdapterInterface
{
/** @var VisitRepositoryInterface */
private $visitRepository;
/** @var string */
private $shortCode;
/** @var VisitsParams */
private $params;
private VisitRepositoryInterface $visitRepository;
private string $shortCode;
private VisitsParams $params;
public function __construct(VisitRepositoryInterface $visitRepository, string $shortCode, VisitsParams $params)
{

View file

@ -13,10 +13,8 @@ class DeleteShortUrlService implements DeleteShortUrlServiceInterface
{
use FindShortCodeTrait;
/** @var EntityManagerInterface */
private $em;
/** @var DeleteShortUrlsOptions */
private $deleteShortUrlsOptions;
private EntityManagerInterface $em;
private DeleteShortUrlsOptions $deleteShortUrlsOptions;
public function __construct(EntityManagerInterface $em, DeleteShortUrlsOptions $deleteShortUrlsOptions)
{

View file

@ -20,8 +20,7 @@ class ShortUrlService implements ShortUrlServiceInterface
use FindShortCodeTrait;
use TagManagerTrait;
/** @var ORM\EntityManagerInterface */
private $em;
private ORM\EntityManagerInterface $em;
public function __construct(ORM\EntityManagerInterface $em)
{

View file

@ -16,8 +16,7 @@ class TagService implements TagServiceInterface
{
use TagManagerTrait;
/** @var ORM\EntityManagerInterface */
private $em;
private ORM\EntityManagerInterface $em;
public function __construct(ORM\EntityManagerInterface $em)
{

View file

@ -24,12 +24,9 @@ class UrlShortener implements UrlShortenerInterface
{
use TagManagerTrait;
/** @var EntityManagerInterface */
private $em;
/** @var UrlShortenerOptions */
private $options;
/** @var UrlValidatorInterface */
private $urlValidator;
private EntityManagerInterface $em;
private UrlShortenerOptions $options;
private UrlValidatorInterface $urlValidator;
public function __construct(
UrlValidatorInterface $urlValidator,

View file

@ -13,8 +13,7 @@ use Shlinkio\Shlink\IpGeolocation\Model\Location;
class VisitService implements VisitServiceInterface
{
/** @var EntityManagerInterface */
private $em;
private EntityManagerInterface $em;
public function __construct(EntityManagerInterface $em)
{

View file

@ -18,10 +18,8 @@ use Zend\Paginator\Paginator;
class VisitsTracker implements VisitsTrackerInterface
{
/** @var ORM\EntityManagerInterface */
private $em;
/** @var EventDispatcherInterface */
private $eventDispatcher;
private ORM\EntityManagerInterface $em;
private EventDispatcherInterface $eventDispatcher;
public function __construct(ORM\EntityManagerInterface $em, EventDispatcherInterface $eventDispatcher)
{

View file

@ -12,8 +12,7 @@ use function Functional\invoke_if;
class ShortUrlDataTransformer implements DataTransformerInterface
{
/** @var array */
private $domainConfig;
private array $domainConfig;
public function __construct(array $domainConfig)
{

View file

@ -14,8 +14,7 @@ class UrlValidator implements UrlValidatorInterface, RequestMethodInterface
{
private const MAX_REDIRECTS = 15;
/** @var ClientInterface */
private $httpClient;
private ClientInterface $httpClient;
public function __construct(ClientInterface $httpClient)
{

View file

@ -28,8 +28,7 @@ class ShortUrlRepositoryTest extends DatabaseTestCase
Domain::class,
];
/** @var ShortUrlRepository */
private $repo;
private ShortUrlRepository $repo;
public function setUp(): void
{

View file

@ -14,8 +14,7 @@ class TagRepositoryTest extends DatabaseTestCase
Tag::class,
];
/** @var TagRepository */
private $repo;
private TagRepository $repo;
protected function setUp(): void
{

View file

@ -26,8 +26,7 @@ class VisitRepositoryTest extends DatabaseTestCase
ShortUrl::class,
];
/** @var VisitRepository */
private $repo;
private VisitRepository $repo;
protected function setUp(): void
{

View file

@ -10,7 +10,6 @@ use Prophecy\Prophecy\ObjectProphecy;
use Psr\Http\Server\RequestHandlerInterface;
use Shlinkio\Shlink\Common\Response\PixelResponse;
use Shlinkio\Shlink\Core\Action\PixelAction;
use Shlinkio\Shlink\Core\Action\RedirectAction;
use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Options\AppOptions;
use Shlinkio\Shlink\Core\Service\UrlShortener;
@ -19,12 +18,9 @@ use Zend\Diactoros\ServerRequest;
class PixelActionTest extends TestCase
{
/** @var RedirectAction */
private $action;
/** @var ObjectProphecy */
private $urlShortener;
/** @var ObjectProphecy */
private $visitTracker;
private PixelAction $action;
private ObjectProphecy $urlShortener;
private ObjectProphecy $visitTracker;
public function setUp(): void
{

View file

@ -21,6 +21,7 @@ use function filesize;
use const FILEINFO_MIME;
/** @deprecated */
class PreviewActionTest extends TestCase
{
/** @var PreviewAction */

View file

@ -19,10 +19,8 @@ use Zend\Expressive\Router\RouterInterface;
class QrCodeActionTest extends TestCase
{
/** @var QrCodeAction */
private $action;
/** @var ObjectProphecy */
private $urlShortener;
private QrCodeAction $action;
private ObjectProphecy $urlShortener;
public function setUp(): void
{

View file

@ -21,12 +21,9 @@ use function array_key_exists;
class RedirectActionTest extends TestCase
{
/** @var RedirectAction */
private $action;
/** @var ObjectProphecy */
private $urlShortener;
/** @var ObjectProphecy */
private $visitTracker;
private RedirectAction $action;
private ObjectProphecy $urlShortener;
private ObjectProphecy $visitTracker;
public function setUp(): void
{

View file

@ -9,8 +9,7 @@ use Shlinkio\Shlink\Core\ConfigProvider;
class ConfigProviderTest extends TestCase
{
/** @var ConfigProvider */
private $configProvider;
private ConfigProvider $configProvider;
public function setUp(): void
{

View file

@ -11,10 +11,6 @@ use Shlinkio\Shlink\Core\Exception\IpCannotBeLocatedException;
use Shlinkio\Shlink\Core\Exception\RuntimeException;
use Throwable;
use function count;
use function func_get_args;
use function random_int;
class IpCannotBeLocatedExceptionTest extends TestCase
{
/** @test */
@ -59,39 +55,4 @@ class IpCannotBeLocatedExceptionTest extends TestCase
yield 'Runtime exception with negative code' => [new RuntimeException('Something went wrong', -50)];
yield 'Logic exception with default code' => [new LogicException('Conditions unmet')];
}
/**
* @test
* @dataProvider provideConstructorArgs
*/
public function constructorInitializesException(): void
{
$args = func_get_args();
[$isNonLocatableAddress, $message] = $args;
$code = $args[2] ?? 0;
$prev = $args[3] ?? null;
switch (count($args)) {
case 2:
$e = new IpCannotBeLocatedException($isNonLocatableAddress, $message);
break;
case 3:
$e = new IpCannotBeLocatedException($isNonLocatableAddress, $message, $code);
break;
default:
$e = new IpCannotBeLocatedException($isNonLocatableAddress, $message, $code, $prev);
}
$this->assertEquals($isNonLocatableAddress, $e->isNonLocatableAddress());
$this->assertEquals($message, $e->getMessage());
$this->assertEquals($code, $e->getCode());
$this->assertEquals($prev, $e->getPrevious());
}
public function provideConstructorArgs(): iterable
{
yield 'without default args' => [true, 'Message'];
yield 'without prev' => [true, 'Message', random_int(1, 100)];
yield 'without all args' => [false, 'Foo', random_int(1, 100), new RuntimeException('Foo')];
}
}

View file

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\Core\Service;
use Doctrine\ORM\EntityManager;
use Exception;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
@ -94,7 +95,9 @@ class VisitServiceTest extends TestCase
});
$this->visitService->locateUnlocatedVisits(function () use ($isNonLocatableAddress) {
throw new IpCannotBeLocatedException($isNonLocatableAddress, 'Cannot be located');
throw $isNonLocatableAddress
? new IpCannotBeLocatedException('Cannot be located')
: IpCannotBeLocatedException::forError(new Exception(''));
});
$findUnlocatedVisits->shouldHaveBeenCalledOnce();