mirror of
https://github.com/shlinkio/shlink.git
synced 2026-02-28 04:03:12 +08:00
Deprecate QR code generation endpoint
This commit is contained in:
18
CHANGELOG.md
18
CHANGELOG.md
@@ -4,6 +4,24 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com), and this project adheres to [Semantic Versioning](https://semver.org).
|
||||
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
* *Nothing*
|
||||
|
||||
### Changed
|
||||
* *Nothing*
|
||||
|
||||
### Deprecated
|
||||
* [#2408](https://github.com/shlinkio/shlink/issues/2408) Generating QR codes via `/{short-code}/qr-code` is now deprecated and will be removed in Shlink 5.0. Use the equivalent capability from web clients instead.
|
||||
|
||||
### Removed
|
||||
* *Nothing*
|
||||
|
||||
### Fixed
|
||||
* *Nothing*
|
||||
|
||||
|
||||
## [4.4.6] - 2025-03-20
|
||||
### Added
|
||||
* *Nothing*
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"pagerfanta/core": "^3.8",
|
||||
"ramsey/uuid": "^4.7",
|
||||
"shlinkio/doctrine-specification": "^2.2",
|
||||
"shlinkio/shlink-common": "^7.0",
|
||||
"shlinkio/shlink-common": "dev-main#e601317 as 7.1",
|
||||
"shlinkio/shlink-config": "^4.0",
|
||||
"shlinkio/shlink-event-dispatcher": "^4.2",
|
||||
"shlinkio/shlink-importer": "^5.6",
|
||||
|
||||
@@ -13,13 +13,22 @@ const DEFAULT_REDIRECT_STATUS_CODE = RedirectStatus::STATUS_302;
|
||||
const DEFAULT_REDIRECT_CACHE_LIFETIME = 30;
|
||||
const LOCAL_LOCK_FACTORY = 'Shlinkio\Shlink\LocalLockFactory';
|
||||
const LOOSE_URI_MATCHER = '/(.+)\:(.+)/i'; // Matches anything starting with a schema.
|
||||
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';
|
||||
const DEFAULT_QR_CODE_ROUND_BLOCK_SIZE = true;
|
||||
const DEFAULT_QR_CODE_ENABLED_FOR_DISABLED_SHORT_URLS = true;
|
||||
const DEFAULT_QR_CODE_COLOR = '#000000'; // Black
|
||||
const DEFAULT_QR_CODE_BG_COLOR = '#ffffff'; // White
|
||||
const IP_ADDRESS_REQUEST_ATTRIBUTE = 'remote_address';
|
||||
const REDIRECT_URL_REQUEST_ATTRIBUTE = 'redirect_url';
|
||||
|
||||
/** @deprecated */
|
||||
const DEFAULT_QR_CODE_SIZE = 300;
|
||||
/** @deprecated */
|
||||
const DEFAULT_QR_CODE_MARGIN = 0;
|
||||
/** @deprecated */
|
||||
const DEFAULT_QR_CODE_FORMAT = 'png';
|
||||
/** @deprecated */
|
||||
const DEFAULT_QR_CODE_ERROR_CORRECTION = 'l';
|
||||
/** @deprecated */
|
||||
const DEFAULT_QR_CODE_ROUND_BLOCK_SIZE = true;
|
||||
/** @deprecated */
|
||||
const DEFAULT_QR_CODE_ENABLED_FOR_DISABLED_SHORT_URLS = true;
|
||||
/** @deprecated */
|
||||
const DEFAULT_QR_CODE_COLOR = '#000000'; // Black
|
||||
/** @deprecated */
|
||||
const DEFAULT_QR_CODE_BG_COLOR = '#ffffff'; // White
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"get": {
|
||||
"deprecated": true,
|
||||
"operationId": "shortUrlQrCode",
|
||||
"tags": [
|
||||
"URL Shortener"
|
||||
],
|
||||
"summary": "Short URL QR code",
|
||||
"description": "Generates a QR code image pointing to a short URL.<br />Since this is not an API endpoint but an image one, when an invalid value is provided for any of the query params, they will fall to their default values instead of throwing an error.",
|
||||
"summary": "[Deprecated] Short URL QR code",
|
||||
"description": "**[Deprecated]** Use an external mechanism to generate QR codes. Shlink dashboard and shlink-web-client provide their own.",
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "../parameters/shortCode.json"
|
||||
|
||||
@@ -28,6 +28,7 @@ use function trim;
|
||||
use const Shlinkio\Shlink\DEFAULT_QR_CODE_BG_COLOR;
|
||||
use const Shlinkio\Shlink\DEFAULT_QR_CODE_COLOR;
|
||||
|
||||
/** @deprecated */
|
||||
final readonly class QrCodeParams
|
||||
{
|
||||
private const int MIN_SIZE = 50;
|
||||
|
||||
@@ -19,6 +19,7 @@ use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifierInterface;
|
||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier;
|
||||
use Shlinkio\Shlink\Core\ShortUrl\ShortUrlResolverInterface;
|
||||
|
||||
/** @deprecated */
|
||||
readonly class QrCodeAction implements MiddlewareInterface
|
||||
{
|
||||
public function __construct(
|
||||
|
||||
@@ -56,15 +56,6 @@ enum EnvVars: string
|
||||
case MATOMO_BASE_URL = 'MATOMO_BASE_URL';
|
||||
case MATOMO_SITE_ID = 'MATOMO_SITE_ID';
|
||||
case MATOMO_API_TOKEN = 'MATOMO_API_TOKEN';
|
||||
case DEFAULT_QR_CODE_SIZE = 'DEFAULT_QR_CODE_SIZE';
|
||||
case DEFAULT_QR_CODE_MARGIN = 'DEFAULT_QR_CODE_MARGIN';
|
||||
case DEFAULT_QR_CODE_FORMAT = 'DEFAULT_QR_CODE_FORMAT';
|
||||
case DEFAULT_QR_CODE_ERROR_CORRECTION = 'DEFAULT_QR_CODE_ERROR_CORRECTION';
|
||||
case DEFAULT_QR_CODE_ROUND_BLOCK_SIZE = 'DEFAULT_QR_CODE_ROUND_BLOCK_SIZE';
|
||||
case QR_CODE_FOR_DISABLED_SHORT_URLS = 'QR_CODE_FOR_DISABLED_SHORT_URLS';
|
||||
case DEFAULT_QR_CODE_COLOR = 'DEFAULT_QR_CODE_COLOR';
|
||||
case DEFAULT_QR_CODE_BG_COLOR = 'DEFAULT_QR_CODE_BG_COLOR';
|
||||
case DEFAULT_QR_CODE_LOGO_URL = 'DEFAULT_QR_CODE_LOGO_URL';
|
||||
case DEFAULT_INVALID_SHORT_URL_REDIRECT = 'DEFAULT_INVALID_SHORT_URL_REDIRECT';
|
||||
case DEFAULT_REGULAR_404_REDIRECT = 'DEFAULT_REGULAR_404_REDIRECT';
|
||||
case DEFAULT_BASE_URL_REDIRECT = 'DEFAULT_BASE_URL_REDIRECT';
|
||||
@@ -95,6 +86,24 @@ enum EnvVars: string
|
||||
case SKIP_INITIAL_GEOLITE_DOWNLOAD = 'SKIP_INITIAL_GEOLITE_DOWNLOAD';
|
||||
/** @deprecated Use REDIRECT_EXTRA_PATH */
|
||||
case REDIRECT_APPEND_EXTRA_PATH = 'REDIRECT_APPEND_EXTRA_PATH';
|
||||
/** @deprecated */
|
||||
case DEFAULT_QR_CODE_SIZE = 'DEFAULT_QR_CODE_SIZE';
|
||||
/** @deprecated */
|
||||
case DEFAULT_QR_CODE_MARGIN = 'DEFAULT_QR_CODE_MARGIN';
|
||||
/** @deprecated */
|
||||
case DEFAULT_QR_CODE_FORMAT = 'DEFAULT_QR_CODE_FORMAT';
|
||||
/** @deprecated */
|
||||
case DEFAULT_QR_CODE_ERROR_CORRECTION = 'DEFAULT_QR_CODE_ERROR_CORRECTION';
|
||||
/** @deprecated */
|
||||
case DEFAULT_QR_CODE_ROUND_BLOCK_SIZE = 'DEFAULT_QR_CODE_ROUND_BLOCK_SIZE';
|
||||
/** @deprecated */
|
||||
case QR_CODE_FOR_DISABLED_SHORT_URLS = 'QR_CODE_FOR_DISABLED_SHORT_URLS';
|
||||
/** @deprecated */
|
||||
case DEFAULT_QR_CODE_COLOR = 'DEFAULT_QR_CODE_COLOR';
|
||||
/** @deprecated */
|
||||
case DEFAULT_QR_CODE_BG_COLOR = 'DEFAULT_QR_CODE_BG_COLOR';
|
||||
/** @deprecated */
|
||||
case DEFAULT_QR_CODE_LOGO_URL = 'DEFAULT_QR_CODE_LOGO_URL';
|
||||
|
||||
public function loadFromEnv(): mixed
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ use const Shlinkio\Shlink\DEFAULT_QR_CODE_MARGIN;
|
||||
use const Shlinkio\Shlink\DEFAULT_QR_CODE_ROUND_BLOCK_SIZE;
|
||||
use const Shlinkio\Shlink\DEFAULT_QR_CODE_SIZE;
|
||||
|
||||
/** @deprecated */
|
||||
final readonly class QrCodeOptions
|
||||
{
|
||||
public function __construct(
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace ShlinkioApiTest\Shlink\Core\Action;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
||||
|
||||
/** @deprecated */
|
||||
class QrCodeTest extends ApiTestCase
|
||||
{
|
||||
#[Test]
|
||||
|
||||
@@ -9,7 +9,6 @@ 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;
|
||||
@@ -286,30 +285,6 @@ class QrCodeActionTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
#[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's logo
|
||||
$code = 'abc123';
|
||||
$req = ServerRequestFactory::fromGlobals()
|
||||
->withAttribute('shortCode', $code)
|
||||
->withQueryParams($query);
|
||||
|
||||
$this->urlResolver->method('resolveEnabledShortUrl')->willReturn(ShortUrl::withLongUrl('https://shlink.io'));
|
||||
$handler = $this->createMock(RequestHandlerInterface::class);
|
||||
|
||||
$resp = $this->action(new QrCodeOptions(size: 250, logoUrl: $logoUrl))->process($req, $handler);
|
||||
$image = imagecreatefromstring($resp->getBody()->__toString());
|
||||
self::assertNotFalse($image);
|
||||
|
||||
// At around 100x100 px we can already find the logo, if present
|
||||
$resultingColor = imagecolorat($image, 100, 100);
|
||||
self::assertEquals(hexdec($expectedColor), $resultingColor);
|
||||
}
|
||||
|
||||
public static function provideEnabled(): iterable
|
||||
{
|
||||
yield 'always enabled' => [true];
|
||||
|
||||
Reference in New Issue
Block a user