diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 530bc44cf..9a54f0842 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -45,11 +45,6 @@ parameters: count: 1 path: src/Annotations/Schema.php - - - message: "#^Ternary operator condition is always true\\.$#" - count: 1 - path: src/Context.php - - message: "#^If condition is always true\\.$#" count: 1 diff --git a/src/Analysis.php b/src/Analysis.php index a200e402e..85b506ba4 100644 --- a/src/Analysis.php +++ b/src/Analysis.php @@ -72,6 +72,8 @@ public function __construct(array $annotations = [], ?Context $context = null) public function addAnnotation(object $annotation, Context $context): void { + assert(!Generator::isDefault($context->version)); + if ($this->annotations->contains($annotation)) { return; } @@ -369,8 +371,7 @@ public function getContext(object $annotation): ?Context return $context; } - // Weird, did you use the addAnnotation/addAnnotations methods? - throw new \Exception('Annotation has no context'); + throw new \RuntimeException('Annotation has no context - did you use addAnnotation()/addAnnotations()'); } /** diff --git a/src/Annotations/AbstractAnnotation.php b/src/Annotations/AbstractAnnotation.php index cfcff57d6..22425ee10 100644 --- a/src/Annotations/AbstractAnnotation.php +++ b/src/Annotations/AbstractAnnotation.php @@ -165,16 +165,6 @@ public function __set(string $property, $value): void $this->_context->logger->warning('Ignoring unexpected property "' . $property . '" for ' . $this->identity() . ', expecting "' . implode('", "', array_keys($fields)) . '" in ' . $this->_context); } - /** - * Check if one of the given version numbers matches the current OpenAPI version. - * - * @param string|array $versions One or more version numbers - */ - public function isOpenApiVersion($versions): bool - { - return $this->_context->isVersion($versions); - } - /** * Merge given annotations to their mapped properties configured in static::$_nested. * @@ -360,7 +350,7 @@ public function jsonSerialize() if (isset($data->ref)) { // Only specific https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md#reference-object $ref = ['$ref' => $data->ref]; - if ($this->isOpenApiVersion(OpenApi::VERSION_3_1_0)) { + if ($this->_context->isVersion(OpenApi::VERSION_3_1_0)) { foreach (['summary', 'description'] as $prop) { if (property_exists($this, $prop)) { if (!Generator::isDefault($this->{$prop})) { @@ -371,7 +361,7 @@ public function jsonSerialize() } if (property_exists($this, 'nullable') && $this->nullable === true) { $ref = ['oneOf' => [$ref]]; - if ($this->isOpenApiVersion(OpenApi::VERSION_3_1_0)) { + if ($this->_context->isVersion(OpenApi::VERSION_3_1_0)) { $ref['oneOf'][] = ['type' => 'null']; } else { $ref['nullable'] = $data->nullable; @@ -391,7 +381,7 @@ public function jsonSerialize() $data = (object) $ref; } - if ($this->isOpenApiVersion(OpenApi::VERSION_3_0_0)) { + if ($this->_context->isVersion(OpenApi::VERSION_3_0_0)) { if (isset($data->exclusiveMinimum) && is_numeric($data->exclusiveMinimum)) { $data->minimum = $data->exclusiveMinimum; $data->exclusiveMinimum = true; @@ -402,7 +392,7 @@ public function jsonSerialize() } } - if ($this->isOpenApiVersion(OpenApi::VERSION_3_1_0)) { + if ($this->_context->isVersion(OpenApi::VERSION_3_1_0)) { if (isset($data->nullable)) { if (true === $data->nullable) { if (isset($data->oneOf)) { diff --git a/src/Annotations/License.php b/src/Annotations/License.php index 8f4f78b73..ac04bc68d 100644 --- a/src/Annotations/License.php +++ b/src/Annotations/License.php @@ -76,7 +76,7 @@ public function jsonSerialize() { $data = parent::jsonSerialize(); - if ($this->isOpenApiVersion(OpenApi::VERSION_3_0_0)) { + if ($this->_context->isVersion(OpenApi::VERSION_3_0_0)) { unset($data->identifier); } @@ -90,7 +90,7 @@ public function validate(array $stack = [], array $skip = [], string $ref = '', { $valid = parent::validate($stack, $skip, $ref, $context); - if ($this->isOpenApiVersion(OpenApi::VERSION_3_1_0)) { + if ($this->_context->isVersion(OpenApi::VERSION_3_1_0)) { if (!Generator::isDefault($this->url) && $this->identifier !== Generator::UNDEFINED) { $this->_context->logger->warning($this->identity() . ' url and identifier are mutually exclusive'); $valid = false; diff --git a/src/Annotations/OpenApi.php b/src/Annotations/OpenApi.php index 4288464ec..8a5e55a2d 100644 --- a/src/Annotations/OpenApi.php +++ b/src/Annotations/OpenApi.php @@ -262,7 +262,7 @@ public function jsonSerialize() { $data = parent::jsonSerialize(); - if (false === $this->isOpenApiVersion(OpenApi::VERSION_3_1_0)) { + if (!$this->_context->isVersion(OpenApi::VERSION_3_1_0)) { unset($data->webhooks); } diff --git a/src/Annotations/Schema.php b/src/Annotations/Schema.php index 6a8bbcf28..12390159b 100644 --- a/src/Annotations/Schema.php +++ b/src/Annotations/Schema.php @@ -484,7 +484,7 @@ public function jsonSerialize() { $data = parent::jsonSerialize(); - if ($this->isOpenApiVersion(OpenApi::VERSION_3_0_0)) { + if ($this->_context->isVersion(OpenApi::VERSION_3_0_0)) { unset($data->examples); if (isset($data->const)) { $data->enum = [$data->const]; @@ -506,7 +506,7 @@ public function validate(array $stack = [], array $skip = [], string $ref = '', return false; } - if ($this->isOpenApiVersion(OpenApi::VERSION_3_0_0)) { + if ($this->_context->isVersion(OpenApi::VERSION_3_0_0)) { if (!Generator::isDefault($this->examples)) { $this->_context->logger->warning($this->identity() . ' is only allowed for ' . OpenApi::VERSION_3_1_0); diff --git a/src/Context.php b/src/Context.php index a42395f75..aae2f014b 100644 --- a/src/Context.php +++ b/src/Context.php @@ -64,6 +64,10 @@ public function __construct(array $properties = [], ?Context $parent = null) $this->parent = $parent; $this->logger = $this->logger ?: new DefaultLogger(); + + if (!$this->version) { + $this->root()->version = OA\OpenApi::DEFAULT_VERSION; + } } /** @@ -120,10 +124,6 @@ public function root(): Context */ public function isVersion($versions): bool { - if (!$this->version) { - throw new \RuntimeException('Version is only available reliably for validation and serialization'); - } - $versions = (array) $versions; $currentVersion = $this->version ?: OA\OpenApi::DEFAULT_VERSION; @@ -188,13 +188,13 @@ public function __debugInfo() } /** - * Create a Context based on the debug_backtrace. + * Create a Context based on `debug_backtrace`. * * @deprecated */ public static function detect(int $index = 0): Context { - // trigger_deprecation('zircote/swagger-php', '4.0', 'Context detecting is deprecated'); + trigger_deprecation('zircote/swagger-php', '4.9', 'Context detecting is deprecated'); $context = new Context(); $backtrace = debug_backtrace(); diff --git a/src/Generator.php b/src/Generator.php index 9f4f8a485..b399600ee 100644 --- a/src/Generator.php +++ b/src/Generator.php @@ -456,7 +456,9 @@ public function generate(iterable $sources, ?Analysis $analysis = null, bool $va $analysis->process($this->getProcessors()); if ($analysis->openapi) { - $analysis->openapi->openapi = $this->version ?: $analysis->openapi->openapi; + // overwrite default/annotated version + $analysis->openapi->openapi = $this->getVersion() ?: $analysis->openapi->openapi; + // update context to provide the same to validation/serialisation code $rootContext->version = $analysis->openapi->openapi; } diff --git a/src/Processors/AugmentProperties.php b/src/Processors/AugmentProperties.php index 76413b0f7..139168e28 100644 --- a/src/Processors/AugmentProperties.php +++ b/src/Processors/AugmentProperties.php @@ -144,7 +144,7 @@ protected function augmentType(Analysis $analysis, OA\Property $property, Contex $property->minimum = 0; } elseif ($type === 'non-zero-int') { $property->type = 'integer'; - if ($property->isOpenApiVersion(OA\OpenApi::VERSION_3_1_0)) { + if ($property->_context->isVersion(OA\OpenApi::VERSION_3_1_0)) { $property->not = ['const' => 0]; } else { $property->not = ['enum' => [0]]; diff --git a/tests/Analysers/ReflectionAnalyserTest.php b/tests/Analysers/ReflectionAnalyserTest.php index 9167a5977..bb5b3b2bd 100644 --- a/tests/Analysers/ReflectionAnalyserTest.php +++ b/tests/Analysers/ReflectionAnalyserTest.php @@ -119,6 +119,7 @@ public function testApiAttributesBasic(AnalyserInterface $analyser): void /** @var Analysis $analysis */ $analysis = (new Generator()) + ->setVersion(OA\OpenApi::VERSION_3_1_0) ->addAlias('oaf', 'OpenApi\\Tests\\Annotations') ->addNamespace('OpenApi\\Tests\\Annotations\\') ->withContext(function (Generator $generator) use ($analyser) { @@ -161,6 +162,7 @@ public function testApiMixedBasic(AnalyserInterface $analyser): void require_once $this->fixture('Apis/Mixed/basic.php'); $analysis = (new Generator()) + ->setVersion(OA\OpenApi::VERSION_3_1_0) ->withContext(function (Generator $generator) use ($analyser) { $analyser->setGenerator($generator); $analysis = $analyser->fromFile($this->fixture('Apis/Mixed/basic.php'), $this->getContext([], $generator->getVersion())); diff --git a/tests/OpenApiTestCase.php b/tests/OpenApiTestCase.php index 0ee3f4bff..cfcc0d505 100644 --- a/tests/OpenApiTestCase.php +++ b/tests/OpenApiTestCase.php @@ -16,7 +16,6 @@ use OpenApi\Context; use OpenApi\Analysers\TokenAnalyser; use OpenApi\Generator; -use OpenApi\Processors\MergeIntoOpenApi; use PHPUnit\Framework\TestCase; use Psr\Log\AbstractLogger; use Psr\Log\LoggerInterface; @@ -243,8 +242,7 @@ public function analysisFromFixtures(array $files, array $processors = [], ?Anal (new Generator($this->getTrackingLogger())) ->setAnalyser($analyzer ?: $this->getAnalyzer()) - // run at least MergeIntoOpenApi to have a valid OpenApi version set - ->setProcessors($processors ?: [new MergeIntoOpenApi()]) + ->setProcessors($processors) ->generate($this->fixtures($files), $analysis, false); return $analysis;