diff --git a/composer.json b/composer.json index 37ee0b9..48e91bc 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,7 @@ }, "require": { "spatie/laravel-data": "^4", - "laravel/framework": "^8|^9|^10|^11", + "laravel/framework": "^8|^9|^10|^11|^12", "phpdocumentor/reflection-docblock": "^5.4", "spatie/invade": "^2" }, diff --git a/src/Data/Operation.php b/src/Data/Operation.php index 62b5ed4..7796a9c 100644 --- a/src/Data/Operation.php +++ b/src/Data/Operation.php @@ -7,6 +7,7 @@ use Illuminate\Http\Response as HttpResponse; use Illuminate\Routing\Route; use Illuminate\Support\Collection; +use Illuminate\Support\Str; use ReflectionClass; use ReflectionFunction; use ReflectionMethod; @@ -36,7 +37,7 @@ public static function fromRoute(Route $route, string $method): self if (is_string($uses)) { $controller_class = new ReflectionClass($route->getController()); - $controller_function = $controller_class->getMethod($route->getActionMethod()); + $controller_function = $controller_class->getMethod(Str::parseCallback($route->action['uses'])[1]); echo $controller_class->name, "::", $controller_function->name, "\n"; } elseif ($uses instanceof Closure) { diff --git a/src/Data/Property.php b/src/Data/Property.php index 288e0f4..3887344 100644 --- a/src/Data/Property.php +++ b/src/Data/Property.php @@ -7,7 +7,7 @@ use ReflectionProperty; use RuntimeException; use Spatie\LaravelData\Data; -use Spatie\LaravelData\Data as LaravelData; +use Spatie\LaravelData\Support\Types\Storage\AcceptedTypesStorage; class Property extends Data { @@ -27,7 +27,8 @@ public function getName(): string */ public static function fromDataClass(string $class): Collection { - if (! is_a($class, LaravelData::class, true)) { + ['kind' => $kind] = AcceptedTypesStorage::getAcceptedTypesAndKind($class); + if ($kind->isNonDataRelated()) { throw new RuntimeException('Class does not extend LaravelData'); } diff --git a/src/Data/Schema.php b/src/Data/Schema.php index 2e070ec..cebbaa4 100644 --- a/src/Data/Schema.php +++ b/src/Data/Schema.php @@ -24,6 +24,7 @@ use Spatie\LaravelData\Support\Factories\DataPropertyFactory; use Spatie\LaravelData\Support\Transformation\TransformationContext; use Spatie\LaravelData\Support\Transformation\TransformationContextFactory; +use Spatie\LaravelData\Support\Types\Storage\AcceptedTypesStorage; use UnitEnum; use Xolvio\OpenApiGenerator\Attributes\CustomContentType; use Xolvio\OpenApiGenerator\Attributes\HttpResponseStatus; @@ -236,7 +237,8 @@ protected static function fromData(string $type_name, bool $nullable): self { $type_name = ltrim($type_name, '\\'); - if (! is_a($type_name, LaravelData::class, true)) { + ['kind' => $kind] = AcceptedTypesStorage::getAcceptedTypesAndKind($type_name); + if ($kind->isNonDataRelated()) { throw new RuntimeException("Type {$type_name} is not a Data class"); } @@ -259,7 +261,8 @@ protected static function fromDataCollection(string $type_name, bool $nullable): { $type_name = ltrim($type_name, '\\'); - if (! is_a($type_name, LaravelData::class, true)) { + ['kind' => $kind] = AcceptedTypesStorage::getAcceptedTypesAndKind($type_name); + if ($kind->isNonDataRelated()) { throw new RuntimeException("Type {$type_name} is not a Data class"); } @@ -297,6 +300,29 @@ protected static function fromListDocblock(ReflectionMethod|ReflectionFunction|R } $class = $tag_type->getValueType()->__toString(); + if (! class_exists($class) && str_starts_with($class, '\\')) { + if ($reflection instanceof ReflectionProperty || $reflection instanceof ReflectionMethod) { + $declaringClass = $reflection->getDeclaringClass(); + } else { + throw new RuntimeException('Cannot resolve class from function reflection'); + } + + $fileName = $declaringClass->getFileName(); + if ($fileName) { + $fileContents = file_get_contents($fileName); + $className = ltrim($class, '\\'); + + // Match use statements + preg_match_all('/use\s+([^;]+);/i', $fileContents, $matches); + foreach ($matches[1] as $useStatement) { + $useStatement = trim($useStatement); + if (str_ends_with($useStatement, '\\' . $className) || $useStatement === $className) { + $class = '\\' . ltrim($useStatement, '\\'); + break; + } + } + } + } return new self( type: 'array', diff --git a/src/OpenApiServiceProvider.php b/src/OpenApiServiceProvider.php index 023e870..456d487 100644 --- a/src/OpenApiServiceProvider.php +++ b/src/OpenApiServiceProvider.php @@ -19,6 +19,10 @@ public function boot(): void ]); } + if (! config('openapi-generator.enabled')) { + return; + } + $this->loadRoutesFrom(__DIR__ . '/routes/routes.php'); $this->loadViewsFrom(__DIR__ . '/resources/views', 'openapi-generator'); } diff --git a/src/config/openapi-generator.php b/src/config/openapi-generator.php index 5cb4aeb..ba66871 100644 --- a/src/config/openapi-generator.php +++ b/src/config/openapi-generator.php @@ -1,6 +1,17 @@ env('OPENAPI_ENABLED', true), + /* |-------------------------------------------------------------------------- | OpenAPI version