Response::assertStatusCodeIsInteger()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2.1481

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 4
ccs 2
cts 3
cp 0.6667
crap 2.1481
rs 10
1
<?php
2
/**
3
 * This file is part of the Divergence package.
4
 *
5
 * (c) Henry Paradiz <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Divergence\Responders;
12
13
use GuzzleHttp\Psr7\Utils;
14
use GuzzleHttp\Psr7\MessageTrait;
15
use Psr\Http\Message\ResponseInterface;
16
17
/**
18
 * Default PSR7 Compatible Response Object for Divergence Framework
19
 *
20
 * Large parts of this file were copied from Guzzle's psr7 library.
21
 * I would have simply extended it but I didn't like the constructor design so I instead copied the code.
22
 *
23
 * {@inheritDoc}
24
 */
25
class Response implements ResponseInterface
26
{
27
    use MessageTrait;
28
29
    /** Map of standard HTTP status code/reason phrases */
30
    private const PHRASES = [
31
        100 => 'Continue',
32
        101 => 'Switching Protocols',
33
        102 => 'Processing',
34
        200 => 'OK',
35
        201 => 'Created',
36
        202 => 'Accepted',
37
        203 => 'Non-Authoritative Information',
38
        204 => 'No Content',
39
        205 => 'Reset Content',
40
        206 => 'Partial Content',
41
        207 => 'Multi-status',
42
        208 => 'Already Reported',
43
        300 => 'Multiple Choices',
44
        301 => 'Moved Permanently',
45
        302 => 'Found',
46
        303 => 'See Other',
47
        304 => 'Not Modified',
48
        305 => 'Use Proxy',
49
        306 => 'Switch Proxy',
50
        307 => 'Temporary Redirect',
51
        400 => 'Bad Request',
52
        401 => 'Unauthorized',
53
        402 => 'Payment Required',
54
        403 => 'Forbidden',
55
        404 => 'Not Found',
56
        405 => 'Method Not Allowed',
57
        406 => 'Not Acceptable',
58
        407 => 'Proxy Authentication Required',
59
        408 => 'Request Time-out',
60
        409 => 'Conflict',
61
        410 => 'Gone',
62
        411 => 'Length Required',
63
        412 => 'Precondition Failed',
64
        413 => 'Request Entity Too Large',
65
        414 => 'Request-URI Too Large',
66
        415 => 'Unsupported Media Type',
67
        416 => 'Requested range not satisfiable',
68
        417 => 'Expectation Failed',
69
        418 => 'I\'m a teapot',
70
        422 => 'Unprocessable Entity',
71
        423 => 'Locked',
72
        424 => 'Failed Dependency',
73
        425 => 'Unordered Collection',
74
        426 => 'Upgrade Required',
75
        428 => 'Precondition Required',
76
        429 => 'Too Many Requests',
77
        431 => 'Request Header Fields Too Large',
78
        451 => 'Unavailable For Legal Reasons',
79
        500 => 'Internal Server Error',
80
        501 => 'Not Implemented',
81
        502 => 'Bad Gateway',
82
        503 => 'Service Unavailable',
83
        504 => 'Gateway Time-out',
84
        505 => 'HTTP Version not supported',
85
        506 => 'Variant Also Negotiates',
86
        507 => 'Insufficient Storage',
87
        508 => 'Loop Detected',
88
        510 => 'Not Extended',
89
        511 => 'Network Authentication Required',
90
    ];
91
92
    /** @var string */
93
    private $reasonPhrase;
94
95
    /** @var int */
96
    private $statusCode;
97
98 55
    public function __construct(ResponseBuilder $responseBuilder)
99
    {
100 55
        $this
101 55
        ->withDefaults(200, [
102 55
            'Content-Type' => $responseBuilder->getContentType(),
103 55
        ], $responseBuilder->getBody());
104
    }
105
106
    /**
107
     * @param int                                  $status  Status code
108
     * @param array<string, string|string[]>       $headers Response headers
109
     * @param string|resource|StreamInterface|null $body    Response body
0 ignored issues
show
Bug introduced by
The type Divergence\Responders\StreamInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
110
     * @param string                               $version Protocol version
111
     * @param string|null                          $reason  Reason phrase (when empty a default will be used based on the status code)
112
     * @return static
113
     */
114 64
    public function withDefaults(
115
        int $status = 200,
116
        array $headers = [],
117
        $body = null,
118
        string $version = '1.1',
119
        string $reason = null
120
    ) {
121 64
        $this->assertStatusCodeRange($status);
122
123 64
        $this->statusCode = $status;
124
125 64
        if ($body !== '' && $body !== null) {
126 62
            $this->stream = Utils::streamFor($body);
127
        }
128
129 64
        $this->setHeaders($headers);
130 64
        if ($reason == '' && isset(self::PHRASES[$this->statusCode])) {
131 64
            $this->reasonPhrase = self::PHRASES[$this->statusCode];
132
        } else {
133
            $this->reasonPhrase = (string) $reason;
134
        }
135
136 64
        $this->protocol = $version;
137
138 64
        return $this;
139
    }
140
141 66
    public function getStatusCode(): int
142
    {
143 66
        return $this->statusCode;
144
    }
145
146 2
    public function getReasonPhrase(): string
147
    {
148 2
        return $this->reasonPhrase;
149
    }
150
151 5
    public function withStatus($code, $reasonPhrase = ''): ResponseInterface
152
    {
153 5
        $this->assertStatusCodeIsInteger($code);
154 5
        $code = (int) $code;
155 5
        $this->assertStatusCodeRange($code);
156
157 5
        $new = clone $this;
158 5
        $new->statusCode = $code;
159 5
        if ($reasonPhrase == '' && isset(self::PHRASES[$new->statusCode])) {
160 5
            $reasonPhrase = self::PHRASES[$new->statusCode];
161
        }
162 5
        $new->reasonPhrase = (string) $reasonPhrase;
163 5
        return $new;
164
    }
165
166
    /**
167
     * @param mixed $statusCode
168
     */
169 5
    private function assertStatusCodeIsInteger($statusCode): void
170
    {
171 5
        if (filter_var($statusCode, FILTER_VALIDATE_INT) === false) {
172
            throw new \InvalidArgumentException('Status code must be an integer value.');
173
        }
174
    }
175
176 66
    private function assertStatusCodeRange(int $statusCode): void
177
    {
178 66
        if ($statusCode < 100 || $statusCode >= 600) {
179
            throw new \InvalidArgumentException('Status code must be an integer value between 1xx and 5xx.');
180
        }
181
    }
182
}
183