diff --git a/CHANGELOG.md b/CHANGELOG.md index c0b408d..6cc4a0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +3.1.0 (unreleased) +===== + +* (deprecation) Deprecate passing a `bool` to the constructor of `ApiResponse`. +* (feature) Enforce passing an explicit status code to the constructor of `ApiReponse`. + 3.0.2 ===== diff --git a/UPGRADE.md b/UPGRADE.md index c2fdec7..2e3c6fa 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,3 +1,10 @@ +3.x to 4.0 +========== + +* Passing a `bool` to the constructor of `ApiResponse` was removed, pass a status code instead. +* The method `ApiResponse::withStatusCode()` was removed. Pass the status code in the constructor instead. + + 2.x to 3.0 ========== diff --git a/src/Api/ApiResponse.php b/src/Api/ApiResponse.php index 5815ee8..646f4c5 100644 --- a/src/Api/ApiResponse.php +++ b/src/Api/ApiResponse.php @@ -10,11 +10,20 @@ class ApiResponse /** */ public function __construct ( - public readonly bool $ok, + bool|int $statusCode, public readonly mixed $data = null, ) { - $this->statusCode = $ok ? 200 : 400; + // @todo remove check in v4, make parameter int only and readonly. + if (\is_int($statusCode)) + { + $this->statusCode = $statusCode; + } + else + { + \trigger_deprecation("21torr/rad", "3.1.0", "Passing a bool as first value to ApiResponse is deprecated. Pass the status code instead."); + $this->statusCode = $statusCode ? 200 : 400; + } } @@ -23,6 +32,13 @@ public function __construct ( */ public function withStatusCode (int $statusCode) : self { + // @todo remove method in v4 + \trigger_deprecation( + "21torr/rad", + "3.1.0", + "Calling ApiResponse::withStatusCode() is deprecated, pass the status code in the constructor instead.", + ); + $this->statusCode = $statusCode; return $this; } @@ -36,4 +52,13 @@ public function withError (?string $error) : self $this->error = $error; return $this; } + + + /** + * + */ + public function isOk () : bool + { + return $this->statusCode >= 200 && $this->statusCode <= 299; + } } diff --git a/src/Api/ApiResponseNormalizer.php b/src/Api/ApiResponseNormalizer.php index d8cc3a2..2468597 100644 --- a/src/Api/ApiResponseNormalizer.php +++ b/src/Api/ApiResponseNormalizer.php @@ -11,7 +11,7 @@ public function normalize (ApiResponse $apiResponse) : array { return \array_filter( [ - "ok" => $apiResponse->ok, + "ok" => $apiResponse->isOk(), "data" => $apiResponse->data, "error" => $apiResponse->error, ], diff --git a/tests/Api/ApiResponseNormalizerTest.php b/tests/Api/ApiResponseNormalizerTest.php index 057bb97..8b668f7 100644 --- a/tests/Api/ApiResponseNormalizerTest.php +++ b/tests/Api/ApiResponseNormalizerTest.php @@ -13,7 +13,7 @@ class ApiResponseNormalizerTest extends TestCase */ public function testMinimal () : void { - $apiResponse = new ApiResponse(false); + $apiResponse = new ApiResponse(400); $normalizer = new ApiResponseNormalizer(); self::assertEquals([ @@ -27,7 +27,7 @@ public function testMinimal () : void public function testMaximal () : void { $apiResponse = (new ApiResponse( - true, + 200, ["o" => "hai"], )) ->withError("error message"); diff --git a/tests/Api/ApiResponseTest.php b/tests/Api/ApiResponseTest.php new file mode 100644 index 0000000..d1c07a4 --- /dev/null +++ b/tests/Api/ApiResponseTest.php @@ -0,0 +1,51 @@ +isOk()); + self::assertFalse((new ApiResponse(418))->isOk()); + } + + + /** + * @group legacy + */ + public function testLegacyBoolConstructorTrue () : void + { + $this->expectDeprecation("Since 21torr/rad 3.1.0: Passing a bool as first value to ApiResponse is deprecated. Pass the status code instead."); + new ApiResponse(true); + } + + /** + * @group legacy + */ + public function testLegacyBoolConstructorFalse () : void + { + $this->expectDeprecation("Since 21torr/rad 3.1.0: Passing a bool as first value to ApiResponse is deprecated. Pass the status code instead."); + new ApiResponse(false); + } + + /** + * @group legacy + */ + public function testLegacyResettingStatusCode () : void + { + $this->expectDeprecation("Since 21torr/rad 3.1.0: Calling ApiResponse::withStatusCode() is deprecated, pass the status code in the constructor instead."); + + (new ApiResponse(201)) + ->withStatusCode(418); + } +} diff --git a/tests/Listener/ControllerResponseListenerTest.php b/tests/Listener/ControllerResponseListenerTest.php index dbc6167..cbf9147 100644 --- a/tests/Listener/ControllerResponseListenerTest.php +++ b/tests/Listener/ControllerResponseListenerTest.php @@ -19,7 +19,7 @@ class ControllerResponseListenerTest extends TestCase */ public function testIntegration () : void { - $event = $this->createEvent(new ApiResponse(true)); + $event = $this->createEvent(new ApiResponse(200)); $listener = new ControllerResponseListener(new ApiResponseNormalizer()); $listener->onView($event); @@ -46,9 +46,9 @@ public function testIntegrationWithOtherResult () : void */ public function provideStatusCode () : iterable { - yield [200, new ApiResponse(true)]; - yield [400, new ApiResponse(false)]; - yield [418, (new ApiResponse(false))->withStatusCode(418)]; + yield [200, new ApiResponse(200)]; + yield [400, new ApiResponse(400)]; + yield [418, new ApiResponse(418)]; } /**