Completed
Push — develop ( 5c2193...01cb9f )
by Neomerx
02:08
created

defaultReadHandler()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 3.1852

Importance

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

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\ModelSchemeInfoInterface;
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\JsonSchemesInterface;
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\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 JsonSchemesInterface                  $jsonSchemes
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
        JsonSchemesInterface $jsonSchemes,
79
        EncoderInterface $encoder
80
    ): ResponseInterface {
81 12
        $queryParser->parse($queryParams);
82
83 11
        $models = $mapper->applyQueryParameters($queryParser, $crud)->index();
84
85
        $encParams = self::defaultCreateEncodingParameters($queryParser);
86
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemes, $encoder, $encParams);
87
        $response  = ($models->getData()) === null ?
88
            $responses->getCodeResponse(404) : $responses->getContentResponse($models);
89
90
        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 JsonSchemesInterface                  $jsonSchemes
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
        JsonSchemesInterface $jsonSchemes,
115
        EncoderInterface $encoder
116
    ): ResponseInterface {
117 1
        $queryParser->parse($queryParams);
118
119 1
        $model = $mapper->applyQueryParameters($queryParser, $crud)->read($index);
120
        assert(!($model instanceof PaginatedDataInterface));
121
122
        $encParams = self::defaultCreateEncodingParameters($queryParser);
123
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemes, $encoder, $encParams);
124
        $response  = $model === null ?
125
            $responses->getCodeResponse(404) : $responses->getContentResponse($model);
126
127
        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 JsonSchemesInterface                  $jsonSchemes
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
        JsonSchemesInterface $jsonSchemes,
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
        $encParams = self::defaultCreateEncodingParameters($queryParser);
160
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemes, $encoder, $encParams);
161
162
        $noData   = $relData === null || ($relData instanceof PaginatedDataInterface && $relData->getData() === null);
163
        $response = $noData === true ? $responses->getCodeResponse(404) : $responses->getContentResponse($relData);
164
165
        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 JsonSchemesInterface                  $jsonSchemes
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
        JsonSchemesInterface $jsonSchemes,
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
        $encParams = self::defaultCreateEncodingParameters($queryParser);
198
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemes, $encoder, $encParams);
199
200
        $noData   = $relData === null || ($relData instanceof PaginatedDataInterface && $relData->getData() === null);
201
        $response = $noData === true ? $responses->getCodeResponse(404) : $responses->getIdentifiersResponse($relData);
202
203
        return $response;
204
    }
205
206
    /** @noinspection PhpTooManyParametersInspection
207
     * @param UriInterface                         $requestUri
208
     * @param string                               $requestBody
209
     * @param string                               $schemeClass
210
     * @param ModelSchemeInfoInterface             $schemeInfo
211
     * @param JsonApiDataValidatingParserInterface $validator
212
     * @param CrudInterface                        $crud
213
     * @param SettingsProviderInterface            $provider
214
     * @param JsonSchemesInterface                 $jsonSchemes
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 $schemeClass,
227
        ModelSchemeInfoInterface $schemeInfo,
228
        JsonApiDataValidatingParserInterface $validator,
229
        CrudInterface $crud,
230
        SettingsProviderInterface $provider,
231
        JsonSchemesInterface $jsonSchemes,
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
            $schemeClass,
241 1
            $schemeInfo,
242 1
            $validator,
243 1
            $crud,
244 1
            $errorFactory,
245 1
            $formatterFactory
246
        );
247
248 1
        return static::defaultCreateResponse($index, $requestUri, $crud, $provider, $jsonSchemes, $encoder);
249
    }
250
251
    /**
252
     * @param string                               $requestBody
253
     * @param string                               $schemeClass
254
     * @param ModelSchemeInfoInterface             $schemeInfo
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 $schemeClass,
265
        ModelSchemeInfoInterface $schemeInfo,
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::mapSchemeDataToModelData($captures, $schemeClass, $schemeInfo);
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 JsonSchemesInterface      $jsonSchemes
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
        JsonSchemesInterface $jsonSchemes,
297
        EncoderInterface $encoder
298
    ): ResponseInterface {
299 1
        $model = $crud->read($index);
300
        assert($model !== null && !($model instanceof PaginatedDataInterface));
301
302
        $encParams = null;
303
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemes, $encoder, $encParams);
304
        $response  = $responses->getCreatedResponse($model);
305
306
        return $response;
307
    }
308
309
    /** @noinspection PhpTooManyParametersInspection
310
     * @param string                               $index
311
     * @param UriInterface                         $requestUri
312
     * @param string                               $requestBody
313
     * @param string                               $schemeClass
314
     * @param ModelSchemeInfoInterface             $schemeInfo
315
     * @param JsonApiDataValidatingParserInterface $validator
316
     * @param CrudInterface                        $crud
317
     * @param SettingsProviderInterface            $provider
318
     * @param JsonSchemesInterface                 $jsonSchemes
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 5
    protected static function defaultUpdateHandler(
330
        string $index,
331
        UriInterface $requestUri,
332
        string $requestBody,
333
        string $schemeClass,
334
        ModelSchemeInfoInterface $schemeInfo,
335
        JsonApiDataValidatingParserInterface $validator,
336
        CrudInterface $crud,
337
        SettingsProviderInterface $provider,
338
        JsonSchemesInterface $jsonSchemes,
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 5
        $updated = static::defaultUpdate(
348 5
            $index,
349 5
            $requestBody,
350 5
            $schemeClass,
351 5
            $schemeInfo,
352 5
            $validator,
353 5
            $crud,
354 5
            $errorFactory,
355 5
            $formatterFactory,
356 5
            $messagesNamespace,
357 5
            $errorMessage
358
        );
359
360 2
        return static::defaultUpdateResponse($updated, $index, $requestUri, $crud, $provider, $jsonSchemes, $encoder);
361
    }
362
363
    /** @noinspection PhpTooManyParametersInspection
364
     * @param string                               $index
365
     * @param string                               $requestBody
366
     * @param string                               $schemeClass
367
     * @param ModelSchemeInfoInterface             $schemeInfo
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 5
    protected static function defaultUpdate(
381
        string $index,
382
        string $requestBody,
383
        string $schemeClass,
384
        ModelSchemeInfoInterface $schemeInfo,
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 5
        $jsonData = static::readJsonFromRequest($requestBody, $errorFactory, $formatterFactory);
393
        // check that index in data and URL are identical
394 4
        $indexValue = $jsonData[DI::KEYWORD_DATA][DI::KEYWORD_ID] ?? null;
395 4
        if (empty($indexValue) === false) {
396 3
            if ($indexValue !== $index) {
397 1
                $errors    = $errorFactory->createErrorCollection();
398 1
                $formatter = $formatterFactory->createFormatter($messagesNamespace);
399 1
                $errors->addDataIdError($formatter->formatMessage($errorMessage));
400
401 3
                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 3
        $captures = $validator->assert($jsonData)->getJsonApiCaptures();
409
410 2
        list ($index, $attributes, $toMany) = static::mapSchemeDataToModelData($captures, $schemeClass, $schemeInfo);
411
412 2
        $updated = $crud->update($index, $attributes, $toMany);
413
414 2
        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 JsonSchemesInterface      $jsonSchemes
424
     * @param EncoderInterface          $encoder
425
     *
426
     * @return ResponseInterface
427
     *
428
     * @SuppressWarnings(PHPMD.ElseExpression)
429
     */
430 2
    protected static function defaultUpdateResponse(
431
        int $updated,
432
        string $index,
433
        UriInterface $requestUri,
434
        CrudInterface $crud,
435
        SettingsProviderInterface $provider,
436
        JsonSchemesInterface $jsonSchemes,
437
        EncoderInterface $encoder
438
    ): ResponseInterface {
439 2
        $encParams = null;
440 2
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemes, $encoder, $encParams);
441 2
        if ($updated > 0) {
442 1
            $model = $crud->read($index);
443
            assert($model !== null && !($model instanceof PaginatedDataInterface));
444
            $response = $responses->getContentResponse($model);
445
        } else {
446 1
            $response = $responses->getCodeResponse(404);
447
        }
448
449 1
        return $response;
450
    }
451
452
    /** @noinspection PhpTooManyParametersInspection
453
     * @param string                               $parentIndex
454
     * @param string                               $modelRelName
455
     * @param string                               $childIndex
456
     * @param UriInterface                         $requestUri
457
     * @param string                               $requestBody
458
     * @param string                               $childSchemeClass
459
     * @param ModelSchemeInfoInterface             $schemeInfo
460
     * @param JsonApiDataValidatingParserInterface $childValidator
461
     * @param CrudInterface                        $parentCrud
462
     * @param CrudInterface                        $childCrud
463
     * @param SettingsProviderInterface            $provider
464
     * @param JsonSchemesInterface                 $jsonSchemes
465
     * @param EncoderInterface                     $encoder
466
     * @param FactoryInterface                     $errorFactory
467
     * @param FormatterFactoryInterface            $formatterFactory
468
     * @param string                               $messagesNamespace
469
     * @param string                               $errorMessage
470
     *
471
     * @return ResponseInterface
472
     *
473
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
474
     */
475 2
    protected static function defaultUpdateInRelationshipHandler(
476
        string $parentIndex,
477
        string $modelRelName,
478
        string $childIndex,
479
        UriInterface $requestUri,
480
        string $requestBody,
481
        string $childSchemeClass,
482
        ModelSchemeInfoInterface $schemeInfo,
483
        JsonApiDataValidatingParserInterface $childValidator,
484
        CrudInterface $parentCrud,
485
        CrudInterface $childCrud,
486
        SettingsProviderInterface $provider,
487
        JsonSchemesInterface $jsonSchemes,
488
        EncoderInterface $encoder,
489
        FactoryInterface $errorFactory,
490
        FormatterFactoryInterface $formatterFactory,
491
        string $messagesNamespace = S::GENERIC_NAMESPACE,
492
        string $errorMessage = Generic::MSG_ERR_INVALID_ELEMENT
493
    ): ResponseInterface {
494 2
        if ($parentCrud->hasInRelationship($parentIndex, $modelRelName, $childIndex) === true) {
495
            return static::defaultUpdateHandler(
496
                $childIndex,
497
                $requestUri,
498
                $requestBody,
499
                $childSchemeClass,
500
                $schemeInfo,
501
                $childValidator,
502
                $childCrud,
503
                $provider,
504
                $jsonSchemes,
505
                $encoder,
506
                $errorFactory,
507
                $formatterFactory,
508
                $messagesNamespace,
509
                $errorMessage
510
            );
511
        }
512
513 1
        $encParams = null;
514 1
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemes, $encoder, $encParams);
515
516 1
        return $responses->getCodeResponse(404);
517
    }
518
519
    /**
520
     * @param string                    $index
521
     * @param UriInterface              $requestUri
522
     * @param CrudInterface             $crud
523
     * @param SettingsProviderInterface $provider
524
     * @param JsonSchemesInterface      $jsonSchemes
525
     * @param EncoderInterface          $encoder
526
     *
527
     * @return ResponseInterface
528
     */
529 1
    protected static function defaultDeleteHandler(
530
        string $index,
531
        UriInterface $requestUri,
532
        CrudInterface $crud,
533
        SettingsProviderInterface $provider,
534
        JsonSchemesInterface $jsonSchemes,
535
        EncoderInterface $encoder
536
    ): ResponseInterface {
537 1
        $crud->remove($index);
538
539 1
        $encParams = null;
540 1
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemes, $encoder, $encParams);
541 1
        $response  = $responses->getCodeResponse(204);
542
543 1
        return $response;
544
    }
545
546
    /** @noinspection PhpTooManyParametersInspection
547
     * @param string                    $parentIndex
548
     * @param string                    $modelRelName
549
     * @param string                    $childIndex
550
     * @param UriInterface              $requestUri
551
     * @param CrudInterface             $parentCrud
552
     * @param CrudInterface             $childCrud
553
     * @param SettingsProviderInterface $provider
554
     * @param JsonSchemesInterface      $jsonSchemes
555
     * @param EncoderInterface          $encoder
556
     *
557
     * @return ResponseInterface
558
     */
559 1
    protected static function defaultDeleteInRelationshipHandler(
560
        string $parentIndex,
561
        string $modelRelName,
562
        string $childIndex,
563
        UriInterface $requestUri,
564
        CrudInterface $parentCrud,
565
        CrudInterface $childCrud,
566
        SettingsProviderInterface $provider,
567
        JsonSchemesInterface $jsonSchemes,
568
        EncoderInterface $encoder
569
    ): ResponseInterface {
570 1
        if ($parentCrud->hasInRelationship($parentIndex, $modelRelName, $childIndex) === true) {
571
            return static::defaultDeleteHandler(
572
                $childIndex,
573
                $requestUri,
574
                $childCrud,
575
                $provider,
576
                $jsonSchemes,
577
                $encoder
578
            );
579
        }
580
581
        $encParams = null;
582
        $responses = static::defaultCreateResponses($requestUri, $provider, $jsonSchemes, $encoder, $encParams);
583
584
        return $responses->getCodeResponse(404);
585
    }
586
587
    /**
588
     * @param ContainerInterface $container
589
     * @param string             $rulesClass
590
     *
591
     * @return JsonApiQueryValidatingParserInterface
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
     * @throws ContainerExceptionInterface
636
     * @throws NotFoundExceptionInterface
637
     */
638 16
    protected static function defaultCreateParameterMapper(
639
        ContainerInterface $container,
640
        string $schemaClass
641
    ): ParametersMapperInterface {
642 16
        static::assertClassImplements($schemaClass, SchemaInterface::class);
643
644
        /** @var SchemaInterface $schemaClass */
645 16
        $jsonResourceType = $schemaClass::TYPE;
646
647
        /** @var ParametersMapperInterface $mapper */
648 16
        $mapper = $container->get(ParametersMapperInterface::class);
649 16
        $mapper->selectRootSchemeByResourceType($jsonResourceType);
650
651 16
        return $mapper;
652
    }
653
654
    /**
655
     * @param JsonApiQueryValidatingParserInterface $queryParser
656
     *
657
     * @return EncodingParametersInterface
658
     */
659
    protected static function defaultCreateEncodingParameters(
660
        JsonApiQueryValidatingParserInterface $queryParser
661
    ): EncodingParametersInterface {
662
        return new EncodingParameters(
663
            $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...
664
            $queryParser->hasFields() === true ? $queryParser->getFields() : null
665
        );
666
    }
667
668
    /**
669
     * @param ContainerInterface $container
670
     * @param string|null        $class
671
     *
672
     * @return CrudInterface
673
     *
674
     * @throws ContainerExceptionInterface
675
     * @throws NotFoundExceptionInterface
676
     */
677 26
    protected static function defaultCreateApi(ContainerInterface $container, string $class): CrudInterface
678
    {
679 26
        static::assertClassImplements($class, CrudInterface::class);
680
681
        /** @var FactoryInterface $factory */
682 26
        $factory = $container->get(FactoryInterface::class);
683 26
        $api     = $factory->createApi($class);
684
685 26
        return $api;
686
    }
687
688
    /**
689
     * @param UriInterface                     $requestUri
690
     * @param SettingsProviderInterface        $provider
691
     * @param JsonSchemesInterface             $jsonSchemes
692
     * @param EncoderInterface                 $encoder
693
     * @param EncodingParametersInterface|null $parameters
694
     *
695
     * @return ResponsesInterface
696
     */
697 4
    protected static function defaultCreateResponses(
698
        UriInterface $requestUri,
699
        SettingsProviderInterface $provider,
700
        JsonSchemesInterface $jsonSchemes,
701
        EncoderInterface $encoder,
702
        ?EncodingParametersInterface $parameters
703
    ): ResponsesInterface {
704 4
        $encoder->forOriginalUri($requestUri);
705 4
        $settings  = $provider->get(S::class);
706 4
        $responses = new Responses(
707 4
            new MediaType(MediaTypeInterface::JSON_API_TYPE, MediaTypeInterface::JSON_API_SUB_TYPE),
708 4
            $encoder,
709 4
            $jsonSchemes,
710 4
            $parameters,
711 4
            $settings[S::KEY_URI_PREFIX],
712 4
            $settings[S::KEY_META]
713
        );
714
715 4
        return $responses;
716
    }
717
718
    /**
719
     * Developers can override the method in order to add/remove some data for `create`/`update` inputs.
720
     *
721
     * @param string                    $requestBody
722
     * @param FactoryInterface          $errorFactory
723
     * @param FormatterFactoryInterface $formatterFactory
724
     * @param string                    $messagesNamespace
725
     * @param string                    $errorMessage
726
     *
727
     * @return array
728
     */
729 6
    protected static function readJsonFromRequest(
730
        string $requestBody,
731
        FactoryInterface $errorFactory,
732
        FormatterFactoryInterface $formatterFactory,
733
        string $messagesNamespace = S::GENERIC_NAMESPACE,
734
        string $errorMessage = Generic::MSG_ERR_INVALID_ELEMENT
735
    ): array {
736 6
        if (empty($requestBody) === true || ($json = json_decode($requestBody, true)) === null) {
737 1
            $formatter = $formatterFactory->createFormatter($messagesNamespace);
738 1
            $errors    = $errorFactory->createErrorCollection();
739 1
            $errors->addDataError($formatter->formatMessage($errorMessage));
740
741 1
            throw new JsonApiException($errors);
742
        }
743
744 5
        return $json;
745
    }
746
747
    /**
748
     * Developers can override the method in order to use custom data mapping from a Schema to Model.
749
     *
750
     * @param array                    $captures
751
     * @param string                   $schemeClass
752
     * @param ModelSchemeInfoInterface $schemeInfo
753
     *
754
     * @return array
755
     */
756 3
    protected static function mapSchemeDataToModelData(
757
        array $captures,
758
        string $schemeClass,
759
        ModelSchemeInfoInterface $schemeInfo
760
    ): array {
761 3
        static::assertClassImplements($schemeClass, SchemaInterface::class);
762
763
        /** @var SchemaInterface $schemeClass */
764 3
        static::assertClassImplements($modelClass = $schemeClass::MODEL, ModelInterface::class);
765
        /** @var ModelInterface $modelClass */
766
767 3
        $index         = null;
768 3
        $fields        = [];
769 3
        $toManyIndexes = [];
770 3
        foreach ($captures as $name => $value) {
771 3
            assert(is_string($name) === true);
772 3
            if ($name === DI::KEYWORD_ID) {
773 3
                $index = $value;
774 3
            } elseif ($schemeClass::hasAttributeMapping($name) === true) {
775 3
                $fieldName          = $schemeClass::getAttributeMapping($name);
776 3
                $fields[$fieldName] = $value;
777 3
            } elseif ($schemeClass::hasRelationshipMapping($name) === true) {
778 2
                $modelRelName = $schemeClass::getRelationshipMapping($name);
779 2
                $relType      = $schemeInfo->getRelationshipType($modelClass, $modelRelName);
0 ignored issues
show
Documentation introduced by
$modelClass is of type object<Limoncello\Contra...ication\ModelInterface>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
780 2
                if ($relType === RelationshipTypes::BELONGS_TO) {
781 2
                    $fkName          = $schemeInfo->getForeignKey($modelClass, $modelRelName);
0 ignored issues
show
Documentation introduced by
$modelClass is of type object<Limoncello\Contra...ication\ModelInterface>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
782 2
                    $fields[$fkName] = $value;
783 2
                } elseif ($relType === RelationshipTypes::BELONGS_TO_MANY) {
784 3
                    $toManyIndexes[$modelRelName] = $value;
785
                }
786
            }
787
        }
788
789 3
        $result = [$index, $fields, $toManyIndexes];
790
791 3
        return $result;
792
    }
793
794
    /**
795
     * @param null|string $value
796
     *
797
     * @return void
798
     */
799 26
    private static function assertClassValueDefined(?string $value): void
800
    {
801 26
        assert(empty($value) === false, 'Value should be defined in `' . static::class . '`.');
802
    }
803
804
    /**
805
     * @param string $class
806
     * @param string $interface
807
     *
808
     * @return void
809
     */
810 26
    private static function assertClassImplements(string $class, string $interface): void
811
    {
812 26
        assert(
813 26
            array_key_exists($interface, class_implements($class)) === true,
814 26
            "Class `$class` should implement `" . $interface . '` interface.'
815
        );
816
    }
817
}
818