You are here

Stream.php in Zircon Profile 8

Namespace

Zend\Diactoros

File

vendor/zendframework/zend-diactoros/src/Stream.php
View source
<?php

/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @see       http://github.com/zendframework/zend-diactoros for the canonical source repository
 * @copyright Copyright (c) 2015 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
 */
namespace Zend\Diactoros;

use InvalidArgumentException;
use RuntimeException;
use Psr\Http\Message\StreamInterface;

/**
 * Implementation of PSR HTTP streams
 */
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) {
      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;
  }

  /**
   * Attach a new stream/resource to the instance.
   *
   * @param string|resource $resource
   * @param string $mode
   * @throws InvalidArgumentException for stream identifier that cannot be
   *     cast to a resource
   * @throws InvalidArgumentException for non-resource stream
   */
  public function attach($resource, $mode = 'r') {
    $this
      ->setStream($resource, $mode);
  }

  /**
   * {@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);
    $mode = $meta['mode'];
    return strstr($mode, 'r') || strstr($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) {
    if (null === $key) {
      return stream_get_meta_data($this->resource);
    }
    $metadata = stream_get_meta_data($this->resource);
    if (!array_key_exists($key, $metadata)) {
      return null;
    }
    return $metadata[$key];
  }

  /**
   * 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;
  }

}

Classes

Namesort descending Description
Stream Implementation of PSR HTTP streams