Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/qr margin #1006

Merged
merged 2 commits into from Feb 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Expand Up @@ -15,6 +15,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this

The file requires the `Long URL` and `Short code` columns, and it also accepts the optional `title`, `domain` and `tags` columns.

* [#1000](https://github.com/shlinkio/shlink/issues/1000) Added support to provide a `margin` query param when generating some URL's QR code.

### Changed
* [#977](https://github.com/shlinkio/shlink/issues/977) Migrated from `laminas/laminas-paginator` to `pagerfanta/core` to handle pagination.
* [#986](https://github.com/shlinkio/shlink/issues/986) Updated official docker image to use PHP 8.
Expand All @@ -24,7 +26,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this

All the existing camelCase flags will continue working for now, but will be removed in Shlink 3.0.0

* [#862](https://github.com/shlinkio/shlink/issues/862) Deprecated endpoint to edit tags for a short URL (`PUT /short-urls/{shortCode}/tags`).
* [#862](https://github.com/shlinkio/shlink/issues/862) Deprecated the endpoint to edit tags for a short URL (`PUT /short-urls/{shortCode}/tags`).

The short URL edition endpoint (`PATCH /short-urls/{shortCode}`) now supports setting the tags too. Use it instead.

Expand Down
11 changes: 11 additions & 0 deletions docs/swagger/paths/{shortCode}_qr-code.json
Expand Up @@ -40,6 +40,17 @@
"svg"
]
}
},
{
"name": "margin",
"in": "query",
"description": "The margin around the QR code image.",
"required": false,
"schema": {
"type": "integer",
"minimum": 0,
"default": 0
}
}
],
"responses": {
Expand Down
26 changes: 20 additions & 6 deletions module/Core/src/Action/QrCodeAction.php
Expand Up @@ -50,12 +50,9 @@ public function process(Request $request, RequestHandlerInterface $handler): Res
}

$query = $request->getQueryParams();
// Size attribute is deprecated
$size = $this->normalizeSize((int) $request->getAttribute('size', $query['size'] ?? self::DEFAULT_SIZE));

$qrCode = new QrCode($this->stringifier->stringify($shortUrl));
$qrCode->setSize($size);
$qrCode->setMargin(0);
$qrCode->setSize($this->resolveSize($request, $query));
$qrCode->setMargin($this->resolveMargin($query));

$format = $query['format'] ?? 'png';
if ($format === 'svg') {
Expand All @@ -65,12 +62,29 @@ public function process(Request $request, RequestHandlerInterface $handler): Res
return new QrCodeResponse($qrCode);
}

private function normalizeSize(int $size): int
private function resolveSize(Request $request, array $query): int
{
// Size attribute is deprecated. After v3.0.0, always use the query param instead
$size = (int) $request->getAttribute('size', $query['size'] ?? self::DEFAULT_SIZE);
if ($size < self::MIN_SIZE) {
return self::MIN_SIZE;
}

return $size > self::MAX_SIZE ? self::MAX_SIZE : $size;
}

private function resolveMargin(array $query): int
{
if (! isset($query['margin'])) {
return 0;
}

$margin = $query['margin'];
$intMargin = (int) $margin;
if ($margin !== (string) $intMargin) {
return 0;
}

return $intMargin < 0 ? 0 : $intMargin;
}
}
15 changes: 15 additions & 0 deletions module/Core/test/Action/QrCodeActionTest.php
Expand Up @@ -133,5 +133,20 @@ public function provideRequestsWithSize(): iterable
ServerRequestFactory::fromGlobals()->withAttribute('size', '350')->withQueryParams(['size' => '123']),
350,
];
yield 'margin' => [ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => '35']), 370];
yield 'margin and size' => [
ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => '100', 'size' => '200']),
400,
];
yield 'negative margin' => [ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => '-50']), 300];
yield 'non-numeric margin' => [ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => 'foo']), 300];
yield 'negative margin and size' => [
ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => '-1', 'size' => '150']),
150,
];
yield 'non-numeric margin and size' => [
ServerRequestFactory::fromGlobals()->withQueryParams(['margin' => 'foo', 'size' => '538']),
538,
];
}
}