diff --git a/CHANGELOG.md b/CHANGELOG.md index 6dddac6..701a5e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +3.3.0 +===== + +* (feature) Add user-readable error message in `ApiResponse`. + + 3.2.2 ===== diff --git a/src/Api/ApiResponse.php b/src/Api/ApiResponse.php index 128141c..594e597 100644 --- a/src/Api/ApiResponse.php +++ b/src/Api/ApiResponse.php @@ -2,10 +2,13 @@ namespace Torr\Rad\Api; +use Symfony\Component\Translation\TranslatableMessage; + class ApiResponse { public int $statusCode; public ?string $error = null; + public TranslatableMessage|string|null $errorMessage = null; /** */ @@ -48,11 +51,18 @@ public function withStatusCode (int $statusCode) : self } /** + * @param string|null $error An error code + * @param string|null $errorMessage A user-readable error message + * * @return $this */ - public function withError (?string $error) : self + public function withError ( + ?string $error, + TranslatableMessage|string|null $errorMessage = null, + ) : self { $this->error = $error; + $this->errorMessage = $errorMessage; return $this; } @@ -64,4 +74,13 @@ public function isOk () : bool { return $this->statusCode >= 200 && $this->statusCode <= 299; } + + /** + * Sghort + */ + public static function error (string $errorMessage, int $statusCode = 400) : self + { + return (new self($statusCode)) + ->withError($errorMessage); + } } diff --git a/src/Api/ApiResponseNormalizer.php b/src/Api/ApiResponseNormalizer.php index e418e8b..1a4e461 100644 --- a/src/Api/ApiResponseNormalizer.php +++ b/src/Api/ApiResponseNormalizer.php @@ -2,8 +2,17 @@ namespace Torr\Rad\Api; +use Symfony\Component\Translation\TranslatableMessage; +use Symfony\Contracts\Translation\TranslatorInterface; + final class ApiResponseNormalizer { + /** + */ + public function __construct ( + private readonly TranslatorInterface $translator, + ) {} + /** * Normalizes the given API response * @@ -16,6 +25,9 @@ public function normalize (ApiResponse $apiResponse) : array "ok" => $apiResponse->isOk(), "data" => $apiResponse->data, "error" => $apiResponse->error, + "errorMessage" => $apiResponse->errorMessage instanceof TranslatableMessage + ? $apiResponse->errorMessage->trans($this->translator) + : $apiResponse->errorMessage, ], static fn (mixed $value) => null !== $value, ); diff --git a/src/Form/FormErrorNormalizer.php b/src/Form/FormErrorNormalizer.php index d5a6584..e648c4f 100644 --- a/src/Form/FormErrorNormalizer.php +++ b/src/Form/FormErrorNormalizer.php @@ -29,7 +29,7 @@ private function normalizeNested (array &$errors, FormInterface $parent, string { if (null === $this->translator) { - throw new MissingOptionalDependencyException("symfony/translator"); + throw new MissingOptionalDependencyException("symfony/translation"); } foreach ($parent->all() as $child) diff --git a/tests/Api/ApiResponseNormalizerTest.php b/tests/Api/ApiResponseNormalizerTest.php index 0b56076..06b56a4 100644 --- a/tests/Api/ApiResponseNormalizerTest.php +++ b/tests/Api/ApiResponseNormalizerTest.php @@ -3,6 +3,7 @@ namespace Tests\Torr\Rad\Api; use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Translator; use Torr\Rad\Api\ApiResponse; use Torr\Rad\Api\ApiResponseNormalizer; @@ -17,7 +18,7 @@ final class ApiResponseNormalizerTest extends TestCase public function testMinimal () : void { $apiResponse = new ApiResponse(400); - $normalizer = new ApiResponseNormalizer(); + $normalizer = new ApiResponseNormalizer(new Translator("de")); self::assertSame([ "ok" => false, @@ -33,13 +34,14 @@ public function testMaximal () : void 200, ["o" => "hai"], )) - ->withError("error message"); - $normalizer = new ApiResponseNormalizer(); + ->withError("error code", "error message"); + $normalizer = new ApiResponseNormalizer(new Translator("de")); self::assertSame([ "ok" => true, "data" => ["o" => "hai"], - "error" => "error message", + "error" => "error code", + "errorMessage" => "error message", ], $normalizer->normalize($apiResponse)); } } diff --git a/tests/Listener/ControllerResponseListenerTest.php b/tests/Listener/ControllerResponseListenerTest.php index e97faaf..aea6399 100644 --- a/tests/Listener/ControllerResponseListenerTest.php +++ b/tests/Listener/ControllerResponseListenerTest.php @@ -8,6 +8,7 @@ use Symfony\Component\HttpKernel\Event\ViewEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelInterface; +use Symfony\Component\Translation\Translator; use Torr\Rad\Api\ApiResponse; use Torr\Rad\Api\ApiResponseNormalizer; use Torr\Rad\Listener\ControllerResponseListener; @@ -24,7 +25,7 @@ public function testIntegration () : void { $event = $this->createEvent(new ApiResponse(200)); - $listener = new ControllerResponseListener(new ApiResponseNormalizer()); + $listener = new ControllerResponseListener(new ApiResponseNormalizer(new Translator("de"))); $listener->onView($event); self::assertInstanceOf(JsonResponse::class, $event->getResponse()); @@ -37,7 +38,7 @@ public function testIntegrationWithOtherResult () : void { $event = $this->createEvent(11); - $listener = new ControllerResponseListener(new ApiResponseNormalizer()); + $listener = new ControllerResponseListener(new ApiResponseNormalizer(new Translator("de"))); $listener->onView($event); self::assertNull($event->getResponse()); @@ -60,7 +61,7 @@ public function testStatusCode (int $expectedStatusCode, ApiResponse $apiRespons { $event = $this->createEvent($apiResponse); - $listener = new ControllerResponseListener(new ApiResponseNormalizer()); + $listener = new ControllerResponseListener(new ApiResponseNormalizer(new Translator("de"))); $listener->onView($event); $response = $event->getResponse();