From 795390947c8817ec13cf7a60704c3f75c55b86b0 Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko Date: Mon, 25 Nov 2024 14:24:08 +0200 Subject: [PATCH 1/2] improved route param documenting when it is explicitly bound --- .../RequestEssentialsExtension.php | 16 ++++++++-- .../RequestEssentialsExtensionTest.php | 31 +++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/Support/OperationExtensions/RequestEssentialsExtension.php b/src/Support/OperationExtensions/RequestEssentialsExtension.php index 694bd9e2..969dea57 100644 --- a/src/Support/OperationExtensions/RequestEssentialsExtension.php +++ b/src/Support/OperationExtensions/RequestEssentialsExtension.php @@ -244,7 +244,8 @@ private function getRoutePathParameters(RouteInfo $routeInfo) * 2. PhpDoc Typehint * 3. String (?) */ - $params = array_map(function (string $paramName) use ($routeInfo, $route, $aliases, $reflectionParamsByKeys, $phpDocTypehintParam) { + $params = array_map(function (string $paramName) use ($routeInfo, $route, $aliases, $reflectionParamsByKeys, $phpDocTypehintParam, $paramsValuesClasses) { + $originalParamName = $paramName; $paramName = $aliases[$paramName]; $description = $phpDocTypehintParam[$paramName]?->description ?? ''; @@ -255,6 +256,7 @@ private function getRoutePathParameters(RouteInfo $routeInfo) $route, $phpDocTypehintParam[$paramName] ?? null, $reflectionParamsByKeys[$paramName] ?? null, + $paramsValuesClasses[$originalParamName] ?? null, ); $param = Parameter::make($paramName, 'path') @@ -300,9 +302,17 @@ private function getExplicitlyBoundParamType(string $name): ?string return null; } - private function getParameterType(string $paramName, string $description, RouteInfo $routeInfo, Route $route, ?ParamTagValueNode $phpDocParam, ?ReflectionParameter $reflectionParam) + private function getParameterType( + string $paramName, + string $description, + RouteInfo $routeInfo, + Route $route, + ?ParamTagValueNode $phpDocParam, + ?ReflectionParameter $reflectionParam, + ?string $boundClass, + ) { - $type = new UnknownType; + $type = $boundClass ? new ObjectType($boundClass) : new UnknownType; if ($routeInfo->reflectionMethod()) { $type->setAttribute('file', $routeInfo->reflectionMethod()->getFileName()); $type->setAttribute('line', $routeInfo->reflectionMethod()->getStartLine()); diff --git a/tests/Support/OperationExtensions/RequestEssentialsExtensionTest.php b/tests/Support/OperationExtensions/RequestEssentialsExtensionTest.php index 0f26f862..acbccc21 100644 --- a/tests/Support/OperationExtensions/RequestEssentialsExtensionTest.php +++ b/tests/Support/OperationExtensions/RequestEssentialsExtensionTest.php @@ -51,6 +51,37 @@ class Foo_RequestRulesTest_Controller public function foo(ModelWithRulesMethod $model) {} } +it('uses explicit binding to infer more info about path params using Route::model', function () { + RouteFacade::model('model_bound', RequestEssentialsExtensionTest_SimpleModel::class); + + $openApiDocument = generateForRoute(function () { + return RouteFacade::get('api/test/{model_bound}', [Foo_RequestExplicitlyBoundTest_Controller::class, 'foo']); + }); + + expect($openApiDocument['paths']['/test/{model_bound}']['get']['parameters'][0]) + ->toHaveKey('schema.type', 'integer') + ->toHaveKey('description', 'The model bound ID'); +}); +it('uses explicit binding to infer more info about path params using Route::bind with typehint', function () { + RouteFacade::bind('model_bound', fn ($value): RequestEssentialsExtensionTest_SimpleModel => RequestEssentialsExtensionTest_SimpleModel::findOrFail($value)); + + $openApiDocument = generateForRoute(function () { + return RouteFacade::get('api/test/{model_bound}', [Foo_RequestExplicitlyBoundTest_Controller::class, 'foo']); + }); + + expect($openApiDocument['paths']['/test/{model_bound}']['get']['parameters'][0]) + ->toHaveKey('schema.type', 'integer') + ->toHaveKey('description', 'The model bound ID'); +}); +class RequestEssentialsExtensionTest_SimpleModel extends \Illuminate\Database\Eloquent\Model +{ + protected $table = 'users'; +} +class Foo_RequestExplicitlyBoundTest_Controller +{ + public function foo() {} +} + it('handles custom key from route to determine model route key type', function () { $openApiDocument = generateForRoute(function () { return RouteFacade::get('api/test/{user:name}', [CustomKey_RequestEssentialsExtensionTest_Controller::class, 'foo']); From f36955a49da414536ccbc04789e8c65b445bdb5f Mon Sep 17 00:00:00 2001 From: romalytvynenko Date: Mon, 25 Nov 2024 12:24:39 +0000 Subject: [PATCH 2/2] Fix styling --- src/Support/OperationExtensions/RequestEssentialsExtension.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Support/OperationExtensions/RequestEssentialsExtension.php b/src/Support/OperationExtensions/RequestEssentialsExtension.php index 969dea57..171ff0f8 100644 --- a/src/Support/OperationExtensions/RequestEssentialsExtension.php +++ b/src/Support/OperationExtensions/RequestEssentialsExtension.php @@ -310,8 +310,7 @@ private function getParameterType( ?ParamTagValueNode $phpDocParam, ?ReflectionParameter $reflectionParam, ?string $boundClass, - ) - { + ) { $type = $boundClass ? new ObjectType($boundClass) : new UnknownType; if ($routeInfo->reflectionMethod()) { $type->setAttribute('file', $routeInfo->reflectionMethod()->getFileName());