Completed
Push — develop ( 5c8fb2...8f8d73 )
by Neomerx
07:05 queued 04:59
created

defaultReadHandler()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 9
cts 9
cp 1
rs 9.0856
c 0
b 0
f 0
cc 2
eloc 19
nc 2
nop 9
crap 2

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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\FormRulesInterface;
33
use Limoncello\Flute\Contracts\Validation\FormValidatorFactoryInterface;
34
use Limoncello\Flute\Contracts\Validation\FormValidatorInterface;
35
use Limoncello\Flute\Contracts\Validation\JsonApiDataRulesInterface;
36
use Limoncello\Flute\Contracts\Validation\JsonApiDataValidatingParserInterface;
37
use Limoncello\Flute\Contracts\Validation\JsonApiParserFactoryInterface;
38
use Limoncello\Flute\Contracts\Validation\JsonApiQueryRulesInterface;
39
use Limoncello\Flute\Contracts\Validation\JsonApiQueryValidatingParserInterface;
40
use Limoncello\Flute\Http\Responses;
41
use Limoncello\Flute\Package\FluteSettings as S;
42
use Limoncello\Flute\Resources\Messages\En\Generic;
43
use Limoncello\Flute\Validation\JsonApi\Rules\DefaultQueryValidationRules;
44
use Neomerx\JsonApi\Contracts\Document\DocumentInterface as DI;
45
use Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface;
46
use Neomerx\JsonApi\Contracts\Http\Headers\MediaTypeInterface;
47
use Neomerx\JsonApi\Contracts\Http\ResponsesInterface;
48
use Neomerx\JsonApi\Encoder\Parameters\EncodingParameters;
49
use Neomerx\JsonApi\Exceptions\JsonApiException;
50
use Neomerx\JsonApi\Http\Headers\MediaType;
51
use Psr\Container\ContainerExceptionInterface;
52
use Psr\Container\ContainerInterface;
53
use Psr\Container\NotFoundExceptionInterface;
54
use Psr\Http\Message\ResponseInterface;
55
use Psr\Http\Message\UriInterface;
56
57
/**
58
 * @package Limoncello\Flute
59
 */
60
trait DefaultControllerMethodsTrait
61
{
62
    /** @noinspection PhpTooManyParametersInspection
63
     * @param array                                 $queryParams
64
     * @param UriInterface                          $requestUri
65
     * @param JsonApiQueryValidatingParserInterface $queryParser
66
     * @param ParametersMapperInterface             $mapper
67
     * @param CrudInterface                         $crud
68
     * @param SettingsProviderInterface             $provider
69
     * @param JsonSchemasInterface                  $jsonSchemas
70
     * @param EncoderInterface                      $encoder
71
     *
72
     * @return ResponseInterface
73
     */
74 12
    protected static function defaultIndexHandler(
75
        array $queryParams,
76
        UriInterface $requestUri,
77
        JsonApiQueryValidatingParserInterface $queryParser,
78
        ParametersMapperInterface $mapper,
79
        CrudInterface $crud,
80
        SettingsProviderInterface $provider,
81
        JsonSchemasInterface $jsonSchemas,
82
        EncoderInterface $encoder
83
    ): ResponseInterface {
84 12
        $queryParser->parse($queryParams);
85
86 11
        $models = $mapper->applyQueryParameters($queryParser, $crud)->index();
87
88 10
        $encParams = self::defaultCreateEncodingParameters($queryParser);
89 10
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
90 10
        $response  = ($models->getData()) === null ?
91 10
            $responses->getCodeResponse(404) : $responses->getContentResponse($models);
92
93 10
        return $response;
94
    }
95
96
    /** @noinspection PhpTooManyParametersInspection
97
     * @param string                                $index
98
     * @param array                                 $queryParams
99
     * @param UriInterface                          $requestUri
100
     * @param JsonApiQueryValidatingParserInterface $queryParser
101
     * @param ParametersMapperInterface             $mapper
102
     * @param CrudInterface                         $crud
103
     * @param SettingsProviderInterface             $provider
104
     * @param JsonSchemasInterface                  $jsonSchemas
105
     * @param EncoderInterface                      $encoder
106
     *
107
     * @return ResponseInterface
108
     */
109 1
    protected static function defaultReadHandler(
110
        string $index,
111
        array $queryParams,
112
        UriInterface $requestUri,
113
        JsonApiQueryValidatingParserInterface $queryParser,
114
        ParametersMapperInterface $mapper,
115
        CrudInterface $crud,
116
        SettingsProviderInterface $provider,
117
        JsonSchemasInterface $jsonSchemas,
118
        EncoderInterface $encoder
119
    ): ResponseInterface {
120 1
        $queryParser->parse($queryParams);
121
122 1
        $model = $mapper->applyQueryParameters($queryParser, $crud)->read($index);
123 1
        assert(!($model instanceof PaginatedDataInterface));
124
125 1
        $encParams = self::defaultCreateEncodingParameters($queryParser);
126 1
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
127 1
        $response  = $model === null ?
128 1
            $responses->getCodeResponse(404) : $responses->getContentResponse($model);
129
130 1
        return $response;
131
    }
132
133
    /** @noinspection PhpTooManyParametersInspection
134
     * @param Closure                               $apiHandler
135
     * @param array                                 $queryParams
136
     * @param UriInterface                          $requestUri
137
     * @param JsonApiQueryValidatingParserInterface $queryParser
138
     * @param ParametersMapperInterface             $mapper
139
     * @param CrudInterface                         $crud
140
     * @param SettingsProviderInterface             $provider
141
     * @param JsonSchemasInterface                  $jsonSchemas
142
     * @param EncoderInterface                      $encoder
143
     *
144
     * @return ResponseInterface
145
     */
146 2
    protected static function defaultReadRelationshipWithClosureHandler(
147
        Closure $apiHandler,
148
        array $queryParams,
149
        UriInterface $requestUri,
150
        JsonApiQueryValidatingParserInterface $queryParser,
151
        ParametersMapperInterface $mapper,
152
        CrudInterface $crud,
153
        SettingsProviderInterface $provider,
154
        JsonSchemasInterface $jsonSchemas,
155
        EncoderInterface $encoder
156
    ): ResponseInterface {
157 2
        $queryParser->parse($queryParams);
158 2
        $mapper->applyQueryParameters($queryParser, $crud);
159
160 2
        $relData = call_user_func($apiHandler);
161
162 2
        $encParams = self::defaultCreateEncodingParameters($queryParser);
163 2
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
164
165 2
        $noData   = $relData === null || ($relData instanceof PaginatedDataInterface && $relData->getData() === null);
166 2
        $response = $noData === true ? $responses->getCodeResponse(404) : $responses->getContentResponse($relData);
167
168 2
        return $response;
169
    }
170
171
    /** @noinspection PhpTooManyParametersInspection
172
     * @param Closure                               $apiHandler
173
     * @param array                                 $queryParams
174
     * @param UriInterface                          $requestUri
175
     * @param JsonApiQueryValidatingParserInterface $queryParser
176
     * @param ParametersMapperInterface             $mapper
177
     * @param CrudInterface                         $crud
178
     * @param SettingsProviderInterface             $provider
179
     * @param JsonSchemasInterface                  $jsonSchemas
180
     * @param EncoderInterface                      $encoder
181
     *
182
     * @return ResponseInterface
183
     */
184 1
    protected static function defaultReadRelationshipIdentifiersWithClosureHandler(
185
        Closure $apiHandler,
186
        array $queryParams,
187
        UriInterface $requestUri,
188
        JsonApiQueryValidatingParserInterface $queryParser,
189
        ParametersMapperInterface $mapper,
190
        CrudInterface $crud,
191
        SettingsProviderInterface $provider,
192
        JsonSchemasInterface $jsonSchemas,
193
        EncoderInterface $encoder
194
    ): ResponseInterface {
195 1
        $queryParser->parse($queryParams);
196 1
        $mapper->applyQueryParameters($queryParser, $crud);
197
198 1
        $relData = call_user_func($apiHandler);
199
200 1
        $encParams = self::defaultCreateEncodingParameters($queryParser);
201 1
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
202
203 1
        $noData   = $relData === null || ($relData instanceof PaginatedDataInterface && $relData->getData() === null);
204 1
        $response = $noData === true ? $responses->getCodeResponse(404) : $responses->getIdentifiersResponse($relData);
205
206 1
        return $response;
207
    }
208
209
    /** @noinspection PhpTooManyParametersInspection
210
     * @param UriInterface                         $requestUri
211
     * @param string                               $requestBody
212
     * @param string                               $schemaClass
213
     * @param ModelSchemaInfoInterface             $schemaInfo
214
     * @param JsonApiDataValidatingParserInterface $validator
215
     * @param CrudInterface                        $crud
216
     * @param SettingsProviderInterface            $provider
217
     * @param JsonSchemasInterface                 $jsonSchemas
218
     * @param EncoderInterface                     $encoder
219
     * @param FactoryInterface                     $errorFactory
220
     * @param FormatterFactoryInterface            $formatterFactory
221
     *
222
     * @return ResponseInterface
223
     *
224
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
225
     */
226 1
    protected static function defaultCreateHandler(
227
        UriInterface $requestUri,
228
        string $requestBody,
229
        string $schemaClass,
230
        ModelSchemaInfoInterface $schemaInfo,
231
        JsonApiDataValidatingParserInterface $validator,
232
        CrudInterface $crud,
233
        SettingsProviderInterface $provider,
234
        JsonSchemasInterface $jsonSchemas,
235
        EncoderInterface $encoder,
236
        FactoryInterface $errorFactory,
237
        FormatterFactoryInterface $formatterFactory
238
    ): ResponseInterface {
239
        // some of the users want to reuse default `create` but have a custom part for responses
240
        // to meet this requirement it is split into two parts.
241 1
        $index = static::defaultCreate(
242 1
            $requestBody,
243 1
            $schemaClass,
244 1
            $schemaInfo,
245 1
            $validator,
246 1
            $crud,
247 1
            $errorFactory,
248 1
            $formatterFactory
249
        );
250
251 1
        return static::defaultCreateResponse($index, $requestUri, $crud, $provider, $jsonSchemas, $encoder);
252
    }
253
254
    /**
255
     * @param string                               $requestBody
256
     * @param string                               $schemaClass
257
     * @param ModelSchemaInfoInterface             $schemaInfo
258
     * @param JsonApiDataValidatingParserInterface $validator
259
     * @param CrudInterface                        $crud
260
     * @param FactoryInterface                     $errorFactory
261
     * @param FormatterFactoryInterface            $formatterFactory
262
     *
263
     * @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...
264
     */
265 1
    protected static function defaultCreate(
266
        string $requestBody,
267
        string $schemaClass,
268
        ModelSchemaInfoInterface $schemaInfo,
269
        JsonApiDataValidatingParserInterface $validator,
270
        CrudInterface $crud,
271
        FactoryInterface $errorFactory,
272
        FormatterFactoryInterface $formatterFactory
273
    ): string {
274 1
        $jsonData = static::readJsonFromRequest($requestBody, $errorFactory, $formatterFactory);
275 1
        $captures = $validator->assert($jsonData)->getJsonApiCaptures();
276
277 1
        list ($index, $attributes, $toMany) = static::mapSchemaDataToModelData($captures, $schemaClass, $schemaInfo);
278
279 1
        $index = $crud->create($index, $attributes, $toMany);
280
281 1
        return $index;
282
    }
283
284
    /**
285
     * @param string                    $index
286
     * @param UriInterface              $requestUri
287
     * @param CrudInterface             $crud
288
     * @param SettingsProviderInterface $provider
289
     * @param JsonSchemasInterface      $jsonSchemas
290
     * @param EncoderInterface          $encoder
291
     *
292
     * @return ResponseInterface
293
     */
294 1
    protected static function defaultCreateResponse(
295
        string $index,
296
        UriInterface $requestUri,
297
        CrudInterface $crud,
298
        SettingsProviderInterface $provider,
299
        JsonSchemasInterface $jsonSchemas,
300
        EncoderInterface $encoder
301
    ): ResponseInterface {
302 1
        $model = $crud->read($index);
303 1
        assert($model !== null && !($model instanceof PaginatedDataInterface));
304
305 1
        $encParams = null;
306 1
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
307 1
        $response  = $responses->getCreatedResponse($model);
308
309 1
        return $response;
310
    }
311
312
    /** @noinspection PhpTooManyParametersInspection
313
     * @param string                               $index
314
     * @param UriInterface                         $requestUri
315
     * @param string                               $requestBody
316
     * @param string                               $schemaClass
317
     * @param ModelSchemaInfoInterface             $schemaInfo
318
     * @param JsonApiDataValidatingParserInterface $validator
319
     * @param CrudInterface                        $crud
320
     * @param SettingsProviderInterface            $provider
321
     * @param JsonSchemasInterface                 $jsonSchemas
322
     * @param EncoderInterface                     $encoder
323
     * @param FactoryInterface                     $errorFactory
324
     * @param FormatterFactoryInterface            $formatterFactory
325
     * @param string                               $messagesNamespace
326
     * @param string                               $errorMessage
327
     *
328
     * @return ResponseInterface
329
     *
330
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
331
     */
332 6
    protected static function defaultUpdateHandler(
333
        string $index,
334
        UriInterface $requestUri,
335
        string $requestBody,
336
        string $schemaClass,
337
        ModelSchemaInfoInterface $schemaInfo,
338
        JsonApiDataValidatingParserInterface $validator,
339
        CrudInterface $crud,
340
        SettingsProviderInterface $provider,
341
        JsonSchemasInterface $jsonSchemas,
342
        EncoderInterface $encoder,
343
        FactoryInterface $errorFactory,
344
        FormatterFactoryInterface $formatterFactory,
345
        string $messagesNamespace = S::GENERIC_NAMESPACE,
346
        string $errorMessage = Generic::MSG_ERR_INVALID_ELEMENT
347
    ): ResponseInterface {
348
        // some of the users want to reuse default `update` but have a custom part for responses
349
        // to meet this requirement it is split into two parts.
350 6
        $updated = static::defaultUpdate(
351 6
            $index,
352 6
            $requestBody,
353 6
            $schemaClass,
354 6
            $schemaInfo,
355 6
            $validator,
356 6
            $crud,
357 6
            $errorFactory,
358 6
            $formatterFactory,
359 6
            $messagesNamespace,
360 6
            $errorMessage
361
        );
362
363 3
        return static::defaultUpdateResponse($updated, $index, $requestUri, $crud, $provider, $jsonSchemas, $encoder);
364
    }
365
366
    /** @noinspection PhpTooManyParametersInspection
367
     * @param string                               $index
368
     * @param string                               $requestBody
369
     * @param string                               $schemaClass
370
     * @param ModelSchemaInfoInterface             $schemaInfo
371
     * @param JsonApiDataValidatingParserInterface $validator
372
     * @param CrudInterface                        $crud
373
     * @param FactoryInterface                     $errorFactory
374
     * @param FormatterFactoryInterface            $formatterFactory
375
     * @param string                               $messagesNamespace
376
     * @param string                               $errorMessage
377
     *
378
     * @return int
379
     *
380
     * @SuppressWarnings(PHPMD.ElseExpression)
381
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
382
     */
383 6
    protected static function defaultUpdate(
384
        string $index,
385
        string $requestBody,
386
        string $schemaClass,
387
        ModelSchemaInfoInterface $schemaInfo,
388
        JsonApiDataValidatingParserInterface $validator,
389
        CrudInterface $crud,
390
        FactoryInterface $errorFactory,
391
        FormatterFactoryInterface $formatterFactory,
392
        string $messagesNamespace = S::GENERIC_NAMESPACE,
393
        string $errorMessage = Generic::MSG_ERR_INVALID_ELEMENT
394
    ): int {
395 6
        $jsonData = static::readJsonFromRequest($requestBody, $errorFactory, $formatterFactory);
396
        // check that index in data and URL are identical
397 5
        $indexValue = $jsonData[DI::KEYWORD_DATA][DI::KEYWORD_ID] ?? null;
398 5
        if (empty($indexValue) === false) {
399 4
            if ($indexValue !== $index) {
400 1
                $errors    = $errorFactory->createErrorCollection();
401 1
                $formatter = $formatterFactory->createFormatter($messagesNamespace);
402 1
                $errors->addDataIdError($formatter->formatMessage($errorMessage));
403
404 4
                throw new JsonApiException($errors);
405
            }
406
        } else {
407
            // put the index to data for our convenience
408 1
            $jsonData[DI::KEYWORD_DATA][DI::KEYWORD_ID] = $index;
409
        }
410
        // validate the data
411 4
        $captures = $validator->assert($jsonData)->getJsonApiCaptures();
412
413 3
        list ($index, $attributes, $toMany) = static::mapSchemaDataToModelData($captures, $schemaClass, $schemaInfo);
414
415 3
        $updated = $crud->update($index, $attributes, $toMany);
416
417 3
        return $updated;
418
    }
419
420
    /**
421
     * @param int                       $updated
422
     * @param string                    $index
423
     * @param UriInterface              $requestUri
424
     * @param CrudInterface             $crud
425
     * @param SettingsProviderInterface $provider
426
     * @param JsonSchemasInterface      $jsonSchemas
427
     * @param EncoderInterface          $encoder
428
     *
429
     * @return ResponseInterface
430
     *
431
     * @SuppressWarnings(PHPMD.ElseExpression)
432
     */
433 3
    protected static function defaultUpdateResponse(
434
        int $updated,
435
        string $index,
436
        UriInterface $requestUri,
437
        CrudInterface $crud,
438
        SettingsProviderInterface $provider,
439
        JsonSchemasInterface $jsonSchemas,
440
        EncoderInterface $encoder
441
    ): ResponseInterface {
442 3
        $encParams = null;
443 3
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
444 3
        if ($updated > 0 && ($model = $crud->read($index)) !== null) {
445 2
            assert(!($model instanceof PaginatedDataInterface));
446 2
            $response = $responses->getContentResponse($model);
447
        } else {
448 1
            $response = $responses->getCodeResponse(404);
449
        }
450
451 3
        return $response;
452
    }
453
454
    /** @noinspection PhpTooManyParametersInspection
455
     * @param string                               $parentIndex
456
     * @param string                               $modelRelName
457
     * @param string                               $childIndex
458
     * @param UriInterface                         $requestUri
459
     * @param string                               $requestBody
460
     * @param string                               $childSchemaClass
461
     * @param ModelSchemaInfoInterface             $schemaInfo
462
     * @param JsonApiDataValidatingParserInterface $childValidator
463
     * @param CrudInterface                        $parentCrud
464
     * @param CrudInterface                        $childCrud
465
     * @param SettingsProviderInterface            $provider
466
     * @param JsonSchemasInterface                 $jsonSchemas
467
     * @param EncoderInterface                     $encoder
468
     * @param FactoryInterface                     $errorFactory
469
     * @param FormatterFactoryInterface            $formatterFactory
470
     * @param string                               $messagesNamespace
471
     * @param string                               $errorMessage
472
     *
473
     * @return ResponseInterface
474
     *
475
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
476
     */
477 2
    protected static function defaultUpdateInRelationshipHandler(
478
        string $parentIndex,
479
        string $modelRelName,
480
        string $childIndex,
481
        UriInterface $requestUri,
482
        string $requestBody,
483
        string $childSchemaClass,
484
        ModelSchemaInfoInterface $schemaInfo,
485
        JsonApiDataValidatingParserInterface $childValidator,
486
        CrudInterface $parentCrud,
487
        CrudInterface $childCrud,
488
        SettingsProviderInterface $provider,
489
        JsonSchemasInterface $jsonSchemas,
490
        EncoderInterface $encoder,
491
        FactoryInterface $errorFactory,
492
        FormatterFactoryInterface $formatterFactory,
493
        string $messagesNamespace = S::GENERIC_NAMESPACE,
494
        string $errorMessage = Generic::MSG_ERR_INVALID_ELEMENT
495
    ): ResponseInterface {
496 2
        if ($parentCrud->hasInRelationship($parentIndex, $modelRelName, $childIndex) === true) {
497 1
            return static::defaultUpdateHandler(
498 1
                $childIndex,
499 1
                $requestUri,
500 1
                $requestBody,
501 1
                $childSchemaClass,
502 1
                $schemaInfo,
503 1
                $childValidator,
504 1
                $childCrud,
505 1
                $provider,
506 1
                $jsonSchemas,
507 1
                $encoder,
508 1
                $errorFactory,
509 1
                $formatterFactory,
510 1
                $messagesNamespace,
511 1
                $errorMessage
512
            );
513
        }
514
515 1
        $encParams = null;
516 1
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
517
518 1
        return $responses->getCodeResponse(404);
519
    }
520
521
    /**
522
     * @param string                    $index
523
     * @param UriInterface              $requestUri
524
     * @param CrudInterface             $crud
525
     * @param SettingsProviderInterface $provider
526
     * @param JsonSchemasInterface      $jsonSchemas
527
     * @param EncoderInterface          $encoder
528
     *
529
     * @return ResponseInterface
530
     */
531 2
    protected static function defaultDeleteHandler(
532
        string $index,
533
        UriInterface $requestUri,
534
        CrudInterface $crud,
535
        SettingsProviderInterface $provider,
536
        JsonSchemasInterface $jsonSchemas,
537
        EncoderInterface $encoder
538
    ): ResponseInterface {
539 2
        $crud->remove($index);
540
541 2
        $encParams = null;
542 2
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
543 2
        $response  = $responses->getCodeResponse(204);
544
545 2
        return $response;
546
    }
547
548
    /** @noinspection PhpTooManyParametersInspection
549
     * @param string                    $parentIndex
550
     * @param string                    $modelRelName
551
     * @param string                    $childIndex
552
     * @param UriInterface              $requestUri
553
     * @param CrudInterface             $parentCrud
554
     * @param CrudInterface             $childCrud
555
     * @param SettingsProviderInterface $provider
556
     * @param JsonSchemasInterface      $jsonSchemas
557
     * @param EncoderInterface          $encoder
558
     *
559
     * @return ResponseInterface
560
     */
561 1
    protected static function defaultDeleteInRelationshipHandler(
562
        string $parentIndex,
563
        string $modelRelName,
564
        string $childIndex,
565
        UriInterface $requestUri,
566
        CrudInterface $parentCrud,
567
        CrudInterface $childCrud,
568
        SettingsProviderInterface $provider,
569
        JsonSchemasInterface $jsonSchemas,
570
        EncoderInterface $encoder
571
    ): ResponseInterface {
572 1
        if ($parentCrud->hasInRelationship($parentIndex, $modelRelName, $childIndex) === true) {
573 1
            return static::defaultDeleteHandler(
574 1
                $childIndex,
575 1
                $requestUri,
576 1
                $childCrud,
577 1
                $provider,
578 1
                $jsonSchemas,
579 1
                $encoder
580
            );
581
        }
582
583 1
        $encParams = null;
584 1
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemas, $encoder, $encParams);
585
586 1
        return $responses->getCodeResponse(404);
587
    }
588
589
    /**
590
     * @param ContainerInterface $container
591
     * @param string             $rulesClass
592
     *
593
     * @return JsonApiQueryValidatingParserInterface
594
     *
595
     * @throws ContainerExceptionInterface
596
     * @throws NotFoundExceptionInterface
597
     */
598 16
    protected static function defaultCreateQueryParser(
599
        ContainerInterface $container,
600
        string $rulesClass = DefaultQueryValidationRules::class
601
    ): JsonApiQueryValidatingParserInterface {
602 16
        static::assertClassImplements($rulesClass, JsonApiQueryRulesInterface::class);
603
604
        /** @var JsonApiParserFactoryInterface $factory */
605 16
        $factory   = $container->get(JsonApiParserFactoryInterface::class);
606 16
        $validator = $factory->createQueryParser($rulesClass);
607
608 16
        return $validator;
609
    }
610
611
    /**
612
     * @param ContainerInterface $container
613
     * @param string             $rulesClass
614
     *
615
     * @return JsonApiDataValidatingParserInterface
616
     *
617
     * @throws ContainerExceptionInterface
618
     * @throws NotFoundExceptionInterface
619
     */
620 8
    protected static function defaultCreateDataParser(
621
        ContainerInterface $container,
622
        string $rulesClass
623
    ): JsonApiDataValidatingParserInterface {
624 8
        static::assertClassImplements($rulesClass, JsonApiDataRulesInterface::class);
625
626
        /** @var JsonApiParserFactoryInterface $factory */
627 8
        $factory   = $container->get(JsonApiParserFactoryInterface::class);
628 8
        $validator = $factory->createDataParser($rulesClass);
629
630 8
        return $validator;
631
    }
632
633
    /**
634
     * @param ContainerInterface $container
635
     * @param string             $rulesClass
636
     *
637
     * @return FormValidatorInterface
638
     *
639
     * @throws ContainerExceptionInterface
640
     * @throws NotFoundExceptionInterface
641
     */
642 1
    protected static function defaultCreateFormValidator(
643
        ContainerInterface $container,
644
        string $rulesClass
645
    ): FormValidatorInterface {
646 1
        static::assertClassImplements($rulesClass, FormRulesInterface::class);
647
648
        /** @var FormValidatorFactoryInterface $factory */
649 1
        $factory   = $container->get(FormValidatorFactoryInterface::class);
650 1
        $validator = $factory->createValidator($rulesClass);
651
652 1
        return $validator;
653
    }
654
655
    /**
656
     * @param ContainerInterface $container
657
     * @param string             $schemaClass
658
     *
659
     * @return ParametersMapperInterface
660
     *
661
     * @throws ContainerExceptionInterface
662
     * @throws NotFoundExceptionInterface
663
     */
664 16
    protected static function defaultCreateParameterMapper(
665
        ContainerInterface $container,
666
        string $schemaClass
667
    ): ParametersMapperInterface {
668 16
        static::assertClassImplements($schemaClass, SchemaInterface::class);
669
670
        /** @var SchemaInterface $schemaClass */
671 16
        $jsonResourceType = $schemaClass::TYPE;
672
673
        /** @var ParametersMapperInterface $mapper */
674 16
        $mapper = $container->get(ParametersMapperInterface::class);
675 16
        $mapper->selectRootSchemaByResourceType($jsonResourceType);
676
677 16
        return $mapper;
678
    }
679
680
    /**
681
     * @param JsonApiQueryValidatingParserInterface $queryParser
682
     *
683
     * @return EncodingParametersInterface
684
     */
685 14
    protected static function defaultCreateEncodingParameters(
686
        JsonApiQueryValidatingParserInterface $queryParser
687
    ): EncodingParametersInterface {
688 14
        return new EncodingParameters(
689 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...
690 14
            $queryParser->hasFields() === true ? $queryParser->getFields() : null
691
        );
692
    }
693
694
    /**
695
     * @param ContainerInterface $container
696
     * @param string|null        $class
697
     *
698
     * @return CrudInterface
699
     *
700
     * @throws ContainerExceptionInterface
701
     * @throws NotFoundExceptionInterface
702
     */
703 26
    protected static function defaultCreateApi(ContainerInterface $container, string $class): CrudInterface
704
    {
705 26
        static::assertClassImplements($class, CrudInterface::class);
706
707
        /** @var FactoryInterface $factory */
708 26
        $factory = $container->get(FactoryInterface::class);
709 26
        $api     = $factory->createApi($class);
710
711 26
        return $api;
712
    }
713
714
    /**
715
     * @param UriInterface                     $requestUri
716
     * @param SettingsProviderInterface        $provider
717
     * @param JsonSchemasInterface             $jsonSchemas
718
     * @param EncoderInterface                 $encoder
719
     * @param EncodingParametersInterface|null $parameters
720
     *
721
     * @return ResponsesInterface
722
     */
723 21
    protected static function defaultCreateResponses(
724
        UriInterface $requestUri,
725
        SettingsProviderInterface $provider,
726
        JsonSchemasInterface $jsonSchemas,
727
        EncoderInterface $encoder,
728
        ?EncodingParametersInterface $parameters
729
    ): ResponsesInterface {
730 21
        $encoder->forOriginalUri($requestUri);
731 21
        $settings  = $provider->get(S::class);
732 21
        $responses = new Responses(
733 21
            new MediaType(MediaTypeInterface::JSON_API_TYPE, MediaTypeInterface::JSON_API_SUB_TYPE),
734 21
            $encoder,
735 21
            $jsonSchemas,
736 21
            $parameters,
737 21
            $settings[S::KEY_URI_PREFIX],
738 21
            $settings[S::KEY_META]
739
        );
740
741 21
        return $responses;
742
    }
743
744
    /**
745
     * Developers can override the method in order to add/remove some data for `create`/`update` inputs.
746
     *
747
     * @param string                    $requestBody
748
     * @param FactoryInterface          $errorFactory
749
     * @param FormatterFactoryInterface $formatterFactory
750
     * @param string                    $messagesNamespace
751
     * @param string                    $errorMessage
752
     *
753
     * @return array
754
     */
755 7
    protected static function readJsonFromRequest(
756
        string $requestBody,
757
        FactoryInterface $errorFactory,
758
        FormatterFactoryInterface $formatterFactory,
759
        string $messagesNamespace = S::GENERIC_NAMESPACE,
760
        string $errorMessage = Generic::MSG_ERR_INVALID_ELEMENT
761
    ): array {
762 7
        if (empty($requestBody) === true || ($json = json_decode($requestBody, true)) === null) {
763 1
            $formatter = $formatterFactory->createFormatter($messagesNamespace);
764 1
            $errors    = $errorFactory->createErrorCollection();
765 1
            $errors->addDataError($formatter->formatMessage($errorMessage));
766
767 1
            throw new JsonApiException($errors);
768
        }
769
770 6
        return $json;
771
    }
772
773
    /**
774
     * Developers can override the method in order to use custom data mapping from a Schema to Model.
775
     *
776
     * @param array                    $captures
777
     * @param string                   $schemaClass
778
     * @param ModelSchemaInfoInterface $schemaInfo
779
     *
780
     * @return array
781
     */
782 4
    protected static function mapSchemaDataToModelData(
783
        array $captures,
784
        string $schemaClass,
785
        ModelSchemaInfoInterface $schemaInfo
786
    ): array {
787 4
        static::assertClassImplements($schemaClass, SchemaInterface::class);
788
789
        /** @var SchemaInterface $schemaClass */
790 4
        static::assertClassImplements($modelClass = $schemaClass::MODEL, ModelInterface::class);
791
        /** @var ModelInterface $modelClass */
792
793 4
        $index         = null;
794 4
        $fields        = [];
795 4
        $toManyIndexes = [];
796 4
        foreach ($captures as $name => $value) {
797 4
            assert(is_string($name) === true);
798 4
            if ($name === DI::KEYWORD_ID) {
799 4
                $index = $value;
800 4
            } elseif ($schemaClass::hasAttributeMapping($name) === true) {
801 4
                $fieldName          = $schemaClass::getAttributeMapping($name);
802 4
                $fields[$fieldName] = $value;
803 4
            } elseif ($schemaClass::hasRelationshipMapping($name) === true) {
804 2
                $modelRelName = $schemaClass::getRelationshipMapping($name);
805 2
                $relType      = $schemaInfo->getRelationshipType($modelClass, $modelRelName);
806 2
                if ($relType === RelationshipTypes::BELONGS_TO) {
807 2
                    $fkName          = $schemaInfo->getForeignKey($modelClass, $modelRelName);
808 2
                    $fields[$fkName] = $value;
809 2
                } elseif ($relType === RelationshipTypes::BELONGS_TO_MANY) {
810 4
                    $toManyIndexes[$modelRelName] = $value;
811
                }
812
            }
813
        }
814
815 4
        $result = [$index, $fields, $toManyIndexes];
816
817 4
        return $result;
818
    }
819
820
    /**
821
     * @param null|string $value
822
     *
823
     * @return void
824
     */
825 26
    private static function assertClassValueDefined(?string $value): void
826
    {
827 26
        assert(empty($value) === false, 'Value should be defined in `' . static::class . '`.');
828
    }
829
830
    /**
831
     * @param string $class
832
     * @param string $interface
833
     *
834
     * @return void
835
     */
836 27
    private static function assertClassImplements(string $class, string $interface): void
837
    {
838 27
        assert(
839 27
            array_key_exists($interface, class_implements($class)) === true,
840 27
            "Class `$class` should implement `" . $interface . '` interface.'
841
        );
842
    }
843
}
844