diff --git a/config/services.yaml b/config/services.yaml index 0bd2092..fbe65ed 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -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' diff --git a/src/State/EntityOperationStateTrait.php b/src/State/EntityOperationStateTrait.php new file mode 100644 index 0000000..abd8cb9 --- /dev/null +++ b/src/State/EntityOperationStateTrait.php @@ -0,0 +1,25 @@ +getClass(); + + if (($options = $operation->getStateOptions()) && $options instanceof Options && $options->getEntityClass()) { + $entityClass = $options->getEntityClass(); + } + + return $entityClass; + } +} diff --git a/src/State/QueryBuilderExtractor.php b/src/State/QueryBuilderExtractor.php new file mode 100644 index 0000000..d844150 --- /dev/null +++ b/src/State/QueryBuilderExtractor.php @@ -0,0 +1,67 @@ + $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 + */ + public function getCollectionExtensions(): iterable + { + return $this->collectionExtensions; + } +}