From 85502c4e5a879eca24f4608d00b69c408bc63c34 Mon Sep 17 00:00:00 2001 From: romalytvynenko Date: Tue, 2 Jul 2024 09:37:29 +0300 Subject: [PATCH] =?UTF-8?q?=D0=90dded=20`response`=20method=20support=20on?= =?UTF-8?q?=20resource=20instances=20(#440)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added response method support on resource instances * Fix styling --------- Co-authored-by: romalytvynenko --- src/ScrambleServiceProvider.php | 2 ++ .../InferExtensions/JsonResourceExtension.php | 34 +++++++++---------- tests/ResponseDocumentingTest.php | 29 ++++++++++++++++ 3 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/ScrambleServiceProvider.php b/src/ScrambleServiceProvider.php index 5ab1d49c..50401c80 100644 --- a/src/ScrambleServiceProvider.php +++ b/src/ScrambleServiceProvider.php @@ -21,6 +21,7 @@ use Dedoc\Scramble\Support\InferExtensions\AbortHelpersExceptionInfer; use Dedoc\Scramble\Support\InferExtensions\JsonResourceCallsTypeInfer; use Dedoc\Scramble\Support\InferExtensions\JsonResourceCreationInfer; +use Dedoc\Scramble\Support\InferExtensions\JsonResourceExtension; use Dedoc\Scramble\Support\InferExtensions\JsonResourceTypeInfer; use Dedoc\Scramble\Support\InferExtensions\JsonResponseMethodReturnTypeExtension; use Dedoc\Scramble\Support\InferExtensions\ModelExtension; @@ -89,6 +90,7 @@ public function configurePackage(Package $package): void $inferExtensionsClasses = array_merge([ ResponseMethodReturnTypeExtension::class, + JsonResourceExtension::class, JsonResponseMethodReturnTypeExtension::class, ModelExtension::class, ], $inferExtensionsClasses); diff --git a/src/Support/InferExtensions/JsonResourceExtension.php b/src/Support/InferExtensions/JsonResourceExtension.php index e1574c0a..ce1bbf3a 100644 --- a/src/Support/InferExtensions/JsonResourceExtension.php +++ b/src/Support/InferExtensions/JsonResourceExtension.php @@ -2,30 +2,28 @@ namespace Dedoc\Scramble\Support\InferExtensions; -use Dedoc\Scramble\Infer\Definition\ClassDefinition; +use Dedoc\Scramble\Infer\Extensions\Event\MethodCallEvent; +use Dedoc\Scramble\Infer\Extensions\MethodReturnTypeExtension; +use Dedoc\Scramble\Support\Type\ArrayType; +use Dedoc\Scramble\Support\Type\Generic; +use Dedoc\Scramble\Support\Type\Literal\LiteralIntegerType; +use Dedoc\Scramble\Support\Type\ObjectType; +use Dedoc\Scramble\Support\Type\Type; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Resources\Json\JsonResource; -use Illuminate\Http\Resources\Json\ResourceCollection; -class JsonResourceExtension +class JsonResourceExtension implements MethodReturnTypeExtension { - public function shouldHandle(ClassDefinition $type) + public function shouldHandle(ObjectType $type): bool { - return $type->isInstanceOf(JsonResource::class) - && ! $type->isInstanceOf(ResourceCollection::class); + return $type->isInstanceOf(JsonResource::class); } - public function getPropertyType(PropertyFetchEvent $event) + public function getMethodReturnType(MethodCallEvent $event): ?Type { - if ($event->getDefinition()->hasProperty($event->getName())) { - return null; - } - - $modelType = $event->getInstance()->templateTypes[0]; - - if ($event->getName() === 'resource') { - return $modelType; - } - - return $modelType->getPropertyType($event->getName()); + return match ($event->name) { + 'response', 'toResponse' => new Generic(JsonResponse::class, [$event->getInstance(), new LiteralIntegerType(200), new ArrayType]), + default => null, + }; } } diff --git a/tests/ResponseDocumentingTest.php b/tests/ResponseDocumentingTest.php index 807be2aa..1a37c5fd 100644 --- a/tests/ResponseDocumentingTest.php +++ b/tests/ResponseDocumentingTest.php @@ -127,3 +127,32 @@ public function toArray(\Illuminate\Http\Request $request) ]; } } + +test('automated response status code inference when using ->response->setStatusCode method', function () { + $openApiDocument = generateForRoute(fn () => \Illuminate\Support\Facades\Route::get('api/test', [Foo_TestSix::class, 'single'])); + + expect($openApiDocument['paths']['/test']['get']['responses'][201]['content']['application/json']['schema']) + ->toBe(['$ref' => '#/components/schemas/Foo_TestFiveResource']); +}); + +test('automated response status code inference when using collection ->response->setStatusCode method', function () { + $openApiDocument = generateForRoute(fn () => \Illuminate\Support\Facades\Route::get('api/test', [Foo_TestSix::class, 'collection'])); + + expect($openApiDocument['paths']['/test']['get']['responses'][201]['content']['application/json']['schema']) + ->toBe([ + 'type' => 'array', + 'items' => ['$ref' => '#/components/schemas/Foo_TestFiveResource'], + ]); +}); +class Foo_TestSix +{ + public function single() + { + return (new Foo_TestFiveResource())->response()->setStatusCode(201); + } + + public function collection() + { + return Foo_TestFiveResource::collection()->response()->setStatusCode(201); + } +}