Inlcuded tags as part of the ShortUrlMeta

This commit is contained in:
Alejandro Celaya 2021-01-30 19:17:12 +01:00
parent 3f2bd657e1
commit 063ee9c195
14 changed files with 60 additions and 99 deletions

View File

@ -145,7 +145,7 @@ class GenerateShortUrlCommand extends BaseCommand
$doValidateUrl = $this->doValidateUrl($input); $doValidateUrl = $this->doValidateUrl($input);
try { try {
$shortUrl = $this->urlShortener->shorten($tags, ShortUrlMeta::fromRawData([ $shortUrl = $this->urlShortener->shorten(ShortUrlMeta::fromRawData([
ShortUrlMetaInputFilter::LONG_URL => $longUrl, ShortUrlMetaInputFilter::LONG_URL => $longUrl,
ShortUrlMetaInputFilter::VALID_SINCE => $this->getOptionWithDeprecatedFallback($input, 'valid-since'), ShortUrlMetaInputFilter::VALID_SINCE => $this->getOptionWithDeprecatedFallback($input, 'valid-since'),
ShortUrlMetaInputFilter::VALID_UNTIL => $this->getOptionWithDeprecatedFallback($input, 'valid-until'), ShortUrlMetaInputFilter::VALID_UNTIL => $this->getOptionWithDeprecatedFallback($input, 'valid-until'),
@ -158,6 +158,7 @@ class GenerateShortUrlCommand extends BaseCommand
ShortUrlMetaInputFilter::DOMAIN => $input->getOption('domain'), ShortUrlMetaInputFilter::DOMAIN => $input->getOption('domain'),
ShortUrlMetaInputFilter::SHORT_CODE_LENGTH => $shortCodeLength, ShortUrlMetaInputFilter::SHORT_CODE_LENGTH => $shortCodeLength,
ShortUrlMetaInputFilter::VALIDATE_URL => $doValidateUrl, ShortUrlMetaInputFilter::VALIDATE_URL => $doValidateUrl,
ShortUrlMetaInputFilter::TAGS => $tags,
])); ]));
$io->writeln([ $io->writeln([

View File

@ -91,11 +91,11 @@ class GenerateShortUrlCommandTest extends TestCase
{ {
$shortUrl = ShortUrl::createEmpty(); $shortUrl = ShortUrl::createEmpty();
$urlToShortCode = $this->urlShortener->shorten( $urlToShortCode = $this->urlShortener->shorten(
Argument::that(function (array $tags) { Argument::that(function (ShortUrlMeta $meta) {
$tags = $meta->getTags();
Assert::assertEquals(['foo', 'bar', 'baz', 'boo', 'zar'], $tags); Assert::assertEquals(['foo', 'bar', 'baz', 'boo', 'zar'], $tags);
return $tags; return true;
}), }),
Argument::cetera(),
)->willReturn($shortUrl); )->willReturn($shortUrl);
$this->commandTester->execute([ $this->commandTester->execute([
@ -117,7 +117,6 @@ class GenerateShortUrlCommandTest extends TestCase
{ {
$shortUrl = ShortUrl::createEmpty(); $shortUrl = ShortUrl::createEmpty();
$urlToShortCode = $this->urlShortener->shorten( $urlToShortCode = $this->urlShortener->shorten(
Argument::type('array'),
Argument::that(function (ShortUrlMeta $meta) use ($expectedValidateUrl) { Argument::that(function (ShortUrlMeta $meta) use ($expectedValidateUrl) {
Assert::assertEquals($expectedValidateUrl, $meta->doValidateUrl()); Assert::assertEquals($expectedValidateUrl, $meta->doValidateUrl());
return $meta; return $meta;

View File

@ -1,30 +0,0 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Core\Model;
final class CreateShortUrlData
{
private array $tags;
private ShortUrlMeta $meta;
public function __construct(array $tags = [], ?ShortUrlMeta $meta = null)
{
$this->tags = $tags;
$this->meta = $meta ?? ShortUrlMeta::createEmpty();
}
/**
* @return string[]
*/
public function getTags(): array
{
return $this->tags;
}
public function getMeta(): ShortUrlMeta
{
return $this->meta;
}
}

View File

@ -201,7 +201,7 @@ class ShortUrlRepository extends EntitySpecificationRepository implements ShortU
return $qb; return $qb;
} }
public function findOneMatching(array $tags, ShortUrlMeta $meta): ?ShortUrl public function findOneMatching(ShortUrlMeta $meta): ?ShortUrl
{ {
$qb = $this->getEntityManager()->createQueryBuilder(); $qb = $this->getEntityManager()->createQueryBuilder();
@ -239,6 +239,7 @@ class ShortUrlRepository extends EntitySpecificationRepository implements ShortU
$this->applySpecification($qb, $apiKey->spec(), 's'); $this->applySpecification($qb, $apiKey->spec(), 's');
} }
$tags = $meta->getTags();
$tagsAmount = count($tags); $tagsAmount = count($tags);
if ($tagsAmount === 0) { if ($tagsAmount === 0) {
return $qb->getQuery()->getOneOrNullResult(); return $qb->getQuery()->getOneOrNullResult();

View File

@ -38,7 +38,7 @@ interface ShortUrlRepositoryInterface extends ObjectRepository, EntitySpecificat
public function shortCodeIsInUse(string $slug, ?string $domain, ?Specification $spec = null): bool; public function shortCodeIsInUse(string $slug, ?string $domain, ?Specification $spec = null): bool;
public function findOneMatching(array $tags, ShortUrlMeta $meta): ?ShortUrl; public function findOneMatching(ShortUrlMeta $meta): ?ShortUrl;
public function importedUrlExists(ImportedShlinkUrl $url): bool; public function importedUrlExists(ImportedShlinkUrl $url): bool;
} }

View File

@ -38,24 +38,23 @@ class UrlShortener implements UrlShortenerInterface
} }
/** /**
* @param string[] $tags
* @throws NonUniqueSlugException * @throws NonUniqueSlugException
* @throws InvalidUrlException * @throws InvalidUrlException
* @throws Throwable * @throws Throwable
*/ */
public function shorten(array $tags, ShortUrlMeta $meta): ShortUrl public function shorten(ShortUrlMeta $meta): ShortUrl
{ {
// First, check if a short URL exists for all provided params // First, check if a short URL exists for all provided params
$existingShortUrl = $this->findExistingShortUrlIfExists($tags, $meta); $existingShortUrl = $this->findExistingShortUrlIfExists($meta);
if ($existingShortUrl !== null) { if ($existingShortUrl !== null) {
return $existingShortUrl; return $existingShortUrl;
} }
$this->urlValidator->validateUrl($meta->getLongUrl(), $meta->doValidateUrl()); $this->urlValidator->validateUrl($meta->getLongUrl(), $meta->doValidateUrl());
return $this->em->transactional(function () use ($tags, $meta) { return $this->em->transactional(function () use ($meta) {
$shortUrl = ShortUrl::fromMeta($meta, $this->relationResolver); $shortUrl = ShortUrl::fromMeta($meta, $this->relationResolver);
$shortUrl->setTags($this->tagNamesToEntities($this->em, $tags)); $shortUrl->setTags($this->tagNamesToEntities($this->em, $meta->getTags()));
$this->verifyShortCodeUniqueness($meta, $shortUrl); $this->verifyShortCodeUniqueness($meta, $shortUrl);
$this->em->persist($shortUrl); $this->em->persist($shortUrl);
@ -64,7 +63,7 @@ class UrlShortener implements UrlShortenerInterface
}); });
} }
private function findExistingShortUrlIfExists(array $tags, ShortUrlMeta $meta): ?ShortUrl private function findExistingShortUrlIfExists(ShortUrlMeta $meta): ?ShortUrl
{ {
if (! $meta->findIfExists()) { if (! $meta->findIfExists()) {
return null; return null;
@ -72,7 +71,7 @@ class UrlShortener implements UrlShortenerInterface
/** @var ShortUrlRepositoryInterface $repo */ /** @var ShortUrlRepositoryInterface $repo */
$repo = $this->em->getRepository(ShortUrl::class); $repo = $this->em->getRepository(ShortUrl::class);
return $repo->findOneMatching($tags, $meta); return $repo->findOneMatching($meta);
} }
private function verifyShortCodeUniqueness(ShortUrlMeta $meta, ShortUrl $shortUrlToBeCreated): void private function verifyShortCodeUniqueness(ShortUrlMeta $meta, ShortUrl $shortUrlToBeCreated): void

View File

@ -12,9 +12,8 @@ use Shlinkio\Shlink\Core\Model\ShortUrlMeta;
interface UrlShortenerInterface interface UrlShortenerInterface
{ {
/** /**
* @param string[] $tags
* @throws NonUniqueSlugException * @throws NonUniqueSlugException
* @throws InvalidUrlException * @throws InvalidUrlException
*/ */
public function shorten(array $tags, ShortUrlMeta $meta): ShortUrl; public function shorten(ShortUrlMeta $meta): ShortUrl;
} }

View File

@ -216,16 +216,16 @@ class ShortUrlRepositoryTest extends DatabaseTestCase
/** @test */ /** @test */
public function findOneMatchingReturnsNullForNonExistingShortUrls(): void public function findOneMatchingReturnsNullForNonExistingShortUrls(): void
{ {
self::assertNull($this->repo->findOneMatching([], ShortUrlMeta::createEmpty())); self::assertNull($this->repo->findOneMatching(ShortUrlMeta::createEmpty()));
self::assertNull($this->repo->findOneMatching([], ShortUrlMeta::fromRawData(['longUrl' => 'foobar']))); self::assertNull($this->repo->findOneMatching(ShortUrlMeta::fromRawData(['longUrl' => 'foobar'])));
self::assertNull($this->repo->findOneMatching( self::assertNull($this->repo->findOneMatching(
['foo', 'bar'], ShortUrlMeta::fromRawData(['longUrl' => 'foobar', 'tags' => ['foo', 'bar']]),
ShortUrlMeta::fromRawData(['longUrl' => 'foobar']),
)); ));
self::assertNull($this->repo->findOneMatching(['foo', 'bar'], ShortUrlMeta::fromRawData([ self::assertNull($this->repo->findOneMatching(ShortUrlMeta::fromRawData([
'validSince' => Chronos::parse('2020-03-05 20:18:30'), 'validSince' => Chronos::parse('2020-03-05 20:18:30'),
'customSlug' => 'this_slug_does_not_exist', 'customSlug' => 'this_slug_does_not_exist',
'longUrl' => 'foobar', 'longUrl' => 'foobar',
'tags' => ['foo', 'bar'],
]))); ])));
} }
@ -263,17 +263,16 @@ class ShortUrlRepositoryTest extends DatabaseTestCase
self::assertSame( self::assertSame(
$shortUrl, $shortUrl,
$this->repo->findOneMatching( $this->repo->findOneMatching(
['foo', 'bar'], ShortUrlMeta::fromRawData(['validSince' => $start, 'longUrl' => 'foo', 'tags' => ['foo', 'bar']]),
ShortUrlMeta::fromRawData(['validSince' => $start, 'longUrl' => 'foo']),
), ),
); );
self::assertSame( self::assertSame(
$shortUrl2, $shortUrl2,
$this->repo->findOneMatching([], ShortUrlMeta::fromRawData(['validUntil' => $end, 'longUrl' => 'bar'])), $this->repo->findOneMatching(ShortUrlMeta::fromRawData(['validUntil' => $end, 'longUrl' => 'bar'])),
); );
self::assertSame( self::assertSame(
$shortUrl3, $shortUrl3,
$this->repo->findOneMatching([], ShortUrlMeta::fromRawData([ $this->repo->findOneMatching(ShortUrlMeta::fromRawData([
'validSince' => $start, 'validSince' => $start,
'validUntil' => $end, 'validUntil' => $end,
'longUrl' => 'baz', 'longUrl' => 'baz',
@ -281,7 +280,7 @@ class ShortUrlRepositoryTest extends DatabaseTestCase
); );
self::assertSame( self::assertSame(
$shortUrl4, $shortUrl4,
$this->repo->findOneMatching([], ShortUrlMeta::fromRawData([ $this->repo->findOneMatching(ShortUrlMeta::fromRawData([
'customSlug' => 'custom', 'customSlug' => 'custom',
'validUntil' => $end, 'validUntil' => $end,
'longUrl' => 'foo', 'longUrl' => 'foo',
@ -289,11 +288,11 @@ class ShortUrlRepositoryTest extends DatabaseTestCase
); );
self::assertSame( self::assertSame(
$shortUrl5, $shortUrl5,
$this->repo->findOneMatching([], ShortUrlMeta::fromRawData(['maxVisits' => 3, 'longUrl' => 'foo'])), $this->repo->findOneMatching(ShortUrlMeta::fromRawData(['maxVisits' => 3, 'longUrl' => 'foo'])),
); );
self::assertSame( self::assertSame(
$shortUrl6, $shortUrl6,
$this->repo->findOneMatching([], ShortUrlMeta::fromRawData(['domain' => 'doma.in', 'longUrl' => 'foo'])), $this->repo->findOneMatching(ShortUrlMeta::fromRawData(['domain' => 'doma.in', 'longUrl' => 'foo'])),
); );
} }
@ -304,6 +303,9 @@ class ShortUrlRepositoryTest extends DatabaseTestCase
$meta = ShortUrlMeta::fromRawData(['validSince' => $start, 'maxVisits' => 50, 'longUrl' => 'foo']); $meta = ShortUrlMeta::fromRawData(['validSince' => $start, 'maxVisits' => 50, 'longUrl' => 'foo']);
$tags = ['foo', 'bar']; $tags = ['foo', 'bar'];
$tagEntities = $this->tagNamesToEntities($this->getEntityManager(), $tags); $tagEntities = $this->tagNamesToEntities($this->getEntityManager(), $tags);
$metaWithTags = ShortUrlMeta::fromRawData(
['validSince' => $start, 'maxVisits' => 50, 'longUrl' => 'foo', 'tags' => $tags],
);
$shortUrl1 = ShortUrl::fromMeta($meta); $shortUrl1 = ShortUrl::fromMeta($meta);
$shortUrl1->setTags($tagEntities); $shortUrl1->setTags($tagEntities);
@ -319,7 +321,7 @@ class ShortUrlRepositoryTest extends DatabaseTestCase
$this->getEntityManager()->flush(); $this->getEntityManager()->flush();
$result = $this->repo->findOneMatching($tags, $meta); $result = $this->repo->findOneMatching($metaWithTags);
self::assertSame($shortUrl1, $result); self::assertSame($shortUrl1, $result);
self::assertNotSame($shortUrl2, $result); self::assertNotSame($shortUrl2, $result);
@ -358,53 +360,58 @@ class ShortUrlRepositoryTest extends DatabaseTestCase
self::assertSame( self::assertSame(
$shortUrl, $shortUrl,
$this->repo->findOneMatching( $this->repo->findOneMatching(
['foo', 'bar'], ShortUrlMeta::fromRawData(['validSince' => $start, 'longUrl' => 'foo', 'tags' => ['foo', 'bar']]),
ShortUrlMeta::fromRawData(['validSince' => $start, 'longUrl' => 'foo']),
), ),
); );
self::assertSame($shortUrl, $this->repo->findOneMatching(['foo', 'bar'], ShortUrlMeta::fromRawData([ self::assertSame($shortUrl, $this->repo->findOneMatching(ShortUrlMeta::fromRawData([
'validSince' => $start, 'validSince' => $start,
'apiKey' => $apiKey, 'apiKey' => $apiKey,
'longUrl' => 'foo', 'longUrl' => 'foo',
'tags' => ['foo', 'bar'],
]))); ])));
self::assertNull($this->repo->findOneMatching(['foo', 'bar'], ShortUrlMeta::fromRawData([ self::assertNull($this->repo->findOneMatching(ShortUrlMeta::fromRawData([
'validSince' => $start, 'validSince' => $start,
'apiKey' => $otherApiKey, 'apiKey' => $otherApiKey,
'longUrl' => 'foo', 'longUrl' => 'foo',
'tags' => ['foo', 'bar'],
]))); ])));
self::assertSame( self::assertSame(
$shortUrl, $shortUrl,
$this->repo->findOneMatching(['foo', 'bar'], ShortUrlMeta::fromRawData([ $this->repo->findOneMatching(ShortUrlMeta::fromRawData([
'validSince' => $start, 'validSince' => $start,
'domain' => $rightDomain->getAuthority(), 'domain' => $rightDomain->getAuthority(),
'longUrl' => 'foo', 'longUrl' => 'foo',
'tags' => ['foo', 'bar'],
])), ])),
); );
self::assertSame( self::assertSame(
$shortUrl, $shortUrl,
$this->repo->findOneMatching(['foo', 'bar'], ShortUrlMeta::fromRawData([ $this->repo->findOneMatching(ShortUrlMeta::fromRawData([
'validSince' => $start, 'validSince' => $start,
'domain' => $rightDomain->getAuthority(), 'domain' => $rightDomain->getAuthority(),
'apiKey' => $rightDomainApiKey, 'apiKey' => $rightDomainApiKey,
'longUrl' => 'foo', 'longUrl' => 'foo',
'tags' => ['foo', 'bar'],
])), ])),
); );
self::assertSame( self::assertSame(
$shortUrl, $shortUrl,
$this->repo->findOneMatching(['foo', 'bar'], ShortUrlMeta::fromRawData([ $this->repo->findOneMatching(ShortUrlMeta::fromRawData([
'validSince' => $start, 'validSince' => $start,
'domain' => $rightDomain->getAuthority(), 'domain' => $rightDomain->getAuthority(),
'apiKey' => $apiKey, 'apiKey' => $apiKey,
'longUrl' => 'foo', 'longUrl' => 'foo',
'tags' => ['foo', 'bar'],
])), ])),
); );
self::assertNull( self::assertNull(
$this->repo->findOneMatching(['foo', 'bar'], ShortUrlMeta::fromRawData([ $this->repo->findOneMatching(ShortUrlMeta::fromRawData([
'validSince' => $start, 'validSince' => $start,
'domain' => $rightDomain->getAuthority(), 'domain' => $rightDomain->getAuthority(),
'apiKey' => $wrongDomainApiKey, 'apiKey' => $wrongDomainApiKey,
'longUrl' => 'foo', 'longUrl' => 'foo',
'tags' => ['foo', 'bar'],
])), ])),
); );
} }

View File

@ -69,7 +69,6 @@ class UrlShortenerTest extends TestCase
public function urlIsProperlyShortened(): void public function urlIsProperlyShortened(): void
{ {
$shortUrl = $this->urlShortener->shorten( $shortUrl = $this->urlShortener->shorten(
[],
ShortUrlMeta::fromRawData(['longUrl' => 'http://foobar.com/12345/hello?foo=bar']), ShortUrlMeta::fromRawData(['longUrl' => 'http://foobar.com/12345/hello?foo=bar']),
); );
@ -84,7 +83,7 @@ class UrlShortenerTest extends TestCase
$ensureUniqueness->shouldBeCalledOnce(); $ensureUniqueness->shouldBeCalledOnce();
$this->expectException(NonUniqueSlugException::class); $this->expectException(NonUniqueSlugException::class);
$this->urlShortener->shorten([], ShortUrlMeta::fromRawData( $this->urlShortener->shorten(ShortUrlMeta::fromRawData(
['customSlug' => 'custom-slug', 'longUrl' => 'http://foobar.com/12345/hello?foo=bar'], ['customSlug' => 'custom-slug', 'longUrl' => 'http://foobar.com/12345/hello?foo=bar'],
)); ));
} }
@ -93,13 +92,13 @@ class UrlShortenerTest extends TestCase
* @test * @test
* @dataProvider provideExistingShortUrls * @dataProvider provideExistingShortUrls
*/ */
public function existingShortUrlIsReturnedWhenRequested(array $tags, ShortUrlMeta $meta, ShortUrl $expected): void public function existingShortUrlIsReturnedWhenRequested(ShortUrlMeta $meta, ShortUrl $expected): void
{ {
$repo = $this->prophesize(ShortUrlRepository::class); $repo = $this->prophesize(ShortUrlRepository::class);
$findExisting = $repo->findOneMatching(Argument::cetera())->willReturn($expected); $findExisting = $repo->findOneMatching(Argument::cetera())->willReturn($expected);
$getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal()); $getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
$result = $this->urlShortener->shorten($tags, $meta); $result = $this->urlShortener->shorten($meta);
$findExisting->shouldHaveBeenCalledOnce(); $findExisting->shouldHaveBeenCalledOnce();
$getRepo->shouldHaveBeenCalledOnce(); $getRepo->shouldHaveBeenCalledOnce();
@ -112,24 +111,21 @@ class UrlShortenerTest extends TestCase
{ {
$url = 'http://foo.com'; $url = 'http://foo.com';
yield [[], ShortUrlMeta::fromRawData(['findIfExists' => true, 'longUrl' => $url]), ShortUrl::withLongUrl( yield [ShortUrlMeta::fromRawData(['findIfExists' => true, 'longUrl' => $url]), ShortUrl::withLongUrl(
$url, $url,
)]; )];
yield [[], ShortUrlMeta::fromRawData( yield [ShortUrlMeta::fromRawData(
['findIfExists' => true, 'customSlug' => 'foo', 'longUrl' => $url], ['findIfExists' => true, 'customSlug' => 'foo', 'longUrl' => $url],
), ShortUrl::withLongUrl($url)]; ), ShortUrl::withLongUrl($url)];
yield [ yield [
['foo', 'bar'], ShortUrlMeta::fromRawData(['findIfExists' => true, 'longUrl' => $url, 'tags' => ['foo', 'bar']]),
ShortUrlMeta::fromRawData(['findIfExists' => true, 'longUrl' => $url]),
ShortUrl::withLongUrl($url)->setTags(new ArrayCollection([new Tag('bar'), new Tag('foo')])), ShortUrl::withLongUrl($url)->setTags(new ArrayCollection([new Tag('bar'), new Tag('foo')])),
]; ];
yield [ yield [
[],
ShortUrlMeta::fromRawData(['findIfExists' => true, 'maxVisits' => 3, 'longUrl' => $url]), ShortUrlMeta::fromRawData(['findIfExists' => true, 'maxVisits' => 3, 'longUrl' => $url]),
ShortUrl::fromMeta(ShortUrlMeta::fromRawData(['maxVisits' => 3, 'longUrl' => $url])), ShortUrl::fromMeta(ShortUrlMeta::fromRawData(['maxVisits' => 3, 'longUrl' => $url])),
]; ];
yield [ yield [
[],
ShortUrlMeta::fromRawData( ShortUrlMeta::fromRawData(
['findIfExists' => true, 'validSince' => Chronos::parse('2017-01-01'), 'longUrl' => $url], ['findIfExists' => true, 'validSince' => Chronos::parse('2017-01-01'), 'longUrl' => $url],
), ),
@ -138,7 +134,6 @@ class UrlShortenerTest extends TestCase
), ),
]; ];
yield [ yield [
[],
ShortUrlMeta::fromRawData( ShortUrlMeta::fromRawData(
['findIfExists' => true, 'validUntil' => Chronos::parse('2017-01-01'), 'longUrl' => $url], ['findIfExists' => true, 'validUntil' => Chronos::parse('2017-01-01'), 'longUrl' => $url],
), ),
@ -147,17 +142,16 @@ class UrlShortenerTest extends TestCase
), ),
]; ];
yield [ yield [
[],
ShortUrlMeta::fromRawData(['findIfExists' => true, 'domain' => 'example.com', 'longUrl' => $url]), ShortUrlMeta::fromRawData(['findIfExists' => true, 'domain' => 'example.com', 'longUrl' => $url]),
ShortUrl::fromMeta(ShortUrlMeta::fromRawData(['domain' => 'example.com', 'longUrl' => $url])), ShortUrl::fromMeta(ShortUrlMeta::fromRawData(['domain' => 'example.com', 'longUrl' => $url])),
]; ];
yield [ yield [
['baz', 'foo', 'bar'],
ShortUrlMeta::fromRawData([ ShortUrlMeta::fromRawData([
'findIfExists' => true, 'findIfExists' => true,
'validUntil' => Chronos::parse('2017-01-01'), 'validUntil' => Chronos::parse('2017-01-01'),
'maxVisits' => 4, 'maxVisits' => 4,
'longUrl' => $url, 'longUrl' => $url,
'tags' => ['baz', 'foo', 'bar'],
]), ]),
ShortUrl::fromMeta(ShortUrlMeta::fromRawData([ ShortUrl::fromMeta(ShortUrlMeta::fromRawData([
'validUntil' => Chronos::parse('2017-01-01'), 'validUntil' => Chronos::parse('2017-01-01'),

View File

@ -8,7 +8,7 @@ use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Shlinkio\Shlink\Core\Exception\ValidationException; use Shlinkio\Shlink\Core\Exception\ValidationException;
use Shlinkio\Shlink\Core\Model\CreateShortUrlData; use Shlinkio\Shlink\Core\Model\ShortUrlMeta;
use Shlinkio\Shlink\Core\Service\UrlShortenerInterface; use Shlinkio\Shlink\Core\Service\UrlShortenerInterface;
use Shlinkio\Shlink\Core\Transformer\ShortUrlDataTransformer; use Shlinkio\Shlink\Core\Transformer\ShortUrlDataTransformer;
use Shlinkio\Shlink\Rest\Action\AbstractRestAction; use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
@ -26,11 +26,9 @@ abstract class AbstractCreateShortUrlAction extends AbstractRestAction
public function handle(Request $request): Response public function handle(Request $request): Response
{ {
$shortUrlData = $this->buildShortUrlData($request); $shortUrlMeta = $this->buildShortUrlData($request);
$tags = $shortUrlData->getTags();
$shortUrlMeta = $shortUrlData->getMeta();
$shortUrl = $this->urlShortener->shorten($tags, $shortUrlMeta); $shortUrl = $this->urlShortener->shorten($shortUrlMeta);
$transformer = new ShortUrlDataTransformer($this->domainConfig); $transformer = new ShortUrlDataTransformer($this->domainConfig);
return new JsonResponse($transformer->transform($shortUrl)); return new JsonResponse($transformer->transform($shortUrl));
@ -39,5 +37,5 @@ abstract class AbstractCreateShortUrlAction extends AbstractRestAction
/** /**
* @throws ValidationException * @throws ValidationException
*/ */
abstract protected function buildShortUrlData(Request $request): CreateShortUrlData; abstract protected function buildShortUrlData(Request $request): ShortUrlMeta;
} }

View File

@ -6,7 +6,6 @@ namespace Shlinkio\Shlink\Rest\Action\ShortUrl;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Shlinkio\Shlink\Core\Exception\ValidationException; use Shlinkio\Shlink\Core\Exception\ValidationException;
use Shlinkio\Shlink\Core\Model\CreateShortUrlData;
use Shlinkio\Shlink\Core\Model\ShortUrlMeta; use Shlinkio\Shlink\Core\Model\ShortUrlMeta;
use Shlinkio\Shlink\Core\Validation\ShortUrlMetaInputFilter; use Shlinkio\Shlink\Core\Validation\ShortUrlMetaInputFilter;
use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware; use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
@ -19,12 +18,11 @@ class CreateShortUrlAction extends AbstractCreateShortUrlAction
/** /**
* @throws ValidationException * @throws ValidationException
*/ */
protected function buildShortUrlData(Request $request): CreateShortUrlData protected function buildShortUrlData(Request $request): ShortUrlMeta
{ {
$payload = (array) $request->getParsedBody(); $payload = (array) $request->getParsedBody();
$payload[ShortUrlMetaInputFilter::API_KEY] = AuthenticationMiddleware::apiKeyFromRequest($request); $payload[ShortUrlMetaInputFilter::API_KEY] = AuthenticationMiddleware::apiKeyFromRequest($request);
$meta = ShortUrlMeta::fromRawData($payload);
return new CreateShortUrlData((array) ($payload['tags'] ?? []), $meta); return ShortUrlMeta::fromRawData($payload);
} }
} }

View File

@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\Rest\Action\ShortUrl; namespace Shlinkio\Shlink\Rest\Action\ShortUrl;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Shlinkio\Shlink\Core\Model\CreateShortUrlData;
use Shlinkio\Shlink\Core\Model\ShortUrlMeta; use Shlinkio\Shlink\Core\Model\ShortUrlMeta;
use Shlinkio\Shlink\Core\Validation\ShortUrlMetaInputFilter; use Shlinkio\Shlink\Core\Validation\ShortUrlMetaInputFilter;
use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware; use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
@ -15,17 +14,17 @@ class SingleStepCreateShortUrlAction extends AbstractCreateShortUrlAction
protected const ROUTE_PATH = '/short-urls/shorten'; protected const ROUTE_PATH = '/short-urls/shorten';
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET]; protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET];
protected function buildShortUrlData(Request $request): CreateShortUrlData protected function buildShortUrlData(Request $request): ShortUrlMeta
{ {
$query = $request->getQueryParams(); $query = $request->getQueryParams();
$longUrl = $query['longUrl'] ?? null; $longUrl = $query['longUrl'] ?? null;
$apiKey = AuthenticationMiddleware::apiKeyFromRequest($request); $apiKey = AuthenticationMiddleware::apiKeyFromRequest($request);
return new CreateShortUrlData([], ShortUrlMeta::fromRawData([ return ShortUrlMeta::fromRawData([
ShortUrlMetaInputFilter::LONG_URL => $longUrl, ShortUrlMetaInputFilter::LONG_URL => $longUrl,
ShortUrlMetaInputFilter::API_KEY => $apiKey, ShortUrlMetaInputFilter::API_KEY => $apiKey,
// This will usually be null, unless this API key enforces one specific domain // This will usually be null, unless this API key enforces one specific domain
ShortUrlMetaInputFilter::DOMAIN => $request->getAttribute(ShortUrlMetaInputFilter::DOMAIN), ShortUrlMetaInputFilter::DOMAIN => $request->getAttribute(ShortUrlMetaInputFilter::DOMAIN),
])); ]);
} }
} }

View File

@ -54,10 +54,7 @@ class CreateShortUrlActionTest extends TestCase
]; ];
$expectedMeta['apiKey'] = $apiKey; $expectedMeta['apiKey'] = $apiKey;
$shorten = $this->urlShortener->shorten( $shorten = $this->urlShortener->shorten(ShortUrlMeta::fromRawData($expectedMeta))->willReturn($shortUrl);
Argument::type('array'),
ShortUrlMeta::fromRawData($expectedMeta),
)->willReturn($shortUrl);
$request = ServerRequestFactory::fromGlobals()->withParsedBody($body)->withAttribute(ApiKey::class, $apiKey); $request = ServerRequestFactory::fromGlobals()->withParsedBody($body)->withAttribute(ApiKey::class, $apiKey);

View File

@ -44,7 +44,6 @@ class SingleStepCreateShortUrlActionTest extends TestCase
'longUrl' => 'http://foobar.com', 'longUrl' => 'http://foobar.com',
])->withAttribute(ApiKey::class, $apiKey); ])->withAttribute(ApiKey::class, $apiKey);
$generateShortCode = $this->urlShortener->shorten( $generateShortCode = $this->urlShortener->shorten(
[],
ShortUrlMeta::fromRawData(['apiKey' => $apiKey, 'longUrl' => 'http://foobar.com']), ShortUrlMeta::fromRawData(['apiKey' => $apiKey, 'longUrl' => 'http://foobar.com']),
)->willReturn(ShortUrl::createEmpty()); )->willReturn(ShortUrl::createEmpty());