Completed
Push — master ( 9e1c2f...16e6fb )
by Bohuslav
03:00
created

Response::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 3
crap 1
1
<?php
2
namespace Kambo\HttpMessage;
3
4
// \Spl
5
use \InvalidArgumentException;
6
7
// \Psr
8
use Psr\Http\Message\ResponseInterface;
9
use Psr\Http\Message\StreamInterface;
10
11
// \HttpMessage
12
use Kambo\HttpMessage\Message;
13
use Kambo\HttpMessage\Headers;
14
use Kambo\HttpMessage\Stream;
15
16
/**
17
 * Representation of an outgoing, server-side response.
18
 *
19
 * Per the HTTP specification, this class encapsulate properties for
20
 * each of the following:
21
 *
22
 * - Protocol version
23
 * - Status code and reason phrase
24
 * - Headers
25
 * - Message body
26
 *
27
 * Responses are considered immutable; all methods that change state retain 
28
 * the internal state of the current message and return an instance that 
29
 * contains the changed state.
30
 *
31
 * @package Kambo\HttpMessage
32
 * @author  Bohuslav Simek <[email protected]>
33
 * @license MIT
34
 */
35
class Response extends Message implements ResponseInterface
36
{
37
    private $status       = 200;
38
    private $reasonPhrase = '';
39
40
    /**
41
     * Status codes and reason phrases
42
     *
43
     * @var array
44
     */
45
    private $messages = [
46
        //Informational 1xx
47
        100 => 'Continue',
48
        101 => 'Switching Protocols',
49
        102 => 'Processing',
50
        //Successful 2xx
51
        200 => 'OK',
52
        201 => 'Created',
53
        202 => 'Accepted',
54
        203 => 'Non-Authoritative Information',
55
        204 => 'No Content',
56
        205 => 'Reset Content',
57
        206 => 'Partial Content',
58
        207 => 'Multi-Status',
59
        208 => 'Already Reported',
60
        226 => 'IM Used',
61
        //Redirection 3xx
62
        300 => 'Multiple Choices',
63
        301 => 'Moved Permanently',
64
        302 => 'Found',
65
        303 => 'See Other',
66
        304 => 'Not Modified',
67
        305 => 'Use Proxy',
68
        306 => '(Unused)',
69
        307 => 'Temporary Redirect',
70
        308 => 'Permanent Redirect',
71
        //Client Error 4xx
72
        400 => 'Bad Request',
73
        401 => 'Unauthorized',
74
        402 => 'Payment Required',
75
        403 => 'Forbidden',
76
        404 => 'Not Found',
77
        405 => 'Method Not Allowed',
78
        406 => 'Not Acceptable',
79
        407 => 'Proxy Authentication Required',
80
        408 => 'Request Timeout',
81
        409 => 'Conflict',
82
        410 => 'Gone',
83
        411 => 'Length Required',
84
        412 => 'Precondition Failed',
85
        413 => 'Request Entity Too Large',
86
        414 => 'Request-URI Too Long',
87
        415 => 'Unsupported Media Type',
88
        416 => 'Requested Range Not Satisfiable',
89
        417 => 'Expectation Failed',
90
        418 => 'I\'m a teapot',
91
        422 => 'Unprocessable Entity',
92
        423 => 'Locked',
93
        424 => 'Failed Dependency',
94
        426 => 'Upgrade Required',
95
        428 => 'Precondition Required',
96
        429 => 'Too Many Requests',
97
        431 => 'Request Header Fields Too Large',
98
        451 => 'Unavailable For Legal Reasons',
99
        //Server Error 5xx
100
        500 => 'Internal Server Error',
101
        501 => 'Not Implemented',
102
        502 => 'Bad Gateway',
103
        503 => 'Service Unavailable',
104
        504 => 'Gateway Timeout',
105
        505 => 'HTTP Version Not Supported',
106
        506 => 'Variant Also Negotiates',
107
        507 => 'Insufficient Storage',
108
        508 => 'Loop Detected',
109
        510 => 'Not Extended',
110
        511 => 'Network Authentication Required',
111
    ];
112
113
    /**
114
     * Create new outgoing, server-side response.
115
     *
116
     * @param int                   $status  The response status code.
117
     * @param Headers|null          $headers The response headers.
118
     * @param StreamInterface|null  $body    The response body.
119
     */
120 4
    public function __construct($status = 200, Headers $headers = null, StreamInterface $body = null)
121
    {
122 4
        parent::__construct($headers, $body);
0 ignored issues
show
Bug introduced by
It seems like $headers defined by parameter $headers on line 120 can also be of type object<Kambo\HttpMessage\Headers>; however, Kambo\HttpMessage\Message::__construct() does only seem to accept object<Kambo\HttpMessage\HeadersInterface>|null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
123 4
        $this->validateStatus($status);
124
125 4
        $this->status  = $status;
126 4
    }
127
128
    /**
129
     * Gets the response status code.
130
     *
131
     * The status code is a 3-digit integer result code of the server's attempt
132
     * to understand and satisfy the request.
133
     *
134
     * @return int Status code.
135
     */
136 2
    public function getStatusCode()
137
    {
138 2
        return $this->status;
139
    }
140
141
    /**
142
     * Return an instance with the specified status code and, optionally, reason phrase.
143
     *
144
     * If no reason phrase is specified, the RFC 7231 or IANA recommended reason 
145
     * phrase is returned according response status code.
146
     *
147
     * This method retain the immutability of the message, and return an 
148
     * instance that has the updated status and reason phrase.
149
     *
150
     * @link http://tools.ietf.org/html/rfc7231#section-6
151
     * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
152
     *
153
     * @param int    $code         The 3-digit integer result code to set.
154
     * @param string $reasonPhrase The reason phrase to use with the provided status code;
155
     *                             if none is provided, implementations MAY use the defaults
156
     *                             as suggested in the HTTP specification.
157
     *
158
     * @return self
159
     *
160
     * @throws \InvalidArgumentException For invalid status code arguments.
161
     */
162 2
    public function withStatus($code, $reasonPhrase = '')
163
    {
164 2
        $clone = clone $this;
165
166 2
        $this->validateStatus($code);
167
168 1
        $clone->status = $code;
169
170 1
        if ($reasonPhrase === '') {
171 1
            $reasonPhrase = $this->messages[$code];
172 1
        }
173
174 1
        $this->reasonPhrase = $reasonPhrase;
175
176 1
        return $clone;
177
    }
178
179
    /**
180
     * Gets the response reason phrase associated with the status code.
181
     *
182
     * The default RFC 7231 recommended reason phrase is selected according 
183
     * response's status code.
184
     *
185
     * @link http://tools.ietf.org/html/rfc7231#section-6
186
     * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
187
     *
188
     * @return string Reason phrase; must return an empty string if none present.
189
     */
190 1
    public function getReasonPhrase()
191
    {
192 1
        return $this->messages[$this->status];
193
    }
194
195
    // ------------ PRIVATE METHODS
196
197
    /**
198
     * Validate status code
199
     *
200
     * @param int $code The 3-digit integer result code to set.
201
     *
202
     * @return void
203
     * @throws \InvalidArgumentException For invalid status code.
204
     */
205 4
    private function validateStatus($code)
206
    {
207 4
        if (!isset($this->messages[$code])) {
208 1
            throw new InvalidArgumentException('A proper HTTP code from RFC 7231 must be provided.');
209
        }
210 4
    }
211
}
212