Passed
Pull Request — master (#38)
by Dante
01:13
created

BEditaClient::createMedia()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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