mirror of
https://github.com/shlinkio/shlink.git
synced 2025-02-25 18:45:27 -06:00
Standardized how inlined or regular specs are applied to query builders
This commit is contained in:
@@ -16,12 +16,6 @@ use Shlinkio\Shlink\Rest\ApiKey\Spec\WithApiKeySpecsEnsuringJoin;
|
||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||
|
||||
use function Functional\map;
|
||||
use function is_object;
|
||||
use function method_exists;
|
||||
use function sprintf;
|
||||
use function strlen;
|
||||
use function strpos;
|
||||
use function substr_replace;
|
||||
|
||||
use const PHP_INT_MAX;
|
||||
|
||||
@@ -60,24 +54,11 @@ class TagRepository extends EntitySpecificationRepository implements TagReposito
|
||||
}
|
||||
|
||||
$apiKey = $filtering?->apiKey();
|
||||
$this->applySpecification($subQb, $apiKey?->spec(false, 'shortUrls'), 't');
|
||||
$this->applySpecification($subQb, new WithApiKeySpecsEnsuringJoin($apiKey, 'shortUrls', true), 't');
|
||||
|
||||
$subQuery = $subQb->getQuery();
|
||||
$subQuerySql = $subQuery->getSQL();
|
||||
|
||||
// Sadly, we need to manually interpolate the params in the query replacing the placeholders, as this is going
|
||||
// to be used as a sub-query in a native query. There's no need to sanitize, though.
|
||||
foreach ($subQuery->getParameters() as $param) {
|
||||
$value = $param->getValue();
|
||||
$pos = strpos($subQuerySql, self::PARAM_PLACEHOLDER);
|
||||
$subQuerySql = substr_replace(
|
||||
$subQuerySql,
|
||||
sprintf('\'%s\'', is_object($value) && method_exists($value, 'getId') ? $value->getId() : $value),
|
||||
$pos === false ? -1 : $pos,
|
||||
strlen(self::PARAM_PLACEHOLDER),
|
||||
);
|
||||
}
|
||||
|
||||
// A native query builder needs to be used here, because DQL and ORM query builders do not support
|
||||
// sub-queries at "from" and "join" level.
|
||||
// If no sub-query is used, the whole list is loaded even with pagination, making it very inefficient.
|
||||
|
||||
@@ -105,7 +105,7 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
|
||||
$shortUrlRepo = $this->getEntityManager()->getRepository(ShortUrl::class);
|
||||
$shortUrlId = $shortUrlRepo->findOne($identifier, $filtering->apiKey()?->spec())?->getId() ?? '-1';
|
||||
|
||||
// Parameters in this query need to be part of the query itself, as we need to use it a sub-query later
|
||||
// Parameters in this query need to be part of the query itself, as we need to use it as sub-query later
|
||||
// Since they are not provided by the caller, it's reasonably safe
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
$qb->from(Visit::class, 'v')
|
||||
@@ -149,7 +149,7 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
|
||||
}
|
||||
|
||||
$this->applyDatesInline($qb, $filtering->dateRange());
|
||||
$this->applySpecification($qb, $filtering->apiKey()?->spec(true), 'v');
|
||||
$this->applySpecification($qb, $filtering->apiKey()?->inlinedSpec(), 'v');
|
||||
|
||||
return $qb;
|
||||
}
|
||||
@@ -174,7 +174,7 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
|
||||
$qb = $this->createAllVisitsQueryBuilder($filtering);
|
||||
$qb->andWhere($qb->expr()->isNotNull('v.shortUrl'));
|
||||
|
||||
$this->applySpecification($qb, $filtering->apiKey()?->spec(true));
|
||||
$this->applySpecification($qb, $filtering->apiKey()?->inlinedSpec());
|
||||
|
||||
return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit(), $filtering->offset());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user