GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( c475eb...086b9c )
by Patrique
01:15
created

ServerRequest::withUploadedFiles()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.6666
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Patoui\Router;
6
7
use InvalidArgumentException;
8
use Psr\Http\Message\ServerRequestInterface;
9
use Psr\Http\Message\StreamInterface;
10
use Psr\Http\Message\UploadedFileInterface;
11
use Psr\Http\Message\UriInterface;
12
13
class ServerRequest implements ServerRequestInterface
14
{
15
    /**
16
     * @var string Represent the HTTP version number (e.g., "1.1", "1.0")
17
     */
18
    private $version;
19
20
    /**
21
     * @var array Contains header by key and array.
22
     * e.g. ['content-type' => ['application/json']]
23
     */
24
    private $headers;
25
26
    /** @var StreamInterface */
27
    private $body;
28
29
    /** @var string */
30
    private $requestTarget;
31
32
    /** @var string */
33
    private $method;
34
35
    /** @var UriInterface */
36
    private $uri;
37
38
    /** @var array */
39
    private $serverParams;
40
41
    /** @var array */
42
    private $cookieParams;
43
44
    /** @var array */
45
    private $queryParams;
46
47
    /** @var array */
48
    private $uploadedFiles;
49
50
    /** @var null|array|object */
51
    private $parsedBody;
52
53
    public function __construct(
54
        string $version,
55
        array $headers,
56
        StreamInterface $body,
57
        string $requestTarget,
58
        string $method,
59
        UriInterface $uri,
60
        array $serverParams,
61
        array $cookieParams,
62
        array $queryParams,
63
        array $uploadedFiles
64
    ) {
65
        $this->validateProtocolVersion($version);
66
        $this->validateHeaders($headers);
67
        $this->validateMethod($method);
68
69
        $this->version = $version;
70
        $this->headers = $headers;
71
        $this->body = $body;
72
        $this->requestTarget = $requestTarget;
73
        $this->method = $method;
74
        $this->uri = $uri;
75
        $this->serverParams = $serverParams;
76
        $this->cookieParams = $cookieParams;
77
        $this->queryParams = $queryParams;
78
        $this->uploadedFiles = $uploadedFiles;
79
    }
80
81
    /**
82
     * Retrieves the HTTP protocol version as a string.
83
     *
84
     * The string MUST contain only the HTTP version number (e.g., "1.1", "1.0").
85
     *
86
     * @return string HTTP protocol version.
87
     */
88
    public function getProtocolVersion()
89
    {
90
        return $this->version;
91
    }
92
93
    /**
94
     * Return an instance with the specified HTTP protocol version.
95
     *
96
     * The version string MUST contain only the HTTP version number (e.g.,
97
     * "1.1", "1.0").
98
     *
99
     * This method MUST be implemented in such a way as to retain the
100
     * immutability of the message, and MUST return an instance that has the
101
     * new protocol version.
102
     *
103
     * @param  string  $version  HTTP protocol version
104
     * @return static
105
     */
106
    public function withProtocolVersion($version) : self
107
    {
108
        $this->validateProtocolVersion($version);
109
110
        $instance = clone $this;
111
        $instance->version = $version;
112
113
        return $instance;
114
    }
115
116
    /**
117
     * Verifies the protocol version.
118
     *
119
     * @throws InvalidArgumentException
120
     * @param  string  $version The version string MUST contain only the HTTP
121
     * version number (e.g., "1.1", "1.0").
122
     */
123
    private function validateProtocolVersion(string $version) : void
124
    {
125
        if (! in_array($version, ['1.1', '2.0'])) {
126
            throw new InvalidArgumentException("Invalid HTTP version: {$version}");
127
        }
128
    }
129
130
    /**
131
     * Retrieves all message header values.
132
     *
133
     * The keys represent the header name as it will be sent over the wire, and
134
     * each value is an array of strings associated with the header.
135
     *
136
     *     // Represent the headers as a string
137
     *     foreach ($message->getHeaders() as $name => $values) {
138
     *         echo $name . ": " . implode(", ", $values);
139
     *     }
140
     *
141
     *     // Emit headers iteratively:
142
     *     foreach ($message->getHeaders() as $name => $values) {
143
     *         foreach ($values as $value) {
144
     *             header(sprintf('%s: %s', $name, $value), false);
145
     *         }
146
     *     }
147
     *
148
     * While header names are not case-sensitive, getHeaders() will preserve the
149
     * exact case in which headers were originally specified.
150
     *
151
     * @return string[][] Returns an associative array of the message's headers. Each
152
     *     key MUST be a header name, and each value MUST be an array of strings
153
     *     for that header.
154
     */
155
    public function getHeaders()
156
    {
157
        return $this->headers;
158
    }
159
160
    /**
161
     * Checks if a header exists by the given case-insensitive name.
162
     *
163
     * @param  string  $name  Case-insensitive header field name.
164
     * @return bool Returns true if any header names match the given header
165
     *     name using a case-insensitive string comparison. Returns false if
166
     *     no matching header name is found in the message.
167
     */
168
    public function hasHeader($name)
169
    {
170
        return array_key_exists(
171
            mb_strtoupper($name),
172
            array_change_key_case($this->headers, CASE_UPPER)
173
        );
174
    }
175
176
    /**
177
     * Retrieves a message header value by the given case-insensitive name.
178
     *
179
     * This method returns an array of all the header values of the given
180
     * case-insensitive header name.
181
     *
182
     * If the header does not appear in the message, this method MUST return an
183
     * empty array.
184
     *
185
     * @param  string  $name  Case-insensitive header field name.
186
     * @return string[] An array of string values as provided for the given
187
     *    header. If the header does not appear in the message, this method MUST
188
     *    return an empty array.
189
     */
190
    public function getHeader($name)
191
    {
192
        $name = mb_strtoupper($name);
193
        $headers = array_change_key_case($this->headers, CASE_UPPER);
194
195
        if (array_key_exists($name, $headers) === false) {
196
            return [];
197
        }
198
199
        return $headers[$name];
200
    }
201
202
    /**
203
     * Retrieves a comma-separated string of the values for a single header.
204
     *
205
     * This method returns all of the header values of the given
206
     * case-insensitive header name as a string concatenated together using
207
     * a comma.
208
     *
209
     * NOTE: Not all header values may be appropriately represented using
210
     * comma concatenation. For such headers, use getHeader() instead
211
     * and supply your own delimiter when concatenating.
212
     *
213
     * If the header does not appear in the message, this method MUST return
214
     * an empty string.
215
     *
216
     * @param  string  $name  Case-insensitive header field name.
217
     * @return string A string of values as provided for the given header
218
     *    concatenated together using a comma. If the header does not appear in
219
     *    the message, this method MUST return an empty string.
220
     */
221
    public function getHeaderLine($name)
222
    {
223
        return implode(',', $this->getHeader($name));
224
    }
225
226
    /**
227
     * Return an instance with the provided value replacing the specified header.
228
     *
229
     * While header names are case-insensitive, the casing of the header will
230
     * be preserved by this function, and returned from getHeaders().
231
     *
232
     * This method MUST be implemented in such a way as to retain the
233
     * immutability of the message, and MUST return an instance that has the
234
     * new and/or updated header and value.
235
     *
236
     * @param  string  $name  Case-insensitive header field name.
237
     * @param  string|string[]  $value  Header value(s).
238
     * @return static
239
     * @throws \InvalidArgumentException for invalid header names or values.
240
     */
241
    public function withHeader($name, $value)
242
    {
243
        $newHeaders = array_merge($this->getHeaders(), [$name => [$value]]);
244
245
        $instance = clone $this;
246
        $instance->headers = $newHeaders;
247
248
        return $instance;
249
    }
250
251
    /**
252
     * Return an instance with the specified header appended with the given value.
253
     *
254
     * Existing values for the specified header will be maintained. The new
255
     * value(s) will be appended to the existing list. If the header did not
256
     * exist previously, it will be added.
257
     *
258
     * This method MUST be implemented in such a way as to retain the
259
     * immutability of the message, and MUST return an instance that has the
260
     * new header and/or value.
261
     *
262
     * @param  string  $name  Case-insensitive header field name to add.
263
     * @param  string|string[]  $value  Header value(s).
264
     * @return static
265
     * @throws \InvalidArgumentException for invalid header names or values.
266
     */
267
    public function withAddedHeader($name, $value)
268
    {
269
        $newHeaders = $this->getHeaders();
270
        $headerToUpdate = $this->getHeader($name);
271
        $headerToUpdate[] = $value;
272
        $newHeaders[$name] = $headerToUpdate;
273
274
        $instance = clone $this;
275
        $instance->headers = $newHeaders;
276
277
        return $instance;
278
    }
279
280
    /**
281
     * Return an instance without the specified header.
282
     *
283
     * Header resolution MUST be done without case-sensitivity.
284
     *
285
     * This method MUST be implemented in such a way as to retain the
286
     * immutability of the message, and MUST return an instance that removes
287
     * the named header.
288
     *
289
     * @param  string  $name  Case-insensitive header field name to remove.
290
     * @return static
291
     */
292
    public function withoutHeader($name)
293
    {
294
        $newHeaders = $this->getHeaders();
295
        unset($newHeaders[$name]);
296
297
        $instance = clone $this;
298
        $instance->headers = $newHeaders;
299
300
        return $instance;
301
    }
302
303
    /**
304
     * Verifies the headers are valid.
305
     *
306
     * @throws InvalidArgumentException
307
     * @param  array  $headers Headers for the incoming request
308
     */
309
    private function validateHeaders(array $headers) : void
310
    {
311
        $exceptionMessage = 'Invalid headers: '.json_encode($headers);
312
313
        if (empty($headers)) {
314
            return;
315
        }
316
317
        $headersWithArraysOnly = array_filter($headers, function ($header) {
318
            return is_array($header);
319
        });
320
321
        if (count($headers) !== count($headersWithArraysOnly)) {
322
            throw new InvalidArgumentException($exceptionMessage);
323
        }
324
325
        foreach ($headers as $key => $header) {
326
            $headerWithStringValuesOnly = array_filter($header, function ($headerValue) {
327
                return is_string($headerValue);
328
            });
329
330
            if (count($header) !== count($headerWithStringValuesOnly)) {
331
                throw new InvalidArgumentException($exceptionMessage);
332
            }
333
        }
334
    }
335
336
    /**
337
     * Gets the body of the message.
338
     *
339
     * @return StreamInterface Returns the body as a stream.
340
     */
341
    public function getBody()
342
    {
343
        return $this->body;
344
    }
345
346
    /**
347
     * Return an instance with the specified message body.
348
     *
349
     * The body MUST be a StreamInterface object.
350
     *
351
     * This method MUST be implemented in such a way as to retain the
352
     * immutability of the message, and MUST return a new instance that has the
353
     * new body stream.
354
     *
355
     * @param  StreamInterface  $body  Body.
356
     * @return static
357
     * @throws \InvalidArgumentException When the body is not valid.
358
     */
359
    public function withBody(StreamInterface $body)
360
    {
361
        $instance = clone $this;
362
        $instance->body = $body;
363
364
        return $instance;
365
    }
366
367
    /**
368
     * Retrieves the message's request target.
369
     *
370
     * Retrieves the message's request-target either as it will appear (for
371
     * clients), as it appeared at request (for servers), or as it was
372
     * specified for the instance (see withRequestTarget()).
373
     *
374
     * In most cases, this will be the origin-form of the composed URI,
375
     * unless a value was provided to the concrete implementation (see
376
     * withRequestTarget() below).
377
     *
378
     * If no URI is available, and no request-target has been specifically
379
     * provided, this method MUST return the string "/".
380
     *
381
     * @return string
382
     */
383
    public function getRequestTarget()
384
    {
385
        return $this->requestTarget;
386
    }
387
388
    /**
389
     * Return an instance with the specific request-target.
390
     *
391
     * If the request needs a non-origin-form request-target — e.g., for
392
     * specifying an absolute-form, authority-form, or asterisk-form —
393
     * this method may be used to create an instance with the specified
394
     * request-target, verbatim.
395
     *
396
     * This method MUST be implemented in such a way as to retain the
397
     * immutability of the message, and MUST return an instance that has the
398
     * changed request target.
399
     *
400
     * @link http://tools.ietf.org/html/rfc7230#section-5.3 (for the various
401
     *     request-target forms allowed in request messages)
402
     * @param  mixed  $requestTarget
403
     * @return static
404
     */
405
    public function withRequestTarget($requestTarget)
406
    {
407
        $instance = clone $this;
408
        $instance->requestTarget = (string) $requestTarget;
409
410
        return $instance;
411
    }
412
413
    /**
414
     * Verifies the HTTP method is valid.
415
     *
416
     * @throws InvalidArgumentException
417
     * @param  string  $method HTTP method for the incoming request
418
     */
419
    private function validateMethod(string $method) : void
420
    {
421
        if (! in_array(strtoupper($method), ['POST', 'GET', 'OPTIONS'])) {
422
            throw new InvalidArgumentException("Invalid HTTP method: {$method}");
423
        }
424
    }
425
426
    /**
427
     * Retrieves the HTTP method of the request.
428
     *
429
     * @return string Returns the request method.
430
     */
431
    public function getMethod()
432
    {
433
        return $this->method;
434
    }
435
436
    /**
437
     * Return an instance with the provided HTTP method.
438
     *
439
     * While HTTP method names are typically all uppercase characters, HTTP
440
     * method names are case-sensitive and thus implementations SHOULD NOT
441
     * modify the given string.
442
     *
443
     * This method MUST be implemented in such a way as to retain the
444
     * immutability of the message, and MUST return an instance that has the
445
     * changed request method.
446
     *
447
     * @param  string  $method  Case-sensitive method.
448
     * @return static
449
     * @throws \InvalidArgumentException for invalid HTTP methods.
450
     */
451
    public function withMethod($method)
452
    {
453
        $this->validateMethod($method);
454
455
        $instance = clone $this;
456
        $instance->method = $method;
457
458
        return $instance;
459
    }
460
461
    /**
462
     * Retrieves the URI instance.
463
     *
464
     * This method MUST return a UriInterface instance.
465
     *
466
     * @link http://tools.ietf.org/html/rfc3986#section-4.3
467
     * @return UriInterface Returns a UriInterface instance
468
     *     representing the URI of the request.
469
     */
470
    public function getUri()
471
    {
472
        return $this->uri;
473
    }
474
475
    /**
476
     * Returns an instance with the provided URI.
477
     *
478
     * This method MUST update the Host header of the returned request by
479
     * default if the URI contains a host component. If the URI does not
480
     * contain a host component, any pre-existing Host header MUST be carried
481
     * over to the returned request.
482
     *
483
     * You can opt-in to preserving the original state of the Host header by
484
     * setting `$preserveHost` to `true`. When `$preserveHost` is set to
485
     * `true`, this method interacts with the Host header in the following ways:
486
     *
487
     * - If the Host header is missing or empty, and the new URI contains
488
     *   a host component, this method MUST update the Host header in the returned
489
     *   request.
490
     * - If the Host header is missing or empty, and the new URI does not contain a
491
     *   host component, this method MUST NOT update the Host header in the returned
492
     *   request.
493
     * - If a Host header is present and non-empty, this method MUST NOT update
494
     *   the Host header in the returned request.
495
     *
496
     * This method MUST be implemented in such a way as to retain the
497
     * immutability of the message, and MUST return an instance that has the
498
     * new UriInterface instance.
499
     *
500
     * @link http://tools.ietf.org/html/rfc3986#section-4.3
501
     * @param  UriInterface  $uri  New request URI to use.
502
     * @param  bool  $preserveHost  Preserve the original state of the Host header.
503
     * @return static
504
     */
505
    public function withUri(UriInterface $uri, $preserveHost = false)
506
    {
507
        $headers = $this->getHeaders();
508
        $currentUriHost = $this->uri->getHost();
509
510
        if ($preserveHost && $currentUriHost) {
511
            $headers['HTTP_HOST'] = [$currentUriHost];
512
        }
513
514
        $instance = clone $this;
515
        $instance->headers = $headers;
516
        $instance->uri = $uri;
517
518
        return $instance;
519
    }
520
521
    /**
522
     * Retrieve server parameters.
523
     *
524
     * Retrieves data related to the incoming request environment,
525
     * typically derived from PHP's $_SERVER superglobal. The data IS NOT
526
     * REQUIRED to originate from $_SERVER.
527
     *
528
     * @return array
529
     */
530
    public function getServerParams()
531
    {
532
        return $this->serverParams;
533
    }
534
535
    /**
536
     * Retrieve cookies.
537
     *
538
     * Retrieves cookies sent by the client to the server.
539
     *
540
     * The data MUST be compatible with the structure of the $_COOKIE
541
     * superglobal.
542
     *
543
     * @return array
544
     */
545
    public function getCookieParams()
546
    {
547
        return $this->cookieParams;
548
    }
549
550
    /**
551
     * Return an instance with the specified cookies.
552
     *
553
     * The data IS NOT REQUIRED to come from the $_COOKIE superglobal, but MUST
554
     * be compatible with the structure of $_COOKIE. Typically, this data will
555
     * be injected at instantiation.
556
     *
557
     * This method MUST NOT update the related Cookie header of the request
558
     * instance, nor related values in the server params.
559
     *
560
     * This method MUST be implemented in such a way as to retain the
561
     * immutability of the message, and MUST return an instance that has the
562
     * updated cookie values.
563
     *
564
     * @param  array  $cookies  Array of key/value pairs representing cookies.
565
     * @return static
566
     */
567
    public function withCookieParams(array $cookies)
568
    {
569
        $instance = clone $this;
570
        $instance->cookieParams = $cookies;
571
572
        return $instance;
573
    }
574
575
    /**
576
     * Retrieve query string arguments.
577
     *
578
     * Retrieves the deserialized query string arguments, if any.
579
     *
580
     * Note: the query params might not be in sync with the URI or server
581
     * params. If you need to ensure you are only getting the original
582
     * values, you may need to parse the query string from `getUri()->getQuery()`
583
     * or from the `QUERY_STRING` server param.
584
     *
585
     * @return array
586
     */
587
    public function getQueryParams()
588
    {
589
        return $this->queryParams;
590
    }
591
592
    /**
593
     * Return an instance with the specified query string arguments.
594
     *
595
     * These values SHOULD remain immutable over the course of the incoming
596
     * request. They MAY be injected during instantiation, such as from PHP's
597
     * $_GET superglobal, or MAY be derived from some other value such as the
598
     * URI. In cases where the arguments are parsed from the URI, the data
599
     * MUST be compatible with what PHP's parse_str() would return for
600
     * purposes of how duplicate query parameters are handled, and how nested
601
     * sets are handled.
602
     *
603
     * Setting query string arguments MUST NOT change the URI stored by the
604
     * request, nor the values in the server params.
605
     *
606
     * This method MUST be implemented in such a way as to retain the
607
     * immutability of the message, and MUST return an instance that has the
608
     * updated query string arguments.
609
     *
610
     * @param  array  $query  Array of query string arguments, typically from
611
     *     $_GET.
612
     * @return static
613
     */
614
    public function withQueryParams(array $query)
615
    {
616
        $instance = clone $this;
617
        $instance->queryParams = array_merge($this->getQueryParams(), $query);
618
619
        return $instance;
620
    }
621
622
    /**
623
     * Retrieve normalized file upload data.
624
     *
625
     * This method returns upload metadata in a normalized tree, with each leaf
626
     * an instance of Psr\Http\Message\UploadedFileInterface.
627
     *
628
     * These values MAY be prepared from $_FILES or the message body during
629
     * instantiation, or MAY be injected via withUploadedFiles().
630
     *
631
     * @return array An array tree of UploadedFileInterface instances; an empty
632
     *     array MUST be returned if no data is present.
633
     */
634
    public function getUploadedFiles()
635
    {
636
        return $this->uploadedFiles;
637
    }
638
639
    /**
640
     * Create a new instance with the specified uploaded files.
641
     *
642
     * This method MUST be implemented in such a way as to retain the
643
     * immutability of the message, and MUST return an instance that has the
644
     * updated body parameters.
645
     *
646
     * @param  array  $uploadedFiles  An array tree of UploadedFileInterface instances.
647
     * @return static
648
     * @throws \InvalidArgumentException if an invalid structure is provided.
649
     */
650
    public function withUploadedFiles(array $uploadedFiles)
651
    {
652
        $filteredUploadedFiles = array_filter($uploadedFiles, function ($uploadedFile) {
653
            return $uploadedFile instanceof UploadedFileInterface;
654
        });
655
656
        if (count($filteredUploadedFiles) !== count($uploadedFiles)) {
657
            throw new InvalidArgumentException(
658
                'Must be an array with instances of '
659
                .UploadedFileInterface::class
660
            );
661
        }
662
663
        $instance = clone $this;
664
        $instance->uploadedFiles = $uploadedFiles;
665
666
        return $instance;
667
    }
668
669
    /**
670
     * Retrieve any parameters provided in the request body.
671
     *
672
     * If the request Content-Type is either application/x-www-form-urlencoded
673
     * or multipart/form-data, and the request method is POST, this method MUST
674
     * return the contents of $_POST.
675
     *
676
     * Otherwise, this method may return any results of deserializing
677
     * the request body content; as parsing returns structured content, the
678
     * potential types MUST be arrays or objects only. A null value indicates
679
     * the absence of body content.
680
     *
681
     * @return null|array|object The deserialized body parameters, if any.
682
     *     These will typically be an array or object.
683
     */
684
    public function getParsedBody()
685
    {
686
        $isPost = $this->isPostRequest();
687
688
        if ($isPost) {
689
            return $_POST;
690
        }
691
692
        return $this->parsedBody;
693
    }
694
695
    /**
696
     * Return an instance with the specified body parameters.
697
     *
698
     * These MAY be injected during instantiation.
699
     *
700
     * If the request Content-Type is either application/x-www-form-urlencoded
701
     * or multipart/form-data, and the request method is POST, use this method
702
     * ONLY to inject the contents of $_POST.
703
     *
704
     * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of
705
     * deserializing the request body content. Deserialization/parsing returns
706
     * structured data, and, as such, this method ONLY accepts arrays or objects,
707
     * or a null value if nothing was available to parse.
708
     *
709
     * As an example, if content negotiation determines that the request data
710
     * is a JSON payload, this method could be used to create a request
711
     * instance with the deserialized parameters.
712
     *
713
     * This method MUST be implemented in such a way as to retain the
714
     * immutability of the message, and MUST return an instance that has the
715
     * updated body parameters.
716
     *
717
     * @param  null|array|object  $data  The deserialized body data. This will
718
     *     typically be in an array or object.
719
     * @return static
720
     * @throws \InvalidArgumentException if an unsupported argument type is
721
     *     provided.
722
     */
723
    public function withParsedBody($data)
724
    {
725
        if (! is_null($data) && ! is_object($data) && ! is_array($data)) {
726
            throw new InvalidArgumentException(
727
                'Parsed body must be of type: null, array, or object'
728
            );
729
        }
730
731
        $data = (array) $data;
732
        $isPost = $this->isPostRequest();
733
        $instance = clone $this;
734
        $instance->parsedBody = array_merge((array) $this->getParsedBody(), $data);
735
736
        if ($isPost) {
737
            // TODO: identify potential risk with assigning values to the super global variable
738
            $_POST = array_merge($_POST, $data);
739
        }
740
741
        return $instance;
742
    }
743
744
    /**
745
     * Retrieve attributes derived from the request.
746
     *
747
     * The request "attributes" may be used to allow injection of any
748
     * parameters derived from the request: e.g., the results of path
749
     * match operations; the results of decrypting cookies; the results of
750
     * deserializing non-form-encoded message bodies; etc. Attributes
751
     * will be application and request specific, and CAN be mutable.
752
     *
753
     * @return array Attributes derived from the request.
754
     */
755
    public function getAttributes()
756
    {
757
        // TODO: Implement getAttributes() method.
758
    }
759
760
    /**
761
     * Retrieve a single derived request attribute.
762
     *
763
     * Retrieves a single derived request attribute as described in
764
     * getAttributes(). If the attribute has not been previously set, returns
765
     * the default value as provided.
766
     *
767
     * This method obviates the need for a hasAttribute() method, as it allows
768
     * specifying a default value to return if the attribute is not found.
769
     *
770
     * @param  string  $name  The attribute name.
771
     * @param  mixed  $default  Default value to return if the attribute does not exist.
772
     * @return mixed
773
     * @see getAttributes()
774
     */
775
    public function getAttribute($name, $default = null)
776
    {
777
        // TODO: Implement getAttribute() method.
778
    }
779
780
    /**
781
     * Return an instance with the specified derived request attribute.
782
     *
783
     * This method allows setting a single derived request attribute as
784
     * described in getAttributes().
785
     *
786
     * This method MUST be implemented in such a way as to retain the
787
     * immutability of the message, and MUST return an instance that has the
788
     * updated attribute.
789
     *
790
     * @param  string  $name  The attribute name.
791
     * @param  mixed  $value  The value of the attribute.
792
     * @return static
793
     * @see getAttributes()
794
     */
795
    public function withAttribute($name, $value)
796
    {
797
        // TODO: Implement withAttribute() method.
798
    }
799
800
    /**
801
     * Return an instance that removes the specified derived request attribute.
802
     *
803
     * This method allows removing a single derived request attribute as
804
     * described in getAttributes().
805
     *
806
     * This method MUST be implemented in such a way as to retain the
807
     * immutability of the message, and MUST return an instance that removes
808
     * the attribute.
809
     *
810
     * @param  string  $name  The attribute name.
811
     * @return static
812
     * @see getAttributes()
813
     */
814
    public function withoutAttribute($name)
815
    {
816
        // TODO: Implement withoutAttribute() method.
817
    }
818
819
    /**
820
     * Determines if the request is a POST request based on content type headers.
821
     * @return bool
822
     */
823
    private function isPostRequest() : bool
824
    {
825
        foreach ($this->getHeader('content-type') as $contentType) {
826
            if ($contentType === 'application/x-www-form-urlencoded' ||
827
                $contentType === 'multipart/form-data') {
828
                return true;
829
            }
830
        }
831
832
        return false;
833
    }
834
}
835