diff --git a/docs/reference/processors.md b/docs/reference/processors.md index 3ea46f9a..ae32253c 100644 --- a/docs/reference/processors.md +++ b/docs/reference/processors.md @@ -43,6 +43,9 @@ Determines `schema`, `enum` and `type`. Use the Schema context to extract useful information and inject that into the annotation. Merges properties. +## [AugmentRequestBody](https://github.com/zircote/swagger-php/tree/master/src/Processors/AugmentRequestBody.php) + +Use the RequestBody context to extract useful information and inject that into the annotation. ## [AugmentProperties](https://github.com/zircote/swagger-php/tree/master/src/Processors/AugmentProperties.php) Use the property context to extract useful information and inject that into the annotation. diff --git a/src/Analysis.php b/src/Analysis.php index 52c6e3ab..a200e402 100644 --- a/src/Analysis.php +++ b/src/Analysis.php @@ -324,6 +324,18 @@ public function getAnnotationsOfType($classes, bool $strict = false): array * @param string $fqdn the source class/interface/trait */ public function getSchemaForSource(string $fqdn): ?OA\Schema + { + return $this->getAnnotationForSource($fqdn, OA\Schema::class); + } + + /** + * @template T of OA\AbstractAnnotation + * + * @param string $fqdn the source class/interface/trait + * @param class-string $class + * @return T|null + */ + public function getAnnotationForSource(string $fqdn, string $class): ?OA\AbstractAnnotation { $fqdn = '\\' . ltrim($fqdn, '\\'); @@ -331,8 +343,9 @@ public function getSchemaForSource(string $fqdn): ?OA\Schema if (array_key_exists($fqdn, $definitions)) { $definition = $definitions[$fqdn]; if (is_iterable($definition['context']->annotations)) { + /** @var OA\AbstractAnnotation $annotation */ foreach (array_reverse($definition['context']->annotations) as $annotation) { - if ($annotation instanceof OA\Schema && $annotation->isRoot(OA\Schema::class) && !$annotation->_context->is('generated')) { + if (is_a($annotation, $class) && $annotation->isRoot($class) && !$annotation->_context->is('generated')) { return $annotation; } } diff --git a/src/Generator.php b/src/Generator.php index 8d5e3a2f..61cf7d41 100644 --- a/src/Generator.php +++ b/src/Generator.php @@ -261,6 +261,7 @@ public function getProcessors(): array new Processors\ExpandTraits(), new Processors\ExpandEnums(), new Processors\AugmentSchemas(), + new Processors\AugmentRequestBody(), new Processors\AugmentProperties(), new Processors\BuildPaths(), new Processors\AugmentParameters(), diff --git a/src/Processors/AugmentRefs.php b/src/Processors/AugmentRefs.php index 0e532a8f..b120d295 100644 --- a/src/Processors/AugmentRefs.php +++ b/src/Processors/AugmentRefs.php @@ -66,6 +66,8 @@ protected function resolveFQCNRefs(Analysis $analysis): void // check if we have a schema for this if ($refSchema = $analysis->getSchemaForSource($annotation->ref)) { $annotation->ref = OA\Components::ref($refSchema); + } elseif ($refAnnotation = $analysis->getAnnotationForSource($annotation->ref, get_class($annotation))) { + $annotation->ref = OA\Components::ref($refAnnotation); } } } diff --git a/src/Processors/AugmentRequestBody.php b/src/Processors/AugmentRequestBody.php new file mode 100644 index 00000000..77733a75 --- /dev/null +++ b/src/Processors/AugmentRequestBody.php @@ -0,0 +1,48 @@ + $requests */ + $requests = $analysis->getAnnotationsOfType(OA\RequestBody::class); + + $this->augmentRequestBody($requests); + } + + /** + * @param array $requests + */ + protected function augmentRequestBody(array $requests): void + { + foreach ($requests as $request) { + if (!$request->isRoot(OA\RequestBody::class)) { + continue; + } + if (Generator::isDefault($request->request)) { + if ($request->_context->is('class')) { + $request->request = $request->_context->class; + } elseif ($request->_context->is('interface')) { + $request->request = $request->_context->interface; + } elseif ($request->_context->is('trait')) { + $request->request = $request->_context->trait; + } elseif ($request->_context->is('enum')) { + $request->request = $request->_context->enum; + } + } + } + } +} diff --git a/tests/Fixtures/Request.php b/tests/Fixtures/Request.php new file mode 100644 index 00000000..a24a72e8 --- /dev/null +++ b/tests/Fixtures/Request.php @@ -0,0 +1,29 @@ +analysisFromFixtures(['Request.php']); + $analysis->process([ + // create openapi->components + new MergeIntoOpenApi(), + // Merge standalone Scheme's into openapi->components + new MergeIntoComponents(), + new BuildPaths(), + new AugmentRequestBody(), + ]); + + $this->assertSame($analysis->openapi->paths[0]->post->requestBody->ref, 'OpenApi\Tests\Fixtures\Request'); + + $analysis->process([ + new AugmentRefs(), + ]); + + $this->assertSame($analysis->openapi->paths[0]->post->requestBody->ref, '#/components/requestBodies/Request'); + } +} diff --git a/tests/Processors/AugmentRequestBodyTest.php b/tests/Processors/AugmentRequestBodyTest.php new file mode 100644 index 00000000..a659c9bd --- /dev/null +++ b/tests/Processors/AugmentRequestBodyTest.php @@ -0,0 +1,34 @@ +analysisFromFixtures(['Request.php']); + $analysis->process([ + // create openapi->components + new MergeIntoOpenApi(), + // Merge standalone Scheme's into openapi->components + new MergeIntoComponents(), + ]); + + $this->assertCount(1, $analysis->openapi->components->requestBodies); + $request = $analysis->openapi->components->requestBodies[0]; + $this->assertSame(Generator::UNDEFINED, $request->request, 'Sanity check. No request was defined'); + $analysis->process([new AugmentRequestBody()]); + + $this->assertSame('Request', $request->request, '@OA\RequestBody()->request based on classname'); + } +}