These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
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\Script\AbstractScript; |
||
9 | use Elasticsearch\Endpoints\AbstractEndpoint; |
||
10 | use Elasticsearch\Endpoints\Indices\ForceMerge; |
||
11 | use Elasticsearch\Endpoints\Indices\Refresh; |
||
12 | use Elasticsearch\Endpoints\Update; |
||
13 | use Psr\Log\LoggerInterface; |
||
14 | use Psr\Log\NullLogger; |
||
15 | |||
16 | /** |
||
17 | * Client to connect the the elasticsearch server. |
||
18 | * |
||
19 | * @author Nicolas Ruflin <[email protected]> |
||
20 | */ |
||
21 | class Client |
||
22 | { |
||
23 | /** |
||
24 | * Config with defaults. |
||
25 | * |
||
26 | * log: Set to true, to enable logging, set a string to log to a specific file |
||
27 | * retryOnConflict: Use in \Elastica\Client::updateDocument |
||
28 | * bigintConversion: Set to true to enable the JSON bigint to string conversion option (see issue #717) |
||
29 | * |
||
30 | * @var array |
||
31 | */ |
||
32 | protected $_config = [ |
||
33 | 'host' => null, |
||
34 | 'port' => null, |
||
35 | 'path' => null, |
||
36 | 'url' => null, |
||
37 | 'proxy' => null, |
||
38 | 'transport' => null, |
||
39 | 'persistent' => true, |
||
40 | 'timeout' => null, |
||
41 | 'connections' => [], // host, port, path, timeout, transport, compression, persistent, timeout, username, password, config -> (curl, headers, url) |
||
42 | 'roundRobin' => false, |
||
43 | 'log' => false, |
||
44 | 'retryOnConflict' => 0, |
||
45 | 'bigintConversion' => false, |
||
46 | 'username' => null, |
||
47 | 'password' => null, |
||
48 | ]; |
||
49 | |||
50 | /** |
||
51 | * @var callback |
||
52 | */ |
||
53 | protected $_callback; |
||
54 | |||
55 | /** |
||
56 | * @var Connection\ConnectionPool |
||
57 | */ |
||
58 | protected $_connectionPool; |
||
59 | |||
60 | /** |
||
61 | * @var \Elastica\Request|null |
||
62 | */ |
||
63 | protected $_lastRequest; |
||
64 | |||
65 | /** |
||
66 | * @var \Elastica\Response|null |
||
67 | */ |
||
68 | protected $_lastResponse; |
||
69 | |||
70 | /** |
||
71 | * @var LoggerInterface |
||
72 | */ |
||
73 | protected $_logger; |
||
74 | |||
75 | /** |
||
76 | * @var string |
||
77 | */ |
||
78 | protected $_version; |
||
79 | |||
80 | /** |
||
81 | * Creates a new Elastica client. |
||
82 | * |
||
83 | * @param array $config OPTIONAL Additional config options |
||
84 | * @param callback $callback OPTIONAL Callback function which can be used to be notified about errors (for example connection down) |
||
85 | * @param LoggerInterface $logger |
||
86 | */ |
||
87 | public function __construct(array $config = [], $callback = null, LoggerInterface $logger = null) |
||
88 | { |
||
89 | $this->_callback = $callback; |
||
90 | |||
91 | if (!$logger && isset($config['log']) && $config['log']) { |
||
92 | $logger = new Log($config['log']); |
||
93 | } |
||
94 | $this->_logger = $logger ?: new NullLogger(); |
||
95 | |||
96 | $this->setConfig($config); |
||
97 | $this->_initConnections(); |
||
98 | } |
||
99 | |||
100 | /** |
||
101 | * Get current version. |
||
102 | * |
||
103 | * @return string |
||
104 | */ |
||
105 | public function getVersion() |
||
106 | { |
||
107 | if ($this->_version) { |
||
108 | return $this->_version; |
||
109 | } |
||
110 | |||
111 | $data = $this->request('/')->getData(); |
||
112 | |||
113 | return $this->_version = $data['version']['number']; |
||
114 | } |
||
115 | |||
116 | /** |
||
117 | * Inits the client connections. |
||
118 | */ |
||
119 | protected function _initConnections() |
||
120 | { |
||
121 | $connections = []; |
||
122 | |||
123 | foreach ($this->getConfig('connections') as $connection) { |
||
0 ignored issues
–
show
|
|||
124 | $connections[] = Connection::create($this->_prepareConnectionParams($connection)); |
||
125 | } |
||
126 | |||
127 | if (isset($this->_config['servers'])) { |
||
128 | foreach ($this->getConfig('servers') as $server) { |
||
129 | $connections[] = Connection::create($this->_prepareConnectionParams($server)); |
||
130 | } |
||
131 | } |
||
132 | |||
133 | // If no connections set, create default connection |
||
134 | if (empty($connections)) { |
||
135 | $connections[] = Connection::create($this->_prepareConnectionParams($this->getConfig())); |
||
0 ignored issues
–
show
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...
|
|||
136 | } |
||
137 | |||
138 | if (!isset($this->_config['connectionStrategy'])) { |
||
139 | if (true === $this->getConfig('roundRobin')) { |
||
140 | $this->setConfigValue('connectionStrategy', 'RoundRobin'); |
||
141 | } else { |
||
142 | $this->setConfigValue('connectionStrategy', 'Simple'); |
||
143 | } |
||
144 | } |
||
145 | |||
146 | $strategy = Connection\Strategy\StrategyFactory::create($this->getConfig('connectionStrategy')); |
||
147 | |||
148 | $this->_connectionPool = new Connection\ConnectionPool($connections, $strategy, $this->_callback); |
||
149 | } |
||
150 | |||
151 | /** |
||
152 | * Creates a Connection params array from a Client or server config array. |
||
153 | * |
||
154 | * @param array $config |
||
155 | * |
||
156 | * @return array |
||
157 | */ |
||
158 | protected function _prepareConnectionParams(array $config) |
||
159 | { |
||
160 | $params = []; |
||
161 | $params['config'] = []; |
||
162 | foreach ($config as $key => $value) { |
||
163 | if (in_array($key, ['bigintConversion', 'curl', 'headers', 'url'])) { |
||
164 | $params['config'][$key] = $value; |
||
165 | } else { |
||
166 | $params[$key] = $value; |
||
167 | } |
||
168 | } |
||
169 | |||
170 | return $params; |
||
171 | } |
||
172 | |||
173 | /** |
||
174 | * Sets specific config values (updates and keeps default values). |
||
175 | * |
||
176 | * @param array $config Params |
||
177 | * |
||
178 | * @return $this |
||
179 | */ |
||
180 | public function setConfig(array $config) |
||
181 | { |
||
182 | foreach ($config as $key => $value) { |
||
183 | $this->_config[$key] = $value; |
||
184 | } |
||
185 | |||
186 | return $this; |
||
187 | } |
||
188 | |||
189 | /** |
||
190 | * Returns a specific config key or the whole |
||
191 | * config array if not set. |
||
192 | * |
||
193 | * @param string $key Config key |
||
194 | * |
||
195 | * @throws \Elastica\Exception\InvalidException |
||
196 | * |
||
197 | * @return array|string Config value |
||
198 | */ |
||
199 | public function getConfig($key = '') |
||
200 | { |
||
201 | if (empty($key)) { |
||
202 | return $this->_config; |
||
203 | } |
||
204 | |||
205 | if (!array_key_exists($key, $this->_config)) { |
||
206 | throw new InvalidException('Config key is not set: '.$key); |
||
207 | } |
||
208 | |||
209 | return $this->_config[$key]; |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * Sets / overwrites a specific config value. |
||
214 | * |
||
215 | * @param string $key Key to set |
||
216 | * @param mixed $value Value |
||
217 | * |
||
218 | * @return $this |
||
219 | */ |
||
220 | public function setConfigValue($key, $value) |
||
221 | { |
||
222 | return $this->setConfig([$key => $value]); |
||
223 | } |
||
224 | |||
225 | /** |
||
226 | * @param array|string $keys config key or path of config keys |
||
227 | * @param mixed $default default value will be returned if key was not found |
||
228 | * |
||
229 | * @return mixed |
||
230 | */ |
||
231 | public function getConfigValue($keys, $default = null) |
||
232 | { |
||
233 | $value = $this->_config; |
||
234 | foreach ((array) $keys as $key) { |
||
235 | if (isset($value[$key])) { |
||
236 | $value = $value[$key]; |
||
237 | } else { |
||
238 | return $default; |
||
239 | } |
||
240 | } |
||
241 | |||
242 | return $value; |
||
243 | } |
||
244 | |||
245 | /** |
||
246 | * Returns the index for the given connection. |
||
247 | * |
||
248 | * @param string $name Index name to create connection to |
||
249 | * |
||
250 | * @return \Elastica\Index Index for the given name |
||
251 | */ |
||
252 | public function getIndex($name) |
||
253 | { |
||
254 | return new Index($this, $name); |
||
255 | } |
||
256 | |||
257 | /** |
||
258 | * Adds a HTTP Header. |
||
259 | * |
||
260 | * @param string $header The HTTP Header |
||
261 | * @param string $headerValue The HTTP Header Value |
||
262 | * |
||
263 | * @throws \Elastica\Exception\InvalidException If $header or $headerValue is not a string |
||
264 | * |
||
265 | * @return $this |
||
266 | */ |
||
267 | View Code Duplication | public function addHeader($header, $headerValue) |
|
0 ignored issues
–
show
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...
|
|||
268 | { |
||
269 | if (is_string($header) && is_string($headerValue)) { |
||
270 | $this->_config['headers'][$header] = $headerValue; |
||
271 | } else { |
||
272 | throw new InvalidException('Header must be a string'); |
||
273 | } |
||
274 | |||
275 | return $this; |
||
276 | } |
||
277 | |||
278 | /** |
||
279 | * Remove a HTTP Header. |
||
280 | * |
||
281 | * @param string $header The HTTP Header to remove |
||
282 | * |
||
283 | * @throws \Elastica\Exception\InvalidException If $header is not a string |
||
284 | * |
||
285 | * @return $this |
||
286 | */ |
||
287 | View Code Duplication | public function removeHeader($header) |
|
0 ignored issues
–
show
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...
|
|||
288 | { |
||
289 | if (is_string($header)) { |
||
290 | if (array_key_exists($header, $this->_config['headers'])) { |
||
291 | unset($this->_config['headers'][$header]); |
||
292 | } |
||
293 | } else { |
||
294 | throw new InvalidException('Header must be a string'); |
||
295 | } |
||
296 | |||
297 | return $this; |
||
298 | } |
||
299 | |||
300 | /** |
||
301 | * Uses _bulk to send documents to the server. |
||
302 | * |
||
303 | * Array of \Elastica\Document as input. Index and type has to be |
||
304 | * set inside the document, because for bulk settings documents, |
||
305 | * documents can belong to any type and index |
||
306 | * |
||
307 | * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html |
||
308 | * |
||
309 | * @param array|\Elastica\Document[] $docs Array of Elastica\Document |
||
310 | * @param array $requestParams |
||
311 | * |
||
312 | * @throws \Elastica\Exception\InvalidException If docs is empty |
||
313 | * |
||
314 | * @return \Elastica\Bulk\ResponseSet Response object |
||
315 | */ |
||
316 | View Code Duplication | public function updateDocuments(array $docs, array $requestParams = []) |
|
317 | { |
||
318 | if (empty($docs)) { |
||
319 | throw new InvalidException('Array has to consist of at least one element'); |
||
320 | } |
||
321 | |||
322 | $bulk = new Bulk($this); |
||
323 | |||
324 | $bulk->addDocuments($docs, Action::OP_TYPE_UPDATE); |
||
325 | foreach ($requestParams as $key => $value) { |
||
326 | $bulk->setRequestParam($key, $value); |
||
327 | } |
||
328 | |||
329 | return $bulk->send(); |
||
330 | } |
||
331 | |||
332 | /** |
||
333 | * Uses _bulk to send documents to the server. |
||
334 | * |
||
335 | * Array of \Elastica\Document as input. Index and type has to be |
||
336 | * set inside the document, because for bulk settings documents, |
||
337 | * documents can belong to any type and index |
||
338 | * |
||
339 | * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html |
||
340 | * |
||
341 | * @param array|\Elastica\Document[] $docs Array of Elastica\Document |
||
342 | * @param array $requestParams |
||
343 | * |
||
344 | * @throws \Elastica\Exception\InvalidException If docs is empty |
||
345 | * |
||
346 | * @return \Elastica\Bulk\ResponseSet Response object |
||
347 | */ |
||
348 | View Code Duplication | public function addDocuments(array $docs, array $requestParams = []) |
|
349 | { |
||
350 | if (empty($docs)) { |
||
351 | throw new InvalidException('Array has to consist of at least one element'); |
||
352 | } |
||
353 | |||
354 | $bulk = new Bulk($this); |
||
355 | |||
356 | $bulk->addDocuments($docs); |
||
357 | |||
358 | foreach ($requestParams as $key => $value) { |
||
359 | $bulk->setRequestParam($key, $value); |
||
360 | } |
||
361 | |||
362 | return $bulk->send(); |
||
363 | } |
||
364 | |||
365 | /** |
||
366 | * Update document, using update script. Requires elasticsearch >= 0.19.0. |
||
367 | * |
||
368 | * @param int|string $id document id |
||
369 | * @param array|\Elastica\Script\AbstractScript|\Elastica\Document $data raw data for request body |
||
370 | * @param string $index index to update |
||
371 | * @param string $type type of index to update |
||
372 | * @param array $options array of query params to use for query. For possible options check es api |
||
373 | * |
||
374 | * @return \Elastica\Response |
||
375 | * |
||
376 | * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html |
||
377 | */ |
||
378 | public function updateDocument($id, $data, $index, $type, array $options = []) |
||
379 | { |
||
380 | $endpoint = new Update(); |
||
381 | $endpoint->setID($id); |
||
382 | $endpoint->setIndex($index); |
||
383 | $endpoint->setType($type); |
||
384 | |||
385 | if ($data instanceof AbstractScript) { |
||
386 | $requestData = $data->toArray(); |
||
387 | } elseif ($data instanceof Document) { |
||
388 | $requestData = ['doc' => $data->getData()]; |
||
389 | |||
390 | if ($data->getDocAsUpsert()) { |
||
391 | $requestData['doc_as_upsert'] = true; |
||
392 | } |
||
393 | |||
394 | $docOptions = $data->getOptions( |
||
395 | [ |
||
396 | 'version', |
||
397 | 'version_type', |
||
398 | 'routing', |
||
399 | 'percolate', |
||
400 | 'parent', |
||
401 | 'fields', |
||
402 | 'retry_on_conflict', |
||
403 | 'consistency', |
||
404 | 'replication', |
||
405 | 'refresh', |
||
406 | 'timeout', |
||
407 | ] |
||
408 | ); |
||
409 | $options += $docOptions; |
||
410 | // set fields param to source only if options was not set before |
||
411 | if ($data instanceof Document && ($data->isAutoPopulate() |
||
412 | || $this->getConfigValue(['document', 'autoPopulate'], false)) |
||
413 | && !isset($options['fields']) |
||
414 | ) { |
||
415 | $options['fields'] = '_source'; |
||
416 | } |
||
417 | } else { |
||
418 | $requestData = $data; |
||
419 | } |
||
420 | |||
421 | //If an upsert document exists |
||
422 | if ($data instanceof AbstractScript || $data instanceof Document) { |
||
423 | if ($data->hasUpsert()) { |
||
424 | $requestData['upsert'] = $data->getUpsert()->getData(); |
||
425 | } |
||
426 | } |
||
427 | |||
428 | if (!isset($options['retry_on_conflict'])) { |
||
429 | if ($retryOnConflict = $this->getConfig('retryOnConflict')) { |
||
430 | $options['retry_on_conflict'] = $retryOnConflict; |
||
431 | } |
||
432 | } |
||
433 | |||
434 | $endpoint->setBody($requestData); |
||
435 | $endpoint->setParams($options); |
||
436 | |||
437 | $response = $this->requestEndpoint($endpoint); |
||
438 | |||
439 | View Code Duplication | if ($response->isOk() |
|
440 | && $data instanceof Document |
||
441 | && ($data->isAutoPopulate() || $this->getConfigValue(['document', 'autoPopulate'], false)) |
||
442 | ) { |
||
443 | $responseData = $response->getData(); |
||
444 | if (isset($responseData['_version'])) { |
||
445 | $data->setVersion($responseData['_version']); |
||
446 | } |
||
447 | if (isset($options['fields'])) { |
||
448 | $this->_populateDocumentFieldsFromResponse($response, $data, $options['fields']); |
||
449 | } |
||
450 | } |
||
451 | |||
452 | return $response; |
||
453 | } |
||
454 | |||
455 | /** |
||
456 | * @param \Elastica\Response $response |
||
457 | * @param \Elastica\Document $document |
||
458 | * @param string $fields Array of field names to be populated or '_source' if whole document data should be updated |
||
459 | */ |
||
460 | protected function _populateDocumentFieldsFromResponse(Response $response, Document $document, $fields) |
||
461 | { |
||
462 | $responseData = $response->getData(); |
||
463 | if ('_source' == $fields) { |
||
464 | if (isset($responseData['get']['_source']) && is_array($responseData['get']['_source'])) { |
||
465 | $document->setData($responseData['get']['_source']); |
||
466 | } |
||
467 | } else { |
||
468 | $keys = explode(',', $fields); |
||
469 | $data = $document->getData(); |
||
470 | foreach ($keys as $key) { |
||
471 | if (isset($responseData['get']['fields'][$key])) { |
||
472 | $data[$key] = $responseData['get']['fields'][$key]; |
||
473 | } elseif (isset($data[$key])) { |
||
474 | unset($data[$key]); |
||
475 | } |
||
476 | } |
||
477 | $document->setData($data); |
||
478 | } |
||
479 | } |
||
480 | |||
481 | /** |
||
482 | * Bulk deletes documents. |
||
483 | * |
||
484 | * @param array|\Elastica\Document[] $docs |
||
485 | * @param array $requestParams |
||
486 | * |
||
487 | * @throws \Elastica\Exception\InvalidException |
||
488 | * |
||
489 | * @return \Elastica\Bulk\ResponseSet |
||
490 | */ |
||
491 | View Code Duplication | public function deleteDocuments(array $docs, array $requestParams = []) |
|
492 | { |
||
493 | if (empty($docs)) { |
||
494 | throw new InvalidException('Array has to consist of at least one element'); |
||
495 | } |
||
496 | |||
497 | $bulk = new Bulk($this); |
||
498 | $bulk->addDocuments($docs, Action::OP_TYPE_DELETE); |
||
499 | |||
500 | foreach ($requestParams as $key => $value) { |
||
501 | $bulk->setRequestParam($key, $value); |
||
502 | } |
||
503 | |||
504 | return $bulk->send(); |
||
505 | } |
||
506 | |||
507 | /** |
||
508 | * Returns the status object for all indices. |
||
509 | * |
||
510 | * @return \Elastica\Status Status object |
||
511 | */ |
||
512 | public function getStatus() |
||
513 | { |
||
514 | return new Status($this); |
||
515 | } |
||
516 | |||
517 | /** |
||
518 | * Returns the current cluster. |
||
519 | * |
||
520 | * @return \Elastica\Cluster Cluster object |
||
521 | */ |
||
522 | public function getCluster() |
||
523 | { |
||
524 | return new Cluster($this); |
||
525 | } |
||
526 | |||
527 | /** |
||
528 | * Establishes the client connections. |
||
529 | */ |
||
530 | public function connect() |
||
531 | { |
||
532 | return $this->_initConnections(); |
||
533 | } |
||
534 | |||
535 | /** |
||
536 | * @param \Elastica\Connection $connection |
||
537 | * |
||
538 | * @return $this |
||
539 | */ |
||
540 | public function addConnection(Connection $connection) |
||
541 | { |
||
542 | $this->_connectionPool->addConnection($connection); |
||
543 | |||
544 | return $this; |
||
545 | } |
||
546 | |||
547 | /** |
||
548 | * Determines whether a valid connection is available for use. |
||
549 | * |
||
550 | * @return bool |
||
551 | */ |
||
552 | public function hasConnection() |
||
553 | { |
||
554 | return $this->_connectionPool->hasConnection(); |
||
555 | } |
||
556 | |||
557 | /** |
||
558 | * @throws \Elastica\Exception\ClientException |
||
559 | * |
||
560 | * @return \Elastica\Connection |
||
561 | */ |
||
562 | public function getConnection() |
||
563 | { |
||
564 | return $this->_connectionPool->getConnection(); |
||
565 | } |
||
566 | |||
567 | /** |
||
568 | * @return \Elastica\Connection[] |
||
569 | */ |
||
570 | public function getConnections() |
||
571 | { |
||
572 | return $this->_connectionPool->getConnections(); |
||
573 | } |
||
574 | |||
575 | /** |
||
576 | * @return \Elastica\Connection\Strategy\StrategyInterface |
||
577 | */ |
||
578 | public function getConnectionStrategy() |
||
579 | { |
||
580 | return $this->_connectionPool->getStrategy(); |
||
581 | } |
||
582 | |||
583 | /** |
||
584 | * @param array|\Elastica\Connection[] $connections |
||
585 | * |
||
586 | * @return $this |
||
587 | */ |
||
588 | public function setConnections(array $connections) |
||
589 | { |
||
590 | $this->_connectionPool->setConnections($connections); |
||
591 | |||
592 | return $this; |
||
593 | } |
||
594 | |||
595 | /** |
||
596 | * Deletes documents with the given ids, index, type from the index. |
||
597 | * |
||
598 | * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html |
||
599 | * |
||
600 | * @param array $ids Document ids |
||
601 | * @param string|\Elastica\Index $index Index name |
||
602 | * @param string|\Elastica\Type $type Type of documents |
||
603 | * @param string|bool $routing Optional routing key for all ids |
||
604 | * |
||
605 | * @throws \Elastica\Exception\InvalidException |
||
606 | * |
||
607 | * @return \Elastica\Bulk\ResponseSet Response object |
||
608 | */ |
||
609 | public function deleteIds(array $ids, $index, $type, $routing = false) |
||
610 | { |
||
611 | if (empty($ids)) { |
||
612 | throw new InvalidException('Array has to consist of at least one id'); |
||
613 | } |
||
614 | |||
615 | $bulk = new Bulk($this); |
||
616 | $bulk->setIndex($index); |
||
617 | $bulk->setType($type); |
||
618 | |||
619 | foreach ($ids as $id) { |
||
620 | $action = new Action(Action::OP_TYPE_DELETE); |
||
621 | $action->setId($id); |
||
622 | |||
623 | if (!empty($routing)) { |
||
624 | $action->setRouting($routing); |
||
625 | } |
||
626 | |||
627 | $bulk->addAction($action); |
||
628 | } |
||
629 | |||
630 | return $bulk->send(); |
||
631 | } |
||
632 | |||
633 | /** |
||
634 | * Bulk operation. |
||
635 | * |
||
636 | * Every entry in the params array has to exactly on array |
||
637 | * of the bulk operation. An example param array would be: |
||
638 | * |
||
639 | * array( |
||
640 | * array('index' => array('_index' => 'test', '_type' => 'user', '_id' => '1')), |
||
641 | * array('user' => array('name' => 'hans')), |
||
642 | * array('delete' => array('_index' => 'test', '_type' => 'user', '_id' => '2')) |
||
643 | * ); |
||
644 | * |
||
645 | * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html |
||
646 | * |
||
647 | * @param array $params Parameter array |
||
648 | * |
||
649 | * @throws \Elastica\Exception\ResponseException |
||
650 | * @throws \Elastica\Exception\InvalidException |
||
651 | * |
||
652 | * @return \Elastica\Bulk\ResponseSet Response object |
||
653 | */ |
||
654 | public function bulk(array $params) |
||
655 | { |
||
656 | if (empty($params)) { |
||
657 | throw new InvalidException('Array has to consist of at least one param'); |
||
658 | } |
||
659 | |||
660 | $bulk = new Bulk($this); |
||
661 | |||
662 | $bulk->addRawData($params); |
||
663 | |||
664 | return $bulk->send(); |
||
665 | } |
||
666 | |||
667 | /** |
||
668 | * Makes calls to the elasticsearch server based on this index. |
||
669 | * |
||
670 | * It's possible to make any REST query directly over this method |
||
671 | * |
||
672 | * @param string $path Path to call |
||
673 | * @param string $method Rest method to use (GET, POST, DELETE, PUT) |
||
674 | * @param array|string $data OPTIONAL Arguments as array or pre-encoded string |
||
675 | * @param array $query OPTIONAL Query params |
||
676 | * @param string $contentType Content-Type sent with this request |
||
677 | * |
||
678 | * @throws Exception\ConnectionException|Exception\ClientException |
||
679 | * |
||
680 | * @return Response Response object |
||
681 | */ |
||
682 | public function request($path, $method = Request::GET, $data = [], array $query = [], $contentType = Request::DEFAULT_CONTENT_TYPE) |
||
683 | { |
||
684 | $connection = $this->getConnection(); |
||
685 | $request = $this->_lastRequest = new Request($path, $method, $data, $query, $connection, $contentType); |
||
686 | $this->_lastResponse = null; |
||
687 | |||
688 | try { |
||
689 | $response = $this->_lastResponse = $request->send(); |
||
690 | } catch (ConnectionException $e) { |
||
691 | $this->_connectionPool->onFail($connection, $e, $this); |
||
692 | |||
693 | $this->_log($e); |
||
694 | |||
695 | // In case there is no valid connection left, throw exception which caused the disabling of the connection. |
||
696 | if (!$this->hasConnection()) { |
||
697 | throw $e; |
||
698 | } |
||
699 | |||
700 | return $this->request($path, $method, $data, $query); |
||
701 | } |
||
702 | |||
703 | $this->_log($request); |
||
704 | |||
705 | return $response; |
||
706 | } |
||
707 | |||
708 | /** |
||
709 | * Makes calls to the elasticsearch server with usage official client Endpoint. |
||
710 | * |
||
711 | * @param AbstractEndpoint $endpoint |
||
712 | * |
||
713 | * @return Response |
||
714 | */ |
||
715 | public function requestEndpoint(AbstractEndpoint $endpoint) |
||
716 | { |
||
717 | return $this->request( |
||
718 | ltrim($endpoint->getURI(), '/'), |
||
719 | $endpoint->getMethod(), |
||
720 | null === $endpoint->getBody() ? [] : $endpoint->getBody(), |
||
721 | $endpoint->getParams() |
||
722 | ); |
||
723 | } |
||
724 | |||
725 | /** |
||
726 | * logging. |
||
727 | * |
||
728 | * @deprecated Overwriting Client->_log is deprecated. Handle logging functionality by using a custom LoggerInterface. |
||
729 | * |
||
730 | * @param mixed $context |
||
731 | */ |
||
732 | protected function _log($context) |
||
733 | { |
||
734 | if ($context instanceof ConnectionException) { |
||
735 | $this->_logger->error('Elastica Request Failure', [ |
||
736 | 'exception' => $context, |
||
737 | 'request' => $context->getRequest()->toArray(), |
||
738 | 'retry' => $this->hasConnection(), |
||
739 | ]); |
||
740 | |||
741 | return; |
||
742 | } |
||
743 | |||
744 | if ($context instanceof Request) { |
||
745 | $this->_logger->debug('Elastica Request', [ |
||
746 | 'request' => $context->toArray(), |
||
747 | 'response' => $this->_lastResponse ? $this->_lastResponse->getData() : null, |
||
748 | 'responseStatus' => $this->_lastResponse ? $this->_lastResponse->getStatus() : null, |
||
749 | ]); |
||
750 | |||
751 | return; |
||
752 | } |
||
753 | |||
754 | $this->_logger->debug('Elastica Request', [ |
||
755 | 'message' => $context, |
||
756 | ]); |
||
757 | } |
||
758 | |||
759 | /** |
||
760 | * Optimizes all search indices. |
||
761 | * |
||
762 | * @param array $args OPTIONAL Optional arguments |
||
763 | * |
||
764 | * @return \Elastica\Response Response object |
||
765 | * |
||
766 | * @deprecated Replaced by forcemergeAll |
||
767 | * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-optimize.html |
||
768 | */ |
||
769 | public function optimizeAll($args = []) |
||
770 | { |
||
771 | trigger_error('Deprecated: Elastica\Client::optimizeAll() is deprecated and will be removed in further Elastica releases. Use Elastica\Client::forcemergeAll() instead.', E_USER_DEPRECATED); |
||
772 | |||
773 | return $this->forcemergeAll($args); |
||
774 | } |
||
775 | |||
776 | /** |
||
777 | * Force merges all search indices. |
||
778 | * |
||
779 | * @param array $args OPTIONAL Optional arguments |
||
780 | * |
||
781 | * @return \Elastica\Response Response object |
||
782 | * |
||
783 | * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html |
||
784 | */ |
||
785 | public function forcemergeAll($args = []) |
||
786 | { |
||
787 | $endpoint = new ForceMerge(); |
||
788 | $endpoint->setParams($args); |
||
789 | |||
790 | return $this->requestEndpoint($endpoint); |
||
791 | } |
||
792 | |||
793 | /** |
||
794 | * Refreshes all search indices. |
||
795 | * |
||
796 | * @return \Elastica\Response Response object |
||
797 | * |
||
798 | * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html |
||
799 | */ |
||
800 | public function refreshAll() |
||
801 | { |
||
802 | return $this->requestEndpoint(new Refresh()); |
||
803 | } |
||
804 | |||
805 | /** |
||
806 | * @return Request|null |
||
807 | */ |
||
808 | public function getLastRequest() |
||
809 | { |
||
810 | return $this->_lastRequest; |
||
811 | } |
||
812 | |||
813 | /** |
||
814 | * @return Response|null |
||
815 | */ |
||
816 | public function getLastResponse() |
||
817 | { |
||
818 | return $this->_lastResponse; |
||
819 | } |
||
820 | |||
821 | /** |
||
822 | * Replace the existing logger. |
||
823 | * |
||
824 | * @param LoggerInterface $logger |
||
825 | * |
||
826 | * @return $this |
||
827 | */ |
||
828 | public function setLogger(LoggerInterface $logger) |
||
829 | { |
||
830 | $this->_logger = $logger; |
||
831 | |||
832 | return $this; |
||
833 | } |
||
834 | } |
||
835 |
There are different options of fixing this problem.
If you want to be on the safe side, you can add an additional type-check:
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:
Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.