1 | <?php |
||
22 | class Response implements PhpRestfulApiResponse |
||
23 | { |
||
24 | use MessageTrait, InjectContentTypeTrait; |
||
25 | |||
26 | const MIN_STATUS_CODE_VALUE = 100; |
||
27 | const MAX_STATUS_CODE_VALUE = 599; |
||
28 | |||
29 | /** |
||
30 | * Map of standard HTTP status code/reason phrases |
||
31 | * |
||
32 | * @var array |
||
33 | */ |
||
34 | protected $phrases = [ |
||
35 | // INFORMATIONAL CODES |
||
36 | 100 => 'Continue', |
||
37 | 101 => 'Switching Protocols', |
||
38 | 102 => 'Processing', |
||
39 | 103 => 'Early Hints', |
||
40 | // SUCCESS CODES |
||
41 | 200 => 'OK', |
||
42 | 201 => 'Created', |
||
43 | 202 => 'Accepted', |
||
44 | 203 => 'Non-Authoritative Information', |
||
45 | 204 => 'No Content', |
||
46 | 205 => 'Reset Content', |
||
47 | 206 => 'Partial Content', |
||
48 | 207 => 'Multi-Status', |
||
49 | 208 => 'Already Reported', |
||
50 | 226 => 'IM Used', |
||
51 | // REDIRECTION CODES |
||
52 | 300 => 'Multiple Choices', |
||
53 | 301 => 'Moved Permanently', |
||
54 | 302 => 'Found', |
||
55 | 303 => 'See Other', |
||
56 | 304 => 'Not Modified', |
||
57 | 305 => 'Use Proxy', |
||
58 | 306 => 'Switch Proxy', // Deprecated to 306 => '(Unused)' |
||
59 | 307 => 'Temporary Redirect', |
||
60 | 308 => 'Permanent Redirect', |
||
61 | // CLIENT ERROR |
||
62 | 400 => 'Bad Request', |
||
63 | 401 => 'Unauthorized', |
||
64 | 402 => 'Payment Required', |
||
65 | 403 => 'Forbidden', |
||
66 | 404 => 'Not Found', |
||
67 | 405 => 'Method Not Allowed', |
||
68 | 406 => 'Not Acceptable', |
||
69 | 407 => 'Proxy Authentication Required', |
||
70 | 408 => 'Request Timeout', |
||
71 | 409 => 'Conflict', |
||
72 | 410 => 'Gone', |
||
73 | 411 => 'Length Required', |
||
74 | 412 => 'Precondition Failed', |
||
75 | 413 => 'Payload Too Large', |
||
76 | 414 => 'URI Too Long', |
||
77 | 415 => 'Unsupported Media Type', |
||
78 | 416 => 'Range Not Satisfiable', |
||
79 | 417 => 'Expectation Failed', |
||
80 | 418 => 'I\'m a teapot', |
||
81 | 421 => 'Misdirected Request', |
||
82 | 422 => 'Unprocessable Entity', |
||
83 | 423 => 'Locked', |
||
84 | 424 => 'Failed Dependency', |
||
85 | 425 => 'Unordered Collection', |
||
86 | 426 => 'Upgrade Required', |
||
87 | 428 => 'Precondition Required', |
||
88 | 429 => 'Too Many Requests', |
||
89 | 431 => 'Request Header Fields Too Large', |
||
90 | 444 => 'Connection Closed Without Response', |
||
91 | 451 => 'Unavailable For Legal Reasons', |
||
92 | // SERVER ERROR |
||
93 | 499 => 'Client Closed Request', |
||
94 | 500 => 'Internal Server Error', |
||
95 | 501 => 'Not Implemented', |
||
96 | 502 => 'Bad Gateway', |
||
97 | 503 => 'Service Unavailable', |
||
98 | 504 => 'Gateway Timeout', |
||
99 | 505 => 'HTTP Version Not Supported', |
||
100 | 506 => 'Variant Also Negotiates', |
||
101 | 507 => 'Insufficient Storage', |
||
102 | 508 => 'Loop Detected', |
||
103 | 510 => 'Not Extended', |
||
104 | 511 => 'Network Authentication Required', |
||
105 | 599 => 'Network Connect Timeout Error', |
||
106 | ]; |
||
107 | |||
108 | /** |
||
109 | * @var string |
||
110 | */ |
||
111 | protected $reasonPhrase = ''; |
||
112 | |||
113 | /** |
||
114 | * @var int |
||
115 | */ |
||
116 | protected $statusCode; |
||
117 | |||
118 | /** |
||
119 | * @var int|string |
||
120 | */ |
||
121 | protected $errorCode; |
||
122 | |||
123 | /** |
||
124 | * Response constructor. |
||
125 | * @param string $body |
||
126 | * @param int $status |
||
127 | * @param int $errorCode |
||
128 | * @param array $headers |
||
129 | */ |
||
130 | 27 | public function __construct($body = 'php://memory', int $status = 200, $errorCode = null, array $headers = []) |
|
138 | |||
139 | /** |
||
140 | * {@inheritdoc} |
||
141 | */ |
||
142 | 24 | public function getStatusCode() |
|
146 | |||
147 | /** |
||
148 | * {@inheritdoc} |
||
149 | */ |
||
150 | 20 | public function getReasonPhrase() |
|
160 | |||
161 | /** |
||
162 | * {@inheritdoc} |
||
163 | */ |
||
164 | 1 | public function withStatus($code, $reasonPhrase = '') |
|
171 | |||
172 | /** |
||
173 | * @param array|null $data |
||
174 | * @param $code |
||
175 | * @param array $headers |
||
176 | * @return Response |
||
177 | */ |
||
178 | 3 | public function withArray($data, $code = 200, array $headers = []) |
|
186 | |||
187 | /** |
||
188 | * @param $data |
||
189 | * @param TransformerAbstract|callable $transformer |
||
190 | * @param int $code |
||
191 | * @param null $resourceKey |
||
192 | * @param array $meta |
||
193 | * @param array $headers |
||
194 | * @return Response |
||
195 | */ |
||
196 | 1 | public function withItem($data, $transformer, $code = 200, $resourceKey = null, $meta = [], array $headers = []) |
|
210 | |||
211 | /** |
||
212 | * @param $data |
||
213 | * @param TransformerAbstract|callable $transformer |
||
214 | * @param int $code |
||
215 | * @param null $resourceKey |
||
216 | * @param Cursor|null $cursor |
||
217 | * @param array $meta |
||
218 | * @param array $headers |
||
219 | * @return Response |
||
220 | */ |
||
221 | 1 | public function withCollection($data, $transformer, $code = 200, $resourceKey = null, Cursor $cursor = null, $meta = [], array $headers = []) |
|
239 | |||
240 | /** |
||
241 | * Response for errors |
||
242 | * |
||
243 | * @param string|array $message |
||
244 | * @param int $statusCode |
||
245 | * @param int|string $errorCode |
||
246 | * @param array $headers |
||
247 | * @return mixed |
||
248 | */ |
||
249 | 19 | public function withError($message, int $statusCode, $errorCode = null, array $headers = []) |
|
269 | |||
270 | /** |
||
271 | * Generates a response with a 403 HTTP header and a given message. |
||
272 | * |
||
273 | * @param string $message |
||
274 | * @param int|string $errorCode |
||
275 | * @param array $headers |
||
276 | * @return mixed |
||
277 | */ |
||
278 | 2 | public function errorForbidden(string $message = '', $errorCode = null, array $headers = []) |
|
282 | |||
283 | /** |
||
284 | * Generates a response with a 500 HTTP header and a given message. |
||
285 | * |
||
286 | * @param string $message |
||
287 | * @param int|string $errorCode |
||
288 | * @param array $headers |
||
289 | * @return mixed |
||
290 | */ |
||
291 | 2 | public function errorInternalError(string $message = '', $errorCode = null, array $headers = []) |
|
295 | |||
296 | /** |
||
297 | * Generates a response with a 404 HTTP header and a given message. |
||
298 | * |
||
299 | * @param string $message |
||
300 | * @param int|string $errorCode |
||
301 | * @param array $headers |
||
302 | * @return mixed |
||
303 | */ |
||
304 | 2 | public function errorNotFound(string $message = '', $errorCode = null, array $headers = []) |
|
308 | |||
309 | /** |
||
310 | * Generates a response with a 401 HTTP header and a given message. |
||
311 | * |
||
312 | * @param string $message |
||
313 | * @param int|string $errorCode |
||
314 | * @param array $headers |
||
315 | * @return mixed |
||
316 | */ |
||
317 | 2 | public function errorUnauthorized(string $message = '', $errorCode = null, array $headers = []) |
|
321 | |||
322 | /** |
||
323 | * Generates a response with a 400 HTTP header and a given message. |
||
324 | * |
||
325 | * @param array $message |
||
326 | * @param int|array $errorCode |
||
327 | * @param array $headers |
||
328 | * @return mixed |
||
329 | */ |
||
330 | 1 | public function errorWrongArgs(array $message, $errorCode = null, array $headers = []) |
|
334 | |||
335 | /** |
||
336 | * Generates a response with a 410 HTTP header and a given message. |
||
337 | * |
||
338 | * @param string $message |
||
339 | * @param int|string $errorCode |
||
340 | * @param array $headers |
||
341 | * @return mixed |
||
342 | */ |
||
343 | 2 | public function errorGone(string $message = '', $errorCode = null, array $headers = []) |
|
347 | |||
348 | /** |
||
349 | * Generates a response with a 405 HTTP header and a given message. |
||
350 | * |
||
351 | * @param string $message |
||
352 | * @param int|string $errorCode |
||
353 | * @param array $headers |
||
354 | * @return mixed |
||
355 | */ |
||
356 | 2 | public function errorMethodNotAllowed(string $message = '', $errorCode = null, array $headers = []) |
|
360 | |||
361 | /** |
||
362 | * Generates a Response with a 431 HTTP header and a given message. |
||
363 | * |
||
364 | * @param string $message |
||
365 | * @param int|string $errorCode |
||
366 | * @param array $headers |
||
367 | * @return mixed |
||
368 | */ |
||
369 | 2 | public function errorUnwillingToProcess(string $message = '', $errorCode = null, array $headers = []) |
|
373 | |||
374 | /** |
||
375 | * Generates a Response with a 422 HTTP header and a given message. |
||
376 | * |
||
377 | * @param string $message |
||
378 | * @param int|string $errorCode |
||
379 | * @param array $headers |
||
380 | * @return mixed |
||
381 | */ |
||
382 | 2 | public function errorUnprocessable(string $message = '', $errorCode = null, array $headers = []) |
|
386 | |||
387 | /** |
||
388 | * @return int|string |
||
389 | */ |
||
390 | 20 | public function getErrorCode() |
|
394 | |||
395 | /** |
||
396 | * @param $errorCode |
||
397 | * @return $this |
||
398 | */ |
||
399 | 27 | public function setErrorCode($errorCode) |
|
403 | |||
404 | /** |
||
405 | * Set a valid status code. |
||
406 | * |
||
407 | * @param int $statusCode |
||
408 | * @throws InvalidArgumentException on an invalid status code. |
||
409 | */ |
||
410 | 27 | protected function setStatusCode(int $statusCode) |
|
424 | |||
425 | /** |
||
426 | * Encode the provided data to JSON. |
||
427 | * |
||
428 | * @param mixed $data |
||
429 | * @return string |
||
430 | * @throws InvalidArgumentException if unable to encode the $data to JSON. |
||
431 | */ |
||
432 | 22 | protected function jsonEncode($data) |
|
453 | } |
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.