Completed
Push — master ( 1a67d2...dfab50 )
by Neomerx
11:35 queued 22s
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\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