mirror of
https://github.com/shlinkio/shlink.git
synced 2024-11-28 00:38:46 +03:00
Created DB-level paginator for tags without stats
This commit is contained in:
parent
6caeb11598
commit
3dd4e33758
5 changed files with 59 additions and 9 deletions
|
@ -49,7 +49,7 @@ class TagRepository extends EntitySpecificationRepository implements TagReposito
|
|||
|
||||
return map(
|
||||
$query->getResult(),
|
||||
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']),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Core\Tag\Paginator\Adapter;
|
||||
|
||||
use Happyr\DoctrineSpecification\Spec;
|
||||
use Pagerfanta\Adapter\AdapterInterface;
|
||||
use Shlinkio\Shlink\Core\Entity\Tag;
|
||||
use Shlinkio\Shlink\Core\Repository\TagRepositoryInterface;
|
||||
use Shlinkio\Shlink\Core\Tag\Model\TagsParams;
|
||||
use Shlinkio\Shlink\Rest\ApiKey\Spec\WithApiKeySpecsEnsuringJoin;
|
||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||
|
||||
abstract class AbstractTagsPaginatorAdapter implements AdapterInterface
|
||||
{
|
||||
public function __construct(
|
||||
protected TagRepositoryInterface $repo,
|
||||
protected TagsParams $params,
|
||||
protected ?ApiKey $apiKey,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getNbResults(): int
|
||||
{
|
||||
return (int) $this->repo->matchSingleScalarResult(Spec::andX(
|
||||
// FIXME I don't think using Spec::selectNew is the correct thing here,
|
||||
// but seems to be the only way to use Spec::COUNT
|
||||
Spec::selectNew(Tag::class, Spec::COUNT('id', true)),
|
||||
new WithApiKeySpecsEnsuringJoin($this->apiKey),
|
||||
));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Core\Tag\Paginator\Adapter;
|
||||
|
||||
use Happyr\DoctrineSpecification\Spec;
|
||||
use Shlinkio\Shlink\Rest\ApiKey\Spec\WithApiKeySpecsEnsuringJoin;
|
||||
|
||||
class TagsPaginatorAdapter extends AbstractTagsPaginatorAdapter
|
||||
{
|
||||
public function getSlice(int $offset, int $length): iterable
|
||||
{
|
||||
return $this->repo->match(Spec::andX(
|
||||
new WithApiKeySpecsEnsuringJoin($this->apiKey),
|
||||
Spec::orderBy('name'),
|
||||
Spec::limit($length),
|
||||
Spec::offset($offset),
|
||||
));
|
||||
}
|
||||
}
|
|
@ -5,7 +5,6 @@ declare(strict_types=1);
|
|||
namespace Shlinkio\Shlink\Core\Tag;
|
||||
|
||||
use Doctrine\ORM;
|
||||
use Happyr\DoctrineSpecification\Spec;
|
||||
use Pagerfanta\Adapter\AdapterInterface;
|
||||
use Pagerfanta\Adapter\ArrayAdapter;
|
||||
use Shlinkio\Shlink\Common\Paginator\Paginator;
|
||||
|
@ -18,7 +17,7 @@ use Shlinkio\Shlink\Core\Repository\TagRepositoryInterface;
|
|||
use Shlinkio\Shlink\Core\Tag\Model\TagInfo;
|
||||
use Shlinkio\Shlink\Core\Tag\Model\TagRenaming;
|
||||
use Shlinkio\Shlink\Core\Tag\Model\TagsParams;
|
||||
use Shlinkio\Shlink\Rest\ApiKey\Spec\WithApiKeySpecsEnsuringJoin;
|
||||
use Shlinkio\Shlink\Core\Tag\Paginator\Adapter\TagsPaginatorAdapter;
|
||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||
|
||||
class TagService implements TagServiceInterface
|
||||
|
@ -34,12 +33,7 @@ class TagService implements TagServiceInterface
|
|||
{
|
||||
/** @var TagRepository $repo */
|
||||
$repo = $this->em->getRepository(Tag::class);
|
||||
$tags = $repo->match(Spec::andX(
|
||||
Spec::orderBy('name'),
|
||||
new WithApiKeySpecsEnsuringJoin($apiKey),
|
||||
));
|
||||
|
||||
return $this->createPaginator(new ArrayAdapter($tags), $params);
|
||||
return $this->createPaginator(new TagsPaginatorAdapter($repo, $params, $apiKey), $params);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -47,11 +47,13 @@ class TagServiceTest extends TestCase
|
|||
$expected = [new Tag('foo'), new Tag('bar')];
|
||||
|
||||
$match = $this->repo->match(Argument::cetera())->willReturn($expected);
|
||||
$count = $this->repo->matchSingleScalarResult(Argument::cetera())->willReturn(0);
|
||||
|
||||
$result = $this->service->listTags(TagsParams::fromRawData([]));
|
||||
|
||||
self::assertEquals($expected, $result->getCurrentPageResults());
|
||||
$match->shouldHaveBeenCalled();
|
||||
$count->shouldHaveBeenCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue