Passed
Pull Request — master (#1999)
by Antoine
02:58
created

CollectionDataProvider   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 77
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 9
eloc 40
dl 0
loc 77
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
B getCollection() 0 40 6
A supports() 0 9 2
1
<?php
2
3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider;
15
16
use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\FullBodySearchCollectionExtensionInterface;
17
use ApiPlatform\Core\Bridge\Elasticsearch\Exception\IndexNotFoundException;
18
use ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Factory\DocumentMetadataFactoryInterface;
19
use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface;
20
use ApiPlatform\Core\DataProvider\Pagination;
21
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
22
use Elasticsearch\Client;
23
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
24
25
/**
26
 * Collection data provider for Elasticsearch.
27
 *
28
 * @experimental
29
 *
30
 * @author Baptiste Meyer <[email protected]>
31
 */
32
final class CollectionDataProvider implements ContextAwareCollectionDataProviderInterface, RestrictedDataProviderInterface
33
{
34
    private $client;
35
    private $indexMetadataFactory;
36
    private $denormalizer;
37
    private $pagination;
38
    private $collectionExtensions;
39
40
    /**
41
     * @param FullBodySearchCollectionExtensionInterface[] $collectionExtensions
42
     */
43
    public function __construct(Client $client, DocumentMetadataFactoryInterface $indexMetadataFactory, DenormalizerInterface $denormalizer, Pagination $pagination, iterable $collectionExtensions = [])
44
    {
45
        $this->client = $client;
46
        $this->indexMetadataFactory = $indexMetadataFactory;
47
        $this->denormalizer = $denormalizer;
48
        $this->pagination = $pagination;
49
        $this->collectionExtensions = $collectionExtensions;
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55
    public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
56
    {
57
        try {
58
            $this->indexMetadataFactory->create($resourceClass);
59
        } catch (IndexNotFoundException $e) {
60
            return false;
61
        }
62
63
        return true;
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69
    public function getCollection(string $resourceClass, string $operationName = null, array $context = [])
70
    {
71
        $indexMetadata = $this->indexMetadataFactory->create($resourceClass);
72
        $body = [];
73
74
        foreach ($this->collectionExtensions as $collectionExtension) {
75
            $collectionExtension->applyToCollection($body, $resourceClass, $operationName, $context);
76
        }
77
78
        if (!isset($body['query']) && !isset($body['aggs'])) {
79
            $body = array_merge($body, [
80
                'query' => [
81
                    'match_all' => new \stdClass(),
82
                ],
83
            ]);
84
        }
85
86
        $limit = $body['size'] ?? $this->pagination->getLimit($resourceClass, $operationName);
87
        $offset = $body['offset'] ?? $this->pagination->getOffset($resourceClass, $operationName);
88
89
        if (!isset($body['size'])) {
90
            $body = array_merge($body, ['size' => $limit]);
91
        }
92
93
        if (!isset($body['from'])) {
94
            $body = array_merge($body, ['from' => $offset]);
95
        }
96
97
        $documents = $this->client->search([
98
            'index' => $indexMetadata->getIndex(),
99
            'type' => $indexMetadata->getType(),
100
            'body' => $body,
101
        ]);
102
103
        return new Paginator(
104
            $this->denormalizer,
105
            $documents,
106
            $resourceClass,
107
            $limit,
108
            $offset
109
        );
110
    }
111
}
112