mirror of
https://github.com/shlinkio/shlink.git
synced 2024-11-28 17:08:58 +03:00
Merge pull request #593 from acelaya-forks/feature/coding-standard-2.1
Feature/coding standard 2.1
This commit is contained in:
commit
18312b0624
113 changed files with 254 additions and 301 deletions
|
@ -13,7 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this
|
||||||
|
|
||||||
#### Changed
|
#### Changed
|
||||||
|
|
||||||
* *Nothing*
|
* [#592](https://github.com/shlinkio/shlink/issues/592) Updated coding styles to use [shlinkio/php-coding-standard](https://github.com/shlinkio/php-coding-standard) v2.1.0.
|
||||||
|
|
||||||
#### Deprecated
|
#### Deprecated
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
"phpstan/phpstan": "^0.12.3",
|
"phpstan/phpstan": "^0.12.3",
|
||||||
"phpunit/phpunit": "^8.3",
|
"phpunit/phpunit": "^8.3",
|
||||||
"roave/security-advisories": "dev-master",
|
"roave/security-advisories": "dev-master",
|
||||||
"shlinkio/php-coding-standard": "~2.0.0",
|
"shlinkio/php-coding-standard": "~2.1.0",
|
||||||
"shlinkio/shlink-test-utils": "^1.2",
|
"shlinkio/shlink-test-utils": "^1.2",
|
||||||
"symfony/var-dumper": "^5.0"
|
"symfony/var-dumper": "^5.0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -17,7 +17,6 @@ final class Version20180801183328 extends AbstractMigration
|
||||||
private const OLD_SIZE = 10;
|
private const OLD_SIZE = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Schema $schema
|
|
||||||
* @throws SchemaException
|
* @throws SchemaException
|
||||||
*/
|
*/
|
||||||
public function up(Schema $schema): void
|
public function up(Schema $schema): void
|
||||||
|
@ -26,7 +25,6 @@ final class Version20180801183328 extends AbstractMigration
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Schema $schema
|
|
||||||
* @throws SchemaException
|
* @throws SchemaException
|
||||||
*/
|
*/
|
||||||
public function down(Schema $schema): void
|
public function down(Schema $schema): void
|
||||||
|
@ -35,8 +33,6 @@ final class Version20180801183328 extends AbstractMigration
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Schema $schema
|
|
||||||
* @param int $size
|
|
||||||
* @throws SchemaException
|
* @throws SchemaException
|
||||||
*/
|
*/
|
||||||
private function setSize(Schema $schema, int $size): void
|
private function setSize(Schema $schema, int $size): void
|
||||||
|
|
|
@ -17,7 +17,6 @@ use Shlinkio\Shlink\Common\Util\IpAddress;
|
||||||
final class Version20180913205455 extends AbstractMigration
|
final class Version20180913205455 extends AbstractMigration
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param Schema $schema
|
|
||||||
*/
|
*/
|
||||||
public function up(Schema $schema): void
|
public function up(Schema $schema): void
|
||||||
{
|
{
|
||||||
|
@ -25,7 +24,6 @@ final class Version20180913205455 extends AbstractMigration
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Schema $schema
|
|
||||||
* @throws DBALException
|
* @throws DBALException
|
||||||
*/
|
*/
|
||||||
public function postUp(Schema $schema): void
|
public function postUp(Schema $schema): void
|
||||||
|
@ -67,7 +65,6 @@ final class Version20180913205455 extends AbstractMigration
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Schema $schema
|
|
||||||
*/
|
*/
|
||||||
public function down(Schema $schema): void
|
public function down(Schema $schema): void
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,7 +19,6 @@ final class Version20180915110857 extends AbstractMigration
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Schema $schema
|
|
||||||
* @throws SchemaException
|
* @throws SchemaException
|
||||||
*/
|
*/
|
||||||
public function up(Schema $schema): void
|
public function up(Schema $schema): void
|
||||||
|
@ -39,7 +38,7 @@ final class Version20180915110857 extends AbstractMigration
|
||||||
[
|
[
|
||||||
'onDelete' => self::ON_DELETE_MAP[$foreignTable],
|
'onDelete' => self::ON_DELETE_MAP[$foreignTable],
|
||||||
'onUpdate' => 'RESTRICT',
|
'onUpdate' => 'RESTRICT',
|
||||||
]
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ final class Version20181020060559 extends AbstractMigration
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Schema $schema
|
|
||||||
* @throws SchemaException
|
* @throws SchemaException
|
||||||
*/
|
*/
|
||||||
public function up(Schema $schema): void
|
public function up(Schema $schema): void
|
||||||
|
|
|
@ -36,7 +36,7 @@ class GenerateKeyCommand extends Command
|
||||||
'expirationDate',
|
'expirationDate',
|
||||||
'e',
|
'e',
|
||||||
InputOption::VALUE_REQUIRED,
|
InputOption::VALUE_REQUIRED,
|
||||||
'The date in which the API key should expire. Use any valid PHP format.'
|
'The date in which the API key should expire. Use any valid PHP format.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ class ListKeysCommand extends Command
|
||||||
'enabledOnly',
|
'enabledOnly',
|
||||||
'e',
|
'e',
|
||||||
InputOption::VALUE_NONE,
|
InputOption::VALUE_NONE,
|
||||||
'Tells if only enabled API keys should be returned.'
|
'Tells if only enabled API keys should be returned.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,8 +81,6 @@ class ListKeysCommand extends Command
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ApiKey $apiKey
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
private function getEnabledSymbol(ApiKey $apiKey): string
|
private function getEnabledSymbol(ApiKey $apiKey): string
|
||||||
{
|
{
|
||||||
|
|
|
@ -41,7 +41,7 @@ class CreateDatabaseCommand extends AbstractDatabaseCommand
|
||||||
$this
|
$this
|
||||||
->setName(self::NAME)
|
->setName(self::NAME)
|
||||||
->setDescription(
|
->setDescription(
|
||||||
'Creates the database needed for shlink to work. It will do nothing if the database already exists'
|
'Creates the database needed for shlink to work. It will do nothing if the database already exists',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ class DeleteShortUrlCommand extends Command
|
||||||
'i',
|
'i',
|
||||||
InputOption::VALUE_NONE,
|
InputOption::VALUE_NONE,
|
||||||
'Ignores the safety visits threshold check, which could make short URLs with many visits to be '
|
'Ignores the safety visits threshold check, which could make short URLs with many visits to be '
|
||||||
. 'accidentally deleted'
|
. 'accidentally deleted',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,45 +47,45 @@ class GenerateShortUrlCommand extends Command
|
||||||
'tags',
|
'tags',
|
||||||
't',
|
't',
|
||||||
InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED,
|
InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED,
|
||||||
'Tags to apply to the new short URL'
|
'Tags to apply to the new short URL',
|
||||||
)
|
)
|
||||||
->addOption(
|
->addOption(
|
||||||
'validSince',
|
'validSince',
|
||||||
's',
|
's',
|
||||||
InputOption::VALUE_REQUIRED,
|
InputOption::VALUE_REQUIRED,
|
||||||
'The date from which this short URL will be valid. '
|
'The date from which this short URL will be valid. '
|
||||||
. 'If someone tries to access it before this date, it will not be found.'
|
. 'If someone tries to access it before this date, it will not be found.',
|
||||||
)
|
)
|
||||||
->addOption(
|
->addOption(
|
||||||
'validUntil',
|
'validUntil',
|
||||||
'u',
|
'u',
|
||||||
InputOption::VALUE_REQUIRED,
|
InputOption::VALUE_REQUIRED,
|
||||||
'The date until which this short URL will be valid. '
|
'The date until which this short URL will be valid. '
|
||||||
. 'If someone tries to access it after this date, it will not be found.'
|
. 'If someone tries to access it after this date, it will not be found.',
|
||||||
)
|
)
|
||||||
->addOption(
|
->addOption(
|
||||||
'customSlug',
|
'customSlug',
|
||||||
'c',
|
'c',
|
||||||
InputOption::VALUE_REQUIRED,
|
InputOption::VALUE_REQUIRED,
|
||||||
'If provided, this slug will be used instead of generating a short code'
|
'If provided, this slug will be used instead of generating a short code',
|
||||||
)
|
)
|
||||||
->addOption(
|
->addOption(
|
||||||
'maxVisits',
|
'maxVisits',
|
||||||
'm',
|
'm',
|
||||||
InputOption::VALUE_REQUIRED,
|
InputOption::VALUE_REQUIRED,
|
||||||
'This will limit the number of visits for this short URL.'
|
'This will limit the number of visits for this short URL.',
|
||||||
)
|
)
|
||||||
->addOption(
|
->addOption(
|
||||||
'findIfExists',
|
'findIfExists',
|
||||||
'f',
|
'f',
|
||||||
InputOption::VALUE_NONE,
|
InputOption::VALUE_NONE,
|
||||||
'This will force existing matching URL to be returned if found, instead of creating a new one.'
|
'This will force existing matching URL to be returned if found, instead of creating a new one.',
|
||||||
)
|
)
|
||||||
->addOption(
|
->addOption(
|
||||||
'domain',
|
'domain',
|
||||||
'd',
|
'd',
|
||||||
InputOption::VALUE_REQUIRED,
|
InputOption::VALUE_REQUIRED,
|
||||||
'The domain to which this short URL will be attached.'
|
'The domain to which this short URL will be attached.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,8 +127,8 @@ class GenerateShortUrlCommand extends Command
|
||||||
$customSlug,
|
$customSlug,
|
||||||
$maxVisits !== null ? (int) $maxVisits : null,
|
$maxVisits !== null ? (int) $maxVisits : null,
|
||||||
$input->getOption('findIfExists'),
|
$input->getOption('findIfExists'),
|
||||||
$input->getOption('domain')
|
$input->getOption('domain'),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
$io->writeln([
|
$io->writeln([
|
||||||
|
|
|
@ -61,25 +61,25 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand
|
||||||
'p',
|
'p',
|
||||||
InputOption::VALUE_REQUIRED,
|
InputOption::VALUE_REQUIRED,
|
||||||
sprintf('The first page to list (%s items per page)', ShortUrlRepositoryAdapter::ITEMS_PER_PAGE),
|
sprintf('The first page to list (%s items per page)', ShortUrlRepositoryAdapter::ITEMS_PER_PAGE),
|
||||||
'1'
|
'1',
|
||||||
)
|
)
|
||||||
->addOption(
|
->addOption(
|
||||||
'searchTerm',
|
'searchTerm',
|
||||||
'st',
|
'st',
|
||||||
InputOption::VALUE_REQUIRED,
|
InputOption::VALUE_REQUIRED,
|
||||||
'A query used to filter results by searching for it on the longUrl and shortCode fields'
|
'A query used to filter results by searching for it on the longUrl and shortCode fields',
|
||||||
)
|
)
|
||||||
->addOption(
|
->addOption(
|
||||||
'tags',
|
'tags',
|
||||||
't',
|
't',
|
||||||
InputOption::VALUE_REQUIRED,
|
InputOption::VALUE_REQUIRED,
|
||||||
'A comma-separated list of tags to filter results'
|
'A comma-separated list of tags to filter results',
|
||||||
)
|
)
|
||||||
->addOption(
|
->addOption(
|
||||||
'orderBy',
|
'orderBy',
|
||||||
'o',
|
'o',
|
||||||
InputOption::VALUE_REQUIRED,
|
InputOption::VALUE_REQUIRED,
|
||||||
'The field from which we want to order by. Pass ASC or DESC separated by a comma'
|
'The field from which we want to order by. Pass ASC or DESC separated by a comma',
|
||||||
)
|
)
|
||||||
->addOption('showTags', null, InputOption::VALUE_NONE, 'Whether to display the tags or not');
|
->addOption('showTags', null, InputOption::VALUE_NONE, 'Whether to display the tags or not');
|
||||||
}
|
}
|
||||||
|
@ -122,6 +122,9 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand
|
||||||
return ExitCodes::EXIT_SUCCESS;
|
return ExitCodes::EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|array|null $orderBy
|
||||||
|
*/
|
||||||
private function renderPage(
|
private function renderPage(
|
||||||
OutputInterface $output,
|
OutputInterface $output,
|
||||||
int $page,
|
int $page,
|
||||||
|
@ -137,7 +140,7 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand
|
||||||
$searchTerm,
|
$searchTerm,
|
||||||
$tags,
|
$tags,
|
||||||
$orderBy,
|
$orderBy,
|
||||||
new DateRange($startDate, $endDate)
|
new DateRange($startDate, $endDate),
|
||||||
);
|
);
|
||||||
|
|
||||||
$headers = ['Short code', 'Short URL', 'Long URL', 'Date created', 'Visits count'];
|
$headers = ['Short code', 'Short URL', 'Long URL', 'Date created', 'Visits count'];
|
||||||
|
@ -159,7 +162,7 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand
|
||||||
|
|
||||||
ShlinkTable::fromOutput($output)->render($headers, $rows, $this->formatCurrentPageMessage(
|
ShlinkTable::fromOutput($output)->render($headers, $rows, $this->formatCurrentPageMessage(
|
||||||
$result,
|
$result,
|
||||||
'Page %s of %s'
|
'Page %s of %s',
|
||||||
));
|
));
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
|
|
|
@ -33,7 +33,7 @@ class CreateTagCommand extends Command
|
||||||
'name',
|
'name',
|
||||||
't',
|
't',
|
||||||
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
|
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
|
||||||
'The name of the tags to create'
|
'The name of the tags to create',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ class DeleteTagsCommand extends Command
|
||||||
'name',
|
'name',
|
||||||
't',
|
't',
|
||||||
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
|
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
|
||||||
'The name of the tags to delete'
|
'The name of the tags to delete',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ abstract class AbstractLockedCommand extends Command
|
||||||
|
|
||||||
if (! $lock->acquire($lockConfig->isBlocking())) {
|
if (! $lock->acquire($lockConfig->isBlocking())) {
|
||||||
$output->writeln(
|
$output->writeln(
|
||||||
sprintf('<comment>Command "%s" is already in progress. Skipping.</comment>', $lockConfig->lockName())
|
sprintf('<comment>Command "%s" is already in progress. Skipping.</comment>', $lockConfig->lockName()),
|
||||||
);
|
);
|
||||||
return ExitCodes::EXIT_WARNING;
|
return ExitCodes::EXIT_WARNING;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ abstract class AbstractWithDateRangeCommand extends Command
|
||||||
$output->writeln(sprintf(
|
$output->writeln(sprintf(
|
||||||
'<comment>> Ignored provided "%s" since its value "%s" is not a valid date. <</comment>',
|
'<comment>> Ignored provided "%s" since its value "%s" is not a valid date. <</comment>',
|
||||||
$key,
|
$key,
|
||||||
$value
|
$value,
|
||||||
));
|
));
|
||||||
|
|
||||||
if ($output->isVeryVerbose()) {
|
if ($output->isVeryVerbose()) {
|
||||||
|
|
|
@ -66,13 +66,13 @@ class LocateVisitsCommand extends AbstractLockedCommand
|
||||||
|
|
||||||
$this->visitService->locateUnlocatedVisits(
|
$this->visitService->locateUnlocatedVisits(
|
||||||
[$this, 'getGeolocationDataForVisit'],
|
[$this, 'getGeolocationDataForVisit'],
|
||||||
static function (VisitLocation $location) use ($output) {
|
static function (VisitLocation $location) use ($output): void {
|
||||||
if (!$location->isEmpty()) {
|
if (!$location->isEmpty()) {
|
||||||
$output->writeln(
|
$output->writeln(
|
||||||
sprintf(' [<info>Address located at "%s"</info>]', $location->getCountryName())
|
sprintf(' [<info>Address located at "%s"</info>]', $location->getCountryName()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->io->success('Finished processing all IPs');
|
$this->io->success('Finished processing all IPs');
|
||||||
|
@ -92,7 +92,7 @@ class LocateVisitsCommand extends AbstractLockedCommand
|
||||||
if (! $visit->hasRemoteAddr()) {
|
if (! $visit->hasRemoteAddr()) {
|
||||||
$this->io->writeln(
|
$this->io->writeln(
|
||||||
'<comment>Ignored visit with no IP address</comment>',
|
'<comment>Ignored visit with no IP address</comment>',
|
||||||
OutputInterface::VERBOSITY_VERBOSE
|
OutputInterface::VERBOSITY_VERBOSE,
|
||||||
);
|
);
|
||||||
throw IpCannotBeLocatedException::forEmptyAddress();
|
throw IpCannotBeLocatedException::forEmptyAddress();
|
||||||
}
|
}
|
||||||
|
@ -119,12 +119,12 @@ class LocateVisitsCommand extends AbstractLockedCommand
|
||||||
private function checkDbUpdate(): void
|
private function checkDbUpdate(): void
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$this->dbUpdater->checkDbUpdate(function (bool $olderDbExists) {
|
$this->dbUpdater->checkDbUpdate(function (bool $olderDbExists): void {
|
||||||
$this->io->writeln(
|
$this->io->writeln(
|
||||||
sprintf('<fg=blue>%s GeoLite2 database...</>', $olderDbExists ? 'Updating' : 'Downloading')
|
sprintf('<fg=blue>%s GeoLite2 database...</>', $olderDbExists ? 'Updating' : 'Downloading'),
|
||||||
);
|
);
|
||||||
$this->progressBar = new ProgressBar($this->io);
|
$this->progressBar = new ProgressBar($this->io);
|
||||||
}, function (int $total, int $downloaded) {
|
}, function (int $total, int $downloaded): void {
|
||||||
$this->progressBar->setMaxSteps($total);
|
$this->progressBar->setMaxSteps($total);
|
||||||
$this->progressBar->setProgress($downloaded);
|
$this->progressBar->setProgress($downloaded);
|
||||||
});
|
});
|
||||||
|
@ -141,7 +141,7 @@ class LocateVisitsCommand extends AbstractLockedCommand
|
||||||
|
|
||||||
$this->io->newLine();
|
$this->io->newLine();
|
||||||
$this->io->writeln(
|
$this->io->writeln(
|
||||||
'<fg=yellow;options=bold>[Warning] GeoLite2 database update failed. Proceeding with old version.</>'
|
'<fg=yellow;options=bold>[Warning] GeoLite2 database update failed. Proceeding with old version.</>',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use function Shlinkio\Shlink\Common\loadConfigFromGlob;
|
||||||
|
|
||||||
class ConfigProvider
|
class ConfigProvider
|
||||||
{
|
{
|
||||||
public function __invoke()
|
public function __invoke(): array
|
||||||
{
|
{
|
||||||
return loadConfigFromGlob(__DIR__ . '/../config/{,*.}config.php');
|
return loadConfigFromGlob(__DIR__ . '/../config/{,*.}config.php');
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ class GeolocationDbUpdateFailedException extends RuntimeException implements Exc
|
||||||
$e = new self(
|
$e = new self(
|
||||||
'An error occurred while updating geolocation database, and an older version could not be found',
|
'An error occurred while updating geolocation database, and an older version could not be found',
|
||||||
0,
|
0,
|
||||||
$prev
|
$prev,
|
||||||
);
|
);
|
||||||
$e->olderDbExists = $olderDbExists;
|
$e->olderDbExists = $olderDbExists;
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ class GenerateKeyCommandTest extends TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function noExpirationDateIsDefinedIfNotProvided()
|
public function noExpirationDateIsDefinedIfNotProvided(): void
|
||||||
{
|
{
|
||||||
$create = $this->apiKeyService->create(null)->willReturn(new ApiKey());
|
$create = $this->apiKeyService->create(null)->willReturn(new ApiKey());
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ class GenerateKeyCommandTest extends TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function expirationDateIsDefinedIfProvided()
|
public function expirationDateIsDefinedIfProvided(): void
|
||||||
{
|
{
|
||||||
$this->apiKeyService->create(Argument::type(Chronos::class))->shouldBeCalledOnce()
|
$this->apiKeyService->create(Argument::type(Chronos::class))->shouldBeCalledOnce()
|
||||||
->willReturn(new ApiKey());
|
->willReturn(new ApiKey());
|
||||||
|
|
|
@ -33,7 +33,7 @@ class CreateDatabaseCommandTest extends TestCase
|
||||||
$locker = $this->prophesize(LockFactory::class);
|
$locker = $this->prophesize(LockFactory::class);
|
||||||
$lock = $this->prophesize(LockInterface::class);
|
$lock = $this->prophesize(LockInterface::class);
|
||||||
$lock->acquire(Argument::any())->willReturn(true);
|
$lock->acquire(Argument::any())->willReturn(true);
|
||||||
$lock->release()->will(function () {
|
$lock->release()->will(function (): void {
|
||||||
});
|
});
|
||||||
$locker->createLock(Argument::cetera())->willReturn($lock->reveal());
|
$locker->createLock(Argument::cetera())->willReturn($lock->reveal());
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ class CreateDatabaseCommandTest extends TestCase
|
||||||
$this->processHelper->reveal(),
|
$this->processHelper->reveal(),
|
||||||
$phpExecutableFinder->reveal(),
|
$phpExecutableFinder->reveal(),
|
||||||
$this->regularConn->reveal(),
|
$this->regularConn->reveal(),
|
||||||
$this->noDbNameConn->reveal()
|
$this->noDbNameConn->reveal(),
|
||||||
);
|
);
|
||||||
$app = new Application();
|
$app = new Application();
|
||||||
$app->add($command);
|
$app->add($command);
|
||||||
|
@ -69,7 +69,7 @@ class CreateDatabaseCommandTest extends TestCase
|
||||||
$shlinkDatabase = 'shlink_database';
|
$shlinkDatabase = 'shlink_database';
|
||||||
$getDatabase = $this->regularConn->getDatabase()->willReturn($shlinkDatabase);
|
$getDatabase = $this->regularConn->getDatabase()->willReturn($shlinkDatabase);
|
||||||
$listDatabases = $this->schemaManager->listDatabases()->willReturn(['foo', $shlinkDatabase, 'bar']);
|
$listDatabases = $this->schemaManager->listDatabases()->willReturn(['foo', $shlinkDatabase, 'bar']);
|
||||||
$createDatabase = $this->schemaManager->createDatabase($shlinkDatabase)->will(function () {
|
$createDatabase = $this->schemaManager->createDatabase($shlinkDatabase)->will(function (): void {
|
||||||
});
|
});
|
||||||
$listTables = $this->schemaManager->listTableNames()->willReturn(['foo_table', 'bar_table']);
|
$listTables = $this->schemaManager->listTableNames()->willReturn(['foo_table', 'bar_table']);
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ class CreateDatabaseCommandTest extends TestCase
|
||||||
$shlinkDatabase = 'shlink_database';
|
$shlinkDatabase = 'shlink_database';
|
||||||
$getDatabase = $this->regularConn->getDatabase()->willReturn($shlinkDatabase);
|
$getDatabase = $this->regularConn->getDatabase()->willReturn($shlinkDatabase);
|
||||||
$listDatabases = $this->schemaManager->listDatabases()->willReturn(['foo', 'bar']);
|
$listDatabases = $this->schemaManager->listDatabases()->willReturn(['foo', 'bar']);
|
||||||
$createDatabase = $this->schemaManager->createDatabase($shlinkDatabase)->will(function () {
|
$createDatabase = $this->schemaManager->createDatabase($shlinkDatabase)->will(function (): void {
|
||||||
});
|
});
|
||||||
$listTables = $this->schemaManager->listTableNames()->willReturn(['foo_table', 'bar_table']);
|
$listTables = $this->schemaManager->listTableNames()->willReturn(['foo_table', 'bar_table']);
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ class CreateDatabaseCommandTest extends TestCase
|
||||||
$shlinkDatabase = 'shlink_database';
|
$shlinkDatabase = 'shlink_database';
|
||||||
$getDatabase = $this->regularConn->getDatabase()->willReturn($shlinkDatabase);
|
$getDatabase = $this->regularConn->getDatabase()->willReturn($shlinkDatabase);
|
||||||
$listDatabases = $this->schemaManager->listDatabases()->willReturn(['foo', $shlinkDatabase, 'bar']);
|
$listDatabases = $this->schemaManager->listDatabases()->willReturn(['foo', $shlinkDatabase, 'bar']);
|
||||||
$createDatabase = $this->schemaManager->createDatabase($shlinkDatabase)->will(function () {
|
$createDatabase = $this->schemaManager->createDatabase($shlinkDatabase)->will(function (): void {
|
||||||
});
|
});
|
||||||
$listTables = $this->schemaManager->listTableNames()->willReturn([]);
|
$listTables = $this->schemaManager->listTableNames()->willReturn([]);
|
||||||
$runCommand = $this->processHelper->mustRun(Argument::type(OutputInterface::class), [
|
$runCommand = $this->processHelper->mustRun(Argument::type(OutputInterface::class), [
|
||||||
|
@ -136,7 +136,7 @@ class CreateDatabaseCommandTest extends TestCase
|
||||||
$shlinkDatabase = 'shlink_database';
|
$shlinkDatabase = 'shlink_database';
|
||||||
$getDatabase = $this->regularConn->getDatabase()->willReturn($shlinkDatabase);
|
$getDatabase = $this->regularConn->getDatabase()->willReturn($shlinkDatabase);
|
||||||
$listDatabases = $this->schemaManager->listDatabases()->willReturn(['foo', 'bar']);
|
$listDatabases = $this->schemaManager->listDatabases()->willReturn(['foo', 'bar']);
|
||||||
$createDatabase = $this->schemaManager->createDatabase($shlinkDatabase)->will(function () {
|
$createDatabase = $this->schemaManager->createDatabase($shlinkDatabase)->will(function (): void {
|
||||||
});
|
});
|
||||||
$listTables = $this->schemaManager->listTableNames()->willReturn(['foo_table', 'bar_table']);
|
$listTables = $this->schemaManager->listTableNames()->willReturn(['foo_table', 'bar_table']);
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ class MigrateDatabaseCommandTest extends TestCase
|
||||||
$locker = $this->prophesize(LockFactory::class);
|
$locker = $this->prophesize(LockFactory::class);
|
||||||
$lock = $this->prophesize(LockInterface::class);
|
$lock = $this->prophesize(LockInterface::class);
|
||||||
$lock->acquire(Argument::any())->willReturn(true);
|
$lock->acquire(Argument::any())->willReturn(true);
|
||||||
$lock->release()->will(function () {
|
$lock->release()->will(function (): void {
|
||||||
});
|
});
|
||||||
$locker->createLock(Argument::cetera())->willReturn($lock->reveal());
|
$locker->createLock(Argument::cetera())->willReturn($lock->reveal());
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ class MigrateDatabaseCommandTest extends TestCase
|
||||||
$command = new MigrateDatabaseCommand(
|
$command = new MigrateDatabaseCommand(
|
||||||
$locker->reveal(),
|
$locker->reveal(),
|
||||||
$this->processHelper->reveal(),
|
$this->processHelper->reveal(),
|
||||||
$phpExecutableFinder->reveal()
|
$phpExecutableFinder->reveal(),
|
||||||
);
|
);
|
||||||
$app = new Application();
|
$app = new Application();
|
||||||
$app->add($command);
|
$app->add($command);
|
||||||
|
|
|
@ -38,7 +38,7 @@ class DeleteShortUrlCommandTest extends TestCase
|
||||||
public function successMessageIsPrintedIfUrlIsProperlyDeleted(): void
|
public function successMessageIsPrintedIfUrlIsProperlyDeleted(): void
|
||||||
{
|
{
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$deleteByShortCode = $this->service->deleteByShortCode($shortCode, false)->will(function () {
|
$deleteByShortCode = $this->service->deleteByShortCode($shortCode, false)->will(function (): void {
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->commandTester->execute(['shortCode' => $shortCode]);
|
$this->commandTester->execute(['shortCode' => $shortCode]);
|
||||||
|
@ -46,7 +46,7 @@ class DeleteShortUrlCommandTest extends TestCase
|
||||||
|
|
||||||
$this->assertStringContainsString(
|
$this->assertStringContainsString(
|
||||||
sprintf('Short URL with short code "%s" successfully deleted.', $shortCode),
|
sprintf('Short URL with short code "%s" successfully deleted.', $shortCode),
|
||||||
$output
|
$output,
|
||||||
);
|
);
|
||||||
$deleteByShortCode->shouldHaveBeenCalledOnce();
|
$deleteByShortCode->shouldHaveBeenCalledOnce();
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ class DeleteShortUrlCommandTest extends TestCase
|
||||||
{
|
{
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$deleteByShortCode = $this->service->deleteByShortCode($shortCode, false)->willThrow(
|
$deleteByShortCode = $this->service->deleteByShortCode($shortCode, false)->willThrow(
|
||||||
Exception\ShortUrlNotFoundException::fromNotFoundShortCode($shortCode)
|
Exception\ShortUrlNotFoundException::fromNotFoundShortCode($shortCode),
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->commandTester->execute(['shortCode' => $shortCode]);
|
$this->commandTester->execute(['shortCode' => $shortCode]);
|
||||||
|
@ -77,13 +77,13 @@ class DeleteShortUrlCommandTest extends TestCase
|
||||||
): void {
|
): void {
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$deleteByShortCode = $this->service->deleteByShortCode($shortCode, Argument::type('bool'))->will(
|
$deleteByShortCode = $this->service->deleteByShortCode($shortCode, Argument::type('bool'))->will(
|
||||||
function (array $args) use ($shortCode) {
|
function (array $args) use ($shortCode): void {
|
||||||
$ignoreThreshold = array_pop($args);
|
$ignoreThreshold = array_pop($args);
|
||||||
|
|
||||||
if (!$ignoreThreshold) {
|
if (!$ignoreThreshold) {
|
||||||
throw Exception\DeleteShortUrlException::fromVisitsThreshold(10, $shortCode);
|
throw Exception\DeleteShortUrlException::fromVisitsThreshold(10, $shortCode);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
$this->commandTester->setInputs($retryAnswer);
|
$this->commandTester->setInputs($retryAnswer);
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ class DeleteShortUrlCommandTest extends TestCase
|
||||||
|
|
||||||
$this->assertStringContainsString(sprintf(
|
$this->assertStringContainsString(sprintf(
|
||||||
'Impossible to delete short URL with short code "%s" since it has more than "10" visits.',
|
'Impossible to delete short URL with short code "%s" since it has more than "10" visits.',
|
||||||
$shortCode
|
$shortCode,
|
||||||
), $output);
|
), $output);
|
||||||
$this->assertStringContainsString($expectedMessage, $output);
|
$this->assertStringContainsString($expectedMessage, $output);
|
||||||
$deleteByShortCode->shouldHaveBeenCalledTimes($expectedDeleteCalls);
|
$deleteByShortCode->shouldHaveBeenCalledTimes($expectedDeleteCalls);
|
||||||
|
@ -110,7 +110,7 @@ class DeleteShortUrlCommandTest extends TestCase
|
||||||
{
|
{
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$deleteByShortCode = $this->service->deleteByShortCode($shortCode, false)->willThrow(
|
$deleteByShortCode = $this->service->deleteByShortCode($shortCode, false)->willThrow(
|
||||||
Exception\DeleteShortUrlException::fromVisitsThreshold(10, $shortCode)
|
Exception\DeleteShortUrlException::fromVisitsThreshold(10, $shortCode),
|
||||||
);
|
);
|
||||||
$this->commandTester->setInputs(['no']);
|
$this->commandTester->setInputs(['no']);
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ class DeleteShortUrlCommandTest extends TestCase
|
||||||
|
|
||||||
$this->assertStringContainsString(sprintf(
|
$this->assertStringContainsString(sprintf(
|
||||||
'Impossible to delete short URL with short code "%s" since it has more than "10" visits.',
|
'Impossible to delete short URL with short code "%s" since it has more than "10" visits.',
|
||||||
$shortCode
|
$shortCode,
|
||||||
), $output);
|
), $output);
|
||||||
$this->assertStringContainsString('Short URL was not deleted.', $output);
|
$this->assertStringContainsString('Short URL was not deleted.', $output);
|
||||||
$deleteByShortCode->shouldHaveBeenCalledOnce();
|
$deleteByShortCode->shouldHaveBeenCalledOnce();
|
||||||
|
|
|
@ -72,7 +72,7 @@ class GenerateShortUrlCommandTest extends TestCase
|
||||||
public function providingNonUniqueSlugOutputsError(): void
|
public function providingNonUniqueSlugOutputsError(): void
|
||||||
{
|
{
|
||||||
$urlToShortCode = $this->urlShortener->urlToShortCode(Argument::cetera())->willThrow(
|
$urlToShortCode = $this->urlShortener->urlToShortCode(Argument::cetera())->willThrow(
|
||||||
NonUniqueSlugException::fromSlug('my-slug')
|
NonUniqueSlugException::fromSlug('my-slug'),
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->commandTester->execute(['longUrl' => 'http://domain.com/invalid', '--customSlug' => 'my-slug']);
|
$this->commandTester->execute(['longUrl' => 'http://domain.com/invalid', '--customSlug' => 'my-slug']);
|
||||||
|
@ -93,7 +93,7 @@ class GenerateShortUrlCommandTest extends TestCase
|
||||||
Assert::assertEquals(['foo', 'bar', 'baz', 'boo', 'zar'], $tags);
|
Assert::assertEquals(['foo', 'bar', 'baz', 'boo', 'zar'], $tags);
|
||||||
return $tags;
|
return $tags;
|
||||||
}),
|
}),
|
||||||
Argument::cetera()
|
Argument::cetera(),
|
||||||
)->willReturn($shortUrl);
|
)->willReturn($shortUrl);
|
||||||
|
|
||||||
$this->commandTester->execute([
|
$this->commandTester->execute([
|
||||||
|
|
|
@ -43,7 +43,7 @@ class GetVisitsCommandTest extends TestCase
|
||||||
{
|
{
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$this->visitsTracker->info($shortCode, new VisitsParams(new DateRange(null, null)))->willReturn(
|
$this->visitsTracker->info($shortCode, new VisitsParams(new DateRange(null, null)))->willReturn(
|
||||||
new Paginator(new ArrayAdapter([]))
|
new Paginator(new ArrayAdapter([])),
|
||||||
)->shouldBeCalledOnce();
|
)->shouldBeCalledOnce();
|
||||||
|
|
||||||
$this->commandTester->execute(['shortCode' => $shortCode]);
|
$this->commandTester->execute(['shortCode' => $shortCode]);
|
||||||
|
@ -57,7 +57,7 @@ class GetVisitsCommandTest extends TestCase
|
||||||
$endDate = '2016-02-01';
|
$endDate = '2016-02-01';
|
||||||
$this->visitsTracker->info(
|
$this->visitsTracker->info(
|
||||||
$shortCode,
|
$shortCode,
|
||||||
new VisitsParams(new DateRange(Chronos::parse($startDate), Chronos::parse($endDate)))
|
new VisitsParams(new DateRange(Chronos::parse($startDate), Chronos::parse($endDate))),
|
||||||
)
|
)
|
||||||
->willReturn(new Paginator(new ArrayAdapter([])))
|
->willReturn(new Paginator(new ArrayAdapter([])))
|
||||||
->shouldBeCalledOnce();
|
->shouldBeCalledOnce();
|
||||||
|
@ -86,7 +86,7 @@ class GetVisitsCommandTest extends TestCase
|
||||||
$info->shouldHaveBeenCalledOnce();
|
$info->shouldHaveBeenCalledOnce();
|
||||||
$this->assertStringContainsString(
|
$this->assertStringContainsString(
|
||||||
sprintf('Ignored provided "startDate" since its value "%s" is not a valid date', $startDate),
|
sprintf('Ignored provided "startDate" since its value "%s" is not a valid date', $startDate),
|
||||||
$output
|
$output,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,9 +97,9 @@ class GetVisitsCommandTest extends TestCase
|
||||||
$this->visitsTracker->info($shortCode, Argument::any())->willReturn(
|
$this->visitsTracker->info($shortCode, Argument::any())->willReturn(
|
||||||
new Paginator(new ArrayAdapter([
|
new Paginator(new ArrayAdapter([
|
||||||
(new Visit(new ShortUrl(''), new Visitor('bar', 'foo', '')))->locate(
|
(new Visit(new ShortUrl(''), new Visitor('bar', 'foo', '')))->locate(
|
||||||
new VisitLocation(new Location('', 'Spain', '', '', 0, 0, ''))
|
new VisitLocation(new Location('', 'Spain', '', '', 0, 0, '')),
|
||||||
),
|
),
|
||||||
]))
|
])),
|
||||||
)->shouldBeCalledOnce();
|
)->shouldBeCalledOnce();
|
||||||
|
|
||||||
$this->commandTester->execute(['shortCode' => $shortCode]);
|
$this->commandTester->execute(['shortCode' => $shortCode]);
|
||||||
|
|
|
@ -162,6 +162,7 @@ class ListShortUrlsCommandTest extends TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param string|array|null $expectedOrderBy
|
||||||
* @test
|
* @test
|
||||||
* @dataProvider provideOrderBy
|
* @dataProvider provideOrderBy
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -40,7 +40,7 @@ class DeleteTagsCommandTest extends TestCase
|
||||||
public function serviceIsInvokedOnSuccess(): void
|
public function serviceIsInvokedOnSuccess(): void
|
||||||
{
|
{
|
||||||
$tagNames = ['foo', 'bar'];
|
$tagNames = ['foo', 'bar'];
|
||||||
$deleteTags = $this->tagService->deleteTags($tagNames)->will(function () {
|
$deleteTags = $this->tagService->deleteTags($tagNames)->will(function (): void {
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->commandTester->execute([
|
$this->commandTester->execute([
|
||||||
|
|
|
@ -45,7 +45,7 @@ class LocateVisitsCommandTest extends TestCase
|
||||||
$this->locker = $this->prophesize(Lock\LockFactory::class);
|
$this->locker = $this->prophesize(Lock\LockFactory::class);
|
||||||
$this->lock = $this->prophesize(Lock\LockInterface::class);
|
$this->lock = $this->prophesize(Lock\LockInterface::class);
|
||||||
$this->lock->acquire(false)->willReturn(true);
|
$this->lock->acquire(false)->willReturn(true);
|
||||||
$this->lock->release()->will(function () {
|
$this->lock->release()->will(function (): void {
|
||||||
});
|
});
|
||||||
$this->locker->createLock(Argument::type('string'), 90.0, false)->willReturn($this->lock->reveal());
|
$this->locker->createLock(Argument::type('string'), 90.0, false)->willReturn($this->lock->reveal());
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ class LocateVisitsCommandTest extends TestCase
|
||||||
$this->visitService->reveal(),
|
$this->visitService->reveal(),
|
||||||
$this->ipResolver->reveal(),
|
$this->ipResolver->reveal(),
|
||||||
$this->locker->reveal(),
|
$this->locker->reveal(),
|
||||||
$this->dbUpdater->reveal()
|
$this->dbUpdater->reveal(),
|
||||||
);
|
);
|
||||||
$app = new Application();
|
$app = new Application();
|
||||||
$app->add($command);
|
$app->add($command);
|
||||||
|
@ -68,16 +68,16 @@ class LocateVisitsCommandTest extends TestCase
|
||||||
$location = new VisitLocation(Location::emptyInstance());
|
$location = new VisitLocation(Location::emptyInstance());
|
||||||
|
|
||||||
$locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will(
|
$locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will(
|
||||||
function (array $args) use ($visit, $location) {
|
function (array $args) use ($visit, $location): void {
|
||||||
$firstCallback = array_shift($args);
|
$firstCallback = array_shift($args);
|
||||||
$firstCallback($visit);
|
$firstCallback($visit);
|
||||||
|
|
||||||
$secondCallback = array_shift($args);
|
$secondCallback = array_shift($args);
|
||||||
$secondCallback($location, $visit);
|
$secondCallback($location, $visit);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
$resolveIpLocation = $this->ipResolver->resolveIpLocation(Argument::any())->willReturn(
|
$resolveIpLocation = $this->ipResolver->resolveIpLocation(Argument::any())->willReturn(
|
||||||
Location::emptyInstance()
|
Location::emptyInstance(),
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->commandTester->execute([]);
|
$this->commandTester->execute([]);
|
||||||
|
@ -98,16 +98,16 @@ class LocateVisitsCommandTest extends TestCase
|
||||||
$location = new VisitLocation(Location::emptyInstance());
|
$location = new VisitLocation(Location::emptyInstance());
|
||||||
|
|
||||||
$locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will(
|
$locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will(
|
||||||
function (array $args) use ($visit, $location) {
|
function (array $args) use ($visit, $location): void {
|
||||||
$firstCallback = array_shift($args);
|
$firstCallback = array_shift($args);
|
||||||
$firstCallback($visit);
|
$firstCallback($visit);
|
||||||
|
|
||||||
$secondCallback = array_shift($args);
|
$secondCallback = array_shift($args);
|
||||||
$secondCallback($location, $visit);
|
$secondCallback($location, $visit);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
$resolveIpLocation = $this->ipResolver->resolveIpLocation(Argument::any())->willReturn(
|
$resolveIpLocation = $this->ipResolver->resolveIpLocation(Argument::any())->willReturn(
|
||||||
Location::emptyInstance()
|
Location::emptyInstance(),
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->commandTester->execute([], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE]);
|
$this->commandTester->execute([], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE]);
|
||||||
|
@ -137,13 +137,13 @@ class LocateVisitsCommandTest extends TestCase
|
||||||
$location = new VisitLocation(Location::emptyInstance());
|
$location = new VisitLocation(Location::emptyInstance());
|
||||||
|
|
||||||
$locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will(
|
$locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will(
|
||||||
function (array $args) use ($visit, $location) {
|
function (array $args) use ($visit, $location): void {
|
||||||
$firstCallback = array_shift($args);
|
$firstCallback = array_shift($args);
|
||||||
$firstCallback($visit);
|
$firstCallback($visit);
|
||||||
|
|
||||||
$secondCallback = array_shift($args);
|
$secondCallback = array_shift($args);
|
||||||
$secondCallback($location, $visit);
|
$secondCallback($location, $visit);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
$resolveIpLocation = $this->ipResolver->resolveIpLocation(Argument::any())->willThrow(WrongIpException::class);
|
$resolveIpLocation = $this->ipResolver->resolveIpLocation(Argument::any())->willThrow(WrongIpException::class);
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ class LocateVisitsCommandTest extends TestCase
|
||||||
{
|
{
|
||||||
$this->lock->acquire(false)->willReturn(false);
|
$this->lock->acquire(false)->willReturn(false);
|
||||||
|
|
||||||
$locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will(function () {
|
$locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will(function (): void {
|
||||||
});
|
});
|
||||||
$resolveIpLocation = $this->ipResolver->resolveIpLocation(Argument::any())->willReturn([]);
|
$resolveIpLocation = $this->ipResolver->resolveIpLocation(Argument::any())->willReturn([]);
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ class LocateVisitsCommandTest extends TestCase
|
||||||
|
|
||||||
$this->assertStringContainsString(
|
$this->assertStringContainsString(
|
||||||
sprintf('Command "%s" is already in progress. Skipping.', LocateVisitsCommand::NAME),
|
sprintf('Command "%s" is already in progress. Skipping.', LocateVisitsCommand::NAME),
|
||||||
$output
|
$output,
|
||||||
);
|
);
|
||||||
$locateVisits->shouldNotHaveBeenCalled();
|
$locateVisits->shouldNotHaveBeenCalled();
|
||||||
$resolveIpLocation->shouldNotHaveBeenCalled();
|
$resolveIpLocation->shouldNotHaveBeenCalled();
|
||||||
|
@ -182,17 +182,17 @@ class LocateVisitsCommandTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function showsProperMessageWhenGeoLiteUpdateFails(bool $olderDbExists, string $expectedMessage): void
|
public function showsProperMessageWhenGeoLiteUpdateFails(bool $olderDbExists, string $expectedMessage): void
|
||||||
{
|
{
|
||||||
$locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will(function () {
|
$locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will(function (): void {
|
||||||
});
|
});
|
||||||
$checkDbUpdate = $this->dbUpdater->checkDbUpdate(Argument::cetera())->will(
|
$checkDbUpdate = $this->dbUpdater->checkDbUpdate(Argument::cetera())->will(
|
||||||
function (array $args) use ($olderDbExists) {
|
function (array $args) use ($olderDbExists): void {
|
||||||
[$mustBeUpdated, $handleProgress] = $args;
|
[$mustBeUpdated, $handleProgress] = $args;
|
||||||
|
|
||||||
$mustBeUpdated($olderDbExists);
|
$mustBeUpdated($olderDbExists);
|
||||||
$handleProgress(100, 50);
|
$handleProgress(100, 50);
|
||||||
|
|
||||||
throw GeolocationDbUpdateFailedException::create($olderDbExists);
|
throw GeolocationDbUpdateFailedException::create($olderDbExists);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->commandTester->execute([]);
|
$this->commandTester->execute([]);
|
||||||
|
@ -200,7 +200,7 @@ class LocateVisitsCommandTest extends TestCase
|
||||||
|
|
||||||
$this->assertStringContainsString(
|
$this->assertStringContainsString(
|
||||||
sprintf('%s GeoLite2 database...', $olderDbExists ? 'Updating' : 'Downloading'),
|
sprintf('%s GeoLite2 database...', $olderDbExists ? 'Updating' : 'Downloading'),
|
||||||
$output
|
$output,
|
||||||
);
|
);
|
||||||
$this->assertStringContainsString($expectedMessage, $output);
|
$this->assertStringContainsString($expectedMessage, $output);
|
||||||
$locateVisits->shouldHaveBeenCalledTimes((int) $olderDbExists);
|
$locateVisits->shouldHaveBeenCalledTimes((int) $olderDbExists);
|
||||||
|
|
|
@ -17,7 +17,7 @@ class ConfigProviderTest extends TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function confiIsProperlyReturned()
|
public function confiIsProperlyReturned(): void
|
||||||
{
|
{
|
||||||
$config = ($this->configProvider)();
|
$config = ($this->configProvider)();
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ class GeolocationDbUpdateFailedExceptionTest extends TestCase
|
||||||
$this->assertEquals($olderDbExists, $e->olderDbExists());
|
$this->assertEquals($olderDbExists, $e->olderDbExists());
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'An error occurred while updating geolocation database, and an older version could not be found',
|
'An error occurred while updating geolocation database, and an older version could not be found',
|
||||||
$e->getMessage()
|
$e->getMessage(),
|
||||||
);
|
);
|
||||||
$this->assertEquals(0, $e->getCode());
|
$this->assertEquals(0, $e->getCode());
|
||||||
$this->assertEquals($prev, $e->getPrevious());
|
$this->assertEquals($prev, $e->getPrevious());
|
||||||
|
|
|
@ -59,7 +59,7 @@ class ApplicationFactoryTest extends TestCase
|
||||||
$command->getDefinition()->willReturn($name);
|
$command->getDefinition()->willReturn($name);
|
||||||
$command->isEnabled()->willReturn(true);
|
$command->isEnabled()->willReturn(true);
|
||||||
$command->getAliases()->willReturn([]);
|
$command->getAliases()->willReturn([]);
|
||||||
$command->setApplication(Argument::type(Application::class))->willReturn(function () {
|
$command->setApplication(Argument::type(Application::class))->willReturn(function (): void {
|
||||||
});
|
});
|
||||||
|
|
||||||
return $command;
|
return $command;
|
||||||
|
|
|
@ -36,14 +36,14 @@ class GeolocationDbUpdaterTest extends TestCase
|
||||||
$this->locker = $this->prophesize(Lock\LockFactory::class);
|
$this->locker = $this->prophesize(Lock\LockFactory::class);
|
||||||
$this->lock = $this->prophesize(Lock\LockInterface::class);
|
$this->lock = $this->prophesize(Lock\LockInterface::class);
|
||||||
$this->lock->acquire(true)->willReturn(true);
|
$this->lock->acquire(true)->willReturn(true);
|
||||||
$this->lock->release()->will(function () {
|
$this->lock->release()->will(function (): void {
|
||||||
});
|
});
|
||||||
$this->locker->createLock(Argument::type('string'))->willReturn($this->lock->reveal());
|
$this->locker->createLock(Argument::type('string'))->willReturn($this->lock->reveal());
|
||||||
|
|
||||||
$this->geolocationDbUpdater = new GeolocationDbUpdater(
|
$this->geolocationDbUpdater = new GeolocationDbUpdater(
|
||||||
$this->dbUpdater->reveal(),
|
$this->dbUpdater->reveal(),
|
||||||
$this->geoLiteDbReader->reveal(),
|
$this->geoLiteDbReader->reveal(),
|
||||||
$this->locker->reveal()
|
$this->locker->reveal(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ class GeolocationDbUpdaterTest extends TestCase
|
||||||
'node_count' => 1,
|
'node_count' => 1,
|
||||||
'record_size' => 4,
|
'record_size' => 4,
|
||||||
]));
|
]));
|
||||||
$download = $this->dbUpdater->downloadFreshCopy(null)->will(function () {
|
$download = $this->dbUpdater->downloadFreshCopy(null)->will(function (): void {
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->geolocationDbUpdater->checkDbUpdate();
|
$this->geolocationDbUpdater->checkDbUpdate();
|
||||||
|
|
|
@ -33,7 +33,7 @@ class ShlinkTableTest extends TestCase
|
||||||
$footerTitle = 'Footer';
|
$footerTitle = 'Footer';
|
||||||
|
|
||||||
$setStyle = $this->baseTable->setStyle(Argument::type(TableStyle::class))->willReturn(
|
$setStyle = $this->baseTable->setStyle(Argument::type(TableStyle::class))->willReturn(
|
||||||
$this->baseTable->reveal()
|
$this->baseTable->reveal(),
|
||||||
);
|
);
|
||||||
$setHeaders = $this->baseTable->setHeaders($headers)->willReturn($this->baseTable->reveal());
|
$setHeaders = $this->baseTable->setHeaders($headers)->willReturn($this->baseTable->reveal());
|
||||||
$setRows = $this->baseTable->setRows($rows)->willReturn($this->baseTable->reveal());
|
$setRows = $this->baseTable->setRows($rows)->willReturn($this->baseTable->reveal());
|
||||||
|
|
|
@ -46,10 +46,7 @@ abstract class AbstractTrackingAction implements MiddlewareInterface
|
||||||
* Process an incoming server request and return a response, optionally delegating
|
* Process an incoming server request and return a response, optionally delegating
|
||||||
* to the next middleware component to create the response.
|
* to the next middleware component to create the response.
|
||||||
*
|
*
|
||||||
* @param ServerRequestInterface $request
|
|
||||||
* @param RequestHandlerInterface $handler
|
|
||||||
*
|
*
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
*/
|
||||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||||
{
|
{
|
||||||
|
|
|
@ -41,10 +41,7 @@ class QrCodeAction implements MiddlewareInterface
|
||||||
* Process an incoming server request and return a response, optionally delegating
|
* Process an incoming server request and return a response, optionally delegating
|
||||||
* to the next middleware component to create the response.
|
* to the next middleware component to create the response.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
|
||||||
* @param RequestHandlerInterface $handler
|
|
||||||
*
|
*
|
||||||
* @return Response
|
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
*/
|
*/
|
||||||
|
@ -71,8 +68,6 @@ class QrCodeAction implements MiddlewareInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Request $request
|
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
private function getSizeParam(Request $request): int
|
private function getSizeParam(Request $request): int
|
||||||
{
|
{
|
||||||
|
|
|
@ -76,7 +76,7 @@ class SimplifiedConfigParser
|
||||||
$simplifiedConfigOrder = array_flip(array_keys(self::SIMPLIFIED_CONFIG_MAPPING));
|
$simplifiedConfigOrder = array_flip(array_keys(self::SIMPLIFIED_CONFIG_MAPPING));
|
||||||
uksort(
|
uksort(
|
||||||
$configForExistingKeys,
|
$configForExistingKeys,
|
||||||
fn (string $a, string $b): int => $simplifiedConfigOrder[$a] - $simplifiedConfigOrder[$b]
|
fn (string $a, string $b): int => $simplifiedConfigOrder[$a] - $simplifiedConfigOrder[$b],
|
||||||
);
|
);
|
||||||
|
|
||||||
return $configForExistingKeys;
|
return $configForExistingKeys;
|
||||||
|
|
|
@ -8,7 +8,7 @@ use function Shlinkio\Shlink\Common\loadConfigFromGlob;
|
||||||
|
|
||||||
class ConfigProvider
|
class ConfigProvider
|
||||||
{
|
{
|
||||||
public function __invoke()
|
public function __invoke(): array
|
||||||
{
|
{
|
||||||
return loadConfigFromGlob(__DIR__ . '/../config/{,*.}config.php');
|
return loadConfigFromGlob(__DIR__ . '/../config/{,*.}config.php');
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,7 +189,7 @@ class ShortUrl extends AbstractEntity
|
||||||
$hasAllTags = count($shortUrlTags) === count($tags) && array_reduce(
|
$hasAllTags = count($shortUrlTags) === count($tags) && array_reduce(
|
||||||
$tags,
|
$tags,
|
||||||
fn (bool $hasAllTags, string $tag) => $hasAllTags && contains($shortUrlTags, $tag),
|
fn (bool $hasAllTags, string $tag) => $hasAllTags && contains($shortUrlTags, $tag),
|
||||||
true
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
return $hasAllTags;
|
return $hasAllTags;
|
||||||
|
|
|
@ -28,9 +28,7 @@ class NotFoundTemplateHandler implements RequestHandlerInterface
|
||||||
/**
|
/**
|
||||||
* Dispatch the next available middleware and return the response.
|
* Dispatch the next available middleware and return the response.
|
||||||
*
|
*
|
||||||
* @param ServerRequestInterface $request
|
|
||||||
*
|
*
|
||||||
* @return ResponseInterface
|
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
|
|
|
@ -62,14 +62,14 @@ class LocateShortUrlVisit
|
||||||
private function downloadOrUpdateGeoLiteDb(string $visitId): bool
|
private function downloadOrUpdateGeoLiteDb(string $visitId): bool
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$this->dbUpdater->checkDbUpdate(function (bool $olderDbExists) {
|
$this->dbUpdater->checkDbUpdate(function (bool $olderDbExists): void {
|
||||||
$this->logger->notice(sprintf('%s GeoLite2 database...', $olderDbExists ? 'Updating' : 'Downloading'));
|
$this->logger->notice(sprintf('%s GeoLite2 database...', $olderDbExists ? 'Updating' : 'Downloading'));
|
||||||
});
|
});
|
||||||
} catch (GeolocationDbUpdateFailedException $e) {
|
} catch (GeolocationDbUpdateFailedException $e) {
|
||||||
if (! $e->olderDbExists()) {
|
if (! $e->olderDbExists()) {
|
||||||
$this->logger->error(
|
$this->logger->error(
|
||||||
'GeoLite2 database download failed. It is not possible to locate visit with id {visitId}. {e}',
|
'GeoLite2 database download failed. It is not possible to locate visit with id {visitId}. {e}',
|
||||||
['e' => $e, 'visitId' => $visitId]
|
['e' => $e, 'visitId' => $visitId],
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ class LocateShortUrlVisit
|
||||||
} catch (WrongIpException $e) {
|
} catch (WrongIpException $e) {
|
||||||
$this->logger->warning(
|
$this->logger->warning(
|
||||||
'Tried to locate visit with id "{visitId}", but its address seems to be wrong. {e}',
|
'Tried to locate visit with id "{visitId}", but its address seems to be wrong. {e}',
|
||||||
['e' => $e, 'visitId' => $visitId]
|
['e' => $e, 'visitId' => $visitId],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ class NotifyVisitToWebHooks
|
||||||
return map($this->webhooks, function (string $webhook) use ($requestOptions, $visitId) {
|
return map($this->webhooks, function (string $webhook) use ($requestOptions, $visitId) {
|
||||||
$promise = $this->httpClient->requestAsync(RequestMethodInterface::METHOD_POST, $webhook, $requestOptions);
|
$promise = $this->httpClient->requestAsync(RequestMethodInterface::METHOD_POST, $webhook, $requestOptions);
|
||||||
return $promise->otherwise(
|
return $promise->otherwise(
|
||||||
partial_left(Closure::fromCallable([$this, 'logWebhookFailure']), $webhook, $visitId)
|
partial_left(Closure::fromCallable([$this, 'logWebhookFailure']), $webhook, $visitId),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ class DeleteShortUrlException extends DomainException implements ProblemDetailsE
|
||||||
$e = new self(sprintf(
|
$e = new self(sprintf(
|
||||||
'Impossible to delete short URL with short code "%s" since it has more than "%s" visits.',
|
'Impossible to delete short URL with short code "%s" since it has more than "%s" visits.',
|
||||||
$shortCode,
|
$shortCode,
|
||||||
$threshold
|
$threshold,
|
||||||
));
|
));
|
||||||
|
|
||||||
$e->detail = $e->getMessage();
|
$e->detail = $e->getMessage();
|
||||||
|
|
|
@ -63,7 +63,7 @@ class ValidationException extends InvalidArgumentException implements ProblemDet
|
||||||
$this->invalidElementsToString(),
|
$this->invalidElementsToString(),
|
||||||
PHP_EOL,
|
PHP_EOL,
|
||||||
PHP_EOL,
|
PHP_EOL,
|
||||||
$this->getTraceAsString()
|
$this->getTraceAsString(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ class ValidationException extends InvalidArgumentException implements ProblemDet
|
||||||
return reduce_left($this->getInvalidElements(), fn ($messages, string $name, $_, string $acc) => $acc . sprintf(
|
return reduce_left($this->getInvalidElements(), fn ($messages, string $name, $_, string $acc) => $acc . sprintf(
|
||||||
"\n '%s' => %s",
|
"\n '%s' => %s",
|
||||||
$name,
|
$name,
|
||||||
is_array($messages) ? print_r($messages, true) : $messages
|
is_array($messages) ? print_r($messages, true) : $messages,
|
||||||
), '');
|
), '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,7 @@ class QrCodeCacheMiddleware implements MiddlewareInterface
|
||||||
* Process an incoming server request and return a response, optionally delegating
|
* Process an incoming server request and return a response, optionally delegating
|
||||||
* to the next middleware component to create the response.
|
* to the next middleware component to create the response.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
|
||||||
* @param RequestHandlerInterface $handler
|
|
||||||
*
|
*
|
||||||
* @return Response
|
|
||||||
*/
|
*/
|
||||||
public function process(Request $request, RequestHandlerInterface $handler): Response
|
public function process(Request $request, RequestHandlerInterface $handler): Response
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,7 +23,6 @@ final class CreateShortUrlData
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return UriInterface
|
|
||||||
*/
|
*/
|
||||||
public function getLongUrl(): UriInterface
|
public function getLongUrl(): UriInterface
|
||||||
{
|
{
|
||||||
|
@ -39,7 +38,6 @@ final class CreateShortUrlData
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ShortUrlMeta
|
|
||||||
*/
|
*/
|
||||||
public function getMeta(): ShortUrlMeta
|
public function getMeta(): ShortUrlMeta
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,7 +48,7 @@ final class ShortUrlMeta
|
||||||
* @param string|null $domain
|
* @param string|null $domain
|
||||||
* @throws ValidationException
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
public static function createFromParams(
|
public static function createFromParams( // phpcs:ignore
|
||||||
$validSince = null,
|
$validSince = null,
|
||||||
$validUntil = null,
|
$validUntil = null,
|
||||||
$customSlug = null,
|
$customSlug = null,
|
||||||
|
|
|
@ -36,7 +36,7 @@ final class Visitor
|
||||||
return new self(
|
return new self(
|
||||||
$request->getHeaderLine('User-Agent'),
|
$request->getHeaderLine('User-Agent'),
|
||||||
$request->getHeaderLine('Referer'),
|
$request->getHeaderLine('Referer'),
|
||||||
$request->getAttribute(IpAddressMiddlewareFactory::REQUEST_ATTR)
|
$request->getAttribute(IpAddressMiddlewareFactory::REQUEST_ATTR),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ final class VisitsParams
|
||||||
return new self(
|
return new self(
|
||||||
new DateRange($startDate, $endDate),
|
new DateRange($startDate, $endDate),
|
||||||
(int) ($query['page'] ?? 1),
|
(int) ($query['page'] ?? 1),
|
||||||
isset($query['itemsPerPage']) ? (int) $query['itemsPerPage'] : null
|
isset($query['itemsPerPage']) ? (int) $query['itemsPerPage'] : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ class AppOptions extends AbstractOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string|null
|
|
||||||
*/
|
*/
|
||||||
public function getDisableTrackParam(): ?string
|
public function getDisableTrackParam(): ?string
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,8 +8,8 @@ use Zend\Stdlib\AbstractOptions;
|
||||||
|
|
||||||
class DeleteShortUrlsOptions extends AbstractOptions
|
class DeleteShortUrlsOptions extends AbstractOptions
|
||||||
{
|
{
|
||||||
private $visitsThreshold = 15;
|
private int $visitsThreshold = 15;
|
||||||
private $checkVisitsThreshold = true;
|
private bool $checkVisitsThreshold = true;
|
||||||
|
|
||||||
public function getVisitsThreshold(): int
|
public function getVisitsThreshold(): int
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,20 +8,18 @@ use Zend\Stdlib\AbstractOptions;
|
||||||
|
|
||||||
class UrlShortenerOptions extends AbstractOptions
|
class UrlShortenerOptions extends AbstractOptions
|
||||||
{
|
{
|
||||||
// phpcs:disable
|
protected $__strictMode__ = false; // phpcs:ignore
|
||||||
protected $__strictMode__ = false;
|
|
||||||
// phpcs:enable
|
|
||||||
|
|
||||||
private $validateUrl = true;
|
private bool $validateUrl = true;
|
||||||
|
|
||||||
public function isUrlValidationEnabled(): bool
|
public function isUrlValidationEnabled(): bool
|
||||||
{
|
{
|
||||||
return $this->validateUrl;
|
return $this->validateUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function setValidateUrl($validateUrl): self
|
protected function setValidateUrl(bool $validateUrl): self
|
||||||
{
|
{
|
||||||
$this->validateUrl = (bool) $validateUrl;
|
$this->validateUrl = $validateUrl;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,12 @@ class ShortUrlRepositoryAdapter implements AdapterInterface
|
||||||
private array $tags;
|
private array $tags;
|
||||||
private ?DateRange $dateRange;
|
private ?DateRange $dateRange;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|array|null $orderBy
|
||||||
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ShortUrlRepositoryInterface $repository,
|
ShortUrlRepositoryInterface $repository,
|
||||||
$searchTerm = null,
|
?string $searchTerm = null,
|
||||||
array $tags = [],
|
array $tags = [],
|
||||||
$orderBy = null,
|
$orderBy = null,
|
||||||
?DateRange $dateRange = null
|
?DateRange $dateRange = null
|
||||||
|
@ -41,9 +44,8 @@ class ShortUrlRepositoryAdapter implements AdapterInterface
|
||||||
*
|
*
|
||||||
* @param int $offset Page offset
|
* @param int $offset Page offset
|
||||||
* @param int $itemCountPerPage Number of items per page
|
* @param int $itemCountPerPage Number of items per page
|
||||||
* @return array
|
|
||||||
*/
|
*/
|
||||||
public function getItems($offset, $itemCountPerPage): array
|
public function getItems($offset, $itemCountPerPage): array // phpcs:ignore
|
||||||
{
|
{
|
||||||
return $this->repository->findList(
|
return $this->repository->findList(
|
||||||
$itemCountPerPage,
|
$itemCountPerPage,
|
||||||
|
@ -51,7 +53,7 @@ class ShortUrlRepositoryAdapter implements AdapterInterface
|
||||||
$this->searchTerm,
|
$this->searchTerm,
|
||||||
$this->tags,
|
$this->tags,
|
||||||
$this->orderBy,
|
$this->orderBy,
|
||||||
$this->dateRange
|
$this->dateRange,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,13 +21,13 @@ class VisitsPaginatorAdapter implements AdapterInterface
|
||||||
$this->params = $params;
|
$this->params = $params;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getItems($offset, $itemCountPerPage): array
|
public function getItems($offset, $itemCountPerPage): array // phpcs:ignore
|
||||||
{
|
{
|
||||||
return $this->visitRepository->findVisitsByShortCode(
|
return $this->visitRepository->findVisitsByShortCode(
|
||||||
$this->shortCode,
|
$this->shortCode,
|
||||||
$this->params->getDateRange(),
|
$this->params->getDateRange(),
|
||||||
$itemCountPerPage,
|
$itemCountPerPage,
|
||||||
$offset
|
$offset,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,9 @@ class ShortUrlRepository extends EntityRepository implements ShortUrlRepositoryI
|
||||||
return $qb->getQuery()->getResult();
|
return $qb->getQuery()->getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|array|null $orderBy
|
||||||
|
*/
|
||||||
private function processOrderByForList(QueryBuilder $qb, $orderBy): array
|
private function processOrderByForList(QueryBuilder $qb, $orderBy): array
|
||||||
{
|
{
|
||||||
$isArray = is_array($orderBy);
|
$isArray = is_array($orderBy);
|
||||||
|
@ -117,7 +120,7 @@ class ShortUrlRepository extends EntityRepository implements ShortUrlRepositoryI
|
||||||
$qb->andWhere($qb->expr()->orX(
|
$qb->andWhere($qb->expr()->orX(
|
||||||
$qb->expr()->like('s.longUrl', ':searchPattern'),
|
$qb->expr()->like('s.longUrl', ':searchPattern'),
|
||||||
$qb->expr()->like('s.shortCode', ':searchPattern'),
|
$qb->expr()->like('s.shortCode', ':searchPattern'),
|
||||||
$qb->expr()->like('t.name', ':searchPattern')
|
$qb->expr()->like('t.name', ':searchPattern'),
|
||||||
));
|
));
|
||||||
$qb->setParameter('searchPattern', '%' . $searchTerm . '%');
|
$qb->setParameter('searchPattern', '%' . $searchTerm . '%');
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ class DeleteShortUrlService implements DeleteShortUrlServiceInterface
|
||||||
if (! $ignoreThreshold && $this->isThresholdReached($shortUrl)) {
|
if (! $ignoreThreshold && $this->isThresholdReached($shortUrl)) {
|
||||||
throw Exception\DeleteShortUrlException::fromVisitsThreshold(
|
throw Exception\DeleteShortUrlException::fromVisitsThreshold(
|
||||||
$this->deleteShortUrlsOptions->getVisitsThreshold(),
|
$this->deleteShortUrlsOptions->getVisitsThreshold(),
|
||||||
$shortUrl->getShortCode()
|
$shortUrl->getShortCode(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,6 @@ use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
|
||||||
trait FindShortCodeTrait
|
trait FindShortCodeTrait
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param string $shortCode
|
|
||||||
* @return ShortUrl
|
|
||||||
* @throws ShortUrlNotFoundException
|
* @throws ShortUrlNotFoundException
|
||||||
*/
|
*/
|
||||||
private function findByShortCode(EntityManagerInterface $em, string $shortCode): ShortUrl
|
private function findByShortCode(EntityManagerInterface $em, string $shortCode): ShortUrl
|
||||||
|
|
|
@ -22,7 +22,7 @@ class ShortUrlDataTransformer implements DataTransformerInterface
|
||||||
/**
|
/**
|
||||||
* @param ShortUrl $shortUrl
|
* @param ShortUrl $shortUrl
|
||||||
*/
|
*/
|
||||||
public function transform($shortUrl): array
|
public function transform($shortUrl): array // phpcs:ignore
|
||||||
{
|
{
|
||||||
$longUrl = $shortUrl->getLongUrl();
|
$longUrl = $shortUrl->getLongUrl();
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ use function trim;
|
||||||
trait TagManagerTrait
|
trait TagManagerTrait
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param EntityManagerInterface $em
|
|
||||||
* @param string[] $tags
|
* @param string[] $tags
|
||||||
* @return Collections\Collection|Tag[]
|
* @return Collections\Collection|Tag[]
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -43,7 +43,7 @@ class ShortUrlRepositoryTest extends DatabaseTestCase
|
||||||
|
|
||||||
$notYetValid = new ShortUrl(
|
$notYetValid = new ShortUrl(
|
||||||
'bar',
|
'bar',
|
||||||
ShortUrlMeta::createFromParams(Chronos::now()->addMonth(), null, 'bar_very_long_text')
|
ShortUrlMeta::createFromParams(Chronos::now()->addMonth(), null, 'bar_very_long_text'),
|
||||||
);
|
);
|
||||||
$this->getEntityManager()->persist($notYetValid);
|
$this->getEntityManager()->persist($notYetValid);
|
||||||
|
|
||||||
|
@ -82,11 +82,11 @@ class ShortUrlRepositoryTest extends DatabaseTestCase
|
||||||
$this->assertSame($withDomain, $this->repo->findOneByShortCode($withDomain->getShortCode(), 'example.com'));
|
$this->assertSame($withDomain, $this->repo->findOneByShortCode($withDomain->getShortCode(), 'example.com'));
|
||||||
$this->assertSame(
|
$this->assertSame(
|
||||||
$withDomainDuplicatingRegular,
|
$withDomainDuplicatingRegular,
|
||||||
$this->repo->findOneByShortCode($withDomainDuplicatingRegular->getShortCode(), 'doma.in')
|
$this->repo->findOneByShortCode($withDomainDuplicatingRegular->getShortCode(), 'doma.in'),
|
||||||
);
|
);
|
||||||
$this->assertSame(
|
$this->assertSame(
|
||||||
$regularOne,
|
$regularOne,
|
||||||
$this->repo->findOneByShortCode($withDomainDuplicatingRegular->getShortCode(), 'other-domain.com')
|
$this->repo->findOneByShortCode($withDomainDuplicatingRegular->getShortCode(), 'other-domain.com'),
|
||||||
);
|
);
|
||||||
$this->assertNull($this->repo->findOneByShortCode('invalid'));
|
$this->assertNull($this->repo->findOneByShortCode('invalid'));
|
||||||
$this->assertNull($this->repo->findOneByShortCode($withDomain->getShortCode()));
|
$this->assertNull($this->repo->findOneByShortCode($withDomain->getShortCode()));
|
||||||
|
@ -160,7 +160,7 @@ class ShortUrlRepositoryTest extends DatabaseTestCase
|
||||||
|
|
||||||
$this->assertCount(
|
$this->assertCount(
|
||||||
2,
|
2,
|
||||||
$this->repo->findList(null, null, null, [], null, new DateRange(Chronos::now()->subDays(2)))
|
$this->repo->findList(null, null, null, [], null, new DateRange(Chronos::now()->subDays(2))),
|
||||||
);
|
);
|
||||||
$this->assertEquals(2, $this->repo->countList(null, [], new DateRange(Chronos::now()->subDays(2))));
|
$this->assertEquals(2, $this->repo->countList(null, [], new DateRange(Chronos::now()->subDays(2))));
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ class ShortUrlRepositoryTest extends DatabaseTestCase
|
||||||
|
|
||||||
$shortUrlWithDomain = new ShortUrl(
|
$shortUrlWithDomain = new ShortUrl(
|
||||||
'foo',
|
'foo',
|
||||||
ShortUrlMeta::createFromRawData(['domain' => 'doma.in', 'customSlug' => 'another-slug'])
|
ShortUrlMeta::createFromRawData(['domain' => 'doma.in', 'customSlug' => 'another-slug']),
|
||||||
);
|
);
|
||||||
$this->getEntityManager()->persist($shortUrlWithDomain);
|
$this->getEntityManager()->persist($shortUrlWithDomain);
|
||||||
|
|
||||||
|
|
|
@ -22,13 +22,13 @@ class TagRepositoryTest extends DatabaseTestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function deleteByNameDoesNothingWhenEmptyListIsProvided()
|
public function deleteByNameDoesNothingWhenEmptyListIsProvided(): void
|
||||||
{
|
{
|
||||||
$this->assertEquals(0, $this->repo->deleteByName([]));
|
$this->assertEquals(0, $this->repo->deleteByName([]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function allTagsWhichMatchNameAreDeleted()
|
public function allTagsWhichMatchNameAreDeleted(): void
|
||||||
{
|
{
|
||||||
$names = ['foo', 'bar', 'baz'];
|
$names = ['foo', 'bar', 'baz'];
|
||||||
$toDelete = ['foo', 'baz'];
|
$toDelete = ['foo', 'baz'];
|
||||||
|
|
|
@ -85,10 +85,10 @@ class VisitRepositoryTest extends DatabaseTestCase
|
||||||
$this->assertCount(6, $this->repo->findVisitsByShortCode($shortUrl->getShortCode()));
|
$this->assertCount(6, $this->repo->findVisitsByShortCode($shortUrl->getShortCode()));
|
||||||
$this->assertCount(2, $this->repo->findVisitsByShortCode($shortUrl->getShortCode(), new DateRange(
|
$this->assertCount(2, $this->repo->findVisitsByShortCode($shortUrl->getShortCode(), new DateRange(
|
||||||
Chronos::parse('2016-01-02'),
|
Chronos::parse('2016-01-02'),
|
||||||
Chronos::parse('2016-01-03')
|
Chronos::parse('2016-01-03'),
|
||||||
)));
|
)));
|
||||||
$this->assertCount(4, $this->repo->findVisitsByShortCode($shortUrl->getShortCode(), new DateRange(
|
$this->assertCount(4, $this->repo->findVisitsByShortCode($shortUrl->getShortCode(), new DateRange(
|
||||||
Chronos::parse('2016-01-03')
|
Chronos::parse('2016-01-03'),
|
||||||
)));
|
)));
|
||||||
$this->assertCount(3, $this->repo->findVisitsByShortCode($shortUrl->getShortCode(), null, 3, 2));
|
$this->assertCount(3, $this->repo->findVisitsByShortCode($shortUrl->getShortCode(), null, 3, 2));
|
||||||
$this->assertCount(2, $this->repo->findVisitsByShortCode($shortUrl->getShortCode(), null, 5, 4));
|
$this->assertCount(2, $this->repo->findVisitsByShortCode($shortUrl->getShortCode(), null, 5, 4));
|
||||||
|
@ -110,10 +110,10 @@ class VisitRepositoryTest extends DatabaseTestCase
|
||||||
$this->assertEquals(6, $this->repo->countVisitsByShortCode($shortUrl->getShortCode()));
|
$this->assertEquals(6, $this->repo->countVisitsByShortCode($shortUrl->getShortCode()));
|
||||||
$this->assertEquals(2, $this->repo->countVisitsByShortCode($shortUrl->getShortCode(), new DateRange(
|
$this->assertEquals(2, $this->repo->countVisitsByShortCode($shortUrl->getShortCode(), new DateRange(
|
||||||
Chronos::parse('2016-01-02'),
|
Chronos::parse('2016-01-02'),
|
||||||
Chronos::parse('2016-01-03')
|
Chronos::parse('2016-01-03'),
|
||||||
)));
|
)));
|
||||||
$this->assertEquals(4, $this->repo->countVisitsByShortCode($shortUrl->getShortCode(), new DateRange(
|
$this->assertEquals(4, $this->repo->countVisitsByShortCode($shortUrl->getShortCode(), new DateRange(
|
||||||
Chronos::parse('2016-01-03')
|
Chronos::parse('2016-01-03'),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ class PixelActionTest extends TestCase
|
||||||
$this->action = new PixelAction(
|
$this->action = new PixelAction(
|
||||||
$this->urlShortener->reveal(),
|
$this->urlShortener->reveal(),
|
||||||
$this->visitTracker->reveal(),
|
$this->visitTracker->reveal(),
|
||||||
new AppOptions()
|
new AppOptions(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ class PixelActionTest extends TestCase
|
||||||
{
|
{
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$this->urlShortener->shortCodeToUrl($shortCode, '')->willReturn(
|
$this->urlShortener->shortCodeToUrl($shortCode, '')->willReturn(
|
||||||
new ShortUrl('http://domain.com/foo/bar')
|
new ShortUrl('http://domain.com/foo/bar'),
|
||||||
)->shouldBeCalledOnce();
|
)->shouldBeCalledOnce();
|
||||||
$this->visitTracker->track(Argument::cetera())->shouldBeCalledOnce();
|
$this->visitTracker->track(Argument::cetera())->shouldBeCalledOnce();
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ class QrCodeActionTest extends TestCase
|
||||||
|
|
||||||
$resp = $this->action->process(
|
$resp = $this->action->process(
|
||||||
(new ServerRequest())->withAttribute('shortCode', $shortCode),
|
(new ServerRequest())->withAttribute('shortCode', $shortCode),
|
||||||
$delegate->reveal()
|
$delegate->reveal(),
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertInstanceOf(QrCodeResponse::class, $resp);
|
$this->assertInstanceOf(QrCodeResponse::class, $resp);
|
||||||
|
|
|
@ -33,7 +33,7 @@ class RedirectActionTest extends TestCase
|
||||||
$this->action = new RedirectAction(
|
$this->action = new RedirectAction(
|
||||||
$this->urlShortener->reveal(),
|
$this->urlShortener->reveal(),
|
||||||
$this->visitTracker->reveal(),
|
$this->visitTracker->reveal(),
|
||||||
new Options\AppOptions(['disableTrackParam' => 'foobar'])
|
new Options\AppOptions(['disableTrackParam' => 'foobar']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ class RedirectActionTest extends TestCase
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$shortUrl = new ShortUrl('http://domain.com/foo/bar?some=thing');
|
$shortUrl = new ShortUrl('http://domain.com/foo/bar?some=thing');
|
||||||
$shortCodeToUrl = $this->urlShortener->shortCodeToUrl($shortCode, '')->willReturn($shortUrl);
|
$shortCodeToUrl = $this->urlShortener->shortCodeToUrl($shortCode, '')->willReturn($shortUrl);
|
||||||
$track = $this->visitTracker->track(Argument::cetera())->will(function () {
|
$track = $this->visitTracker->track(Argument::cetera())->will(function (): void {
|
||||||
});
|
});
|
||||||
|
|
||||||
$request = (new ServerRequest())->withAttribute('shortCode', $shortCode)->withQueryParams($query);
|
$request = (new ServerRequest())->withAttribute('shortCode', $shortCode)->withQueryParams($query);
|
||||||
|
|
|
@ -17,7 +17,7 @@ class ConfigProviderTest extends TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function properConfigIsReturned()
|
public function properConfigIsReturned(): void
|
||||||
{
|
{
|
||||||
$config = $this->configProvider->__invoke();
|
$config = $this->configProvider->__invoke();
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ use Shlinkio\Shlink\Core\Entity\Tag;
|
||||||
class TagTest extends TestCase
|
class TagTest extends TestCase
|
||||||
{
|
{
|
||||||
/** @test */
|
/** @test */
|
||||||
public function jsonSerializationOfTagsReturnsItsStringRepresentation()
|
public function jsonSerializationOfTagsReturnsItsStringRepresentation(): void
|
||||||
{
|
{
|
||||||
$tag = new Tag('This is my name');
|
$tag = new Tag('This is my name');
|
||||||
$this->assertEquals((string) $tag, $tag->jsonSerialize());
|
$this->assertEquals((string) $tag, $tag->jsonSerialize());
|
||||||
|
|
|
@ -73,9 +73,9 @@ class NotFoundRedirectHandlerTest extends TestCase
|
||||||
'',
|
'',
|
||||||
$this->prophesize(MiddlewareInterface::class)->reveal(),
|
$this->prophesize(MiddlewareInterface::class)->reveal(),
|
||||||
['GET'],
|
['GET'],
|
||||||
RedirectAction::class
|
RedirectAction::class,
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
->withUri(new Uri('/abc123')),
|
->withUri(new Uri('/abc123')),
|
||||||
'invalidShortUrl',
|
'invalidShortUrl',
|
||||||
|
|
|
@ -49,7 +49,7 @@ class NotFoundTemplateHandlerTest extends TestCase
|
||||||
yield [
|
yield [
|
||||||
$request->withAttribute(
|
$request->withAttribute(
|
||||||
RouteResult::class,
|
RouteResult::class,
|
||||||
RouteResult::fromRoute(new Route('', $this->prophesize(MiddlewareInterface::class)->reveal()))
|
RouteResult::fromRoute(new Route('', $this->prophesize(MiddlewareInterface::class)->reveal())),
|
||||||
),
|
),
|
||||||
NotFoundTemplateHandler::INVALID_SHORT_CODE_TEMPLATE,
|
NotFoundTemplateHandler::INVALID_SHORT_CODE_TEMPLATE,
|
||||||
];
|
];
|
||||||
|
|
|
@ -47,7 +47,7 @@ class LocateShortUrlVisitTest extends TestCase
|
||||||
$this->em->reveal(),
|
$this->em->reveal(),
|
||||||
$this->logger->reveal(),
|
$this->logger->reveal(),
|
||||||
$this->dbUpdater->reveal(),
|
$this->dbUpdater->reveal(),
|
||||||
$this->eventDispatcher->reveal()
|
$this->eventDispatcher->reveal(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ class LocateShortUrlVisitTest extends TestCase
|
||||||
$logWarning = $this->logger->warning('Tried to locate visit with id "{visitId}", but it does not exist.', [
|
$logWarning = $this->logger->warning('Tried to locate visit with id "{visitId}", but it does not exist.', [
|
||||||
'visitId' => 123,
|
'visitId' => 123,
|
||||||
]);
|
]);
|
||||||
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function () {
|
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void {
|
||||||
});
|
});
|
||||||
|
|
||||||
($this->locateVisit)($event);
|
($this->locateVisit)($event);
|
||||||
|
@ -76,16 +76,16 @@ class LocateShortUrlVisitTest extends TestCase
|
||||||
{
|
{
|
||||||
$event = new ShortUrlVisited('123');
|
$event = new ShortUrlVisited('123');
|
||||||
$findVisit = $this->em->find(Visit::class, '123')->willReturn(
|
$findVisit = $this->em->find(Visit::class, '123')->willReturn(
|
||||||
new Visit(new ShortUrl(''), new Visitor('', '', '1.2.3.4'))
|
new Visit(new ShortUrl(''), new Visitor('', '', '1.2.3.4')),
|
||||||
);
|
);
|
||||||
$resolveLocation = $this->ipLocationResolver->resolveIpLocation(Argument::cetera())->willThrow(
|
$resolveLocation = $this->ipLocationResolver->resolveIpLocation(Argument::cetera())->willThrow(
|
||||||
WrongIpException::class
|
WrongIpException::class,
|
||||||
);
|
);
|
||||||
$logWarning = $this->logger->warning(
|
$logWarning = $this->logger->warning(
|
||||||
Argument::containingString('Tried to locate visit with id "{visitId}", but its address seems to be wrong.'),
|
Argument::containingString('Tried to locate visit with id "{visitId}", but its address seems to be wrong.'),
|
||||||
Argument::type('array')
|
Argument::type('array'),
|
||||||
);
|
);
|
||||||
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function () {
|
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void {
|
||||||
});
|
});
|
||||||
|
|
||||||
($this->locateVisit)($event);
|
($this->locateVisit)($event);
|
||||||
|
@ -105,10 +105,10 @@ class LocateShortUrlVisitTest extends TestCase
|
||||||
{
|
{
|
||||||
$event = new ShortUrlVisited('123');
|
$event = new ShortUrlVisited('123');
|
||||||
$findVisit = $this->em->find(Visit::class, '123')->willReturn($visit);
|
$findVisit = $this->em->find(Visit::class, '123')->willReturn($visit);
|
||||||
$flush = $this->em->flush()->will(function () {
|
$flush = $this->em->flush()->will(function (): void {
|
||||||
});
|
});
|
||||||
$resolveIp = $this->ipLocationResolver->resolveIpLocation(Argument::any());
|
$resolveIp = $this->ipLocationResolver->resolveIpLocation(Argument::any());
|
||||||
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function () {
|
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void {
|
||||||
});
|
});
|
||||||
|
|
||||||
($this->locateVisit)($event);
|
($this->locateVisit)($event);
|
||||||
|
@ -139,10 +139,10 @@ class LocateShortUrlVisitTest extends TestCase
|
||||||
$event = new ShortUrlVisited('123');
|
$event = new ShortUrlVisited('123');
|
||||||
|
|
||||||
$findVisit = $this->em->find(Visit::class, '123')->willReturn($visit);
|
$findVisit = $this->em->find(Visit::class, '123')->willReturn($visit);
|
||||||
$flush = $this->em->flush()->will(function () {
|
$flush = $this->em->flush()->will(function (): void {
|
||||||
});
|
});
|
||||||
$resolveIp = $this->ipLocationResolver->resolveIpLocation($ipAddr)->willReturn($location);
|
$resolveIp = $this->ipLocationResolver->resolveIpLocation($ipAddr)->willReturn($location);
|
||||||
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function () {
|
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void {
|
||||||
});
|
});
|
||||||
|
|
||||||
($this->locateVisit)($event);
|
($this->locateVisit)($event);
|
||||||
|
@ -165,11 +165,11 @@ class LocateShortUrlVisitTest extends TestCase
|
||||||
$event = new ShortUrlVisited('123');
|
$event = new ShortUrlVisited('123');
|
||||||
|
|
||||||
$findVisit = $this->em->find(Visit::class, '123')->willReturn($visit);
|
$findVisit = $this->em->find(Visit::class, '123')->willReturn($visit);
|
||||||
$flush = $this->em->flush()->will(function () {
|
$flush = $this->em->flush()->will(function (): void {
|
||||||
});
|
});
|
||||||
$resolveIp = $this->ipLocationResolver->resolveIpLocation($ipAddr)->willReturn($location);
|
$resolveIp = $this->ipLocationResolver->resolveIpLocation($ipAddr)->willReturn($location);
|
||||||
$checkUpdateDb = $this->dbUpdater->checkDbUpdate(Argument::cetera())->willThrow($e);
|
$checkUpdateDb = $this->dbUpdater->checkDbUpdate(Argument::cetera())->willThrow($e);
|
||||||
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function () {
|
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void {
|
||||||
});
|
});
|
||||||
|
|
||||||
($this->locateVisit)($event);
|
($this->locateVisit)($event);
|
||||||
|
@ -181,7 +181,7 @@ class LocateShortUrlVisitTest extends TestCase
|
||||||
$checkUpdateDb->shouldHaveBeenCalledOnce();
|
$checkUpdateDb->shouldHaveBeenCalledOnce();
|
||||||
$this->logger->warning(
|
$this->logger->warning(
|
||||||
'GeoLite2 database update failed. Proceeding with old version. {e}',
|
'GeoLite2 database update failed. Proceeding with old version. {e}',
|
||||||
['e' => $e]
|
['e' => $e],
|
||||||
)->shouldHaveBeenCalledOnce();
|
)->shouldHaveBeenCalledOnce();
|
||||||
$dispatch->shouldHaveBeenCalledOnce();
|
$dispatch->shouldHaveBeenCalledOnce();
|
||||||
}
|
}
|
||||||
|
@ -196,15 +196,15 @@ class LocateShortUrlVisitTest extends TestCase
|
||||||
$event = new ShortUrlVisited('123');
|
$event = new ShortUrlVisited('123');
|
||||||
|
|
||||||
$findVisit = $this->em->find(Visit::class, '123')->willReturn($visit);
|
$findVisit = $this->em->find(Visit::class, '123')->willReturn($visit);
|
||||||
$flush = $this->em->flush()->will(function () {
|
$flush = $this->em->flush()->will(function (): void {
|
||||||
});
|
});
|
||||||
$resolveIp = $this->ipLocationResolver->resolveIpLocation($ipAddr)->willReturn($location);
|
$resolveIp = $this->ipLocationResolver->resolveIpLocation($ipAddr)->willReturn($location);
|
||||||
$checkUpdateDb = $this->dbUpdater->checkDbUpdate(Argument::cetera())->willThrow($e);
|
$checkUpdateDb = $this->dbUpdater->checkDbUpdate(Argument::cetera())->willThrow($e);
|
||||||
$logError = $this->logger->error(
|
$logError = $this->logger->error(
|
||||||
'GeoLite2 database download failed. It is not possible to locate visit with id {visitId}. {e}',
|
'GeoLite2 database download failed. It is not possible to locate visit with id {visitId}. {e}',
|
||||||
['e' => $e, 'visitId' => 123]
|
['e' => $e, 'visitId' => 123],
|
||||||
);
|
);
|
||||||
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function () {
|
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void {
|
||||||
});
|
});
|
||||||
|
|
||||||
($this->locateVisit)($event);
|
($this->locateVisit)($event);
|
||||||
|
|
|
@ -43,7 +43,7 @@ class DeleteShortUrlExceptionTest extends TestCase
|
||||||
return [$number, $shortCode = generateRandomShortCode(6), sprintf(
|
return [$number, $shortCode = generateRandomShortCode(6), sprintf(
|
||||||
'Impossible to delete short URL with short code "%s" since it has more than "%s" visits.',
|
'Impossible to delete short URL with short code "%s" since it has more than "%s" visits.',
|
||||||
$shortCode,
|
$shortCode,
|
||||||
$number
|
$number,
|
||||||
)];
|
)];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ class QrCodeCacheMiddlewareTest extends TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function noCachedPathFallsBackToNextMiddleware()
|
public function noCachedPathFallsBackToNextMiddleware(): void
|
||||||
{
|
{
|
||||||
$delegate = $this->prophesize(RequestHandlerInterface::class);
|
$delegate = $this->prophesize(RequestHandlerInterface::class);
|
||||||
$delegate->handle(Argument::any())->willReturn(new Response())->shouldBeCalledOnce();
|
$delegate->handle(Argument::any())->willReturn(new Response())->shouldBeCalledOnce();
|
||||||
|
@ -37,7 +37,7 @@ class QrCodeCacheMiddlewareTest extends TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function cachedPathReturnsCacheContent()
|
public function cachedPathReturnsCacheContent(): void
|
||||||
{
|
{
|
||||||
$isCalled = false;
|
$isCalled = false;
|
||||||
$uri = (new Uri())->withPath('/foo');
|
$uri = (new Uri())->withPath('/foo');
|
||||||
|
|
|
@ -21,11 +21,12 @@ class ShortUrlRepositoryAdapterTest extends TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param string|array|null $orderBy
|
||||||
* @test
|
* @test
|
||||||
* @dataProvider provideFilteringArgs
|
* @dataProvider provideFilteringArgs
|
||||||
*/
|
*/
|
||||||
public function getItemsFallsBackToFindList(
|
public function getItemsFallsBackToFindList(
|
||||||
$searchTerm = null,
|
?string $searchTerm = null,
|
||||||
array $tags = [],
|
array $tags = [],
|
||||||
?DateRange $dateRange = null,
|
?DateRange $dateRange = null,
|
||||||
$orderBy = null
|
$orderBy = null
|
||||||
|
@ -40,8 +41,11 @@ class ShortUrlRepositoryAdapterTest extends TestCase
|
||||||
* @test
|
* @test
|
||||||
* @dataProvider provideFilteringArgs
|
* @dataProvider provideFilteringArgs
|
||||||
*/
|
*/
|
||||||
public function countFallsBackToCountList($searchTerm = null, array $tags = [], ?DateRange $dateRange = null): void
|
public function countFallsBackToCountList(
|
||||||
{
|
?string $searchTerm = null,
|
||||||
|
array $tags = [],
|
||||||
|
?DateRange $dateRange = null
|
||||||
|
): void {
|
||||||
$adapter = new ShortUrlRepositoryAdapter($this->repo->reveal(), $searchTerm, $tags, null, $dateRange);
|
$adapter = new ShortUrlRepositoryAdapter($this->repo->reveal(), $searchTerm, $tags, null, $dateRange);
|
||||||
|
|
||||||
$this->repo->countList($searchTerm, $tags, $dateRange)->shouldBeCalledOnce();
|
$this->repo->countList($searchTerm, $tags, $dateRange)->shouldBeCalledOnce();
|
||||||
|
|
|
@ -29,7 +29,7 @@ class DeleteShortUrlServiceTest extends TestCase
|
||||||
public function setUp(): void
|
public function setUp(): void
|
||||||
{
|
{
|
||||||
$shortUrl = (new ShortUrl(''))->setVisits(
|
$shortUrl = (new ShortUrl(''))->setVisits(
|
||||||
new ArrayCollection(map(range(0, 10), fn () => new Visit(new ShortUrl(''), Visitor::emptyInstance())))
|
new ArrayCollection(map(range(0, 10), fn () => new Visit(new ShortUrl(''), Visitor::emptyInstance()))),
|
||||||
);
|
);
|
||||||
$this->shortCode = $shortUrl->getShortCode();
|
$this->shortCode = $shortUrl->getShortCode();
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ class DeleteShortUrlServiceTest extends TestCase
|
||||||
$this->expectException(DeleteShortUrlException::class);
|
$this->expectException(DeleteShortUrlException::class);
|
||||||
$this->expectExceptionMessage(sprintf(
|
$this->expectExceptionMessage(sprintf(
|
||||||
'Impossible to delete short URL with short code "%s" since it has more than "5" visits.',
|
'Impossible to delete short URL with short code "%s" since it has more than "5" visits.',
|
||||||
$this->shortCode
|
$this->shortCode,
|
||||||
));
|
));
|
||||||
|
|
||||||
$service->deleteByShortCode($this->shortCode);
|
$service->deleteByShortCode($this->shortCode);
|
||||||
|
|
|
@ -97,7 +97,7 @@ class ShortUrlServiceTest extends TestCase
|
||||||
Chronos::parse('2017-01-01 00:00:00')->toAtomString(),
|
Chronos::parse('2017-01-01 00:00:00')->toAtomString(),
|
||||||
Chronos::parse('2017-01-05 00:00:00')->toAtomString(),
|
Chronos::parse('2017-01-05 00:00:00')->toAtomString(),
|
||||||
null,
|
null,
|
||||||
5
|
5,
|
||||||
));
|
));
|
||||||
|
|
||||||
$this->assertSame($shortUrl, $result);
|
$this->assertSame($shortUrl, $result);
|
||||||
|
|
|
@ -42,7 +42,7 @@ class UrlShortenerTest extends TestCase
|
||||||
$this->em->flush()->willReturn(null);
|
$this->em->flush()->willReturn(null);
|
||||||
$this->em->commit()->willReturn(null);
|
$this->em->commit()->willReturn(null);
|
||||||
$this->em->beginTransaction()->willReturn(null);
|
$this->em->beginTransaction()->willReturn(null);
|
||||||
$this->em->persist(Argument::any())->will(function ($arguments) {
|
$this->em->persist(Argument::any())->will(function ($arguments): void {
|
||||||
/** @var ShortUrl $shortUrl */
|
/** @var ShortUrl $shortUrl */
|
||||||
[$shortUrl] = $arguments;
|
[$shortUrl] = $arguments;
|
||||||
$shortUrl->setId('10');
|
$shortUrl->setId('10');
|
||||||
|
@ -59,7 +59,7 @@ class UrlShortenerTest extends TestCase
|
||||||
$this->urlShortener = new UrlShortener(
|
$this->urlShortener = new UrlShortener(
|
||||||
$this->urlValidator->reveal(),
|
$this->urlValidator->reveal(),
|
||||||
$this->em->reveal(),
|
$this->em->reveal(),
|
||||||
new UrlShortenerOptions(['validate_url' => $urlValidationEnabled])
|
new UrlShortenerOptions(['validate_url' => $urlValidationEnabled]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ class UrlShortenerTest extends TestCase
|
||||||
$shortUrl = $this->urlShortener->urlToShortCode(
|
$shortUrl = $this->urlShortener->urlToShortCode(
|
||||||
new Uri('http://foobar.com/12345/hello?foo=bar'),
|
new Uri('http://foobar.com/12345/hello?foo=bar'),
|
||||||
[],
|
[],
|
||||||
ShortUrlMeta::createEmpty()
|
ShortUrlMeta::createEmpty(),
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertEquals('http://foobar.com/12345/hello?foo=bar', $shortUrl->getLongUrl());
|
$this->assertEquals('http://foobar.com/12345/hello?foo=bar', $shortUrl->getLongUrl());
|
||||||
|
@ -85,7 +85,7 @@ class UrlShortenerTest extends TestCase
|
||||||
function () use (&$callIndex, $expectedCalls) {
|
function () use (&$callIndex, $expectedCalls) {
|
||||||
$callIndex++;
|
$callIndex++;
|
||||||
return $callIndex < $expectedCalls;
|
return $callIndex < $expectedCalls;
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
$repo->findBy(Argument::cetera())->willReturn([]);
|
$repo->findBy(Argument::cetera())->willReturn([]);
|
||||||
$getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
|
$getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
|
||||||
|
@ -93,7 +93,7 @@ class UrlShortenerTest extends TestCase
|
||||||
$shortUrl = $this->urlShortener->urlToShortCode(
|
$shortUrl = $this->urlShortener->urlToShortCode(
|
||||||
new Uri('http://foobar.com/12345/hello?foo=bar'),
|
new Uri('http://foobar.com/12345/hello?foo=bar'),
|
||||||
[],
|
[],
|
||||||
ShortUrlMeta::createEmpty()
|
ShortUrlMeta::createEmpty(),
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertEquals('http://foobar.com/12345/hello?foo=bar', $shortUrl->getLongUrl());
|
$this->assertEquals('http://foobar.com/12345/hello?foo=bar', $shortUrl->getLongUrl());
|
||||||
|
@ -116,7 +116,7 @@ class UrlShortenerTest extends TestCase
|
||||||
$this->urlShortener->urlToShortCode(
|
$this->urlShortener->urlToShortCode(
|
||||||
new Uri('http://foobar.com/12345/hello?foo=bar'),
|
new Uri('http://foobar.com/12345/hello?foo=bar'),
|
||||||
[],
|
[],
|
||||||
ShortUrlMeta::createEmpty()
|
ShortUrlMeta::createEmpty(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,13 +124,15 @@ class UrlShortenerTest extends TestCase
|
||||||
public function validatorIsCalledWhenUrlValidationIsEnabled(): void
|
public function validatorIsCalledWhenUrlValidationIsEnabled(): void
|
||||||
{
|
{
|
||||||
$this->setUrlShortener(true);
|
$this->setUrlShortener(true);
|
||||||
$validateUrl = $this->urlValidator->validateUrl('http://foobar.com/12345/hello?foo=bar')->will(function () {
|
$validateUrl = $this->urlValidator->validateUrl('http://foobar.com/12345/hello?foo=bar')->will(
|
||||||
});
|
function (): void {
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
$this->urlShortener->urlToShortCode(
|
$this->urlShortener->urlToShortCode(
|
||||||
new Uri('http://foobar.com/12345/hello?foo=bar'),
|
new Uri('http://foobar.com/12345/hello?foo=bar'),
|
||||||
[],
|
[],
|
||||||
ShortUrlMeta::createEmpty()
|
ShortUrlMeta::createEmpty(),
|
||||||
);
|
);
|
||||||
|
|
||||||
$validateUrl->shouldHaveBeenCalledOnce();
|
$validateUrl->shouldHaveBeenCalledOnce();
|
||||||
|
@ -151,7 +153,7 @@ class UrlShortenerTest extends TestCase
|
||||||
$this->urlShortener->urlToShortCode(
|
$this->urlShortener->urlToShortCode(
|
||||||
new Uri('http://foobar.com/12345/hello?foo=bar'),
|
new Uri('http://foobar.com/12345/hello?foo=bar'),
|
||||||
[],
|
[],
|
||||||
ShortUrlMeta::createFromRawData(['customSlug' => 'custom-slug'])
|
ShortUrlMeta::createFromRawData(['customSlug' => 'custom-slug']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +185,7 @@ class UrlShortenerTest extends TestCase
|
||||||
|
|
||||||
yield [$url, [], ShortUrlMeta::createFromRawData(['findIfExists' => true]), new ShortUrl($url)];
|
yield [$url, [], ShortUrlMeta::createFromRawData(['findIfExists' => true]), new ShortUrl($url)];
|
||||||
yield [$url, [], ShortUrlMeta::createFromRawData(
|
yield [$url, [], ShortUrlMeta::createFromRawData(
|
||||||
['findIfExists' => true, 'customSlug' => 'foo']
|
['findIfExists' => true, 'customSlug' => 'foo'],
|
||||||
), new ShortUrl($url)];
|
), new ShortUrl($url)];
|
||||||
yield [
|
yield [
|
||||||
$url,
|
$url,
|
||||||
|
|
|
@ -42,21 +42,21 @@ class VisitServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
$unlocatedVisits = map(
|
$unlocatedVisits = map(
|
||||||
range(1, 200),
|
range(1, 200),
|
||||||
fn (int $i) => new Visit(new ShortUrl(sprintf('short_code_%s', $i)), Visitor::emptyInstance())
|
fn (int $i) => new Visit(new ShortUrl(sprintf('short_code_%s', $i)), Visitor::emptyInstance()),
|
||||||
);
|
);
|
||||||
|
|
||||||
$repo = $this->prophesize(VisitRepository::class);
|
$repo = $this->prophesize(VisitRepository::class);
|
||||||
$findUnlocatedVisits = $repo->findUnlocatedVisits(false)->willReturn($unlocatedVisits);
|
$findUnlocatedVisits = $repo->findUnlocatedVisits(false)->willReturn($unlocatedVisits);
|
||||||
$getRepo = $this->em->getRepository(Visit::class)->willReturn($repo->reveal());
|
$getRepo = $this->em->getRepository(Visit::class)->willReturn($repo->reveal());
|
||||||
|
|
||||||
$persist = $this->em->persist(Argument::type(Visit::class))->will(function () {
|
$persist = $this->em->persist(Argument::type(Visit::class))->will(function (): void {
|
||||||
});
|
});
|
||||||
$flush = $this->em->flush()->will(function () {
|
$flush = $this->em->flush()->will(function (): void {
|
||||||
});
|
});
|
||||||
$clear = $this->em->clear()->will(function () {
|
$clear = $this->em->clear()->will(function (): void {
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->visitService->locateUnlocatedVisits(fn () => Location::emptyInstance(), function () {
|
$this->visitService->locateUnlocatedVisits(fn () => Location::emptyInstance(), function (): void {
|
||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
|
|
||||||
$this->assertInstanceOf(VisitLocation::class, array_shift($args));
|
$this->assertInstanceOf(VisitLocation::class, array_shift($args));
|
||||||
|
@ -84,14 +84,14 @@ class VisitServiceTest extends TestCase
|
||||||
$findUnlocatedVisits = $repo->findUnlocatedVisits(false)->willReturn($unlocatedVisits);
|
$findUnlocatedVisits = $repo->findUnlocatedVisits(false)->willReturn($unlocatedVisits);
|
||||||
$getRepo = $this->em->getRepository(Visit::class)->willReturn($repo->reveal());
|
$getRepo = $this->em->getRepository(Visit::class)->willReturn($repo->reveal());
|
||||||
|
|
||||||
$persist = $this->em->persist(Argument::type(Visit::class))->will(function () {
|
$persist = $this->em->persist(Argument::type(Visit::class))->will(function (): void {
|
||||||
});
|
});
|
||||||
$flush = $this->em->flush()->will(function () {
|
$flush = $this->em->flush()->will(function (): void {
|
||||||
});
|
});
|
||||||
$clear = $this->em->clear()->will(function () {
|
$clear = $this->em->clear()->will(function (): void {
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->visitService->locateUnlocatedVisits(function () use ($isNonLocatableAddress) {
|
$this->visitService->locateUnlocatedVisits(function () use ($isNonLocatableAddress): void {
|
||||||
throw $isNonLocatableAddress
|
throw $isNonLocatableAddress
|
||||||
? new IpCannotBeLocatedException('Cannot be located')
|
? new IpCannotBeLocatedException('Cannot be located')
|
||||||
: IpCannotBeLocatedException::forError(new Exception(''));
|
: IpCannotBeLocatedException::forError(new Exception(''));
|
||||||
|
|
|
@ -45,7 +45,7 @@ class UrlValidatorTest extends TestCase
|
||||||
$request = $this->httpClient->request(
|
$request = $this->httpClient->request(
|
||||||
RequestMethodInterface::METHOD_GET,
|
RequestMethodInterface::METHOD_GET,
|
||||||
$expectedUrl,
|
$expectedUrl,
|
||||||
[RequestOptions::ALLOW_REDIRECTS => ['max' => 15]]
|
[RequestOptions::ALLOW_REDIRECTS => ['max' => 15]],
|
||||||
)->willReturn(new Response());
|
)->willReturn(new Response());
|
||||||
|
|
||||||
$this->urlValidator->validateUrl($expectedUrl);
|
$this->urlValidator->validateUrl($expectedUrl);
|
||||||
|
|
|
@ -43,8 +43,6 @@ abstract class AbstractCreateShortUrlAction extends AbstractRestAction
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Request $request
|
|
||||||
* @return CreateShortUrlData
|
|
||||||
* @throws ValidationException
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
abstract protected function buildShortUrlData(Request $request): CreateShortUrlData;
|
abstract protected function buildShortUrlData(Request $request): CreateShortUrlData;
|
||||||
|
|
|
@ -16,8 +16,6 @@ class CreateShortUrlAction extends AbstractCreateShortUrlAction
|
||||||
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_POST];
|
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_POST];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Request $request
|
|
||||||
* @return CreateShortUrlData
|
|
||||||
* @throws ValidationException
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
protected function buildShortUrlData(Request $request): CreateShortUrlData
|
protected function buildShortUrlData(Request $request): CreateShortUrlData
|
||||||
|
@ -35,7 +33,7 @@ class CreateShortUrlAction extends AbstractCreateShortUrlAction
|
||||||
$postData['customSlug'] ?? null,
|
$postData['customSlug'] ?? null,
|
||||||
$postData['maxVisits'] ?? null,
|
$postData['maxVisits'] ?? null,
|
||||||
$postData['findIfExists'] ?? null,
|
$postData['findIfExists'] ?? null,
|
||||||
$postData['domain'] ?? null
|
$postData['domain'] ?? null,
|
||||||
);
|
);
|
||||||
|
|
||||||
return new CreateShortUrlData(new Uri($postData['longUrl']), (array) ($postData['tags'] ?? []), $meta);
|
return new CreateShortUrlData(new Uri($postData['longUrl']), (array) ($postData['tags'] ?? []), $meta);
|
||||||
|
|
|
@ -37,8 +37,6 @@ class ListShortUrlsAction extends AbstractRestAction
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Request $request
|
|
||||||
* @return Response
|
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function handle(Request $request): Response
|
public function handle(Request $request): Response
|
||||||
|
@ -46,7 +44,7 @@ class ListShortUrlsAction extends AbstractRestAction
|
||||||
$params = $this->queryToListParams($request->getQueryParams());
|
$params = $this->queryToListParams($request->getQueryParams());
|
||||||
$shortUrls = $this->shortUrlService->listShortUrls(...$params);
|
$shortUrls = $this->shortUrlService->listShortUrls(...$params);
|
||||||
return new JsonResponse(['shortUrls' => $this->serializePaginator($shortUrls, new ShortUrlDataTransformer(
|
return new JsonResponse(['shortUrls' => $this->serializePaginator($shortUrls, new ShortUrlDataTransformer(
|
||||||
$this->domainConfig
|
$this->domainConfig,
|
||||||
))]);
|
))]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +67,7 @@ class ListShortUrlsAction extends AbstractRestAction
|
||||||
{
|
{
|
||||||
return new DateRange(
|
return new DateRange(
|
||||||
isset($query['startDate']) ? Chronos::parse($query['startDate']) : null,
|
isset($query['startDate']) ? Chronos::parse($query['startDate']) : null,
|
||||||
isset($query['endDate']) ? Chronos::parse($query['endDate']) : null
|
isset($query['endDate']) ? Chronos::parse($query['endDate']) : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,6 @@ class ResolveShortUrlAction extends AbstractRestAction
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Request $request
|
|
||||||
* @return Response
|
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function handle(Request $request): Response
|
public function handle(Request $request): Response
|
||||||
|
|
|
@ -30,8 +30,6 @@ class SingleStepCreateShortUrlAction extends AbstractCreateShortUrlAction
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Request $request
|
|
||||||
* @return CreateShortUrlData
|
|
||||||
* @throws ValidationException
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
protected function buildShortUrlData(Request $request): CreateShortUrlData
|
protected function buildShortUrlData(Request $request): CreateShortUrlData
|
||||||
|
|
|
@ -28,9 +28,7 @@ class CreateTagsAction extends AbstractRestAction
|
||||||
* Process an incoming server request and return a response, optionally delegating
|
* Process an incoming server request and return a response, optionally delegating
|
||||||
* to the next middleware component to create the response.
|
* to the next middleware component to create the response.
|
||||||
*
|
*
|
||||||
* @param ServerRequestInterface $request
|
|
||||||
*
|
*
|
||||||
* @return ResponseInterface
|
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
|
|
|
@ -28,9 +28,7 @@ class DeleteTagsAction extends AbstractRestAction
|
||||||
* Process an incoming server request and return a response, optionally delegating
|
* Process an incoming server request and return a response, optionally delegating
|
||||||
* to the next middleware component to create the response.
|
* to the next middleware component to create the response.
|
||||||
*
|
*
|
||||||
* @param ServerRequestInterface $request
|
|
||||||
*
|
*
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
*/
|
||||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,9 +28,7 @@ class ListTagsAction extends AbstractRestAction
|
||||||
* Process an incoming server request and return a response, optionally delegating
|
* Process an incoming server request and return a response, optionally delegating
|
||||||
* to the next middleware component to create the response.
|
* to the next middleware component to create the response.
|
||||||
*
|
*
|
||||||
* @param ServerRequestInterface $request
|
|
||||||
*
|
*
|
||||||
* @return ResponseInterface
|
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
|
|
|
@ -29,9 +29,7 @@ class UpdateTagAction extends AbstractRestAction
|
||||||
* Process an incoming server request and return a response, optionally delegating
|
* Process an incoming server request and return a response, optionally delegating
|
||||||
* to the next middleware component to create the response.
|
* to the next middleware component to create the response.
|
||||||
*
|
*
|
||||||
* @param ServerRequestInterface $request
|
|
||||||
*
|
*
|
||||||
* @return ResponseInterface
|
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
|
|
|
@ -8,5 +8,5 @@ use Zend\ServiceManager\AbstractPluginManager;
|
||||||
|
|
||||||
class AuthenticationPluginManager extends AbstractPluginManager implements AuthenticationPluginManagerInterface
|
class AuthenticationPluginManager extends AbstractPluginManager implements AuthenticationPluginManagerInterface
|
||||||
{
|
{
|
||||||
protected $instanceOf = Plugin\AuthenticationPluginInterface::class;
|
protected $instanceOf = Plugin\AuthenticationPluginInterface::class; // phpcs:ignore
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ class RequestToHttpAuthPlugin implements RequestToHttpAuthPluginInterface
|
||||||
return array_reduce(
|
return array_reduce(
|
||||||
self::SUPPORTED_AUTH_HEADERS,
|
self::SUPPORTED_AUTH_HEADERS,
|
||||||
fn (bool $carry, string $header) => $carry || $request->hasHeader($header),
|
fn (bool $carry, string $header) => $carry || $request->hasHeader($header),
|
||||||
false
|
false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ class ConfigProvider
|
||||||
$this->loadConfig = Closure::fromCallable($loadConfig ?? fn (string $glob) => loadConfigFromGlob($glob));
|
$this->loadConfig = Closure::fromCallable($loadConfig ?? fn (string $glob) => loadConfigFromGlob($glob));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __invoke()
|
public function __invoke(): array
|
||||||
{
|
{
|
||||||
$config = ($this->loadConfig)(__DIR__ . '/../config/{,*.}config.php');
|
$config = ($this->loadConfig)(__DIR__ . '/../config/{,*.}config.php');
|
||||||
return $this->applyRoutesPrefix($config);
|
return $this->applyRoutesPrefix($config);
|
||||||
|
|
|
@ -22,7 +22,7 @@ class MissingAuthenticationException extends RuntimeException implements Problem
|
||||||
{
|
{
|
||||||
$e = new self(sprintf(
|
$e = new self(sprintf(
|
||||||
'Expected one of the following authentication headers, ["%s"], but none were provided',
|
'Expected one of the following authentication headers, ["%s"], but none were provided',
|
||||||
implode('", "', $expectedTypes)
|
implode('", "', $expectedTypes),
|
||||||
));
|
));
|
||||||
|
|
||||||
$e->detail = $e->getMessage();
|
$e->detail = $e->getMessage();
|
||||||
|
|
|
@ -23,10 +23,7 @@ class BodyParserMiddleware implements MiddlewareInterface, RequestMethodInterfac
|
||||||
* Process an incoming server request and return a response, optionally delegating
|
* Process an incoming server request and return a response, optionally delegating
|
||||||
* to the next middleware component to create the response.
|
* to the next middleware component to create the response.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
|
||||||
* @param RequestHandlerInterface $handler
|
|
||||||
*
|
*
|
||||||
* @return Response
|
|
||||||
*/
|
*/
|
||||||
public function process(Request $request, RequestHandlerInterface $handler): Response
|
public function process(Request $request, RequestHandlerInterface $handler): Response
|
||||||
{
|
{
|
||||||
|
@ -55,8 +52,6 @@ class BodyParserMiddleware implements MiddlewareInterface, RequestMethodInterfac
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Request $request
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
private function getRequestContentType(Request $request): string
|
private function getRequestContentType(Request $request): string
|
||||||
{
|
{
|
||||||
|
@ -66,8 +61,6 @@ class BodyParserMiddleware implements MiddlewareInterface, RequestMethodInterfac
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Request $request
|
|
||||||
* @return Request
|
|
||||||
*/
|
*/
|
||||||
private function parseFromJson(Request $request): Request
|
private function parseFromJson(Request $request): Request
|
||||||
{
|
{
|
||||||
|
@ -81,8 +74,6 @@ class BodyParserMiddleware implements MiddlewareInterface, RequestMethodInterfac
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Request $request
|
|
||||||
* @return Request
|
|
||||||
*/
|
*/
|
||||||
private function parseFromUrlEncoded(Request $request): Request
|
private function parseFromUrlEncoded(Request $request): Request
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,7 +9,7 @@ use Zend\Expressive\Router\Middleware\ImplicitOptionsMiddleware;
|
||||||
|
|
||||||
class EmptyResponseImplicitOptionsMiddlewareFactory
|
class EmptyResponseImplicitOptionsMiddlewareFactory
|
||||||
{
|
{
|
||||||
public function __invoke()
|
public function __invoke(): ImplicitOptionsMiddleware
|
||||||
{
|
{
|
||||||
return new ImplicitOptionsMiddleware(fn () => new EmptyResponse());
|
return new ImplicitOptionsMiddleware(fn () => new EmptyResponse());
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,37 +16,36 @@ class ShortUrlsFixture extends AbstractFixture
|
||||||
/**
|
/**
|
||||||
* Load data fixtures with the passed EntityManager
|
* Load data fixtures with the passed EntityManager
|
||||||
*
|
*
|
||||||
* @param ObjectManager $manager
|
|
||||||
*/
|
*/
|
||||||
public function load(ObjectManager $manager): void
|
public function load(ObjectManager $manager): void
|
||||||
{
|
{
|
||||||
$abcShortUrl = $this->setShortUrlDate(
|
$abcShortUrl = $this->setShortUrlDate(
|
||||||
new ShortUrl('https://shlink.io', ShortUrlMeta::createFromRawData(['customSlug' => 'abc123'])),
|
new ShortUrl('https://shlink.io', ShortUrlMeta::createFromRawData(['customSlug' => 'abc123'])),
|
||||||
'2018-05-01'
|
'2018-05-01',
|
||||||
);
|
);
|
||||||
$manager->persist($abcShortUrl);
|
$manager->persist($abcShortUrl);
|
||||||
|
|
||||||
$defShortUrl = $this->setShortUrlDate(new ShortUrl(
|
$defShortUrl = $this->setShortUrlDate(new ShortUrl(
|
||||||
'https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/',
|
'https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/',
|
||||||
ShortUrlMeta::createFromParams(Chronos::parse('2020-05-01'), null, 'def456')
|
ShortUrlMeta::createFromParams(Chronos::parse('2020-05-01'), null, 'def456'),
|
||||||
), '2019-01-01 00:00:10');
|
), '2019-01-01 00:00:10');
|
||||||
$manager->persist($defShortUrl);
|
$manager->persist($defShortUrl);
|
||||||
|
|
||||||
$customShortUrl = $this->setShortUrlDate(new ShortUrl(
|
$customShortUrl = $this->setShortUrlDate(new ShortUrl(
|
||||||
'https://shlink.io',
|
'https://shlink.io',
|
||||||
ShortUrlMeta::createFromParams(null, null, 'custom', 2)
|
ShortUrlMeta::createFromParams(null, null, 'custom', 2),
|
||||||
), '2019-01-01 00:00:20');
|
), '2019-01-01 00:00:20');
|
||||||
$manager->persist($customShortUrl);
|
$manager->persist($customShortUrl);
|
||||||
|
|
||||||
$withDomainShortUrl = $this->setShortUrlDate(new ShortUrl(
|
$withDomainShortUrl = $this->setShortUrlDate(new ShortUrl(
|
||||||
'https://blog.alejandrocelaya.com/2019/04/27/considerations-to-properly-use-open-source-software-projects/',
|
'https://blog.alejandrocelaya.com/2019/04/27/considerations-to-properly-use-open-source-software-projects/',
|
||||||
ShortUrlMeta::createFromRawData(['domain' => 'example.com', 'customSlug' => 'ghi789'])
|
ShortUrlMeta::createFromRawData(['domain' => 'example.com', 'customSlug' => 'ghi789']),
|
||||||
), '2019-01-01 00:00:30');
|
), '2019-01-01 00:00:30');
|
||||||
$manager->persist($withDomainShortUrl);
|
$manager->persist($withDomainShortUrl);
|
||||||
|
|
||||||
$withDomainAndSlugShortUrl = $this->setShortUrlDate(new ShortUrl(
|
$withDomainAndSlugShortUrl = $this->setShortUrlDate(new ShortUrl(
|
||||||
'https://google.com',
|
'https://google.com',
|
||||||
ShortUrlMeta::createFromRawData(['domain' => 'some-domain.com', 'customSlug' => 'custom-with-domain'])
|
ShortUrlMeta::createFromRawData(['domain' => 'some-domain.com', 'customSlug' => 'custom-with-domain']),
|
||||||
), '2018-10-20');
|
), '2018-10-20');
|
||||||
$manager->persist($withDomainAndSlugShortUrl);
|
$manager->persist($withDomainAndSlugShortUrl);
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ class AuthenticationTest extends ApiTestCase
|
||||||
{
|
{
|
||||||
$expectedDetail = sprintf(
|
$expectedDetail = sprintf(
|
||||||
'Expected one of the following authentication headers, ["%s"], but none were provided',
|
'Expected one of the following authentication headers, ["%s"], but none were provided',
|
||||||
implode('", "', RequestToHttpAuthPlugin::SUPPORTED_AUTH_HEADERS)
|
implode('", "', RequestToHttpAuthPlugin::SUPPORTED_AUTH_HEADERS),
|
||||||
);
|
);
|
||||||
|
|
||||||
$resp = $this->callApi(self::METHOD_GET, '/short-urls');
|
$resp = $this->callApi(self::METHOD_GET, '/short-urls');
|
||||||
|
|
|
@ -25,7 +25,7 @@ class HealthActionTest extends TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function passResponseIsReturnedWhenConnectionSucceeds()
|
public function passResponseIsReturnedWhenConnectionSucceeds(): void
|
||||||
{
|
{
|
||||||
$ping = $this->conn->ping()->willReturn(true);
|
$ping = $this->conn->ping()->willReturn(true);
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ class HealthActionTest extends TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function failResponseIsReturnedWhenConnectionFails()
|
public function failResponseIsReturnedWhenConnectionFails(): void
|
||||||
{
|
{
|
||||||
$ping = $this->conn->ping()->willReturn(false);
|
$ping = $this->conn->ping()->willReturn(false);
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ class HealthActionTest extends TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function failResponseIsReturnedWhenConnectionThrowsException()
|
public function failResponseIsReturnedWhenConnectionThrowsException(): void
|
||||||
{
|
{
|
||||||
$ping = $this->conn->ping()->willThrow(Exception::class);
|
$ping = $this->conn->ping()->willThrow(Exception::class);
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ class CreateShortUrlActionTest extends TestCase
|
||||||
$shorten = $this->urlShortener->urlToShortCode(
|
$shorten = $this->urlShortener->urlToShortCode(
|
||||||
Argument::type(Uri::class),
|
Argument::type(Uri::class),
|
||||||
Argument::type('array'),
|
Argument::type('array'),
|
||||||
$expectedMeta
|
$expectedMeta,
|
||||||
)->willReturn($shortUrl);
|
)->willReturn($shortUrl);
|
||||||
|
|
||||||
$request = ServerRequestFactory::fromGlobals()->withParsedBody($body);
|
$request = ServerRequestFactory::fromGlobals()->withParsedBody($body);
|
||||||
|
|
|
@ -25,7 +25,7 @@ class DeleteShortUrlActionTest extends TestCase
|
||||||
/** @test */
|
/** @test */
|
||||||
public function emptyResponseIsReturnedIfProperlyDeleted(): void
|
public function emptyResponseIsReturnedIfProperlyDeleted(): void
|
||||||
{
|
{
|
||||||
$deleteByShortCode = $this->service->deleteByShortCode(Argument::any())->will(function () {
|
$deleteByShortCode = $this->service->deleteByShortCode(Argument::any())->will(function (): void {
|
||||||
});
|
});
|
||||||
|
|
||||||
$resp = $this->action->handle(new ServerRequest());
|
$resp = $this->action->handle(new ServerRequest());
|
||||||
|
|
|
@ -44,7 +44,7 @@ class EditShortUrlActionTest extends TestCase
|
||||||
'maxVisits' => 5,
|
'maxVisits' => 5,
|
||||||
]);
|
]);
|
||||||
$updateMeta = $this->shortUrlService->updateMetadataByShortCode(Argument::cetera())->willReturn(
|
$updateMeta = $this->shortUrlService->updateMetadataByShortCode(Argument::cetera())->willReturn(
|
||||||
new ShortUrl('')
|
new ShortUrl(''),
|
||||||
);
|
);
|
||||||
|
|
||||||
$resp = $this->action->handle($request);
|
$resp = $this->action->handle($request);
|
||||||
|
|
|
@ -39,7 +39,7 @@ class EditShortUrlTagsActionTest extends TestCase
|
||||||
|
|
||||||
$response = $this->action->handle(
|
$response = $this->action->handle(
|
||||||
(new ServerRequest())->withAttribute('shortCode', 'abc123')
|
(new ServerRequest())->withAttribute('shortCode', 'abc123')
|
||||||
->withParsedBody(['tags' => []])
|
->withParsedBody(['tags' => []]),
|
||||||
);
|
);
|
||||||
$this->assertEquals(200, $response->getStatusCode());
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ class ListShortUrlsActionTest extends TestCase
|
||||||
$expectedSearchTerm,
|
$expectedSearchTerm,
|
||||||
$expectedTags,
|
$expectedTags,
|
||||||
$expectedOrderBy,
|
$expectedOrderBy,
|
||||||
$expectedDateRange
|
$expectedDateRange,
|
||||||
)->willReturn(new Paginator(new ArrayAdapter()));
|
)->willReturn(new Paginator(new ArrayAdapter()));
|
||||||
|
|
||||||
/** @var JsonResponse $response */
|
/** @var JsonResponse $response */
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue