Passed
Push — next ( d68df8...ee030a )
by Bas
03:07
created

ArangoClient::jsonEncode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ArangoClient;
6
7
use ArangoClient\Admin\AdminManager;
8
use ArangoClient\Exceptions\ArangoException;
9
use ArangoClient\Schema\SchemaManager;
10
use Exception;
11
use GuzzleHttp\Client;
12
use GuzzleHttp\Exception\GuzzleException;
13
use GuzzleHttp\Exception\RequestException;
14
use GuzzleHttp\Psr7\StreamWrapper;
15
use JsonMachine\JsonMachine;
16
use Psr\Http\Message\ResponseInterface;
17
use Throwable;
18
19
/*
20
 * The arangoClient handles connections to ArangoDB's HTTP REST API.
21
 * @see https://www.arangodb.com/docs/stable/http/
22
 */
23
class ArangoClient
24
{
25
    /**
26
     * @var array<string|numeric|null>
27
     */
28
    protected array $config = [
29
        'host' => 'http://localhost',
30
        'port' => '8529',
31
        'AuthUser' => 'root',
32
        'AuthPassword' => null,
33
        'AuthType' => 'basic'
34
    ];
35
36
    protected Client $httpClient;
37
38
    /**
39
     * @var SchemaManager|null
40
     */
41
    protected ?SchemaManager $schemaManager = null;
42
43
    /**
44
     * @var AdminManager|null
45
     */
46
    protected ?AdminManager $adminManager = null;
47
48
    /**
49
     * ArangoClient constructor.
50
     *
51
     * @param  array<string|numeric|null>|null  $config
52
     * @param  Client|null  $httpClient
53
     */
54 52
    public function __construct(array $config = null, Client $httpClient = null)
55
    {
56 52
        if ($config !== null) {
57
            $this->config = $config;
58
        }
59
60 52
        $this->config = $this->mapHttpClientConfig();
61
62 52
        $this->httpClient = isset($httpClient) ? $httpClient : new Client($this->config);
63 52
    }
64
65
    /**
66
     * @psalm-suppress MixedReturnStatement
67
     *
68
     * @param  string  $method
69
     * @param  string  $uri
70
     * @param  array<mixed>  $options
71
     * @return array<mixed>
72
     * @throws ArangoException
73
     */
74 52
    public function request(string $method, string $uri, array $options = []): array
75
    {
76 52
        $response = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $response is dead and can be removed.
Loading history...
77
        try {
78 52
            $response = $this->httpClient->request($method, $uri, $options);
79 1
        } catch (\Throwable $e) {
80 1
            $this->handleGuzzleException($e);
81
        }
82
83 52
        return $this->decodeResponse($response);
84
    }
85
86
    /**
87
     * @return array<string|numeric|null>
88
     */
89 52
    protected function mapHttpClientConfig(): array
90
    {
91 52
        $this->config['base_uri'] = (string) $this->config['host'] . ':' . (string) $this->config['port'];
92
93 52
        return $this->config;
94
    }
95
96
    /**
97
     * @return array<string|numeric|null>
98
     */
99 1
    public function getConfig(): array
100
    {
101 1
        return $this->config;
102
    }
103
104
    /**
105
     * @psalm-suppress MixedAssignment, MixedArrayOffset
106
     * @SuppressWarnings(PHPMD.StaticAccess)
107
     *
108
     * @param  ResponseInterface|null  $response
109
     * @return array<mixed>
110
     */
111 52
    protected function decodeResponse(?ResponseInterface $response): array
112
    {
113 52
        if (! isset($response)) {
114
            return [];
115
        }
116
117 52
        $decodedResponse = [];
118
119 52
        $phpStream = StreamWrapper::getResource($response->getBody());
120 52
        $decodedStream = JsonMachine::fromStream($phpStream);
121
122 52
        foreach ($decodedStream as $key => $value) {
123 52
            $decodedResponse[$key] = $value;
124
        }
125
126 52
        return $decodedResponse;
127
    }
128
129
    /**
130
     * @param  array<mixed>  $data
131
     * @return string
132
     */
133 5
    public function jsonEncode(array $data)
134
    {
135 5
        return (string) json_encode($data, JSON_FORCE_OBJECT);
136
    }
137
138
    /**
139
     * @return string
140
     */
141 52
    public function getUser(): string
142
    {
143 52
        return (string) $this->config['AuthUser'];
144
    }
145
146
    /**
147
     * @param  string  $query
148
     * @param  array<scalar>  $bindVars
149
     * @param  array<array>  $collections
150
     * @param  array<scalar>  $options
151
     * @return Statement
152
     */
153 7
    public function prepare(
154
        string $query,
155
        array $bindVars = [],
156
        array $collections = [],
157
        array $options = []
158
    ): Statement {
159 7
        return new Statement($this, $query, $bindVars, $collections, $options);
160
    }
161
162
    /**
163
     * @return SchemaManager
164
     */
165 1
    public function schema(): SchemaManager
166
    {
167 1
        if (! isset($this->schemaManager)) {
168 1
            $this->schemaManager = new SchemaManager($this);
169
        }
170 1
        return $this->schemaManager;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->schemaManager could return the type null which is incompatible with the type-hinted return ArangoClient\Schema\SchemaManager. Consider adding an additional type-check to rule them out.
Loading history...
171
    }
172
    /**
173
     * @return AdminManager
174
     */
175 1
    public function admin(): AdminManager
176
    {
177 1
        if (! isset($this->adminManager)) {
178 1
            $this->adminManager = new AdminManager($this);
179
        }
180 1
        return $this->adminManager;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->adminManager could return the type null which is incompatible with the type-hinted return ArangoClient\Admin\AdminManager. Consider adding an additional type-check to rule them out.
Loading history...
181
    }
182
183
    /**
184
     * @param  Throwable  $e
185
     * @throws ArangoException
186
     */
187 1
    private function handleGuzzleException(Throwable $e): void
188
    {
189 1
        $message = $e->getMessage();
190 1
        $code = $e->getCode();
191 1
        if ($e instanceof RequestException && $e->hasResponse()) {
192 1
            $decodedResponse = $this->decodeResponse($e->getResponse());
193 1
            $message = (string) $decodedResponse['errorMessage'];
194 1
            $code = (int) $decodedResponse['code'];
195
        }
196
197
        throw(
198 1
            new ArangoException(
199 1
                $message,
200 1
                (int) $code
201
            )
202
        );
203
    }
204
}
205