* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare(strict_types=1); namespace ApiPlatform\Elasticsearch\State; use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; use ApiPlatform\Elasticsearch\Paginator; use ApiPlatform\Elasticsearch\Util\ElasticsearchVersion; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\Pagination\Pagination; use ApiPlatform\State\ProviderInterface; use Elasticsearch\Client; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; /** * Collection provider for Elasticsearch. * * @experimental * * @author Baptiste Meyer * @author Vincent Chalamon */ final class CollectionProvider implements ProviderInterface { private $client; private $documentMetadataFactory; private $denormalizer; private $pagination; private $collectionExtensions; /** * @param RequestBodySearchCollectionExtensionInterface[] $collectionExtensions */ public function __construct(Client $client, DocumentMetadataFactoryInterface $documentMetadataFactory, DenormalizerInterface $denormalizer, Pagination $pagination, iterable $collectionExtensions = []) { $this->client = $client; $this->documentMetadataFactory = $documentMetadataFactory; $this->denormalizer = $denormalizer; $this->pagination = $pagination; $this->collectionExtensions = $collectionExtensions; } /** * {@inheritdoc} */ public function provide(Operation $operation, array $uriVariables = [], array $context = []) { $resourceClass = $operation->getClass(); $operationName = $operation->getName(); $documentMetadata = $this->documentMetadataFactory->create($resourceClass); $body = []; foreach ($this->collectionExtensions as $collectionExtension) { $body = $collectionExtension->applyToCollection($body, $resourceClass, $operation, $context); } if (!isset($body['query']) && !isset($body['aggs'])) { $body['query'] = ['match_all' => new \stdClass()]; } $limit = $body['size'] = $body['size'] ?? $this->pagination->getLimit($operation, $context); $offset = $body['from'] = $body['from'] ?? $this->pagination->getOffset($operation, $context); $params = [ 'index' => $documentMetadata->getIndex(), 'body' => $body, ]; if (ElasticsearchVersion::supportsMappingType()) { $params['type'] = $documentMetadata->getType(); } $documents = $this->client->search($params); return new Paginator( $this->denormalizer, $documents, $resourceClass, $limit, $offset, $context ); } }