diff --git a/Examples/webhook-example/OpenApiSpec.php b/Examples/webhook-example/OpenApiSpec.php index 85472253..5ce29887 100644 --- a/Examples/webhook-example/OpenApiSpec.php +++ b/Examples/webhook-example/OpenApiSpec.php @@ -11,23 +11,21 @@ * title="Webhook Example", * ), * webhooks={ - * { - * "newPet": @OA\PathItem( - * @OA\Post( - * @OA\RequestBody( - * description="Information about a new pet in the system", - * @OA\MediaType( - * mediaType="application/xml", - * @OA\Schema(ref="#/components/schemas/Pet") - * ), + * "newPet": @OA\PathItem( + * @OA\Post( + * @OA\RequestBody( + * description="Information about a new pet in the system", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/Pet") * ), - * @OA\Response( - * response=200, - * description="Return a 200 status to indicate that the data was received successfully" - * ) + * ), + * @OA\Response( + * response=200, + * description="Return a 200 status to indicate that the data was received successfully" * ) * ) - * } + * ) * } * ) */ diff --git a/Examples/webhook-example/webhook-example.yaml b/Examples/webhook-example/webhook-example.yaml index d0f30193..e7bf6718 100644 --- a/Examples/webhook-example/webhook-example.yaml +++ b/Examples/webhook-example/webhook-example.yaml @@ -16,6 +16,7 @@ components: type: string tag: type: string + type: object webhooks: newPet: post: diff --git a/src/Annotations/OpenApi.php b/src/Annotations/OpenApi.php index 32c4addd..32cfdf48 100644 --- a/src/Annotations/OpenApi.php +++ b/src/Annotations/OpenApi.php @@ -150,6 +150,18 @@ public function validate(array $stack = null, array $skip = null, string $ref = return false; } + if ($this->openapi === self::VERSION_3_0_0 && Generator::isDefault($this->paths)) { + $this->_context->logger->warning('The OpenAPI document must contain paths field'); + + return false; + } + + if ($this->openapi === self::VERSION_3_1_0 && Generator::isDefault($this->paths) && Generator::isDefault($this->webhooks) && Generator::isDefault($this->components)) { + $this->_context->logger->warning('The OpenAPI document must contain at least one paths field, a components field or a webhooks field'); + + return false; + } + return parent::validate([], [], '#', new \stdClass()); } @@ -237,4 +249,19 @@ private static function resolveRef(string $ref, string $resolved, $container, ar throw new \Exception('$ref "' . $unresolved . '" not found'); } + + /** + * @inheritdoc + */ + #[\ReturnTypeWillChange] + public function jsonSerialize() + { + $data = parent::jsonSerialize(); + + if (false === $this->_context->isVersion(OpenApi::VERSION_3_1_0)) { + unset($data->webhooks); + } + + return $data; + } } diff --git a/src/Attributes/OpenApi.php b/src/Attributes/OpenApi.php index 874578a1..9ffce16e 100644 --- a/src/Attributes/OpenApi.php +++ b/src/Attributes/OpenApi.php @@ -16,9 +16,9 @@ class OpenApi extends \OpenApi\Annotations\OpenApi * @param Server[]|null $servers * @param Tag[]|null $tags * @param PathItem[]|null $paths + * @param array|null $webhooks * @param array|null $x * @param Attachable[]|null $attachables - * @param array|null $webhooks */ public function __construct( string $openapi = self::DEFAULT_VERSION, diff --git a/tests/Annotations/OpenApiTest.php b/tests/Annotations/OpenApiTest.php index cf786264..33e48a17 100644 --- a/tests/Annotations/OpenApiTest.php +++ b/tests/Annotations/OpenApiTest.php @@ -11,10 +11,18 @@ class OpenApiTest extends OpenApiTestCase { - public function testValidVersion(): void + public function testValidVersion310(): void { - $this->assertOpenApiLogEntryContains('Required @OA\Info() not found'); - $this->assertOpenApiLogEntryContains('Required @OA\PathItem() not found'); + $this->assertOpenApiLogEntryContains('The OpenAPI document must contain at least one paths field, a components field or a webhooks field'); + + $openapi = new OA\OpenApi(['_context' => $this->getContext()]); + $openapi->openapi = '3.1.0'; + $openapi->validate(); + } + + public function testValidVersion300(): void + { + $this->assertOpenApiLogEntryContains('The OpenAPI document must contain paths field'); $openapi = new OA\OpenApi(['_context' => $this->getContext()]); $openapi->openapi = '3.0.0'; diff --git a/tests/ContextTest.php b/tests/ContextTest.php index 4604b867..d6e3cea8 100644 --- a/tests/ContextTest.php +++ b/tests/ContextTest.php @@ -26,7 +26,7 @@ public function testDetect(): void public function testFullyQualifiedName(): void { - $this->assertOpenApiLogEntryContains('Required @OA\PathItem() not found'); + $this->assertOpenApiLogEntryContains('The OpenAPI document must contain paths field'); $openapi = (new Generator($this->getTrackingLogger())) ->setAnalyser(new TokenAnalyser()) ->generate([$this->fixture('Customer.php')]); diff --git a/tests/GeneratorTest.php b/tests/GeneratorTest.php index 3dbd1c3f..3853cbad 100644 --- a/tests/GeneratorTest.php +++ b/tests/GeneratorTest.php @@ -38,8 +38,7 @@ public function testScan(string $sourceDir, iterable $sources): void public function testScanInvalidSource(): void { $this->assertOpenApiLogEntryContains('Skipping invalid source: /tmp/__swagger_php_does_not_exist__'); - $this->assertOpenApiLogEntryContains('Required @OA\Info() not found'); - $this->assertOpenApiLogEntryContains('Required @OA\PathItem() not found'); + $this->assertOpenApiLogEntryContains('The OpenAPI document must contain paths field'); (new Generator($this->getTrackingLogger())) ->setAnalyser($this->getAnalyzer())