mirror of
https://github.com/shlinkio/shlink.git
synced 2025-02-25 18:45:27 -06:00
Merge pull request #2313 from acelaya-forks/feature/qr-disable-logo
Allow QR code logo to be individually disabled
This commit is contained in:
commit
83570f5c25
@ -18,6 +18,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this
|
||||
|
||||
All [URI-reserved characters](https://datatracker.ietf.org/doc/html/rfc3986#section-2.2) were disallowed up until now, but from now on, only the gen-delimiters are.
|
||||
|
||||
* [#2229](https://github.com/shlinkio/shlink/issues/2229) Add `logo=disabled` query param to dynamically disable the default logo on QR codes.
|
||||
|
||||
### Changed
|
||||
* [#2281](https://github.com/shlinkio/shlink/issues/2281) Update docker image to PHP 8.4
|
||||
* [#2124](https://github.com/shlinkio/shlink/issues/2124) Improve how Shlink decides if a GeoLite db file needs to be downloaded, and reduces the chances for API limits to be reached.
|
||||
|
@ -85,6 +85,16 @@
|
||||
"type": "string",
|
||||
"default": "#ffffff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "logo",
|
||||
"in": "query",
|
||||
"description": "Currently used to disable the logo that was set via configuration options. It may be used in future to dynamically choose from multiple logos.",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"enum": ["disable"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
|
@ -28,20 +28,21 @@ use function trim;
|
||||
use const Shlinkio\Shlink\DEFAULT_QR_CODE_BG_COLOR;
|
||||
use const Shlinkio\Shlink\DEFAULT_QR_CODE_COLOR;
|
||||
|
||||
final class QrCodeParams
|
||||
final readonly class QrCodeParams
|
||||
{
|
||||
private const int MIN_SIZE = 50;
|
||||
private const int MAX_SIZE = 1000;
|
||||
private const array SUPPORTED_FORMATS = ['png', 'svg'];
|
||||
|
||||
private function __construct(
|
||||
public readonly int $size,
|
||||
public readonly int $margin,
|
||||
public readonly WriterInterface $writer,
|
||||
public readonly ErrorCorrectionLevel $errorCorrectionLevel,
|
||||
public readonly RoundBlockSizeMode $roundBlockSizeMode,
|
||||
public readonly ColorInterface $color,
|
||||
public readonly ColorInterface $bgColor,
|
||||
public int $size,
|
||||
public int $margin,
|
||||
public WriterInterface $writer,
|
||||
public ErrorCorrectionLevel $errorCorrectionLevel,
|
||||
public RoundBlockSizeMode $roundBlockSizeMode,
|
||||
public ColorInterface $color,
|
||||
public ColorInterface $bgColor,
|
||||
public bool $disableLogo,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -57,6 +58,7 @@ final class QrCodeParams
|
||||
roundBlockSizeMode: self::resolveRoundBlockSize($query, $defaults),
|
||||
color: self::resolveColor($query, $defaults),
|
||||
bgColor: self::resolveBackgroundColor($query, $defaults),
|
||||
disableLogo: isset($query['logo']) && $query['logo'] === 'disable',
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ readonly class QrCodeAction implements MiddlewareInterface
|
||||
private function buildQrCode(Builder $qrCodeBuilder, QrCodeParams $params): ResultInterface
|
||||
{
|
||||
$logoUrl = $this->options->logoUrl;
|
||||
if ($logoUrl === null) {
|
||||
if ($logoUrl === null || $params->disableLogo) {
|
||||
return $qrCodeBuilder->build();
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ use Laminas\Diactoros\ServerRequest;
|
||||
use Laminas\Diactoros\ServerRequestFactory;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\Attributes\TestWith;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
@ -294,11 +295,16 @@ class QrCodeActionTest extends TestCase
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function logoIsAddedToQrCodeIfOptionIsDefined(): void
|
||||
#[TestWith([[], '4696E5'])] // The logo has Shlink's brand color
|
||||
#[TestWith([['logo' => 'invalid'], '4696E5'])] // Invalid `logo` values are ignored. Default logo is still rendered
|
||||
#[TestWith([['logo' => 'disable'], '000000'])] // No logo will be added if explicitly disabled
|
||||
public function logoIsAddedToQrCodeIfOptionIsDefined(array $query, string $expectedColor): void
|
||||
{
|
||||
$logoUrl = 'https://avatars.githubusercontent.com/u/20341790?v=4'; // Shlink logo
|
||||
$logoUrl = 'https://avatars.githubusercontent.com/u/20341790?v=4'; // Shlink's logo
|
||||
$code = 'abc123';
|
||||
$req = ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $code);
|
||||
$req = ServerRequestFactory::fromGlobals()
|
||||
->withAttribute('shortCode', $code)
|
||||
->withQueryParams($query);
|
||||
|
||||
$this->urlResolver->method('resolveEnabledShortUrl')->with(
|
||||
ShortUrlIdentifier::fromShortCodeAndDomain($code),
|
||||
@ -309,9 +315,9 @@ class QrCodeActionTest extends TestCase
|
||||
$image = imagecreatefromstring($resp->getBody()->__toString());
|
||||
self::assertNotFalse($image);
|
||||
|
||||
// At around 100x100 px we can already find the logo, which has Shlink's brand color
|
||||
// At around 100x100 px we can already find the logo, if present
|
||||
$resultingColor = imagecolorat($image, 100, 100);
|
||||
self::assertEquals(hexdec('4696E5'), $resultingColor);
|
||||
self::assertEquals(hexdec($expectedColor), $resultingColor);
|
||||
}
|
||||
|
||||
public static function provideEnabled(): iterable
|
||||
|
Loading…
Reference in New Issue
Block a user