Completed
Push — master ( a49287...23805c )
by Avtandil
14:39 queued 15s
created

ElasticsearchManager::createIndex()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 5
nop 3
dl 0
loc 26
rs 9.504
c 0
b 0
f 0
1
<?php
2
/*
3
 * This file is part of the Laravel Lodash package.
4
 *
5
 * (c) Avtandil Kikabidze aka LONGMAN <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
declare(strict_types=1);
11
12
namespace Longman\LaravelLodash\Elasticsearch;
13
14
use Elasticsearch\Client;
15
use InvalidArgumentException;
16
17
class ElasticsearchManager implements ElasticsearchManagerContract
18
{
19
    /** @var \Elasticsearch\Client */
20
    protected $client;
21
22
    /** @var bool */
23
    protected $enabled;
24
25
    /** @var int|null */
26
    protected $timeout;
27
28
    public function __construct(Client $client, bool $enabled = false)
29
    {
30
        $this->client = $client;
31
        $this->enabled = $enabled;
32
    }
33
34
    public function setEnabled(bool $enabled): ElasticsearchManagerContract
35
    {
36
        $this->enabled = $enabled;
37
38
        return $this;
39
    }
40
41
    public function setTimeout(int $timeout): ElasticsearchManagerContract
42
    {
43
        $this->timeout = $timeout;
44
45
        return $this;
46
    }
47
48
    public function createIndex(string $index_name, array $settings, array $mappings): void
49
    {
50
        if (! $this->isEnabled()) {
51
            return;
52
        }
53
54
        $params = [
55
            'index' => $index_name,
56
            'body'  => [
57
                'settings' => $settings,
58
                'mappings' => $mappings,
59
            ],
60
        ];
61
62
        if (! empty($this->timeout)) {
63
            $params['client'] = [
64
                'timeout' => $this->timeout,
65
            ];
66
        }
67
68
        $response = $this->client->indices()->create($params);
69
70
        if ($response['acknowledged'] !== true) {
71
            throw new ElasticsearchException('Something went wrong during index creation');
72
        }
73
    }
74
75
    public function deleteIndexes(array $names): void
76
    {
77
        if (! $this->isEnabled()) {
78
            return;
79
        }
80
        if (empty($names)) {
81
            throw new InvalidArgumentException('Index names can not be empty');
82
        }
83
84
        $params = [
85
            'index' => implode(',', $names),
86
        ];
87
88
        if (! empty($this->timeout)) {
89
            $params['client'] = [
90
                'timeout' => $this->timeout,
91
            ];
92
        }
93
94
        $response = $this->client->indices()->delete($params);
95
        if ($response['acknowledged'] !== true) {
96
            throw new ElasticsearchException('Something went wrong during index deletion');
97
        }
98
    }
99
100
    public function deleteIndexesByAlias(string $alias_name): void
101
    {
102
        if (! $this->isEnabled()) {
103
            return;
104
        }
105
106
        $params = [
107
            'name' => $alias_name,
108
        ];
109
110
        $response = $this->client->indices()->getAlias($params);
111
        if (empty($response)) {
112
            throw new ElasticsearchException('Can not get alias ' . $alias_name);
113
        }
114
115
        $indexes = array_keys($response);
116
        $this->deleteIndexes($indexes);
117
    }
118
119
    /**
120
     * @throws \Longman\LaravelLodash\Elasticsearch\ElasticsearchException
121
     */
122 View Code Duplication
    public function addDocumentsToIndex(string $index_name, string $type_name, array $items)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
123
    {
124
        if (! $this->isEnabled()) {
125
            return;
126
        }
127
128
        $params = [
129
            'body' => [],
130
        ];
131
132
        if (! empty($this->timeout)) {
133
            $params['client'] = [
134
                'timeout' => $this->timeout,
135
            ];
136
        }
137
138
        foreach ($items as $id => $item) {
139
            $params['body'][] = [
140
                'create' => [
141
                    '_index' => $index_name,
142
                    '_type'  => $type_name,
143
                    '_id'    => $id,
144
                ],
145
            ];
146
147
            $params['body'][] = $item;
148
        }
149
150
        $responses = $this->client->bulk($params);
151
        if ($responses['errors'] === true) {
152
            $this->handleBulkError($responses, 'Error occurred during bulk create');
0 ignored issues
show
Documentation introduced by
$responses is of type callable, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
153
        }
154
    }
155
156
    /**
157
     * @throws \Longman\LaravelLodash\Elasticsearch\ElasticsearchException
158
     */
159 View Code Duplication
    public function updateDocumentsInIndex(string $index_name, string $type_name, array $items)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
160
    {
161
        if (! $this->isEnabled()) {
162
            return;
163
        }
164
165
        $params = [
166
            'body' => [],
167
        ];
168
169
        if (! empty($this->timeout)) {
170
            $params['client'] = [
171
                'timeout' => $this->timeout,
172
            ];
173
        }
174
175
        foreach ($items as $id => $item) {
176
            $params['body'][] = [
177
                'update' => [
178
                    '_index' => $index_name,
179
                    '_type'  => $type_name,
180
                    '_id'    => $id,
181
                ],
182
            ];
183
184
            $params['body'][] = ['doc' => $item];
185
        }
186
187
        $responses = $this->client->bulk($params);
188
        if ($responses['errors'] === true) {
189
            $this->handleBulkError($responses, 'Error occurred during bulk update');
0 ignored issues
show
Documentation introduced by
$responses is of type callable, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
190
        }
191
    }
192
193
    /**
194
     * @throws \Longman\LaravelLodash\Elasticsearch\ElasticsearchException
195
     */
196 View Code Duplication
    public function addOrUpdateDocumentsInIndex(string $index_name, string $type_name, array $items)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
197
    {
198
        if (! $this->isEnabled()) {
199
            return;
200
        }
201
202
        $params = [
203
            'body' => [],
204
        ];
205
206
        if (! empty($this->timeout)) {
207
            $params['client'] = [
208
                'timeout' => $this->timeout,
209
            ];
210
        }
211
212
        foreach ($items as $id => $item) {
213
            $params['body'][] = [
214
                'index' => [
215
                    '_index' => $index_name,
216
                    '_type'  => $type_name,
217
                    '_id'    => $id,
218
                ],
219
            ];
220
221
            $params['body'][] = $item;
222
        }
223
224
        $responses = $this->client->bulk($params);
225
        if ($responses['errors'] === true) {
226
            $this->handleBulkError($responses, 'Error occurred during bulk index');
0 ignored issues
show
Documentation introduced by
$responses is of type callable, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
227
        }
228
    }
229
230
    /**
231
     * @throws \Longman\LaravelLodash\Elasticsearch\ElasticsearchException
232
     */
233
    protected function handleBulkError(array $responses, string $message)
234
    {
235
        $errors = [];
236
        foreach ($responses['items'] as $item) {
237
            $row = $item;
238
            $row = reset($row);
239
            if (! empty($row['error'])) {
240
                $errors[] = $row['error'];
241
            }
242
        }
243
244
        throw new ElasticsearchException($message, $errors);
245
    }
246
247 View Code Duplication
    public function refreshIndex(string $index_name): void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
248
    {
249
        if (! $this->isEnabled()) {
250
            return;
251
        }
252
253
        $params = [
254
            'index' => $index_name,
255
        ];
256
257
        if (! empty($this->timeout)) {
258
            $params['client'] = [
259
                'timeout' => $this->timeout,
260
            ];
261
        }
262
263
        $this->client->indices()->refresh($params);
264
    }
265
266 View Code Duplication
    public function performSearch(ElasticsearchQueryContract $query): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
267
    {
268
        if (! $this->isEnabled()) {
269
            return [];
270
        }
271
272
        $params = $query->build();
273
        if (! empty($this->timeout)) {
274
            $params['client'] = [
275
                'timeout' => $this->timeout,
276
            ];
277
        }
278
279
        $results = $this->client->search($params);
280
281
        return $results;
282
    }
283
284
    public function switchIndexAlias(string $alias_name, string $index_name): void
285
    {
286
        if (! $this->isEnabled()) {
287
            return;
288
        }
289
290
        $params = [
291
            'name' => $alias_name,
292
        ];
293
294
        $exists = $this->client->indices()->existsAlias($params);
295
296
        $actions = [];
297
        // If alias already exists remove from indexes
298
        if ($exists) {
299
            $params = [
300
                'name' => $alias_name,
301
            ];
302
303
            $response = $this->client->indices()->getAlias($params);
304
            if (empty($response)) {
305
                throw new ElasticsearchException('Can not get alias ' . $alias_name);
306
            }
307
308
            $indexes = array_keys($response);
309
310
            foreach ($indexes as $index) {
311
                $actions[] = [
312
                    'remove' => [
313
                        'index' => $index,
314
                        'alias' => $alias_name,
315
                    ],
316
                ];
317
            }
318
        }
319
320
        $actions[] = [
321
            'add' => [
322
                'index' => $index_name,
323
                'alias' => $alias_name,
324
            ],
325
        ];
326
327
        $params = [
328
            'body' => [
329
                'actions' => $actions,
330
            ],
331
        ];
332
333
        $response = $this->client->indices()->updateAliases($params);
334
        if ($response['acknowledged'] !== true) {
335
            throw new ElasticsearchException('Switching alias response error');
336
        }
337
    }
338
339
    public function createTemplate(string $name, array $settings): void
340
    {
341
        if (! $this->isEnabled()) {
342
            return;
343
        }
344
345
        $params = [
346
            'name' => $name,
347
            'body' => $settings,
348
        ];
349
350
        if (! empty($this->timeout)) {
351
            $params['client'] = [
352
                'timeout' => $this->timeout,
353
            ];
354
        }
355
356
        $response = $this->client->indices()->putTemplate($params);
357
358
        if ($response['acknowledged'] !== true) {
359
            throw new ElasticsearchException('Something went wrong during template creation');
360
        }
361
    }
362
363
    public function ping(): bool
364
    {
365
        if (! $this->isEnabled()) {
366
            return false;
367
        }
368
369
        return $this->client->ping();
370
    }
371
372
    public function getClient(): Client
373
    {
374
        return $this->client;
375
    }
376
377
    public function isEnabled(): bool
378
    {
379
        return $this->enabled;
380
    }
381
}
382