Chris@0
|
1 <?php
|
Chris@0
|
2 /**
|
Chris@12
|
3 * @see https://github.com/zendframework/zend-diactoros for the canonical source repository
|
Chris@16
|
4 * @copyright Copyright (c) 2015-2018 Zend Technologies USA Inc. (http://www.zend.com)
|
Chris@0
|
5 * @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
|
Chris@0
|
6 */
|
Chris@0
|
7
|
Chris@0
|
8 namespace Zend\Diactoros\Response;
|
Chris@0
|
9
|
Chris@0
|
10 use Psr\Http\Message\ResponseInterface;
|
Chris@12
|
11 use RuntimeException;
|
Chris@0
|
12
|
Chris@16
|
13 use function ob_get_length;
|
Chris@16
|
14 use function ob_get_level;
|
Chris@16
|
15 use function sprintf;
|
Chris@16
|
16 use function str_replace;
|
Chris@16
|
17 use function ucwords;
|
Chris@16
|
18
|
Chris@16
|
19 /**
|
Chris@16
|
20 * @deprecated since 1.8.0. The package zendframework/zend-httphandlerrunner
|
Chris@16
|
21 * now provides this functionality.
|
Chris@16
|
22 */
|
Chris@0
|
23 trait SapiEmitterTrait
|
Chris@0
|
24 {
|
Chris@0
|
25 /**
|
Chris@12
|
26 * Checks to see if content has previously been sent.
|
Chris@0
|
27 *
|
Chris@12
|
28 * If either headers have been sent or the output buffer contains content,
|
Chris@12
|
29 * raises an exception.
|
Chris@12
|
30 *
|
Chris@12
|
31 * @throws RuntimeException if headers have already been sent.
|
Chris@12
|
32 * @throws RuntimeException if output is present in the output buffer.
|
Chris@0
|
33 */
|
Chris@12
|
34 private function assertNoPreviousOutput()
|
Chris@0
|
35 {
|
Chris@12
|
36 if (headers_sent()) {
|
Chris@12
|
37 throw new RuntimeException('Unable to emit response; headers already sent');
|
Chris@0
|
38 }
|
Chris@0
|
39
|
Chris@12
|
40 if (ob_get_level() > 0 && ob_get_length() > 0) {
|
Chris@12
|
41 throw new RuntimeException('Output has been emitted previously; cannot emit response');
|
Chris@12
|
42 }
|
Chris@0
|
43 }
|
Chris@0
|
44
|
Chris@0
|
45 /**
|
Chris@0
|
46 * Emit the status line.
|
Chris@0
|
47 *
|
Chris@0
|
48 * Emits the status line using the protocol version and status code from
|
Chris@0
|
49 * the response; if a reason phrase is available, it, too, is emitted.
|
Chris@0
|
50 *
|
Chris@12
|
51 * It is important to mention that this method should be called after
|
Chris@12
|
52 * `emitHeaders()` in order to prevent PHP from changing the status code of
|
Chris@12
|
53 * the emitted response.
|
Chris@12
|
54 *
|
Chris@0
|
55 * @param ResponseInterface $response
|
Chris@12
|
56 *
|
Chris@12
|
57 * @see \Zend\Diactoros\Response\SapiEmitterTrait::emitHeaders()
|
Chris@0
|
58 */
|
Chris@0
|
59 private function emitStatusLine(ResponseInterface $response)
|
Chris@0
|
60 {
|
Chris@0
|
61 $reasonPhrase = $response->getReasonPhrase();
|
Chris@12
|
62 $statusCode = $response->getStatusCode();
|
Chris@12
|
63
|
Chris@0
|
64 header(sprintf(
|
Chris@0
|
65 'HTTP/%s %d%s',
|
Chris@0
|
66 $response->getProtocolVersion(),
|
Chris@12
|
67 $statusCode,
|
Chris@0
|
68 ($reasonPhrase ? ' ' . $reasonPhrase : '')
|
Chris@12
|
69 ), true, $statusCode);
|
Chris@0
|
70 }
|
Chris@0
|
71
|
Chris@0
|
72 /**
|
Chris@0
|
73 * Emit response headers.
|
Chris@0
|
74 *
|
Chris@0
|
75 * Loops through each header, emitting each; if the header value
|
Chris@0
|
76 * is an array with multiple values, ensures that each is sent
|
Chris@0
|
77 * in such a way as to create aggregate headers (instead of replace
|
Chris@0
|
78 * the previous).
|
Chris@0
|
79 *
|
Chris@0
|
80 * @param ResponseInterface $response
|
Chris@0
|
81 */
|
Chris@0
|
82 private function emitHeaders(ResponseInterface $response)
|
Chris@0
|
83 {
|
Chris@12
|
84 $statusCode = $response->getStatusCode();
|
Chris@12
|
85
|
Chris@0
|
86 foreach ($response->getHeaders() as $header => $values) {
|
Chris@0
|
87 $name = $this->filterHeader($header);
|
Chris@0
|
88 $first = $name === 'Set-Cookie' ? false : true;
|
Chris@0
|
89 foreach ($values as $value) {
|
Chris@0
|
90 header(sprintf(
|
Chris@0
|
91 '%s: %s',
|
Chris@0
|
92 $name,
|
Chris@0
|
93 $value
|
Chris@12
|
94 ), $first, $statusCode);
|
Chris@0
|
95 $first = false;
|
Chris@0
|
96 }
|
Chris@0
|
97 }
|
Chris@0
|
98 }
|
Chris@0
|
99
|
Chris@0
|
100 /**
|
Chris@0
|
101 * Filter a header name to wordcase
|
Chris@0
|
102 *
|
Chris@0
|
103 * @param string $header
|
Chris@0
|
104 * @return string
|
Chris@0
|
105 */
|
Chris@0
|
106 private function filterHeader($header)
|
Chris@0
|
107 {
|
Chris@0
|
108 $filtered = str_replace('-', ' ', $header);
|
Chris@0
|
109 $filtered = ucwords($filtered);
|
Chris@0
|
110 return str_replace(' ', '-', $filtered);
|
Chris@0
|
111 }
|
Chris@0
|
112 }
|