Permalink
Browse files

Better handling of StreamInterface::detach()

Calling StreamInterface::detach() now returns the underlying resource
or null if no resource is wrapped by the abstraction. Other methods have
been updated to behave without errors if a stream is closed or detached.
  • Loading branch information...
mtdowling committed Jul 9, 2014
1 parent a39ed0b commit 368ee042ef5d88ffbc19632e0c114a54a3ac45b2
Showing with 44 additions and 13 deletions.
  1. +22 −9 src/Stream.php
  2. +10 −3 src/StreamInterface.php
  3. +12 −1 tests/StreamTest.php
View
@@ -82,34 +82,47 @@ public function __destruct()
public function __toString()
{
if (!$this->stream) {
return '';
}
$this->seek(0);
return (string) stream_get_contents($this->stream);
}
public function getContents($maxLength = -1)
{
return stream_get_contents($this->stream, $maxLength);
return $this->stream
? stream_get_contents($this->stream, $maxLength)
: '';
}
public function close()
{
if (is_resource($this->stream)) {
fclose($this->stream);
}
$this->meta = [];
$this->stream = null;
}
public function detach()
{
$this->stream = null;
$result = $this->stream;
$this->stream = $this->size = null;
$this->readable = $this->writable = $this->seekable = false;
return $result;
}
public function getSize()
{
if ($this->size !== null) {
return $this->size;
} elseif (!$this->stream) {
return null;
}
// If the stream is a file based stream and local, then use fstat
@@ -128,27 +141,27 @@ public function getSize()
public function isReadable()
{
return $this->stream && $this->readable;
return $this->readable;
}
public function isWritable()
{
return $this->stream && $this->writable;
return $this->writable;
}
public function isSeekable()
{
return $this->stream && $this->seekable;
return $this->seekable;
}
public function eof()
{
return feof($this->stream);
return $this->stream && feof($this->stream);
}
public function tell()
{
return ftell($this->stream);
return $this->stream ? ftell($this->stream) : false;
}
public function setSize($size)
@@ -167,15 +180,15 @@ public function seek($offset, $whence = SEEK_SET)
public function read($length)
{
return fread($this->stream, $length);
return $this->readable ? fread($this->stream, $length) : '';
}
public function write($string)
{
// We can't know the size after writing anything
$this->size = null;
return fwrite($this->stream, $string);
return $this->writable ? fwrite($this->stream, $string) : false;
}
/**
View
@@ -25,7 +25,14 @@ public function close();
/**
* Separates any underlying resources from the stream.
*
* After the stream has been detached, the stream is in an unusable state.
* After the underlying resource has been detached, the stream object is in
* an unusable state. If you wish to use a Stream object as a PHP stream
* but keep the Stream object in a consistent state, use
* {@see GuzzleHttp\Stream\GuzzleStreamWrapper::getResource}.
*
* @return resource|null Returns the underlying PHP stream resource or null
* if the Stream object did not utilize an underlying
* stream resource.
*/
public function detach();
@@ -68,7 +75,7 @@ public function isSeekable();
* SEEK_CUR: Set position to current location plus offset
* SEEK_END: Set position to end-of-stream plus offset
*
* @return bool Returns TRUE on success or FALSE on failure
* @return bool Returns true on success or false on failure
* @link http://www.php.net/manual/en/function.fseek.php
*/
public function seek($offset, $whence = SEEK_SET);
@@ -86,7 +93,7 @@ public function isWritable();
* @param string $string The string that is to be written.
*
* @return int|bool Returns the number of bytes written to the stream on
* success or FALSE on failure.
* success or false on failure.
*/
public function write($string);
View
@@ -135,8 +135,19 @@ public function testCanDetachStream()
$r = fopen('php://temp', 'w+');
$stream = new Stream($r);
$this->assertTrue($stream->isReadable());
$stream->detach();
$this->assertSame($r, $stream->detach());
$this->assertNull($stream->detach());
$this->assertFalse($stream->isReadable());
$this->assertSame('', $stream->read(10));
$this->assertFalse($stream->isWritable());
$this->assertFalse($stream->write('foo'));
$this->assertFalse($stream->isSeekable());
$this->assertFalse($stream->seek(10));
$this->assertFalse($stream->tell());
$this->assertFalse($stream->eof());
$this->assertNull($stream->getSize());
$this->assertSame('', (string) $stream);
$this->assertSame('', $stream->getContents());
$stream->close();
}

0 comments on commit 368ee04

Please sign in to comment.