mirror of
https://github.com/shlinkio/shlink.git
synced 2025-03-14 12:11:19 +03:00
Return deviceLongUrls as part of the short URL data and document API changes
This commit is contained in:
parent
b1b67c497e
commit
48bd97fe41
12 changed files with 159 additions and 65 deletions
20
docs/swagger/definitions/DeviceLongUrls.json
Normal file
20
docs/swagger/definitions/DeviceLongUrls.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"android": {
|
||||
"description": "The long URL to redirect to when the short URL is visited from a device running Android",
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"ios": {
|
||||
"description": "The long URL to redirect to when the short URL is visited from a device running iOS",
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"desktop": {
|
||||
"description": "The long URL to redirect to when the short URL is visited from a desktop browser",
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
}
|
7
docs/swagger/definitions/DeviceLongUrlsResp.json
Normal file
7
docs/swagger/definitions/DeviceLongUrlsResp.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "object",
|
||||
"required": ["android", "ios", "desktop"],
|
||||
"allOf": [{
|
||||
"$ref": "./DeviceLongUrls.json"
|
||||
}]
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
"shortCode",
|
||||
"shortUrl",
|
||||
"longUrl",
|
||||
"deviceLongUrls",
|
||||
"dateCreated",
|
||||
"visitsCount",
|
||||
"visitsSummary",
|
||||
|
@ -27,6 +28,9 @@
|
|||
"type": "string",
|
||||
"description": "The original long URL."
|
||||
},
|
||||
"deviceLongUrls": {
|
||||
"$ref": "./DeviceLongUrlsResp.json"
|
||||
},
|
||||
"dateCreated": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
"description": "The long URL this short URL will redirect to",
|
||||
"type": "string"
|
||||
},
|
||||
"deviceLongUrls": {
|
||||
"$ref": "./DeviceLongUrls.json"
|
||||
},
|
||||
"validSince": {
|
||||
"description": "The date (in ISO-8601 format) from which this short code will be valid",
|
||||
"type": "string",
|
||||
|
|
|
@ -163,6 +163,11 @@
|
|||
"shortCode": "12C18",
|
||||
"shortUrl": "https://s.test/12C18",
|
||||
"longUrl": "https://store.steampowered.com",
|
||||
"deviceLongUrls": {
|
||||
"android": null,
|
||||
"ios": null,
|
||||
"desktop": null
|
||||
},
|
||||
"dateCreated": "2016-08-21T20:34:16+02:00",
|
||||
"visitsSummary": {
|
||||
"total": 328,
|
||||
|
@ -186,6 +191,11 @@
|
|||
"shortCode": "12Kb3",
|
||||
"shortUrl": "https://s.test/12Kb3",
|
||||
"longUrl": "https://shlink.io",
|
||||
"deviceLongUrls": {
|
||||
"android": null,
|
||||
"ios": "https://shlink.io/ios",
|
||||
"desktop": null
|
||||
},
|
||||
"dateCreated": "2016-05-01T20:34:16+02:00",
|
||||
"visitsSummary": {
|
||||
"total": 1029,
|
||||
|
@ -208,6 +218,11 @@
|
|||
"shortCode": "123bA",
|
||||
"shortUrl": "https://example.com/123bA",
|
||||
"longUrl": "https://www.google.com",
|
||||
"deviceLongUrls": {
|
||||
"android": null,
|
||||
"ios": null,
|
||||
"desktop": null
|
||||
},
|
||||
"dateCreated": "2015-10-01T20:34:16+02:00",
|
||||
"visitsSummary": {
|
||||
"total": 25,
|
||||
|
@ -320,6 +335,11 @@
|
|||
"shortCode": "12C18",
|
||||
"shortUrl": "https://s.test/12C18",
|
||||
"longUrl": "https://store.steampowered.com",
|
||||
"deviceLongUrls": {
|
||||
"android": null,
|
||||
"ios": null,
|
||||
"desktop": null
|
||||
},
|
||||
"dateCreated": "2016-08-21T20:34:16+02:00",
|
||||
"visitsSummary": {
|
||||
"total": 0,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"get": {
|
||||
"operationId": "shortenUrl",
|
||||
"deprecated": true,
|
||||
"tags": [
|
||||
"Short URLs"
|
||||
],
|
||||
|
@ -52,6 +53,11 @@
|
|||
},
|
||||
"example": {
|
||||
"longUrl": "https://github.com/shlinkio/shlink",
|
||||
"deviceLongUrls": {
|
||||
"android": null,
|
||||
"ios": null,
|
||||
"desktop": null
|
||||
},
|
||||
"shortUrl": "https://s.test/abc123",
|
||||
"shortCode": "abc123",
|
||||
"dateCreated": "2016-08-21T20:34:16+02:00",
|
||||
|
|
|
@ -40,6 +40,11 @@
|
|||
"shortCode": "12Kb3",
|
||||
"shortUrl": "https://s.test/12Kb3",
|
||||
"longUrl": "https://shlink.io",
|
||||
"deviceLongUrls": {
|
||||
"android": null,
|
||||
"ios": null,
|
||||
"desktop": null
|
||||
},
|
||||
"dateCreated": "2016-05-01T20:34:16+02:00",
|
||||
"visitsSummary": {
|
||||
"total": 1029,
|
||||
|
@ -162,6 +167,11 @@
|
|||
"shortCode": "12Kb3",
|
||||
"shortUrl": "https://s.test/12Kb3",
|
||||
"longUrl": "https://shlink.io",
|
||||
"deviceLongUrls": {
|
||||
"android": "https://shlink.io/android",
|
||||
"ios": null,
|
||||
"desktop": null
|
||||
},
|
||||
"dateCreated": "2016-05-01T20:34:16+02:00",
|
||||
"visitsSummary": {
|
||||
"total": 1029,
|
||||
|
|
|
@ -25,8 +25,10 @@ use Shlinkio\Shlink\Core\Visit\Model\VisitType;
|
|||
use Shlinkio\Shlink\Importer\Model\ImportedShlinkUrl;
|
||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||
|
||||
use function array_fill_keys;
|
||||
use function count;
|
||||
use function Functional\map;
|
||||
use function Shlinkio\Shlink\Core\enumValues;
|
||||
use function Shlinkio\Shlink\Core\generateRandomShortCode;
|
||||
use function Shlinkio\Shlink\Core\normalizeDate;
|
||||
use function Shlinkio\Shlink\Core\normalizeOptionalDate;
|
||||
|
@ -330,7 +332,7 @@ class ShortUrl extends AbstractEntity
|
|||
|
||||
public function deviceLongUrls(): array
|
||||
{
|
||||
$data = [];
|
||||
$data = array_fill_keys(enumValues(DeviceType::class), null);
|
||||
foreach ($this->deviceLongUrls as $deviceUrl) {
|
||||
$data[$deviceUrl->deviceType->value] = $deviceUrl->longUrl();
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ class ShortUrlDataTransformer implements DataTransformerInterface
|
|||
'shortCode' => $shortUrl->getShortCode(),
|
||||
'shortUrl' => $this->stringifier->stringify($shortUrl),
|
||||
'longUrl' => $shortUrl->getLongUrl(),
|
||||
'deviceLongUrls' => $shortUrl->deviceLongUrls(),
|
||||
'dateCreated' => $shortUrl->getDateCreated()->toAtomString(),
|
||||
'tags' => invoke($shortUrl->getTags(), '__toString'),
|
||||
'meta' => $this->buildMeta($shortUrl),
|
||||
|
|
|
@ -52,6 +52,7 @@ class PublishingUpdatesGeneratorTest extends TestCase
|
|||
'shortCode' => $shortUrl->getShortCode(),
|
||||
'shortUrl' => 'http:/' . $shortUrl->getShortCode(),
|
||||
'longUrl' => 'longUrl',
|
||||
'deviceLongUrls' => $shortUrl->deviceLongUrls(),
|
||||
'dateCreated' => $shortUrl->getDateCreated()->toAtomString(),
|
||||
'visitsCount' => 0,
|
||||
'tags' => [],
|
||||
|
@ -129,6 +130,7 @@ class PublishingUpdatesGeneratorTest extends TestCase
|
|||
'shortCode' => $shortUrl->getShortCode(),
|
||||
'shortUrl' => 'http:/' . $shortUrl->getShortCode(),
|
||||
'longUrl' => 'longUrl',
|
||||
'deviceLongUrls' => $shortUrl->deviceLongUrls(),
|
||||
'dateCreated' => $shortUrl->getDateCreated()->toAtomString(),
|
||||
'visitsCount' => 0,
|
||||
'tags' => [],
|
||||
|
|
|
@ -20,6 +20,9 @@ use Shlinkio\Shlink\Core\ShortUrl\ShortUrlService;
|
|||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||
use ShlinkioTest\Shlink\Core\Util\ApiKeyHelpersTrait;
|
||||
|
||||
use function array_fill_keys;
|
||||
use function Shlinkio\Shlink\Core\enumValues;
|
||||
|
||||
class ShortUrlServiceTest extends TestCase
|
||||
{
|
||||
use ApiKeyHelpersTrait;
|
||||
|
@ -74,7 +77,7 @@ class ShortUrlServiceTest extends TestCase
|
|||
);
|
||||
|
||||
$resolveDeviceLongUrls = function () use ($shortUrlEdit): array {
|
||||
$result = [];
|
||||
$result = array_fill_keys(enumValues(DeviceType::class), null);
|
||||
foreach ($shortUrlEdit->deviceLongUrls ?? [] as $longUrl) {
|
||||
$result[$longUrl->deviceType->value] = $longUrl->longUrl;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace ShlinkioApiTest\Shlink\Rest\Action;
|
|||
|
||||
use Cake\Chronos\Chronos;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
use Shlinkio\Shlink\Core\Model\DeviceType;
|
||||
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
||||
|
||||
use function count;
|
||||
|
@ -169,109 +170,124 @@ class ListShortUrlsTest extends ApiTestCase
|
|||
|
||||
public function provideFilteredLists(): iterable
|
||||
{
|
||||
// FIXME Cannot use enums in constants in PHP 8.1. Change this once support for PHP 8.1 is dropped
|
||||
$withDeviceLongUrls = static fn (array $shortUrl, ?array $longUrls = null) => [
|
||||
...$shortUrl,
|
||||
'deviceLongUrls' => $longUrls ?? [
|
||||
DeviceType::ANDROID->value => null,
|
||||
DeviceType::IOS->value => null,
|
||||
DeviceType::DESKTOP->value => null,
|
||||
],
|
||||
];
|
||||
$shortUrlMeta = $withDeviceLongUrls(self::SHORT_URL_META, [
|
||||
DeviceType::ANDROID->value => 'https://blog.alejandrocelaya.com/android',
|
||||
DeviceType::IOS->value => 'https://blog.alejandrocelaya.com/ios',
|
||||
DeviceType::DESKTOP->value => null,
|
||||
]);
|
||||
|
||||
yield [[], [
|
||||
self::SHORT_URL_CUSTOM_DOMAIN,
|
||||
self::SHORT_URL_CUSTOM_SLUG,
|
||||
self::SHORT_URL_META,
|
||||
self::SHORT_URL_CUSTOM_SLUG_AND_DOMAIN,
|
||||
self::SHORT_URL_SHLINK_WITH_TITLE,
|
||||
self::SHORT_URL_DOCS,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_DOMAIN),
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_SLUG),
|
||||
$shortUrlMeta,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_SLUG_AND_DOMAIN),
|
||||
$withDeviceLongUrls(self::SHORT_URL_SHLINK_WITH_TITLE),
|
||||
$withDeviceLongUrls(self::SHORT_URL_DOCS),
|
||||
], 'valid_api_key'];
|
||||
yield [['excludePastValidUntil' => 'true'], [
|
||||
self::SHORT_URL_CUSTOM_DOMAIN,
|
||||
self::SHORT_URL_CUSTOM_SLUG,
|
||||
self::SHORT_URL_META,
|
||||
self::SHORT_URL_CUSTOM_SLUG_AND_DOMAIN,
|
||||
self::SHORT_URL_SHLINK_WITH_TITLE,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_DOMAIN),
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_SLUG),
|
||||
$shortUrlMeta,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_SLUG_AND_DOMAIN),
|
||||
$withDeviceLongUrls(self::SHORT_URL_SHLINK_WITH_TITLE),
|
||||
], 'valid_api_key'];
|
||||
yield [['excludeMaxVisitsReached' => 'true'], [
|
||||
self::SHORT_URL_CUSTOM_DOMAIN,
|
||||
self::SHORT_URL_CUSTOM_SLUG,
|
||||
self::SHORT_URL_META,
|
||||
self::SHORT_URL_CUSTOM_SLUG_AND_DOMAIN,
|
||||
self::SHORT_URL_DOCS,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_DOMAIN),
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_SLUG),
|
||||
$shortUrlMeta,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_SLUG_AND_DOMAIN),
|
||||
$withDeviceLongUrls(self::SHORT_URL_DOCS),
|
||||
], 'valid_api_key'];
|
||||
yield [['orderBy' => 'shortCode'], [
|
||||
self::SHORT_URL_SHLINK_WITH_TITLE,
|
||||
self::SHORT_URL_CUSTOM_SLUG,
|
||||
self::SHORT_URL_CUSTOM_SLUG_AND_DOMAIN,
|
||||
self::SHORT_URL_META,
|
||||
self::SHORT_URL_DOCS,
|
||||
self::SHORT_URL_CUSTOM_DOMAIN,
|
||||
$withDeviceLongUrls(self::SHORT_URL_SHLINK_WITH_TITLE),
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_SLUG),
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_SLUG_AND_DOMAIN),
|
||||
$shortUrlMeta,
|
||||
$withDeviceLongUrls(self::SHORT_URL_DOCS),
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_DOMAIN),
|
||||
], 'valid_api_key'];
|
||||
yield [['orderBy' => 'shortCode-DESC'], [
|
||||
self::SHORT_URL_DOCS,
|
||||
self::SHORT_URL_CUSTOM_DOMAIN,
|
||||
self::SHORT_URL_META,
|
||||
self::SHORT_URL_CUSTOM_SLUG_AND_DOMAIN,
|
||||
self::SHORT_URL_CUSTOM_SLUG,
|
||||
self::SHORT_URL_SHLINK_WITH_TITLE,
|
||||
$withDeviceLongUrls(self::SHORT_URL_DOCS),
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_DOMAIN),
|
||||
$shortUrlMeta,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_SLUG_AND_DOMAIN),
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_SLUG),
|
||||
$withDeviceLongUrls(self::SHORT_URL_SHLINK_WITH_TITLE),
|
||||
], 'valid_api_key'];
|
||||
yield [['orderBy' => 'title-DESC'], [
|
||||
self::SHORT_URL_META,
|
||||
self::SHORT_URL_CUSTOM_SLUG,
|
||||
self::SHORT_URL_DOCS,
|
||||
self::SHORT_URL_CUSTOM_DOMAIN,
|
||||
self::SHORT_URL_CUSTOM_SLUG_AND_DOMAIN,
|
||||
self::SHORT_URL_SHLINK_WITH_TITLE,
|
||||
$shortUrlMeta,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_SLUG),
|
||||
$withDeviceLongUrls(self::SHORT_URL_DOCS),
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_DOMAIN),
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_SLUG_AND_DOMAIN),
|
||||
$withDeviceLongUrls(self::SHORT_URL_SHLINK_WITH_TITLE),
|
||||
], 'valid_api_key'];
|
||||
yield [['startDate' => Chronos::parse('2018-12-01')->toAtomString()], [
|
||||
self::SHORT_URL_CUSTOM_DOMAIN,
|
||||
self::SHORT_URL_CUSTOM_SLUG,
|
||||
self::SHORT_URL_META,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_DOMAIN),
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_SLUG),
|
||||
$shortUrlMeta,
|
||||
], 'valid_api_key'];
|
||||
yield [['endDate' => Chronos::parse('2018-12-01')->toAtomString()], [
|
||||
self::SHORT_URL_CUSTOM_SLUG_AND_DOMAIN,
|
||||
self::SHORT_URL_SHLINK_WITH_TITLE,
|
||||
self::SHORT_URL_DOCS,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_SLUG_AND_DOMAIN),
|
||||
$withDeviceLongUrls(self::SHORT_URL_SHLINK_WITH_TITLE),
|
||||
$withDeviceLongUrls(self::SHORT_URL_DOCS),
|
||||
], 'valid_api_key'];
|
||||
yield [['tags' => ['foo']], [
|
||||
self::SHORT_URL_CUSTOM_DOMAIN,
|
||||
self::SHORT_URL_META,
|
||||
self::SHORT_URL_SHLINK_WITH_TITLE,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_DOMAIN),
|
||||
$shortUrlMeta,
|
||||
$withDeviceLongUrls(self::SHORT_URL_SHLINK_WITH_TITLE),
|
||||
], 'valid_api_key'];
|
||||
yield [['tags' => ['bar']], [
|
||||
self::SHORT_URL_META,
|
||||
$shortUrlMeta,
|
||||
], 'valid_api_key'];
|
||||
yield [['tags' => ['foo', 'bar']], [
|
||||
self::SHORT_URL_CUSTOM_DOMAIN,
|
||||
self::SHORT_URL_META,
|
||||
self::SHORT_URL_SHLINK_WITH_TITLE,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_DOMAIN),
|
||||
$shortUrlMeta,
|
||||
$withDeviceLongUrls(self::SHORT_URL_SHLINK_WITH_TITLE),
|
||||
], 'valid_api_key'];
|
||||
yield [['tags' => ['foo', 'bar'], 'tagsMode' => 'any'], [
|
||||
self::SHORT_URL_CUSTOM_DOMAIN,
|
||||
self::SHORT_URL_META,
|
||||
self::SHORT_URL_SHLINK_WITH_TITLE,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_DOMAIN),
|
||||
$shortUrlMeta,
|
||||
$withDeviceLongUrls(self::SHORT_URL_SHLINK_WITH_TITLE),
|
||||
], 'valid_api_key'];
|
||||
yield [['tags' => ['foo', 'bar'], 'tagsMode' => 'all'], [
|
||||
self::SHORT_URL_META,
|
||||
$shortUrlMeta,
|
||||
], 'valid_api_key'];
|
||||
yield [['tags' => ['foo', 'bar', 'baz']], [
|
||||
self::SHORT_URL_CUSTOM_DOMAIN,
|
||||
self::SHORT_URL_META,
|
||||
self::SHORT_URL_SHLINK_WITH_TITLE,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_DOMAIN),
|
||||
$shortUrlMeta,
|
||||
$withDeviceLongUrls(self::SHORT_URL_SHLINK_WITH_TITLE),
|
||||
], 'valid_api_key'];
|
||||
yield [['tags' => ['foo', 'bar', 'baz'], 'tagsMode' => 'all'], [], 'valid_api_key'];
|
||||
yield [['tags' => ['foo'], 'endDate' => Chronos::parse('2018-12-01')->toAtomString()], [
|
||||
self::SHORT_URL_SHLINK_WITH_TITLE,
|
||||
$withDeviceLongUrls(self::SHORT_URL_SHLINK_WITH_TITLE),
|
||||
], 'valid_api_key'];
|
||||
yield [['searchTerm' => 'alejandro'], [
|
||||
self::SHORT_URL_CUSTOM_DOMAIN,
|
||||
self::SHORT_URL_META,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_DOMAIN),
|
||||
$shortUrlMeta,
|
||||
], 'valid_api_key'];
|
||||
yield [['searchTerm' => 'cool'], [
|
||||
self::SHORT_URL_SHLINK_WITH_TITLE,
|
||||
$withDeviceLongUrls(self::SHORT_URL_SHLINK_WITH_TITLE),
|
||||
], 'valid_api_key'];
|
||||
yield [['searchTerm' => 'example.com'], [
|
||||
self::SHORT_URL_CUSTOM_DOMAIN,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_DOMAIN),
|
||||
], 'valid_api_key'];
|
||||
yield [[], [
|
||||
self::SHORT_URL_CUSTOM_SLUG,
|
||||
self::SHORT_URL_META,
|
||||
self::SHORT_URL_SHLINK_WITH_TITLE,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_SLUG),
|
||||
$shortUrlMeta,
|
||||
$withDeviceLongUrls(self::SHORT_URL_SHLINK_WITH_TITLE),
|
||||
], 'author_api_key'];
|
||||
yield [[], [
|
||||
self::SHORT_URL_CUSTOM_DOMAIN,
|
||||
$withDeviceLongUrls(self::SHORT_URL_CUSTOM_DOMAIN),
|
||||
], 'domain_api_key'];
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue