Passed
Pull Request — master (#51)
by Dante
01:10
created

BEditaClient::removeObjects()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
/**
4
 * BEdita, API-first content management framework
5
 * Copyright 2023 Atlas Srl, ChannelWeb Srl, Chialab Srl
6
 *
7
 * Licensed under The MIT License
8
 * For full copyright and license information, please see the LICENSE.txt
9
 * Redistributions of files must retain the above copyright notice.
10
 */
11
12
namespace BEdita\SDK;
13
14
/**
15
 * BEdita API Client class
16
 */
17
class BEditaClient extends BaseClient
18
{
19
    /**
20
     * Classic authentication via POST /auth using username and password
21
     *
22
     * @param string $username username
23
     * @param string $password password
24
     * @return array|null Response in array format
25
     */
26
    public function authenticate(string $username, string $password): ?array
27
    {
28
        // remove `Authorization` header containing user data in JWT token when using API KEY
29
        $headers = $this->getDefaultHeaders();
30
        if (!empty($headers['X-Api-Key'])) {
31
            unset($headers['Authorization']);
32
            $this->setDefaultHeaders($headers);
33
        }
34
35
        return $this->post('/auth', json_encode(compact('username', 'password') + ['grant_type' => 'password']), ['Content-Type' => 'application/json']);
36
    }
37
38
    /**
39
     * GET a list of resources or objects of a given type
40
     *
41
     * @param string $type Object type name
42
     * @param array|null $query Optional query string
43
     * @param array|null $headers Custom request headers
44
     * @return array|null Response in array format
45
     */
46
    public function getObjects(string $type = 'objects', ?array $query = null, ?array $headers = null): ?array
47
    {
48
        return $this->get(sprintf('/%s', $type), $query, $headers);
49
    }
50
51
    /**
52
     * GET a single object of a given type
53
     *
54
     * @param int|string $id Object id
55
     * @param string $type Object type name
56
     * @param array|null $query Optional query string
57
     * @param array|null $headers Custom request headers
58
     * @return array|null Response in array format
59
     */
60
    public function getObject($id, string $type = 'objects', ?array $query = null, ?array $headers = null): ?array
61
    {
62
        return $this->get(sprintf('/%s/%s', $type, $id), $query, $headers);
63
    }
64
65
    /**
66
     * Get a list of related resources or objects
67
     *
68
     * @param int|string $id Resource id or object uname/id
69
     * @param string $type Type name
70
     * @param string $relation Relation name
71
     * @param array|null $query Optional query string
72
     * @param array|null $headers Custom request headers
73
     * @return array|null Response in array format
74
     */
75
    public function getRelated($id, string $type, string $relation, ?array $query = null, ?array $headers = null): ?array
76
    {
77
        return $this->get(sprintf('/%s/%s/%s', $type, $id, $relation), $query, $headers);
78
    }
79
80
    /**
81
     * Add a list of related resources or objects
82
     *
83
     * @param int|string $id Resource id or object uname/id
84
     * @param string $type Type name
85
     * @param string $relation Relation name
86
     * @param array $data Related resources or objects to add, MUST contain id and type
87
     * @param array|null $headers Custom request headers
88
     * @return array|null Response in array format
89
     */
90
    public function addRelated($id, string $type, string $relation, array $data, ?array $headers = null): ?array
91
    {
92
        return $this->post(sprintf('/%s/%s/relationships/%s', $type, $id, $relation), json_encode(compact('data')), $headers);
93
    }
94
95
    /**
96
     * Remove a list of related resources or objects
97
     *
98
     * @param int|string $id Resource id or object uname/id
99
     * @param string $type Type name
100
     * @param string $relation Relation name
101
     * @param array $data Related resources or objects to remove from relation
102
     * @param array|null $headers Custom request headers
103
     * @return array|null Response in array format
104
     */
105
    public function removeRelated($id, string $type, string $relation, array $data, ?array $headers = null): ?array
106
    {
107
        return $this->delete(sprintf('/%s/%s/relationships/%s', $type, $id, $relation), json_encode(compact('data')), $headers);
108
    }
109
110
    /**
111
     * Replace a list of related resources or objects: previuosly related are removed and replaced with these.
112
     *
113
     * @param int|string $id Object id
114
     * @param string $type Object type name
115
     * @param string $relation Relation name
116
     * @param array $data Related resources or objects to insert
117
     * @param array|null $headers Custom request headers
118
     * @return array|null Response in array format
119
     */
120
    public function replaceRelated($id, string $type, string $relation, array $data, ?array $headers = null): ?array
121
    {
122
        return $this->patch(sprintf('/%s/%s/relationships/%s', $type, $id, $relation), json_encode(compact('data')), $headers);
123
    }
124
125
    /**
126
     * Create a new object or resource (POST) or modify an existing one (PATCH)
127
     *
128
     * @param string $type Object or resource type name
129
     * @param array $data Object or resource data to save
130
     * @param array|null $headers Custom request headers
131
     * @return array|null Response in array format
132
     */
133
    public function save(string $type, array $data, ?array $headers = null): ?array
134
    {
135
        $id = null;
136
        if (array_key_exists('id', $data)) {
137
            $id = $data['id'];
138
            unset($data['id']);
139
        }
140
141
        $body = [
142
            'data' => [
143
                'type' => $type,
144
                'attributes' => $data,
145
            ],
146
        ];
147
        if (!$id) {
148
            return $this->post(sprintf('/%s', $type), json_encode($body), $headers);
149
        }
150
        $body['data']['id'] = $id;
151
152
        return $this->patch(sprintf('/%s/%s', $type, $id), json_encode($body), $headers);
153
    }
154
155
    /**
156
     * [DEPRECATED] Create a new object (POST) or modify an existing one (PATCH)
157
     *
158
     * @param string $type Object type name
159
     * @param array $data Object data to save
160
     * @param array|null $headers Custom request headers
161
     * @return array|null Response in array format
162
     * @deprecated Use `save()` method instead
163
     * @codeCoverageIgnore
164
     */
165
    public function saveObject(string $type, array $data, ?array $headers = null): ?array
166
    {
167
        return $this->save($type, $data, $headers);
168
    }
169
170
    /**
171
     * Delete an object (DELETE) => move to trashcan.
172
     *
173
     * @param int|string $id Object id
174
     * @param string $type Object type name
175
     * @return array|null Response in array format
176
     */
177
    public function deleteObject($id, string $type): ?array
178
    {
179
        return $this->delete(sprintf('/%s/%s', $type, $id));
180
    }
181
182
    /**
183
     * Delete objects (DELETE) => move to trashcan.
184
     *
185
     * @param array $ids Object ids
186
     * @param string|null $type Object type name
187
     * @return array|null Response in array format
188
     */
189
    public function deleteObjects(array $ids, string $type = 'objects'): ?array
190
    {
191
        return $this->delete(sprintf('/%s?ids=%s', $type, implode(',', $ids)));
192
    }
193
194
    /**
195
     * Remove an object => permanently remove object from trashcan.
196
     *
197
     * @param int|string $id Object id
198
     * @return array|null Response in array format
199
     */
200
    public function remove($id): ?array
201
    {
202
        return $this->delete(sprintf('/trash/%s', $id));
203
    }
204
205
    /**
206
     * Remove objects => permanently remove objects from trashcan.
207
     *
208
     * @param array $ids Object ids
209
     * @return array|null Response in array format
210
     */
211
    public function removeObjects(array $ids): ?array
212
    {
213
        return $this->delete(sprintf('/trash?ids=%s', implode(',', $ids)));
214
    }
215
216
    /**
217
     * Upload file (POST)
218
     *
219
     * @param string $filename The file name
220
     * @param string $filepath File full path: could be on a local filesystem or a remote reachable URL
221
     * @param array|null $headers Custom request headers
222
     * @return array|null Response in array format
223
     * @throws \BEdita\SDK\BEditaClientException
224
     */
225
    public function upload(string $filename, string $filepath, ?array $headers = null): ?array
226
    {
227
        if (!file_exists($filepath)) {
228
            throw new BEditaClientException('File not found', 500);
229
        }
230
        $file = file_get_contents($filepath);
231
        if (!$file) {
232
            throw new BEditaClientException('File get contents failed', 500);
233
        }
234
        if (empty($headers['Content-Type'])) {
235
            $headers['Content-Type'] = mime_content_type($filepath);
236
        }
237
238
        return $this->post(sprintf('/streams/upload/%s', $filename), $file, $headers);
239
    }
240
241
    /**
242
     * Create media by type and body data and link it to a stream:
243
     *  - `POST /:type` with `$body` as payload, create media object
244
     *  - `PATCH /streams/:stream_id/relationships/object` modify stream adding relation to media
245
     *  - `GET /:type/:id` get media data
246
     *
247
     * @param string $streamId The stream identifier
248
     * @param string $type The type
249
     * @param array $body The body data
250
     * @return array|null Response in array format
251
     * @throws \BEdita\SDK\BEditaClientException
252
     */
253
    public function createMediaFromStream($streamId, string $type, array $body): ?array
254
    {
255
        $id = $this->createMedia($type, $body);
256
        $this->addStreamToMedia($streamId, $id, $type);
257
258
        return $this->getObject($id, $type);
259
    }
260
261
    /**
262
     * Create media.
263
     *
264
     * @param string $type The type
265
     * @param array $body The body
266
     * @return string
267
     * @throws \BEdita\SDK\BEditaClientException
268
     */
269
    public function createMedia(string $type, array $body): string
270
    {
271
        $response = $this->post(sprintf('/%s', $type), json_encode($body));
272
        if (empty($response)) {
273
            throw new BEditaClientException('Invalid response from POST ' . sprintf('/%s', $type));
274
        }
275
276
        return (string)$response['data']['id'];
277
    }
278
279
    /**
280
     * Add stream to media using patch /streams/%s/relationships/object.
281
     *
282
     * @param string $streamId The stream ID
283
     * @param string $id The object ID
284
     * @param string $type The type
285
     * @return void
286
     * @throws \BEdita\SDK\BEditaClientException
287
     */
288
    public function addStreamToMedia(string $streamId, string $id, string $type): void
289
    {
290
        $response = $this->patch(
291
            sprintf('/streams/%s/relationships/object', $streamId),
292
            json_encode([
293
                'data' => [
294
                    'id' => $id,
295
                    'type' => $type,
296
                ],
297
            ])
298
        );
299
        if (empty($response)) {
300
            throw new BEditaClientException('Invalid response from PATCH ' . sprintf('/streams/%s/relationships/object', $id));
301
        }
302
    }
303
304
    /**
305
     * Thumbnail request using `GET /media/thumbs` endpoint
306
     *
307
     *  Usage:
308
     *          thumbs(123) => `GET /media/thumbs/123`
309
     *          thumbs(123, ['preset' => 'glide']) => `GET /media/thumbs/123&preset=glide`
310
     *          thumbs(null, ['ids' => '123,124,125']) => `GET /media/thumbs?ids=123,124,125`
311
     *          thumbs(null, ['ids' => '123,124,125', 'preset' => 'async']) => `GET /media/thumbs?ids=123,124,125&preset=async`
312
     *          thumbs(123, ['options' => ['w' => 100, 'h' => 80, 'fm' => 'jpg']]) => `GET /media/thumbs/123/options[w]=100&options[h]=80&options[fm]=jpg` (these options could be not available... just set in preset(s))
313
     *
314
     * @param int|null $id the media Id.
315
     * @param array $query The query params for thumbs call.
316
     * @return array|null Response in array format
317
     */
318
    public function thumbs($id = null, $query = []): ?array
319
    {
320
        if (empty($id) && empty($query['ids'])) {
321
            throw new BEditaClientException('Invalid empty id|ids for thumbs');
322
        }
323
        $endpoint = empty($id) ? '/media/thumbs' : sprintf('/media/thumbs/%d', $id);
324
325
        return $this->get($endpoint, $query);
326
    }
327
328
    /**
329
     * Get JSON SCHEMA of a resource or object
330
     *
331
     * @param string $type Object or resource type name
332
     * @return array|null JSON SCHEMA in array format
333
     */
334
    public function schema(string $type): ?array
335
    {
336
        return $this->get(
337
            sprintf('/model/schema/%s', $type),
338
            null,
339
            ['Accept' => 'application/schema+json']
340
        );
341
    }
342
343
    /**
344
     * Get info of a relation (data, params) and get left/right object types
345
     *
346
     * @param string $name relation name
347
     * @return array|null relation data in array format
348
     */
349
    public function relationData(string $name): ?array
350
    {
351
        return $this->get(
352
            sprintf('/model/relations/%s', $name),
353
            ['include' => 'left_object_types,right_object_types']
354
        );
355
    }
356
357
    /**
358
     * Restore object from trash
359
     *
360
     * @param int|string $id Object id
361
     * @param string $type Object type name
362
     * @return array|null Response in array format
363
     */
364
    public function restoreObject($id, string $type): ?array
365
    {
366
        return $this->patch(
367
            sprintf('/trash/%s', $id),
368
            json_encode([
369
                'data' => [
370
                    'id' => $id,
371
                    'type' => $type,
372
                ],
373
            ])
374
        );
375
    }
376
377
    /**
378
     * Restore objects from trash
379
     *
380
     * @param array $ids Object ids
381
     * @param string|null $type Object type
382
     * @return array|null Response in array format
383
     */
384
    public function restoreObjects(array $ids, string $type = 'objects'): ?array
385
    {
386
        $res = null;
387
        foreach ($ids as $id) {
388
            $res = !empty($res) ? $res : $this->restoreObject($id, $type);
389
        }
390
391
        return $res;
392
    }
393
}
394