Passed
Push — master ( e0508e...1ccf58 )
by Alexander
02:12
created

RequestModelFactory   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 78
Duplicated Lines 0 %

Test Coverage

Coverage 97.06%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 13
eloc 31
c 1
b 0
f 0
dl 0
loc 78
ccs 33
cts 34
cp 0.9706
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A createInstances() 0 8 2
A paramsIsRequestModel() 0 7 3
A processModel() 0 12 3
A getRequestData() 0 9 1
A getModelRequestClasses() 0 10 3
A __construct() 0 4 1
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\Validator\ValidatorInterface;
13
14
final class RequestModelFactory
15
{
16
    private Injector $injector;
17
    private ValidatorInterface $validator;
18
19 15
    public function __construct(ValidatorInterface $validator, Injector $injector)
20
    {
21 15
        $this->validator = $validator;
22 15
        $this->injector = $injector;
23 15
    }
24
25
    /**
26
     * @param ServerRequestInterface $request
27
     * @param array|ReflectionParameter[] $handlerParams
28
     *
29
     * @throws ReflectionException
30
     *
31
     * @return array
32
     */
33 9
    public function createInstances(ServerRequestInterface $request, array $handlerParams): array
34
    {
35 9
        $requestModelInstances = [];
36 9
        foreach ($this->getModelRequestClasses($handlerParams) as $modelClass) {
37 8
            $requestModelInstances[] = $this->processModel($request, $this->injector->make($modelClass));
38
        }
39
40 8
        return $requestModelInstances;
41
    }
42
43 8
    private function processModel(ServerRequestInterface $request, RequestModelInterface $model): RequestModelInterface
44
    {
45 8
        $requestData = $this->getRequestData($request);
46 8
        $model->setRequestData($requestData);
47 8
        if ($model instanceof ValidatableModelInterface) {
48 2
            $result = $this->validator->validate($model, $model->getRules());
49 2
            if (!$result->isValid()) {
50 1
                throw new RequestValidationException($result->getErrors());
51
            }
52
        }
53
54 7
        return $model;
55
    }
56
57
    /**
58
     * @param array|ReflectionParameter[] $handlerParams
59
     *
60
     * @return array
61
     */
62 9
    private function getModelRequestClasses(array $handlerParams): array
63
    {
64 9
        $modelClasses = [];
65 9
        foreach ($handlerParams as $param) {
66 9
            if ($this->paramsIsRequestModel($param)) {
67 8
                $modelClasses[] = $param->getType()->getName();
68
            }
69
        }
70
71 9
        return $modelClasses;
72
    }
73
74 9
    private function paramsIsRequestModel(ReflectionParameter $param): bool
75
    {
76 9
        if (!$param->hasType() || $param->getType()->isBuiltin()) {
77
            return false;
78
        }
79
80 9
        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

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