Completed
Push — master ( ec75c5...ca1ddf )
by Nicolas
03:01
created

Index::requestEndpoint()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
namespace Elastica;
3
4
use Elastica\Exception\InvalidException;
5
use Elastica\Exception\ResponseException;
6
use Elastica\Index\Settings as IndexSettings;
7
use Elastica\Index\Stats as IndexStats;
8
use Elastica\ResultSet\BuilderInterface;
9
use Elasticsearch\Endpoints\AbstractEndpoint;
10
11
/**
12
 * Elastica index object.
13
 *
14
 * Handles reads, deletes and configurations of an index
15
 *
16
 * @author   Nicolas Ruflin <[email protected]>
17
 */
18
class Index implements SearchableInterface
19
{
20
    /**
21
     * Index name.
22
     *
23
     * @var string Index name
24
     */
25
    protected $_name;
26
27
    /**
28
     * Client object.
29
     *
30
     * @var \Elastica\Client Client object
31
     */
32
    protected $_client;
33
34
    /**
35
     * Creates a new index object.
36
     *
37
     * All the communication to and from an index goes of this object
38
     *
39
     * @param \Elastica\Client $client Client object
40
     * @param string           $name   Index name
41
     */
42 View Code Duplication
    public function __construct(Client $client, $name)
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...
43
    {
44
        $this->_client = $client;
45
46
        if (!is_scalar($name)) {
47
            throw new InvalidException('Index name should be a scalar type');
48
        }
49
        $this->_name = (string) $name;
50
    }
51
52
    /**
53
     * Returns a type object for the current index with the given name.
54
     *
55
     * @param string $type Type name
56
     *
57
     * @return \Elastica\Type Type object
58
     */
59
    public function getType($type)
60
    {
61
        return new Type($this, $type);
62
    }
63
64
    /**
65
     * Return Index Stats.
66
     *
67
     * @return \Elastica\Index\Stats
68
     */
69
    public function getStats()
70
    {
71
        return new IndexStats($this);
72
    }
73
74
    /**
75
     * Gets all the type mappings for an index.
76
     *
77
     * @return array
78
     */
79 View Code Duplication
    public function getMapping()
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...
80
    {
81
        $path = '_mapping';
82
83
        $response = $this->request($path, Request::GET);
84
        $data = $response->getData();
85
86
        // Get first entry as if index is an Alias, the name of the mapping is the real name and not alias name
87
        $mapping = array_shift($data);
88
89
        if (isset($mapping['mappings'])) {
90
            return $mapping['mappings'];
91
        }
92
93
        return [];
94
    }
95
96
    /**
97
     * Returns the index settings object.
98
     *
99
     * @return \Elastica\Index\Settings Settings object
100
     */
101
    public function getSettings()
102
    {
103
        return new IndexSettings($this);
104
    }
105
106
    /**
107
     * Uses _bulk to send documents to the server.
108
     *
109
     * @param array|\Elastica\Document[] $docs Array of Elastica\Document
110
     *
111
     * @return \Elastica\Bulk\ResponseSet
112
     *
113
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
114
     */
115
    public function updateDocuments(array $docs)
116
    {
117
        foreach ($docs as $doc) {
118
            $doc->setIndex($this->getName());
119
        }
120
121
        return $this->getClient()->updateDocuments($docs);
122
    }
123
124
    /**
125
     * Uses _bulk to send documents to the server.
126
     *
127
     * @param array|\Elastica\Document[] $docs Array of Elastica\Document
128
     *
129
     * @return \Elastica\Bulk\ResponseSet
130
     *
131
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
132
     */
133
    public function addDocuments(array $docs)
134
    {
135
        foreach ($docs as $doc) {
136
            $doc->setIndex($this->getName());
137
        }
138
139
        return $this->getClient()->addDocuments($docs);
140
    }
141
142
    /**
143
     * Deletes entries in the db based on a query.
144
     *
145
     * @param \Elastica\Query|string|array $query   Query object or array
146
     * @param array                        $options Optional params
147
     *
148
     * @return \Elastica\Response
149
     *
150
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/5.0/docs-delete-by-query.html
151
     */
152
    public function deleteByQuery($query, array $options = [])
153
    {
154
        $query = Query::create($query)->getQuery();
155
156
        return $this->request('_delete_by_query', Request::POST, ['query' => is_array($query) ? $query : $query->toArray()], $options);
157
    }
158
159
    /**
160
     * Deletes the index.
161
     *
162
     * @return \Elastica\Response Response object
163
     */
164
    public function delete()
165
    {
166
        $response = $this->request('', Request::DELETE);
167
168
        return $response;
169
    }
170
171
    /**
172
     * Uses _bulk to delete documents from the server.
173
     *
174
     * @param array|\Elastica\Document[] $docs Array of Elastica\Document
175
     *
176
     * @return \Elastica\Bulk\ResponseSet
177
     *
178
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
179
     */
180
    public function deleteDocuments(array $docs)
181
    {
182
        foreach ($docs as $doc) {
183
            $doc->setIndex($this->getName());
184
        }
185
186
        return $this->getClient()->deleteDocuments($docs);
187
    }
188
189
    /**
190
     * Optimizes search index.
191
     *
192
     * Detailed arguments can be found here in the link
193
     *
194
     * @param array $args OPTIONAL Additional arguments
195
     *
196
     * @return array Server response
197
     *
198
     * @deprecated Replaced by forcemerge
199
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-optimize.html
200
     */
201
    public function optimize($args = [])
202
    {
203
        trigger_error('Deprecated: Elastica\Index::optimize() is deprecated and will be removed in further Elastica releases. Use Elastica\Index::forcemerge() instead.', E_USER_DEPRECATED);
204
205
        return $this->forcemerge($args);
206
    }
207
208
    /**
209
     * Force merges index.
210
     *
211
     * Detailed arguments can be found here in the link
212
     *
213
     * @param array $args OPTIONAL Additional arguments
214
     *
215
     * @return array Server response
216
     *
217
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html
218
     */
219
    public function forcemerge($args = [])
220
    {
221
        return $this->request('_forcemerge', Request::POST, [], $args);
222
    }
223
224
    /**
225
     * Refreshes the index.
226
     *
227
     * @return \Elastica\Response Response object
228
     *
229
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html
230
     */
231
    public function refresh()
232
    {
233
        return $this->request('_refresh', Request::POST, []);
234
    }
235
236
    /**
237
     * Creates a new index with the given arguments.
238
     *
239
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html
240
     *
241
     * @param array      $args    OPTIONAL Arguments to use
242
     * @param bool|array $options OPTIONAL
243
     *                            bool=> Deletes index first if already exists (default = false).
244
     *                            array => Associative array of options (option=>value)
245
     *
246
     * @throws \Elastica\Exception\InvalidException
247
     * @throws \Elastica\Exception\ResponseException
248
     *
249
     * @return \Elastica\Response Server response
250
     */
251
    public function create(array $args = [], $options = null)
252
    {
253
        if (is_bool($options) && $options) {
254
            try {
255
                $this->delete();
256
            } catch (ResponseException $e) {
257
                // Table can't be deleted, because doesn't exist
258
            }
259
        } elseif (is_array($options)) {
260
            foreach ($options as $key => $value) {
261
                switch ($key) {
262
                    case 'recreate':
263
                        try {
264
                            $this->delete();
265
                        } catch (ResponseException $e) {
266
                            // Table can't be deleted, because doesn't exist
267
                        }
268
                        break;
269
                    default:
270
                        throw new InvalidException('Invalid option '.$key);
271
                        break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
272
                }
273
            }
274
        }
275
276
        return $this->request('', Request::PUT, $args);
277
    }
278
279
    /**
280
     * Checks if the given index is already created.
281
     *
282
     * @return bool True if index exists
283
     */
284
    public function exists()
285
    {
286
        $response = $this->getClient()->request($this->getName(), Request::HEAD);
287
288
        return $response->getStatus() === 200;
289
    }
290
291
    /**
292
     * @param string|array|\Elastica\Query $query
293
     * @param int|array                    $options
294
     * @param BuilderInterface             $builder
295
     *
296
     * @return Search
297
     */
298
    public function createSearch($query = '', $options = null, BuilderInterface $builder = null)
299
    {
300
        $search = new Search($this->getClient(), $builder);
301
        $search->addIndex($this);
302
        $search->setOptionsAndQuery($options, $query);
303
304
        return $search;
305
    }
306
307
    /**
308
     * Searches in this index.
309
     *
310
     * @param string|array|\Elastica\Query $query   Array with all query data inside or a Elastica\Query object
311
     * @param int|array                    $options OPTIONAL Limit or associative array of options (option=>value)
312
     *
313
     * @return \Elastica\ResultSet with all results inside
314
     *
315
     * @see \Elastica\SearchableInterface::search
316
     */
317
    public function search($query = '', $options = null)
318
    {
319
        $search = $this->createSearch($query, $options);
320
321
        return $search->search();
322
    }
323
324
    /**
325
     * Counts results of query.
326
     *
327
     * @param string|array|\Elastica\Query $query Array with all query data inside or a Elastica\Query object
328
     *
329
     * @return int number of documents matching the query
330
     *
331
     * @see \Elastica\SearchableInterface::count
332
     */
333
    public function count($query = '')
334
    {
335
        $search = $this->createSearch($query);
336
337
        return $search->count();
0 ignored issues
show
Bug Compatibility introduced by
The expression $search->count(); of type Elastica\ResultSet|integer adds the type Elastica\ResultSet to the return on line 337 which is incompatible with the return type declared by the interface Elastica\SearchableInterface::count of type integer.
Loading history...
338
    }
339
340
    /**
341
     * Opens an index.
342
     *
343
     * @return \Elastica\Response Response object
344
     *
345
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-open-close.html
346
     */
347
    public function open()
348
    {
349
        return $this->request('_open', Request::POST);
350
    }
351
352
    /**
353
     * Closes the index.
354
     *
355
     * @return \Elastica\Response Response object
356
     *
357
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-open-close.html
358
     */
359
    public function close()
360
    {
361
        return $this->request('_close', Request::POST);
362
    }
363
364
    /**
365
     * Returns the index name.
366
     *
367
     * @return string Index name
368
     */
369
    public function getName()
370
    {
371
        return $this->_name;
372
    }
373
374
    /**
375
     * Returns index client.
376
     *
377
     * @return \Elastica\Client Index client object
378
     */
379
    public function getClient()
380
    {
381
        return $this->_client;
382
    }
383
384
    /**
385
     * Adds an alias to the current index.
386
     *
387
     * @param string $name    Alias name
388
     * @param bool   $replace OPTIONAL If set, an existing alias will be replaced
389
     *
390
     * @return \Elastica\Response Response
391
     *
392
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html
393
     */
394
    public function addAlias($name, $replace = false)
395
    {
396
        $path = '_aliases';
397
398
        $data = ['actions' => []];
399
400
        if ($replace) {
401
            $status = new Status($this->getClient());
402
            foreach ($status->getIndicesWithAlias($name) as $index) {
403
                $data['actions'][] = ['remove' => ['index' => $index->getName(), 'alias' => $name]];
404
            }
405
        }
406
407
        $data['actions'][] = ['add' => ['index' => $this->getName(), 'alias' => $name]];
408
409
        return $this->getClient()->request($path, Request::POST, $data);
410
    }
411
412
    /**
413
     * Removes an alias pointing to the current index.
414
     *
415
     * @param string $name Alias name
416
     *
417
     * @return \Elastica\Response Response
418
     *
419
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html
420
     */
421
    public function removeAlias($name)
422
    {
423
        $path = '_aliases';
424
425
        $data = ['actions' => [['remove' => ['index' => $this->getName(), 'alias' => $name]]]];
426
427
        return $this->getClient()->request($path, Request::POST, $data);
428
    }
429
430
    /**
431
     * Returns all index aliases.
432
     *
433
     * @return array Aliases
434
     */
435
    public function getAliases()
436
    {
437
        $responseData = $this->request('_alias/*', Request::GET)->getData();
438
439
        if (!isset($responseData[$this->getName()])) {
440
            return [];
441
        }
442
443
        $data = $responseData[$this->getName()];
444
        if (!empty($data['aliases'])) {
445
            return array_keys($data['aliases']);
446
        }
447
448
        return [];
449
    }
450
451
    /**
452
     * Checks if the index has the given alias.
453
     *
454
     * @param string $name Alias name
455
     *
456
     * @return bool
457
     */
458
    public function hasAlias($name)
459
    {
460
        return in_array($name, $this->getAliases());
461
    }
462
463
    /**
464
     * Clears the cache of an index.
465
     *
466
     * @return \Elastica\Response Response object
467
     *
468
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-clearcache.html
469
     */
470
    public function clearCache()
471
    {
472
        $path = '_cache/clear';
473
        // TODO: add additional cache clean arguments
474
        return $this->request($path, Request::POST);
475
    }
476
477
    /**
478
     * Flushes the index to storage.
479
     *
480
     * @param array $options
481
     *
482
     * @return Response Response object
483
     *
484
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-flush.html
485
     */
486
    public function flush(array $options = [])
487
    {
488
        $path = '_flush';
489
490
        return $this->request($path, Request::POST, [], $options);
491
    }
492
493
    /**
494
     * Can be used to change settings during runtime. One example is to use it for bulk updating.
495
     *
496
     * @param array $data Data array
497
     *
498
     * @return \Elastica\Response Response object
499
     *
500
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html
501
     */
502
    public function setSettings(array $data)
503
    {
504
        return $this->request('_settings', Request::PUT, $data);
505
    }
506
507
    /**
508
     * Makes calls to the elasticsearch server based on this index.
509
     *
510
     * @param string       $path   Path to call
511
     * @param string       $method Rest method to use (GET, POST, DELETE, PUT)
512
     * @param array|string $data   OPTIONAL Arguments as array or encoded string
513
     * @param array        $query  OPTIONAL Query params
514
     *
515
     * @return \Elastica\Response Response object
516
     */
517
    public function request($path, $method, $data = [], array $query = [])
518
    {
519
        $path = $this->getName().'/'.$path;
520
521
        return $this->getClient()->request($path, $method, $data, $query);
522
    }
523
524
    /**
525
     * Makes calls to the elasticsearch server with usage official client Endpoint based on this index
526
     *
527
     * @param AbstractEndpoint $endpoint
528
     * @return Response
529
     */
530
    public function requestEndpoint(AbstractEndpoint $endpoint)
531
    {
532
        $cloned = clone $endpoint;
533
        $cloned->setIndex($this->getName());
534
        return $this->getClient()->requestEndpoint($cloned);
535
    }
536
537
    /**
538
     * Analyzes a string.
539
     *
540
     * Detailed arguments can be found here in the link
541
     *
542
     * @param string $text String to be analyzed
543
     * @param array  $args OPTIONAL Additional arguments
544
     *
545
     * @return array Server response
546
     *
547
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-analyze.html
548
     */
549
    public function analyze($text, $args = [])
550
    {
551
        $data = $this->request('_analyze', Request::POST, $text, $args)->getData();
552
553
        // Support for "Explain" parameter, that returns a different response structure from Elastic
554
        // @see: https://www.elastic.co/guide/en/elasticsearch/reference/current/_explain_analyze.html
555
        if (isset($args['explain']) && $args['explain']) {
556
            return $data['detail'];
557
        }
558
559
        return $data['tokens'];
560
    }
561
}
562