diff --git a/src/Routing/Router.php b/src/Routing/Router.php index 36dd59e..38c350c 100644 --- a/src/Routing/Router.php +++ b/src/Routing/Router.php @@ -9,7 +9,7 @@ use WellRESTed\Message\Response; use WellRESTed\Message\ServerRequest; use WellRESTed\Routing\Route\RouteFactory; use WellRESTed\Routing\Route\RouteFactoryInterface; -use WellRESTed\Stream\StringStream; +use WellRESTed\Stream\Stream; class Router implements MiddlewareInterface { @@ -64,7 +64,7 @@ class Router implements MiddlewareInterface $this->routeTable->dispatch($request, $response); } catch (HttpException $e) { $response = $response->withStatus($e->getCode()); - $response = $response->withBody(new StringStream($e->getMessage())); + $response = $response->withBody(new Stream($e->getMessage())); } $statusCode = $response->getStatusCode(); if (isset($this->statusHandlers[$statusCode])) { diff --git a/src/Stream/Stream.php b/src/Stream/Stream.php index b0c901c..6257298 100644 --- a/src/Stream/Stream.php +++ b/src/Stream/Stream.php @@ -7,15 +7,27 @@ use Psr\Http\Message\StreamableInterface; class Stream implements StreamableInterface { /** @var resource */ - private $handle; + private $resource; /** - * @param resource $handle A file system pointer resource that is typically created using fopen(). + * Create a new Stream passing either a stream resource handle (e.g., + * from fopen) or a string. + * + * If $resource is a string, the Stream will open a php://temp stream, + * write the string to the stream, and use that temp resource. + * + * @param resource|string $resource A file system pointer resource or + * string */ - public function __construct($handle) + public function __construct($resource) { - if (is_resource($handle)) { - $this->handle = $handle; + if (is_resource($resource) && get_resource_type($resource) === "stream") { + $this->resource = $resource; + } elseif (is_string($resource)) { + $this->resource = fopen("php://temp", "r+"); + if ($resource !== "") { + $this->write($resource); + } } else { throw new \InvalidArgumentException("Expected a resource handler."); } @@ -33,7 +45,7 @@ class Stream implements StreamableInterface */ public function __toString() { - rewind($this->handle); + rewind($this->resource); return $this->getContents(); } @@ -44,7 +56,7 @@ class Stream implements StreamableInterface */ public function close() { - fclose($this->handle); + fclose($this->resource); } /** @@ -56,8 +68,8 @@ class Stream implements StreamableInterface */ public function detach() { - $stream = $this->handle; - $this->handle = null; + $stream = $this->resource; + $this->resource = null; return $stream; } @@ -68,7 +80,7 @@ class Stream implements StreamableInterface */ public function getSize() { - $statistics = fstat($this->handle); + $statistics = fstat($this->resource); return $statistics["size"] ?: null; } @@ -79,7 +91,7 @@ class Stream implements StreamableInterface */ public function tell() { - return ftell($this->handle); + return ftell($this->resource); } /** @@ -89,7 +101,7 @@ class Stream implements StreamableInterface */ public function eof() { - return feof($this->handle); + return feof($this->resource); } /** @@ -116,7 +128,7 @@ class Stream implements StreamableInterface */ public function seek($offset, $whence = SEEK_SET) { - fseek($this->handle, $offset, $whence); + fseek($this->resource, $offset, $whence); } /** @@ -132,7 +144,7 @@ class Stream implements StreamableInterface */ public function rewind() { - rewind($this->handle); + rewind($this->resource); } /** @@ -155,7 +167,7 @@ class Stream implements StreamableInterface */ public function write($string) { - return fwrite($this->handle, $string); + return fwrite($this->resource, $string); } /** @@ -180,7 +192,7 @@ class Stream implements StreamableInterface */ public function read($length) { - return fread($this->handle, $length); + return fread($this->resource, $length); } /** @@ -190,7 +202,7 @@ class Stream implements StreamableInterface */ public function getContents() { - return stream_get_contents($this->handle); + return stream_get_contents($this->resource); } /** @@ -207,7 +219,7 @@ class Stream implements StreamableInterface */ public function getMetadata($key = null) { - $metadata = stream_get_meta_data($this->handle); + $metadata = stream_get_meta_data($this->resource); if ($key === null) { return $metadata; } else { diff --git a/src/Stream/StringStream.php b/src/Stream/StringStream.php deleted file mode 100644 index 63da573..0000000 --- a/src/Stream/StringStream.php +++ /dev/null @@ -1,13 +0,0 @@ -assertNotNull($stream); - } - - public function testCreatesInstanceWithString() - { - $message = "Hello, World!"; - $stream = new StringStream($message); - $this->assertEquals($message, (string) $stream); - } - - public function testAllowsWriting() - { - $message = "Hello, World!"; - $stream = new StringStream(); - $stream->write("Hello,"); - $stream->write(" World!"); - $this->assertEquals($message, (string) $stream); - } -} diff --git a/test/tests/unit/Stream/StreamTest.php b/test/tests/unit/Stream/StreamTest.php index 014f499..d6fa259 100644 --- a/test/tests/unit/Stream/StreamTest.php +++ b/test/tests/unit/Stream/StreamTest.php @@ -4,134 +4,125 @@ namespace WellRESTed\Test\Stream; use WellRESTed\Stream\Stream; +/** + * @uses WellRESTed\Stream\Stream + */ class StreamTest extends \PHPUnit_Framework_TestCase { - private $handle; + private $resource; private $content = "Hello, world!"; public function setUp() { - $this->handle = fopen("php://memory", "w+"); - fwrite($this->handle, $this->content); + $this->resource = fopen("php://memory", "w+"); + fwrite($this->resource, $this->content); } public function tearDown() { - if (is_resource($this->handle)) { - fclose($this->handle); + if (is_resource($this->resource)) { + fclose($this->resource); } } /** * @covers WellRESTed\Stream\Stream::__construct() */ - public function testCreatesInstance() + public function testCreatesInstanceWithStreamResource() { - $stream = new Stream($this->handle); + $stream = new Stream($this->resource); + $this->assertNotNull($stream); + } + + public function testCreatesInstanceWithString() + { + $stream = new Stream("Hello, world!"); $this->assertNotNull($stream); } /** * @covers WellRESTed\Stream\Stream::__construct() * @expectedException \InvalidArgumentException + * @dataProvider invalidResourceProvider */ - public function testThrowsExceptiondWithoutHandle() + public function testThrowsExceptiondWithInvalidResource($resource) { - new Stream(null); + new Stream($resource); + } + + public function invalidResourceProvider() + { + return [ + [null], + [true], + [4], + [[]] + ]; } /** * @covers WellRESTed\Stream\Stream::__toString() - * @uses WellRESTed\Stream\Stream */ public function testCastsToString() { - $content = "Hello, world!"; - - $h = fopen("php://memory", "w+"); - fwrite($h, $content); - rewind($h); - - $stream = new Stream($h); - $this->assertEquals($content, (string) $stream); - } - - /** - * @covers WellRESTed\Stream\Stream::__toString() - * @uses WellRESTed\Stream\Stream - */ - public function testRewindsBeforeCastingToString() - { - $content = "Hello, world!"; - - $h = fopen("php://memory", "w+"); - fwrite($h, $content); - - $stream = new Stream($h); - $this->assertEquals($content, (string) $stream); + $stream = new Stream($this->resource); + $this->assertEquals($this->content, (string) $stream); } /** * @covers WellRESTed\Stream\Stream::close() - * @uses WellRESTed\Stream\Stream */ public function testClosesHandle() { - $stream = new Stream($this->handle); + $stream = new Stream($this->resource); $stream->close(); - $this->assertFalse(is_resource($this->handle)); + $this->assertFalse(is_resource($this->resource)); } /** * @covers WellRESTed\Stream\Stream::detach() - * @uses WellRESTed\Stream\Stream */ public function testDetachReturnsHandle() { - $stream = new Stream($this->handle); - $h = $stream->detach(); - $this->assertSame($this->handle, $h); + $stream = new Stream($this->resource); + $this->assertSame($this->resource, $stream->detach()); } /** * @covers WellRESTed\Stream\Stream::detach() - * @uses WellRESTed\Stream\Stream */ public function testDetachUnsetsInstanceVariable() { - $stream = new Stream($this->handle); + $stream = new Stream($this->resource); $stream->detach(); $this->assertNull($stream->detach()); } /** * @covers WellRESTed\Stream\Stream::getSize - * @uses WellRESTed\Stream\Stream */ public function testReturnsSize() { - $stream = new Stream($this->handle); + $stream = new Stream($this->resource); $this->assertEquals(strlen($this->content), $stream->getSize()); } /** * @covers WellRESTed\Stream\Stream::tell - * @uses WellRESTed\Stream\Stream */ public function testTellReturnsHandlePosition() { - $stream = new Stream($this->handle); - fseek($this->handle, 10); + $stream = new Stream($this->resource); + fseek($this->resource, 10); $this->assertEquals(10, $stream->tell()); } /** * @covers WellRESTed\Stream\Stream::eof - * @uses WellRESTed\Stream\Stream */ public function testReturnsOef() { - $stream = new Stream($this->handle); + $stream = new Stream($this->resource); $stream->rewind(); $this->assertFalse($stream->eof()); $stream->getContents(); @@ -140,58 +131,53 @@ class StreamTest extends \PHPUnit_Framework_TestCase /** * @covers WellRESTed\Stream\Stream::isSeekable - * @uses WellRESTed\Stream\Stream */ public function testReadsSeekableStatusFromMetadata() { - $stream = new Stream($this->handle); - $metadata = stream_get_meta_data($this->handle); + $stream = new Stream($this->resource); + $metadata = stream_get_meta_data($this->resource); $seekable = $metadata["seekable"] == 1; $this->assertEquals($seekable, $stream->isSeekable()); } /** * @covers WellRESTed\Stream\Stream::seek - * @uses WellRESTed\Stream\Stream */ public function testSeeksToPosition() { - $stream = new Stream($this->handle); + $stream = new Stream($this->resource); $stream->seek(10); - $this->assertEquals(10, ftell($this->handle)); + $this->assertEquals(10, ftell($this->resource)); } /** * @covers WellRESTed\Stream\Stream::rewind - * @uses WellRESTed\Stream\Stream */ public function testRewindReturnsToBeginning() { - $stream = new Stream($this->handle); + $stream = new Stream($this->resource); $stream->seek(10); $stream->rewind(); - $this->assertEquals(0, ftell($this->handle)); + $this->assertEquals(0, ftell($this->resource)); } /** * @covers WellRESTed\Stream\Stream::write - * @uses WellRESTed\Stream\Stream */ public function testWritesToHandle() { $message = "\nThis is a stream."; - $stream = new Stream($this->handle); + $stream = new Stream($this->resource); $stream->write($message); $this->assertEquals($this->content . $message, (string) $stream); } /** * @covers WellRESTed\Stream\Stream::read - * @uses WellRESTed\Stream\Stream */ public function testReadsFromStream() { - $stream = new Stream($this->handle); + $stream = new Stream($this->resource); $stream->seek(7); $string = $stream->read(5); $this->assertEquals("world", $string); @@ -199,11 +185,10 @@ class StreamTest extends \PHPUnit_Framework_TestCase /** * @covers WellRESTed\Stream\Stream::getContents - * @uses WellRESTed\Stream\Stream */ public function testReadsToEnd() { - $stream = new Stream($this->handle); + $stream = new Stream($this->resource); $stream->seek(7); $string = $stream->getContents(); $this->assertEquals("world!", $string); @@ -211,28 +196,25 @@ class StreamTest extends \PHPUnit_Framework_TestCase /** * @covers WellRESTed\Stream\Stream::getMetadata - * @uses WellRESTed\Stream\Stream */ public function testReturnsMetadataArray() { - $stream = new Stream($this->handle); - $this->assertEquals(stream_get_meta_data($this->handle), $stream->getMetadata()); + $stream = new Stream($this->resource); + $this->assertEquals(stream_get_meta_data($this->resource), $stream->getMetadata()); } /** * @covers WellRESTed\Stream\Stream::getMetadata - * @uses WellRESTed\Stream\Stream */ public function testReturnsMetadataItem() { - $stream = new Stream($this->handle); - $metadata = stream_get_meta_data($this->handle); + $stream = new Stream($this->resource); + $metadata = stream_get_meta_data($this->resource); $this->assertEquals($metadata["mode"], $stream->getMetadata("mode")); } /** * @covers WellRESTed\Stream\Stream::isReadable - * @uses WellRESTed\Stream\Stream * @dataProvider modeProvider */ public function testReturnsIsReadableForReadableStreams($mode, $readable, $writeable) @@ -241,15 +223,13 @@ class StreamTest extends \PHPUnit_Framework_TestCase if ($mode[0] === "x") { unlink($tmp); } - fclose($this->handle); - $this->handle = fopen($tmp, $mode); - $stream = new Stream($this->handle); + $resource = fopen($tmp, $mode); + $stream = new Stream($resource); $this->assertEquals($readable, $stream->isReadable()); } /** * @covers WellRESTed\Stream\Stream::isWritable - * @uses WellRESTed\Stream\Stream * @dataProvider modeProvider */ public function testReturnsIsWritableForWritableStreams($mode, $readable, $writeable) @@ -258,9 +238,8 @@ class StreamTest extends \PHPUnit_Framework_TestCase if ($mode[0] === "x") { unlink($tmp); } - fclose($this->handle); - $this->handle = fopen($tmp, $mode); - $stream = new Stream($this->handle); + $resource = fopen($tmp, $mode); + $stream = new Stream($resource); $this->assertEquals($writeable, $stream->isWritable()); }