/src/http/Stream.php
https://github.com/bixuehujin/blink · PHP · 320 lines · 187 code · 56 blank · 77 comment · 31 complexity · 03eb75bd1aa180b860f7825c3fb1f52d MD5 · raw file
- <?php
- /**
- * The file is modified from zend-diactoros project.
- *
- * Zend Framework (http://framework.zend.com/)
- *
- * @see http://github.com/zendframework/zend-diactoros for the canonical source repository
- * @copyright Copyright (c) 2015-2016 Zend Technologies USA Inc. (http://www.zend.com)
- * @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
- */
- namespace blink\http;
- use RuntimeException;
- use InvalidArgumentException;
- use Psr\Http\Message\StreamInterface;
- /**
- * Class Stream
- *
- * @package blink\http
- */
- class Stream implements StreamInterface
- {
- /**
- * @var resource
- */
- protected $resource;
- /**
- * @var string|resource
- */
- protected $stream;
- /**
- * @param string|resource $stream
- * @param string $mode Mode with which to open stream
- * @throws InvalidArgumentException
- */
- public function __construct($stream, $mode = 'r')
- {
- $this->setStream($stream, $mode);
- }
- /**
- * {@inheritdoc}
- */
- public function __toString()
- {
- if (! $this->isReadable()) {
- return '';
- }
- try {
- $this->rewind();
- return $this->getContents();
- } catch (RuntimeException $e) {
- var_dump($e);
- return '';
- }
- }
- /**
- * @inheritDoc
- */
- public function close()
- {
- if (!$this->resource) {
- return;
- }
- $resource = $this->detach();
- fclose($resource);
- }
- /**
- * @inheritDoc
- */
- public function detach()
- {
- $resource = $this->resource;
- $this->resource = null;
- return $resource;
- }
- /**
- * @inheritDoc
- */
- public function getSize()
- {
- if (null === $this->resource) {
- return null;
- }
- $stats = fstat($this->resource);
- return $stats['size'];
- }
- /**
- * @inheritDoc
- */
- public function tell()
- {
- if (!$this->resource) {
- throw new RuntimeException('No resource available; cannot tell position');
- }
- $result = ftell($this->resource);
- if (!is_int($result)) {
- throw new RuntimeException('Error occurred during tell operation');
- }
- return $result;
- }
- /**
- * @inheritDoc
- */
- public function eof()
- {
- if (!$this->resource) {
- return true;
- }
- return feof($this->resource);
- }
- /**
- * @inheritDoc
- */
- public function isSeekable()
- {
- if (!$this->resource) {
- return false;
- }
- $meta = stream_get_meta_data($this->resource);
- return $meta['seekable'];
- }
- /**
- * @inheritDoc
- */
- public function seek($offset, $whence = SEEK_SET)
- {
- if (!$this->resource) {
- throw new RuntimeException('No resource available; cannot seek position');
- }
- if (!$this->isSeekable()) {
- throw new RuntimeException('Stream is not seekable');
- }
- $result = fseek($this->resource, $offset, $whence);
- if (0 !== $result) {
- throw new RuntimeException('Error seeking within stream');
- }
- return true;
- }
- /**
- * @inheritDoc
- */
- public function rewind()
- {
- return $this->seek(0);
- }
- /**
- * @inheritDoc
- */
- public function isWritable()
- {
- if (! $this->resource) {
- return false;
- }
- $meta = stream_get_meta_data($this->resource);
- $mode = $meta['mode'];
- return (
- strstr($mode, 'x')
- || strstr($mode, 'w')
- || strstr($mode, 'c')
- || strstr($mode, 'a')
- || strstr($mode, '+')
- );
- }
- /**
- * @inheritDoc
- */
- public function write($string)
- {
- if (!$this->resource) {
- throw new RuntimeException('No resource available; cannot write');
- }
- if (!$this->isWritable()) {
- throw new RuntimeException('Stream is not writable');
- }
- $result = fwrite($this->resource, $string);
- if (false === $result) {
- throw new RuntimeException('Error writing to stream');
- }
- return $result;
- }
- /**
- * @inheritDoc
- */
- public function isReadable()
- {
- if (!$this->resource) {
- return false;
- }
- $meta = stream_get_meta_data($this->resource);
- return strstr($meta['mode'], 'r') || strstr($meta['mode'], '+');
- }
- /**
- * @inheritDoc
- */
- public function read($length)
- {
- if (!$this->resource) {
- throw new RuntimeException('No resource available; cannot read');
- }
- if (!$this->isReadable()) {
- throw new RuntimeException('Stream is not readable');
- }
- $result = fread($this->resource, $length);
- if (false === $result) {
- throw new RuntimeException('Error reading stream');
- }
- return $result;
- }
- /**
- * @inheritDoc
- */
- public function getContents()
- {
- if (!$this->isReadable()) {
- throw new RuntimeException('Stream is not readable');
- }
- $result = stream_get_contents($this->resource);
- if (false === $result) {
- throw new RuntimeException('Error reading from stream');
- }
- return $result;
- }
- /**
- * @inheritDoc
- */
- public function getMetadata($key = null)
- {
- $meta = stream_get_meta_data($this->resource);
- if ($key === null) {
- return $meta;
- }
- return array_key_exists($key, $meta) ? $meta[$key] : null;
- }
- /**
- * Set the internal stream resource.
- *
- * @param string|resource $stream String stream target or stream resource.
- * @param string $mode Resource mode for stream target.
- * @throws InvalidArgumentException for invalid streams or resources.
- */
- private function setStream($stream, $mode = 'r')
- {
- $error = null;
- $resource = $stream;
- if (is_string($stream)) {
- set_error_handler(function ($e) use (&$error) {
- $error = $e;
- }, E_WARNING);
- $resource = fopen($stream, $mode);
- restore_error_handler();
- }
- if ($error) {
- throw new InvalidArgumentException('Invalid stream reference provided');
- }
- if (! is_resource($resource) || 'stream' !== get_resource_type($resource)) {
- throw new InvalidArgumentException(
- 'Invalid stream provided; must be a string stream identifier or stream resource'
- );
- }
- if ($stream !== $resource) {
- $this->stream = $stream;
- }
- $this->resource = $resource;
- }
- }