feat: put query functionality to QueryBuilderExtractor
This commit is contained in:
@@ -91,7 +91,7 @@ services:
|
||||
arguments:
|
||||
- !tagged 'app.service.scout.processor'
|
||||
|
||||
App\State\MoneyTotalStateProvider:
|
||||
App\State\QueryBuilderExtractor:
|
||||
arguments:
|
||||
- !tagged 'api_platform.doctrine.orm.query_extension.collection'
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\State;
|
||||
|
||||
use ApiPlatform\Doctrine\Orm\State\Options;
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
|
||||
trait EntityOperationStateTrait
|
||||
{
|
||||
/**
|
||||
* Extract the FQCN for the Entity behind a given Operation.
|
||||
*
|
||||
* @return string A FQCN
|
||||
*/
|
||||
public function getEntityClass(Operation $operation): string
|
||||
{
|
||||
$entityClass = $operation->getClass();
|
||||
|
||||
if (($options = $operation->getStateOptions()) && $options instanceof Options && $options->getEntityClass()) {
|
||||
$entityClass = $options->getEntityClass();
|
||||
}
|
||||
|
||||
return $entityClass;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\State;
|
||||
|
||||
use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator;
|
||||
use ApiPlatform\Metadata\Exception\RuntimeException;
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
class QueryBuilderExtractor
|
||||
{
|
||||
use EntityOperationStateTrait;
|
||||
|
||||
/**
|
||||
* @param iterable<QueryCollectionExtensionInterface> $collectionExtensions
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly iterable $collectionExtensions,
|
||||
private ManagerRegistry $managerRegistry,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Get the QueryBuilder behind a given API operation.
|
||||
*
|
||||
* @param callable(QueryCollectionExtensionInterface): bool|null $extensionFilter A function
|
||||
*
|
||||
* @return QueryBuilder The query builder for the given params
|
||||
*/
|
||||
public function getQueryBuilder(
|
||||
Operation $operation,
|
||||
array $context = [],
|
||||
?callable $extensionFilter = null,
|
||||
): QueryBuilder {
|
||||
$entityClass = $this->getEntityClass($operation);
|
||||
$manager = $this->managerRegistry->getManagerForClass($entityClass);
|
||||
$repository = $manager->getRepository($entityClass);
|
||||
if (!method_exists($repository, 'createQueryBuilder')) {
|
||||
throw new RuntimeException('The repository class must have a "createQueryBuilder" method.');
|
||||
}
|
||||
|
||||
$queryBuilder = $repository->createQueryBuilder('o');
|
||||
$queryNameGenerator = new QueryNameGenerator();
|
||||
|
||||
$extensionFilter ??= static fn($extension) => true;
|
||||
foreach ($this->getCollectionExtensions() as $extension) {
|
||||
if (!$extensionFilter($extension)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$extension->applyToCollection($queryBuilder, $queryNameGenerator, $entityClass, $operation, $context);
|
||||
}
|
||||
|
||||
return $queryBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the collection extensions injected by default.
|
||||
*
|
||||
* @return iterable<QueryCollectionExtensionInterface>
|
||||
*/
|
||||
public function getCollectionExtensions(): iterable
|
||||
{
|
||||
return $this->collectionExtensions;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user