9da36ff8439da7bc1c999c3e329cc02ef66652e0
[yaffs-website] / vendor / zendframework / zend-diactoros / src / Response / SapiStreamEmitter.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\Response;
9
10 use Psr\Http\Message\ResponseInterface;
11
12 use function is_array;
13 use function preg_match;
14 use function strlen;
15 use function substr;
16
17 /**
18  * @deprecated since 1.8.0. The package zendframework/zend-httphandlerrunner
19  *     now provides this functionality.
20  */
21 class SapiStreamEmitter implements EmitterInterface
22 {
23     use SapiEmitterTrait;
24
25     /**
26      * Emits a response for a PHP SAPI environment.
27      *
28      * Emits the status line and headers via the header() function, and the
29      * body content via the output buffer.
30      *
31      * @param ResponseInterface $response
32      * @param int $maxBufferLength Maximum output buffering size for each iteration
33      */
34     public function emit(ResponseInterface $response, $maxBufferLength = 8192)
35     {
36         $this->assertNoPreviousOutput();
37         $this->emitHeaders($response);
38         $this->emitStatusLine($response);
39
40         $range = $this->parseContentRange($response->getHeaderLine('Content-Range'));
41
42         if (is_array($range) && $range[0] === 'bytes') {
43             $this->emitBodyRange($range, $response, $maxBufferLength);
44             return;
45         }
46
47         $this->emitBody($response, $maxBufferLength);
48     }
49
50     /**
51      * Emit the message body.
52      *
53      * @param ResponseInterface $response
54      * @param int $maxBufferLength
55      */
56     private function emitBody(ResponseInterface $response, $maxBufferLength)
57     {
58         $body = $response->getBody();
59
60         if ($body->isSeekable()) {
61             $body->rewind();
62         }
63
64         if (! $body->isReadable()) {
65             echo $body;
66             return;
67         }
68
69         while (! $body->eof()) {
70             echo $body->read($maxBufferLength);
71         }
72     }
73
74     /**
75      * Emit a range of the message body.
76      *
77      * @param array $range
78      * @param ResponseInterface $response
79      * @param int $maxBufferLength
80      */
81     private function emitBodyRange(array $range, ResponseInterface $response, $maxBufferLength)
82     {
83         list($unit, $first, $last, $length) = $range;
84
85         $body = $response->getBody();
86
87         $length = $last - $first + 1;
88
89         if ($body->isSeekable()) {
90             $body->seek($first);
91
92             $first = 0;
93         }
94
95         if (! $body->isReadable()) {
96             echo substr($body->getContents(), $first, $length);
97             return;
98         }
99
100         $remaining = $length;
101
102         while ($remaining >= $maxBufferLength && ! $body->eof()) {
103             $contents   = $body->read($maxBufferLength);
104             $remaining -= strlen($contents);
105
106             echo $contents;
107         }
108
109         if ($remaining > 0 && ! $body->eof()) {
110             echo $body->read($remaining);
111         }
112     }
113
114     /**
115      * Parse content-range header
116      * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16
117      *
118      * @param string $header
119      * @return false|array [unit, first, last, length]; returns false if no
120      *     content range or an invalid content range is provided
121      */
122     private function parseContentRange($header)
123     {
124         if (preg_match('/(?P<unit>[\w]+)\s+(?P<first>\d+)-(?P<last>\d+)\/(?P<length>\d+|\*)/', $header, $matches)) {
125             return [
126                 $matches['unit'],
127                 (int) $matches['first'],
128                 (int) $matches['last'],
129                 $matches['length'] === '*' ? '*' : (int) $matches['length'],
130             ];
131         }
132         return false;
133     }
134 }