Completed
Pull Request — master (#1017)
by Tim
05:07
created

Client::getLastResponse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Elastica;
4
5
use Elastica\Bulk\Action;
6
use Elastica\Exception\ConnectionException;
7
use Elastica\Exception\InvalidException;
8
use Elastica\Exception\RuntimeException;
9
use Elastica\ResultSet\Builder;
10
use Elastica\ResultSet\BuilderInterface;
11
use Elastica\Script\AbstractScript;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Elastica\AbstractScript.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
12
use Psr\Log\LoggerInterface;
13
14
/**
15
 * Client to connect the the elasticsearch server.
16
 *
17
 * @author Nicolas Ruflin <[email protected]>
18
 */
19
class Client
20
{
21
    /**
22
     * Config with defaults.
23
     *
24
     * log: Set to true, to enable logging, set a string to log to a specific file
25
     * retryOnConflict: Use in \Elastica\Client::updateDocument
26
     * bigintConversion: Set to true to enable the JSON bigint to string conversion option (see issue #717)
27
     *
28
     * @var array
29
     */
30
    protected $_config = array(
31
        'host' => null,
32
        'port' => null,
33
        'path' => null,
34
        'url' => null,
35
        'proxy' => null,
36
        'transport' => null,
37
        'persistent' => true,
38
        'timeout' => null,
39
        'connections' => array(), // host, port, path, timeout, transport, compression, persistent, timeout, config -> (curl, headers, url)
40
        'roundRobin' => false,
41
        'log' => false,
42
        'retryOnConflict' => 0,
43
        'bigintConversion' => false,
44
        'username' => null,
45
        'password' => null,
46
    );
47
48
    /**
49
     * @var callback
50
     */
51
    protected $_callback = null;
52
53
    /**
54
     * @var Connection\ConnectionPool
55
     */
56
    protected $_connectionPool = null;
57
58
    /**
59
     * @var \Elastica\Request
60
     */
61
    protected $_lastRequest;
62
63
    /**
64
     * @var \Elastica\Response
65
     */
66
    protected $_lastResponse;
67
68
    /**
69
     * @var LoggerInterface
70
     */
71
    protected $_logger = null;
72
73
    /**
74
     * @var BuilderInterface
75
     */
76
    private $_resultSetBuilder;
77
78
    /**
79
     * Creates a new Elastica client.
80
     *
81
     * @param array $config OPTIONAL Additional config options
82
     * @param callback $callback OPTIONAL Callback function which can be used to be notified about errors (for example connection down)
83
     * @param BuilderInterface $resultSetBuilder
84
     */
85
    public function __construct(array $config = array(), $callback = null, BuilderInterface $resultSetBuilder = null)
86
    {
87
        $this->_resultSetBuilder = $resultSetBuilder ?: new Builder();
88
89
        $this->setConfig($config);
90
        $this->_callback = $callback;
91
        $this->_initConnections();
92
    }
93
94
    /**
95
     * Inits the client connections.
96
     */
97
    protected function _initConnections()
98
    {
99
        $connections = array();
100
101
        foreach ($this->getConfig('connections') as $connection) {
0 ignored issues
show
Bug introduced by
The expression $this->getConfig('connections') of type array|string is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
102
            $connections[] = Connection::create($this->_prepareConnectionParams($connection));
103
        }
104
105
        if (isset($this->_config['servers'])) {
106
            foreach ($this->getConfig('servers') as $server) {
0 ignored issues
show
Bug introduced by
The expression $this->getConfig('servers') of type array|string is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
107
                $connections[] = Connection::create($this->_prepareConnectionParams($server));
108
            }
109
        }
110
111
        // If no connections set, create default connection
112
        if (empty($connections)) {
113
            $connections[] = Connection::create($this->_prepareConnectionParams($this->getConfig()));
0 ignored issues
show
Bug introduced by
It seems like $this->getConfig() targeting Elastica\Client::getConfig() can also be of type string; however, Elastica\Client::_prepareConnectionParams() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
114
        }
115
116
        if (!isset($this->_config['connectionStrategy'])) {
117
            if ($this->getConfig('roundRobin') === true) {
118
                $this->setConfigValue('connectionStrategy', 'RoundRobin');
119
            } else {
120
                $this->setConfigValue('connectionStrategy', 'Simple');
121
            }
122
        }
123
124
        $strategy = Connection\Strategy\StrategyFactory::create($this->getConfig('connectionStrategy'));
125
126
        $this->_connectionPool = new Connection\ConnectionPool($connections, $strategy, $this->_callback);
127
    }
128
129
    /**
130
     * Creates a Connection params array from a Client or server config array.
131
     *
132
     * @param array $config
133
     *
134
     * @return array
135
     */
136
    protected function _prepareConnectionParams(array $config)
137
    {
138
        $params = array();
139
        $params['config'] = array();
140
        foreach ($config as $key => $value) {
141
            if (in_array($key, array('bigintConversion', 'curl', 'headers', 'url'))) {
142
                $params['config'][$key] = $value;
143
            } else {
144
                $params[$key] = $value;
145
            }
146
        }
147
148
        return $params;
149
    }
150
151
    /**
152
     * Sets specific config values (updates and keeps default values).
153
     *
154
     * @param array $config Params
155
     *
156
     * @return $this
157
     */
158
    public function setConfig(array $config)
159
    {
160
        foreach ($config as $key => $value) {
161
            $this->_config[$key] = $value;
162
        }
163
164
        return $this;
165
    }
166
167
    /**
168
     * Returns a specific config key or the whole
169
     * config array if not set.
170
     *
171
     * @param string $key Config key
172
     *
173
     * @throws \Elastica\Exception\InvalidException
174
     *
175
     * @return array|string Config value
176
     */
177
    public function getConfig($key = '')
178
    {
179
        if (empty($key)) {
180
            return $this->_config;
181
        }
182
183
        if (!array_key_exists($key, $this->_config)) {
184
            throw new InvalidException('Config key is not set: '.$key);
185
        }
186
187
        return $this->_config[$key];
188
    }
189
190
    /**
191
     * Sets / overwrites a specific config value.
192
     *
193
     * @param string $key   Key to set
194
     * @param mixed  $value Value
195
     *
196
     * @return $this
197
     */
198
    public function setConfigValue($key, $value)
199
    {
200
        return $this->setConfig(array($key => $value));
201
    }
202
203
    /**
204
     * @param array|string $keys    config key or path of config keys
205
     * @param mixed        $default default value will be returned if key was not found
206
     *
207
     * @return mixed
208
     */
209
    public function getConfigValue($keys, $default = null)
210
    {
211
        $value = $this->_config;
212
        foreach ((array) $keys as $key) {
213
            if (isset($value[$key])) {
214
                $value = $value[$key];
215
            } else {
216
                return $default;
217
            }
218
        }
219
220
        return $value;
221
    }
222
223
    /**
224
     * Returns the index for the given connection.
225
     *
226
     * @param string $name Index name to create connection to
227
     *
228
     * @return \Elastica\Index Index for the given name
229
     */
230
    public function getIndex($name)
231
    {
232
        return new Index($this, $name, $this->_resultSetBuilder);
0 ignored issues
show
Unused Code introduced by
The call to Index::__construct() has too many arguments starting with $this->_resultSetBuilder.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
233
    }
234
235
    /**
236
     * Adds a HTTP Header.
237
     *
238
     * @param string $header      The HTTP Header
239
     * @param string $headerValue The HTTP Header Value
240
     *
241
     * @throws \Elastica\Exception\InvalidException If $header or $headerValue is not a string
242
     *
243
     * @return $this
244
     */
245 View Code Duplication
    public function addHeader($header, $headerValue)
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...
246
    {
247
        if (is_string($header) && is_string($headerValue)) {
248
            $this->_config['headers'][$header] = $headerValue;
249
        } else {
250
            throw new InvalidException('Header must be a string');
251
        }
252
253
        return $this;
254
    }
255
256
    /**
257
     * Remove a HTTP Header.
258
     *
259
     * @param string $header The HTTP Header to remove
260
     *
261
     * @throws \Elastica\Exception\InvalidException If $header is not a string
262
     *
263
     * @return $this
264
     */
265 View Code Duplication
    public function removeHeader($header)
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...
266
    {
267
        if (is_string($header)) {
268
            if (array_key_exists($header, $this->_config['headers'])) {
269
                unset($this->_config['headers'][$header]);
270
            }
271
        } else {
272
            throw new InvalidException('Header must be a string');
273
        }
274
275
        return $this;
276
    }
277
278
    /**
279
     * Uses _bulk to send documents to the server.
280
     *
281
     * Array of \Elastica\Document as input. Index and type has to be
282
     * set inside the document, because for bulk settings documents,
283
     * documents can belong to any type and index
284
     *
285
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
286
     *
287
     * @param array|\Elastica\Document[] $docs Array of Elastica\Document
288
     *
289
     * @throws \Elastica\Exception\InvalidException If docs is empty
290
     *
291
     * @return \Elastica\Bulk\ResponseSet Response object
292
     */
293 View Code Duplication
    public function updateDocuments(array $docs)
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...
294
    {
295
        if (empty($docs)) {
296
            throw new InvalidException('Array has to consist of at least one element');
297
        }
298
299
        $bulk = new Bulk($this);
300
301
        $bulk->addDocuments($docs, \Elastica\Bulk\Action::OP_TYPE_UPDATE);
302
303
        return $bulk->send();
304
    }
305
306
    /**
307
     * Uses _bulk to send documents to the server.
308
     *
309
     * Array of \Elastica\Document as input. Index and type has to be
310
     * set inside the document, because for bulk settings documents,
311
     * documents can belong to any type and index
312
     *
313
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
314
     *
315
     * @param array|\Elastica\Document[] $docs Array of Elastica\Document
316
     *
317
     * @throws \Elastica\Exception\InvalidException If docs is empty
318
     *
319
     * @return \Elastica\Bulk\ResponseSet Response object
320
     */
321 View Code Duplication
    public function addDocuments(array $docs)
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...
322
    {
323
        if (empty($docs)) {
324
            throw new InvalidException('Array has to consist of at least one element');
325
        }
326
327
        $bulk = new Bulk($this);
328
329
        $bulk->addDocuments($docs);
330
331
        return $bulk->send();
332
    }
333
334
    /**
335
     * Update document, using update script. Requires elasticsearch >= 0.19.0.
336
     *
337
     * @param int                                                      $id      document id
338
     * @param array|\Elastica\Script\AbstractScript|\Elastica\Document $data    raw data for request body
339
     * @param string                                                   $index   index to update
340
     * @param string                                                   $type    type of index to update
341
     * @param array                                                    $options array of query params to use for query. For possible options check es api
342
     *
343
     * @return \Elastica\Response
344
     *
345
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html
346
     */
347
    public function updateDocument($id, $data, $index, $type, array $options = array())
348
    {
349
        $path = $index.'/'.$type.'/'.$id.'/_update';
350
351
        if ($data instanceof AbstractScript) {
352
            $requestData = $data->toArray();
353
        } elseif ($data instanceof Document) {
354
            $requestData = array('doc' => $data->getData());
355
356
            if ($data->getDocAsUpsert()) {
357
                $requestData['doc_as_upsert'] = true;
358
            }
359
360
            $docOptions = $data->getOptions(
361
                array(
362
                    'version',
363
                    'version_type',
364
                    'routing',
365
                    'percolate',
366
                    'parent',
367
                    'fields',
368
                    'retry_on_conflict',
369
                    'consistency',
370
                    'replication',
371
                    'refresh',
372
                    'timeout',
373
                )
374
            );
375
            $options += $docOptions;
376
            // set fields param to source only if options was not set before
377
            if ($data instanceof Document && ($data->isAutoPopulate()
378
                || $this->getConfigValue(array('document', 'autoPopulate'), false))
379
                && !isset($options['fields'])
380
            ) {
381
                $options['fields'] = '_source';
382
            }
383
        } else {
384
            $requestData = $data;
385
        }
386
387
        //If an upsert document exists
388
        if ($data instanceof AbstractScript || $data instanceof Document) {
389
            if ($data->hasUpsert()) {
390
                $requestData['upsert'] = $data->getUpsert()->getData();
391
            }
392
        }
393
394
        if (!isset($options['retry_on_conflict'])) {
395
            $retryOnConflict = $this->getConfig('retryOnConflict');
396
            $options['retry_on_conflict'] = $retryOnConflict;
397
        }
398
399
        $response = $this->request($path, Request::POST, $requestData, $options);
400
401 View Code Duplication
        if ($response->isOk()
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
402
            && $data instanceof Document
403
            && ($data->isAutoPopulate() || $this->getConfigValue(array('document', 'autoPopulate'), false))
404
        ) {
405
            $responseData = $response->getData();
406
            if (isset($responseData['_version'])) {
407
                $data->setVersion($responseData['_version']);
408
            }
409
            if (isset($options['fields'])) {
410
                $this->_populateDocumentFieldsFromResponse($response, $data, $options['fields']);
411
            }
412
        }
413
414
        return $response;
415
    }
416
417
    /**
418
     * @param \Elastica\Response $response
419
     * @param \Elastica\Document $document
420
     * @param string             $fields   Array of field names to be populated or '_source' if whole document data should be updated
421
     */
422
    protected function _populateDocumentFieldsFromResponse(Response $response, Document $document, $fields)
423
    {
424
        $responseData = $response->getData();
425
        if ('_source' == $fields) {
426
            if (isset($responseData['get']['_source']) && is_array($responseData['get']['_source'])) {
427
                $document->setData($responseData['get']['_source']);
428
            }
429
        } else {
430
            $keys = explode(',', $fields);
431
            $data = $document->getData();
432
            foreach ($keys as $key) {
433
                if (isset($responseData['get']['fields'][$key])) {
434
                    $data[$key] = $responseData['get']['fields'][$key];
435
                } elseif (isset($data[$key])) {
436
                    unset($data[$key]);
437
                }
438
            }
439
            $document->setData($data);
440
        }
441
    }
442
443
    /**
444
     * Bulk deletes documents.
445
     *
446
     * @param array|\Elastica\Document[] $docs
447
     *
448
     * @throws \Elastica\Exception\InvalidException
449
     *
450
     * @return \Elastica\Bulk\ResponseSet
451
     */
452 View Code Duplication
    public function deleteDocuments(array $docs)
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...
453
    {
454
        if (empty($docs)) {
455
            throw new InvalidException('Array has to consist of at least one element');
456
        }
457
458
        $bulk = new Bulk($this);
459
        $bulk->addDocuments($docs, Action::OP_TYPE_DELETE);
460
461
        return $bulk->send();
462
    }
463
464
    /**
465
     * Returns the status object for all indices.
466
     *
467
     * @return \Elastica\Status Status object
468
     */
469
    public function getStatus()
470
    {
471
        return new Status($this);
472
    }
473
474
    /**
475
     * Returns the current cluster.
476
     *
477
     * @return \Elastica\Cluster Cluster object
478
     */
479
    public function getCluster()
480
    {
481
        return new Cluster($this);
482
    }
483
484
    /**
485
     * @param \Elastica\Connection $connection
486
     *
487
     * @return $this
488
     */
489
    public function addConnection(Connection $connection)
490
    {
491
        $this->_connectionPool->addConnection($connection);
492
493
        return $this;
494
    }
495
496
    /**
497
     * Determines whether a valid connection is available for use.
498
     *
499
     * @return bool
500
     */
501
    public function hasConnection()
502
    {
503
        return $this->_connectionPool->hasConnection();
504
    }
505
506
    /**
507
     * @throws \Elastica\Exception\ClientException
508
     *
509
     * @return \Elastica\Connection
510
     */
511
    public function getConnection()
512
    {
513
        return $this->_connectionPool->getConnection();
514
    }
515
516
    /**
517
     * @return \Elastica\Connection[]
518
     */
519
    public function getConnections()
520
    {
521
        return $this->_connectionPool->getConnections();
522
    }
523
524
    /**
525
     * @return \Elastica\Connection\Strategy\StrategyInterface
526
     */
527
    public function getConnectionStrategy()
528
    {
529
        return $this->_connectionPool->getStrategy();
530
    }
531
532
    /**
533
     * @param array|\Elastica\Connection[] $connections
534
     *
535
     * @return $this
536
     */
537
    public function setConnections(array $connections)
538
    {
539
        $this->_connectionPool->setConnections($connections);
540
541
        return $this;
542
    }
543
544
    /**
545
     * Deletes documents with the given ids, index, type from the index.
546
     *
547
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
548
     *
549
     * @param array                  $ids     Document ids
550
     * @param string|\Elastica\Index $index   Index name
551
     * @param string|\Elastica\Type  $type    Type of documents
552
     * @param string|bool            $routing Optional routing key for all ids
553
     *
554
     * @throws \Elastica\Exception\InvalidException
555
     *
556
     * @return \Elastica\Bulk\ResponseSet Response  object
557
     */
558
    public function deleteIds(array $ids, $index, $type, $routing = false)
559
    {
560
        if (empty($ids)) {
561
            throw new InvalidException('Array has to consist of at least one id');
562
        }
563
564
        $bulk = new Bulk($this);
565
        $bulk->setIndex($index);
566
        $bulk->setType($type);
567
568
        foreach ($ids as $id) {
569
            $action = new Action(Action::OP_TYPE_DELETE);
570
            $action->setId($id);
571
572
            if (!empty($routing)) {
573
                $action->setRouting($routing);
0 ignored issues
show
Bug introduced by
It seems like $routing defined by parameter $routing on line 558 can also be of type boolean; however, Elastica\Bulk\Action::setRouting() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
574
            }
575
576
            $bulk->addAction($action);
577
        }
578
579
        return $bulk->send();
580
    }
581
582
    /**
583
     * Bulk operation.
584
     *
585
     * Every entry in the params array has to exactly on array
586
     * of the bulk operation. An example param array would be:
587
     *
588
     * array(
589
     *         array('index' => array('_index' => 'test', '_type' => 'user', '_id' => '1')),
590
     *         array('user' => array('name' => 'hans')),
591
     *         array('delete' => array('_index' => 'test', '_type' => 'user', '_id' => '2'))
592
     * );
593
     *
594
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
595
     *
596
     * @param array $params Parameter array
597
     *
598
     * @throws \Elastica\Exception\ResponseException
599
     * @throws \Elastica\Exception\InvalidException
600
     *
601
     * @return \Elastica\Bulk\ResponseSet Response object
602
     */
603
    public function bulk(array $params)
604
    {
605
        if (empty($params)) {
606
            throw new InvalidException('Array has to consist of at least one param');
607
        }
608
609
        $bulk = new Bulk($this);
610
611
        $bulk->addRawData($params);
612
613
        return $bulk->send();
614
    }
615
616
    /**
617
     * Makes calls to the elasticsearch server based on this index.
618
     *
619
     * It's possible to make any REST query directly over this method
620
     *
621
     * @param string $path   Path to call
622
     * @param string $method Rest method to use (GET, POST, DELETE, PUT)
623
     * @param array  $data   OPTIONAL Arguments as array
624
     * @param array  $query  OPTIONAL Query params
625
     *
626
     * @throws Exception\ConnectionException|\Exception
627
     *
628
     * @return \Elastica\Response Response object
629
     */
630
    public function request($path, $method = Request::GET, $data = array(), array $query = array())
631
    {
632
        $connection = $this->getConnection();
633
        try {
634
            $request = new Request($path, $method, $data, $query, $connection);
635
636
            $this->_log($request);
637
638
            $response = $request->send();
639
640
            $this->_lastRequest = $request;
641
            $this->_lastResponse = $response;
642
643
            return $response;
644
        } catch (ConnectionException $e) {
645
            $this->_connectionPool->onFail($connection, $e, $this);
646
647
            // In case there is no valid connection left, throw exception which caused the disabling of the connection.
648
            if (!$this->hasConnection()) {
649
                throw $e;
650
            }
651
652
            return $this->request($path, $method, $data, $query);
653
        }
654
    }
655
656
    /**
657
     * Optimizes all search indices.
658
     *
659
     * @param array $args OPTIONAL Optional arguments
660
     *
661
     * @return \Elastica\Response Response object
662
     *
663
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-optimize.html
664
     */
665
    public function optimizeAll($args = array())
666
    {
667
        return $this->request('_optimize', Request::POST, array(), $args);
668
    }
669
670
    /**
671
     * Refreshes all search indices.
672
     *
673
     * @return \Elastica\Response Response object
674
     *
675
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html
676
     */
677
    public function refreshAll()
678
    {
679
        return $this->request('_refresh', Request::POST);
680
    }
681
682
    /**
683
     * logging.
684
     *
685
     * @param string|\Elastica\Request $context
686
     *
687
     * @throws Exception\RuntimeException
688
     */
689
    protected function _log($context)
690
    {
691
        $log = $this->getConfig('log');
692
        if ($log && !class_exists('Psr\Log\AbstractLogger')) {
693
            throw new RuntimeException('Class Psr\Log\AbstractLogger not found');
694
        } elseif (!$this->_logger && $log) {
695
            $this->setLogger(new Log($this->getConfig('log')));
0 ignored issues
show
Bug introduced by
It seems like $this->getConfig('log') targeting Elastica\Client::getConfig() can also be of type array; however, Elastica\Log::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
696
        }
697
        if ($this->_logger) {
698
            if ($context instanceof Request) {
699
                $data = $context->toArray();
700
            } else {
701
                $data = array('message' => $context);
702
            }
703
            $this->_logger->debug('logging Request', $data);
704
        }
705
    }
706
707
    /**
708
     * @return \Elastica\Request
709
     */
710
    public function getLastRequest()
711
    {
712
        return $this->_lastRequest;
713
    }
714
715
    /**
716
     * @return \Elastica\Response
717
     */
718
    public function getLastResponse()
719
    {
720
        return $this->_lastResponse;
721
    }
722
723
    /**
724
     * set Logger.
725
     *
726
     * @param LoggerInterface $logger
727
     *
728
     * @return $this
729
     */
730
    public function setLogger(LoggerInterface $logger)
731
    {
732
        $this->_logger = $logger;
733
734
        return $this;
735
    }
736
737
    /**
738
     * @return BuilderInterface
739
     */
740
    public function getResultSetBuilder()
741
    {
742
        return $this->_resultSetBuilder;
743
    }
744
}
745