diff --git a/src/Support/OperationExtensions/RequestEssentialsExtension.php b/src/Support/OperationExtensions/RequestEssentialsExtension.php index 694bd9e2..171ff0f8 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,16 @@ private function getExplicitlyBoundParamType(string $name): ?string return null; } - private function getParameterType(string $paramName, string $description, RouteInfo $routeInfo, Route $route, ?ParamTagValueNode $phpDocParam, ?ReflectionParameter $reflectionParam) - { - $type = new UnknownType; + private function getParameterType( + string $paramName, + string $description, + RouteInfo $routeInfo, + Route $route, + ?ParamTagValueNode $phpDocParam, + ?ReflectionParameter $reflectionParam, + ?string $boundClass, + ) { + $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']);