diff --git a/CHANGELOG.md b/CHANGELOG.md index 13c2e2c..c8a4800 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [1.2.0] - unreleased + +### Added + +- Add support for Guzzle 8 + ## [1.1.0] - 2024-11-26 ### Changed diff --git a/README.md b/README.md index 7e6b5b5..aab7c76 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# Guzzle 7 HTTP Adapter +# Guzzle 7/8 HTTP Adapter [![Latest Version](https://img.shields.io/github/release/php-http/guzzle7-adapter.svg?style=flat-square)](https://github.com/php-http/guzzle7-adapter/releases) [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) [![Total Downloads](https://img.shields.io/packagist/dt/php-http/guzzle7-adapter.svg?style=flat-square)](https://packagist.org/packages/php-http/guzzle7-adapter) -**Guzzle 7 HTTP Adapter.** +**Guzzle 7/8 HTTP Adapter.** ## Install diff --git a/composer.json b/composer.json index 55ce418..09abcef 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ "php": "^7.3 | ^8.0", "php-http/httplug": "^2.4", "psr/http-client": "^1.0.3", - "guzzlehttp/guzzle": "^7.10" + "guzzlehttp/guzzle": "^7.10 || ^8.0" }, "require-dev": { "phpunit/phpunit": "^9.6.31 || ^10.0 || ^11.0 || ^12.0", diff --git a/phpstan.neon.dist b/phpstan.neon.dist index d42940e..83ce653 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,5 +1,70 @@ parameters: level: 5 - reportUnmatchedIgnoredErrors: false paths: - src + - tests + + ignoreErrors: + - + message: '#^Non\-static access to static property Http\\Client\\Tests\\HttpBaseTest\:\:\$defaultHeaders\.$#' + identifier: staticProperty.nonStaticAccess + count: 1 + # Only occurs with php-http/client-integration-tests ≥ 4.0.0 + reportUnmatched: false + path: tests/DefaultHttpAdapterWithConfigTest.php + + - + message: '#^Static access to instance property Http\\Client\\Tests\\HttpBaseTest\:\:\$defaultHeaders\.$#' + identifier: property.staticAccess + count: 1 + # Only occurs with php-http/client-integration-tests < 4.0.0 + reportUnmatched: false + path: tests/DefaultHttpAdapterWithConfigTest.php + + - + message: '#^Attribute class PHPUnit\\Framework\\Attributes\\DataProvider does not exist\.$#' + identifier: attribute.notFound + count: 1 + # Only occurs with phpunit/phpunit < 10.0.0 + reportUnmatched: false + path: tests/PromiseExceptionTest.php + + - + message: '#^Call to function method_exists\(\) with GuzzleHttp\\Exception\\RequestException and ''getResponse'' will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + # Only occurs with guzzlehttp/guzzle < 8.0.0 + reportUnmatched: false + path: src/Promise.php + + - + message: '#^Call to function method_exists\(\) with GuzzleHttp\\Exception\\RequestException and ''hasResponse'' will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + # Only occurs with guzzlehttp/guzzle < 8.0.0 + reportUnmatched: false + path: src/Promise.php + + - + message: '#^Parameter \#2 \$code of class GuzzleHttp\\Exception\\TransferException constructor expects int, PHPUnit\\Framework\\MockObject\\MockObject&Psr\\Http\\Message\\RequestInterface given\.$#' + identifier: argument.type + count: 1 + # Only occurs with guzzlehttp/guzzle < 8.0.0 + reportUnmatched: false + path: tests/PromiseExceptionTest.php + + - + message: '#^Call to function method_exists\(\) with ''GuzzleHttp\\\\Exception\\\\TransferException'' and ''getRequest'' will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + # Only occurs with guzzlehttp/guzzle ≥ 8.0.0 + reportUnmatched: false + path: tests/PromiseExceptionTest.php + + - + message: '#^Class GuzzleHttp\\Exception\\TransferException constructor invoked with 1 parameter, 2\-4 required\.$#' + identifier: arguments.count + count: 1 + # Only occurs with guzzlehttp/guzzle ≥ 8.0.0 + reportUnmatched: false + path: tests/PromiseExceptionTest.php diff --git a/src/Promise.php b/src/Promise.php index 14a8812..4b92c8a 100644 --- a/src/Promise.php +++ b/src/Promise.php @@ -109,7 +109,8 @@ private function handleException(GuzzleExceptions\GuzzleException $exception) if ($exception instanceof GuzzleExceptions\RequestException) { // Make sure we have a response for the HttpException - if ($exception->hasResponse()) { + if ((class_exists(GuzzleExceptions\ResponseException::class) && $exception instanceof GuzzleExceptions\ResponseException) + || (method_exists($exception, 'hasResponse') && method_exists($exception, 'getResponse') && $exception->hasResponse())) { return new HttplugException\HttpException( $exception->getMessage(), $exception->getRequest(), diff --git a/tests/PromiseExceptionTest.php b/tests/PromiseExceptionTest.php index a80083e..18c69ef 100644 --- a/tests/PromiseExceptionTest.php +++ b/tests/PromiseExceptionTest.php @@ -38,28 +38,51 @@ public function testExceptionThatIsThrownForGuzzleException( $promise->wait(); } - public static function exceptionThatIsThrownForGuzzleExceptionProvider(): array + public static function exceptionThatIsThrownForGuzzleExceptionProvider(): iterable { $request = (new PromiseExceptionTest('request'))->getMockBuilder(RequestInterface::class)->getMock(); $response = (new PromiseExceptionTest('response'))->getMockBuilder(ResponseInterface::class)->getMock(); - return [ - [$request, new GuzzleExceptions\ConnectException('foo', $request), NetworkException::class], - [$request, new GuzzleExceptions\TooManyRedirectsException('foo', $request), RequestException::class], - [$request, new GuzzleExceptions\RequestException('foo', $request, $response), HttpException::class], - [$request, new GuzzleExceptions\BadResponseException('foo', $request, $response), HttpException::class], - [$request, new GuzzleExceptions\ClientException('foo', $request, $response), HttpException::class], - [$request, new GuzzleExceptions\ServerException('foo', $request, $response), HttpException::class], - [$request, new GuzzleExceptions\TransferException('foo'), TransferException::class], - // check cases without response - [$request, new GuzzleExceptions\RequestException('foo', $request), RequestException::class], - [$request, new GuzzleExceptions\BadResponseException('foo', $request, $response), RequestException::class], - [$request, new GuzzleExceptions\ClientException('foo', $request, $response), RequestException::class], - [$request, new GuzzleExceptions\ServerException('foo', $request, $response), RequestException::class], - // Non PSR-18 Exceptions thrown - [$request, new \Exception('foo'), TransferException::class], - [$request, new \Error('foo'), TransferException::class], - [$request, 'whatever', UnexpectedValueException::class], - ]; + + yield [$request, new GuzzleExceptions\ConnectException('foo', $request), NetworkException::class]; + + yield [$request, new GuzzleExceptions\TooManyRedirectsException('foo', $request, $response), RequestException::class]; + + yield [$request, new GuzzleExceptions\RequestException('foo', $request), HttpException::class]; + + if (class_exists(GuzzleExceptions\ResponseException::class)) { + // Guzzle 8 + yield [$request, new GuzzleExceptions\ResponseException('foo', $request, $response), HttpException::class]; + } + + yield [$request, new GuzzleExceptions\BadResponseException('foo', $request, $response), HttpException::class]; + + yield [$request, new GuzzleExceptions\ClientException('foo', $request, $response), HttpException::class]; + + yield [$request, new GuzzleExceptions\ServerException('foo', $request, $response), HttpException::class]; + + if (method_exists(GuzzleExceptions\TransferException::class, 'getRequest')) { + // Guzzle 8 + yield [$request, new GuzzleExceptions\TransferException('foo', $request), TransferException::class]; + } else { + // Guzzle 7 + yield [$request, new GuzzleExceptions\TransferException('foo'), TransferException::class]; + } + + // check cases without response + yield [$request, new GuzzleExceptions\RequestException('foo', $request), RequestException::class]; + + yield [$request, new GuzzleExceptions\BadResponseException('foo', $request, $response), RequestException::class]; + + yield [$request, new GuzzleExceptions\ClientException('foo', $request, $response), RequestException::class]; + + yield [$request, new GuzzleExceptions\ServerException('foo', $request, $response), RequestException::class]; + + // Non PSR-18 Exceptions thrown + yield [$request, new \Exception('foo'), TransferException::class]; + + yield [$request, new \Error('foo'), TransferException::class]; + + yield [$request, 'whatever', UnexpectedValueException::class]; } }