This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | declare(strict_types = 1); |
||
3 | |||
4 | /** |
||
5 | * Micro |
||
6 | * |
||
7 | * @author Raffael Sahli <[email protected]> |
||
8 | * @copyright Copyright (c) 2017 gyselroth GmbH (https://gyselroth.com) |
||
9 | * @license MIT https://opensource.org/licenses/MIT |
||
10 | */ |
||
11 | |||
12 | namespace Micro\Http; |
||
13 | |||
14 | use \Micro\Http; |
||
15 | use \Closure; |
||
16 | |||
17 | class Response |
||
18 | { |
||
19 | /** |
||
20 | * Output format |
||
21 | * |
||
22 | * @var string |
||
23 | */ |
||
24 | protected $output_format = 'json'; |
||
25 | |||
26 | |||
27 | /** |
||
28 | * Possible output formats |
||
29 | */ |
||
30 | const OUTPUT_FORMATS = [ |
||
31 | 'json' => 'application/json; charset=utf-8', |
||
32 | 'xml' => 'application/xml; charset=utf-8', |
||
33 | 'text' => 'text/html; charset=utf-8' |
||
34 | ]; |
||
35 | |||
36 | |||
37 | /** |
||
38 | * Human readable output |
||
39 | * |
||
40 | * @var bool |
||
41 | */ |
||
42 | protected $pretty_format = false; |
||
43 | |||
44 | |||
45 | /** |
||
46 | * Headers |
||
47 | * |
||
48 | * @var array |
||
49 | */ |
||
50 | protected $headers = []; |
||
51 | |||
52 | |||
53 | /** |
||
54 | * Code |
||
55 | * |
||
56 | * @var int |
||
57 | */ |
||
58 | protected $code = 200; |
||
59 | |||
60 | |||
61 | /** |
||
62 | * Body |
||
63 | * |
||
64 | * @var string |
||
65 | */ |
||
66 | protected $body; |
||
67 | |||
68 | |||
69 | /** |
||
70 | * body only |
||
71 | * |
||
72 | * @var bool |
||
73 | */ |
||
74 | protected $body_only = false; |
||
75 | |||
76 | |||
77 | /** |
||
78 | * Init response |
||
79 | * |
||
80 | * @return void |
||
0 ignored issues
–
show
|
|||
81 | */ |
||
82 | public function __construct() |
||
83 | { |
||
84 | $this->setupFormats(); |
||
85 | } |
||
86 | |||
87 | |||
88 | /** |
||
89 | * Set header |
||
90 | * |
||
91 | * @param string $header |
||
92 | * @param string $value |
||
93 | * @return Response |
||
94 | */ |
||
95 | public function setHeader(string $header, string $value): Response |
||
96 | { |
||
97 | $this->headers[$header] = $value; |
||
98 | return $this; |
||
99 | } |
||
100 | |||
101 | |||
102 | /** |
||
103 | * Delete header |
||
104 | * |
||
105 | * @param string $header |
||
106 | * @return Response |
||
107 | */ |
||
108 | public function removeHeader(string $header): Response |
||
109 | { |
||
110 | if(isset($this->headers[$header])) { |
||
111 | unset($this->headers[$header]); |
||
112 | } |
||
113 | |||
114 | return $this; |
||
115 | } |
||
116 | |||
117 | |||
118 | /** |
||
119 | * Get headers |
||
120 | * |
||
121 | * @return array |
||
122 | */ |
||
123 | public function getHeaders(): array |
||
124 | { |
||
125 | return $this->headers; |
||
126 | } |
||
127 | |||
128 | |||
129 | /** |
||
130 | * Send headers |
||
131 | * |
||
132 | * @return Response |
||
133 | */ |
||
134 | public function sendHeaders(): Response |
||
135 | { |
||
136 | foreach ($this->headers as $header => $value) { |
||
137 | header($header.': '.$value); |
||
138 | } |
||
139 | |||
140 | return $this; |
||
141 | } |
||
142 | |||
143 | |||
144 | /** |
||
145 | * Set response code |
||
146 | * |
||
147 | * @param int $code |
||
148 | * @return Response |
||
149 | */ |
||
150 | public function setCode(int $code): Response |
||
151 | { |
||
152 | if (!array_key_exists($code, Http::STATUS_CODES)) { |
||
153 | throw new Exception('invalid http code set'); |
||
154 | } |
||
155 | |||
156 | $this->code = $code; |
||
157 | return $this; |
||
158 | } |
||
159 | |||
160 | |||
161 | /** |
||
162 | * Get response code |
||
163 | * |
||
164 | * @return int |
||
165 | */ |
||
166 | public function getCode(): int |
||
167 | { |
||
168 | return $this->code; |
||
169 | } |
||
170 | |||
171 | |||
172 | /** |
||
173 | * Set body |
||
174 | * |
||
175 | * @param mixed $body |
||
176 | * @param bool $body_only |
||
177 | * @return Response |
||
178 | */ |
||
179 | public function setBody($body, bool $body_only = false): Response |
||
180 | { |
||
181 | $this->body = $body; |
||
182 | $this->body_only = $body_only; |
||
183 | $this->setOutputFormat($this->output_format); |
||
184 | |||
185 | return $this; |
||
186 | } |
||
187 | |||
188 | |||
189 | /** |
||
190 | * Get body |
||
191 | * |
||
192 | * @return string |
||
193 | */ |
||
194 | public function getBody() |
||
195 | { |
||
196 | return $this->body; |
||
197 | } |
||
198 | |||
199 | |||
200 | /** |
||
201 | * Sends the actual response. |
||
202 | * |
||
203 | * @return void |
||
204 | */ |
||
205 | public function send(): void |
||
206 | { |
||
207 | $status = Http::STATUS_CODES[$this->code]; |
||
208 | $this->sendHeaders(); |
||
209 | header('HTTP/1.0 '.$this->code.' '.$status, true, $this->code); |
||
210 | |||
211 | if ($this->body === null && $this->code == 204) { |
||
212 | $this->terminate(); |
||
213 | } |
||
214 | |||
215 | if($this->body instanceof Closure) { |
||
216 | $body = $this->body->call($this); |
||
217 | } else { |
||
218 | $body = $this->body; |
||
219 | } |
||
220 | |||
221 | if ($this->body_only === false && $this->output_format !== 'text') { |
||
222 | $body = ['data' => $body]; |
||
223 | $body['status'] = intval($this->code); |
||
224 | $body = array_reverse($body, true); |
||
225 | } |
||
226 | |||
227 | switch ($this->output_format) { |
||
228 | case null: |
||
229 | break; |
||
230 | |||
231 | default: |
||
232 | case 'json': |
||
0 ignored issues
–
show
case 'json': echo $t...JSON($body); break; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
233 | echo $this->asJSON($body); |
||
234 | break; |
||
235 | |||
236 | case 'xml': |
||
237 | echo $this->asXML($body); |
||
238 | break; |
||
239 | |||
240 | case 'text': |
||
241 | echo $body; |
||
242 | break; |
||
243 | } |
||
244 | |||
245 | //$this->terminate(); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
84% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
246 | } |
||
247 | |||
248 | |||
249 | /** |
||
250 | * Get output format |
||
251 | * |
||
252 | * @return string |
||
253 | */ |
||
254 | public function getOutputFormat(): string |
||
255 | { |
||
256 | return $this->output_format; |
||
257 | } |
||
258 | |||
259 | |||
260 | /** |
||
261 | * Convert response to human readable output |
||
262 | * |
||
263 | * @param bool $format |
||
264 | * @return Response |
||
265 | */ |
||
266 | public function setPrettyFormat(bool $format): Response |
||
267 | { |
||
268 | $this->pretty_format = (bool)$format; |
||
269 | return $this; |
||
270 | } |
||
271 | |||
272 | |||
273 | /** |
||
274 | * Set header Content-Length $body. |
||
275 | * |
||
276 | * @param string $body |
||
277 | * @return Response |
||
278 | */ |
||
279 | public function setContentLength(string $body): Response |
||
280 | { |
||
281 | header('Content-Length: '.strlen($body)); |
||
282 | return $this; |
||
283 | } |
||
284 | |||
285 | |||
286 | /** |
||
287 | * Converts $body to pretty json. |
||
288 | * |
||
289 | * @param mixed $body |
||
290 | * @return string |
||
291 | */ |
||
292 | public function asJSON($body): string |
||
293 | { |
||
294 | if ($this->pretty_format) { |
||
295 | $result = json_encode($body, JSON_PRETTY_PRINT); |
||
296 | } else { |
||
297 | $result = json_encode($body); |
||
298 | } |
||
299 | |||
300 | $this->setContentLength($result); |
||
301 | |||
302 | return $result; |
||
303 | } |
||
304 | |||
305 | |||
306 | /** |
||
307 | * Converts mixed data to XML |
||
308 | * |
||
309 | * @param mixed $data |
||
310 | * @param SimpleXMLElement $xml |
||
311 | * @param string $child_name |
||
312 | * @return string |
||
313 | */ |
||
314 | public function toXML($data, Config $xml, string $child_name): string |
||
315 | { |
||
316 | if (is_array($data)) { |
||
317 | foreach ($data as $k => $v) { |
||
318 | if (is_array($v)) { |
||
319 | (is_int($k)) ? $this->toXML($v, $xml->addChild($child_name), $v) : $this->toXML($v, $xml->addChild(strtolower($k)), $child_name); |
||
0 ignored issues
–
show
$v is of type array , but the function expects a string .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() |
|||
320 | } else { |
||
321 | (is_int($k)) ? $xml->addChild($child_name, $v) : $xml->addChild(strtolower($k), $v); |
||
322 | } |
||
323 | } |
||
324 | } else { |
||
325 | $xml->addChild($child_name, $data); |
||
326 | } |
||
327 | |||
328 | return $xml->asXML(); |
||
329 | } |
||
330 | |||
331 | |||
332 | /** |
||
333 | * Converts response to xml. |
||
334 | * |
||
335 | * @param mixed $body |
||
336 | * @return string |
||
337 | */ |
||
338 | public function asXML($body): string |
||
339 | { |
||
340 | $root = new Config('<response></response>'); |
||
341 | $raw = $this->toXML($body, $root, 'node'); |
||
342 | |||
343 | if ($this->pretty_format) { |
||
344 | $raw = $this->prettyXml($raw); |
||
345 | } |
||
346 | |||
347 | $this->setContentLength($raw); |
||
348 | return $raw; |
||
349 | } |
||
350 | |||
351 | |||
352 | /** |
||
353 | * Pretty formatted xml |
||
354 | * |
||
355 | * @param string $xml |
||
356 | * @return string |
||
357 | */ |
||
358 | public function prettyXml(string $xml): string |
||
359 | { |
||
360 | $domxml = new \DOMDocument('1.0'); |
||
361 | $domxml->preserveWhiteSpace = false; |
||
362 | $domxml->formatOutput = true; |
||
363 | $domxml->loadXML($xml); |
||
364 | |||
365 | return $domxml->saveXML(); |
||
366 | } |
||
367 | |||
368 | |||
369 | /** |
||
370 | * Set the current output format. |
||
371 | * |
||
372 | * @param string $format |
||
373 | * @return Response |
||
374 | */ |
||
375 | public function setOutputFormat(?string $format=null): Response |
||
376 | { |
||
377 | if($format === null) { |
||
378 | $this->output_format = null; |
||
379 | return $this->removeHeader('Content-Type'); |
||
380 | } |
||
381 | |||
382 | if(!array_key_exists($format, self::OUTPUT_FORMATS)) { |
||
383 | throw new Exception('invalid output format given'); |
||
384 | } |
||
385 | |||
386 | $this->setHeader('Content-Type', self::OUTPUT_FORMATS[$format]); |
||
387 | $this->output_format = $format; |
||
388 | return $this; |
||
389 | } |
||
390 | |||
391 | |||
392 | /** |
||
393 | * Abort after response |
||
394 | * |
||
395 | * @return void |
||
396 | */ |
||
397 | public function terminate(): void |
||
398 | { |
||
399 | exit(); |
||
400 | } |
||
401 | |||
402 | |||
403 | /** |
||
404 | * Setup formats. |
||
405 | * |
||
406 | * @return Response |
||
407 | */ |
||
408 | public function setupFormats(): Response |
||
409 | { |
||
410 | $pretty = array_key_exists('pretty', $_GET) && ($_GET['pretty'] != 'false' && $_GET['pretty'] != '0'); |
||
411 | $this->setPrettyFormat($pretty); |
||
412 | |||
413 | //through HTTP_ACCEPT |
||
414 | if (isset($_SERVER['HTTP_ACCEPT']) && strpos($_SERVER['HTTP_ACCEPT'], '*/*') === false) { |
||
415 | foreach (self::OUTPUT_FORMATS as $format) { |
||
416 | if (strpos($_SERVER['HTTP_ACCEPT'], $format) !== false) { |
||
417 | $this->output_format = $format; |
||
418 | break; |
||
419 | } |
||
420 | } |
||
421 | } |
||
422 | |||
423 | return $this; |
||
424 | } |
||
425 | } |
||
426 |
Adding a
@return
annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.Please refer to the PHP core documentation on constructors.