Completed
Push — master ( 1a67d2...dfab50 )
by Neomerx
11:35 queued 22s
created

mapSchemaDataToModelData()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 37
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 7

Importance

Changes 0
Metric Value
dl 0
loc 37
ccs 23
cts 23
cp 1
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 27
nc 7
nop 3
crap 7
1
<?php namespace Limoncello\Flute\Http\Traits;
2
3
/**
4
 * Copyright 2015-2017 [email protected]
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use Closure;
20
use Limoncello\Contracts\Application\ModelInterface;
21
use Limoncello\Contracts\Data\ModelSchemaInfoInterface;
22
use Limoncello\Contracts\Data\RelationshipTypes;
23
use Limoncello\Contracts\L10n\FormatterFactoryInterface;
24
use Limoncello\Contracts\Settings\SettingsProviderInterface;
25
use Limoncello\Flute\Contracts\Api\CrudInterface;
26
use Limoncello\Flute\Contracts\Encoder\EncoderInterface;
27
use Limoncello\Flute\Contracts\FactoryInterface;
28
use Limoncello\Flute\Contracts\Http\Query\ParametersMapperInterface;
29
use Limoncello\Flute\Contracts\Models\PaginatedDataInterface;
30
use Limoncello\Flute\Contracts\Schema\JsonSchemasInterface;
31
use Limoncello\Flute\Contracts\Schema\SchemaInterface;
32
use Limoncello\Flute\Contracts\Validation\JsonApiDataRulesInterface;
33
use Limoncello\Flute\Contracts\Validation\JsonApiDataValidatingParserInterface;
34
use Limoncello\Flute\Contracts\Validation\JsonApiParserFactoryInterface;
35
use Limoncello\Flute\Contracts\Validation\JsonApiQueryRulesInterface;
36
use Limoncello\Flute\Contracts\Validation\JsonApiQueryValidatingParserInterface;
37
use Limoncello\Flute\Http\Responses;
38
use Limoncello\Flute\Package\FluteSettings as S;
39
use Limoncello\Flute\Resources\Messages\En\Generic;
40
use Limoncello\Flute\Validation\JsonApi\Rules\DefaultQueryValidationRules;
41
use Neomerx\JsonApi\Contracts\Document\DocumentInterface as DI;
42
use Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface;
43
use Neomerx\JsonApi\Contracts\Http\Headers\MediaTypeInterface;
44
use Neomerx\JsonApi\Contracts\Http\ResponsesInterface;
45
use Neomerx\JsonApi\Encoder\Parameters\EncodingParameters;
46
use Neomerx\JsonApi\Exceptions\JsonApiException;
47
use Neomerx\JsonApi\Http\Headers\MediaType;
48
use Psr\Container\ContainerExceptionInterface;
49
use Psr\Container\ContainerInterface;
50
use Psr\Container\NotFoundExceptionInterface;
51
use Psr\Http\Message\ResponseInterface;
52
use Psr\Http\Message\UriInterface;
53
54
/**
55
 * @package Limoncello\Flute
56
 */
57
trait DefaultControllerMethodsTrait
58
{
59
    /** @noinspection PhpTooManyParametersInspection
60
     * @param array                                 $queryParams
61
     * @param UriInterface                          $requestUri
62
     * @param JsonApiQueryValidatingParserInterface $queryParser
63
     * @param ParametersMapperInterface             $mapper
64
     * @param CrudInterface                         $crud
65
     * @param SettingsProviderInterface             $provider
66
     * @param JsonSchemasInterface                  $jsonSchemas
67
     * @param EncoderInterface                      $encoder
68
     *
69
     * @return ResponseInterface
70
     */
71 12
    protected static function defaultIndexHandler(
72
        array $queryParams,
73
        UriInterface $requestUri,
74
        JsonApiQueryValidatingParserInterface $queryParser,
75
        ParametersMapperInterface $mapper,
76
        CrudInterface $crud,
77
        SettingsProviderInterface $provider,
78
        JsonSchemasInterface $jsonSchemas,
79
        EncoderInterface $encoder
80
    ): ResponseInterface {
81 12
        $queryParser->parse($queryParams);
82
83 11
        $models = $mapper->applyQueryParameters($queryParser, $crud)->index();
84
85 10
        $encParams = self::defaultCreateEncodingParameters($queryParser);
86 10
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
87 10
        $response  = ($models->getData()) === null ?
88 10
            $responses->getCodeResponse(404) : $responses->getContentResponse($models);
89
90 10
        return $response;
91
    }
92
93
    /** @noinspection PhpTooManyParametersInspection
94
     * @param string                                $index
95
     * @param array                                 $queryParams
96
     * @param UriInterface                          $requestUri
97
     * @param JsonApiQueryValidatingParserInterface $queryParser
98
     * @param ParametersMapperInterface             $mapper
99
     * @param CrudInterface                         $crud
100
     * @param SettingsProviderInterface             $provider
101
     * @param JsonSchemasInterface                  $jsonSchemas
102
     * @param EncoderInterface                      $encoder
103
     *
104
     * @return ResponseInterface
105
     */
106 1
    protected static function defaultReadHandler(
107
        string $index,
108
        array $queryParams,
109
        UriInterface $requestUri,
110
        JsonApiQueryValidatingParserInterface $queryParser,
111
        ParametersMapperInterface $mapper,
112
        CrudInterface $crud,
113
        SettingsProviderInterface $provider,
114
        JsonSchemasInterface $jsonSchemas,
115
        EncoderInterface $encoder
116
    ): ResponseInterface {
117 1
        $queryParser->parse($queryParams);
118
119 1
        $model = $mapper->applyQueryParameters($queryParser, $crud)->read($index);
120 1
        assert(!($model instanceof PaginatedDataInterface));
121
122 1
        $encParams = self::defaultCreateEncodingParameters($queryParser);
123 1
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
124 1
        $response  = $model === null ?
125 1
            $responses->getCodeResponse(404) : $responses->getContentResponse($model);
126
127 1
        return $response;
128
    }
129
130
    /** @noinspection PhpTooManyParametersInspection
131
     * @param Closure                               $apiHandler
132
     * @param array                                 $queryParams
133
     * @param UriInterface                          $requestUri
134
     * @param JsonApiQueryValidatingParserInterface $queryParser
135
     * @param ParametersMapperInterface             $mapper
136
     * @param CrudInterface                         $crud
137
     * @param SettingsProviderInterface             $provider
138
     * @param JsonSchemasInterface                  $jsonSchemas
139
     * @param EncoderInterface                      $encoder
140
     *
141
     * @return ResponseInterface
142
     */
143 2
    protected static function defaultReadRelationshipWithClosureHandler(
144
        Closure $apiHandler,
145
        array $queryParams,
146
        UriInterface $requestUri,
147
        JsonApiQueryValidatingParserInterface $queryParser,
148
        ParametersMapperInterface $mapper,
149
        CrudInterface $crud,
150
        SettingsProviderInterface $provider,
151
        JsonSchemasInterface $jsonSchemas,
152
        EncoderInterface $encoder
153
    ): ResponseInterface {
154 2
        $queryParser->parse($queryParams);
155 2
        $mapper->applyQueryParameters($queryParser, $crud);
156
157 2
        $relData = call_user_func($apiHandler);
158
159 2
        $encParams = self::defaultCreateEncodingParameters($queryParser);
160 2
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
161
162 2
        $noData   = $relData === null || ($relData instanceof PaginatedDataInterface && $relData->getData() === null);
163 2
        $response = $noData === true ? $responses->getCodeResponse(404) : $responses->getContentResponse($relData);
164
165 2
        return $response;
166
    }
167
168
    /** @noinspection PhpTooManyParametersInspection
169
     * @param Closure                               $apiHandler
170
     * @param array                                 $queryParams
171
     * @param UriInterface                          $requestUri
172
     * @param JsonApiQueryValidatingParserInterface $queryParser
173
     * @param ParametersMapperInterface             $mapper
174
     * @param CrudInterface                         $crud
175
     * @param SettingsProviderInterface             $provider
176
     * @param JsonSchemasInterface                  $jsonSchemas
177
     * @param EncoderInterface                      $encoder
178
     *
179
     * @return ResponseInterface
180
     */
181 1
    protected static function defaultReadRelationshipIdentifiersWithClosureHandler(
182
        Closure $apiHandler,
183
        array $queryParams,
184
        UriInterface $requestUri,
185
        JsonApiQueryValidatingParserInterface $queryParser,
186
        ParametersMapperInterface $mapper,
187
        CrudInterface $crud,
188
        SettingsProviderInterface $provider,
189
        JsonSchemasInterface $jsonSchemas,
190
        EncoderInterface $encoder
191
    ): ResponseInterface {
192 1
        $queryParser->parse($queryParams);
193 1
        $mapper->applyQueryParameters($queryParser, $crud);
194
195 1
        $relData = call_user_func($apiHandler);
196
197 1
        $encParams = self::defaultCreateEncodingParameters($queryParser);
198 1
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
199
200 1
        $noData   = $relData === null || ($relData instanceof PaginatedDataInterface && $relData->getData() === null);
201 1
        $response = $noData === true ? $responses->getCodeResponse(404) : $responses->getIdentifiersResponse($relData);
202
203 1
        return $response;
204
    }
205
206
    /** @noinspection PhpTooManyParametersInspection
207
     * @param UriInterface                         $requestUri
208
     * @param string                               $requestBody
209
     * @param string                               $schemaClass
210
     * @param ModelSchemaInfoInterface             $schemaInfo
211
     * @param JsonApiDataValidatingParserInterface $validator
212
     * @param CrudInterface                        $crud
213
     * @param SettingsProviderInterface            $provider
214
     * @param JsonSchemasInterface                 $jsonSchemas
215
     * @param EncoderInterface                     $encoder
216
     * @param FactoryInterface                     $errorFactory
217
     * @param FormatterFactoryInterface            $formatterFactory
218
     *
219
     * @return ResponseInterface
220
     *
221
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
222
     */
223 1
    protected static function defaultCreateHandler(
224
        UriInterface $requestUri,
225
        string $requestBody,
226
        string $schemaClass,
227
        ModelSchemaInfoInterface $schemaInfo,
228
        JsonApiDataValidatingParserInterface $validator,
229
        CrudInterface $crud,
230
        SettingsProviderInterface $provider,
231
        JsonSchemasInterface $jsonSchemas,
232
        EncoderInterface $encoder,
233
        FactoryInterface $errorFactory,
234
        FormatterFactoryInterface $formatterFactory
235
    ): ResponseInterface {
236
        // some of the users want to reuse default `create` but have a custom part for responses
237
        // to meet this requirement it is split into two parts.
238 1
        $index = static::defaultCreate(
239 1
            $requestBody,
240 1
            $schemaClass,
241 1
            $schemaInfo,
242 1
            $validator,
243 1
            $crud,
244 1
            $errorFactory,
245 1
            $formatterFactory
246
        );
247
248 1
        return static::defaultCreateResponse($index, $requestUri, $crud, $provider, $jsonSchemas, $encoder);
249
    }
250
251
    /**
252
     * @param string                               $requestBody
253
     * @param string                               $schemaClass
254
     * @param ModelSchemaInfoInterface             $schemaInfo
255
     * @param JsonApiDataValidatingParserInterface $validator
256
     * @param CrudInterface                        $crud
257
     * @param FactoryInterface                     $errorFactory
258
     * @param FormatterFactoryInterface            $formatterFactory
259
     *
260
     * @return ResponseInterface
0 ignored issues
show
Documentation introduced by
Should the return type not be string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
261
     */
262 1
    protected static function defaultCreate(
263
        string $requestBody,
264
        string $schemaClass,
265
        ModelSchemaInfoInterface $schemaInfo,
266
        JsonApiDataValidatingParserInterface $validator,
267
        CrudInterface $crud,
268
        FactoryInterface $errorFactory,
269
        FormatterFactoryInterface $formatterFactory
270
    ): string {
271 1
        $jsonData = static::readJsonFromRequest($requestBody, $errorFactory, $formatterFactory);
272 1
        $captures = $validator->assert($jsonData)->getJsonApiCaptures();
273
274 1
        list ($index, $attributes, $toMany) = static::mapSchemaDataToModelData($captures, $schemaClass, $schemaInfo);
275
276 1
        $index = $crud->create($index, $attributes, $toMany);
277
278 1
        return $index;
279
    }
280
281
    /**
282
     * @param string                    $index
283
     * @param UriInterface              $requestUri
284
     * @param CrudInterface             $crud
285
     * @param SettingsProviderInterface $provider
286
     * @param JsonSchemasInterface      $jsonSchemas
287
     * @param EncoderInterface          $encoder
288
     *
289
     * @return ResponseInterface
290
     */
291 1
    protected static function defaultCreateResponse(
292
        string $index,
293
        UriInterface $requestUri,
294
        CrudInterface $crud,
295
        SettingsProviderInterface $provider,
296
        JsonSchemasInterface $jsonSchemas,
297
        EncoderInterface $encoder
298
    ): ResponseInterface {
299 1
        $model = $crud->read($index);
300 1
        assert($model !== null && !($model instanceof PaginatedDataInterface));
301
302 1
        $encParams = null;
303 1
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
304 1
        $response  = $responses->getCreatedResponse($model);
305
306 1
        return $response;
307
    }
308
309
    /** @noinspection PhpTooManyParametersInspection
310
     * @param string                               $index
311
     * @param UriInterface                         $requestUri
312
     * @param string                               $requestBody
313
     * @param string                               $schemaClass
314
     * @param ModelSchemaInfoInterface             $schemaInfo
315
     * @param JsonApiDataValidatingParserInterface $validator
316
     * @param CrudInterface                        $crud
317
     * @param SettingsProviderInterface            $provider
318
     * @param JsonSchemasInterface                 $jsonSchemas
319
     * @param EncoderInterface                     $encoder
320
     * @param FactoryInterface                     $errorFactory
321
     * @param FormatterFactoryInterface            $formatterFactory
322
     * @param string                               $messagesNamespace
323
     * @param string                               $errorMessage
324
     *
325
     * @return ResponseInterface
326
     *
327
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
328
     */
329 6
    protected static function defaultUpdateHandler(
330
        string $index,
331
        UriInterface $requestUri,
332
        string $requestBody,
333
        string $schemaClass,
334
        ModelSchemaInfoInterface $schemaInfo,
335
        JsonApiDataValidatingParserInterface $validator,
336
        CrudInterface $crud,
337
        SettingsProviderInterface $provider,
338
        JsonSchemasInterface $jsonSchemas,
339
        EncoderInterface $encoder,
340
        FactoryInterface $errorFactory,
341
        FormatterFactoryInterface $formatterFactory,
342
        string $messagesNamespace = S::GENERIC_NAMESPACE,
343
        string $errorMessage = Generic::MSG_ERR_INVALID_ELEMENT
344
    ): ResponseInterface {
345
        // some of the users want to reuse default `update` but have a custom part for responses
346
        // to meet this requirement it is split into two parts.
347 6
        $updated = static::defaultUpdate(
348 6
            $index,
349 6
            $requestBody,
350 6
            $schemaClass,
351 6
            $schemaInfo,
352 6
            $validator,
353 6
            $crud,
354 6
            $errorFactory,
355 6
            $formatterFactory,
356 6
            $messagesNamespace,
357 6
            $errorMessage
358
        );
359
360 3
        return static::defaultUpdateResponse($updated, $index, $requestUri, $crud, $provider, $jsonSchemas, $encoder);
361
    }
362
363
    /** @noinspection PhpTooManyParametersInspection
364
     * @param string                               $index
365
     * @param string                               $requestBody
366
     * @param string                               $schemaClass
367
     * @param ModelSchemaInfoInterface             $schemaInfo
368
     * @param JsonApiDataValidatingParserInterface $validator
369
     * @param CrudInterface                        $crud
370
     * @param FactoryInterface                     $errorFactory
371
     * @param FormatterFactoryInterface            $formatterFactory
372
     * @param string                               $messagesNamespace
373
     * @param string                               $errorMessage
374
     *
375
     * @return int
376
     *
377
     * @SuppressWarnings(PHPMD.ElseExpression)
378
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
379
     */
380 6
    protected static function defaultUpdate(
381
        string $index,
382
        string $requestBody,
383
        string $schemaClass,
384
        ModelSchemaInfoInterface $schemaInfo,
385
        JsonApiDataValidatingParserInterface $validator,
386
        CrudInterface $crud,
387
        FactoryInterface $errorFactory,
388
        FormatterFactoryInterface $formatterFactory,
389
        string $messagesNamespace = S::GENERIC_NAMESPACE,
390
        string $errorMessage = Generic::MSG_ERR_INVALID_ELEMENT
391
    ): int {
392 6
        $jsonData = static::readJsonFromRequest($requestBody, $errorFactory, $formatterFactory);
393
        // check that index in data and URL are identical
394 5
        $indexValue = $jsonData[DI::KEYWORD_DATA][DI::KEYWORD_ID] ?? null;
395 5
        if (empty($indexValue) === false) {
396 4
            if ($indexValue !== $index) {
397 1
                $errors    = $errorFactory->createErrorCollection();
398 1
                $formatter = $formatterFactory->createFormatter($messagesNamespace);
399 1
                $errors->addDataIdError($formatter->formatMessage($errorMessage));
400
401 4
                throw new JsonApiException($errors);
402
            }
403
        } else {
404
            // put the index to data for our convenience
405 1
            $jsonData[DI::KEYWORD_DATA][DI::KEYWORD_ID] = $index;
406
        }
407
        // validate the data
408 4
        $captures = $validator->assert($jsonData)->getJsonApiCaptures();
409
410 3
        list ($index, $attributes, $toMany) = static::mapSchemaDataToModelData($captures, $schemaClass, $schemaInfo);
411
412 3
        $updated = $crud->update($index, $attributes, $toMany);
413
414 3
        return $updated;
415
    }
416
417
    /**
418
     * @param int                       $updated
419
     * @param string                    $index
420
     * @param UriInterface              $requestUri
421
     * @param CrudInterface             $crud
422
     * @param SettingsProviderInterface $provider
423
     * @param JsonSchemasInterface      $jsonSchemas
424
     * @param EncoderInterface          $encoder
425
     *
426
     * @return ResponseInterface
427
     *
428
     * @SuppressWarnings(PHPMD.ElseExpression)
429
     */
430 3
    protected static function defaultUpdateResponse(
431
        int $updated,
432
        string $index,
433
        UriInterface $requestUri,
434
        CrudInterface $crud,
435
        SettingsProviderInterface $provider,
436
        JsonSchemasInterface $jsonSchemas,
437
        EncoderInterface $encoder
438
    ): ResponseInterface {
439 3
        $encParams = null;
440 3
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
441 3
        if ($updated > 0 && ($model = $crud->read($index)) !== null) {
442 2
            assert(!($model instanceof PaginatedDataInterface));
443 2
            $response = $responses->getContentResponse($model);
444
        } else {
445 1
            $response = $responses->getCodeResponse(404);
446
        }
447
448 3
        return $response;
449
    }
450
451
    /** @noinspection PhpTooManyParametersInspection
452
     * @param string                               $parentIndex
453
     * @param string                               $modelRelName
454
     * @param string                               $childIndex
455
     * @param UriInterface                         $requestUri
456
     * @param string                               $requestBody
457
     * @param string                               $childSchemaClass
458
     * @param ModelSchemaInfoInterface             $schemaInfo
459
     * @param JsonApiDataValidatingParserInterface $childValidator
460
     * @param CrudInterface                        $parentCrud
461
     * @param CrudInterface                        $childCrud
462
     * @param SettingsProviderInterface            $provider
463
     * @param JsonSchemasInterface                 $jsonSchemas
464
     * @param EncoderInterface                     $encoder
465
     * @param FactoryInterface                     $errorFactory
466
     * @param FormatterFactoryInterface            $formatterFactory
467
     * @param string                               $messagesNamespace
468
     * @param string                               $errorMessage
469
     *
470
     * @return ResponseInterface
471
     *
472
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
473
     */
474 2
    protected static function defaultUpdateInRelationshipHandler(
475
        string $parentIndex,
476
        string $modelRelName,
477
        string $childIndex,
478
        UriInterface $requestUri,
479
        string $requestBody,
480
        string $childSchemaClass,
481
        ModelSchemaInfoInterface $schemaInfo,
482
        JsonApiDataValidatingParserInterface $childValidator,
483
        CrudInterface $parentCrud,
484
        CrudInterface $childCrud,
485
        SettingsProviderInterface $provider,
486
        JsonSchemasInterface $jsonSchemas,
487
        EncoderInterface $encoder,
488
        FactoryInterface $errorFactory,
489
        FormatterFactoryInterface $formatterFactory,
490
        string $messagesNamespace = S::GENERIC_NAMESPACE,
491
        string $errorMessage = Generic::MSG_ERR_INVALID_ELEMENT
492
    ): ResponseInterface {
493 2
        if ($parentCrud->hasInRelationship($parentIndex, $modelRelName, $childIndex) === true) {
494 1
            return static::defaultUpdateHandler(
495 1
                $childIndex,
496 1
                $requestUri,
497 1
                $requestBody,
498 1
                $childSchemaClass,
499 1
                $schemaInfo,
500 1
                $childValidator,
501 1
                $childCrud,
502 1
                $provider,
503 1
                $jsonSchemas,
504 1
                $encoder,
505 1
                $errorFactory,
506 1
                $formatterFactory,
507 1
                $messagesNamespace,
508 1
                $errorMessage
509
            );
510
        }
511
512 1
        $encParams = null;
513 1
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
514
515 1
        return $responses->getCodeResponse(404);
516
    }
517
518
    /**
519
     * @param string                    $index
520
     * @param UriInterface              $requestUri
521
     * @param CrudInterface             $crud
522
     * @param SettingsProviderInterface $provider
523
     * @param JsonSchemasInterface      $jsonSchemas
524
     * @param EncoderInterface          $encoder
525
     *
526
     * @return ResponseInterface
527
     */
528 2
    protected static function defaultDeleteHandler(
529
        string $index,
530
        UriInterface $requestUri,
531
        CrudInterface $crud,
532
        SettingsProviderInterface $provider,
533
        JsonSchemasInterface $jsonSchemas,
534
        EncoderInterface $encoder
535
    ): ResponseInterface {
536 2
        $crud->remove($index);
537
538 2
        $encParams = null;
539 2
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
540 2
        $response  = $responses->getCodeResponse(204);
541
542 2
        return $response;
543
    }
544
545
    /** @noinspection PhpTooManyParametersInspection
546
     * @param string                    $parentIndex
547
     * @param string                    $modelRelName
548
     * @param string                    $childIndex
549
     * @param UriInterface              $requestUri
550
     * @param CrudInterface             $parentCrud
551
     * @param CrudInterface             $childCrud
552
     * @param SettingsProviderInterface $provider
553
     * @param JsonSchemasInterface      $jsonSchemas
554
     * @param EncoderInterface          $encoder
555
     *
556
     * @return ResponseInterface
557
     */
558 1
    protected static function defaultDeleteInRelationshipHandler(
559
        string $parentIndex,
560
        string $modelRelName,
561
        string $childIndex,
562
        UriInterface $requestUri,
563
        CrudInterface $parentCrud,
564
        CrudInterface $childCrud,
565
        SettingsProviderInterface $provider,
566
        JsonSchemasInterface $jsonSchemas,
567
        EncoderInterface $encoder
568
    ): ResponseInterface {
569 1
        if ($parentCrud->hasInRelationship($parentIndex, $modelRelName, $childIndex) === true) {
570 1
            return static::defaultDeleteHandler(
571 1
                $childIndex,
572 1
                $requestUri,
573 1
                $childCrud,
574 1
                $provider,
575 1
                $jsonSchemas,
576 1
                $encoder
577
            );
578
        }
579
580 1
        $encParams = null;
581 1
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
582
583 1
        return $responses->getCodeResponse(404);
584
    }
585
586
    /**
587
     * @param ContainerInterface $container
588
     * @param string             $rulesClass
589
     *
590
     * @return JsonApiQueryValidatingParserInterface
591
     *
592
     * @throws ContainerExceptionInterface
593
     * @throws NotFoundExceptionInterface
594
     */
595 16
    protected static function defaultCreateQueryParser(
596
        ContainerInterface $container,
597
        string $rulesClass = DefaultQueryValidationRules::class
598
    ): JsonApiQueryValidatingParserInterface {
599 16
        static::assertClassImplements($rulesClass, JsonApiQueryRulesInterface::class);
600
601
        /** @var JsonApiParserFactoryInterface $factory */
602 16
        $factory   = $container->get(JsonApiParserFactoryInterface::class);
603 16
        $validator = $factory->createQueryParser($rulesClass);
604
605 16
        return $validator;
606
    }
607
608
    /**
609
     * @param ContainerInterface $container
610
     * @param string             $rulesClass
611
     *
612
     * @return JsonApiDataValidatingParserInterface
613
     *
614
     * @throws ContainerExceptionInterface
615
     * @throws NotFoundExceptionInterface
616
     */
617 8
    protected static function defaultCreateDataParser(
618
        ContainerInterface $container,
619
        string $rulesClass
620
    ): JsonApiDataValidatingParserInterface {
621 8
        static::assertClassImplements($rulesClass, JsonApiDataRulesInterface::class);
622
623
        /** @var JsonApiParserFactoryInterface $factory */
624 8
        $factory   = $container->get(JsonApiParserFactoryInterface::class);
625 8
        $validator = $factory->createDataParser($rulesClass);
626
627 8
        return $validator;
628
    }
629
630
    /**
631
     * @param ContainerInterface $container
632
     * @param string             $schemaClass
633
     *
634
     * @return ParametersMapperInterface
635
     *
636
     * @throws ContainerExceptionInterface
637
     * @throws NotFoundExceptionInterface
638
     */
639 16
    protected static function defaultCreateParameterMapper(
640
        ContainerInterface $container,
641
        string $schemaClass
642
    ): ParametersMapperInterface {
643 16
        static::assertClassImplements($schemaClass, SchemaInterface::class);
644
645
        /** @var SchemaInterface $schemaClass */
646 16
        $jsonResourceType = $schemaClass::TYPE;
647
648
        /** @var ParametersMapperInterface $mapper */
649 16
        $mapper = $container->get(ParametersMapperInterface::class);
650 16
        $mapper->selectRootSchemaByResourceType($jsonResourceType);
651
652 16
        return $mapper;
653
    }
654
655
    /**
656
     * @param JsonApiQueryValidatingParserInterface $queryParser
657
     *
658
     * @return EncodingParametersInterface
659
     */
660 14
    protected static function defaultCreateEncodingParameters(
661
        JsonApiQueryValidatingParserInterface $queryParser
662
    ): EncodingParametersInterface {
663 14
        return new EncodingParameters(
664 14
            $queryParser->hasIncludes() === true ? array_keys($queryParser->getIncludes()) : null,
0 ignored issues
show
Bug introduced by
It seems like $queryParser->hasInclude...->getIncludes()) : null can also be of type array; however, Neomerx\JsonApi\Encoder\...rameters::__construct() does only seem to accept null|array<integer,string>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
665 14
            $queryParser->hasFields() === true ? $queryParser->getFields() : null
666
        );
667
    }
668
669
    /**
670
     * @param ContainerInterface $container
671
     * @param string|null        $class
672
     *
673
     * @return CrudInterface
674
     *
675
     * @throws ContainerExceptionInterface
676
     * @throws NotFoundExceptionInterface
677
     */
678 26
    protected static function defaultCreateApi(ContainerInterface $container, string $class): CrudInterface
679
    {
680 26
        static::assertClassImplements($class, CrudInterface::class);
681
682
        /** @var FactoryInterface $factory */
683 26
        $factory = $container->get(FactoryInterface::class);
684 26
        $api     = $factory->createApi($class);
685
686 26
        return $api;
687
    }
688
689
    /**
690
     * @param UriInterface                     $requestUri
691
     * @param SettingsProviderInterface        $provider
692
     * @param JsonSchemasInterface             $jsonSchemas
693
     * @param EncoderInterface                 $encoder
694
     * @param EncodingParametersInterface|null $parameters
695
     *
696
     * @return ResponsesInterface
697
     */
698 21
    protected static function defaultCreateResponses(
699
        UriInterface $requestUri,
700
        SettingsProviderInterface $provider,
701
        JsonSchemasInterface $jsonSchemas,
702
        EncoderInterface $encoder,
703
        ?EncodingParametersInterface $parameters
704
    ): ResponsesInterface {
705 21
        $encoder->forOriginalUri($requestUri);
706 21
        $settings  = $provider->get(S::class);
707 21
        $responses = new Responses(
708 21
            new MediaType(MediaTypeInterface::JSON_API_TYPE, MediaTypeInterface::JSON_API_SUB_TYPE),
709 21
            $encoder,
710 21
            $jsonSchemas,
711 21
            $parameters,
712 21
            $settings[S::KEY_URI_PREFIX],
713 21
            $settings[S::KEY_META]
714
        );
715
716 21
        return $responses;
717
    }
718
719
    /**
720
     * Developers can override the method in order to add/remove some data for `create`/`update` inputs.
721
     *
722
     * @param string                    $requestBody
723
     * @param FactoryInterface          $errorFactory
724
     * @param FormatterFactoryInterface $formatterFactory
725
     * @param string                    $messagesNamespace
726
     * @param string                    $errorMessage
727
     *
728
     * @return array
729
     */
730 7
    protected static function readJsonFromRequest(
731
        string $requestBody,
732
        FactoryInterface $errorFactory,
733
        FormatterFactoryInterface $formatterFactory,
734
        string $messagesNamespace = S::GENERIC_NAMESPACE,
735
        string $errorMessage = Generic::MSG_ERR_INVALID_ELEMENT
736
    ): array {
737 7
        if (empty($requestBody) === true || ($json = json_decode($requestBody, true)) === null) {
738 1
            $formatter = $formatterFactory->createFormatter($messagesNamespace);
739 1
            $errors    = $errorFactory->createErrorCollection();
740 1
            $errors->addDataError($formatter->formatMessage($errorMessage));
741
742 1
            throw new JsonApiException($errors);
743
        }
744
745 6
        return $json;
746
    }
747
748
    /**
749
     * Developers can override the method in order to use custom data mapping from a Schema to Model.
750
     *
751
     * @param array                    $captures
752
     * @param string                   $schemaClass
753
     * @param ModelSchemaInfoInterface $schemaInfo
754
     *
755
     * @return array
756
     */
757 4
    protected static function mapSchemaDataToModelData(
758
        array $captures,
759
        string $schemaClass,
760
        ModelSchemaInfoInterface $schemaInfo
761
    ): array {
762 4
        static::assertClassImplements($schemaClass, SchemaInterface::class);
763
764
        /** @var SchemaInterface $schemaClass */
765 4
        static::assertClassImplements($modelClass = $schemaClass::MODEL, ModelInterface::class);
766
        /** @var ModelInterface $modelClass */
767
768 4
        $index         = null;
769 4
        $fields        = [];
770 4
        $toManyIndexes = [];
771 4
        foreach ($captures as $name => $value) {
772 4
            assert(is_string($name) === true);
773 4
            if ($name === DI::KEYWORD_ID) {
774 4
                $index = $value;
775 4
            } elseif ($schemaClass::hasAttributeMapping($name) === true) {
776 4
                $fieldName          = $schemaClass::getAttributeMapping($name);
777 4
                $fields[$fieldName] = $value;
778 4
            } elseif ($schemaClass::hasRelationshipMapping($name) === true) {
779 2
                $modelRelName = $schemaClass::getRelationshipMapping($name);
780 2
                $relType      = $schemaInfo->getRelationshipType($modelClass, $modelRelName);
781 2
                if ($relType === RelationshipTypes::BELONGS_TO) {
782 2
                    $fkName          = $schemaInfo->getForeignKey($modelClass, $modelRelName);
783 2
                    $fields[$fkName] = $value;
784 2
                } elseif ($relType === RelationshipTypes::BELONGS_TO_MANY) {
785 4
                    $toManyIndexes[$modelRelName] = $value;
786
                }
787
            }
788
        }
789
790 4
        $result = [$index, $fields, $toManyIndexes];
791
792 4
        return $result;
793
    }
794
795
    /**
796
     * @param null|string $value
797
     *
798
     * @return void
799
     */
800 26
    private static function assertClassValueDefined(?string $value): void
801
    {
802 26
        assert(empty($value) === false, 'Value should be defined in `' . static::class . '`.');
803
    }
804
805
    /**
806
     * @param string $class
807
     * @param string $interface
808
     *
809
     * @return void
810
     */
811 26
    private static function assertClassImplements(string $class, string $interface): void
812
    {
813 26
        assert(
814 26
            array_key_exists($interface, class_implements($class)) === true,
815 26
            "Class `$class` should implement `" . $interface . '` interface.'
816
        );
817
    }
818
}
819