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 — 3.x ( eaee12...768a94 )
by
unknown
19s
created

Response::isBadRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
/**
3
 * Slim Framework (https://slimframework.com)
4
 *
5
 * @link      https://github.com/slimphp/Slim
6
 * @copyright Copyright (c) 2011-2017 Josh Lockhart
7
 * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
8
 */
9
namespace Slim\Http;
10
11
use InvalidArgumentException;
12
use Psr\Http\Message\ResponseInterface;
13
use Psr\Http\Message\StreamInterface;
14
use Psr\Http\Message\UriInterface;
15
use Slim\Interfaces\Http\HeadersInterface;
16
17
/**
18
 * Response
19
 *
20
 * This class represents an HTTP response. It manages
21
 * the response status, headers, and body
22
 * according to the PSR-7 standard.
23
 *
24
 * @link https://github.com/php-fig/http-message/blob/master/src/MessageInterface.php
25
 * @link https://github.com/php-fig/http-message/blob/master/src/ResponseInterface.php
26
 */
27
class Response extends Message implements ResponseInterface
28
{
29
    /**
30
     * Status code
31
     *
32
     * @var int
33
     */
34
    protected $status = StatusCode::HTTP_OK;
35
36
    /**
37
     * Reason phrase
38
     *
39
     * @var string
40
     */
41
    protected $reasonPhrase = '';
42
43
    /**
44
     * Status codes and reason phrases
45
     *
46
     * @var array
47
     */
48
    protected static $messages = [
49
        //Informational 1xx
50
        StatusCode::HTTP_CONTINUE => 'Continue',
51
        StatusCode::HTTP_SWITCHING_PROTOCOLS => 'Switching Protocols',
52
        StatusCode::HTTP_PROCESSING => 'Processing',
53
        //Successful 2xx
54
        StatusCode::HTTP_OK => 'OK',
55
        StatusCode::HTTP_CREATED => 'Created',
56
        StatusCode::HTTP_ACCEPTED => 'Accepted',
57
        StatusCode::HTTP_NONAUTHORITATIVE_INFORMATION => 'Non-Authoritative Information',
58
        StatusCode::HTTP_NO_CONTENT => 'No Content',
59
        StatusCode::HTTP_RESET_CONTENT => 'Reset Content',
60
        StatusCode::HTTP_PARTIAL_CONTENT => 'Partial Content',
61
        StatusCode::HTTP_MULTI_STATUS => 'Multi-Status',
62
        StatusCode::HTTP_ALREADY_REPORTED => 'Already Reported',
63
        StatusCode::HTTP_IM_USED => 'IM Used',
64
        //Redirection 3xx
65
        StatusCode::HTTP_MULTIPLE_CHOICES => 'Multiple Choices',
66
        StatusCode::HTTP_MOVED_PERMANENTLY => 'Moved Permanently',
67
        StatusCode::HTTP_FOUND => 'Found',
68
        StatusCode::HTTP_SEE_OTHER => 'See Other',
69
        StatusCode::HTTP_NOT_MODIFIED => 'Not Modified',
70
        StatusCode::HTTP_USE_PROXY => 'Use Proxy',
71
        StatusCode::HTTP_UNUSED => '(Unused)',
72
        StatusCode::HTTP_TEMPORARY_REDIRECT => 'Temporary Redirect',
73
        StatusCode::HTTP_PERMANENT_REDIRECT => 'Permanent Redirect',
74
        //Client Error 4xx
75
        StatusCode::HTTP_BAD_REQUEST => 'Bad Request',
76
        StatusCode::HTTP_UNAUTHORIZED => 'Unauthorized',
77
        StatusCode::HTTP_PAYMENT_REQUIRED => 'Payment Required',
78
        StatusCode::HTTP_FORBIDDEN => 'Forbidden',
79
        StatusCode::HTTP_NOT_FOUND => 'Not Found',
80
        StatusCode::HTTP_METHOD_NOT_ALLOWED => 'Method Not Allowed',
81
        StatusCode::HTTP_NOT_ACCEPTABLE => 'Not Acceptable',
82
        StatusCode::HTTP_PROXY_AUTHENTICATION_REQUIRED => 'Proxy Authentication Required',
83
        StatusCode::HTTP_REQUEST_TIMEOUT => 'Request Timeout',
84
        StatusCode::HTTP_CONFLICT => 'Conflict',
85
        StatusCode::HTTP_GONE => 'Gone',
86
        StatusCode::HTTP_LENGTH_REQUIRED => 'Length Required',
87
        StatusCode::HTTP_PRECONDITION_FAILED => 'Precondition Failed',
88
        StatusCode::HTTP_REQUEST_ENTITY_TOO_LARGE => 'Request Entity Too Large',
89
        StatusCode::HTTP_REQUEST_URI_TOO_LONG => 'Request-URI Too Long',
90
        StatusCode::HTTP_UNSUPPORTED_MEDIA_TYPE => 'Unsupported Media Type',
91
        StatusCode::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE => 'Requested Range Not Satisfiable',
92
        StatusCode::HTTP_EXPECTATION_FAILED => 'Expectation Failed',
93
        StatusCode::HTTP_IM_A_TEAPOT => 'I\'m a teapot',
94
        StatusCode::HTTP_MISDIRECTED_REQUEST => 'Misdirected Request',
95
        StatusCode::HTTP_UNPROCESSABLE_ENTITY => 'Unprocessable Entity',
96
        StatusCode::HTTP_LOCKED => 'Locked',
97
        StatusCode::HTTP_FAILED_DEPENDENCY => 'Failed Dependency',
98
        StatusCode::HTTP_UPGRADE_REQUIRED => 'Upgrade Required',
99
        StatusCode::HTTP_PRECONDITION_REQUIRED => 'Precondition Required',
100
        StatusCode::HTTP_TOO_MANY_REQUESTS => 'Too Many Requests',
101
        StatusCode::HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE => 'Request Header Fields Too Large',
102
        StatusCode::HTTP_CONNECTION_CLOSED_WITHOUT_RESPONSE => 'Connection Closed Without Response',
103
        StatusCode::HTTP_UNAVAILABLE_FOR_LEGAL_REASONS => 'Unavailable For Legal Reasons',
104
        StatusCode::HTTP_CLIENT_CLOSED_REQUEST => 'Client Closed Request',
105
        //Server Error 5xx
106
        StatusCode::HTTP_INTERNAL_SERVER_ERROR => 'Internal Server Error',
107
        StatusCode::HTTP_NOT_IMPLEMENTED => 'Not Implemented',
108
        StatusCode::HTTP_BAD_GATEWAY => 'Bad Gateway',
109
        StatusCode::HTTP_SERVICE_UNAVAILABLE => 'Service Unavailable',
110
        StatusCode::HTTP_GATEWAY_TIMEOUT => 'Gateway Timeout',
111
        StatusCode::HTTP_VERSION_NOT_SUPPORTED => 'HTTP Version Not Supported',
112
        StatusCode::HTTP_VARIANT_ALSO_NEGOTIATES => 'Variant Also Negotiates',
113
        StatusCode::HTTP_INSUFFICIENT_STORAGE => 'Insufficient Storage',
114
        StatusCode::HTTP_LOOP_DETECTED => 'Loop Detected',
115
        StatusCode::HTTP_NOT_EXTENDED => 'Not Extended',
116
        StatusCode::HTTP_NETWORK_AUTHENTICATION_REQUIRED => 'Network Authentication Required',
117
        StatusCode::HTTP_NETWORK_CONNECTION_TIMEOUT_ERROR => 'Network Connect Timeout Error',
118
    ];
119
120
    /**
121
     * EOL characters used for HTTP response.
122
     *
123
     * @var string
124
     */
125
    const EOL = "\r\n";
126
127
    /**
128
     * Create new HTTP response.
129
     *
130
     * @param int                   $status  The response status code.
131
     * @param HeadersInterface|null $headers The response headers.
132
     * @param StreamInterface|null  $body    The response body.
133
     */
134
    public function __construct(
135
        $status = StatusCode::HTTP_OK,
136
        HeadersInterface $headers = null,
137
        StreamInterface $body = null
138
    ) {
139
        $this->status = $this->filterStatus($status);
140
        $this->headers = $headers ? $headers : new Headers();
141
        $this->body = $body ? $body : new Body(fopen('php://temp', 'r+'));
142
    }
143
144
    /**
145
     * This method is applied to the cloned object
146
     * after PHP performs an initial shallow-copy. This
147
     * method completes a deep-copy by creating new objects
148
     * for the cloned object's internal reference pointers.
149
     */
150
    public function __clone()
151
    {
152
        $this->headers = clone $this->headers;
153
    }
154
155
    /*******************************************************************************
156
     * Status
157
     ******************************************************************************/
158
159
    /**
160
     * Gets the response status code.
161
     *
162
     * The status code is a 3-digit integer result code of the server's attempt
163
     * to understand and satisfy the request.
164
     *
165
     * @return int Status code.
166
     */
167
    public function getStatusCode()
168
    {
169
        return $this->status;
170
    }
171
172
    /**
173
     * Return an instance with the specified status code and, optionally, reason phrase.
174
     *
175
     * If no reason phrase is specified, implementations MAY choose to default
176
     * to the RFC 7231 or IANA recommended reason phrase for the response's
177
     * status code.
178
     *
179
     * This method MUST be implemented in such a way as to retain the
180
     * immutability of the message, and MUST return an instance that has the
181
     * updated status and reason phrase.
182
     *
183
     * @link http://tools.ietf.org/html/rfc7231#section-6
184
     * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
185
     * @param int $code The 3-digit integer result code to set.
186
     * @param string $reasonPhrase The reason phrase to use with the
187
     *     provided status code; if none is provided, implementations MAY
188
     *     use the defaults as suggested in the HTTP specification.
189
     * @return static
190
     * @throws \InvalidArgumentException For invalid status code arguments.
191
     */
192
    public function withStatus($code, $reasonPhrase = '')
193
    {
194
        $code = $this->filterStatus($code);
195
196
        if (!is_string($reasonPhrase) && !method_exists($reasonPhrase, '__toString')) {
197
            throw new InvalidArgumentException('ReasonPhrase must be a string');
198
        }
199
200
        $clone = clone $this;
201
        $clone->status = $code;
202
        if ($reasonPhrase === '' && isset(static::$messages[$code])) {
203
            $reasonPhrase = static::$messages[$code];
204
        }
205
206
        if ($reasonPhrase === '') {
207
            throw new InvalidArgumentException('ReasonPhrase must be supplied for this code');
208
        }
209
210
        $clone->reasonPhrase = $reasonPhrase;
211
212
        return $clone;
213
    }
214
215
    /**
216
     * Filter HTTP status code.
217
     *
218
     * @param  int $status HTTP status code.
219
     * @return int
220
     * @throws \InvalidArgumentException If an invalid HTTP status code is provided.
221
     */
222
    protected function filterStatus($status)
223
    {
224
        if (!is_integer($status) ||
225
            $status<StatusCode::HTTP_CONTINUE ||
226
            $status>StatusCode::HTTP_NETWORK_CONNECTION_TIMEOUT_ERROR
227
        ) {
228
            throw new InvalidArgumentException('Invalid HTTP status code');
229
        }
230
231
        return $status;
232
    }
233
234
    /**
235
     * Gets the response reason phrase associated with the status code.
236
     *
237
     * Because a reason phrase is not a required element in a response
238
     * status line, the reason phrase value MAY be null. Implementations MAY
239
     * choose to return the default RFC 7231 recommended reason phrase (or those
240
     * listed in the IANA HTTP Status Code Registry) for the response's
241
     * status code.
242
     *
243
     * @link http://tools.ietf.org/html/rfc7231#section-6
244
     * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
245
     * @return string Reason phrase; must return an empty string if none present.
246
     */
247
    public function getReasonPhrase()
248
    {
249
        if ($this->reasonPhrase) {
250
            return $this->reasonPhrase;
251
        }
252
        if (isset(static::$messages[$this->status])) {
253
            return static::$messages[$this->status];
254
        }
255
        return '';
256
    }
257
258
    /*******************************************************************************
259
     * Headers
260
     ******************************************************************************/
261
262
    /**
263
     * Return an instance with the provided value replacing the specified header.
264
     *
265
     * If a Location header is set and the status code is 200, then set the status
266
     * code to 302 to mimic what PHP does. See https://github.com/slimphp/Slim/issues/1730
267
     *
268
     * @param string $name Case-insensitive header field name.
269
     * @param string|string[] $value Header value(s).
270
     * @return static
271
     * @throws \InvalidArgumentException for invalid header names or values.
272
     */
273
    public function withHeader($name, $value)
274
    {
275
        $clone = clone $this;
276
        $clone->headers->set($name, $value);
277
278
        if ($clone->getStatusCode() === StatusCode::HTTP_OK && strtolower($name) === 'location') {
279
            $clone = $clone->withStatus(StatusCode::HTTP_FOUND);
280
        }
281
282
        return $clone;
283
    }
284
285
286
    /*******************************************************************************
287
     * Body
288
     ******************************************************************************/
289
290
    /**
291
     * Write data to the response body.
292
     *
293
     * Note: This method is not part of the PSR-7 standard.
294
     *
295
     * Proxies to the underlying stream and writes the provided data to it.
296
     *
297
     * @param string $data
298
     * @return $this
299
     */
300
    public function write($data)
301
    {
302
        $this->getBody()->write($data);
303
304
        return $this;
305
    }
306
307
    /*******************************************************************************
308
     * Response Helpers
309
     ******************************************************************************/
310
311
    /**
312
     * Redirect.
313
     *
314
     * Note: This method is not part of the PSR-7 standard.
315
     *
316
     * This method prepares the response object to return an HTTP Redirect
317
     * response to the client.
318
     *
319
     * @param  string|UriInterface $url    The redirect destination.
320
     * @param  int|null            $status The redirect HTTP status code.
321
     * @return static
322
     */
323
    public function withRedirect($url, $status = null)
324
    {
325
        $responseWithRedirect = $this->withHeader('Location', (string)$url);
326
327
        if (is_null($status) && $this->getStatusCode() === StatusCode::HTTP_OK) {
328
            $status = StatusCode::HTTP_FOUND;
329
        }
330
331
        if (!is_null($status)) {
332
            return $responseWithRedirect->withStatus($status);
333
        }
334
335
        return $responseWithRedirect;
336
    }
337
338
    /**
339
     * Json.
340
     *
341
     * Note: This method is not part of the PSR-7 standard.
342
     *
343
     * This method prepares the response object to return an HTTP Json
344
     * response to the client.
345
     *
346
     * @param  mixed  $data   The data
347
     * @param  int    $status The HTTP status code.
348
     * @param  int    $encodingOptions Json encoding options
349
     * @throws \RuntimeException
350
     * @return static
351
     */
352
    public function withJson($data, $status = null, $encodingOptions = 0)
353
    {
354
        $response = $this->withBody(new Body(fopen('php://temp', 'r+')));
355
        $response->body->write($json = json_encode($data, $encodingOptions));
356
357
        // Ensure that the json encoding passed successfully
358
        if ($json === false) {
359
            throw new \RuntimeException(json_last_error_msg(), json_last_error());
360
        }
361
362
        $responseWithJson = $response->withHeader('Content-Type', 'application/json');
363
        if (isset($status)) {
364
            return $responseWithJson->withStatus($status);
365
        }
366
        return $responseWithJson;
367
    }
368
369
    /**
370
     * Is this response empty?
371
     *
372
     * Note: This method is not part of the PSR-7 standard.
373
     *
374
     * @return bool
375
     */
376
    public function isEmpty()
377
    {
378
        return in_array(
379
            $this->getStatusCode(),
380
            [StatusCode::HTTP_NO_CONTENT, StatusCode::HTTP_RESET_CONTENT, StatusCode::HTTP_NOT_MODIFIED]
381
        );
382
    }
383
384
    /**
385
     * Is this response informational?
386
     *
387
     * Note: This method is not part of the PSR-7 standard.
388
     *
389
     * @return bool
390
     */
391
    public function isInformational()
392
    {
393
        return $this->getStatusCode() >= StatusCode::HTTP_CONTINUE && $this->getStatusCode() < StatusCode::HTTP_OK;
394
    }
395
396
    /**
397
     * Is this response OK?
398
     *
399
     * Note: This method is not part of the PSR-7 standard.
400
     *
401
     * @return bool
402
     */
403
    public function isOk()
404
    {
405
        return $this->getStatusCode() === StatusCode::HTTP_OK;
406
    }
407
408
    /**
409
     * Is this response successful?
410
     *
411
     * Note: This method is not part of the PSR-7 standard.
412
     *
413
     * @return bool
414
     */
415
    public function isSuccessful()
416
    {
417
        return $this->getStatusCode() >= StatusCode::HTTP_OK &&
418
            $this->getStatusCode() < StatusCode::HTTP_MULTIPLE_CHOICES;
419
    }
420
421
    /**
422
     * Is this response a redirect?
423
     *
424
     * Note: This method is not part of the PSR-7 standard.
425
     *
426
     * @return bool
427
     */
428
    public function isRedirect()
429
    {
430
        return in_array(
431
            $this->getStatusCode(),
432
            [
433
                StatusCode::HTTP_MOVED_PERMANENTLY,
434
                StatusCode::HTTP_FOUND,
435
                StatusCode::HTTP_SEE_OTHER,
436
                StatusCode::HTTP_TEMPORARY_REDIRECT,
437
                StatusCode::HTTP_PERMANENT_REDIRECT
438
            ]
439
        );
440
    }
441
442
    /**
443
     * Is this response a redirection?
444
     *
445
     * Note: This method is not part of the PSR-7 standard.
446
     *
447
     * @return bool
448
     */
449
    public function isRedirection()
450
    {
451
        return $this->getStatusCode() >= StatusCode::HTTP_MULTIPLE_CHOICES &&
452
            $this->getStatusCode() < StatusCode::HTTP_BAD_REQUEST;
453
    }
454
455
    /**
456
     * Is this response forbidden?
457
     *
458
     * Note: This method is not part of the PSR-7 standard.
459
     *
460
     * @return bool
461
     * @api
462
     */
463
    public function isForbidden()
464
    {
465
        return $this->getStatusCode() === StatusCode::HTTP_FORBIDDEN;
466
    }
467
468
    /**
469
     * Is this response not Found?
470
     *
471
     * Note: This method is not part of the PSR-7 standard.
472
     *
473
     * @return bool
474
     */
475
    public function isNotFound()
476
    {
477
        return $this->getStatusCode() === StatusCode::HTTP_NOT_FOUND;
478
    }
479
480
    /**
481
     * Is this a bad request?
482
     *
483
     * Note: This method is not part of the PSR-7 standard.
484
     *
485
     * @return bool
486
     */
487
    public function isBadRequest()
488
    {
489
        return $this->getStatusCode() === StatusCode::HTTP_BAD_REQUEST;
490
    }
491
492
    /**
493
     * Is this response a client error?
494
     *
495
     * Note: This method is not part of the PSR-7 standard.
496
     *
497
     * @return bool
498
     */
499
    public function isClientError()
500
    {
501
        return $this->getStatusCode() >= StatusCode::HTTP_BAD_REQUEST &&
502
            $this->getStatusCode() < StatusCode::HTTP_INTERNAL_SERVER_ERROR;
503
    }
504
505
    /**
506
     * Is this response a server error?
507
     *
508
     * Note: This method is not part of the PSR-7 standard.
509
     *
510
     * @return bool
511
     */
512
    public function isServerError()
513
    {
514
        return $this->getStatusCode() >= StatusCode::HTTP_INTERNAL_SERVER_ERROR && $this->getStatusCode() < 600;
515
    }
516
517
    /**
518
     * Convert response to string.
519
     *
520
     * Note: This method is not part of the PSR-7 standard.
521
     *
522
     * @return string
523
     */
524
    public function __toString()
525
    {
526
        $output = sprintf(
527
            'HTTP/%s %s %s',
528
            $this->getProtocolVersion(),
529
            $this->getStatusCode(),
530
            $this->getReasonPhrase()
531
        );
532
        $output .= Response::EOL;
533
        foreach ($this->getHeaders() as $name => $values) {
534
            $output .= sprintf('%s: %s', $name, $this->getHeaderLine($name)) . Response::EOL;
535
        }
536
        $output .= Response::EOL;
537
        $output .= (string)$this->getBody();
538
539
        return $output;
540
    }
541
}
542