Passed
Pull Request — master (#1)
by
unknown
18:34 queued 03:37
created

RequestModelFactory::getRequestData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
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
12
final class RequestModelFactory
13
{
14
    private Injector $injector;
15
    private RequestModelValidator $validator;
16
17
    public function __construct(RequestModelValidator $validator, Injector $injector)
18
    {
19
        $this->validator = $validator;
20
        $this->injector = $injector;
21
    }
22
23
    /**
24
     * @param ServerRequestInterface $request
25
     * @param array|ReflectionParameter[] $handlerParams
26
     * @return array
27
     * @throws ReflectionException
28
     */
29
    public function createInstances(ServerRequestInterface $request, array $handlerParams): array
30
    {
31
        $requestModelInstances = [];
32
        foreach ($this->getModelRequestClasses($handlerParams) as $modelClass) {
33
            $requestModelInstances[] = $this->processModel($request, $this->injector->make($modelClass));
34
        }
35
36
        return $requestModelInstances;
37
    }
38
39
    private function processModel(ServerRequestInterface $request, RequestModelInterface $model): RequestModelInterface
40
    {
41
        $requestData = $this->getRequestData($request);
42
        $model->setRequestData($requestData);
43
        if ($model instanceof ValidatableModelInterface) {
44
            $this->validateRequest($model, $requestData);
45
        }
46
47
        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...
48
    }
49
50
    /**
51
     * @param array|ReflectionParameter[] $handlerParams
52
     * @return array
53
     */
54
    private function getModelRequestClasses(array $handlerParams): array
55
    {
56
        $modelClasses = [];
57
        foreach ($handlerParams as $param) {
58
            if ($this->paramsIsRequestModel($param)) {
59
                $modelClasses[] = $param->getClass()->getName();
60
            }
61
        }
62
63
        return $modelClasses;
64
    }
65
66
    private function paramsIsRequestModel(ReflectionParameter $param): bool
67
    {
68
        return $param->getClass()->implementsInterface(RequestModelInterface::class);
69
    }
70
71
    private function getRequestData(ServerRequestInterface $request): array
72
    {
73
        return [
74
            'query' => $request->getQueryParams(),
75
            'body' => $request->getParsedBody(),
76
            'attributes' => $request->getAttributes(),
77
            'headers' => $request->getHeaders(),
78
            'files' => $request->getUploadedFiles(),
79
            'cookie' => $request->getCookieParams()
80
        ];
81
    }
82
83
    private function validateRequest(ValidatableModelInterface $model, array $requestData): void
84
    {
85
        $errors = $this->validator->validate($requestData, $model->getRules());
86
        if (!empty($errors)) {
87
            throw new RequestValidationException($errors);
88
        }
89
    }
90
}
91