Passed
Push — master ( 29521a...b34be3 )
by Alexander
24:53 queued 23:31
created

RequestModelFactory::processModel()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 5
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 9
ccs 6
cts 6
cp 1
crap 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\RequestModel;
6
7
use Psr\Http\Message\ServerRequestInterface;
8
use ReflectionParameter;
9
use Yiisoft\Injector\Injector;
10
use ReflectionException;
11
use ReflectionClass;
12
13
final class RequestModelFactory
14
{
15
    private Injector $injector;
16
    private RequestModelValidator $validator;
17
18 14
    public function __construct(RequestModelValidator $validator, Injector $injector)
19
    {
20 14
        $this->validator = $validator;
21 14
        $this->injector = $injector;
22 14
    }
23
24
    /**
25
     * @param ServerRequestInterface $request
26
     * @param array|ReflectionParameter[] $handlerParams
27
     * @return array
28
     * @throws ReflectionException
29
     */
30 8
    public function createInstances(ServerRequestInterface $request, array $handlerParams): array
31
    {
32 8
        $requestModelInstances = [];
33 8
        foreach ($this->getModelRequestClasses($handlerParams) as $modelClass) {
34 7
            $requestModelInstances[] = $this->processModel($request, $this->injector->make($modelClass));
35
        }
36
37 7
        return $requestModelInstances;
38
    }
39
40 7
    private function processModel(ServerRequestInterface $request, RequestModelInterface $model): RequestModelInterface
41
    {
42 7
        $requestData = $this->getRequestData($request);
43 7
        $model->setRequestData($requestData);
44 7
        if ($model instanceof ValidatableModelInterface) {
45 2
            $this->validateRequest($model, $requestData);
46
        }
47
48 6
        return $model;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $model could return the type Yiisoft\RequestModel\ValidatableModelInterface which is incompatible with the type-hinted return Yiisoft\RequestModel\RequestModelInterface. Consider adding an additional type-check to rule them out.
Loading history...
49
    }
50
51
    /**
52
     * @param array|ReflectionParameter[] $handlerParams
53
     * @return array
54
     */
55 8
    private function getModelRequestClasses(array $handlerParams): array
56
    {
57 8
        $modelClasses = [];
58 8
        foreach ($handlerParams as $param) {
59 8
            if ($this->paramsIsRequestModel($param)) {
60 7
                $modelClasses[] = $param->getType()->getName();
61
            }
62
        }
63
64 8
        return $modelClasses;
65
    }
66
67 8
    private function paramsIsRequestModel(ReflectionParameter $param): bool
68
    {
69 8
        if (!$param->hasType() || $param->getType()->isBuiltin()) {
70
            return false;
71
        }
72
73 8
        return (new ReflectionClass($param->getType()->getName()))->implementsInterface(RequestModelInterface::class);
74
    }
75
76 7
    private function getRequestData(ServerRequestInterface $request): array
77
    {
78
        return [
79 7
            'query' => $request->getQueryParams(),
80 7
            'body' => $request->getParsedBody(),
81 7
            'attributes' => $request->getAttributes(),
82 7
            'headers' => $request->getHeaders(),
83 7
            'files' => $request->getUploadedFiles(),
84 7
            'cookie' => $request->getCookieParams()
85
        ];
86
    }
87
88 2
    private function validateRequest(ValidatableModelInterface $model, array $requestData): void
89
    {
90 2
        $errors = $this->validator->validate($requestData, $model->getRules());
91 2
        if (!empty($errors)) {
92 1
            throw new RequestValidationException($errors);
93
        }
94 1
    }
95
}
96