mirror of
https://github.com/shlinkio/shlink.git
synced 2026-03-06 23:33:13 +08:00
Create repository to handle expired short URLs deletion
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Core\ShortUrl\Model;
|
||||
|
||||
final readonly class ExpiredShortUrlsConditions
|
||||
{
|
||||
public function __construct(public bool $pastValidUntil = true, public bool $maxVisitsReached = false)
|
||||
{
|
||||
}
|
||||
|
||||
public static function fromQuery(array $query): self
|
||||
{
|
||||
return new self(
|
||||
pastValidUntil: (bool) ($query['pastValidUntil'] ?? true),
|
||||
maxVisitsReached: (bool) ($query['maxVisitsReached'] ?? true),
|
||||
);
|
||||
}
|
||||
|
||||
public function hasConditions(): bool
|
||||
{
|
||||
return $this->pastValidUntil || $this->maxVisitsReached;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Core\ShortUrl\Repository;
|
||||
|
||||
use Cake\Chronos\Chronos;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepository;
|
||||
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ExpiredShortUrlsConditions;
|
||||
use Shlinkio\Shlink\Core\Visit\Entity\ShortUrlVisitsCount;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
class ExpiredShortUrlsRepository extends EntitySpecificationRepository implements ExpiredShortUrlsRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function delete(ExpiredShortUrlsConditions $conditions = new ExpiredShortUrlsConditions()): int
|
||||
{
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
$qb->delete(ShortUrl::class, 's');
|
||||
|
||||
return $this->applyConditions($qb, $conditions, fn () => (int) $qb->getQuery()->execute());
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function dryCount(ExpiredShortUrlsConditions $conditions = new ExpiredShortUrlsConditions()): int
|
||||
{
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
$qb->select('COUNT(s.id)')
|
||||
->from(ShortUrl::class, 's');
|
||||
|
||||
return $this->applyConditions($qb, $conditions, fn () => (int) $qb->getQuery()->getSingleScalarResult());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable(): int $getResultFromQueryBuilder
|
||||
*/
|
||||
private function applyConditions(
|
||||
QueryBuilder $qb,
|
||||
ExpiredShortUrlsConditions $conditions,
|
||||
callable $getResultFromQueryBuilder,
|
||||
): int {
|
||||
if (! $conditions->hasConditions()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($conditions->pastValidUntil) {
|
||||
$qb
|
||||
->where($qb->expr()->andX(
|
||||
$qb->expr()->isNotNull('s.validUntil'),
|
||||
$qb->expr()->lt('s.validUntil', ':now'),
|
||||
))
|
||||
->setParameter('now', Chronos::now()->toDateTimeString());
|
||||
}
|
||||
|
||||
if ($conditions->maxVisitsReached) {
|
||||
$qb->orWhere($qb->expr()->andX(
|
||||
$qb->expr()->isNotNull('s.maxVisits'),
|
||||
$qb->expr()->lte(
|
||||
's.maxVisits',
|
||||
sprintf(
|
||||
'(SELECT COALESCE(SUM(vc.count), 0) FROM %s as vc WHERE vc.shortUrl=s)',
|
||||
ShortUrlVisitsCount::class,
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $getResultFromQueryBuilder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Core\ShortUrl\Repository;
|
||||
|
||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ExpiredShortUrlsConditions;
|
||||
|
||||
interface ExpiredShortUrlsRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Delete expired short URLs matching provided conditions
|
||||
*/
|
||||
public function delete(ExpiredShortUrlsConditions $conditions = new ExpiredShortUrlsConditions()): int;
|
||||
|
||||
/**
|
||||
* Count how many expired short URLs would be deleted for provided conditions
|
||||
*/
|
||||
public function dryCount(ExpiredShortUrlsConditions $conditions = new ExpiredShortUrlsConditions()): int;
|
||||
}
|
||||
Reference in New Issue
Block a user