3
3
namespace Tobyz \JsonApiServer ;
4
4
5
5
use ArrayObject ;
6
+ use HttpAccept \AcceptParser ;
6
7
use Psr \Http \Message \ServerRequestInterface ;
7
8
use RuntimeException ;
8
9
use Tobyz \JsonApiServer \Endpoint \Endpoint ;
10
+ use Tobyz \JsonApiServer \Exception \NotAcceptableException ;
9
11
use Tobyz \JsonApiServer \Exception \Request \InvalidSparseFieldsetsException ;
10
12
use Tobyz \JsonApiServer \Resource \Collection ;
11
13
use Tobyz \JsonApiServer \Resource \Resource ;
@@ -29,6 +31,8 @@ class Context
29
31
30
32
private ?array $ body ;
31
33
private ?string $ path ;
34
+ private ?array $ requestedExtensions = null ;
35
+ private ?array $ requestedProfiles = null ;
32
36
33
37
private WeakMap $ endpoints ;
34
38
private WeakMap $ resourceIds ;
@@ -38,6 +42,8 @@ class Context
38
42
39
43
public function __construct (public JsonApi $ api , public ServerRequestInterface $ request )
40
44
{
45
+ $ this ->parseAcceptHeader ();
46
+
41
47
$ this ->endpoints = new WeakMap ();
42
48
$ this ->resourceIds = new WeakMap ();
43
49
$ this ->modelIds = new WeakMap ();
@@ -211,13 +217,93 @@ public function sortRequested(string $field): bool
211
217
return false ;
212
218
}
213
219
220
+ /**
221
+ * Determine whether a profile has been requested.
222
+ */
223
+ public function profileRequested (string $ uri ): bool
224
+ {
225
+ return in_array ($ uri , $ this ->requestedProfiles ());
226
+ }
227
+
228
+ /**
229
+ * Get all requested profile URIs.
230
+ *
231
+ * @return array
232
+ */
233
+ public function requestedProfiles (): array
234
+ {
235
+ if ($ this ->requestedProfiles === null ) {
236
+ $ this ->parseAcceptHeader ();
237
+ }
238
+
239
+ return $ this ->requestedProfiles ;
240
+ }
241
+
242
+ /**
243
+ * Get all requested extension URIs from Accept header.
244
+ *
245
+ * @return array
246
+ */
247
+ public function requestedExtensions (): array
248
+ {
249
+ if ($ this ->requestedExtensions === null ) {
250
+ $ this ->parseAcceptHeader ();
251
+ }
252
+
253
+ return $ this ->requestedExtensions ;
254
+ }
255
+
256
+ private function parseAcceptHeader (): void
257
+ {
258
+ $ accept = $ this ->request ->getHeaderLine ('Accept ' );
259
+
260
+ if (!$ accept ) {
261
+ $ this ->requestedProfiles = [];
262
+ $ this ->requestedExtensions = [];
263
+ return ;
264
+ }
265
+
266
+ $ list = (new AcceptParser ())->parse ($ accept );
267
+
268
+ foreach ($ list as $ mediaType ) {
269
+ if (!in_array ($ mediaType ->name (), [$ this ->api ::MEDIA_TYPE , '*/* ' ])) {
270
+ continue ;
271
+ }
272
+
273
+ if (array_diff (array_keys ($ mediaType ->parameters ()), ['ext ' , 'profile ' ])) {
274
+ continue ;
275
+ }
276
+
277
+ $ extensionUris = $ mediaType ->hasParamater ('ext ' )
278
+ ? explode (' ' , $ mediaType ->getParameter ('ext ' ))
279
+ : [];
280
+
281
+ if (array_diff ($ extensionUris , array_keys ($ this ->api ->extensions ))) {
282
+ continue ;
283
+ }
284
+
285
+ $ profileUris = $ mediaType ->hasParamater ('profile ' )
286
+ ? explode (' ' , $ mediaType ->getParameter ('profile ' ))
287
+ : [];
288
+
289
+ $ this ->requestedProfiles = $ profileUris ;
290
+ $ this ->requestedExtensions = $ extensionUris ;
291
+ return ;
292
+ }
293
+
294
+ throw new NotAcceptableException ();
295
+ }
296
+
214
297
public function withRequest (ServerRequestInterface $ request ): static
215
298
{
216
299
$ new = clone $ this ;
217
300
$ new ->request = $ request ;
218
301
$ new ->sparseFields = new WeakMap ();
219
302
$ new ->body = null ;
220
303
$ new ->path = null ;
304
+ $ new ->requestedProfiles = null ;
305
+ $ new ->requestedExtensions = null ;
306
+ $ new ->parseAcceptHeader ();
221
307
return $ new ;
222
308
}
223
309
0 commit comments