Completed
Push — develop ( 26b032...524257 )
by Neomerx
18:05 queued 09:45
created

DefaultControllerMethodsTrait::defaultRead()   B

Complexity

Conditions 4
Paths 2

Size

Total Lines 26
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 26
rs 8.5806
c 0
b 0
f 0
ccs 11
cts 11
cp 1
cc 4
eloc 21
nc 2
nop 9
crap 4

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 defaultIndex(
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 10
        $encodingParams = new EncodingParameters(
86 10
            $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...
87 10
            $queryParser->hasFields() === true ? $queryParser->getFields() : null
88
        );
89 10
        $responses      = static::createResponses($requestUri, $provider, $jsonSchemes, $encoder, $encodingParams);
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 JsonSchemesInterface                  $jsonSchemes
105
     * @param EncoderInterface                      $encoder
106
     *
107
     * @return ResponseInterface
108
     */
109 1
    protected static function defaultRead(
110
        string $index,
111
        array $queryParams,
112
        UriInterface $requestUri,
113
        JsonApiQueryValidatingParserInterface $queryParser,
114
        ParametersMapperInterface $mapper,
115
        CrudInterface $crud,
116
        SettingsProviderInterface $provider,
117
        JsonSchemesInterface $jsonSchemes,
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
        $encodingParams = new EncodingParameters(
126 1
            $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...
127 1
            $queryParser->hasFields() === true ? $queryParser->getFields() : null
128
        );
129 1
        $responses      = static::createResponses($requestUri, $provider, $jsonSchemes, $encoder, $encodingParams);
130 1
        $response       = $model === null ?
131 1
            $responses->getCodeResponse(404) : $responses->getContentResponse($model);
132
133 1
        return $response;
134
    }
135
136
    /** @noinspection PhpTooManyParametersInspection
137
     * @param Closure                               $apiHandler
138
     * @param array                                 $queryParams
139
     * @param UriInterface                          $requestUri
140
     * @param JsonApiQueryValidatingParserInterface $queryParser
141
     * @param ParametersMapperInterface             $mapper
142
     * @param CrudInterface                         $crud
143
     * @param SettingsProviderInterface             $provider
144
     * @param JsonSchemesInterface                  $jsonSchemes
145
     * @param EncoderInterface                      $encoder
146
     *
147
     * @return ResponseInterface
148
     */
149 2
    protected static function defaultReadRelationshipWithClosure(
150
        Closure $apiHandler,
151
        array $queryParams,
152
        UriInterface $requestUri,
153
        JsonApiQueryValidatingParserInterface $queryParser,
154
        ParametersMapperInterface $mapper,
155
        CrudInterface $crud,
156
        SettingsProviderInterface $provider,
157
        JsonSchemesInterface $jsonSchemes,
158
        EncoderInterface $encoder
159
    ): ResponseInterface {
160 2
        $queryParser->parse($queryParams);
161 2
        $mapper->applyQueryParameters($queryParser, $crud);
162
163 2
        $relData = call_user_func($apiHandler);
164
165 2
        $encodingParams = new EncodingParameters(
166 2
            $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...
167 2
            $queryParser->hasFields() === true ? $queryParser->getFields() : null
168
        );
169 2
        $responses      = static::createResponses($requestUri, $provider, $jsonSchemes, $encoder, $encodingParams);
170
171 2
        $noData   = $relData === null || ($relData instanceof PaginatedDataInterface && $relData->getData() === null);
172 2
        $response = $noData === true ? $responses->getCodeResponse(404) : $responses->getContentResponse($relData);
173
174 2
        return $response;
175
    }
176
177
    /** @noinspection PhpTooManyParametersInspection
178
     * @param Closure                               $apiHandler
179
     * @param array                                 $queryParams
180
     * @param UriInterface                          $requestUri
181
     * @param JsonApiQueryValidatingParserInterface $queryParser
182
     * @param ParametersMapperInterface             $mapper
183
     * @param CrudInterface                         $crud
184
     * @param SettingsProviderInterface             $provider
185
     * @param JsonSchemesInterface                  $jsonSchemes
186
     * @param EncoderInterface                      $encoder
187
     *
188
     * @return ResponseInterface
189
     */
190 1
    protected static function defaultReadRelationshipIdentifiersWithClosure(
191
        Closure $apiHandler,
192
        array $queryParams,
193
        UriInterface $requestUri,
194
        JsonApiQueryValidatingParserInterface $queryParser,
195
        ParametersMapperInterface $mapper,
196
        CrudInterface $crud,
197
        SettingsProviderInterface $provider,
198
        JsonSchemesInterface $jsonSchemes,
199
        EncoderInterface $encoder
200
    ): ResponseInterface {
201 1
        $queryParser->parse($queryParams);
202 1
        $mapper->applyQueryParameters($queryParser, $crud);
203
204 1
        $relData = call_user_func($apiHandler);
205
206 1
        $encodingParams = new EncodingParameters(
207 1
            $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...
208 1
            $queryParser->hasFields() === true ? $queryParser->getFields() : null
209
        );
210 1
        $responses      = static::createResponses($requestUri, $provider, $jsonSchemes, $encoder, $encodingParams);
211
212 1
        $noData   = $relData === null || ($relData instanceof PaginatedDataInterface && $relData->getData() === null);
213 1
        $response = $noData === true ? $responses->getCodeResponse(404) : $responses->getIdentifiersResponse($relData);
214
215 1
        return $response;
216
    }
217
218
    /** @noinspection PhpTooManyParametersInspection
219
     * @param UriInterface                         $requestUri
220
     * @param string                               $requestBody
221
     * @param string                               $schemeClass
222
     * @param ModelSchemeInfoInterface             $schemeInfo
223
     * @param JsonApiDataValidatingParserInterface $validator
224
     * @param CrudInterface                        $crud
225
     * @param SettingsProviderInterface            $provider
226
     * @param JsonSchemesInterface                 $jsonSchemes
227
     * @param EncoderInterface                     $encoder
228
     * @param FactoryInterface                     $errorFactory
229
     * @param FormatterFactoryInterface            $formatterFactory
230
     *
231
     * @return ResponseInterface
232
     *
233
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
234
     */
235 1
    protected static function defaultCreate(
236
        UriInterface $requestUri,
237
        string $requestBody,
238
        string $schemeClass,
239
        ModelSchemeInfoInterface $schemeInfo,
240
        JsonApiDataValidatingParserInterface $validator,
241
        CrudInterface $crud,
242
        SettingsProviderInterface $provider,
243
        JsonSchemesInterface $jsonSchemes,
244
        EncoderInterface $encoder,
245
        FactoryInterface $errorFactory,
246
        FormatterFactoryInterface $formatterFactory
247
    ): ResponseInterface {
248 1
        $jsonData = static::readJsonFromRequest($requestBody, $errorFactory, $formatterFactory);
249 1
        $captures = $validator->assert($jsonData)->getJsonApiCaptures();
250
251 1
        list ($index, $attributes, $toMany) = static::mapSchemeDataToModelData($captures, $schemeClass, $schemeInfo);
252
253 1
        $index = $crud->create($index, $attributes, $toMany);
254 1
        $model = $crud->read($index);
255 1
        assert($model !== null && !($model instanceof PaginatedDataInterface));
256
257 1
        $encodingParams = null;
258 1
        $responses      = static::createResponses($requestUri, $provider, $jsonSchemes, $encoder, $encodingParams);
259 1
        $response       = $responses->getCreatedResponse($model);
260
261 1
        return $response;
262
    }
263
264
    /** @noinspection PhpTooManyParametersInspection
265
     * @param string                               $index
266
     * @param UriInterface                         $requestUri
267
     * @param string                               $requestBody
268
     * @param string                               $schemeClass
269
     * @param ModelSchemeInfoInterface             $schemeInfo
270
     * @param JsonApiDataValidatingParserInterface $validator
271
     * @param CrudInterface                        $crud
272
     * @param SettingsProviderInterface            $provider
273
     * @param JsonSchemesInterface                 $jsonSchemes
274
     * @param EncoderInterface                     $encoder
275
     * @param FactoryInterface                     $errorFactory
276
     * @param FormatterFactoryInterface            $formatterFactory
277
     * @param string                               $messagesNamespace
278
     * @param string                               $errorMessage
279
     *
280
     * @return ResponseInterface
281
     *
282
     * @SuppressWarnings(PHPMD.ElseExpression)
283
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
284
     */
285 6
    protected static function defaultUpdate(
286
        string $index,
287
        UriInterface $requestUri,
288
        string $requestBody,
289
        string $schemeClass,
290
        ModelSchemeInfoInterface $schemeInfo,
291
        JsonApiDataValidatingParserInterface $validator,
292
        CrudInterface $crud,
293
        SettingsProviderInterface $provider,
294
        JsonSchemesInterface $jsonSchemes,
295
        EncoderInterface $encoder,
296
        FactoryInterface $errorFactory,
297
        FormatterFactoryInterface $formatterFactory,
298
        string $messagesNamespace = S::GENERIC_NAMESPACE,
299
        string $errorMessage = Generic::MSG_ERR_INVALID_ELEMENT
300
    ): ResponseInterface {
301 6
        $jsonData = static::readJsonFromRequest($requestBody, $errorFactory, $formatterFactory);
302
        // check that index in data and URL are identical
303 5
        $indexValue = $jsonData[DI::KEYWORD_DATA][DI::KEYWORD_ID] ?? null;
304 5
        if (empty($indexValue) === false) {
305 4
            if ($indexValue !== $index) {
306 1
                $errors    = $errorFactory->createErrorCollection();
307 1
                $formatter = $formatterFactory->createFormatter($messagesNamespace);
308 1
                $errors->addDataIdError($formatter->formatMessage($errorMessage));
309
310 4
                throw new JsonApiException($errors);
311
            }
312
        } else {
313
            // put the index to data for our convenience
314 1
            $jsonData[DI::KEYWORD_DATA][DI::KEYWORD_ID] = $index;
315
        }
316
        // validate the data
317 4
        $captures = $validator->assert($jsonData)->getJsonApiCaptures();
318
319 3
        list ($index, $attributes, $toMany) = static::mapSchemeDataToModelData($captures, $schemeClass, $schemeInfo);
320
321 3
        $updated = $crud->update($index, $attributes, $toMany);
322
323 3
        $encodingParams = null;
324 3
        $responses      = static::createResponses($requestUri, $provider, $jsonSchemes, $encoder, $encodingParams);
325 3
        if ($updated > 0) {
326 2
            $model = $crud->read($index);
327 2
            assert($model !== null && !($model instanceof PaginatedDataInterface));
328 2
            $response = $responses->getContentResponse($model);
329
        } else {
330 1
            $response = $responses->getCodeResponse(404);
331
        }
332
333 3
        return $response;
334
    }
335
336
    /** @noinspection PhpTooManyParametersInspection
337
     * @param string                               $parentIndex
338
     * @param string                               $modelRelName
339
     * @param string                               $childIndex
340
     * @param UriInterface                         $requestUri
341
     * @param string                               $requestBody
342
     * @param string                               $childSchemeClass
343
     * @param ModelSchemeInfoInterface             $schemeInfo
344
     * @param JsonApiDataValidatingParserInterface $childValidator
345
     * @param CrudInterface                        $parentCrud
346
     * @param CrudInterface                        $childCrud
347
     * @param SettingsProviderInterface            $provider
348
     * @param JsonSchemesInterface                 $jsonSchemes
349
     * @param EncoderInterface                     $encoder
350
     * @param FactoryInterface                     $errorFactory
351
     * @param FormatterFactoryInterface            $formatterFactory
352
     * @param string                               $messagesNamespace
353
     * @param string                               $errorMessage
354
     *
355
     * @return ResponseInterface
356
     *
357
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
358
     */
359 2
    protected static function defaultUpdateInRelationship(
360
        string $parentIndex,
361
        string $modelRelName,
362
        string $childIndex,
363
        UriInterface $requestUri,
364
        string $requestBody,
365
        string $childSchemeClass,
366
        ModelSchemeInfoInterface $schemeInfo,
367
        JsonApiDataValidatingParserInterface $childValidator,
368
        CrudInterface $parentCrud,
369
        CrudInterface $childCrud,
370
        SettingsProviderInterface $provider,
371
        JsonSchemesInterface $jsonSchemes,
372
        EncoderInterface $encoder,
373
        FactoryInterface $errorFactory,
374
        FormatterFactoryInterface $formatterFactory,
375
        string $messagesNamespace = S::GENERIC_NAMESPACE,
376
        string $errorMessage = Generic::MSG_ERR_INVALID_ELEMENT
377
    ): ResponseInterface {
378 2
        if ($parentCrud->hasInRelationship($parentIndex, $modelRelName, $childIndex) === true) {
379 1
            return static::defaultUpdate(
380 1
                $childIndex,
381 1
                $requestUri,
382 1
                $requestBody,
383 1
                $childSchemeClass,
384 1
                $schemeInfo,
385 1
                $childValidator,
386 1
                $childCrud,
387 1
                $provider,
388 1
                $jsonSchemes,
389 1
                $encoder,
390 1
                $errorFactory,
391 1
                $formatterFactory,
392 1
                $messagesNamespace,
393 1
                $errorMessage
394
            );
395
        }
396
397 1
        $encodingParams = null;
398 1
        $responses      = static::createResponses($requestUri, $provider, $jsonSchemes, $encoder, $encodingParams);
399
400 1
        return $responses->getCodeResponse(404);
401
    }
402
403
    /**
404
     * @param string                    $index
405
     * @param UriInterface              $requestUri
406
     * @param CrudInterface             $crud
407
     * @param SettingsProviderInterface $provider
408
     * @param JsonSchemesInterface      $jsonSchemes
409
     * @param EncoderInterface          $encoder
410
     *
411
     * @return ResponseInterface
412
     */
413 2
    protected static function defaultDelete(
414
        string $index,
415
        UriInterface $requestUri,
416
        CrudInterface $crud,
417
        SettingsProviderInterface $provider,
418
        JsonSchemesInterface $jsonSchemes,
419
        EncoderInterface $encoder
420
    ): ResponseInterface {
421 2
        $crud->remove($index);
422
423 2
        $encodingParams = null;
424 2
        $responses      = static::createResponses($requestUri, $provider, $jsonSchemes, $encoder, $encodingParams);
425 2
        $response       = $responses->getCodeResponse(204);
426
427 2
        return $response;
428
    }
429
430
    /** @noinspection PhpTooManyParametersInspection
431
     * @param string                    $parentIndex
432
     * @param string                    $modelRelName
433
     * @param string                    $childIndex
434
     * @param UriInterface              $requestUri
435
     * @param CrudInterface             $parentCrud
436
     * @param CrudInterface             $childCrud
437
     * @param SettingsProviderInterface $provider
438
     * @param JsonSchemesInterface      $jsonSchemes
439
     * @param EncoderInterface          $encoder
440
     *
441
     * @return ResponseInterface
442
     */
443 1
    protected static function defaultDeleteInRelationship(
444
        string $parentIndex,
445
        string $modelRelName,
446
        string $childIndex,
447
        UriInterface $requestUri,
448
        CrudInterface $parentCrud,
449
        CrudInterface $childCrud,
450
        SettingsProviderInterface $provider,
451
        JsonSchemesInterface $jsonSchemes,
452
        EncoderInterface $encoder
453
    ): ResponseInterface {
454 1
        if ($parentCrud->hasInRelationship($parentIndex, $modelRelName, $childIndex) === true) {
455 1
            return static::defaultDelete(
456 1
                $childIndex,
457 1
                $requestUri,
458 1
                $childCrud,
459 1
                $provider,
460 1
                $jsonSchemes,
461 1
                $encoder
462
            );
463
        }
464
465 1
        $encodingParams = null;
466 1
        $responses      = static::createResponses($requestUri, $provider, $jsonSchemes, $encoder, $encodingParams);
467
468 1
        return $responses->getCodeResponse(404);
469
    }
470
471
    /**
472
     * @param ContainerInterface $container
473
     * @param string             $rulesClass
474
     *
475
     * @return JsonApiQueryValidatingParserInterface
476
     * @throws ContainerExceptionInterface
477
     * @throws NotFoundExceptionInterface
478
     */
479 16
    protected static function createQueryValidator(
480
        ContainerInterface $container,
481
        string $rulesClass = DefaultQueryValidationRules::class
482
    ): JsonApiQueryValidatingParserInterface {
483 16
        static::assertClassImplements($rulesClass, JsonApiQueryRulesInterface::class);
484
485
        /** @var JsonApiParserFactoryInterface $factory */
486 16
        $factory   = $container->get(JsonApiParserFactoryInterface::class);
487 16
        $validator = $factory->createQueryParser($rulesClass);
488
489 16
        return $validator;
490
    }
491
492
    /**
493
     * @param ContainerInterface $container
494
     * @param string             $rulesClass
495
     *
496
     * @return JsonApiDataValidatingParserInterface
497
     *
498
     * @throws ContainerExceptionInterface
499
     * @throws NotFoundExceptionInterface
500
     */
501 8
    protected static function createDataValidator(
502
        ContainerInterface $container,
503
        string $rulesClass
504
    ): JsonApiDataValidatingParserInterface {
505 8
        static::assertClassImplements($rulesClass, JsonApiDataRulesInterface::class);
506
507
        /** @var JsonApiParserFactoryInterface $factory */
508 8
        $factory   = $container->get(JsonApiParserFactoryInterface::class);
509 8
        $validator = $factory->createDataParser($rulesClass);
510
511 8
        return $validator;
512
    }
513
514
    /**
515
     * @param string                    $requestBody
516
     * @param FactoryInterface          $errorFactory
517
     * @param FormatterFactoryInterface $formatterFactory
518
     * @param string                    $messagesNamespace
519
     * @param string                    $errorMessage
520
     *
521
     * @return array
522
     */
523 7
    protected static function readJsonFromRequest(
524
        string $requestBody,
525
        FactoryInterface $errorFactory,
526
        FormatterFactoryInterface $formatterFactory,
527
        string $messagesNamespace = S::GENERIC_NAMESPACE,
528
        string $errorMessage = Generic::MSG_ERR_INVALID_ELEMENT
529
    ): array {
530 7
        if (empty($requestBody) === true || ($json = json_decode($requestBody, true)) === null) {
531 1
            $formatter = $formatterFactory->createFormatter($messagesNamespace);
532 1
            $errors    = $errorFactory->createErrorCollection();
533 1
            $errors->addDataError($formatter->formatMessage($errorMessage));
534
535 1
            throw new JsonApiException($errors);
536
        }
537
538 6
        return $json;
539
    }
540
541
    /**
542
     * @param ContainerInterface $container
543
     * @param string             $schemaClass
544
     *
545
     * @return ParametersMapperInterface
546
     * @throws ContainerExceptionInterface
547
     * @throws NotFoundExceptionInterface
548
     */
549 16
    protected static function createParameterMapper(
550
        ContainerInterface $container,
551
        string $schemaClass
552
    ): ParametersMapperInterface {
553 16
        static::assertClassImplements($schemaClass, SchemaInterface::class);
554
555
        /** @var SchemaInterface $schemaClass */
556 16
        $schemaClass      = static::SCHEMA_CLASS;
557 16
        $jsonResourceType = $schemaClass::TYPE;
558
559
        /** @var ParametersMapperInterface $mapper */
560 16
        $mapper = $container->get(ParametersMapperInterface::class);
561 16
        $mapper->selectRootSchemeByResourceType($jsonResourceType);
562
563 16
        return $mapper;
564
    }
565
566
    /**
567
     * @param array                    $captures
568
     * @param string                   $schemeClass
569
     * @param ModelSchemeInfoInterface $schemeInfo
570
     *
571
     * @return array
572
     */
573 4
    protected static function mapSchemeDataToModelData(
574
        array $captures,
575
        string $schemeClass,
576
        ModelSchemeInfoInterface $schemeInfo
577
    ): array {
578 4
        static::assertClassImplements($schemeClass, SchemaInterface::class);
579
580
        /** @var SchemaInterface $schemeClass */
581 4
        static::assertClassImplements($modelClass = $schemeClass::MODEL, ModelInterface::class);
582
        /** @var ModelInterface $modelClass */
583
584 4
        $index         = null;
585 4
        $fields        = [];
586 4
        $toManyIndexes = [];
587 4
        foreach ($captures as $name => $value) {
588 4
            assert(is_string($name) === true);
589 4
            if ($name === DI::KEYWORD_ID) {
590 4
                $index = $value;
591 4
            } elseif ($schemeClass::hasAttributeMapping($name) === true) {
592 4
                $fieldName          = $schemeClass::getAttributeMapping($name);
593 4
                $fields[$fieldName] = $value;
594 4
            } elseif ($schemeClass::hasRelationshipMapping($name) === true) {
595 2
                $modelRelName = $schemeClass::getRelationshipMapping($name);
596 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...
597 2
                if ($relType === RelationshipTypes::BELONGS_TO) {
598 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...
599 2
                    $fields[$fkName] = $value;
600 2
                } elseif ($relType === RelationshipTypes::BELONGS_TO_MANY) {
601 4
                    $toManyIndexes[$modelRelName] = $value;
602
                }
603
            }
604
        }
605
606 4
        $result = [$index, $fields, $toManyIndexes];
607
608 4
        return $result;
609
    }
610
611
    /**
612
     * @param ContainerInterface $container
613
     * @param string|null        $class
614
     *
615
     * @return CrudInterface
616
     *
617
     * @throws ContainerExceptionInterface
618
     * @throws NotFoundExceptionInterface
619
     */
620 26
    protected static function createApi(ContainerInterface $container, string $class): CrudInterface
621
    {
622 26
        static::assertClassImplements($class, CrudInterface::class);
623
624
        /** @var FactoryInterface $factory */
625 26
        $factory = $container->get(FactoryInterface::class);
626 26
        $api     = $factory->createApi($class);
627
628 26
        return $api;
629
    }
630
631
    /**
632
     * @param UriInterface                     $requestUri
633
     * @param SettingsProviderInterface        $provider
634
     * @param JsonSchemesInterface             $jsonSchemes
635
     * @param EncoderInterface                 $encoder
636
     * @param EncodingParametersInterface|null $parameters
637
     *
638
     * @return ResponsesInterface
639
     */
640 21
    protected static function createResponses(
641
        UriInterface $requestUri,
642
        SettingsProviderInterface $provider,
643
        JsonSchemesInterface $jsonSchemes,
644
        EncoderInterface $encoder,
645
        ?EncodingParametersInterface $parameters
646
    ): ResponsesInterface {
647 21
        $encoder->forOriginalUri($requestUri);
648 21
        $settings  = $provider->get(S::class);
649 21
        $responses = new Responses(
650 21
            new MediaType(MediaTypeInterface::JSON_API_TYPE, MediaTypeInterface::JSON_API_SUB_TYPE),
651 21
            $encoder,
652 21
            $jsonSchemes,
653 21
            $parameters,
654 21
            $settings[S::KEY_URI_PREFIX],
655 21
            $settings[S::KEY_META]
656
        );
657
658 21
        return $responses;
659
    }
660
661
    /**
662
     * @param null|string $value
663
     *
664
     * @return void
665
     */
666 26
    protected static function assertClassValueDefined(?string $value): void
667
    {
668 26
        assert(empty($value) === false, 'Value should be defined in `' . static::class . '`.');
669
    }
670
671
    /**
672
     * @param string $class
673
     * @param string $interface
674
     *
675
     * @return void
676
     */
677 26
    protected static function assertClassImplements(string $class, string $interface): void
678
    {
679 26
        assert(
680 26
            array_key_exists($interface, class_implements($class)) === true,
681 26
            "Class `$class` should implement `" . $interface . '` interface.'
682
        );
683
    }
684
}
685