mirror of
https://github.com/shlinkio/shlink.git
synced 2025-03-27 12:01:49 +03:00
Extracted tags filtering params to a DTO
This commit is contained in:
parent
4b90cf93d3
commit
e998c8434d
6 changed files with 55 additions and 20 deletions
|
@ -8,6 +8,7 @@ use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepository;
|
||||||
use Happyr\DoctrineSpecification\Spec;
|
use Happyr\DoctrineSpecification\Spec;
|
||||||
use Shlinkio\Shlink\Core\Entity\Tag;
|
use Shlinkio\Shlink\Core\Entity\Tag;
|
||||||
use Shlinkio\Shlink\Core\Tag\Model\TagInfo;
|
use Shlinkio\Shlink\Core\Tag\Model\TagInfo;
|
||||||
|
use Shlinkio\Shlink\Core\Tag\Model\TagsListFiltering;
|
||||||
use Shlinkio\Shlink\Core\Tag\Spec\CountTagsWithName;
|
use Shlinkio\Shlink\Core\Tag\Spec\CountTagsWithName;
|
||||||
use Shlinkio\Shlink\Rest\ApiKey\Spec\WithApiKeySpecsEnsuringJoin;
|
use Shlinkio\Shlink\Rest\ApiKey\Spec\WithApiKeySpecsEnsuringJoin;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
@ -32,29 +33,24 @@ class TagRepository extends EntitySpecificationRepository implements TagReposito
|
||||||
/**
|
/**
|
||||||
* @return TagInfo[]
|
* @return TagInfo[]
|
||||||
*/
|
*/
|
||||||
public function findTagsWithInfo(
|
public function findTagsWithInfo(?TagsListFiltering $filtering = null): array
|
||||||
?int $limit = null,
|
{
|
||||||
?int $offset = null,
|
|
||||||
?string $searchTerm = null,
|
|
||||||
?ApiKey $apiKey = null,
|
|
||||||
): array {
|
|
||||||
$qb = $this->createQueryBuilder('t');
|
$qb = $this->createQueryBuilder('t');
|
||||||
$qb->select('t AS tag', 'COUNT(DISTINCT s.id) AS shortUrlsCount', 'COUNT(DISTINCT v.id) AS visitsCount')
|
$qb->select('t AS tag', 'COUNT(DISTINCT s.id) AS shortUrlsCount', 'COUNT(DISTINCT v.id) AS visitsCount')
|
||||||
->leftJoin('t.shortUrls', 's')
|
->leftJoin('t.shortUrls', 's')
|
||||||
->leftJoin('s.visits', 'v')
|
->leftJoin('s.visits', 'v')
|
||||||
->groupBy('t')
|
->groupBy('t')
|
||||||
->orderBy('t.name', 'ASC')
|
->orderBy('t.name', 'ASC')
|
||||||
->setMaxResults($limit)
|
->setMaxResults($filtering?->limit())
|
||||||
->setFirstResult($offset);
|
->setFirstResult($filtering?->offset());
|
||||||
|
|
||||||
|
$apiKey = $filtering?->apiKey();
|
||||||
if ($apiKey !== null) {
|
if ($apiKey !== null) {
|
||||||
$this->applySpecification($qb, $apiKey->spec(false, 'shortUrls'), 't');
|
$this->applySpecification($qb, $apiKey->spec(false, 'shortUrls'), 't');
|
||||||
}
|
}
|
||||||
|
|
||||||
$query = $qb->getQuery();
|
|
||||||
|
|
||||||
return map(
|
return map(
|
||||||
$query->getResult(),
|
$qb->getQuery()->getResult(),
|
||||||
static fn (array $row) => new TagInfo($row['tag'], (int) $row['shortUrlsCount'], (int) $row['visitsCount']),
|
static fn (array $row) => new TagInfo($row['tag'], (int) $row['shortUrlsCount'], (int) $row['visitsCount']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ namespace Shlinkio\Shlink\Core\Repository;
|
||||||
use Doctrine\Persistence\ObjectRepository;
|
use Doctrine\Persistence\ObjectRepository;
|
||||||
use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryInterface;
|
use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryInterface;
|
||||||
use Shlinkio\Shlink\Core\Tag\Model\TagInfo;
|
use Shlinkio\Shlink\Core\Tag\Model\TagInfo;
|
||||||
|
use Shlinkio\Shlink\Core\Tag\Model\TagsListFiltering;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
interface TagRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface
|
interface TagRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface
|
||||||
|
@ -16,12 +17,7 @@ interface TagRepositoryInterface extends ObjectRepository, EntitySpecificationRe
|
||||||
/**
|
/**
|
||||||
* @return TagInfo[]
|
* @return TagInfo[]
|
||||||
*/
|
*/
|
||||||
public function findTagsWithInfo(
|
public function findTagsWithInfo(?TagsListFiltering $filtering = null): array;
|
||||||
?int $limit = null,
|
|
||||||
?int $offset = null,
|
|
||||||
?string $searchTerm = null,
|
|
||||||
?ApiKey $apiKey = null,
|
|
||||||
): array;
|
|
||||||
|
|
||||||
public function tagExists(string $tag, ?ApiKey $apiKey = null): bool;
|
public function tagExists(string $tag, ?ApiKey $apiKey = null): bool;
|
||||||
}
|
}
|
||||||
|
|
38
module/Core/src/Tag/Model/TagsListFiltering.php
Normal file
38
module/Core/src/Tag/Model/TagsListFiltering.php
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Shlinkio\Shlink\Core\Tag\Model;
|
||||||
|
|
||||||
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
|
final class TagsListFiltering
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private ?int $limit = null,
|
||||||
|
private ?int $offset = null,
|
||||||
|
private ?string $searchTerm = null,
|
||||||
|
private ?ApiKey $apiKey = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function limit(): ?int
|
||||||
|
{
|
||||||
|
return $this->limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function offset(): ?int
|
||||||
|
{
|
||||||
|
return $this->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function searchTerm(): ?string
|
||||||
|
{
|
||||||
|
return $this->searchTerm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function apiKey(): ?ApiKey
|
||||||
|
{
|
||||||
|
return $this->apiKey;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,10 +4,14 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Shlinkio\Shlink\Core\Tag\Paginator\Adapter;
|
namespace Shlinkio\Shlink\Core\Tag\Paginator\Adapter;
|
||||||
|
|
||||||
|
use Shlinkio\Shlink\Core\Tag\Model\TagsListFiltering;
|
||||||
|
|
||||||
class TagsInfoPaginatorAdapter extends AbstractTagsPaginatorAdapter
|
class TagsInfoPaginatorAdapter extends AbstractTagsPaginatorAdapter
|
||||||
{
|
{
|
||||||
public function getSlice(int $offset, int $length): iterable
|
public function getSlice(int $offset, int $length): iterable
|
||||||
{
|
{
|
||||||
return $this->repo->findTagsWithInfo($length, $offset, null, $this->apiKey);
|
return $this->repo->findTagsWithInfo(
|
||||||
|
new TagsListFiltering($length, $offset, $this->params->searchTerm(), $this->apiKey),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ class TagRepositoryTest extends DatabaseTestCase
|
||||||
$this->getEntityManager()->persist(Visit::forValidShortUrl($shortUrl2, Visitor::emptyInstance()));
|
$this->getEntityManager()->persist(Visit::forValidShortUrl($shortUrl2, Visitor::emptyInstance()));
|
||||||
$this->getEntityManager()->flush();
|
$this->getEntityManager()->flush();
|
||||||
|
|
||||||
$result = $this->repo->findTagsWithInfo();
|
$result = $this->repo->findTagsWithInfo(); // TODO Test with some filters
|
||||||
|
|
||||||
self::assertCount(4, $result);
|
self::assertCount(4, $result);
|
||||||
self::assertEquals(0, $result[0]->shortUrlsCount());
|
self::assertEquals(0, $result[0]->shortUrlsCount());
|
||||||
|
|
|
@ -16,6 +16,7 @@ use Shlinkio\Shlink\Core\Exception\TagNotFoundException;
|
||||||
use Shlinkio\Shlink\Core\Repository\TagRepository;
|
use Shlinkio\Shlink\Core\Repository\TagRepository;
|
||||||
use Shlinkio\Shlink\Core\Tag\Model\TagInfo;
|
use Shlinkio\Shlink\Core\Tag\Model\TagInfo;
|
||||||
use Shlinkio\Shlink\Core\Tag\Model\TagRenaming;
|
use Shlinkio\Shlink\Core\Tag\Model\TagRenaming;
|
||||||
|
use Shlinkio\Shlink\Core\Tag\Model\TagsListFiltering;
|
||||||
use Shlinkio\Shlink\Core\Tag\Model\TagsParams;
|
use Shlinkio\Shlink\Core\Tag\Model\TagsParams;
|
||||||
use Shlinkio\Shlink\Core\Tag\TagService;
|
use Shlinkio\Shlink\Core\Tag\TagService;
|
||||||
use Shlinkio\Shlink\Rest\ApiKey\Model\ApiKeyMeta;
|
use Shlinkio\Shlink\Rest\ApiKey\Model\ApiKeyMeta;
|
||||||
|
@ -64,7 +65,7 @@ class TagServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
$expected = [new TagInfo(new Tag('foo'), 1, 1), new TagInfo(new Tag('bar'), 3, 10)];
|
$expected = [new TagInfo(new Tag('foo'), 1, 1), new TagInfo(new Tag('bar'), 3, 10)];
|
||||||
|
|
||||||
$find = $this->repo->findTagsWithInfo(2, 0, null, $apiKey)->willReturn($expected);
|
$find = $this->repo->findTagsWithInfo(new TagsListFiltering(2, 0, null, $apiKey))->willReturn($expected);
|
||||||
$count = $this->repo->matchSingleScalarResult(Argument::cetera())->willReturn(2);
|
$count = $this->repo->matchSingleScalarResult(Argument::cetera())->willReturn(2);
|
||||||
|
|
||||||
$result = $this->service->tagsInfo(TagsParams::fromRawData([]), $apiKey); // TODO Add more cases with params
|
$result = $this->service->tagsInfo(TagsParams::fromRawData([]), $apiKey); // TODO Add more cases with params
|
||||||
|
|
Loading…
Add table
Reference in a new issue