From 70c8e7e82d8071745236e149c66238cdc923106f Mon Sep 17 00:00:00 2001 From: Thomas Flori <thflori@gmail.com> Date: Sun, 5 Aug 2018 12:13:06 +0200 Subject: [PATCH] remove code duplicates by protected methods with overwritten visibility --- src/ChangeableMessageTrait.php | 122 ++----------------------- src/ClientRequest.php | 77 ++-------------- src/MessageTrait.php | 158 +++++++++++++++++++++++++-------- src/Request.php | 102 +++++++++++++++++---- src/Response.php | 31 +++++-- src/ServerResponse.php | 25 +----- 6 files changed, 245 insertions(+), 270 deletions(-) diff --git a/src/ChangeableMessageTrait.php b/src/ChangeableMessageTrait.php index 98c9463..4d14ef2 100644 --- a/src/ChangeableMessageTrait.php +++ b/src/ChangeableMessageTrait.php @@ -2,123 +2,13 @@ namespace Tal; -use Psr\Http\Message\StreamInterface; - trait ChangeableMessageTrait { - use MessageTrait; - - /** - * Sets the specified HTTP protocol version. - * - * The version string MUST contain only the HTTP version number (e.g., - * "1.1", "1.0"). - * - * @param string $version HTTP protocol version - * @return static - */ - public function setProtocolVersion($version) - { - $this->protocol = $version; - return $this; - } - - /** - * Sets the provided value replacing the specified header. - * - * While header names are case-insensitive, the casing of the header will - * be preserved by this function, and returned from getHeaders(). - * - * @param string $header Case-insensitive header field name. - * @param string|string[] $value Header value(s). - * @return static - * @throws \InvalidArgumentException for invalid header names or values. - */ - public function setHeader($header, $value) - { - if (!is_array($value)) { - $value = [$value]; - } - - $value = $this->trimHeaderValues($value); - $normalized = strtolower($header); - - if (isset($this->headerNames[$normalized])) { - unset($this->headers[$this->headerNames[$normalized]]); - } - $this->headerNames[$normalized] = $header; - $this->headers[$header] = $value; - - return $this; - } - - /** - * Adds the specified header appended with the given value. - * - * Existing values for the specified header will be maintained. The new - * value(s) will be appended to the existing list. If the header did not - * exist previously, it will be added. - * - * @param string $header Case-insensitive header field name to add. - * @param string|string[] $value Header value(s). - * @return static - * @throws \InvalidArgumentException for invalid header names or values. - */ - public function addHeader($header, $value) - { - if (!is_array($value)) { - $value = [$value]; - } - - $value = $this->trimHeaderValues($value); - $normalized = strtolower($header); - - if (isset($this->headerNames[$normalized])) { - $header = $this->headerNames[$normalized]; - $this->headers[$header] = array_merge($this->headers[$header], $value); - } else { - $this->headerNames[$normalized] = $header; - $this->headers[$header] = $value; - } - - return $this; - } - - /** - * Deletes the specified header. - * - * Header resolution MUST be done without case-sensitivity. - * - * @param string $header Case-insensitive header field name to remove. - * @return static - */ - public function deleteHeader($header) - { - $normalized = strtolower($header); - - if (!isset($this->headerNames[$normalized])) { - return $this; - } - - $header = $this->headerNames[$normalized]; - - unset($this->headers[$header], $this->headerNames[$normalized]); - - return $this; - } - - /** - * Sets the specified message body. - * - * The body MUST be a StreamInterface object. - * - * @param StreamInterface $body Body. - * @return static - * @throws \InvalidArgumentException When the body is not valid. - */ - public function setBody(StreamInterface $body) - { - $this->stream = $body; - return $this; + use MessageTrait { + setProtocolVersion as public; + setHeader as public; + addHeader as public; + deleteHeader as public; + setBody as public; } } diff --git a/src/ClientRequest.php b/src/ClientRequest.php index 18d2c5c..309c21d 100644 --- a/src/ClientRequest.php +++ b/src/ClientRequest.php @@ -2,7 +2,6 @@ namespace Tal; -use InvalidArgumentException; use Psr\Http\Message\UriInterface; use Tal\Psr7Extended\ClientRequestInterface; @@ -10,85 +9,21 @@ class ClientRequest extends Request implements ClientRequestInterface { use ChangeableMessageTrait; - /** - * Sets the specific request-target. - * - * If the request needs a non-origin-form request-target — e.g., for - * specifying an absolute-form, authority-form, or asterisk-form — - * this method may be used to create an instance with the specified - * request-target, verbatim. - * - * @link http://tools.ietf.org/html/rfc7230#section-5.3 (for the various - * request-target forms allowed in request messages) - * @param mixed $requestTarget - * @return static - */ + /** {@inheritDoc} */ public function setRequestTarget($requestTarget) { - if (preg_match('#\s#', $requestTarget)) { - throw new InvalidArgumentException( - 'Invalid request target provided; cannot contain whitespace' - ); - } - - $this->requestTarget = $requestTarget; - return $this; + return parent::setRequestTarget($requestTarget); } - /** - * Sets the provided HTTP method. - * - * While HTTP method names are typically all uppercase characters, HTTP - * method names are case-sensitive and thus implementations SHOULD NOT - * modify the given string. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * changed request method. - * - * @param string $method Case-sensitive method. - * @return static - * @throws \InvalidArgumentException for invalid HTTP methods. - */ + /** {@inheritDoc} */ public function setMethod($method) { - $this->method = strtoupper($method); - return $this; + return parent::setMethod($method); } - /** - * Sets the provided URI. - * - * This method MUST update the Host header of the returned request by - * default if the URI contains a host component. If the URI does not - * contain a host component, any pre-existing Host header MUST be carried - * over to the returned request. - * - * You can opt-in to preserving the original state of the Host header by - * setting `$preserveHost` to `true`. When `$preserveHost` is set to - * `true`, this method interacts with the Host header in the following ways: - * - * - If the Host header is missing or empty, and the new URI contains - * a host component, this method MUST update the Host header in the returned - * request. - * - If the Host header is missing or empty, and the new URI does not contain a - * host component, this method MUST NOT update the Host header in the returned - * request. - * - If a Host header is present and non-empty, this method MUST NOT update - * the Host header in the returned request. - * - * @link http://tools.ietf.org/html/rfc3986#section-4.3 - * @param UriInterface $uri New request URI to use. - * @param bool $preserveHost Preserve the original state of the Host header. - * @return static - */ + /** {@inheritDoc} */ public function setUri(UriInterface $uri, $preserveHost = false) { - $this->uri = $uri; - - if (!$preserveHost) { - $this->updateHostFromUri(); - } - return $this; + return parent::setUri($uri, $preserveHost); } } diff --git a/src/MessageTrait.php b/src/MessageTrait.php index 6f53690..041dbb4 100644 --- a/src/MessageTrait.php +++ b/src/MessageTrait.php @@ -34,8 +34,7 @@ trait MessageTrait } $new = clone $this; - $new->protocol = $version; - return $new; + return $new->setProtocolVersion($version); } public function getHeaders() @@ -68,42 +67,14 @@ trait MessageTrait public function withHeader($header, $value) { - if (!is_array($value)) { - $value = [$value]; - } - - $value = $this->trimHeaderValues($value); - $normalized = strtolower($header); - $new = clone $this; - if (isset($new->headerNames[$normalized])) { - unset($new->headers[$new->headerNames[$normalized]]); - } - $new->headerNames[$normalized] = $header; - $new->headers[$header] = $value; - - return $new; + return $new->setHeader($header, $value); } public function withAddedHeader($header, $value) { - if (!is_array($value)) { - $value = [$value]; - } - - $value = $this->trimHeaderValues($value); - $normalized = strtolower($header); - $new = clone $this; - if (isset($new->headerNames[$normalized])) { - $header = $this->headerNames[$normalized]; - $new->headers[$header] = array_merge($this->headers[$header], $value); - } else { - $new->headerNames[$normalized] = $header; - $new->headers[$header] = $value; - } - - return $new; + return $new->addHeader($header, $value); } public function withoutHeader($header) @@ -114,12 +85,8 @@ trait MessageTrait return $this; } - $header = $this->headerNames[$normalized]; - $new = clone $this; - unset($new->headers[$header], $new->headerNames[$normalized]); - - return $new; + return $new->deleteHeader($header); } public function getBody() @@ -138,8 +105,7 @@ trait MessageTrait } $new = clone $this; - $new->stream = $body; - return $new; + return $new->setBody($body); } protected function setHeaders(array $headers) @@ -182,4 +148,118 @@ trait MessageTrait return trim($value, " \t"); }, $values); } + + /** + * Sets the specified HTTP protocol version. + * + * The version string MUST contain only the HTTP version number (e.g., + * "1.1", "1.0"). + * + * @param string $version HTTP protocol version + * @return static + */ + protected function setProtocolVersion($version) + { + $this->protocol = $version; + return $this; + } + + /** + * Sets the provided value replacing the specified header. + * + * While header names are case-insensitive, the casing of the header will + * be preserved by this function, and returned from getHeaders(). + * + * @param string $header Case-insensitive header field name. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + protected function setHeader($header, $value) + { + if (!is_array($value)) { + $value = [$value]; + } + + $value = $this->trimHeaderValues($value); + $normalized = strtolower($header); + + if (isset($this->headerNames[$normalized])) { + unset($this->headers[$this->headerNames[$normalized]]); + } + $this->headerNames[$normalized] = $header; + $this->headers[$header] = $value; + + return $this; + } + + /** + * Adds the specified header appended with the given value. + * + * Existing values for the specified header will be maintained. The new + * value(s) will be appended to the existing list. If the header did not + * exist previously, it will be added. + * + * @param string $header Case-insensitive header field name to add. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + protected function addHeader($header, $value) + { + if (!is_array($value)) { + $value = [$value]; + } + + $value = $this->trimHeaderValues($value); + $normalized = strtolower($header); + + if (isset($this->headerNames[$normalized])) { + $header = $this->headerNames[$normalized]; + $this->headers[$header] = array_merge($this->headers[$header], $value); + } else { + $this->headerNames[$normalized] = $header; + $this->headers[$header] = $value; + } + + return $this; + } + + /** + * Deletes the specified header. + * + * Header resolution MUST be done without case-sensitivity. + * + * @param string $header Case-insensitive header field name to remove. + * @return static + */ + protected function deleteHeader($header) + { + $normalized = strtolower($header); + + if (!isset($this->headerNames[$normalized])) { + return $this; + } + + $header = $this->headerNames[$normalized]; + + unset($this->headers[$header], $this->headerNames[$normalized]); + + return $this; + } + + /** + * Sets the specified message body. + * + * The body MUST be a StreamInterface object. + * + * @param StreamInterface $body Body. + * @return static + * @throws \InvalidArgumentException When the body is not valid. + */ + protected function setBody(StreamInterface $body) + { + $this->stream = $body; + return $this; + } } diff --git a/src/Request.php b/src/Request.php index 1890882..a2ba489 100644 --- a/src/Request.php +++ b/src/Request.php @@ -76,15 +76,8 @@ abstract class Request implements RequestInterface public function withRequestTarget($requestTarget) { - if (preg_match('#\s#', $requestTarget)) { - throw new InvalidArgumentException( - 'Invalid request target provided; cannot contain whitespace' - ); - } - $new = clone $this; - $new->requestTarget = $requestTarget; - return $new; + return $new->setRequestTarget($requestTarget); } public function getMethod() @@ -95,8 +88,7 @@ abstract class Request implements RequestInterface public function withMethod($method) { $new = clone $this; - $new->method = strtoupper($method); - return $new; + return $new->setMethod($method); } public function getUri() @@ -111,13 +103,7 @@ abstract class Request implements RequestInterface } $new = clone $this; - $new->uri = $uri; - - if (!$preserveHost) { - $new->updateHostFromUri(); - } - - return $new; + return $new->setUri($uri, $preserveHost); } protected function updateHostFromUri() @@ -142,4 +128,86 @@ abstract class Request implements RequestInterface // See: http://tools.ietf.org/html/rfc7230#section-5.4 $this->headers = [$header => [$host]] + $this->headers; } + + /** + * Sets the specific request-target. + * + * If the request needs a non-origin-form request-target — e.g., for + * specifying an absolute-form, authority-form, or asterisk-form — + * this method may be used to create an instance with the specified + * request-target, verbatim. + * + * @link http://tools.ietf.org/html/rfc7230#section-5.3 (for the various + * request-target forms allowed in request messages) + * @param mixed $requestTarget + * @return static + */ + protected function setRequestTarget($requestTarget) + { + if (preg_match('#\s#', $requestTarget)) { + throw new InvalidArgumentException( + 'Invalid request target provided; cannot contain whitespace' + ); + } + + $this->requestTarget = $requestTarget; + return $this; + } + + /** + * Sets the provided HTTP method. + * + * While HTTP method names are typically all uppercase characters, HTTP + * method names are case-sensitive and thus implementations SHOULD NOT + * modify the given string. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * changed request method. + * + * @param string $method Case-sensitive method. + * @return static + * @throws \InvalidArgumentException for invalid HTTP methods. + */ + protected function setMethod($method) + { + $this->method = strtoupper($method); + return $this; + } + + /** + * Sets the provided URI. + * + * This method MUST update the Host header of the returned request by + * default if the URI contains a host component. If the URI does not + * contain a host component, any pre-existing Host header MUST be carried + * over to the returned request. + * + * You can opt-in to preserving the original state of the Host header by + * setting `$preserveHost` to `true`. When `$preserveHost` is set to + * `true`, this method interacts with the Host header in the following ways: + * + * - If the Host header is missing or empty, and the new URI contains + * a host component, this method MUST update the Host header in the returned + * request. + * - If the Host header is missing or empty, and the new URI does not contain a + * host component, this method MUST NOT update the Host header in the returned + * request. + * - If a Host header is present and non-empty, this method MUST NOT update + * the Host header in the returned request. + * + * @link http://tools.ietf.org/html/rfc3986#section-4.3 + * @param UriInterface $uri New request URI to use. + * @param bool $preserveHost Preserve the original state of the Host header. + * @return static + */ + protected function setUri(UriInterface $uri, $preserveHost = false) + { + $this->uri = $uri; + + if (!$preserveHost) { + $this->updateHostFromUri(); + } + return $this; + } } diff --git a/src/Response.php b/src/Response.php index 30774b1..20b8ff4 100644 --- a/src/Response.php +++ b/src/Response.php @@ -124,11 +124,32 @@ abstract class Response implements ResponseInterface public function withStatus($code, $reasonPhrase = '') { $new = clone $this; - $new->statusCode = (int) $code; - if ($reasonPhrase == '' && isset(self::$phrases[$new->statusCode])) { - $reasonPhrase = self::$phrases[$new->statusCode]; + return $new->setStatus($code, $reasonPhrase); + } + + /** + * Sets the specified status code and, optionally, reason phrase. + * + * If no reason phrase is specified, implementations MAY choose to default + * to the RFC 7231 or IANA recommended reason phrase for the response's + * status code. + * + * @link http://tools.ietf.org/html/rfc7231#section-6 + * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml + * @param int $code The 3-digit integer result code to set. + * @param string $reasonPhrase The reason phrase to use with the + * provided status code; if none is provided, implementations MAY + * use the defaults as suggested in the HTTP specification. + * @return static + * @throws \InvalidArgumentException For invalid status code arguments. + */ + protected function setStatus($code, $reasonPhrase = '') + { + $this->statusCode = (int) $code; + if ($reasonPhrase == '' && isset(static::$phrases[$this->statusCode])) { + $reasonPhrase = static::$phrases[$this->statusCode]; } - $new->reasonPhrase = $reasonPhrase; - return $new; + $this->reasonPhrase = $reasonPhrase; + return $this; } } diff --git a/src/ServerResponse.php b/src/ServerResponse.php index 594e19d..7df088c 100644 --- a/src/ServerResponse.php +++ b/src/ServerResponse.php @@ -2,36 +2,17 @@ namespace Tal; +use Psr\Http\Message\StreamInterface; use Tal\Psr7Extended\ServerResponseInterface; class ServerResponse extends Response implements ServerResponseInterface { use ChangeableMessageTrait; - /** - * Sets the specified status code and, optionally, reason phrase. - * - * If no reason phrase is specified, implementations MAY choose to default - * to the RFC 7231 or IANA recommended reason phrase for the response's - * status code. - * - * @link http://tools.ietf.org/html/rfc7231#section-6 - * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml - * @param int $code The 3-digit integer result code to set. - * @param string $reasonPhrase The reason phrase to use with the - * provided status code; if none is provided, implementations MAY - * use the defaults as suggested in the HTTP specification. - * @return static - * @throws \InvalidArgumentException For invalid status code arguments. - */ + /** {@inheritDoc} */ public function setStatus($code, $reasonPhrase = '') { - $this->statusCode = (int) $code; - if ($reasonPhrase == '' && isset(static::$phrases[$this->statusCode])) { - $reasonPhrase = static::$phrases[$this->statusCode]; - } - $this->reasonPhrase = $reasonPhrase; - return $this; + return parent::setStatus($code, $reasonPhrase); } /** -- GitLab