Passed
Push — develop ( 33032a...666b96 )
by Henry
02:03
created

Response::getStatusCode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
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\MessageTrait;
14
use Psr\Http\Message\ResponseInterface;
15
16
/**
17
 * Default PSR7 Compatible Response Object for Divergence Framework
18
 *
19
 * Large parts of this file were copied from Guzzle's psr7 library.
20
 * I would have simply extended it but I didn't like the constructor design so I instead copied the code.
21
 *
22
 * {@inheritDoc}
23
 */
24
class Response implements ResponseInterface
25
{
26
    use MessageTrait;
27
28
    /** Map of standard HTTP status code/reason phrases */
29
    private const PHRASES = [
30
        100 => 'Continue',
31
        101 => 'Switching Protocols',
32
        102 => 'Processing',
33
        200 => 'OK',
34
        201 => 'Created',
35
        202 => 'Accepted',
36
        203 => 'Non-Authoritative Information',
37
        204 => 'No Content',
38
        205 => 'Reset Content',
39
        206 => 'Partial Content',
40
        207 => 'Multi-status',
41
        208 => 'Already Reported',
42
        300 => 'Multiple Choices',
43
        301 => 'Moved Permanently',
44
        302 => 'Found',
45
        303 => 'See Other',
46
        304 => 'Not Modified',
47
        305 => 'Use Proxy',
48
        306 => 'Switch Proxy',
49
        307 => 'Temporary Redirect',
50
        400 => 'Bad Request',
51
        401 => 'Unauthorized',
52
        402 => 'Payment Required',
53
        403 => 'Forbidden',
54
        404 => 'Not Found',
55
        405 => 'Method Not Allowed',
56
        406 => 'Not Acceptable',
57
        407 => 'Proxy Authentication Required',
58
        408 => 'Request Time-out',
59
        409 => 'Conflict',
60
        410 => 'Gone',
61
        411 => 'Length Required',
62
        412 => 'Precondition Failed',
63
        413 => 'Request Entity Too Large',
64
        414 => 'Request-URI Too Large',
65
        415 => 'Unsupported Media Type',
66
        416 => 'Requested range not satisfiable',
67
        417 => 'Expectation Failed',
68
        418 => 'I\'m a teapot',
69
        422 => 'Unprocessable Entity',
70
        423 => 'Locked',
71
        424 => 'Failed Dependency',
72
        425 => 'Unordered Collection',
73
        426 => 'Upgrade Required',
74
        428 => 'Precondition Required',
75
        429 => 'Too Many Requests',
76
        431 => 'Request Header Fields Too Large',
77
        451 => 'Unavailable For Legal Reasons',
78
        500 => 'Internal Server Error',
79
        501 => 'Not Implemented',
80
        502 => 'Bad Gateway',
81
        503 => 'Service Unavailable',
82
        504 => 'Gateway Time-out',
83
        505 => 'HTTP Version not supported',
84
        506 => 'Variant Also Negotiates',
85
        507 => 'Insufficient Storage',
86
        508 => 'Loop Detected',
87
        510 => 'Not Extended',
88
        511 => 'Network Authentication Required',
89
    ];
90
91
    /** @var string */
92
    private $reasonPhrase;
93
94
    /** @var int */
95
    private $statusCode;
96
97
    public function __construct(ResponseBuilder $responseBuilder)
98
    {
99
        $this
100
        ->withDefaults(200, [
101
            'Content-Type' => $responseBuilder->getContentType(),
102
        ], $responseBuilder->getBody());
103
    }
104
105
    /**
106
     * @param int                                  $status  Status code
107
     * @param array<string, string|string[]>       $headers Response headers
108
     * @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...
109
     * @param string                               $version Protocol version
110
     * @param string|null                          $reason  Reason phrase (when empty a default will be used based on the status code)
111
     * @return static
112
     */
113
    public function withDefaults(
114
        int $status = 200,
115
        array $headers = [],
116
        $body = null,
117
        string $version = '1.1',
118
        string $reason = null
119
    ) {
120
        $this->assertStatusCodeRange($status);
121
122
        $this->statusCode = $status;
123
124
        if ($body !== '' && $body !== null) {
125
            $this->stream = \GuzzleHttp\Psr7\stream_for($body);
0 ignored issues
show
Deprecated Code introduced by
The function GuzzleHttp\Psr7\stream_for() has been deprecated: stream_for will be removed in guzzlehttp/psr7:2.0. Use Utils::streamFor instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

125
            $this->stream = /** @scrutinizer ignore-deprecated */ \GuzzleHttp\Psr7\stream_for($body);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
126
        }
127
128
        $this->setHeaders($headers);
129
        if ($reason == '' && isset(self::PHRASES[$this->statusCode])) {
130
            $this->reasonPhrase = self::PHRASES[$this->statusCode];
131
        } else {
132
            $this->reasonPhrase = (string) $reason;
133
        }
134
135
        $this->protocol = $version;
136
137
        return $this;
138
    }
139
140
    public function getStatusCode(): int
141
    {
142
        return $this->statusCode;
143
    }
144
145
    public function getReasonPhrase(): string
146
    {
147
        return $this->reasonPhrase;
148
    }
149
150
    public function withStatus($code, $reasonPhrase = ''): ResponseInterface
151
    {
152
        $this->assertStatusCodeIsInteger($code);
153
        $code = (int) $code;
154
        $this->assertStatusCodeRange($code);
155
156
        $new = clone $this;
157
        $new->statusCode = $code;
158
        if ($reasonPhrase == '' && isset(self::PHRASES[$new->statusCode])) {
159
            $reasonPhrase = self::PHRASES[$new->statusCode];
160
        }
161
        $new->reasonPhrase = (string) $reasonPhrase;
162
        return $new;
163
    }
164
165
    /**
166
     * @param mixed $statusCode
167
     */
168
    private function assertStatusCodeIsInteger($statusCode): void
169
    {
170
        if (filter_var($statusCode, FILTER_VALIDATE_INT) === false) {
171
            throw new \InvalidArgumentException('Status code must be an integer value.');
172
        }
173
    }
174
175
    private function assertStatusCodeRange(int $statusCode): void
176
    {
177
        if ($statusCode < 100 || $statusCode >= 600) {
178
            throw new \InvalidArgumentException('Status code must be an integer value between 1xx and 5xx.');
179
        }
180
    }
181
}
182