Client::request()   B
last analyzed

Complexity

Conditions 8
Paths 24

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 8

Importance

Changes 0
Metric Value
dl 0
loc 31
ccs 18
cts 18
cp 1
rs 8.1795
c 0
b 0
f 0
cc 8
nc 24
nop 5
crap 8
1
<?php
2
3
/*
4
 * This file is part of the FOSElasticaBundle package.
5
 *
6
 * (c) FriendsOfSymfony <https://friendsofsymfony.github.com/>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace FOS\ElasticaBundle\Elastica;
13
14
use Elastica\Client as BaseClient;
15
use Elastica\Exception\ClientException;
16
use Elastica\Index as BaseIndex;
17
use Elastica\Request;
18
use Elastica\Response;
19
use FOS\ElasticaBundle\Logger\ElasticaLogger;
20
use Symfony\Component\Stopwatch\Stopwatch;
21
22
/**
23
 * Extends the default Elastica client to provide logging for errors that occur
24
 * during communication with ElasticSearch.
25
 *
26
 * @author Gordon Franke <[email protected]>
27
 */
28
class Client extends BaseClient
29
{
30
    /**
31
     * Stores created indexes to avoid recreation.
32
     *
33
     * @var array
34
     */
35
    private $indexCache = [];
36
37
    /**
38
     * Stores created index template to avoid recreation.
39
     *
40
     * @var array
41
     */
42
    private $indexTemplateCache = [];
43
44
    /**
45
     * Symfony's debugging Stopwatch.
46
     *
47
     * @var Stopwatch|null
48
     */
49
    private $stopwatch;
50
51
    /**
52
     * {@inheritdoc}
53
     */
54 13
    public function request(string $path, string $method = Request::GET, $data = [], array $query = [], string $contentType = Request::DEFAULT_CONTENT_TYPE): Response
55
    {
56 13
        if ($this->stopwatch) {
57 11
            $this->stopwatch->start('es_request', 'fos_elastica');
58
        }
59
60 13
        $response = parent::request($path, $method, $data, $query, $contentType);
61 13
        $responseData = $response->getData();
62
63 13
        $transportInfo = $response->getTransferInfo();
64 13
        $connection = $this->getLastRequest()->getConnection();
65 13
        $forbiddenHttpCodes = $connection->hasConfig('http_error_codes') ? $connection->getConfig('http_error_codes') : [];
66
67 13
        if (isset($transportInfo['http_code']) && \in_array($transportInfo['http_code'], $forbiddenHttpCodes, true)) {
68 1
            $body = \is_array($responseData) ? \json_encode($responseData) : $responseData;
69 1
            $message = \sprintf('Error in transportInfo: response code is %s, response body is %s', $transportInfo['http_code'], $body);
70 1
            throw new ClientException($message);
71
        }
72
73 12
        if (isset($responseData['took'], $responseData['hits'])) {
74 2
            $this->logQuery($path, $method, $data, $query, $response->getQueryTime(), $response->getEngineTime(), $responseData['hits']['total']['value'] ?? 0);
75
        } else {
76 11
            $this->logQuery($path, $method, $data, $query, $response->getQueryTime(), 0, 0);
77
        }
78
79 12
        if ($this->stopwatch) {
80 11
            $this->stopwatch->stop('es_request');
81
        }
82
83 12
        return $response;
84
    }
85
86 13
    public function getIndex(string $name): BaseIndex
87
    {
88 13
        if (isset($this->indexCache[$name])) {
89 9
            return $this->indexCache[$name];
90
        }
91
92 13
        return $this->indexCache[$name] = new Index($this, $name);
93
    }
94
95 6
    public function getIndexTemplate($name): IndexTemplate
96
    {
97 6
        if (isset($this->indexTemplateCache[$name])) {
98 1
            return $this->indexTemplateCache[$name];
99
        }
100
101 6
        return $this->indexTemplateCache[$name] = new IndexTemplate($this, $name);
102
    }
103
104
    /**
105
     * Sets a stopwatch instance for debugging purposes.
106
     */
107 15
    public function setStopwatch(?Stopwatch $stopwatch = null): void
108
    {
109 15
        $this->stopwatch = $stopwatch;
110 15
    }
111
112
    /**
113
     * Log the query if we have an instance of ElasticaLogger.
114
     *
115
     * @param array|string $data
116
     * @param int          $queryTime
117
     * @param int          $engineMS
118
     */
119 12
    private function logQuery(string $path, string $method, $data, array $query, $queryTime, $engineMS = 0, int $itemCount = 0): void
120
    {
121 12
        if (!$this->_logger instanceof ElasticaLogger) {
122
            return;
123
        }
124
125 12
        $connection = $this->getLastRequest()->getConnection();
126
127
        $connectionArray = [
128 12
            'host' => $connection->getHost(),
129 12
            'port' => $connection->getPort(),
130 12
            'transport' => $connection->getTransport(),
131 12
            'headers' => $connection->hasConfig('headers') ? $connection->getConfig('headers') : [],
132
        ];
133
134 12
        $this->_logger->logQuery($path, $method, $data, $queryTime, $connectionArray, $query, $engineMS, $itemCount);
135 12
    }
136
}
137