Skip to content

Commit efd7611

Browse files
authored
Support use x-* in ref (#1776)
1 parent 471f2e7 commit efd7611

2 files changed

Lines changed: 39 additions & 6 deletions

File tree

src/Annotations/OpenApi.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,21 @@ private static function resolveRef(string $ref, string $resolved, $container, ar
219219
$unresolved = $slash === false ? $resolved . $subpath : $resolved . $subpath . '/';
220220

221221
if (is_object($container)) {
222-
if (property_exists($container, $property) === false) {
222+
// support use x-* in ref
223+
$xKey = strpos($property, 'x-') === 0 ? substr($property, 2) : null;
224+
if ($xKey) {
225+
if (!is_array($container->x) || !array_key_exists($xKey, $container->x)) {
226+
$xKey = null;
227+
}
228+
}
229+
if (property_exists($container, $property) === false && !$xKey) {
223230
throw new OpenApiException('$ref "' . $ref . '" not found');
224231
}
232+
233+
$nextContainer = $xKey ? $container->x[$xKey] : $container->{$property};
234+
225235
if ($slash === false) {
226-
return $container->{$property};
236+
return $nextContainer;
227237
}
228238
$mapping = [];
229239
foreach ($container::$_nested as $nestedClass => $nested) {
@@ -232,7 +242,7 @@ private static function resolveRef(string $ref, string $resolved, $container, ar
232242
}
233243
}
234244

235-
return self::resolveRef($ref, $unresolved, $container->{$property}, $mapping);
245+
return self::resolveRef($ref, $unresolved, $nextContainer, $mapping);
236246
} elseif (is_array($container)) {
237247
if (array_key_exists($property, $container)) {
238248
return self::resolveRef($ref, $unresolved, $container[$property], []);

tests/RefTest.php

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,23 @@ public function testRef(): void
1919
$this->assertInstanceOf(OA\Info::class, $info);
2020

2121
$comment = <<<END
22-
@OA\Get(
22+
@OA\Post(
2323
path="/api/~/endpoint",
24-
@OA\Response(response="default", description="A response")
24+
@OA\Response(
25+
response="default",
26+
description="A response",
27+
@OA\JsonContent(ref="#/components/schemas/String/x-custom-key")
28+
)
29+
)
30+
31+
@OA\Schema(
32+
schema="String",
33+
@OA\Property(property="value", type="string"),
34+
x={
35+
"custom-key": @OA\Schema(
36+
@OA\Property(property="value", type="string"),
37+
)
38+
}
2539
)
2640
END;
2741
$openapi->merge($this->annotationsFromDocBlockParser($comment));
@@ -32,8 +46,17 @@ public function testRef(): void
3246
$analysis->validate();
3347
// escape / as ~1
3448
// escape ~ as ~0
35-
$response = $openapi->ref('#/paths/~1api~1~0~1endpoint/get/responses/default');
49+
$response = $openapi->ref('#/paths/~1api~1~0~1endpoint/post/responses/default');
3650
$this->assertInstanceOf(OA\Response::class, $response);
3751
$this->assertSame('A response', $response->description);
52+
53+
// ref x value
54+
$schema = $openapi->ref('#/components/schemas/String/x-custom-key');
55+
$this->assertInstanceOf(OA\Schema::class, $schema);
56+
57+
// ref x with deep
58+
$property = $openapi->ref('#/components/schemas/String/x-custom-key/properties/value');
59+
$this->assertInstanceOf(OA\Property::class, $property);
60+
$this->assertSame('string', $property->type);
3861
}
3962
}

0 commit comments

Comments
 (0)