Passed
Push — master ( bcfc4f...79d52d )
by Alexander
17:49 queued 15:27
created

RequestModelFactory::paramsIsRequestModel()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 3.1406

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 3
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 7
ccs 3
cts 4
cp 0.75
crap 3.1406
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\RequestModel;
6
7
use Psr\Http\Message\ServerRequestInterface;
8
use ReflectionClass;
9
use ReflectionException;
10
use ReflectionParameter;
11
use Yiisoft\Injector\Injector;
12
use Yiisoft\Router\CurrentRouteInterface;
13
use Yiisoft\Validator\ValidatorInterface;
14
15
final class RequestModelFactory
16
{
17
    private Injector $injector;
18
    private ValidatorInterface $validator;
19
    private CurrentRouteInterface $currentRoute;
20
21 16
    public function __construct(ValidatorInterface $validator, Injector $injector, CurrentRouteInterface $currentRoute)
22
    {
23 16
        $this->validator = $validator;
24 16
        $this->injector = $injector;
25 16
        $this->currentRoute = $currentRoute;
26 16
    }
27
28
    /**
29
     * @param ServerRequestInterface $request
30
     * @param array|ReflectionParameter[] $handlerParams
31
     *
32
     * @throws ReflectionException
33
     *
34
     * @return array
35
     */
36 10
    public function createInstances(ServerRequestInterface $request, array $handlerParams): array
37
    {
38 10
        $requestModelInstances = [];
39 10
        foreach ($this->getModelRequestClasses($handlerParams) as $modelClass) {
40 9
            $requestModelInstances[] = $this->processModel($request, $this->injector->make($modelClass));
41
        }
42
43 9
        return $requestModelInstances;
44
    }
45
46 9
    private function processModel(ServerRequestInterface $request, RequestModelInterface $model): RequestModelInterface
47
    {
48 9
        $requestData = $this->getRequestData($request);
49 9
        $model->setRequestData($requestData);
50 9
        if ($model instanceof ValidatableModelInterface) {
51 2
            $result = $this->validator->validate($model, $model->getRules());
52 2
            if (!$result->isValid()) {
53 1
                throw new RequestValidationException($result->getErrors());
54
            }
55
        }
56
57 8
        return $model;
58
    }
59
60
    /**
61
     * @param array|ReflectionParameter[] $handlerParams
62
     *
63
     * @return array
64
     */
65 10
    private function getModelRequestClasses(array $handlerParams): array
66
    {
67 10
        $modelClasses = [];
68 10
        foreach ($handlerParams as $param) {
69 10
            if ($this->paramsIsRequestModel($param)) {
70 9
                $modelClasses[] = $param->getType()->getName();
71
            }
72
        }
73
74 10
        return $modelClasses;
75
    }
76
77 10
    private function paramsIsRequestModel(ReflectionParameter $param): bool
78
    {
79 10
        if (!$param->hasType() || $param->getType()->isBuiltin()) {
80
            return false;
81
        }
82
83 10
        return (new ReflectionClass($param->getType()->getName()))->implementsInterface(RequestModelInterface::class);
0 ignored issues
show
Bug introduced by
The method getName() does not exist on ReflectionType. It seems like you code against a sub-type of ReflectionType such as ReflectionNamedType. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

83
        return (new ReflectionClass($param->getType()->/** @scrutinizer ignore-call */ getName()))->implementsInterface(RequestModelInterface::class);
Loading history...
84
    }
85
86 9
    private function getRequestData(ServerRequestInterface $request): array
87
    {
88
        return [
89 9
            'query' => $request->getQueryParams(),
90 9
            'body' => $request->getParsedBody(),
91 9
            'attributes' => $request->getAttributes(),
92 9
            'headers' => $request->getHeaders(),
93 9
            'files' => $request->getUploadedFiles(),
94 9
            'cookie' => $request->getCookieParams(),
95 9
            'router' => $this->currentRoute->getArguments(),
96
        ];
97
    }
98
}
99