diff --git a/CHANGELOG.md b/CHANGELOG.md index 8be387e3..e709a493 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this ### Fixed * [#904](https://github.com/shlinkio/shlink/issues/904) Explicitly added missing "Domains" and "Integrations" tags to swagger docs. +* [#901](https://github.com/shlinkio/shlink/issues/901) Ensured domains which are not in use on any short URL are not returned on the list of domains. ## [2.4.1] - 2020-11-10 diff --git a/module/Core/src/Domain/Repository/DomainRepository.php b/module/Core/src/Domain/Repository/DomainRepository.php index 6f998c42..f02dd120 100644 --- a/module/Core/src/Domain/Repository/DomainRepository.php +++ b/module/Core/src/Domain/Repository/DomainRepository.php @@ -5,7 +5,9 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Core\Domain\Repository; use Doctrine\ORM\EntityRepository; +use Doctrine\ORM\Query\Expr\Join; use Shlinkio\Shlink\Core\Entity\Domain; +use Shlinkio\Shlink\Core\Entity\ShortUrl; class DomainRepository extends EntityRepository implements DomainRepositoryInterface { @@ -14,7 +16,9 @@ class DomainRepository extends EntityRepository implements DomainRepositoryInter */ public function findDomainsWithout(?string $excludedAuthority = null): array { - $qb = $this->createQueryBuilder('d')->orderBy('d.authority', 'ASC'); + $qb = $this->createQueryBuilder('d'); + $qb->join(ShortUrl::class, 's', Join::WITH, 's.domain = d') + ->orderBy('d.authority', 'ASC'); if ($excludedAuthority !== null) { $qb->where($qb->expr()->neq('d.authority', ':excludedAuthority')) diff --git a/module/Core/test-db/Domain/Repository/DomainRepositoryTest.php b/module/Core/test-db/Domain/Repository/DomainRepositoryTest.php index b79f15f1..79f9caaf 100644 --- a/module/Core/test-db/Domain/Repository/DomainRepositoryTest.php +++ b/module/Core/test-db/Domain/Repository/DomainRepositoryTest.php @@ -6,11 +6,15 @@ namespace ShlinkioTest\Shlink\Core\Domain\Repository; use Shlinkio\Shlink\Core\Domain\Repository\DomainRepository; use Shlinkio\Shlink\Core\Entity\Domain; +use Shlinkio\Shlink\Core\Entity\ShortUrl; +use Shlinkio\Shlink\Core\Model\ShortUrlMeta; +use Shlinkio\Shlink\Core\ShortUrl\Resolver\ShortUrlRelationResolverInterface; +use Shlinkio\Shlink\Rest\Entity\ApiKey; use Shlinkio\Shlink\TestUtils\DbTest\DatabaseTestCase; class DomainRepositoryTest extends DatabaseTestCase { - protected const ENTITIES_TO_EMPTY = [Domain::class]; + protected const ENTITIES_TO_EMPTY = [ShortUrl::class, Domain::class]; private DomainRepository $repo; @@ -23,12 +27,23 @@ class DomainRepositoryTest extends DatabaseTestCase public function findDomainsReturnsExpectedResult(): void { $fooDomain = new Domain('foo.com'); - $barDomain = new Domain('bar.com'); - $bazDomain = new Domain('baz.com'); - $this->getEntityManager()->persist($fooDomain); + $fooShortUrl = $this->createShortUrl($fooDomain); + $this->getEntityManager()->persist($fooShortUrl); + + $barDomain = new Domain('bar.com'); $this->getEntityManager()->persist($barDomain); + $barShortUrl = $this->createShortUrl($barDomain); + $this->getEntityManager()->persist($barShortUrl); + + $bazDomain = new Domain('baz.com'); $this->getEntityManager()->persist($bazDomain); + $bazShortUrl = $this->createShortUrl($bazDomain); + $this->getEntityManager()->persist($bazShortUrl); + + $detachedDomain = new Domain('detached.com'); + $this->getEntityManager()->persist($detachedDomain); + $this->getEntityManager()->flush(); self::assertEquals([$barDomain, $bazDomain, $fooDomain], $this->repo->findDomainsWithout()); @@ -36,4 +51,30 @@ class DomainRepositoryTest extends DatabaseTestCase self::assertEquals([$bazDomain, $fooDomain], $this->repo->findDomainsWithout('bar.com')); self::assertEquals([$barDomain, $fooDomain], $this->repo->findDomainsWithout('baz.com')); } + + private function createShortUrl(Domain $domain): ShortUrl + { + return new ShortUrl( + 'foo', + ShortUrlMeta::fromRawData(['domain' => $domain->getAuthority()]), + new class ($domain) implements ShortUrlRelationResolverInterface { + private Domain $domain; + + public function __construct(Domain $domain) + { + $this->domain = $domain; + } + + public function resolveDomain(?string $domain): ?Domain + { + return $this->domain; + } + + public function resolveApiKey(?string $key): ?ApiKey + { + return null; + } + }, + ); + } } diff --git a/module/Rest/test-api/Fixtures/DomainFixture.php b/module/Rest/test-api/Fixtures/DomainFixture.php new file mode 100644 index 00000000..4c30b5b8 --- /dev/null +++ b/module/Rest/test-api/Fixtures/DomainFixture.php @@ -0,0 +1,19 @@ +persist($orphanDomain); + $manager->flush(); + } +}