diff --git a/src/Generator/ClassGenerator.php b/src/Generator/ClassGenerator.php index 7347a44..a7386e3 100644 --- a/src/Generator/ClassGenerator.php +++ b/src/Generator/ClassGenerator.php @@ -58,6 +58,10 @@ private function addSchemas(Configuration $configuration, OpenApi $openApi): arr $models = []; foreach ($schemas as $name => $schema) { + if ($schema instanceof Reference) { + $schema = $schema->resolve(); + } + if ($schema instanceof Schema) { $classModel = $this->classTransformer->transform( $configuration, diff --git a/src/Generator/ClassTransformer.php b/src/Generator/ClassTransformer.php index a27a37d..a5da35e 100644 --- a/src/Generator/ClassTransformer.php +++ b/src/Generator/ClassTransformer.php @@ -23,6 +23,7 @@ use Reinfi\OpenApiModels\Model\ArrayType; use Reinfi\OpenApiModels\Model\ClassModel; use Reinfi\OpenApiModels\Model\Imports; +use Reinfi\OpenApiModels\Model\InlineSchemaReference; use Reinfi\OpenApiModels\Model\OneOfReference; use Reinfi\OpenApiModels\Model\OneOfType; use Reinfi\OpenApiModels\Model\ScalarType; @@ -504,6 +505,11 @@ private function resolveArrayType( $arrayType = Types::OneOf; } + if ($arrayType instanceof InlineSchemaReference) { + $itemsSchema = $arrayType->schema; + $arrayType = Types::Object; + } + if ($arrayType === Types::Object) { $inlineObject = $this->transformInlineObject( $configuration, diff --git a/src/Generator/PropertyResolver.php b/src/Generator/PropertyResolver.php index ddceb30..e9b0724 100644 --- a/src/Generator/PropertyResolver.php +++ b/src/Generator/PropertyResolver.php @@ -8,6 +8,7 @@ use Nette\PhpGenerator\PromotedParameter; use openapiphp\openapi\spec\Reference; use openapiphp\openapi\spec\Schema; +use Reinfi\OpenApiModels\Model\InlineSchemaReference; use Reinfi\OpenApiModels\Model\OneOfReference; use Reinfi\OpenApiModels\Model\ScalarType; @@ -18,7 +19,7 @@ public function resolve( string $name, Schema|Reference $schema, bool $required, - ScalarType|ClassReference|OneOfReference|Types|string $type, + ScalarType|ClassReference|InlineSchemaReference|OneOfReference|Types|string $type, ): PromotedParameter { $property = $constructor->addPromotedParameter($name); diff --git a/src/Generator/ReferenceResolver.php b/src/Generator/ReferenceResolver.php index e405225..10eba9c 100644 --- a/src/Generator/ReferenceResolver.php +++ b/src/Generator/ReferenceResolver.php @@ -10,6 +10,7 @@ use openapiphp\openapi\spec\Schema; use Reinfi\OpenApiModels\Exception\InvalidReferenceException; use Reinfi\OpenApiModels\Model\SchemaWithName; +use Throwable; readonly class ReferenceResolver { @@ -20,8 +21,21 @@ public function resolve(OpenApi $openApi, Reference $reference): SchemaWithName $reference->getReference(), $matches ) !== 1) { + try { + $resolvedSchema = $reference->resolve(); + + if ($resolvedSchema instanceof Schema) { + return new SchemaWithName(OpenApiType::Schemas, '', $resolvedSchema); + } + } catch (Throwable $throwable) { + throw new InvalidArgumentException( + sprintf('Invalid reference "%s" given, does not match pattern', $reference->getReference()), + previous: $throwable, + ); + } + throw new InvalidArgumentException( - sprintf('Invalid reference "%s" given, does not match pattern', $reference->getReference()) + sprintf('Invalid reference "%s" given, does not match pattern', $reference->getReference()), ); } diff --git a/src/Generator/TypeResolver.php b/src/Generator/TypeResolver.php index d858cdf..9af0f6d 100644 --- a/src/Generator/TypeResolver.php +++ b/src/Generator/TypeResolver.php @@ -9,6 +9,7 @@ use openapiphp\openapi\spec\OpenApi; use openapiphp\openapi\spec\Reference; use openapiphp\openapi\spec\Schema; +use Reinfi\OpenApiModels\Model\InlineSchemaReference; use Reinfi\OpenApiModels\Model\OneOfReference; use Reinfi\OpenApiModels\Model\ScalarType; @@ -22,13 +23,13 @@ public function __construct( /** * @phpstan-assert Schema $schema when return type is string|Types|null - * @return ($schema is Reference ? ClassReference|OneOfReference|ScalarType : ($throwException is true ? string|Types : string|Types|null)) + * @return ($schema is Reference ? ClassReference|InlineSchemaReference|OneOfReference|ScalarType : ($throwException is true ? string|Types : string|Types|null)) */ public function resolve( OpenApi $openApi, Schema|Reference $schema, bool $throwException = true - ): ScalarType|ClassReference|OneOfReference|string|Types|null { + ): ScalarType|ClassReference|InlineSchemaReference|OneOfReference|string|Types|null { if ($schema instanceof Reference) { $schemaWithName = $this->referenceResolver->resolve($openApi, $schema); @@ -46,6 +47,10 @@ public function resolve( return new ScalarType($referenceType, $schemaWithName->schema); } + if ($schemaWithName->name === '') { + return new InlineSchemaReference($schemaWithName->schema); + } + return new ClassReference( $schemaWithName->openApiType, $this->namespaceResolver->resolveNamespace($schemaWithName->openApiType, $schemaWithName->schema) diff --git a/src/Model/InlineSchemaReference.php b/src/Model/InlineSchemaReference.php new file mode 100644 index 0000000..3cd7b05 --- /dev/null +++ b/src/Model/InlineSchemaReference.php @@ -0,0 +1,15 @@ + [ 'type' => 'object', ], - 'Test3' => [ - '$ref' => '#/components/schemas/Test4', - ], ], ], ]); @@ -77,6 +74,12 @@ public function testItGeneratesRequestBodies(): void $configuration = new Configuration([], '', ''); $openApi = new OpenApi([ + 'openapi' => '3.0.0', + 'info' => [ + 'title' => 'Test API', + 'version' => '1.0.0', + ], + 'paths' => [], 'components' => [ 'requestBodies' => [ 'Test1' => [ @@ -123,6 +126,12 @@ public function testItGeneratesResponses(): void $configuration = new Configuration([], '', ''); $openApi = new OpenApi([ + 'openapi' => '3.0.0', + 'info' => [ + 'title' => 'Test API', + 'version' => '1.0.0', + ], + 'paths' => [], 'components' => [ 'responses' => [ 'Test1' => [ @@ -169,6 +178,12 @@ public function testItGeneratesReferenceClasses(): void $configuration = new Configuration([], '', ''); $openApi = new OpenApi([ + 'openapi' => '3.0.0', + 'info' => [ + 'title' => 'Test API', + 'version' => '1.0.0', + ], + 'paths' => [], 'components' => [ 'responses' => [ 'Test1' => [ @@ -215,6 +230,12 @@ public function testItGeneratesOnlyJsonSchema(): void $configuration = new Configuration([], '', ''); $openApi = new OpenApi([ + 'openapi' => '3.0.0', + 'info' => [ + 'title' => 'Test API', + 'version' => '1.0.0', + ], + 'paths' => [], 'components' => [ 'responses' => [ 'Test1' => [ @@ -270,6 +291,12 @@ public function testItThrowsExceptionIfJsonContentTypeNotFound(): void $configuration = new Configuration([], '', ''); $openApi = new OpenApi([ + 'openapi' => '3.0.0', + 'info' => [ + 'title' => 'Test API', + 'version' => '1.0.0', + ], + 'paths' => [], 'components' => [ 'responses' => [ 'Test1' => [ @@ -304,6 +331,12 @@ public function testItSetsCommentIfTopLevelHasDescription(): void $configuration = new Configuration([], '', ''); $openApi = new OpenApi([ + 'openapi' => '3.0.0', + 'info' => [ + 'title' => 'Test API', + 'version' => '1.0.0', + ], + 'paths' => [], 'components' => [ 'responses' => [ 'Test1' => [ diff --git a/test/Generator/ReferenceResolverTest.php b/test/Generator/ReferenceResolverTest.php index a8b4325..28bcbe2 100644 --- a/test/Generator/ReferenceResolverTest.php +++ b/test/Generator/ReferenceResolverTest.php @@ -57,11 +57,19 @@ public function testItThrowsExceptionIfNotValidReference(): void self::expectException(InvalidArgumentException::class); self::expectExceptionMessage('Invalid reference "no-valid-reference" given, does not match pattern'); - $openApi = new OpenApi([]); - $reference = new Reference([ - '$ref' => 'no-valid-reference', + $openApi = new OpenApi([ + 'components' => [ + 'schemas' => [ + 'InvalidReference' => [ + '$ref' => 'no-valid-reference', + ], + ], + ], ]); + $reference = $openApi->components?->schemas['InvalidReference']; + self::assertInstanceOf(Reference::class, $reference); + $resolver = new ReferenceResolver(); $resolver->resolve($openApi, $reference); }