Skip to content

Commit

Permalink
Allow FQCN in $ref (#1418)
Browse files Browse the repository at this point in the history
  • Loading branch information
DerManoMann authored Feb 25, 2023
1 parent f2bcbd5 commit de32660
Show file tree
Hide file tree
Showing 33 changed files with 139 additions and 45 deletions.
4 changes: 2 additions & 2 deletions Examples/using-links-php81/PullRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ public function __construct(
/**
* @var Repository
*/
#[OAT\Property(ref: '#/components/schemas/repository')]
#[OAT\Property(ref: Repository::class)]
public $repository;

/**
* @var User
*/
#[OAT\Property(ref: '#/components/schemas/user')]
#[OAT\Property(ref: User::class)]
public $author;
}
5 changes: 0 additions & 5 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,6 @@ parameters:
count: 1
path: src/Generator.php

-
message: "#^Instanceof between \\(callable\\)\\|OpenApi\\\\Processors\\\\ProcessorInterface and class\\-string\\|false results in an error\\.$#"
count: 1
path: src/Generator.php

-
message: "#^Variable \\$logLine in empty\\(\\) always exists and is not falsy\\.$#"
count: 1
Expand Down
2 changes: 1 addition & 1 deletion src/Analysers/AttributeAnnotationFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public function build(\Reflector $reflector, Context $context): array
}

$annotations = array_values(array_filter($annotations, function ($a) {
return $a !== null && $a instanceof OA\AbstractAnnotation;
return $a instanceof OA\AbstractAnnotation;
}));

// merge backwards into parents...
Expand Down
2 changes: 1 addition & 1 deletion src/Annotations/Examples.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Examples extends AbstractAnnotation
/**
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|object
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;

Expand Down
2 changes: 1 addition & 1 deletion src/Annotations/Header.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Header extends AbstractAnnotation
/**
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|object
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;

Expand Down
2 changes: 1 addition & 1 deletion src/Annotations/Link.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Link extends AbstractAnnotation
/**
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|object
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;

Expand Down
2 changes: 1 addition & 1 deletion src/Annotations/Parameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Parameter extends AbstractAnnotation
/**
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|object
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;

Expand Down
2 changes: 1 addition & 1 deletion src/Annotations/PathItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class PathItem extends AbstractAnnotation
/**
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|object
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;

Expand Down
2 changes: 1 addition & 1 deletion src/Annotations/RequestBody.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class RequestBody extends AbstractAnnotation
/**
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|object
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;

Expand Down
2 changes: 1 addition & 1 deletion src/Annotations/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class Response extends AbstractAnnotation
/**
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|object
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;

Expand Down
2 changes: 1 addition & 1 deletion src/Annotations/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Schema extends AbstractAnnotation
/**
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|object
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;

Expand Down
2 changes: 1 addition & 1 deletion src/Annotations/SecurityScheme.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SecurityScheme extends AbstractAnnotation
/**
* @see [Using refs](https://swagger.io/docs/specification/using-ref/)
*
* @var string|object
* @var string|class-string|object
*/
public $ref = Generator::UNDEFINED;

Expand Down
1 change: 1 addition & 0 deletions src/Attributes/AdditionalProperties.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
class AdditionalProperties extends \OpenApi\Annotations\AdditionalProperties
{
/**
* @param string|class-string|object|null $ref
* @param string[] $required
* @param Property[] $properties
* @param int|float $maximum
Expand Down
5 changes: 3 additions & 2 deletions src/Attributes/Examples.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
class Examples extends \OpenApi\Annotations\Examples
{
/**
* @param array<string,mixed>|null $x
* @param Attachable[]|null $attachables
* @param string|class-string|object|null $ref
* @param array<string,mixed>|null $x
* @param Attachable[]|null $attachables
*/
public function __construct(
?string $example = null,
Expand Down
5 changes: 3 additions & 2 deletions src/Attributes/Header.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
class Header extends \OpenApi\Annotations\Header
{
/**
* @param array<string,mixed>|null $x
* @param Attachable[]|null $attachables
* @param string|class-string|object|null $ref
* @param array<string,mixed>|null $x
* @param Attachable[]|null $attachables
*/
public function __construct(
string|object|null $ref = null,
Expand Down
1 change: 1 addition & 0 deletions src/Attributes/Items.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
class Items extends \OpenApi\Annotations\Items
{
/**
* @param string|class-string|object|null $ref
* @param string[] $required
* @param Property[] $properties
* @param int|float $maximum
Expand Down
1 change: 1 addition & 0 deletions src/Attributes/JsonContent.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
class JsonContent extends \OpenApi\Annotations\JsonContent
{
/**
* @param string|class-string|object|null $ref
* @param array<string,Examples> $examples
* @param string[] $required
* @param Property[] $properties
Expand Down
7 changes: 4 additions & 3 deletions src/Attributes/Link.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
class Link extends \OpenApi\Annotations\Link
{
/**
* @param array<string,mixed> $parameters
* @param array<string,mixed>|null $x
* @param Attachable[]|null $attachables
* @param string|class-string|object|null $ref
* @param array<string,mixed> $parameters
* @param array<string,mixed>|null $x
* @param Attachable[]|null $attachables
*/
public function __construct(
?string $link = null,
Expand Down
1 change: 1 addition & 0 deletions src/Attributes/ParameterTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
trait ParameterTrait
{
/**
* @param string|class-string|object|null $ref
* @param array<string,Examples> $examples
* @param array<MediaType>|JsonContent|XmlContent|Attachable|null $content
* @param array<string,mixed>|null $x
Expand Down
1 change: 1 addition & 0 deletions src/Attributes/Property.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
class Property extends \OpenApi\Annotations\Property
{
/**
* @param string|class-string|object|null $ref
* @param string[] $required
* @param Property[] $properties
* @param int|float $maximum
Expand Down
1 change: 1 addition & 0 deletions src/Attributes/RequestBody.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
class RequestBody extends OA\RequestBody
{
/**
* @param string|class-string|object|null $ref
* @param array<MediaType>|JsonContent|XmlContent|Attachable|null $content
* @param array<string,mixed>|null $x
* @param Attachable[]|null $attachables
Expand Down
1 change: 1 addition & 0 deletions src/Attributes/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
class Response extends OA\Response
{
/**
* @param string|class-string|object|null $ref
* @param Header[] $headers
* @param MediaType|JsonContent|XmlContent|Attachable|array<MediaType|JsonContent|XmlContent|Attachable> $content
* @param Link[] $links
Expand Down
1 change: 1 addition & 0 deletions src/Attributes/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
class Schema extends \OpenApi\Annotations\Schema
{
/**
* @param string|class-string|object|null $ref
* @param string[] $required
* @param Property[] $properties
* @param int|float $maximum
Expand Down
7 changes: 4 additions & 3 deletions src/Attributes/SecurityScheme.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
class SecurityScheme extends \OpenApi\Annotations\SecurityScheme
{
/**
* @param Flow[] $flows
* @param array<string,mixed>|null $x
* @param Attachable[]|null $attachables
* @param string|class-string|object|null $ref
* @param Flow[] $flows
* @param array<string,mixed>|null $x
* @param Attachable[]|null $attachables
*/
public function __construct(
string|object|null $ref = null,
Expand Down
1 change: 1 addition & 0 deletions src/Attributes/XmlContent.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
class XmlContent extends \OpenApi\Annotations\XmlContent
{
/**
* @param string|class-string|object|null $ref
* @param array<string,Examples> $examples
* @param string[] $required
* @param int|float $maximum
Expand Down
8 changes: 1 addition & 7 deletions src/Processors/AugmentProperties.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
class AugmentProperties implements ProcessorInterface
{
use Concerns\DocblockTrait;
use Concerns\RefTrait;
use Concerns\TypesTrait;

public function __invoke(Analysis $analysis)
Expand Down Expand Up @@ -67,13 +68,6 @@ public function __invoke(Analysis $analysis)
}
}

protected function toRefKey(Context $context, ?string $name): string
{
$fqn = strtolower($context->fullyQualifiedName($name));

return ltrim($fqn, '\\');
}

protected function augmentType(Analysis $analysis, OA\Property $property, Context $context, array $refs, array $varMatches): void
{
// docblock typehints
Expand Down
29 changes: 26 additions & 3 deletions src/Processors/AugmentRefs.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,20 @@
use OpenApi\Annotations as OA;
use OpenApi\Generator;

/**
* Update refs broken due to `allOf` augmenting.
*/
class AugmentRefs implements ProcessorInterface
{
use Concerns\RefTrait;

public function __invoke(Analysis $analysis)
{
$this->resolveAllOfRefs($analysis);
$this->resolveFQCNRefs($analysis);
}

/**
* Update refs broken due to `allOf` augmenting.
*/
protected function resolveAllOfRefs(Analysis $analysis)
{
/** @var OA\Schema[] $schemas */
$schemas = $analysis->getAnnotationsOfType(OA\Schema::class);
Expand Down Expand Up @@ -46,4 +54,19 @@ public function __invoke(Analysis $analysis)
}
}
}

protected function resolveFQCNRefs(Analysis $analysis)
{
/** @var OA\AbstractAnnotation[] $annotations */
$annotations = $analysis->getAnnotationsOfType([OA\Examples::class, OA\Header::class, OA\Link::class, OA\Parameter::class, OA\PathItem::class, OA\RequestBody::class, OA\Response::class, OA\Schema::class, OA\SecurityScheme::class]);

foreach ($annotations as $annotation) {
if (property_exists($annotation, 'ref') && !Generator::isDefault($annotation->ref) && is_string($annotation->ref) && !$this->isRef($annotation->ref)) {
// check if we have a schema for this
if ($refSchema = $analysis->getSchemaForSource($annotation->ref)) {
$annotation->ref = OA\Components::ref($refSchema);
}
}
}
}
}
24 changes: 24 additions & 0 deletions src/Processors/Concerns/RefTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php declare(strict_types=1);

/**
* @license Apache 2.0
*/

namespace OpenApi\Processors\Concerns;

use OpenApi\Context;

trait RefTrait
{
protected function toRefKey(Context $context, ?string $name): string
{
$fqn = strtolower($context->fullyQualifiedName($name));

return ltrim($fqn, '\\');
}

protected function isRef(?string $ref): bool
{
return $ref && 0 === strpos($ref, '#/');
}
}
5 changes: 2 additions & 3 deletions src/Processors/ExpandEnums.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,10 @@ protected function expandSchemaEnum(Analysis $analysis): void
} else {
throw new \InvalidArgumentException("Unexpected enum value, requires specifying the Enum class string: $schema->enum");
}
} elseif (is_array($schema->enum)) {
} else {
// might be an array of \UnitEnum::class, string, int, etc...
assert(is_array($schema->enum));
$cases = $schema->enum;
} else {
throw new \InvalidArgumentException('Unexpected enum value, requires Enum class string or array');
}

$enums = [];
Expand Down
6 changes: 3 additions & 3 deletions tests/Fixtures/Apis/Attributes/basic.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class ProductController
#[OAT\Response(
response: 200,
description: 'successful operation',
content: [new OAT\MediaType(mediaType: 'application/json', schema: new OAT\Schema(ref: '#/components/schemas/Product'))],
content: [new OAT\MediaType(mediaType: 'application/json', schema: new OAT\Schema(ref: Product::class))],
headers: [
new OAT\Header(header: 'X-Rate-Limit', description: 'calls per hour allowed by the user', schema: new OAT\Schema(type: 'integer', format: 'int32')),
]
Expand All @@ -126,7 +126,7 @@ public function getProduct(
#[OAT\Response(
response: 200,
description: 'successful operation',
content: new OAT\JsonContent(ref: '#/components/schemas/Product')
content: new OAT\JsonContent(ref: Product::class)
)]
#[OAT\RequestBody(
required: true,
Expand Down Expand Up @@ -157,7 +157,7 @@ public function addProduct()
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(ref: '#/components/schemas/Product')
items: new OAT\Items(ref: Product::class)
),
]
)
Expand Down
4 changes: 2 additions & 2 deletions tests/Fixtures/Apis/Mixed/basic.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class ProductController
new OAT\Response(
response: 200,
description: 'successful operation',
content: new OAT\JsonContent(ref: '#/components/schemas/Product'),
content: new OAT\JsonContent(ref: Product::class),
headers: [
new OAT\Header(header: 'X-Rate-Limit', description: 'calls per hour allowed by the user', schema: new OAT\Schema(type: 'integer', format: 'int32')),
]
Expand Down Expand Up @@ -187,7 +187,7 @@ public function addProduct()
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(ref: '#/components/schemas/Product')
items: new OAT\Items(ref: Product::class)
),
]
)
Expand Down
Loading

0 comments on commit de32660

Please sign in to comment.