diff --git a/.styleci.yml b/.styleci.yml index 5328b61..2c1e770 100644 --- a/.styleci.yml +++ b/.styleci.yml @@ -12,3 +12,4 @@ enabled: disabled: - phpdoc_annotation_without_dot # This is still buggy: https://github.com/symfony/symfony/pull/19198 + - single_line_throw diff --git a/CHANGELOG.md b/CHANGELOG.md index b2202bb..f034858 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,19 @@ # Change Log -## 1.4.0 - +## 1.4.0 - 2020-07-02 + +### Added + +- Support for the PSR-17 response factory + +### Changed + +- Drop support for PHP 5 and 7.0 +- Consitent implementation of union type checking ### Fixed -- `reset()` should not trigger `setDefaultException` error condition -### Breaking -- drop support for PHP 5 and 7.0 +- `reset()` should not trigger `setDefaultException` error condition ## 1.3.1 - 2019-11-06 diff --git a/composer.json b/composer.json index 662387c..cc60787 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,11 @@ "php-http/client-common": "^1.9 || ^2.0", "php-http/discovery": "^1.0", "php-http/httplug": "^1.0 || ^2.0", - "php-http/message-factory": "^1.0" + "php-http/message-factory": "^1.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "symfony/polyfill-php80": "^1.17" }, "provide": { "php-http/async-client-implementation": "1.0", diff --git a/spec/ClientSpec.php b/spec/ClientSpec.php index f72481e..b5ee678 100644 --- a/spec/ClientSpec.php +++ b/spec/ClientSpec.php @@ -7,6 +7,7 @@ use Http\Message\RequestMatcher; use Http\Message\ResponseFactory; use Http\Mock\Client; +use Psr\Http\Client\ClientExceptionInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use PhpSpec\ObjectBehavior; @@ -49,16 +50,16 @@ function it_returns_the_default_response_for_a_request(RequestInterface $request function it_throws_an_exception_for_a_request(RequestInterface $request) { - $this->addException(new \Exception()); + $this->addException(new Exception()); - $this->shouldThrow('Exception')->duringSendRequest($request); + $this->shouldThrow(Exception::class)->duringSendRequest($request); } function it_throws_the_default_exception_for_a_request(RequestInterface $request) { - $this->setDefaultException(new \Exception()); + $this->setDefaultException(new Exception()); - $this->shouldThrow('Exception')->duringSendRequest($request); + $this->shouldThrow(Exception::class)->duringSendRequest($request); } function it_creates_an_empty_response_when_none_is_added( @@ -94,8 +95,8 @@ function it_reset( ) { $this->addResponse($response); $this->setDefaultResponse($response); - $this->addException(new \Exception()); - $this->setDefaultException(new \Exception()); + $this->addException(new Exception()); + $this->setDefaultException(new Exception()); $responseFactory->createResponse()->willReturn($newResponse); @@ -122,8 +123,8 @@ function it_throws_exception_if_request_matcher_matches( RequestInterface $request ) { $matcher->matches($request)->willReturn(true); - $this->on($matcher, new \Exception()); - $this->shouldThrow('Exception')->duringSendRequest($request); + $this->on($matcher, new Exception()); + $this->shouldThrow(Exception::class)->duringSendRequest($request); } function it_skips_conditional_response_if_matcher_returns_false( @@ -155,3 +156,7 @@ function(RequestInterface $request) use ($response) { $this->sendRequest($request)->shouldReturn($response); } } + +class Exception extends \Exception implements ClientExceptionInterface +{ +} diff --git a/src/Client.php b/src/Client.php index 1b3782b..7f6a606 100644 --- a/src/Client.php +++ b/src/Client.php @@ -12,6 +12,7 @@ use Http\Message\ResponseFactory; use Psr\Http\Client\ClientExceptionInterface; use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseFactoryInterface; use Psr\Http\Message\ResponseInterface; /** @@ -28,7 +29,7 @@ class Client implements HttpClient, HttpAsyncClient use VersionBridgeClient; /** - * @var ResponseFactory + * @var ResponseFactory|ResponseFactoryInterface */ private $responseFactory; @@ -62,8 +63,17 @@ class Client implements HttpClient, HttpAsyncClient */ private $defaultException; - public function __construct(ResponseFactory $responseFactory = null) + /** + * @param ResponseFactory|ResponseFactoryInterface|null + */ + public function __construct($responseFactory = null) { + if (!$responseFactory instanceof ResponseFactory && !$responseFactory instanceof ResponseFactoryInterface && null !== $responseFactory) { + throw new \TypeError( + sprintf('%s::__construct(): Argument #1 ($responseFactory) must be of type %s|%s|null, %s given', self::class, ResponseFactory::class, ResponseFactoryInterface::class, get_debug_type($responseFactory)) + ); + } + $this->responseFactory = $responseFactory ?: MessageFactoryDiscovery::find(); } @@ -122,6 +132,12 @@ public function doSendRequest(RequestInterface $request) */ public function on(RequestMatcher $requestMatcher, $result) { + if (!$result instanceof ResponseInterface && !$result instanceof Exception && !$result instanceof ClientExceptionInterface && !is_callable($result)) { + throw new \TypeError( + sprintf('%s::on(): Argument #2 ($result) must be of type %s|%s|%s|callable, %s given', self::class, ResponseInterface::class, Exception::class, ClientExceptionInterface::class, get_debug_type($result)) + ); + } + $callable = self::makeCallable($result); $this->conditionalResults[] = [ @@ -133,8 +149,6 @@ public function on(RequestMatcher $requestMatcher, $result) /** * @param ResponseInterface|Exception|ClientExceptionInterface|callable $result * - * @throws \InvalidArgumentException - * * @return callable */ private static function makeCallable($result) @@ -149,13 +163,9 @@ private static function makeCallable($result) }; } - if ($result instanceof \Exception) { - return function () use ($result) { - throw $result; - }; - } - - throw new \InvalidArgumentException('Result must be either a response, an exception, or a callable'); + return function () use ($result) { + throw $result; + }; } /**