RequestDeserializationMiddleware::shouldValidate()   C
last analyzed

Complexity

Conditions 7
Paths 5

Size

Total Lines 34
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 34
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 18
nc 5
nop 1
1
<?php
2
3
namespace Realshadow\RequestDeserializer\Http\Middleware;
4
5
use Dingo\Api\Http\Request;
6
use Realshadow\RequestDeserializer\Contracts\RequestInterface;
7
use Realshadow\RequestDeserializer\Http\Request\RequestHandler;
8
use Closure;
9
10
11
/**
12
 * Class RequestDeserializationMiddleware
13
 *
14
 * @package Realshadow\RequestDeserializer\Http\Middleware
15
 * @author Lukáš Homza <[email protected]>
16
 */
17
class RequestDeserializationMiddleware
18
{
19
20
    /**
21
     * Request handler for deserialization of incoming requests
22
     *
23
     * @var RequestHandler $requestHandler
24
     */
25
    private $requestHandler;
26
27
    /**
28
     * Request entity class
29
     *
30
     * @var null|string $requestEntity
31
     */
32
    private $requestEntity;
33
34
    /**
35
     * Argument position in controllers arguments
36
     *
37
     * @var int $argumentPosition
38
     */
39
    private $argumentPosition = 0;
40
41
    /**
42
     * Determine matched controller and action from request
43
     *
44
     * @param Request|\Illuminate\Http\Request $request
45
     *
46
     * @return array
47
     */
48
    private function parseMatchedRoute(Request $request)
49
    {
50
        $action = $request->route()->getAction()['uses'];
51
52
        return explode('@', $action instanceof \Closure ? '@' : $action);
53
    }
54
55
    /**
56
     * @param Request|\Illuminate\Http\Request $request
57
     *
58
     * @return bool
59
     * @throws \ReflectionException
60
     */
61
    private function shouldValidate(Request $request)
62
    {
63
        $shouldValidate = false;
64
65
        list($controller, $action) = $this->parseMatchedRoute($request);
66
67
        if ($controller && $action) {
68
            $reflection = new \ReflectionMethod($controller, $action);
69
            foreach ($reflection->getParameters() AS $position => $param) {
70
                if ($param->getClass() === null) {
71
                    continue;
72
                }
73
74
                # -- requests have to implement RequestInterface
75
                if (in_array(RequestInterface::class, $param->getClass()->getInterfaceNames(), true)) {
76
                    if ($param->getClass()->isInterface()) {
77
                        $this->requestEntity = get_class(
78
                            app($param->getClass()->getName())
79
                        );
80
                    } else {
81
                        $this->requestEntity = $param->getClass()->getName();
82
                    }
83
84
                    $this->argumentPosition = $position;
85
86
                    $shouldValidate = true;
87
88
                    break;
89
                }
90
            }
91
        }
92
93
        return $shouldValidate;
94
    }
95
96
    /**
97
     * RequestDeserializationMiddleware constructor.
98
     *
99
     * @param RequestHandler $requestHandler
100
     */
101
    public function __construct(RequestHandler $requestHandler)
102
    {
103
        $this->requestHandler = $requestHandler;
104
    }
105
106
    /**
107
     * Handle an incoming request.
108
     *
109
     * @param \Illuminate\Http\Request $request
110
     * @param \Closure $next
111
     *
112
     * @return mixed
113
     * @throws \ReflectionException
114
     *
115
     * @throws \LogicException
116
     * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
117
     * @throws \Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException
118
     */
119
    public function handle($request, Closure $next)
120
    {
121
        if ( ! $this->shouldValidate($request)) {
0 ignored issues
show
Compatibility introduced by
$request of type object<Illuminate\Http\Request> is not a sub-type of object<Dingo\Api\Http\Request>. It seems like you assume a child class of the class Illuminate\Http\Request to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
122
            return $next($request);
123
        }
124
125
        $this->requestHandler->setArgumentPosition($this->argumentPosition);
126
127
        if ($request->method() === Request::METHOD_GET) {
128
            $this->requestHandler->hydrate($this->requestEntity, $request->query->all());
129
        } else {
130
            $this->requestHandler->deserialize($this->requestEntity, $request->getContent());
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, Realshadow\RequestDeseri...tHandler::deserialize() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
131
        }
132
133
        return $next($request);
134
    }
135
136
}
137