Change Request constructor signature

Various updates to Message classes
This commit is contained in:
PJ Dietz 2020-08-09 13:10:14 -04:00
parent bdc5ac40d9
commit 7ade042b4b
7 changed files with 101 additions and 61 deletions

View File

@ -13,4 +13,16 @@
<directory name="vendor" /> <directory name="vendor" />
</ignoreFiles> </ignoreFiles>
</projectFiles> </projectFiles>
<issueHandlers>
<DocblockTypeContradiction>
<errorLevel type="suppress">
<file name="src/Message/ServerRequest.php" />
</errorLevel>
</DocblockTypeContradiction>
<MissingClosureParamType>
<errorLevel type="suppress">
<file name="src/Message/Message.php" />
</errorLevel>
</MissingClosureParamType>
</issueHandlers>
</psalm> </psalm>

View File

@ -28,11 +28,13 @@ abstract class Message implements MessageInterface
* *
* @param array $headers Associative array with header field names as * @param array $headers Associative array with header field names as
* (string) keys and lists of header field values (string[]) as values. * (string) keys and lists of header field values (string[]) as values.
* @param StreamInterface $body A stream representation of the message * @param StreamInterface|null $body A stream representation of the message
* entity body * entity body
*/ */
public function __construct(array $headers = null, StreamInterface $body = null) public function __construct(
{ array $headers = [],
?StreamInterface $body = null
) {
$this->headers = new HeaderCollection(); $this->headers = new HeaderCollection();
if ($headers) { if ($headers) {
foreach ($headers as $name => $values) { foreach ($headers as $name => $values) {
@ -265,22 +267,32 @@ abstract class Message implements MessageInterface
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
private function getValidatedHeaders($name, $value) /**
* @param mixed $name
* @param mixed|mixed[] $values
* @return string[]
* @throws \InvalidArgumentException Name is not a string or value is not
* a string or array of strings
*/
private function getValidatedHeaders($name, $values)
{ {
$is_allowed = function ($item) {
return is_string($item) || is_numeric($item);
};
if (!is_string($name)) { if (!is_string($name)) {
throw new \InvalidArgumentException('Header name must be a string'); throw new \InvalidArgumentException('Header name must be a string');
} }
if ($is_allowed($value)) { if (!is_array($values)) {
return [$value]; $values = [$values];
} elseif (is_array($value) && count($value) === count(array_filter($value, $is_allowed))) { }
return $value;
} else { $isNotStringOrNumber = function ($item): bool {
return !(is_string($item) || is_numeric($item));
};
$invalid = array_filter($values, $isNotStringOrNumber);
if ($invalid) {
throw new \InvalidArgumentException('Header values must be a string or string[]'); throw new \InvalidArgumentException('Header values must be a string or string[]');
} }
return array_map('strval', $values);
} }
} }

View File

@ -91,6 +91,7 @@ class NullStream implements StreamInterface
* PHP $whence values for `fseek()`. SEEK_SET: Set position equal to * PHP $whence values for `fseek()`. SEEK_SET: Set position equal to
* offset bytes SEEK_CUR: Set position to current location plus offset * offset bytes SEEK_CUR: Set position to current location plus offset
* SEEK_END: Set position to end-of-stream plus offset. * SEEK_END: Set position to end-of-stream plus offset.
* @return void
* @throws \RuntimeException on failure. * @throws \RuntimeException on failure.
*/ */
public function seek($offset, $whence = SEEK_SET) public function seek($offset, $whence = SEEK_SET)
@ -103,6 +104,7 @@ class NullStream implements StreamInterface
* *
* @see seek() * @see seek()
* @link http://www.php.net/manual/en/function.fseek.php * @link http://www.php.net/manual/en/function.fseek.php
* @return void
* @throws \RuntimeException on failure. * @throws \RuntimeException on failure.
*/ */
public function rewind() public function rewind()

View File

@ -22,7 +22,7 @@ class Request extends Message implements RequestInterface
{ {
/** @var string */ /** @var string */
protected $method; protected $method;
/** @var string */ /** @var string|null */
protected $requestTarget; protected $requestTarget;
/** @var UriInterface */ /** @var UriInterface */
protected $uri; protected $uri;
@ -33,26 +33,24 @@ class Request extends Message implements RequestInterface
* Create a new Request. * Create a new Request.
* *
* @see \WellRESTed\Message\Message * @see \WellRESTed\Message\Message
* @param UriInterface $uri * @param string|UriInterface $uri
* @param string $method * @param string $method
* @param array $headers * @param array $headers
* @param StreamInterface $body * @param StreamInterface|null $body
*/ */
public function __construct( public function __construct(
UriInterface $uri = null, string $method = 'GET',
$method = "GET", $uri = '',
array $headers = null, array $headers = [],
StreamInterface $body = null ?StreamInterface $body = null
) { ) {
parent::__construct($headers, $body); parent::__construct($headers, $body);
if ($uri !== null) {
$this->uri = $uri;
} else {
$this->uri = new Uri();
}
$this->method = $method; $this->method = $method;
if (!($uri instanceof UriInterface)) {
$uri = new Uri($uri);
}
$this->uri = $uri;
$this->requestTarget = null;
} }
public function __clone() public function __clone()
@ -83,7 +81,7 @@ class Request extends Message implements RequestInterface
public function getRequestTarget() public function getRequestTarget()
{ {
// Use the explicitly set request target first. // Use the explicitly set request target first.
if (isset($this->requestTarget)) { if ($this->requestTarget !== null) {
return $this->requestTarget; return $this->requestTarget;
} }
@ -211,7 +209,7 @@ class Request extends Message implements RequestInterface
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** /**
* @param string $method * @param mixed $method
* @return string * @return string
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
*/ */

View File

@ -36,10 +36,13 @@ class Response extends Message implements ResponseInterface
* @see \WellRESTed\Message\Message * @see \WellRESTed\Message\Message
* @param int $statusCode * @param int $statusCode
* @param array $headers * @param array $headers
* @param StreamInterface $body * @param StreamInterface|null $body
*/ */
public function __construct($statusCode = 500, array $headers = null, StreamInterface $body = null) public function __construct(
{ int $statusCode = 500,
array $headers = [],
?StreamInterface $body = null
) {
parent::__construct($headers, $body); parent::__construct($headers, $body);
$this->statusCode = $statusCode; $this->statusCode = $statusCode;
$this->reasonPhrase = $this->getDefaultReasonPhraseForStatusCode($statusCode); $this->reasonPhrase = $this->getDefaultReasonPhraseForStatusCode($statusCode);

View File

@ -5,6 +5,7 @@ namespace WellRESTed\Message;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
use Psr\Http\Message\UploadedFileInterface; use Psr\Http\Message\UploadedFileInterface;
use Psr\Http\Message\UriInterface;
/** /**
* Representation of an incoming, server-side HTTP request. * Representation of an incoming, server-side HTTP request.
@ -336,9 +337,13 @@ class ServerRequest extends Request implements ServerRequestInterface
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
protected function readFromServerRequest(array $attributes = null) /**
* @param array $attributes
* @return void
*/
protected function readFromServerRequest(array $attributes = [])
{ {
$this->attributes = $attributes ?: []; $this->attributes = $attributes;
$this->serverParams = $_SERVER; $this->serverParams = $_SERVER;
$this->cookieParams = $_COOKIE; $this->cookieParams = $_COOKIE;
$this->readUploadedFiles($_FILES); $this->readUploadedFiles($_FILES);
@ -367,7 +372,7 @@ class ServerRequest extends Request implements ServerRequestInterface
} }
} }
protected function readUploadedFiles($input) protected function readUploadedFiles(array $input): void
{ {
$uploadedFiles = []; $uploadedFiles = [];
foreach ($input as $name => $value) { foreach ($input as $name => $value) {
@ -376,8 +381,11 @@ class ServerRequest extends Request implements ServerRequestInterface
$this->uploadedFiles = $uploadedFiles; $this->uploadedFiles = $uploadedFiles;
} }
protected function addUploadedFilesToBranch(&$branch, $name, $value) protected function addUploadedFilesToBranch(
{ array &$branch,
string $name,
array $value
): void {
// Check for each of the expected keys. // Check for each of the expected keys.
if (isset($value["name"], $value["type"], $value["tmp_name"], $value["error"], $value["size"])) { if (isset($value["name"], $value["type"], $value["tmp_name"], $value["error"], $value["size"])) {
// This is a file. It may be a single file, or a list of files. // This is a file. It may be a single file, or a list of files.
@ -419,7 +427,7 @@ class ServerRequest extends Request implements ServerRequestInterface
} }
} }
protected function readUri() protected function readUri(): UriInterface
{ {
$uri = ""; $uri = "";
@ -449,7 +457,7 @@ class ServerRequest extends Request implements ServerRequestInterface
* @return static * @return static
* @static * @static
*/ */
public static function getServerRequest(array $attributes = null) public static function getServerRequest(array $attributes = [])
{ {
$request = new static(); $request = new static();
$request->readFromServerRequest($attributes); $request->readFromServerRequest($attributes);
@ -480,28 +488,22 @@ class ServerRequest extends Request implements ServerRequestInterface
protected function getServerRequestHeaders() protected function getServerRequestHeaders()
{ {
// http://www.php.net/manual/en/function.getallheaders.php#84262 // http://www.php.net/manual/en/function.getallheaders.php#84262
$headers = array(); $headers = [];
foreach ($_SERVER as $name => $value) { foreach ($_SERVER as $name => $value) {
if (substr($name, 0, 5) === "HTTP_") { if (substr($name, 0, 5) === "HTTP_") {
$name = $this->normalizeHeaderName(substr($name, 5)); $name = $this->normalizeHeaderName(substr($name, 5));
$headers[$name] = $value; $headers[$name] = trim($value);
} elseif ($this->isContentHeader($name, $value)) { } elseif ($this->isContentHeader($name) && !empty(trim($value))) {
$name = $this->normalizeHeaderName($name); $name = $this->normalizeHeaderName($name);
$headers[$name] = $value; $headers[$name] = trim($value);
} }
} }
return $headers; return $headers;
} }
/** private function isContentHeader(string $name): bool
* @param $name
* @param $value
* @return bool
*/
private function isContentHeader($name, $value)
{ {
return ($name === "CONTENT_LENGTH" || $name === "CONTENT_TYPE") return ($name === 'CONTENT_LENGTH' || $name === 'CONTENT_TYPE');
&& trim($value);
} }
/** /**
@ -540,7 +542,11 @@ class ServerRequest extends Request implements ServerRequestInterface
return true; return true;
} }
private function isValidUploadedFilesBranch($branch) /**
* @param UploadedFileInterface|array $branch
* @return bool
*/
private function isValidUploadedFilesBranch($branch): bool
{ {
if (is_array($branch)) { if (is_array($branch)) {
// Branch. // Branch.

View File

@ -19,32 +19,39 @@ class RequestTest extends TestCase
$this->assertNotNull($request); $this->assertNotNull($request);
} }
public function testCreatesInstanceWithMethod()
{
$method = 'POST';
$request = new Request($method);
$this->assertSame($method, $request->getMethod());
}
public function testCreatesInstanceWithUri() public function testCreatesInstanceWithUri()
{ {
$uri = new Uri(); $uri = new Uri();
$request = new Request($uri); $request = new Request('GET', $uri);
$this->assertSame($uri, $request->getUri()); $this->assertSame($uri, $request->getUri());
} }
public function testCreatesInstanceWithMethod() public function testCreatesInstanceWithStringUri()
{ {
$method = "POST"; $uri = 'http://localhost:8080';
$request = new Request(null, $method); $request = new Request('GET', $uri);
$this->assertSame($method, $request->getMethod()); $this->assertSame($uri, (string) $request->getUri());
} }
public function testSetsHeadersOnConstruction() public function testSetsHeadersOnConstruction()
{ {
$request = new Request(null, null, [ $request = new Request('GET', '/', [
"X-foo" => ["bar","baz"] 'X-foo' => ['bar', 'baz']
]); ]);
$this->assertEquals(["bar","baz"], $request->getHeader("X-foo")); $this->assertEquals(['bar', 'baz'], $request->getHeader('X-foo'));
} }
public function testSetsBodyOnConstruction() public function testSetsBodyOnConstruction()
{ {
$body = new NullStream(); $body = new NullStream();
$request = new Request(null, null, [], $body); $request = new Request('GET', '/', [], $body);
$this->assertSame($body, $request->getBody()); $this->assertSame($body, $request->getBody());
} }