Completed
Push — b0.1.0 ( b9dc7d...d3207e )
by Sebastian
05:42
created

Request::validateHttpMethod()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 11
nc 2
nop 1
dl 0
loc 16
ccs 0
cts 15
cp 0
crap 6
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Linna Http Message.
5
 *
6
 * @author Sebastian Rapetti <[email protected]>
7
 * @copyright (c) 2019, Sebastian Rapetti
8
 * @license http://opensource.org/licenses/MIT MIT License
9
 */
10
declare(strict_types=1);
11
12
namespace Linna\Http\Message;
13
14
use InvalidArgumentException;
15
use Psr\Http\Message\RequestInterface;
16
use Psr\Http\Message\UriInterface;
17
18
/**
19
 * PSR-7 Request implementation.
20
 */
21
class Request extends Message implements RequestInterface
22
{
23
    /**
24
     * @var string Request HTTP method (GET, POST, PUT.....).
25
     */
26
    protected $method = '';
27
28
    /**
29
     * @var string Request target.
30
     */
31
    protected $target = '';
32
33
    /**
34
     * @var UriInterface Request uri.
35
     */
36
    protected $uri;
37
38
    /**
39
     * Class Constructor.
40
     *
41
     * @param UriInterface $uri
42
     * @param string       $method
43
     * @param string       $body
44
     * @param array        $headers
45
     */
46
    public function __construct(UriInterface $uri, string $method = 'GET', string $body = 'php://memory', array $headers = [])
47
    {
48
        //force __toString method
49
        $this->uri = $uri;
50
51
        //check for valide method
52
        $this->method = $this->validateHttpMethod(strtoupper($method));
53
54
        parent::$body = new Stream($body, 'wb+');
55
        parent::$headers = $headers;
56
    }
57
58
    /**
59
     * Validate HTTP Method
60
     *
61
     * @param string $method HTTP Method
62
     *
63
     * @return string
64
     *
65
     * @throws InvalidArgumentException if passed method is not an HTTP valid method.
66
     */
67
    private function validateHttpMethod(string $method): string
68
    {
69
        if (in_array($method, [
70
            'GET',
71
            'HEAD',
72
            'POST',
73
            'PUT',
74
            'DELETE',
75
            'CONNECT',
76
            'OPTIONS',
77
            'TRACE'
78
            ])) {
79
            return $method;
80
        }
81
82
        throw new InvalidArgumentException('Invalid HTTP method.');
83
    }
84
85
    /**
86
     * Retrieves the message's request target.
87
     *
88
     * Retrieves the message's request-target either as it will appear (for
89
     * clients), as it appeared at request (for servers), or as it was
90
     * specified for the instance (see withRequestTarget()).
91
     *
92
     * In most cases, this will be the origin-form of the composed URI,
93
     * unless a value was provided to the concrete implementation (see
94
     * withRequestTarget() below).
95
     *
96
     * If no URI is available, and no request-target has been specifically
97
     * provided, this method MUST return the string "/".
98
     *
99
     * @return string
100
     */
101
    public function getRequestTarget(): string
102
    {
103
        if (!empty($this->target)) {
104
            return $this->target;
105
        }
106
107
        $target = $this->uri->getPath();
108
109
        if ($this->uri->getQuery()) {
110
            $target .= '?' . $this->uri->getQuery();
111
        }
112
113
        if (empty($target)) {
114
            return '/';
115
        }
116
117
        return $target;
118
    }
119
120
    /**
121
     * Return an instance with the specific request-target.
122
     *
123
     * If the request needs a non-origin-form request-target — e.g., for
124
     * specifying an absolute-form, authority-form, or asterisk-form —
125
     * this method may be used to create an instance with the specified
126
     * request-target, verbatim.
127
     *
128
     * This method MUST be implemented in such a way as to retain the
129
     * immutability of the message, and MUST return an instance that has the
130
     * changed request target.
131
     *
132
     * @link http://tools.ietf.org/html/rfc7230#section-5.3 (for the various
133
     *       request-target forms allowed in request messages)
134
     *
135
     * @param mixed $requestTarget
136
     *
137
     * @return static
138
     */
139
    public function withRequestTarget(string $requestTarget): RequestInterface
140
    {
141
        $new = clone $this;
142
        $new->target = $requestTarget;
143
144
        return $new;
145
    }
146
147
    /**
148
     * Retrieves the HTTP method of the request.
149
     *
150
     * @return string Returns the request method.
151
     */
152
    public function getMethod(): string
153
    {
154
        return $this->method;
155
    }
156
157
    /**
158
     * Return an instance with the provided HTTP method.
159
     *
160
     * While HTTP method names are typically all uppercase characters, HTTP
161
     * method names are case-sensitive and thus implementations SHOULD NOT
162
     * modify the given string.
163
     *
164
     * This method MUST be implemented in such a way as to retain the
165
     * immutability of the message, and MUST return an instance that has the
166
     * changed request method.
167
     *
168
     * @param string $method Case-sensitive method.
169
     *
170
     * @throws InvalidArgumentException for invalid HTTP methods.
171
     *
172
     * @return static
173
     */
174
    public function withMethod(string $method): RequestInterface
175
    {
176
        $new = clone $this;
177
        $new->method = $this->validateHttpMethod(strtoupper($method));
178
179
        return $new;
180
    }
181
182
    /**
183
     * Retrieves the URI instance.
184
     *
185
     * This method MUST return a UriInterface instance.
186
     *
187
     * @link http://tools.ietf.org/html/rfc3986#section-4.3
188
     *
189
     * @return UriInterface Returns a UriInterface instance
190
     *                      representing the URI of the request.
191
     */
192
    public function getUri(): UriInterface
193
    {
194
        return $this->uri;
195
    }
196
197
    /**
198
     * Returns an instance with the provided URI.
199
     *
200
     * This method MUST update the Host header of the returned request by
201
     * default if the URI contains a host component. If the URI does not
202
     * contain a host component, any pre-existing Host header MUST be carried
203
     * over to the returned request.
204
     *
205
     * You can opt-in to preserving the original state of the Host header by
206
     * setting `$preserveHost` to `true`. When `$preserveHost` is set to
207
     * `true`, this method interacts with the Host header in the following ways:
208
     *
209
     * - If the Host header is missing or empty, and the new URI contains
210
     *   a host component, this method MUST update the Host header in the returned
211
     *   request.
212
     * - If the Host header is missing or empty, and the new URI does not contain a
213
     *   host component, this method MUST NOT update the Host header in the returned
214
     *   request.
215
     * - If a Host header is present and non-empty, this method MUST NOT update
216
     *   the Host header in the returned request.
217
     *
218
     * This method MUST be implemented in such a way as to retain the
219
     * immutability of the message, and MUST return an instance that has the
220
     * new UriInterface instance.
221
     *
222
     * @link http://tools.ietf.org/html/rfc3986#section-4.3
223
     *
224
     * @param UriInterface $uri          New request URI to use.
225
     * @param bool         $preserveHost Preserve the original state of the Host header.
226
     *
227
     * @return static
228
     */
229
    public function withUri(UriInterface $uri, bool $preserveHost = false): RequestInterface
230
    {
231
    }
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return Psr\Http\Message\RequestInterface. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
232
}
233