17cae64e556798d141d7007ae2cc87f151eac33f
[yaffs-website] / vendor / zendframework / zend-diactoros / src / Response.php
1 <?php
2 /**
3  * @see       https://github.com/zendframework/zend-diactoros for the canonical source repository
4  * @copyright Copyright (c) 2015-2018 Zend Technologies USA Inc. (http://www.zend.com)
5  * @license   https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
6  */
7
8 namespace Zend\Diactoros;
9
10 use InvalidArgumentException;
11 use Psr\Http\Message\ResponseInterface;
12 use Psr\Http\Message\StreamInterface;
13
14 use function gettype;
15 use function is_float;
16 use function is_numeric;
17 use function is_scalar;
18 use function sprintf;
19
20 /**
21  * HTTP response encapsulation.
22  *
23  * Responses are considered immutable; all methods that might change state are
24  * implemented such that they retain the internal state of the current
25  * message and return a new instance that contains the changed state.
26  */
27 class Response implements ResponseInterface
28 {
29     use MessageTrait;
30
31     const MIN_STATUS_CODE_VALUE = 100;
32     const MAX_STATUS_CODE_VALUE = 599;
33
34     /**
35      * Map of standard HTTP status code/reason phrases
36      *
37      * @var array
38      */
39     private $phrases = [
40         // INFORMATIONAL CODES
41         100 => 'Continue',
42         101 => 'Switching Protocols',
43         102 => 'Processing',
44         103 => 'Early Hints',
45         // SUCCESS CODES
46         200 => 'OK',
47         201 => 'Created',
48         202 => 'Accepted',
49         203 => 'Non-Authoritative Information',
50         204 => 'No Content',
51         205 => 'Reset Content',
52         206 => 'Partial Content',
53         207 => 'Multi-Status',
54         208 => 'Already Reported',
55         226 => 'IM Used',
56         // REDIRECTION CODES
57         300 => 'Multiple Choices',
58         301 => 'Moved Permanently',
59         302 => 'Found',
60         303 => 'See Other',
61         304 => 'Not Modified',
62         305 => 'Use Proxy',
63         306 => 'Switch Proxy', // Deprecated to 306 => '(Unused)'
64         307 => 'Temporary Redirect',
65         308 => 'Permanent Redirect',
66         // CLIENT ERROR
67         400 => 'Bad Request',
68         401 => 'Unauthorized',
69         402 => 'Payment Required',
70         403 => 'Forbidden',
71         404 => 'Not Found',
72         405 => 'Method Not Allowed',
73         406 => 'Not Acceptable',
74         407 => 'Proxy Authentication Required',
75         408 => 'Request Timeout',
76         409 => 'Conflict',
77         410 => 'Gone',
78         411 => 'Length Required',
79         412 => 'Precondition Failed',
80         413 => 'Payload Too Large',
81         414 => 'URI Too Long',
82         415 => 'Unsupported Media Type',
83         416 => 'Range Not Satisfiable',
84         417 => 'Expectation Failed',
85         418 => 'I\'m a teapot',
86         421 => 'Misdirected Request',
87         422 => 'Unprocessable Entity',
88         423 => 'Locked',
89         424 => 'Failed Dependency',
90         425 => 'Too Early',
91         426 => 'Upgrade Required',
92         428 => 'Precondition Required',
93         429 => 'Too Many Requests',
94         431 => 'Request Header Fields Too Large',
95         444 => 'Connection Closed Without Response',
96         451 => 'Unavailable For Legal Reasons',
97         // SERVER ERROR
98         499 => 'Client Closed Request',
99         500 => 'Internal Server Error',
100         501 => 'Not Implemented',
101         502 => 'Bad Gateway',
102         503 => 'Service Unavailable',
103         504 => 'Gateway Timeout',
104         505 => 'HTTP Version Not Supported',
105         506 => 'Variant Also Negotiates',
106         507 => 'Insufficient Storage',
107         508 => 'Loop Detected',
108         510 => 'Not Extended',
109         511 => 'Network Authentication Required',
110         599 => 'Network Connect Timeout Error',
111     ];
112
113     /**
114      * @var string
115      */
116     private $reasonPhrase;
117
118     /**
119      * @var int
120      */
121     private $statusCode;
122
123     /**
124      * @param string|resource|StreamInterface $body Stream identifier and/or actual stream resource
125      * @param int $status Status code for the response, if any.
126      * @param array $headers Headers for the response, if any.
127      * @throws InvalidArgumentException on any invalid element.
128      */
129     public function __construct($body = 'php://memory', $status = 200, array $headers = [])
130     {
131         $this->setStatusCode($status);
132         $this->stream = $this->getStream($body, 'wb+');
133         $this->setHeaders($headers);
134     }
135
136     /**
137      * {@inheritdoc}
138      */
139     public function getStatusCode()
140     {
141         return $this->statusCode;
142     }
143
144     /**
145      * {@inheritdoc}
146      */
147     public function getReasonPhrase()
148     {
149         return $this->reasonPhrase;
150     }
151
152     /**
153      * {@inheritdoc}
154      */
155     public function withStatus($code, $reasonPhrase = '')
156     {
157         $new = clone $this;
158         $new->setStatusCode($code, $reasonPhrase);
159         return $new;
160     }
161
162     /**
163      * Set a valid status code.
164      *
165      * @param int $code
166      * @param string $reasonPhrase
167      * @throws InvalidArgumentException on an invalid status code.
168      */
169     private function setStatusCode($code, $reasonPhrase = '')
170     {
171         if (! is_numeric($code)
172             || is_float($code)
173             || $code < static::MIN_STATUS_CODE_VALUE
174             || $code > static::MAX_STATUS_CODE_VALUE
175         ) {
176             throw new InvalidArgumentException(sprintf(
177                 'Invalid status code "%s"; must be an integer between %d and %d, inclusive',
178                 is_scalar($code) ? $code : gettype($code),
179                 static::MIN_STATUS_CODE_VALUE,
180                 static::MAX_STATUS_CODE_VALUE
181             ));
182         }
183
184         if (! is_string($reasonPhrase)) {
185             throw new InvalidArgumentException(sprintf(
186                 'Unsupported response reason phrase; must be a string, received %s',
187                 is_object($reasonPhrase) ? get_class($reasonPhrase) : gettype($reasonPhrase)
188             ));
189         }
190
191         if ($reasonPhrase === '' && isset($this->phrases[$code])) {
192             $reasonPhrase = $this->phrases[$code];
193         }
194
195         $this->reasonPhrase = $reasonPhrase;
196         $this->statusCode = (int) $code;
197     }
198 }