Completed
Push — master ( 2c1f3d...7a9a35 )
by Adam
05:47
created

Search/Adapter/Algolia/AlgoliaSearchAdapter.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/*
3
 * WellCommerce Open-Source E-Commerce Platform
4
 * 
5
 * This file is part of the WellCommerce package.
6
 *
7
 * (c) Adam Piotrowski <[email protected]>
8
 * 
9
 * For the full copyright and license information,
10
 * please view the LICENSE file that was distributed with this source code.
11
 */
12
13
namespace WellCommerce\Component\Search\Adapter\Algolia;
14
15
use AlgoliaSearch\Client;
16
use Doctrine\Common\Collections\Collection;
17
use Symfony\Component\OptionsResolver\OptionsResolver;
18
use WellCommerce\Component\Search\Adapter\AdapterInterface;
19
use WellCommerce\Component\Search\Adapter\QueryBuilderInterface;
20
use WellCommerce\Component\Search\Model\DocumentInterface;
21
use WellCommerce\Component\Search\Model\FieldInterface;
22
use WellCommerce\Component\Search\Request\SearchRequestInterface;
23
24
/**
25
 * Class AlgoliaSearchAdapter
26
 *
27
 * @author  Adam Piotrowski <[email protected]>
28
 */
29
final class AlgoliaSearchAdapter implements AdapterInterface
30
{
31
    /**
32
     * @var array
33
     */
34
    private $options = [];
35
    
36
    /**
37
     * @var Client
38
     */
39
    private $client;
40
    
41
    /**
42
     * ElasticSearchAdapter constructor.
43
     *
44
     * @param array $options
45
     */
46
    public function __construct(array $options = [])
47
    {
48
        $resolver = new OptionsResolver();
49
        $this->configureOptions($resolver);
50
        $this->options = $resolver->resolve($options);
51
    }
52
    
53
    public function search(SearchRequestInterface $request): array
54
    {
55
        $indexName = $this->getIndexName($request->getLocale(), $request->getType()->getName());
56
        $index     = $this->getClient()->initIndex($indexName);
57
        $body      = $this->createQueryBuilder($request)->getQuery();
58
        $results   = $index->search($request->getPhrase(), [
59
            'attributesToRetrieve' => $body,
60
            'hitsPerPage'          => $this->options['result_limit'],
61
        ]);
62
        
63
        return $this->processResults($results);
64
    }
65
    
66
    public function addDocument(DocumentInterface $document)
67
    {
68
        $indexName = $this->getIndexName($document->getLocale(), $document->getType()->getName());
69
        $index     = $this->getClient()->initIndex($indexName);
70
        
71
        $index->addObject($this->createDocumentBody($document), $document->getIdentifier());
72
    }
73
    
74
    public function addDocuments(Collection $documents, string $locale, string $type)
75
    {
76
        $request = [];
77
        
78
        $documents->map(function (DocumentInterface $document) use (&$request) {
79
            $body             = $this->createDocumentBody($document);
80
            $body['objectID'] = $document->getIdentifier();
81
            $request[]        = $body;
82
        });
83
        
84
        $indexName = $this->getIndexName($locale, $type);
85
        $index     = $this->getClient()->initIndex($indexName);
86
        
87
        if (!empty($request)) {
88
            $index->addObjects($request);
89
        }
90
    }
91
    
92
    public function removeDocument(DocumentInterface $document)
93
    {
94
        $indexName = $this->getIndexName($document->getLocale(), $document->getType()->getName());
95
        $index     = $this->getClient()->initIndex($indexName);
96
        
97
        $index->deleteObject($document->getIdentifier());
98
    }
99
    
100
    public function updateDocument(DocumentInterface $document)
101
    {
102
        $indexName        = $this->getIndexName($document->getLocale(), $document->getType()->getName());
103
        $index            = $this->getClient()->initIndex($indexName);
104
        $body             = $this->createDocumentBody($document);
105
        $body['objectID'] = $document->getIdentifier();
106
        
107
        $index->saveObject($body);
108
    }
109
    
110
    public function getIndexName(string $locale, string $type): string
111
    {
112
        return sprintf('%s%s_%s', $this->options['index_prefix'], $locale, $type);
113
    }
114
    
115
    public function createIndex(string $locale, string $type)
116
    {
117
    }
118
    
119
    public function removeIndex(string $locale, string $type)
120
    {
121
        $indexName = $this->getIndexName($locale, $type);
122
        
123
        return $this->getClient()->deleteIndex($indexName);
124
    }
125
    
126
    public function flushIndex(string $locale, string $type)
127
    {
128
        $indexName = $this->getIndexName($locale, $type);
129
        $index     = $this->getClient()->initIndex($indexName);
130
        
131
        return $index->clearIndex();
132
    }
133
    
134
    public function getStats(string $locale)
0 ignored issues
show
The parameter $locale is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
135
    {
136
        return $this->getClient()->getLogs(0, 100);
137
    }
138
    
139
    private function createQueryBuilder(SearchRequestInterface $request): QueryBuilderInterface
140
    {
141
        return new $this->options['query_builder_class']($request, $this->options['query_min_length']);
142
    }
143
    
144
    private function configureOptions(OptionsResolver $resolver)
145
    {
146
        $resolver->setRequired([
147
            'app_id',
148
            'app_key',
149
            'result_limit',
150
            'index_prefix',
151
            'query_builder_class',
152
        ]);
153
        
154
        $resolver->setDefault('query_min_length', 3);
155
        $resolver->setDefault('result_limit', 100);
156
        $resolver->setDefault('query_builder_class', AlgoliaQueryBuilder::class);
157
        
158
        $resolver->setAllowedTypes('app_id', 'string');
159
        $resolver->setAllowedTypes('app_key', 'string');
160
        $resolver->setAllowedTypes('index_prefix', 'string');
161
        $resolver->setAllowedTypes('query_min_length', 'integer');
162
        $resolver->setAllowedTypes('result_limit', 'integer');
163
        $resolver->setAllowedTypes('query_builder_class', 'string');
164
    }
165
    
166
    private function createDocumentBody(DocumentInterface $document): array
167
    {
168
        $body = [];
169
        
170
        $document->getFields()->map(function (FieldInterface $field) use (&$body) {
171
            $body[$field->getName()] = $field->getValue();
172
        });
173
        
174
        return $body;
175
    }
176
    
177
    private function getClient(): Client
178
    {
179
        if (null === $this->client) {
180
            $this->client = new Client($this->options['app_id'], $this->options['app_key']);
181
        }
182
        
183
        return $this->client;
184
    }
185
    
186
    private function processResults(array $results): array
187
    {
188
        $identifiers = [];
189
        
190
        foreach ($results['hits'] as $hit) {
191
            $identifiers[] = $hit['objectID'];
192
        }
193
        
194
        return $identifiers;
195
    }
196
}
197