Completed
Push — master ( 29d040...599906 )
by Neomerx
04:36
created

BaseController::deleteImpl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
ccs 0
cts 0
cp 0
cc 1
eloc 9
nc 1
nop 4
crap 2
1
<?php namespace Limoncello\Flute\Http;
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 Limoncello\Contracts\Application\ModelInterface;
20
use Limoncello\Contracts\Data\ModelSchemeInfoInterface;
21
use Limoncello\Contracts\Data\RelationshipTypes;
22
use Limoncello\Contracts\L10n\FormatterFactoryInterface;
23
use Limoncello\Contracts\L10n\FormatterInterface;
24
use Limoncello\Flute\Contracts\Api\CrudInterface;
25
use Limoncello\Flute\Contracts\FactoryInterface;
26
use Limoncello\Flute\Contracts\Http\ControllerInterface;
27
use Limoncello\Flute\Contracts\Models\PaginatedDataInterface;
28
use Limoncello\Flute\Contracts\Schema\JsonSchemesInterface;
29
use Limoncello\Flute\Contracts\Schema\SchemaInterface;
30
use Limoncello\Flute\Contracts\Validation\JsonApiValidatorFactoryInterface;
31
use Limoncello\Flute\Contracts\Validation\JsonApiValidatorInterface;
32
use Limoncello\Flute\Http\Query\FilterParameterCollection;
33
use Limoncello\Flute\Http\Traits\CreateResponsesTrait;
34
use Limoncello\Flute\L10n\Messages;
35
use Neomerx\JsonApi\Contracts\Document\DocumentInterface as DI;
36
use Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface;
37
use Neomerx\JsonApi\Contracts\Http\Query\QueryParametersParserInterface;
38
use Neomerx\JsonApi\Contracts\Http\ResponsesInterface;
39
use Neomerx\JsonApi\Exceptions\JsonApiException;
40
use Psr\Container\ContainerInterface;
41
use Psr\Http\Message\ResponseInterface;
42
use Psr\Http\Message\ServerRequestInterface;
43
44
/**
45
 * @package Limoncello\Flute
46
 *
47
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
48
 */
49
abstract class BaseController implements ControllerInterface
50
{
51
    use CreateResponsesTrait;
52
53
    /** API class name */
54
    const API_CLASS = null;
55
56
    /** JSON API Schema class name */
57
    const SCHEMA_CLASS = null;
58
59
    /** JSON API validation rules set class */
60
    const ON_CREATE_VALIDATION_RULES_SET_CLASS = null;
61
62
    /** JSON API validation rules set class */
63
    const ON_UPDATE_VALIDATION_RULES_SET_CLASS = null;
64
65
    /** URI key used in routing table */
66
    const ROUTE_KEY_INDEX = 'idx';
67
68
    /**
69
     * @inheritdoc
70
     */
71 12
    public static function index(
72
        array $routeParams,
73
        ContainerInterface $container,
74
        ServerRequestInterface $request
75
    ): ResponseInterface {
76
        /** @var QueryParametersParserInterface $queryParser */
77 12
        $queryParser    = $container->get(QueryParametersParserInterface::class);
78 12
        $encodingParams = $queryParser->parse($request);
79
80
        list ($filters, $sorts, $includes, $paging) =
81 12
            static::mapQueryParameters($container, $encodingParams, static::SCHEMA_CLASS);
82
83 10
        $modelData = static::createApi($container)->index($filters, $sorts, $includes, $paging);
84 10
        $responses = static::createResponses($container, $request, $encodingParams);
85 10
        $response  = $modelData->getPaginatedData()->getData() === null ?
86 10
            $responses->getCodeResponse(404) : $responses->getContentResponse($modelData);
87
88 10
        return $response;
89
    }
90
91
    /**
92
     * @inheritdoc
93
     */
94 1
    public static function create(
95
        array $routeParams,
96
        ContainerInterface $container,
97
        ServerRequestInterface $request
98
    ): ResponseInterface {
99 1
        $validator = static::createOnCreateValidator($container);
100 1
        $jsonData  = static::readJsonFromRequest($container, $request);
101 1
        $captures  = $validator->assert($jsonData)->getJsonApiCaptures();
102
103
        list ($index, $attributes, $toMany) =
104 1
            static::mapSchemeDataToModelData($container, $captures, static::SCHEMA_CLASS);
105 1
106 1
        $api   = self::createApi($container);
107
        $index = $api->create($index, $attributes, $toMany);
108
        $data  = $api->read($index);
109 1
110
        $response = static::createResponses($container, $request)->getCreatedResponse($data);
111 1
112 1
        return $response;
113 1
    }
114
115 1
    /**
116
     * @inheritdoc
117 1
     */
118
    public static function read(
119
        array $routeParams,
120
        ContainerInterface $container,
121
        ServerRequestInterface $request
122
    ): ResponseInterface {
123 1
        /** @var QueryParametersParserInterface $queryParser */
124
        $queryParser    = $container->get(QueryParametersParserInterface::class);
125
        $encodingParams = $queryParser->parse($request);
126
127
        list ($filters, , $includes) = static::mapQueryParameters($container, $encodingParams, static::SCHEMA_CLASS);
128
129 1
        $index    = $routeParams[static::ROUTE_KEY_INDEX];
130 1
        $response = static::readImpl(
0 ignored issues
show
Bug introduced by
Since readImpl() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of readImpl() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
131
            static::createApi($container),
132 1
            static::createResponses($container, $request, $encodingParams),
133
            $index,
134 1
            $filters,
135 1
            $includes
136 1
        );
137 1
138 1
        return $response;
139 1
    }
140 1
141
    /**
142
     * @inheritdoc
143 1
     */
144
    public static function update(
145
        array $routeParams,
146
        ContainerInterface $container,
147
        ServerRequestInterface $request
148
    ): ResponseInterface {
149 4
        $validator = static::createOnUpdateValidator($container);
150
        $jsonData  = static::readJsonFromRequest($container, $request);
151
        $jsonData  = static::normalizeIndexValueOnUpdate($routeParams, $container, $jsonData);
152
        $captures  = $validator->assert($jsonData)->getJsonApiCaptures();
153
154 4
        list ($index, $attributes, $toMany) =
155 4
            static::mapSchemeDataToModelData($container, $captures, static::SCHEMA_CLASS);
156 4
        $api = self::createApi($container);
157
158
        return self::updateImpl($index, $attributes, $toMany, $container, $request, $api);
159 4
    }
160 4
161 2
    /**
162
     * @inheritdoc
163
     */
164 2
    public static function delete(
165 2
        array $routeParams,
166
        ContainerInterface $container,
167 1
        ServerRequestInterface $request
168 1
    ): ResponseInterface {
169 1
        $index = $routeParams[static::ROUTE_KEY_INDEX];
170 1
171
        return static::deleteImpl($index, $container, $request, self::createApi($container));
0 ignored issues
show
Bug introduced by
Since deleteImpl() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of deleteImpl() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
172
    }
173 1
174
    /**
175
     * @param string                 $index
176
     * @param string                 $relationshipName
177 1
     * @param ContainerInterface     $container
178 1
     * @param ServerRequestInterface $request
179
     *
180 1
     * @return ResponseInterface
181
     */
182 View Code Duplication
    protected static function readRelationship(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
183
        string $index,
184
        string $relationshipName,
185
        ContainerInterface $container,
186 1
        ServerRequestInterface $request
187
    ): ResponseInterface {
188
        /** @var PaginatedDataInterface $relData */
189
        /** @var EncodingParametersInterface $encodingParams */
190
        list ($relData, $encodingParams) = self::readRelationshipData($index, $relationshipName, $container, $request);
191 1
192
        $responses = static::createResponses($container, $request, $encodingParams);
193 1
        $response  = $relData->getData() === null ?
194
            $responses->getCodeResponse(404) : $responses->getContentResponse($relData);
195
196
        return $response;
197
    }
198
199
    /**
200
     * @param string                 $index
201
     * @param string                 $relationshipName
202
     * @param ContainerInterface     $container
203
     * @param ServerRequestInterface $request
204 2
     *
205
     * @return ResponseInterface
206
     */
207 View Code Duplication
    protected static function readRelationshipIdentifiers(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
208
        string $index,
209
        string $relationshipName,
210
        ContainerInterface $container,
211
        ServerRequestInterface $request
212 2
    ): ResponseInterface {
213
        /** @var PaginatedDataInterface $relData */
214 2
        /** @var EncodingParametersInterface $encodingParams */
215 2
        list ($relData, $encodingParams) = self::readRelationshipData($index, $relationshipName, $container, $request);
216 2
217
        $responses = static::createResponses($container, $request, $encodingParams);
218 2
        $response  = $relData->getData() === null ?
219
            $responses->getCodeResponse(404) : $responses->getIdentifiersResponse($relData);
220
221
        return $response;
222
    }
223
224
    /**
225
     * @param ContainerInterface $container
226
     * @param string|null        $class
227
     *
228
     * @return CrudInterface
229 1
     */
230
    protected static function createApi(ContainerInterface $container, string $class = null): CrudInterface
231
    {
232
        /** @var FactoryInterface $factory */
233
        $factory = $container->get(FactoryInterface::class);
234
        $api     = $factory->createApi($class ?? static::API_CLASS);
235
236
        return $api;
237 1
    }
238
239 1
    /**
240 1
     * @param ContainerInterface          $container
241 1
     * @param EncodingParametersInterface $parameters
242
     * @param string                      $schemaClass
243 1
     *
244
     * @return array
245
     */
246
    protected static function mapQueryParameters(
247
        ContainerInterface $container,
248
        EncodingParametersInterface $parameters,
249
        string $schemaClass
250
    ): array {
251
        /** @var FactoryInterface $factory */
252 20
        $factory          = $container->get(FactoryInterface::class);
253
        $errors           = $factory->createErrorCollection();
254
        $queryTransformer = new QueryTransformer(
255 20
            $container->get(ModelSchemeInfoInterface::class),
256 20
            $container->get(JsonSchemesInterface::class),
257
            static::createMessageFormatter($container),
258 20
            $schemaClass
259
        );
260
261
        $result = $queryTransformer->mapParameters($errors, $parameters);
262
        if ($errors->count() > 0) {
263
            throw new JsonApiException($errors);
264
        }
265
266
        return $result;
267
    }
268 16
269
    /**
270
     * @param ContainerInterface     $container
271
     * @param ServerRequestInterface $request
272
     *
273
     * @return array
274 16
     */
275 16
    protected static function readJsonFromRequest(ContainerInterface $container, ServerRequestInterface $request): array
276 16
    {
277 16
        $body = (string)$request->getBody();
278 16
        if (empty($body) === true || ($json = json_decode($body, true)) === null) {
279 16
            /** @var FactoryInterface $factory */
280 16
            $factory = $container->get(FactoryInterface::class);
281
            $errors  = $factory->createErrorCollection();
282
            $errors->addDataError(
283 16
                static::createMessageFormatter($container)->formatMessage(Messages::MSG_ERR_INVALID_ELEMENT)
284 16
            );
285 2
286
            throw new JsonApiException($errors);
287
        }
288 14
289
        return $json;
290
    }
291
292
    /**
293
     * @param array              $routeParams
294
     * @param ContainerInterface $container
295
     * @param array              $jsonData
296
     *
297 7
     * @return array
298
     */
299 7
    protected static function normalizeIndexValueOnUpdate(
300 7
        array $routeParams,
301
        ContainerInterface $container,
302 1
        array $jsonData
303 1
    ): array {
304 1
        // check that index in data and URL are identical
305 1
        $index         = $routeParams[static::ROUTE_KEY_INDEX];
306
        $dataSection   = null;
307
        $hasIndexValue =
308 1
            array_key_exists(DI::KEYWORD_DATA, $jsonData) &&
309
            array_key_exists(DI::KEYWORD_ID, ($dataSection = $jsonData[DI::KEYWORD_DATA]));
310
        if ($hasIndexValue === true) {
311 6
            assert($dataSection !== null);
312
            if ($dataSection[DI::KEYWORD_ID] !== $index) {
313
                /** @var FactoryInterface $factory */
314
                $factory = $container->get(FactoryInterface::class);
315
                $errors  = $factory->createErrorCollection();
316
                $errors->addDataIdError(
317
                    static::createMessageFormatter($container)->formatMessage(Messages::MSG_ERR_INVALID_ELEMENT)
318
                );
319
320
                throw new JsonApiException($errors);
321
            }
322
        } else {
323
            // put the index to data for our convenience
324 1
            $jsonData[DI::KEYWORD_DATA][DI::KEYWORD_ID] = $index;
325
        }
326
327
        return $jsonData;
328
    }
329
330
    /**
331
     * @param int|string             $parentIndex
332
     * @param string                 $relationshipName
333 1
     * @param int|string             $childIndex
334 1
     * @param string                 $childApiClass
335 1
     * @param ContainerInterface     $container
336 1
     * @param ServerRequestInterface $request
337 1
     *
338
     * @return ResponseInterface
339
     */
340 1 View Code Duplication
    protected static function deleteInRelationship(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
341
        $parentIndex,
342 1
        string $relationshipName,
343
        $childIndex,
344
        string $childApiClass,
345
        ContainerInterface $container,
346
        ServerRequestInterface $request
347
    ): ResponseInterface {
348
        /** @var SchemaInterface $schemaClass */
349
        $schemaClass  = static::SCHEMA_CLASS;
350
        $modelRelName = $schemaClass::getRelationshipMapping($relationshipName);
351
        $hasChild     = self::createApi($container)->hasInRelationship($parentIndex, $modelRelName, $childIndex);
352
        if ($hasChild === false) {
353
            return static::createResponses($container, $request)->getCodeResponse(404);
354
        }
355
356
        $childApi = self::createApi($container, $childApiClass);
357 2
358
        return static::deleteImpl($childIndex, $container, $request, $childApi);
0 ignored issues
show
Bug introduced by
Since deleteImpl() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of deleteImpl() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
359
    }
360
361
    /** @noinspection PhpTooManyParametersInspection
362
     * @param int|string             $parentIndex
363
     * @param string                 $relationshipName
364
     * @param int|string             $childIndex
365
     * @param array                  $attributes
366
     * @param array                  $toMany
367
     * @param string                 $childApiClass
368 2
     * @param ContainerInterface     $container
369 2
     * @param ServerRequestInterface $request
370 2
     *
371 2
     * @return ResponseInterface
372 1
     */
373 View Code Duplication
    protected static function updateInRelationship(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
374
        $parentIndex,
375 1
        string $relationshipName,
376
        $childIndex,
377 1
        array $attributes,
378
        array $toMany,
379
        string $childApiClass,
380
        ContainerInterface $container,
381
        ServerRequestInterface $request
382
    ): ResponseInterface {
383
        /** @var SchemaInterface $schemaClass */
384
        $schemaClass  = static::SCHEMA_CLASS;
385
        $modelRelName = $schemaClass::getRelationshipMapping($relationshipName);
386 7
        $hasChild     = self::createApi($container)->hasInRelationship($parentIndex, $modelRelName, $childIndex);
387
        if ($hasChild === false) {
388
            return static::createResponses($container, $request)->getCodeResponse(404);
389
        }
390
391 7
        $childApi = self::createApi($container, $childApiClass);
392 7
393
        return static::updateImpl($childIndex, $attributes, $toMany, $container, $request, $childApi);
0 ignored issues
show
Bug introduced by
Since updateImpl() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of updateImpl() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
394 7
    }
395
396
    /**
397
     * @param ContainerInterface $container
398
     *
399
     * @return JsonApiValidatorInterface
400
     */
401 View Code Duplication
    protected static function createOnCreateValidator(ContainerInterface $container): JsonApiValidatorInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
402
    {
403
        assert(
404 4
            empty(static::ON_CREATE_VALIDATION_RULES_SET_CLASS) === false,
405
            'Validation rules set should be defined for class ' . static::class . '.'
406
        );
407
408
        return static::createJsonApiValidator($container, static::ON_CREATE_VALIDATION_RULES_SET_CLASS);
409 4
    }
410
411
    /**
412 4
     * @param ContainerInterface $container
413 4
     *
414
     * @return JsonApiValidatorInterface
415
     */
416 View Code Duplication
    protected static function createOnUpdateValidator(ContainerInterface $container): JsonApiValidatorInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
417 4
    {
418
        assert(
419 4
            empty(static::ON_UPDATE_VALIDATION_RULES_SET_CLASS) === false,
420 4
            'Validation rules set should be defined for class ' . static::class . '.'
421 4
        );
422 4
423 4
        return static::createJsonApiValidator($container, static::ON_UPDATE_VALIDATION_RULES_SET_CLASS);
424 4
    }
425 4
426 4
    /**
427 4
     * @param ContainerInterface $container
428 4
     * @param string             $rulesSetClass
429 2
     *
430 2
     * @return JsonApiValidatorInterface
431 2
     */
432 2
    protected static function createJsonApiValidator(
433 2
        ContainerInterface $container,
434 2
        string $rulesSetClass
435 4
    ): JsonApiValidatorInterface {
436
        /** @var JsonApiValidatorFactoryInterface $validatorFactory */
437
        $validatorFactory = $container->get(JsonApiValidatorFactoryInterface::class);
438
        $validator        = $validatorFactory->createValidator($rulesSetClass);
439
440 4
        return $validator;
441
    }
442 4
443
    /**
444
     * @param ContainerInterface $container
445
     * @param array              $captures
446
     * @param string             $schemeClass
447
     *
448
     * @return array
449
     */
450
    protected static function mapSchemeDataToModelData(
451
        ContainerInterface $container,
452
        array $captures,
453
        string $schemeClass
454 3
    ): array {
455
        assert(in_array(SchemaInterface::class, class_implements($schemeClass)));
456
        /** @var SchemaInterface $schemeClass */
457
458
        $modelClass = $schemeClass::MODEL;
459
        assert(in_array(ModelInterface::class, class_implements($modelClass)));
460
        /** @var ModelInterface $modelClass */
461 3
462 3
        /** @var ModelSchemeInfoInterface $schemeInfo */
463 3
        $schemeInfo = $container->get(ModelSchemeInfoInterface::class);
464
465 3
        $index         = null;
466
        $fields        = [];
467
        $toManyIndexes = [];
468
        foreach ($captures as $name => $value) {
469
            if ($name === DI::KEYWORD_ID) {
470
                $index = $value;
471
            } elseif ($schemeClass::hasAttributeMapping($name) === true) {
472
                $fieldName          = $schemeClass::getAttributeMapping($name);
473
                $fields[$fieldName] = $value;
474
            } elseif ($schemeClass::hasRelationshipMapping($name) === true) {
475
                $modelRelName = $schemeClass::getRelationshipMapping($name);
476 3
                $relType      = $schemeInfo->getRelationshipType($modelClass, $modelRelName);
477
                if ($relType === RelationshipTypes::BELONGS_TO) {
478
                    $fkName          = $schemeInfo->getForeignKey($modelClass, $modelRelName);
479
                    $fields[$fkName] = $value;
480
                } elseif ($relType === RelationshipTypes::BELONGS_TO_MANY) {
481
                    $toManyIndexes[$modelRelName] = $value;
482
                }
483 3
            }
484 3
        }
485
486
        $result = [$index, $fields, $toManyIndexes];
487 3
488 3
        return $result;
489
    }
490 3
491
    /**
492
     * @param CrudInterface                  $api
493 3
     * @param ResponsesInterface             $responses
494 3
     * @param string|int                     $index
495 3
     * @param FilterParameterCollection|null $filters
496
     * @param array|null                     $includes
497 3
     *
498
     * @return mixed
499
     */
500
    private static function readImpl(
501
        CrudInterface $api,
502
        ResponsesInterface $responses,
503
        $index,
504
        FilterParameterCollection $filters = null,
505
        array $includes = null
506
    ) {
507
        $modelData = $api->read($index, $filters, $includes);
508
        $response  = $modelData->getPaginatedData()->getData() === null ?
509
            $responses->getCodeResponse(404) : $responses->getContentResponse($modelData);
510 2
511
        return $response;
512
    }
513
514
    /**
515
     * @param string                 $index
516
     * @param string                 $relationshipName
517
     * @param ContainerInterface     $container
518 2
     * @param ServerRequestInterface $request
519
     *
520 2
     * @return array [PaginatedDataInterface, EncodingParametersInterface]
521
     */
522 2
    private static function readRelationshipData(
523
        string $index,
524
        string $relationshipName,
525
        ContainerInterface $container,
526
        ServerRequestInterface $request
527
    ): array {
528
        /** @var QueryParametersParserInterface $queryParser */
529
        $queryParser    = $container->get(QueryParametersParserInterface::class);
530
        $encodingParams = $queryParser->parse($request);
531
532
        /** @var JsonSchemesInterface $jsonSchemes */
533 2
        $jsonSchemes  = $container->get(JsonSchemesInterface::class);
534
        $targetSchema = $jsonSchemes->getRelationshipSchema(static::SCHEMA_CLASS, $relationshipName);
535
        list ($filters, $sorts, , $paging) =
536
            static::mapQueryParameters($container, $encodingParams, get_class($targetSchema));
537
538
        /** @var SchemaInterface $schemaClass */
539 2
        $schemaClass  = static::SCHEMA_CLASS;
540 2
        $modelRelName = $schemaClass::getRelationshipMapping($relationshipName);
541
        $relData      = self::createApi($container)->readRelationship($index, $modelRelName, $filters, $sorts, $paging);
542 2
543
        return [$relData, $encodingParams];
544
    }
545
546
    /**
547
     * @param string|int             $index
548
     * @param array                  $attributes
549
     * @param array                  $toMany
550
     * @param ContainerInterface     $container
551 18
     * @param ServerRequestInterface $request
552
     * @param CrudInterface          $api
553
     *
554
     * @return ResponseInterface
555
     */
556 18
    private static function updateImpl(
557 18
        $index,
558
        array $attributes,
559 18
        array $toMany,
560
        ContainerInterface $container,
561
        ServerRequestInterface $request,
562
        CrudInterface $api
563
    ): ResponseInterface {
564
        $api->update($index, $attributes, $toMany);
565
566
        $response = static::readImpl($api, static::createResponses($container, $request), $index);
0 ignored issues
show
Bug introduced by
Since readImpl() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of readImpl() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
567
568
        return $response;
569
    }
570
571
    /**
572
     * @param string|int             $index
573
     * @param ContainerInterface     $container
574
     * @param ServerRequestInterface $request
575
     * @param CrudInterface          $api
576
     *
577
     * @return ResponseInterface
578
     */
579
    private static function deleteImpl(
580
        $index,
581
        ContainerInterface $container,
582
        ServerRequestInterface $request,
583
        CrudInterface $api
584
    ): ResponseInterface {
585
        $api->delete($index);
586
        $response = static::createResponses($container, $request)->getCodeResponse(204);
587
588
        return $response;
589
    }
590
591
    /**
592
     * @param ContainerInterface $container
593
     * @param string             $namespace
594
     *
595
     * @return FormatterInterface
596
     */
597
    protected static function createMessageFormatter(
598
        ContainerInterface $container,
599
        string $namespace = Messages::RESOURCES_NAMESPACE
600
    ): FormatterInterface {
601
        /** @var FormatterFactoryInterface $factory */
602
        $factory          = $container->get(FormatterFactoryInterface::class);
603
        $messageFormatter = $factory->createFormatter($namespace);
604
605
        return $messageFormatter;
606
    }
607
}
608