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()