diff --git a/module/Core/src/Entity/ShortUrl.php b/module/Core/src/Entity/ShortUrl.php index 53215a68..810281fa 100644 --- a/module/Core/src/Entity/ShortUrl.php +++ b/module/Core/src/Entity/ShortUrl.php @@ -171,24 +171,29 @@ class ShortUrl extends AbstractEntity ShortUrlEdit $shortUrlEdit, ?ShortUrlRelationResolverInterface $relationResolver = null ): void { - if ($shortUrlEdit->hasValidSince()) { + if ($shortUrlEdit->validSinceWasProvided()) { $this->validSince = $shortUrlEdit->validSince(); } - if ($shortUrlEdit->hasValidUntil()) { + if ($shortUrlEdit->validUntilWasProvided()) { $this->validUntil = $shortUrlEdit->validUntil(); } - if ($shortUrlEdit->hasMaxVisits()) { + if ($shortUrlEdit->maxVisitsWasProvided()) { $this->maxVisits = $shortUrlEdit->maxVisits(); } - if ($shortUrlEdit->hasLongUrl()) { - $this->longUrl = $shortUrlEdit->longUrl(); + if ($shortUrlEdit->longUrlWasProvided()) { + $this->longUrl = $shortUrlEdit->longUrl() ?? $this->longUrl; } - if ($shortUrlEdit->hasTags()) { + if ($shortUrlEdit->tagsWereProvided()) { $relationResolver = $relationResolver ?? new SimpleShortUrlRelationResolver(); $this->tags = $relationResolver->resolveTags($shortUrlEdit->tags()); } - if ($shortUrlEdit->hasTitle()) { + if ( + $this->title === null + || $shortUrlEdit->titleWasProvided() + || ($this->titleWasAutoResolved && $shortUrlEdit->titleWasAutoResolved()) + ) { $this->title = $shortUrlEdit->title(); + $this->titleWasAutoResolved = $shortUrlEdit->titleWasAutoResolved(); } } diff --git a/module/Core/src/Model/ShortUrlEdit.php b/module/Core/src/Model/ShortUrlEdit.php index ddb7d317..c2f97eed 100644 --- a/module/Core/src/Model/ShortUrlEdit.php +++ b/module/Core/src/Model/ShortUrlEdit.php @@ -27,6 +27,7 @@ final class ShortUrlEdit private array $tags = []; private bool $titlePropWasProvided = false; private ?string $title = null; + private bool $titleWasAutoResolved = false; private ?bool $validateUrl = null; private function __construct() @@ -74,7 +75,7 @@ final class ShortUrlEdit return $this->longUrl; } - public function hasLongUrl(): bool + public function longUrlWasProvided(): bool { return $this->longUrlPropWasProvided && $this->longUrl !== null; } @@ -84,7 +85,7 @@ final class ShortUrlEdit return $this->validSince; } - public function hasValidSince(): bool + public function validSinceWasProvided(): bool { return $this->validSincePropWasProvided; } @@ -94,7 +95,7 @@ final class ShortUrlEdit return $this->validUntil; } - public function hasValidUntil(): bool + public function validUntilWasProvided(): bool { return $this->validUntilPropWasProvided; } @@ -104,7 +105,7 @@ final class ShortUrlEdit return $this->maxVisits; } - public function hasMaxVisits(): bool + public function maxVisitsWasProvided(): bool { return $this->maxVisitsPropWasProvided; } @@ -117,7 +118,7 @@ final class ShortUrlEdit return $this->tags; } - public function hasTags(): bool + public function tagsWereProvided(): bool { return $this->tagsPropWasProvided; } @@ -127,11 +128,25 @@ final class ShortUrlEdit return $this->title; } - public function hasTitle(): bool + public function titleWasProvided(): bool { return $this->titlePropWasProvided; } + public function titleWasAutoResolved(): bool + { + return $this->titleWasAutoResolved; + } + + public function withResolvedTitle(string $title): self + { + $copy = clone $this; + $copy->title = $title; + $copy->titleWasAutoResolved = true; + + return $copy; + } + public function doValidateUrl(): ?bool { return $this->validateUrl; diff --git a/module/Core/src/Service/ShortUrlService.php b/module/Core/src/Service/ShortUrlService.php index 70606219..e412b63b 100644 --- a/module/Core/src/Service/ShortUrlService.php +++ b/module/Core/src/Service/ShortUrlService.php @@ -61,8 +61,8 @@ class ShortUrlService implements ShortUrlServiceInterface ShortUrlEdit $shortUrlEdit, ?ApiKey $apiKey = null ): ShortUrl { - if ($shortUrlEdit->hasLongUrl()) { - $this->urlValidator->validateUrl($shortUrlEdit->longUrl(), $shortUrlEdit->doValidateUrl()); + if ($shortUrlEdit->longUrlWasProvided()) { + $shortUrlEdit = $this->processTitleAndValidateUrl($shortUrlEdit); } $shortUrl = $this->urlResolver->resolveShortUrl($identifier, $apiKey); @@ -72,4 +72,15 @@ class ShortUrlService implements ShortUrlServiceInterface return $shortUrl; } + + private function processTitleAndValidateUrl(ShortUrlEdit $shortUrlEdit): ShortUrlEdit + { + if ($shortUrlEdit->titleWasProvided()) { + $this->urlValidator->validateUrl($shortUrlEdit->longUrl(), $shortUrlEdit->doValidateUrl()); + return $shortUrlEdit; + } + + $title = $this->urlValidator->validateUrlWithTitle($shortUrlEdit->longUrl(), $shortUrlEdit->doValidateUrl()); + return $title === null ? $shortUrlEdit : $shortUrlEdit->withResolvedTitle($title); + } } diff --git a/module/Core/test/Service/ShortUrlServiceTest.php b/module/Core/test/Service/ShortUrlServiceTest.php index 178561f0..d4920f27 100644 --- a/module/Core/test/Service/ShortUrlServiceTest.php +++ b/module/Core/test/Service/ShortUrlServiceTest.php @@ -102,7 +102,7 @@ class ShortUrlServiceTest extends TestCase self::assertEquals($shortUrlEdit->longUrl() ?? $originalLongUrl, $shortUrl->getLongUrl()); $findShortUrl->shouldHaveBeenCalled(); $flush->shouldHaveBeenCalled(); - $this->urlValidator->validateUrl( + $this->urlValidator->validateUrlWithTitle( $shortUrlEdit->longUrl(), $shortUrlEdit->doValidateUrl(), )->shouldHaveBeenCalledTimes($expectedValidateCalls);