From d565c4af167105d3c1776c5012fc8a11488c811a Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 8 Feb 2019 21:24:02 +0200 Subject: [PATCH] Improvements for `Grav\Framework\Psr7` --- .../src/Grav/Framework/Psr7/AbstractUri.php | 1 + system/src/Grav/Framework/Psr7/Request.php | 23 +--- system/src/Grav/Framework/Psr7/Response.php | 39 ++----- .../src/Grav/Framework/Psr7/ServerRequest.php | 22 +--- system/src/Grav/Framework/Psr7/Stream.php | 19 +-- .../Traits/ServerRequestDecoratorTrait.php | 37 +++--- .../Psr7/Traits/UriDecorationTrait.php | 35 ++++-- system/src/Grav/Framework/Psr7/Uri.php | 109 ++++++++++++++++++ 8 files changed, 176 insertions(+), 109 deletions(-) diff --git a/system/src/Grav/Framework/Psr7/AbstractUri.php b/system/src/Grav/Framework/Psr7/AbstractUri.php index 4133283d7..942dc8e7e 100644 --- a/system/src/Grav/Framework/Psr7/AbstractUri.php +++ b/system/src/Grav/Framework/Psr7/AbstractUri.php @@ -16,6 +16,7 @@ use Psr\Http\Message\UriInterface; * Bare minimum PSR7 implementation. * * @package Grav\Framework\Uri\Psr7 + * @deprecated 1.6 */ abstract class AbstractUri implements UriInterface { diff --git a/system/src/Grav/Framework/Psr7/Request.php b/system/src/Grav/Framework/Psr7/Request.php index 82b116a9b..24ea3b6d4 100644 --- a/system/src/Grav/Framework/Psr7/Request.php +++ b/system/src/Grav/Framework/Psr7/Request.php @@ -21,31 +21,14 @@ class Request implements RequestInterface use RequestDecoratorTrait; /** - * @param RequestInterface $request - * @return static - */ - protected static function createFrom(RequestInterface $request) - { - if ($request instanceof self) { - return $request; - } - - return new static($request, null); - } - - /** - * @param string|RequestInterface $method HTTP method + * @param string $method HTTP method * @param string|UriInterface $uri URI * @param array $headers Request headers * @param string|null|resource|StreamInterface $body Request body * @param string $version Protocol version */ - public function __construct($method, $uri, array $headers = [], $body = null, string $version = '1.1') + public function __construct(string $method, $uri, array $headers = [], $body = null, string $version = '1.1') { - if ($method instanceof RequestInterface) { - $this->message = $method; - } else { - $this->message = new \Nyholm\Psr7\Request($method, $uri, $headers, $body, $version); - } + $this->message = new \Nyholm\Psr7\Request($method, $uri, $headers, $body, $version); } } diff --git a/system/src/Grav/Framework/Psr7/Response.php b/system/src/Grav/Framework/Psr7/Response.php index fa4cb851f..c8ba17a23 100644 --- a/system/src/Grav/Framework/Psr7/Response.php +++ b/system/src/Grav/Framework/Psr7/Response.php @@ -30,37 +30,15 @@ class Response implements ResponseInterface private const EOL = "\r\n"; /** - * @var ResponseInterface; - */ - private $response; - - /** - * @param ResponseInterface $response - * @return static - */ - protected static function createFrom(ResponseInterface $response) - { - if ($response instanceof self) { - return $response; - } - - return new static($response); - } - - /** - * @param int|ResponseInterface $status Status code + * @param int $status Status code * @param array $headers Response headers * @param string|null|resource|StreamInterface $body Response body * @param string $version Protocol version * @param string|null $reason Reason phrase (optional) */ - public function __construct($status = 200, array $headers = [], $body = null, string $version = '1.1', string $reason = null) + public function __construct(int $status = 200, array $headers = [], $body = null, string $version = '1.1', string $reason = null) { - if ($status instanceof ResponseInterface) { - $this->message = $status; - } else { - $this->message = new \Nyholm\Psr7\Response($status, $headers, $body, $version, $reason); - } + $this->message = new \Nyholm\Psr7\Response($status, $headers, $body, $version, $reason); } /** @@ -93,7 +71,10 @@ class Response implements ResponseInterface $response = $response->withStatus($status); } - return static::createFrom($response); + $new = clone $this; + $new->message = $response; + + return $new; } /** @@ -115,9 +96,11 @@ class Response implements ResponseInterface if ($status === null) { $status = 302; } - $response = $response->withStatus($status); - return static::createFrom($response); + $new = clone $this; + $new->message = $response->withStatus($status); + + return $new; } /** diff --git a/system/src/Grav/Framework/Psr7/ServerRequest.php b/system/src/Grav/Framework/Psr7/ServerRequest.php index c4f4ccef3..dca0a2808 100644 --- a/system/src/Grav/Framework/Psr7/ServerRequest.php +++ b/system/src/Grav/Framework/Psr7/ServerRequest.php @@ -24,19 +24,6 @@ class ServerRequest implements ServerRequestInterface { use ServerRequestDecoratorTrait; - /** - * @param ServerRequestInterface $request - * @return static - */ - public static function createFrom(ServerRequestInterface $request) - { - if ($request instanceof self) { - return $request; - } - - return new static($request, null); - } - /** * @param string $method HTTP method * @param string|UriInterface $uri URI @@ -45,14 +32,9 @@ class ServerRequest implements ServerRequestInterface * @param string $version Protocol version * @param array $serverParams Typically the $_SERVER superglobal */ - public function __construct($method, $uri, array $headers = [], $body = null, string $version = '1.1', array $serverParams = []) - + public function __construct(string $method, $uri, array $headers = [], $body = null, string $version = '1.1', array $serverParams = []) { - if ($method instanceof ServerRequestInterface) { - $this->message = $method; - } else { - $this->message = new \Nyholm\Psr7\ServerRequest($method, $uri, $headers, $body, $version, $serverParams); - } + $this->message = new \Nyholm\Psr7\ServerRequest($method, $uri, $headers, $body, $version, $serverParams); } /** diff --git a/system/src/Grav/Framework/Psr7/Stream.php b/system/src/Grav/Framework/Psr7/Stream.php index f10baa4d2..b90490018 100644 --- a/system/src/Grav/Framework/Psr7/Stream.php +++ b/system/src/Grav/Framework/Psr7/Stream.php @@ -18,25 +18,8 @@ class Stream implements StreamInterface { use StreamDecoratorTrait; - /** - * @param StreamInterface $stream - * @return static - */ - public static function createFrom(StreamInterface $stream) - { - if ($stream instanceof self) { - return $stream; - } - - return new static($stream); - } - public function __construct($body = '') { - if ($body instanceof StreamInterface) { - $this->stream = $body; - } else { - $this->stream = new static(\Nyholm\Psr7\Stream::create($body)); - } + $this->stream = new static(\Nyholm\Psr7\Stream::create($body)); } } diff --git a/system/src/Grav/Framework/Psr7/Traits/ServerRequestDecoratorTrait.php b/system/src/Grav/Framework/Psr7/Traits/ServerRequestDecoratorTrait.php index 9595951dc..6543f0d6a 100644 --- a/system/src/Grav/Framework/Psr7/Traits/ServerRequestDecoratorTrait.php +++ b/system/src/Grav/Framework/Psr7/Traits/ServerRequestDecoratorTrait.php @@ -77,9 +77,10 @@ trait ServerRequestDecoratorTrait */ public function withAttribute($name, $value) { - $serverRequest = $this->message->withAttribute($name, $value); + $new = clone $this; + $new->message = $this->message->withAttribute($name, $value); - return static::createFrom($serverRequest); + return $new; } /** @@ -87,13 +88,12 @@ trait ServerRequestDecoratorTrait */ public function withAttributes(array $attributes) { - $serverRequest = $this->message; - + $new = clone $this; foreach ($attributes as $attribute => $value) { - $serverRequest = $serverRequest->withAttribute($attribute, $value); + $new->message = $new->withAttribute($attribute, $value); } - return static::createFrom($serverRequest); + return $new; } /** @@ -101,9 +101,10 @@ trait ServerRequestDecoratorTrait */ public function withoutAttribute($name) { - $serverRequest = $this->message->withoutAttribute($name); + $new = clone $this; + $new->message = $this->message->withoutAttribute($name); - return static::createFrom($serverRequest); + return $new; } /** @@ -111,9 +112,10 @@ trait ServerRequestDecoratorTrait */ public function withCookieParams(array $cookies) { - $serverRequest = $this->message->withCookieParams($cookies); + $new = clone $this; + $new->message = $this->message->withCookieParams($cookies); - return static::createFrom($serverRequest); + return $new; } /** @@ -121,9 +123,10 @@ trait ServerRequestDecoratorTrait */ public function withParsedBody($data) { - $serverRequest = $this->message->withParsedBody($data); + $new = clone $this; + $new->message = $this->message->withParsedBody($data); - return static::createFrom($serverRequest); + return $new; } /** @@ -131,9 +134,10 @@ trait ServerRequestDecoratorTrait */ public function withQueryParams(array $query) { - $serverRequest = $this->message->withQueryParams($query); + $new = clone $this; + $new->message = $this->message->withQueryParams($query); - return static::createFrom($serverRequest); + return $new; } /** @@ -141,8 +145,9 @@ trait ServerRequestDecoratorTrait */ public function withUploadedFiles(array $uploadedFiles) { - $serverRequest = $this->message->withUploadedFiles($uploadedFiles); + $new = clone $this; + $new->message = $this->message->withUploadedFiles($uploadedFiles); - return static::createFrom($serverRequest); + return $new; } } diff --git a/system/src/Grav/Framework/Psr7/Traits/UriDecorationTrait.php b/system/src/Grav/Framework/Psr7/Traits/UriDecorationTrait.php index ae7029a76..e1e1af6bc 100644 --- a/system/src/Grav/Framework/Psr7/Traits/UriDecorationTrait.php +++ b/system/src/Grav/Framework/Psr7/Traits/UriDecorationTrait.php @@ -65,36 +65,57 @@ trait UriDecorationTrait public function withScheme($scheme): UriInterface { - return $this->uri->withScheme($scheme); + $new = clone $this; + $new->uri = $this->uri->withScheme($scheme); + + return $new; } public function withUserInfo($user, $password = null): UriInterface { - return $this->uri->withUserInfo($user, $password); + $new = clone $this; + $new->uri = $this->uri->withUserInfo($user, $password); + + return $new; } public function withHost($host): UriInterface { - return $this->uri->withHost($host); + $new = clone $this; + $new->uri = $this->uri->withHost($host); + + return $new; } public function withPort($port): UriInterface { - return $this->uri->withPort($port); + $new = clone $this; + $new->uri = $this->uri->withPort($port); + + return $new; } public function withPath($path): UriInterface { - return $this->uri->withPath($path); + $new = clone $this; + $new->uri = $this->uri->withPath($path); + + return $new; } public function withQuery($query): UriInterface { - return $this->uri->withQuery($query); + $new = clone $this; + $new->uri = $this->uri->withQuery($query); + + return $new; } public function withFragment($fragment): UriInterface { - return $this->uri->withFragment($fragment); + $new = clone $this; + $new->uri = $this->uri->withFragment($fragment); + + return $new; } } diff --git a/system/src/Grav/Framework/Psr7/Uri.php b/system/src/Grav/Framework/Psr7/Uri.php index 122610291..28614ca8a 100644 --- a/system/src/Grav/Framework/Psr7/Uri.php +++ b/system/src/Grav/Framework/Psr7/Uri.php @@ -12,14 +12,123 @@ declare(strict_types=1); namespace Grav\Framework\Psr7; use Grav\Framework\Psr7\Traits\UriDecorationTrait; +use Grav\Framework\Uri\UriFactory; +use GuzzleHttp\Psr7\Uri as GuzzleUri; use Psr\Http\Message\UriInterface; class Uri implements UriInterface { use UriDecorationTrait; + /** @var array Array of Uri query. */ + private $queryParams; + public function __construct(string $uri = '') { $this->uri = new \Nyholm\Psr7\Uri($uri); } + + /** + * @return array + */ + public function getQueryParams(): array + { + return UriFactory::parseQuery($this->getQuery()); + } + + /** + * @param array $params + * @return UriInterface + */ + public function withQueryParams(array $params): UriInterface + { + $query = UriFactory::buildQuery($params); + + return $this->withQuery($query); + } + + /** + * Whether the URI has the default port of the current scheme. + * + * `$uri->getPort()` may return the standard port. This method can be used for some non-http/https Uri. + * + * @return bool + */ + public function isDefaultPort(): bool + { + return $this->getPort() === null || GuzzleUri::isDefaultPort($this); + } + + /** + * Whether the URI is absolute, i.e. it has a scheme. + * + * An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true + * if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative + * to another URI, the base URI. Relative references can be divided into several forms: + * - network-path references, e.g. '//example.com/path' + * - absolute-path references, e.g. '/path' + * - relative-path references, e.g. 'subpath' + * + * @return bool + * @link https://tools.ietf.org/html/rfc3986#section-4 + */ + public function isAbsolute(): bool + { + return GuzzleUri::isAbsolute($this); + } + + /** + * Whether the URI is a network-path reference. + * + * A relative reference that begins with two slash characters is termed an network-path reference. + * + * @return bool + * @link https://tools.ietf.org/html/rfc3986#section-4.2 + */ + public function isNetworkPathReference(): bool + { + return GuzzleUri::isNetworkPathReference($this); + } + + /** + * Whether the URI is a absolute-path reference. + * + * A relative reference that begins with a single slash character is termed an absolute-path reference. + * + * @return bool + * @link https://tools.ietf.org/html/rfc3986#section-4.2 + */ + public function isAbsolutePathReference(): bool + { + return GuzzleUri::isAbsolutePathReference($this); + } + + /** + * Whether the URI is a relative-path reference. + * + * A relative reference that does not begin with a slash character is termed a relative-path reference. + * + * @return bool + * @link https://tools.ietf.org/html/rfc3986#section-4.2 + */ + public function isRelativePathReference(): bool + { + return GuzzleUri::isRelativePathReference($this); + } + + /** + * Whether the URI is a same-document reference. + * + * A same-document reference refers to a URI that is, aside from its fragment + * component, identical to the base URI. When no base URI is given, only an empty + * URI reference (apart from its fragment) is considered a same-document reference. + * + * @param UriInterface|null $base An optional base URI to compare against + * @return bool + * @link https://tools.ietf.org/html/rfc3986#section-4.4 + */ + public function isSameDocumentReference(UriInterface $base = null): bool + { + return GuzzleUri::isSameDocumentReference($this, $base); + } }