Created DB-level paginator for tags without stats

This commit is contained in:
Alejandro Celaya 2022-01-05 23:30:35 +01:00
parent 6caeb11598
commit 3dd4e33758
5 changed files with 59 additions and 9 deletions

View file

@ -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']),
);
}

View file

@ -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),
));
}
}

View file

@ -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),
));
}
}

View file

@ -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);
}
/**

View file

@ -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();
}
/**