From c339512f012e714bb63f018eef51c122718551a5 Mon Sep 17 00:00:00 2001 From: PJ Dietz Date: Sun, 9 Aug 2020 13:29:05 -0400 Subject: [PATCH] Add type hints to Stream, UploadedFile, and Uri --- psalm.xml | 1 + src/Message/Stream.php | 2 + src/Message/UploadedFile.php | 16 +++++- src/Message/Uri.php | 60 ++++++++++---------- test/tests/unit/Message/UploadedFileTest.php | 7 ++- 5 files changed, 51 insertions(+), 35 deletions(-) diff --git a/psalm.xml b/psalm.xml index 9b0f03a..1f59fbb 100644 --- a/psalm.xml +++ b/psalm.xml @@ -17,6 +17,7 @@ + diff --git a/src/Message/Stream.php b/src/Message/Stream.php index 4543e38..7bcd6f9 100644 --- a/src/Message/Stream.php +++ b/src/Message/Stream.php @@ -166,6 +166,7 @@ class Stream implements StreamInterface * PHP $whence values for `fseek()`. SEEK_SET: Set position equal to * offset bytes SEEK_CUR: Set position to current location plus offset * SEEK_END: Set position to end-of-stream plus offset. + * @return void * @throws \RuntimeException on failure. */ public function seek($offset, $whence = SEEK_SET) @@ -191,6 +192,7 @@ class Stream implements StreamInterface * * @see seek() * @link http://www.php.net/manual/en/function.fseek.php + * @return void * @throws \RuntimeException on failure. */ public function rewind() diff --git a/src/Message/UploadedFile.php b/src/Message/UploadedFile.php index d5cfc9b..aa8094e 100644 --- a/src/Message/UploadedFile.php +++ b/src/Message/UploadedFile.php @@ -10,12 +10,19 @@ use Psr\Http\Message\UploadedFileInterface; */ class UploadedFile implements UploadedFileInterface { + /** @var string */ private $clientFilename; + /** @var string */ private $clientMediaType; + /** @var int */ private $error; + /** @var bool */ private $moved = false; + /** @var int */ private $size; + /** @var StreamInterface */ private $stream; + /** @var string|null */ private $tmpName; /** @@ -57,10 +64,11 @@ class UploadedFile implements UploadedFileInterface $this->size = $size; if (file_exists($tmpName)) { + $this->stream = new Stream(fopen($tmpName, 'r')); $this->tmpName = $tmpName; - $this->stream = new Stream(fopen($tmpName, "r")); } else { $this->stream = new NullStream(); + $this->tmpName = null; } } @@ -82,8 +90,11 @@ class UploadedFile implements UploadedFileInterface */ public function getStream() { + if ($this->tmpName === null) { + throw new \RuntimeException("Unable to read uploaded file."); + } if ($this->moved) { - throw new \RuntimeException("File has already been moved"); + throw new \RuntimeException("File has already been moved."); } if (php_sapi_name() !== "cli" && !is_uploaded_file($this->tmpName)) { throw new \RuntimeException("File is not an uploaded file."); @@ -105,6 +116,7 @@ class UploadedFile implements UploadedFileInterface * @see http://php.net/is_uploaded_file * @see http://php.net/move_uploaded_file * @param string $path Path to which to move the uploaded file. + * @return void * @throws \InvalidArgumentException if the $path specified is invalid. * @throws \RuntimeException on any error during the move operation, or on * the second or subsequent call to the method. diff --git a/src/Message/Uri.php b/src/Message/Uri.php index 6feaffb..78007b8 100644 --- a/src/Message/Uri.php +++ b/src/Message/Uri.php @@ -40,36 +40,36 @@ class Uri implements UriInterface /** * @param string $uri A string representation of a URI. */ - public function __construct($uri = "") + public function __construct(string $uri = '') { - if (is_string($uri) && $uri !== "") { - $parsed = parse_url($uri); - if ($parsed !== false) { - if (isset($parsed["scheme"])) { - $this->scheme = $parsed["scheme"]; - } - if (isset($parsed["host"])) { - $this->host = strtolower($parsed["host"]); - } - if (isset($parsed["port"])) { - $this->port = $parsed["port"]; - } - if (isset($parsed["user"])) { - $this->user = $parsed["user"]; - } - if (isset($parsed["pass"])) { - $this->password = $parsed["pass"]; - } - if (isset($parsed["path"])) { - $this->path = $parsed["path"]; - } - if (isset($parsed["query"])) { - $this->query = $parsed["query"]; - } - if (isset($parsed["fragment"])) { - $this->fragment = $parsed["fragment"]; - } - } + $parsed = parse_url($uri); + if (!$parsed) { + return; + } + + if (isset($parsed['scheme'])) { + $this->scheme = $parsed['scheme']; + } + if (isset($parsed['host'])) { + $this->host = strtolower($parsed['host']); + } + if (isset($parsed['port'])) { + $this->port = $parsed['port']; + } + if (isset($parsed['user'])) { + $this->user = $parsed['user']; + } + if (isset($parsed['pass'])) { + $this->password = $parsed['pass']; + } + if (isset($parsed['path'])) { + $this->path = $parsed['path']; + } + if (isset($parsed['query'])) { + $this->query = $parsed['query']; + } + if (isset($parsed['fragment'])) { + $this->fragment = $parsed['fragment']; } } @@ -538,7 +538,7 @@ class Uri implements UriInterface $reserved = ':/?#[]@!$&\'()*+,;='; $reserved = preg_quote($reserved); $pattern = '~(?:%(?![a-fA-F0-9]{2}))|(?:[^%a-zA-Z0-9\-\.\_\~' . $reserved . ']{1})~'; - $callback = function ($matches) { + $callback = function (array $matches): string { return urlencode($matches[0]); }; return preg_replace_callback($pattern, $callback, $subject); diff --git a/test/tests/unit/Message/UploadedFileTest.php b/test/tests/unit/Message/UploadedFileTest.php index 09b65f6..bab21ee 100644 --- a/test/tests/unit/Message/UploadedFileTest.php +++ b/test/tests/unit/Message/UploadedFileTest.php @@ -40,7 +40,7 @@ class UploadedFileTest extends TestCase public function testGetStreamReturnsStreamInterface() { - $file = new UploadedFile("", "", 0, "", 0); + $file = new UploadedFile("", "", 0, $this->tmpName, 0); $this->assertInstanceOf(StreamInterface::class, $file->getStream()); } @@ -53,10 +53,11 @@ class UploadedFileTest extends TestCase $this->assertEquals($content, (string) $stream); } - public function testGetStreamReturnsEmptyStreamForNoFile() + public function testGetStreamThrowsRuntimeExceptionForNoFile() { $file = new UploadedFile("", "", 0, "", 0); - $this->assertTrue($file->getStream()->eof()); + $this->expectException(RuntimeException::class); + $file->getStream(); } public function testGetStreamThrowsExceptionAfterMoveTo()