mirror of
https://github.com/shlinkio/shlink.git
synced 2025-02-17 07:49:54 +03:00
Added new config to set custom defaults for QR codes
This commit is contained in:
parent
cbec4a4e81
commit
6a1ee2b894
7 changed files with 174 additions and 31 deletions
21
config/autoload/qr-codes.global.php
Normal file
21
config/autoload/qr-codes.global.php
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use function Shlinkio\Shlink\Common\env;
|
||||||
|
|
||||||
|
use const Shlinkio\Shlink\DEFAULT_QR_CODE_ERROR_CORRECTION;
|
||||||
|
use const Shlinkio\Shlink\DEFAULT_QR_CODE_FORMAT;
|
||||||
|
use const Shlinkio\Shlink\DEFAULT_QR_CODE_MARGIN;
|
||||||
|
use const Shlinkio\Shlink\DEFAULT_QR_CODE_SIZE;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
'qr_codes' => [
|
||||||
|
'size' => (int) env('DEFAULT_QR_CODE_SIZE', DEFAULT_QR_CODE_SIZE),
|
||||||
|
'margin' => (int) env('DEFAULT_QR_CODE_MARGIN', DEFAULT_QR_CODE_MARGIN),
|
||||||
|
'format' => env('DEFAULT_QR_CODE_FORMAT', DEFAULT_QR_CODE_FORMAT),
|
||||||
|
'error_correction' => env('DEFAULT_QR_CODE_ERROR_CORRECTION', DEFAULT_QR_CODE_ERROR_CORRECTION),
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
|
@ -14,3 +14,7 @@ const DEFAULT_REDIRECT_CACHE_LIFETIME = 30;
|
||||||
const LOCAL_LOCK_FACTORY = 'Shlinkio\Shlink\LocalLockFactory';
|
const LOCAL_LOCK_FACTORY = 'Shlinkio\Shlink\LocalLockFactory';
|
||||||
const CUSTOM_SLUGS_REGEXP = '/[^\pL\pN._~]/u'; // Any unicode letter or number, plus ".", "_" and "~" chars
|
const CUSTOM_SLUGS_REGEXP = '/[^\pL\pN._~]/u'; // Any unicode letter or number, plus ".", "_" and "~" chars
|
||||||
const TITLE_TAG_VALUE = '/<title[^>]*>(.*?)<\/title>/i'; // Matches the value inside an html title tag
|
const TITLE_TAG_VALUE = '/<title[^>]*>(.*?)<\/title>/i'; // Matches the value inside an html title tag
|
||||||
|
const DEFAULT_QR_CODE_SIZE = 300;
|
||||||
|
const DEFAULT_QR_CODE_MARGIN = 0;
|
||||||
|
const DEFAULT_QR_CODE_FORMAT = 'png';
|
||||||
|
const DEFAULT_QR_CODE_ERROR_CORRECTION = 'l';
|
||||||
|
|
|
@ -25,6 +25,7 @@ return [
|
||||||
Options\NotFoundRedirectOptions::class => ConfigAbstractFactory::class,
|
Options\NotFoundRedirectOptions::class => ConfigAbstractFactory::class,
|
||||||
Options\UrlShortenerOptions::class => ConfigAbstractFactory::class,
|
Options\UrlShortenerOptions::class => ConfigAbstractFactory::class,
|
||||||
Options\TrackingOptions::class => ConfigAbstractFactory::class,
|
Options\TrackingOptions::class => ConfigAbstractFactory::class,
|
||||||
|
Options\QrCodeOptions::class => ConfigAbstractFactory::class,
|
||||||
|
|
||||||
Service\UrlShortener::class => ConfigAbstractFactory::class,
|
Service\UrlShortener::class => ConfigAbstractFactory::class,
|
||||||
Service\ShortUrlService::class => ConfigAbstractFactory::class,
|
Service\ShortUrlService::class => ConfigAbstractFactory::class,
|
||||||
|
@ -86,6 +87,7 @@ return [
|
||||||
Options\NotFoundRedirectOptions::class => ['config.not_found_redirects'],
|
Options\NotFoundRedirectOptions::class => ['config.not_found_redirects'],
|
||||||
Options\UrlShortenerOptions::class => ['config.url_shortener'],
|
Options\UrlShortenerOptions::class => ['config.url_shortener'],
|
||||||
Options\TrackingOptions::class => ['config.tracking'],
|
Options\TrackingOptions::class => ['config.tracking'],
|
||||||
|
Options\QrCodeOptions::class => ['config.qr_codes'],
|
||||||
|
|
||||||
Service\UrlShortener::class => [
|
Service\UrlShortener::class => [
|
||||||
ShortUrl\Helper\ShortUrlTitleResolutionHelper::class,
|
ShortUrl\Helper\ShortUrlTitleResolutionHelper::class,
|
||||||
|
@ -138,6 +140,7 @@ return [
|
||||||
Service\ShortUrl\ShortUrlResolver::class,
|
Service\ShortUrl\ShortUrlResolver::class,
|
||||||
ShortUrl\Helper\ShortUrlStringifier::class,
|
ShortUrl\Helper\ShortUrlStringifier::class,
|
||||||
'Logger_Shlink',
|
'Logger_Shlink',
|
||||||
|
Options\QrCodeOptions::class,
|
||||||
],
|
],
|
||||||
Action\RobotsAction::class => [Crawling\CrawlingHelper::class],
|
Action\RobotsAction::class => [Crawling\CrawlingHelper::class],
|
||||||
|
|
||||||
|
|
|
@ -14,15 +14,17 @@ use Endroid\QrCode\Writer\SvgWriter;
|
||||||
use Endroid\QrCode\Writer\WriterInterface;
|
use Endroid\QrCode\Writer\WriterInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
|
use Shlinkio\Shlink\Core\Options\QrCodeOptions;
|
||||||
|
|
||||||
|
use function Functional\contains;
|
||||||
use function strtolower;
|
use function strtolower;
|
||||||
use function trim;
|
use function trim;
|
||||||
|
|
||||||
final class QrCodeParams
|
final class QrCodeParams
|
||||||
{
|
{
|
||||||
private const DEFAULT_SIZE = 300;
|
|
||||||
private const MIN_SIZE = 50;
|
private const MIN_SIZE = 50;
|
||||||
private const MAX_SIZE = 1000;
|
private const MAX_SIZE = 1000;
|
||||||
|
private const SUPPORTED_FORMATS = ['png', 'svg'];
|
||||||
|
|
||||||
private function __construct(
|
private function __construct(
|
||||||
private int $size,
|
private int $size,
|
||||||
|
@ -32,22 +34,22 @@ final class QrCodeParams
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function fromRequest(ServerRequestInterface $request): self
|
public static function fromRequest(ServerRequestInterface $request, QrCodeOptions $defaults): self
|
||||||
{
|
{
|
||||||
$query = $request->getQueryParams();
|
$query = $request->getQueryParams();
|
||||||
|
|
||||||
return new self(
|
return new self(
|
||||||
self::resolveSize($request, $query),
|
self::resolveSize($request, $query, $defaults),
|
||||||
self::resolveMargin($query),
|
self::resolveMargin($query, $defaults),
|
||||||
self::resolveWriter($query),
|
self::resolveWriter($query, $defaults),
|
||||||
self::resolveErrorCorrection($query),
|
self::resolveErrorCorrection($query, $defaults),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function resolveSize(Request $request, array $query): int
|
private static function resolveSize(Request $request, array $query, QrCodeOptions $defaults): int
|
||||||
{
|
{
|
||||||
// FIXME Size attribute is deprecated. After v3.0.0, always use the query param instead
|
// FIXME Size attribute is deprecated. After v3.0.0, always use the query param instead
|
||||||
$size = (int) $request->getAttribute('size', $query['size'] ?? self::DEFAULT_SIZE);
|
$size = (int) $request->getAttribute('size', $query['size'] ?? $defaults->size());
|
||||||
if ($size < self::MIN_SIZE) {
|
if ($size < self::MIN_SIZE) {
|
||||||
return self::MIN_SIZE;
|
return self::MIN_SIZE;
|
||||||
}
|
}
|
||||||
|
@ -55,13 +57,9 @@ final class QrCodeParams
|
||||||
return $size > self::MAX_SIZE ? self::MAX_SIZE : $size;
|
return $size > self::MAX_SIZE ? self::MAX_SIZE : $size;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function resolveMargin(array $query): int
|
private static function resolveMargin(array $query, QrCodeOptions $defaults): int
|
||||||
{
|
{
|
||||||
$margin = $query['margin'] ?? null;
|
$margin = $query['margin'] ?? (string) $defaults->margin();
|
||||||
if ($margin === null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$intMargin = (int) $margin;
|
$intMargin = (int) $margin;
|
||||||
if ($margin !== (string) $intMargin) {
|
if ($margin !== (string) $intMargin) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -70,18 +68,20 @@ final class QrCodeParams
|
||||||
return $intMargin < 0 ? 0 : $intMargin;
|
return $intMargin < 0 ? 0 : $intMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function resolveWriter(array $query): WriterInterface
|
private static function resolveWriter(array $query, QrCodeOptions $defaults): WriterInterface
|
||||||
{
|
{
|
||||||
$format = strtolower(trim($query['format'] ?? 'png'));
|
$qFormat = self::normalizeParam($query['format'] ?? '');
|
||||||
|
$format = contains(self::SUPPORTED_FORMATS, $qFormat) ? $qFormat : self::normalizeParam($defaults->format());
|
||||||
|
|
||||||
return match ($format) {
|
return match ($format) {
|
||||||
'svg' => new SvgWriter(),
|
'svg' => new SvgWriter(),
|
||||||
default => new PngWriter(),
|
default => new PngWriter(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function resolveErrorCorrection(array $query): ErrorCorrectionLevelInterface
|
private static function resolveErrorCorrection(array $query, QrCodeOptions $defaults): ErrorCorrectionLevelInterface
|
||||||
{
|
{
|
||||||
$errorCorrectionLevel = strtolower(trim($query['errorCorrection'] ?? 'l'));
|
$errorCorrectionLevel = self::normalizeParam($query['errorCorrection'] ?? $defaults->errorCorrection());
|
||||||
return match ($errorCorrectionLevel) {
|
return match ($errorCorrectionLevel) {
|
||||||
'h' => new ErrorCorrectionLevelHigh(),
|
'h' => new ErrorCorrectionLevelHigh(),
|
||||||
'q' => new ErrorCorrectionLevelQuartile(),
|
'q' => new ErrorCorrectionLevelQuartile(),
|
||||||
|
@ -90,6 +90,11 @@ final class QrCodeParams
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function normalizeParam(string $param): string
|
||||||
|
{
|
||||||
|
return strtolower(trim($param));
|
||||||
|
}
|
||||||
|
|
||||||
public function size(): int
|
public function size(): int
|
||||||
{
|
{
|
||||||
return $this->size;
|
return $this->size;
|
||||||
|
|
|
@ -14,6 +14,7 @@ use Shlinkio\Shlink\Common\Response\QrCodeResponse;
|
||||||
use Shlinkio\Shlink\Core\Action\Model\QrCodeParams;
|
use Shlinkio\Shlink\Core\Action\Model\QrCodeParams;
|
||||||
use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
|
use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
|
||||||
use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier;
|
use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier;
|
||||||
|
use Shlinkio\Shlink\Core\Options\QrCodeOptions;
|
||||||
use Shlinkio\Shlink\Core\Service\ShortUrl\ShortUrlResolverInterface;
|
use Shlinkio\Shlink\Core\Service\ShortUrl\ShortUrlResolverInterface;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifierInterface;
|
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifierInterface;
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@ class QrCodeAction implements MiddlewareInterface
|
||||||
private ShortUrlResolverInterface $urlResolver,
|
private ShortUrlResolverInterface $urlResolver,
|
||||||
private ShortUrlStringifierInterface $stringifier,
|
private ShortUrlStringifierInterface $stringifier,
|
||||||
private LoggerInterface $logger,
|
private LoggerInterface $logger,
|
||||||
|
private QrCodeOptions $defaultOptions,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +39,7 @@ class QrCodeAction implements MiddlewareInterface
|
||||||
return $handler->handle($request);
|
return $handler->handle($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
$params = QrCodeParams::fromRequest($request);
|
$params = QrCodeParams::fromRequest($request, $this->defaultOptions);
|
||||||
$qrCodeBuilder = Builder::create()
|
$qrCodeBuilder = Builder::create()
|
||||||
->data($this->stringifier->stringify($shortUrl))
|
->data($this->stringifier->stringify($shortUrl))
|
||||||
->size($params->size())
|
->size($params->size())
|
||||||
|
|
60
module/Core/src/Options/QrCodeOptions.php
Normal file
60
module/Core/src/Options/QrCodeOptions.php
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Shlinkio\Shlink\Core\Options;
|
||||||
|
|
||||||
|
use Laminas\Stdlib\AbstractOptions;
|
||||||
|
|
||||||
|
use const Shlinkio\Shlink\DEFAULT_QR_CODE_ERROR_CORRECTION;
|
||||||
|
use const Shlinkio\Shlink\DEFAULT_QR_CODE_FORMAT;
|
||||||
|
use const Shlinkio\Shlink\DEFAULT_QR_CODE_MARGIN;
|
||||||
|
use const Shlinkio\Shlink\DEFAULT_QR_CODE_SIZE;
|
||||||
|
|
||||||
|
class QrCodeOptions extends AbstractOptions
|
||||||
|
{
|
||||||
|
private int $size = DEFAULT_QR_CODE_SIZE;
|
||||||
|
private int $margin = DEFAULT_QR_CODE_MARGIN;
|
||||||
|
private string $format = DEFAULT_QR_CODE_FORMAT;
|
||||||
|
private string $errorCorrection = DEFAULT_QR_CODE_ERROR_CORRECTION;
|
||||||
|
|
||||||
|
public function size(): int
|
||||||
|
{
|
||||||
|
return $this->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setSize(int $size): void
|
||||||
|
{
|
||||||
|
$this->size = $size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function margin(): int
|
||||||
|
{
|
||||||
|
return $this->margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setMargin(int $margin): void
|
||||||
|
{
|
||||||
|
$this->margin = $margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function format(): string
|
||||||
|
{
|
||||||
|
return $this->format;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setFormat(string $format): void
|
||||||
|
{
|
||||||
|
$this->format = $format;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function errorCorrection(): string
|
||||||
|
{
|
||||||
|
return $this->errorCorrection;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setErrorCorrection(string $errorCorrection): void
|
||||||
|
{
|
||||||
|
$this->errorCorrection = $errorCorrection;
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ use Shlinkio\Shlink\Core\Action\QrCodeAction;
|
||||||
use Shlinkio\Shlink\Core\Entity\ShortUrl;
|
use Shlinkio\Shlink\Core\Entity\ShortUrl;
|
||||||
use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
|
use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
|
||||||
use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier;
|
use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier;
|
||||||
|
use Shlinkio\Shlink\Core\Options\QrCodeOptions;
|
||||||
use Shlinkio\Shlink\Core\Service\ShortUrl\ShortUrlResolverInterface;
|
use Shlinkio\Shlink\Core\Service\ShortUrl\ShortUrlResolverInterface;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifier;
|
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifier;
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ class QrCodeActionTest extends TestCase
|
||||||
|
|
||||||
private QrCodeAction $action;
|
private QrCodeAction $action;
|
||||||
private ObjectProphecy $urlResolver;
|
private ObjectProphecy $urlResolver;
|
||||||
|
private QrCodeOptions $options;
|
||||||
|
|
||||||
public function setUp(): void
|
public function setUp(): void
|
||||||
{
|
{
|
||||||
|
@ -38,11 +40,13 @@ class QrCodeActionTest extends TestCase
|
||||||
$router->generateUri(Argument::cetera())->willReturn('/foo/bar');
|
$router->generateUri(Argument::cetera())->willReturn('/foo/bar');
|
||||||
|
|
||||||
$this->urlResolver = $this->prophesize(ShortUrlResolverInterface::class);
|
$this->urlResolver = $this->prophesize(ShortUrlResolverInterface::class);
|
||||||
|
$this->options = new QrCodeOptions();
|
||||||
|
|
||||||
$this->action = new QrCodeAction(
|
$this->action = new QrCodeAction(
|
||||||
$this->urlResolver->reveal(),
|
$this->urlResolver->reveal(),
|
||||||
new ShortUrlStringifier(['domain' => 'doma.in']),
|
new ShortUrlStringifier(['domain' => 'doma.in']),
|
||||||
new NullLogger(),
|
new NullLogger(),
|
||||||
|
$this->options,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,9 +89,11 @@ class QrCodeActionTest extends TestCase
|
||||||
* @dataProvider provideQueries
|
* @dataProvider provideQueries
|
||||||
*/
|
*/
|
||||||
public function imageIsReturnedWithExpectedContentTypeBasedOnProvidedFormat(
|
public function imageIsReturnedWithExpectedContentTypeBasedOnProvidedFormat(
|
||||||
|
string $defaultFormat,
|
||||||
array $query,
|
array $query,
|
||||||
string $expectedContentType,
|
string $expectedContentType,
|
||||||
): void {
|
): void {
|
||||||
|
$this->options->setFromArray(['format' => $defaultFormat]);
|
||||||
$code = 'abc123';
|
$code = 'abc123';
|
||||||
$this->urlResolver->resolveEnabledShortUrl(new ShortUrlIdentifier($code, ''))->willReturn(
|
$this->urlResolver->resolveEnabledShortUrl(new ShortUrlIdentifier($code, ''))->willReturn(
|
||||||
ShortUrl::createEmpty(),
|
ShortUrl::createEmpty(),
|
||||||
|
@ -102,18 +108,26 @@ class QrCodeActionTest extends TestCase
|
||||||
|
|
||||||
public function provideQueries(): iterable
|
public function provideQueries(): iterable
|
||||||
{
|
{
|
||||||
yield 'no format' => [[], 'image/png'];
|
yield 'no format, png default' => ['png', [], 'image/png'];
|
||||||
yield 'png format' => [['format' => 'png'], 'image/png'];
|
yield 'no format, svg default' => ['svg', [], 'image/svg+xml'];
|
||||||
yield 'svg format' => [['format' => 'svg'], 'image/svg+xml'];
|
yield 'png format, png default' => ['png', ['format' => 'png'], 'image/png'];
|
||||||
yield 'unsupported format' => [['format' => 'jpg'], 'image/png'];
|
yield 'png format, svg default' => ['svg', ['format' => 'png'], 'image/png'];
|
||||||
|
yield 'svg format, png default' => ['png', ['format' => 'svg'], 'image/svg+xml'];
|
||||||
|
yield 'svg format, svg default' => ['svg', ['format' => 'svg'], 'image/svg+xml'];
|
||||||
|
yield 'unsupported format, png default' => ['png', ['format' => 'jpg'], 'image/png'];
|
||||||
|
yield 'unsupported format, svg default' => ['svg', ['format' => 'jpg'], 'image/svg+xml'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @dataProvider provideRequestsWithSize
|
* @dataProvider provideRequestsWithSize
|
||||||
*/
|
*/
|
||||||
public function imageIsReturnedWithExpectedSize(ServerRequestInterface $req, int $expectedSize): void
|
public function imageIsReturnedWithExpectedSize(
|
||||||
{
|
array $defaults,
|
||||||
|
ServerRequestInterface $req,
|
||||||
|
int $expectedSize,
|
||||||
|
): void {
|
||||||
|
$this->options->setFromArray($defaults);
|
||||||
$code = 'abc123';
|
$code = 'abc123';
|
||||||
$this->urlResolver->resolveEnabledShortUrl(new ShortUrlIdentifier($code, ''))->willReturn(
|
$this->urlResolver->resolveEnabledShortUrl(new ShortUrlIdentifier($code, ''))->willReturn(
|
||||||
ShortUrl::createEmpty(),
|
ShortUrl::createEmpty(),
|
||||||
|
@ -128,25 +142,59 @@ class QrCodeActionTest extends TestCase
|
||||||
|
|
||||||
public function provideRequestsWithSize(): iterable
|
public function provideRequestsWithSize(): iterable
|
||||||
{
|
{
|
||||||
yield 'no size' => [ServerRequestFactory::fromGlobals(), 300];
|
yield 'different margin and size defaults' => [
|
||||||
yield 'size in attr' => [ServerRequestFactory::fromGlobals()->withAttribute('size', '400'), 400];
|
['size' => 660, 'margin' => 40],
|
||||||
yield 'size in query' => [ServerRequestFactory::fromGlobals()->withQueryParams(['size' => '123']), 123];
|
ServerRequestFactory::fromGlobals(),
|
||||||
|
740,
|
||||||
|
];
|
||||||
|
yield 'no size' => [[], ServerRequestFactory::fromGlobals(), 300];
|
||||||
|
yield 'no size, different default' => [['size' => 500], ServerRequestFactory::fromGlobals(), 500];
|
||||||
|
yield 'size in attr' => [[], ServerRequestFactory::fromGlobals()->withAttribute('size', '400'), 400];
|
||||||
|
yield 'size in query' => [[], ServerRequestFactory::fromGlobals()->withQueryParams(['size' => '123']), 123];
|
||||||
|
yield 'size in query, default margin' => [
|
||||||
|
['margin' => 25],
|
||||||
|
ServerRequestFactory::fromGlobals()->withQueryParams(['size' => '123']),
|
||||||
|
173,
|
||||||
|
];
|
||||||
yield 'size in query and attr' => [
|
yield 'size in query and attr' => [
|
||||||
|
[],
|
||||||
ServerRequestFactory::fromGlobals()->withAttribute('size', '350')->withQueryParams(['size' => '123']),
|
ServerRequestFactory::fromGlobals()->withAttribute('size', '350')->withQueryParams(['size' => '123']),
|
||||||
350,
|
350,
|
||||||
];
|
];
|
||||||
yield 'margin' => [ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => '35']), 370];
|
yield 'margin' => [[], ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => '35']), 370];
|
||||||
|
yield 'margin and different default' => [
|
||||||
|
['size' => 400],
|
||||||
|
ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => '35']),
|
||||||
|
470,
|
||||||
|
];
|
||||||
yield 'margin and size' => [
|
yield 'margin and size' => [
|
||||||
|
[],
|
||||||
ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => '100', 'size' => '200']),
|
ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => '100', 'size' => '200']),
|
||||||
400,
|
400,
|
||||||
];
|
];
|
||||||
yield 'negative margin' => [ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => '-50']), 300];
|
yield 'negative margin' => [[], ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => '-50']), 300];
|
||||||
yield 'non-numeric margin' => [ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => 'foo']), 300];
|
yield 'negative margin, default margin' => [
|
||||||
|
['margin' => 10],
|
||||||
|
ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => '-50']),
|
||||||
|
300,
|
||||||
|
];
|
||||||
|
yield 'non-numeric margin' => [
|
||||||
|
[],
|
||||||
|
ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => 'foo']),
|
||||||
|
300,
|
||||||
|
];
|
||||||
yield 'negative margin and size' => [
|
yield 'negative margin and size' => [
|
||||||
|
[],
|
||||||
|
ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => '-1', 'size' => '150']),
|
||||||
|
150,
|
||||||
|
];
|
||||||
|
yield 'negative margin and size, default margin' => [
|
||||||
|
['margin' => 5],
|
||||||
ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => '-1', 'size' => '150']),
|
ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => '-1', 'size' => '150']),
|
||||||
150,
|
150,
|
||||||
];
|
];
|
||||||
yield 'non-numeric margin and size' => [
|
yield 'non-numeric margin and size' => [
|
||||||
|
[],
|
||||||
ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => 'foo', 'size' => '538']),
|
ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => 'foo', 'size' => '538']),
|
||||||
538,
|
538,
|
||||||
];
|
];
|
||||||
|
|
Loading…
Add table
Reference in a new issue