annotate vendor/zendframework/zend-diactoros/src/Response/SapiStreamEmitter.php @ 0:c75dbcec494b

Initial commit from drush-created site
author Chris Cannam
date Thu, 05 Jul 2018 14:24:15 +0000
parents
children 5311817fb629
rev   line source
Chris@0 1 <?php
Chris@0 2 /**
Chris@0 3 * Zend Framework (http://framework.zend.com/)
Chris@0 4 *
Chris@0 5 * @see http://github.com/zendframework/zend-diactoros for the canonical source repository
Chris@0 6 * @copyright Copyright (c) 2015-2016 Zend Technologies USA Inc. (http://www.zend.com)
Chris@0 7 * @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
Chris@0 8 */
Chris@0 9
Chris@0 10 namespace Zend\Diactoros\Response;
Chris@0 11
Chris@0 12 use Psr\Http\Message\ResponseInterface;
Chris@0 13 use RuntimeException;
Chris@0 14 use Zend\Diactoros\RelativeStream;
Chris@0 15
Chris@0 16 class SapiStreamEmitter implements EmitterInterface
Chris@0 17 {
Chris@0 18 use SapiEmitterTrait;
Chris@0 19
Chris@0 20 /**
Chris@0 21 * Emits a response for a PHP SAPI environment.
Chris@0 22 *
Chris@0 23 * Emits the status line and headers via the header() function, and the
Chris@0 24 * body content via the output buffer.
Chris@0 25 *
Chris@0 26 * @param ResponseInterface $response
Chris@0 27 * @param int $maxBufferLength Maximum output buffering size for each iteration
Chris@0 28 */
Chris@0 29 public function emit(ResponseInterface $response, $maxBufferLength = 8192)
Chris@0 30 {
Chris@0 31 if (headers_sent()) {
Chris@0 32 throw new RuntimeException('Unable to emit response; headers already sent');
Chris@0 33 }
Chris@0 34
Chris@0 35 $response = $this->injectContentLength($response);
Chris@0 36
Chris@0 37 $this->emitStatusLine($response);
Chris@0 38 $this->emitHeaders($response);
Chris@0 39 $this->flush();
Chris@0 40
Chris@0 41 $range = $this->parseContentRange($response->getHeaderLine('Content-Range'));
Chris@0 42
Chris@0 43 if (is_array($range) && $range[0] === 'bytes') {
Chris@0 44 $this->emitBodyRange($range, $response, $maxBufferLength);
Chris@0 45 return;
Chris@0 46 }
Chris@0 47
Chris@0 48 $this->emitBody($response, $maxBufferLength);
Chris@0 49 }
Chris@0 50
Chris@0 51 /**
Chris@0 52 * Emit the message body.
Chris@0 53 *
Chris@0 54 * @param ResponseInterface $response
Chris@0 55 * @param int $maxBufferLength
Chris@0 56 */
Chris@0 57 private function emitBody(ResponseInterface $response, $maxBufferLength)
Chris@0 58 {
Chris@0 59 $body = $response->getBody();
Chris@0 60
Chris@0 61 if ($body->isSeekable()) {
Chris@0 62 $body->rewind();
Chris@0 63 }
Chris@0 64
Chris@0 65 if (! $body->isReadable()) {
Chris@0 66 echo $body;
Chris@0 67 return;
Chris@0 68 }
Chris@0 69
Chris@0 70 while (! $body->eof()) {
Chris@0 71 echo $body->read($maxBufferLength);
Chris@0 72 }
Chris@0 73 }
Chris@0 74
Chris@0 75 /**
Chris@0 76 * Emit a range of the message body.
Chris@0 77 *
Chris@0 78 * @param array $range
Chris@0 79 * @param ResponseInterface $response
Chris@0 80 * @param int $maxBufferLength
Chris@0 81 */
Chris@0 82 private function emitBodyRange(array $range, ResponseInterface $response, $maxBufferLength)
Chris@0 83 {
Chris@0 84 list($unit, $first, $last, $length) = $range;
Chris@0 85
Chris@0 86 $body = $response->getBody();
Chris@0 87
Chris@0 88 $length = $last - $first + 1;
Chris@0 89
Chris@0 90 if ($body->isSeekable()) {
Chris@0 91 $body->seek($first);
Chris@0 92
Chris@0 93 $first = 0;
Chris@0 94 }
Chris@0 95
Chris@0 96 if (! $body->isReadable()) {
Chris@0 97 echo substr($body->getContents(), $first, $length);
Chris@0 98 return;
Chris@0 99 }
Chris@0 100
Chris@0 101 $remaining = $length;
Chris@0 102
Chris@0 103 while ($remaining >= $maxBufferLength && ! $body->eof()) {
Chris@0 104 $contents = $body->read($maxBufferLength);
Chris@0 105 $remaining -= strlen($contents);
Chris@0 106
Chris@0 107 echo $contents;
Chris@0 108 }
Chris@0 109
Chris@0 110 if ($remaining > 0 && ! $body->eof()) {
Chris@0 111 echo $body->read($remaining);
Chris@0 112 }
Chris@0 113 }
Chris@0 114
Chris@0 115 /**
Chris@0 116 * Parse content-range header
Chris@0 117 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16
Chris@0 118 *
Chris@0 119 * @param string $header
Chris@0 120 * @return false|array [unit, first, last, length]; returns false if no
Chris@0 121 * content range or an invalid content range is provided
Chris@0 122 */
Chris@0 123 private function parseContentRange($header)
Chris@0 124 {
Chris@0 125 if (preg_match('/(?P<unit>[\w]+)\s+(?P<first>\d+)-(?P<last>\d+)\/(?P<length>\d+|\*)/', $header, $matches)) {
Chris@0 126 return [
Chris@0 127 $matches['unit'],
Chris@0 128 (int) $matches['first'],
Chris@0 129 (int) $matches['last'],
Chris@0 130 $matches['length'] === '*' ? '*' : (int) $matches['length'],
Chris@0 131 ];
Chris@0 132 }
Chris@0 133 return false;
Chris@0 134 }
Chris@0 135 }