From 16d90d19cff7cd23884d45c3153f6b0496f55910 Mon Sep 17 00:00:00 2001 From: David Buchmann Date: Thu, 25 Nov 2021 16:43:07 +0100 Subject: [PATCH] cleanups found with phpstan --- composer.json | 2 +- phpstan.neon.dist | 31 ++++++++++++++++++++++++++----- src/HttpMethodsClient.php | 8 ++++---- src/Plugin/AddHostPlugin.php | 6 +++--- src/Plugin/ContentTypePlugin.php | 8 ++++---- src/Plugin/CookiePlugin.php | 2 +- src/Plugin/DecoderPlugin.php | 6 +++--- src/Plugin/ErrorPlugin.php | 6 +++--- src/Plugin/RedirectPlugin.php | 14 ++++++-------- src/Plugin/RetryPlugin.php | 16 +++++++++------- src/Plugin/SeekableBodyPlugin.php | 8 ++++---- src/PluginChain.php | 5 +---- src/PluginClient.php | 4 +--- src/PluginClientFactory.php | 8 ++++---- 14 files changed, 70 insertions(+), 54 deletions(-) diff --git a/composer.json b/composer.json index eb5cb4c..2ea45aa 100644 --- a/composer.json +++ b/composer.json @@ -13,8 +13,8 @@ "require": { "php": "^7.1 || ^8.0", "php-http/httplug": "^2.0", - "php-http/message-factory": "^1.0", "php-http/message": "^1.6", + "php-http/message-factory": "^1.0", "psr/http-client": "^1.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.0", diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 1373517..328ca33 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -5,18 +5,19 @@ parameters: paths: - src ignoreErrors: + # Exception still thrown in PHP 8, not sure why phpstan complains - - message: "#^Cannot call method createStream\\(\\) on Psr\\\\Http\\\\Message\\\\StreamFactoryInterface\\|null\\.$#" - count: 1 - path: src/HttpMethodsClient.php + message: "#^Dead catch - UnexpectedValueException is never thrown in the try block\\.$#" + count: 2 + path: src/BatchResult.php - - message: "#^Method Http\\\\Client\\\\Common\\\\Plugin\\\\Journal\\:\\:addSuccess\\(\\) has no return typehint specified\\.$#" + message: "#^Method Http\\\\Client\\\\Common\\\\Plugin\\\\Journal\\:\\:addSuccess\\(\\) has no return type specified\\.$#" count: 1 path: src/Plugin/Journal.php - - message: "#^Method Http\\\\Client\\\\Common\\\\Plugin\\\\Journal\\:\\:addFailure\\(\\) has no return typehint specified\\.$#" + message: "#^Method Http\\\\Client\\\\Common\\\\Plugin\\\\Journal\\:\\:addFailure\\(\\) has no return type specified\\.$#" count: 1 path: src/Plugin/Journal.php @@ -24,3 +25,23 @@ parameters: message: "#^Call to an undefined method Http\\\\Client\\\\HttpAsyncClient\\:\\:sendRequest\\(\\)\\.$#" count: 1 path: src/PluginClient.php + + - + message: "#^Method Http\\\\Client\\\\Common\\\\EmulatedHttpClient\\:\\:sendRequest\\(\\) should return Psr\\\\Http\\\\Message\\\\ResponseInterface but returns mixed\\.$#" + count: 1 + path: src/EmulatedHttpClient.php + + - + message: "#^Anonymous function should return Psr\\\\Http\\\\Message\\\\ResponseInterface but returns mixed\\.$#" + count: 1 + path: src/Plugin/RedirectPlugin.php + + - + message: "#^Method Http\\\\Client\\\\Common\\\\Plugin\\\\RetryPlugin\\:\\:retry\\(\\) should return Psr\\\\Http\\\\Message\\\\ResponseInterface but returns mixed\\.$#" + count: 1 + path: src/Plugin/RetryPlugin.php + + - + message: "#^Method Http\\\\Client\\\\Common\\\\PluginClient\\:\\:sendRequest\\(\\) should return Psr\\\\Http\\\\Message\\\\ResponseInterface but returns mixed\\.$#" + count: 2 + path: src/PluginClient.php diff --git a/src/HttpMethodsClient.php b/src/HttpMethodsClient.php index f62b187..497921b 100644 --- a/src/HttpMethodsClient.php +++ b/src/HttpMethodsClient.php @@ -124,10 +124,6 @@ private function createRequest(string $method, $uri, array $headers = [], $body ); } - if (is_string($body) && '' !== $body && null === $this->streamFactory) { - throw new \RuntimeException('Cannot create request: A stream factory is required to create a request with a non-empty string body.'); - } - $request = $this->requestFactory->createRequest($method, $uri); foreach ($headers as $key => $value) { @@ -135,6 +131,10 @@ private function createRequest(string $method, $uri, array $headers = [], $body } if (null !== $body && '' !== $body) { + if (null === $this->streamFactory) { + throw new \RuntimeException('Cannot create request: A stream factory is required to create a request with a non-empty string body.'); + } + $request = $request->withBody( is_string($body) ? $this->streamFactory->createStream($body) : $body ); diff --git a/src/Plugin/AddHostPlugin.php b/src/Plugin/AddHostPlugin.php index 33ede17..c7fb05a 100644 --- a/src/Plugin/AddHostPlugin.php +++ b/src/Plugin/AddHostPlugin.php @@ -28,10 +28,10 @@ final class AddHostPlugin implements Plugin private $replace; /** - * @param array $config { + * @param array{'replace'?: bool} $config * - * @var bool $replace True will replace all hosts, false will only add host when none is specified. - * } + * Configuration options: + * - replace: True will replace all hosts, false will only add host when none is specified. */ public function __construct(UriInterface $host, array $config = []) { diff --git a/src/Plugin/ContentTypePlugin.php b/src/Plugin/ContentTypePlugin.php index c3fb25c..9a87f99 100644 --- a/src/Plugin/ContentTypePlugin.php +++ b/src/Plugin/ContentTypePlugin.php @@ -35,11 +35,11 @@ final class ContentTypePlugin implements Plugin private $sizeLimit; /** - * @param array $config { + * @param array{'skip_detection'?: bool, 'size_limit'?: int} $config * - * @var bool $skip_detection true skip detection if stream size is bigger than $size_limit - * @var int $size_limit size stream limit for which the detection as to be skipped. - * } + * Configuration options: + * - skip_detection: true skip detection if stream size is bigger than $size_limit + * - size_limit: size stream limit for which the detection as to be skipped. */ public function __construct(array $config = []) { diff --git a/src/Plugin/CookiePlugin.php b/src/Plugin/CookiePlugin.php index d0c862b..aa4d5d7 100644 --- a/src/Plugin/CookiePlugin.php +++ b/src/Plugin/CookiePlugin.php @@ -97,7 +97,7 @@ private function createCookie(RequestInterface $request, string $setCookieHeader { $parts = array_map('trim', explode(';', $setCookieHeader)); - if (empty($parts) || !strpos($parts[0], '=')) { + if ('' === $parts[0] || false === strpos($parts[0], '=')) { return null; } diff --git a/src/Plugin/DecoderPlugin.php b/src/Plugin/DecoderPlugin.php index 271ad3c..b685967 100644 --- a/src/Plugin/DecoderPlugin.php +++ b/src/Plugin/DecoderPlugin.php @@ -31,10 +31,10 @@ final class DecoderPlugin implements Plugin private $useContentEncoding; /** - * @param array $config { + * @param array{'use_content_encoding'?: bool} $config * - * @var bool $use_content_encoding Whether this plugin should look at the Content-Encoding header first or only at the Transfer-Encoding (defaults to true). - * } + * Configuration options: + * - use_content_encoding: Whether this plugin should look at the Content-Encoding header first or only at the Transfer-Encoding (defaults to true). */ public function __construct(array $config = []) { diff --git a/src/Plugin/ErrorPlugin.php b/src/Plugin/ErrorPlugin.php index a187295..06c795f 100644 --- a/src/Plugin/ErrorPlugin.php +++ b/src/Plugin/ErrorPlugin.php @@ -37,10 +37,10 @@ final class ErrorPlugin implements Plugin private $onlyServerException; /** - * @param array $config { + * @param array{'only_server_exception'?: bool} $config * - * @var bool only_server_exception Whether this plugin should only throw 5XX Exceptions (default to false). - * } + * Configuration options: + * - only_server_exception: Whether this plugin should only throw 5XX Exceptions (default to false). */ public function __construct(array $config = []) { diff --git a/src/Plugin/RedirectPlugin.php b/src/Plugin/RedirectPlugin.php index 488b3aa..5b45826 100644 --- a/src/Plugin/RedirectPlugin.php +++ b/src/Plugin/RedirectPlugin.php @@ -102,12 +102,12 @@ final class RedirectPlugin implements Plugin private $circularDetection = []; /** - * @param array $config { + * @param array{'preserve_header'?: bool|string[], 'use_default_for_multiple'?: bool, 'strict'?: bool} $config * - * @var bool|string[] $preserve_header True keeps all headers, false remove all of them, an array is interpreted as a list of header names to keep - * @var bool $use_default_for_multiple Whether the location header must be directly used for a multiple redirection status code (300) - * @var bool $strict When true, redirect codes 300, 301, 302 will not modify request method and body. - * } + * Configuration options: + * - preserve_header: True keeps all headers, false remove all of them, an array is interpreted as a list of header names to keep + * - use_default_for_multiple: Whether the location header must be directly used for a multiple redirection status code (300) + * - strict: When true, redirect codes 300, 301, 302 will not modify request method and body. */ public function __construct(array $config = []) { @@ -182,9 +182,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl } // Call redirect request synchronously - $redirectPromise = $first($redirectRequest); - - return $redirectPromise->wait(); + return $first($redirectRequest)->wait(); }); } diff --git a/src/Plugin/RetryPlugin.php b/src/Plugin/RetryPlugin.php index 92b7cbf..144679e 100644 --- a/src/Plugin/RetryPlugin.php +++ b/src/Plugin/RetryPlugin.php @@ -56,14 +56,14 @@ final class RetryPlugin implements Plugin private $retryStorage = []; /** - * @param array $config { + * @param array{'retries'?: int, 'error_response_decider'?: callable, 'exception_decider'?: callable, 'error_response_delay'?: callable, 'exception_delay'?: callable} $config * - * @var int $retries Number of retries to attempt if an exception occurs before letting the exception bubble up - * @var callable $error_response_decider A callback that gets a request and response to decide whether the request should be retried - * @var callable $exception_decider A callback that gets a request and an exception to decide after a failure whether the request should be retried - * @var callable $error_response_delay A callback that gets a request and response and the current number of retries and returns how many microseconds we should wait before trying again - * @var callable $exception_delay A callback that gets a request, an exception and the current number of retries and returns how many microseconds we should wait before trying again - * } + * Configuration options: + * - retries: Number of retries to attempt if an exception occurs before letting the exception bubble up + * - error_response_decider: A callback that gets a request and response to decide whether the request should be retried + * - exception_decider: A callback that gets a request and an exception to decide after a failure whether the request should be retried + * - error_response_delay: A callback that gets a request and response and the current number of retries and returns how many microseconds we should wait before trying again + * - exception_delay: A callback that gets a request, an exception and the current number of retries and returns how many microseconds we should wait before trying again */ public function __construct(array $config = []) { @@ -115,6 +115,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl } if (call_user_func($this->errorResponseDecider, $request, $response)) { + /** @var int $time */ $time = call_user_func($this->errorResponseDelay, $request, $response, $this->retryStorage[$chainIdentifier]); $response = $this->retry($request, $next, $first, $chainIdentifier, $time); } @@ -139,6 +140,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl throw $exception; } + /** @var int $time */ $time = call_user_func($this->exceptionDelay, $request, $exception, $this->retryStorage[$chainIdentifier]); return $this->retry($request, $next, $first, $chainIdentifier, $time); diff --git a/src/Plugin/SeekableBodyPlugin.php b/src/Plugin/SeekableBodyPlugin.php index 5c20af3..1be2cde 100644 --- a/src/Plugin/SeekableBodyPlugin.php +++ b/src/Plugin/SeekableBodyPlugin.php @@ -23,11 +23,11 @@ abstract class SeekableBodyPlugin implements Plugin protected $memoryBufferSize; /** - * @param array $config { + * @param array{'use_file_buffer'?: bool, 'memory_boffer_size'?: int} $config * - * @var bool $use_file_buffer Whether this plugin should use a file as a buffer if the stream is too big, defaults to true - * @var int $memory_buffer_size Max memory size in bytes to use for the buffer before it use a file, defaults to 2097152 (2 mb) - * } + * Configuration options: + * - use_file_buffer: Whether this plugin should use a file as a buffer if the stream is too big, defaults to true + * - memory_buffer_size: Max memory size in bytes to use for the buffer before it use a file, defaults to 2097152 (2 mb) */ public function __construct(array $config = []) { diff --git a/src/PluginChain.php b/src/PluginChain.php index db72332..fcb1914 100644 --- a/src/PluginChain.php +++ b/src/PluginChain.php @@ -26,10 +26,7 @@ final class PluginChain /** * @param Plugin[] $plugins A plugin chain * @param callable(RequestInterface): Promise $clientCallable Callable making the HTTP call - * @param array $options { - * - * @var int $max_restarts - * } + * @param array{'max_restarts'?: int} $options */ public function __construct(array $plugins, callable $clientCallable, array $options = []) { diff --git a/src/PluginClient.php b/src/PluginClient.php index 48bafab..d67145d 100644 --- a/src/PluginClient.php +++ b/src/PluginClient.php @@ -46,9 +46,7 @@ final class PluginClient implements HttpClient, HttpAsyncClient /** * @param ClientInterface|HttpAsyncClient $client An HTTP async client * @param Plugin[] $plugins A plugin chain - * @param array $options { - * @var int $max_restarts - * } + * @param array{'max_restarts'?: int} $options */ public function __construct($client, array $plugins = [], array $options = []) { diff --git a/src/PluginClientFactory.php b/src/PluginClientFactory.php index 0c91fc3..f7e93e3 100644 --- a/src/PluginClientFactory.php +++ b/src/PluginClientFactory.php @@ -39,11 +39,11 @@ public static function setFactory(callable $factory): void /** * @param ClientInterface|HttpAsyncClient $client * @param Plugin[] $plugins - * @param array $options { + * @param array{'client_name'?: string} $options * - * @var string $client_name to give client a name which may be used when displaying client information like in - * the HTTPlugBundle profiler. - * } + * Configuration options: + * - client_name: to give client a name which may be used when displaying client information + * like in the HTTPlugBundle profiler. * * @see PluginClient constructor for PluginClient specific $options. */