Document::readHeader()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * Sandro Keil (https://sandro-keil.de)
4
 *
5
 * @link      http://github.com/sandrokeil/arangodb-php-client for the canonical source repository
6
 * @copyright Copyright (c) 2018-2020 Sandro Keil
7
 * @license   http://github.com/sandrokeil/arangodb-php-client/blob/master/LICENSE.md New BSD License
8
 */
9
10
declare(strict_types=1);
11
12
namespace ArangoDb\Type;
13
14
use ArangoDb\Exception\LogicException;
15
use ArangoDb\Guard\Guard;
16
use ArangoDb\Http\Url;
17
use ArangoDb\Util\Json;
18
use Fig\Http\Message\RequestMethodInterface;
19
use Psr\Http\Message\RequestFactoryInterface;
20
use Psr\Http\Message\RequestInterface;
21
use Psr\Http\Message\StreamFactoryInterface;
22
23
final class Document implements DocumentType, Transactional
24
{
25
    /**
26
     * @var string|null
27
     */
28
    private $collectionName;
29
30
    /**
31
     * @var string|null
32
     */
33
    private $id;
34
35
    /**
36
     * @var array
37
     */
38
    private $options;
39
40
    /**
41
     * @var array
42
     */
43
    private $data;
44
45
    /**
46
     * @var string
47
     */
48
    private $uri;
49
50
    /**
51
     * @var string
52
     */
53
    private $method;
54
55
    /**
56
     * Guard
57
     *
58
     * @var Guard
59
     */
60
    private $guard;
61
62
    /**
63
     * @param null|string $collectionName
64
     * @param null|string $id
65
     * @param string $uri
66
     * @param string $method
67
     * @param array $options
68
     * @param array $docs
69
     */
70 27
    private function __construct(
71
        ?string $collectionName,
72
        ?string $id,
73
        string $uri = '',
74
        string $method = RequestMethodInterface::METHOD_GET,
75
        array $options = [],
76
        array $docs = []
77
    ) {
78 27
        $this->collectionName = $collectionName;
79 27
        $this->id = $id;
80 27
        $this->uri = $uri;
81 27
        $this->method = $method;
82 27
        $this->options = $options;
83 27
        $this->data = $docs;
84 27
    }
85
86 3
    public static function read(string $id): DocumentType
87
    {
88 3
        return new self(
89 3
            null,
90
            $id,
91 3
            Url::DOCUMENT . '/' . $id
92
        );
93
    }
94
95 4
    public static function readHeader(string $id): DocumentType
96
    {
97 4
        return new self(
98 4
            null,
99
            $id,
100 4
            Url::DOCUMENT . '/' . $id,
101 4
            RequestMethodInterface::METHOD_HEAD
102
        );
103
    }
104
105 24
    public static function create(
106
        string $collectionName,
107
        array $docs,
108
        int $flags = 0
109
    ): DocumentType {
110 24
        $options = [];
111
112 24
        if (0 !== ($flags & self::FLAG_RETURN_NEW)) {
113 13
            $options['returnNew'] = true;
114
        }
115 24
        if (0 !== ($flags & self::FLAG_WAIT_FOR_SYNC)) {
116
            $options['waitForSync'] = true;
117
        }
118 24
        if (0 !== ($flags & self::FLAG_SILENT)) {
119
            $options['silent'] = true;
120
        }
121
122 24
        return new self(
123 24
            $collectionName,
124 24
            null,
125 24
            Url::DOCUMENT . '/' . $collectionName,
126 24
            RequestMethodInterface::METHOD_POST,
127
            $options,
128
            $docs
129
        );
130
    }
131
132 1
    public static function delete(
133
        string $collectionName,
134
        array $keys,
135
        int $flags = 0
136
    ): DocumentType {
137 1
        $options = [];
138
139 1
        if (0 !== ($flags & self::FLAG_RETURN_OLD)) {
140
            $options['returnOld'] = true;
141
        }
142 1
        if (0 !== ($flags & self::FLAG_WAIT_FOR_SYNC)) {
143
            $options['waitForSync'] = true;
144
        }
145 1
        if (0 !== ($flags & self::FLAG_CHECK_REVS)) {
146
            $options['ignoreRevs'] = false;
147
        }
148
149 1
        return new self(
150 1
            $collectionName,
151 1
            null,
152 1
            Url::DOCUMENT . '/' . $collectionName,
153 1
            RequestMethodInterface::METHOD_DELETE,
154
            $options,
155
            $keys
156
        );
157
    }
158
159 3
    public static function deleteOne(
160
        string $id,
161
        int $flags = 0
162
    ): DocumentType {
163 3
        $options = [];
164
165 3
        if (0 !== ($flags & self::FLAG_RETURN_OLD)) {
166
            $options['returnOld'] = true;
167
        }
168 3
        if (0 !== ($flags & self::FLAG_WAIT_FOR_SYNC)) {
169
            $options['waitForSync'] = true;
170
        }
171 3
        if (0 !== ($flags & self::FLAG_SILENT)) {
172
            $options['silent'] = true;
173
        }
174 3
        return new self(null, $id, Url::DOCUMENT . '/' . $id, RequestMethodInterface::METHOD_DELETE, $options);
175
    }
176
177 2
    public static function update(
178
        string $collectionName,
179
        array $data,
180
        int $flags = 0
181
    ): DocumentType {
182 2
        $options = [];
183
184 2
        if (0 !== ($flags & self::FLAG_RETURN_OLD)) {
185
            $options['returnOld'] = true;
186
        }
187 2
        if (0 !== ($flags & self::FLAG_RETURN_NEW)) {
188 1
            $options['returnNew'] = true;
189
        }
190 2
        if (0 !== ($flags & self::FLAG_WAIT_FOR_SYNC)) {
191
            $options['waitForSync'] = true;
192
        }
193 2
        if (0 !== ($flags & self::FLAG_REPLACE_OBJECTS)) {
194
            $options['mergeObjects'] = false;
195
        }
196 2
        if (0 !== ($flags & self::FLAG_SILENT)) {
197
            $options['silent'] = true;
198
        }
199 2
        if (0 !== ($flags & self::FLAG_REMOVE_NULL)) {
200
            $options['keepNull'] = false;
201
        }
202
203 2
        return new self(
204 2
            $collectionName,
205 2
            null,
206 2
            Url::DOCUMENT . '/' . $collectionName,
207 2
            RequestMethodInterface::METHOD_PATCH,
208
            $options,
209
            $data
210
        );
211
    }
212
213 2
    public static function updateOne(
214
        string $id,
215
        array $data,
216
        int $flags = 0
217
    ): DocumentType {
218 2
        $options = [];
219
220 2
        if (0 !== ($flags & self::FLAG_RETURN_OLD)) {
221
            $options['returnOld'] = true;
222
        }
223 2
        if (0 !== ($flags & self::FLAG_RETURN_NEW)) {
224 1
            $options['returnNew'] = true;
225
        }
226 2
        if (0 !== ($flags & self::FLAG_WAIT_FOR_SYNC)) {
227
            $options['waitForSync'] = true;
228
        }
229 2
        if (0 !== ($flags & self::FLAG_REPLACE_OBJECTS)) {
230
            $options['mergeObjects'] = false;
231
        }
232 2
        if (0 !== ($flags & self::FLAG_SILENT)) {
233
            $options['silent'] = true;
234
        }
235 2
        if (0 !== ($flags & self::FLAG_REMOVE_NULL)) {
236
            $options['keepNull'] = false;
237
        }
238
239 2
        return new self(null, $id, Url::DOCUMENT . '/' . $id, RequestMethodInterface::METHOD_PATCH, $options, $data);
240
    }
241
242 2
    public static function replace(
243
        string $collectionName,
244
        array $data,
245
        int $flags = 0
246
    ): DocumentType {
247 2
        $options = [];
248
249 2
        if (0 !== ($flags & self::FLAG_RETURN_OLD)) {
250
            $options['returnOld'] = true;
251
        }
252 2
        if (0 !== ($flags & self::FLAG_RETURN_NEW)) {
253 1
            $options['returnNew'] = true;
254
        }
255 2
        if (0 !== ($flags & self::FLAG_WAIT_FOR_SYNC)) {
256
            $options['waitForSync'] = true;
257
        }
258 2
        if (0 !== ($flags & self::FLAG_SILENT)) {
259
            $options['silent'] = true;
260
        }
261 2
        if (0 !== ($flags & self::FLAG_CHECK_REVS)) {
262
            $options['ignoreRevs'] = true;
263
        }
264
265 2
        return new self(
266 2
            $collectionName,
267 2
            null,
268 2
            Url::DOCUMENT . '/' . $collectionName,
269 2
            RequestMethodInterface::METHOD_PUT,
270
            $options,
271
            $data
272
        );
273
    }
274
275 2
    public static function replaceOne(
276
        string $id,
277
        array $data,
278
        int $flags = 0
279
    ): DocumentType {
280 2
        $options = [];
281
282 2
        if (0 !== ($flags & self::FLAG_RETURN_OLD)) {
283
            $options['returnOld'] = true;
284
        }
285 2
        if (0 !== ($flags & self::FLAG_RETURN_NEW)) {
286 1
            $options['returnNew'] = true;
287
        }
288 2
        if (0 !== ($flags & self::FLAG_WAIT_FOR_SYNC)) {
289
            $options['waitForSync'] = true;
290
        }
291 2
        if (0 !== ($flags & self::FLAG_SILENT)) {
292
            $options['silent'] = true;
293
        }
294 2
        if (0 !== ($flags & self::FLAG_CHECK_REVS)) {
295
            $options['ignoreRevs'] = false;
296
        }
297
298 2
        return new self(null, $id, Url::DOCUMENT . '/' . $id, RequestMethodInterface::METHOD_PUT, $options, $data);
299
    }
300
301 19
    public function toRequest(
302
        RequestFactoryInterface $requestFactory,
303
        StreamFactoryInterface $streamFactory
304
    ): RequestInterface {
305 19
        $uri = $this->uri;
306
307 19
        if (0 !== count($this->options)) {
308 6
            $uri .= '?' . http_build_query($this->options);
309
        }
310
311 19
        $request = $requestFactory->createRequest($this->method, $uri);
312
313 19
        if (0 === count($this->data)) {
314 6
            return $request;
315
        }
316
317 17
        return $request->withBody($streamFactory->createStream(Json::encode($this->data)));
318
    }
319
320 7
    public function toJs(): string
321
    {
322 7
        if (null !== $this->collectionName) {
323 7
            switch ($this->method) {
324
                case RequestMethodInterface::METHOD_POST:
325 7
                    return 'var rId = db.' . $this->collectionName
326 7
                        . '.insert(' . Json::encode($this->data) . ', ' . Json::encode($this->options) . ');';
327
                case RequestMethodInterface::METHOD_DELETE:
328
                    return 'var rId = db.' . $this->collectionName
329
                        . '.removeByKeys(' . Json::encode($this->data) . ');';
330
331
                case RequestMethodInterface::METHOD_PUT:
332
                case RequestMethodInterface::METHOD_PATCH:
333 2
                    $function = $this->method === RequestMethodInterface::METHOD_PUT ? 'replace' : 'update';
334
335
                    $keys = array_map(function ($doc) {
336 2
                        if (isset($doc['_key'])) {
337 2
                            return ['_key' => $doc['_key']];
338
                        }
339
                        if (isset($doc['_id'])) {
340
                            return ['_id' => $doc['_id']];
341
                        }
342
                        throw new LogicException('Cannot perform document updates due missing _key or _id value.');
343 2
                    }, $this->data);
344
345 2
                    return 'var rId = db.' . $this->collectionName
346 2
                        . '.' . $function . '(' . Json::encode($keys) . ', '
347 2
                        . Json::encode($this->data) . ', '
348 2
                        . Json::encode($this->options) . ');';
349
                default:
350
                    break;
351
            }
352
        }
353
354 2
        if (null !== $this->id) {
355 2
            switch ($this->method) {
356
                case RequestMethodInterface::METHOD_PUT:
357 1
                    return 'var rId = db._replace("' . $this->id . '", '
358 1
                        . Json::encode($this->data) . ', '
359 1
                        . Json::encode($this->options) . ');';
360
                case RequestMethodInterface::METHOD_DELETE:
361
                    return 'var rId = db._remove("' . $this->id . '", ' . Json::encode($this->options) . ');';
362
                case RequestMethodInterface::METHOD_PATCH:
363 1
                    return 'var rId = db._update("' . $this->id . '", '
364 1
                        . Json::encode($this->data) . ', '
365 1
                        . Json::encode($this->options) . ');';
366
                default:
367
                    return 'var rId = db._document("' . $this->id . '");';
368
            }
369
        }
370
        throw new LogicException('This operation is not supported');
371
    }
372
373 7
    public function collectionsRead(): array
374
    {
375 7
        if ($this->method === RequestMethodInterface::METHOD_GET
376 7
            && $collectionName = $this->determineCollectionName()
377
        ) {
378
            return [$collectionName];
379
        }
380 7
        return [];
381
    }
382
383 7
    public function collectionsWrite(): array
384
    {
385 7
        if ($this->method !== RequestMethodInterface::METHOD_GET
386 7
            && $collectionName = $this->determineCollectionName()
387
        ) {
388 7
            return [$collectionName];
389
        }
390
        return [];
391
    }
392
393 7
    private function determineCollectionName(): ?string
394
    {
395 7
        if (null !== $this->collectionName) {
396 7
            return $this->collectionName;
397
        }
398 2
        if (null !== $this->id
399 2
            && ($length = strpos($this->id, '/')) !== false
400
        ) {
401 2
            return substr($this->id, 0, $length);
402
        }
403
        return null;
404
    }
405
406 7
    public function useGuard(Guard $guard): Type
407
    {
408 7
        $this->guard = $guard;
409 7
        return $this;
410
    }
411
412 16
    public function guard(): ?Guard
413
    {
414 16
        return $this->guard;
415
    }
416
}
417