Skip to content

Commit 2e99b84

Browse files
committed
add openapiAnnotation
1 parent 613aa9d commit 2e99b84

File tree

7 files changed

+115
-24
lines changed

7 files changed

+115
-24
lines changed

src/OpenApi/Annotations/OpenApi.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66

77
use Attribute;
88

9-
#[Attribute(Attribute::TARGET_METHOD)]
9+
#[Attribute(Attribute::TARGET_PROPERTY)]
1010
class OpenApi
1111
{
12+
1213
public function __construct(
13-
public string $descriptions,
14+
public string $description = '',
15+
public string $example = '',
1416
) {
1517
}
1618
}

src/OpenApi/Collections/OpenApiCollection.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Astral\Serialize\OpenApi\Collections;
44

55
use Astral\Serialize\OpenApi\Annotations\Headers;
6+
use Astral\Serialize\OpenApi\Annotations\OpenApi;
67
use Astral\Serialize\OpenApi\Annotations\RequestBody;
78
use Astral\Serialize\OpenApi\Annotations\Response;
89
use Astral\Serialize\OpenApi\Annotations\Route;
@@ -126,7 +127,7 @@ className: $className,
126127
name: current($property->getInputNamesByGroups($groups,$className)),
127128
types: $property->getTypes(),
128129
type: ParameterTypeEnum::getByTypes($property->getTypes()),
129-
descriptions: '',
130+
openApiAnnotation: $this->getOpenApiAnnotation($property->getAttributes()),
130131
required: !$property->isNullable(),
131132
ignore: false,
132133
);
@@ -143,4 +144,15 @@ className: $className,
143144

144145
return $vols;
145146
}
147+
148+
public function getOpenApiAnnotation(array $attributes): OpenApi|null
149+
{
150+
foreach ($attributes as $attribute){
151+
if($attribute->getName() === OpenApi::class){
152+
return $attribute->newInstance();
153+
}
154+
}
155+
156+
return null;
157+
}
146158
}

src/OpenApi/Collections/ParameterCollection.php

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,25 @@
44

55
namespace Astral\Serialize\OpenApi\Collections;
66

7-
use Astral\Serialize\Enums\TypeKindEnum;
7+
use Astral\Serialize\OpenApi\Annotations\OpenApi;
88
use Astral\Serialize\OpenApi\Enum\ParameterTypeEnum;
99
use Astral\Serialize\Support\Collections\TypeCollection;
1010
use Attribute;
11+
use ReflectionAttribute;
1112

1213
class ParameterCollection
1314
{
1415
public function __construct(
15-
public string $className,
16-
public string $name,
16+
public string $className,
17+
public string $name,
1718
/** @var TypeCollection[] $types */
18-
public array $types,
19-
public ParameterTypeEnum $type,
20-
public string $descriptions = '',
21-
public mixed $example = '',
22-
public bool $required = false,
23-
public bool $ignore = false,
19+
public array $types,
20+
public ParameterTypeEnum $type,
21+
public OpenApi|null $openApiAnnotation = null,
22+
public bool $required = false,
23+
public bool $ignore = false,
2424
/** @var array<ParameterCollection[]> $children */
25-
public array $children = [],
25+
public array $children = [],
2626
){
2727
}
2828
}

src/OpenApi/Storage/OpenAPI/SchemaStorage.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Astral\Serialize\OpenApi\Storage\OpenAPI;
66

77
use Astral\Serialize\Enums\TypeKindEnum;
8+
use Astral\Serialize\OpenApi\Annotations\OpenApi;
89
use Astral\Serialize\OpenApi\Collections\ParameterCollection;
910
use Astral\Serialize\OpenApi\Enum\ParameterTypeEnum;
1011
use Astral\Serialize\OpenApi\Storage\StorageInterface;
@@ -79,7 +80,7 @@ private function buildBasicPropertySchema(ParameterCollection $parameter, array
7980
$currentNode['properties'][$propertyName] = [
8081
'type' => $parameter->type->value,
8182
'description' => $this->getDescriptions($parameter),
82-
'example' => $parameter->example,
83+
'example' => $parameter->openApiAnnotation?->example,
8384
];
8485

8586
// 添加必填字段标记
@@ -162,12 +163,11 @@ private function buildNestedProperties(ParameterCollection $topParameter, array
162163

163164
public function getDescriptions(ParameterCollection $parameter):string
164165
{
166+
$description = $parameter->openApiAnnotation?->description ?? '';
165167
if(!ParameterTypeEnum::hasEnum($parameter->types)){
166-
return $parameter->descriptions;
168+
return $description;
167169
}
168170

169-
$descriptions = $parameter->descriptions;
170-
171171
$names = [];
172172
foreach ($parameter->types as $type) {
173173
if (TypeKindEnum::ENUM === $type->kind && enum_exists($type->className)) {
@@ -177,8 +177,8 @@ public function getDescriptions(ParameterCollection $parameter):string
177177
}
178178
}
179179

180-
$descriptions .= 'Optional values:' . implode('', $names);
180+
$description .= ($description ? ' ' : '').'optional values:' . implode('', $names);
181181

182-
return $descriptions;
182+
return $description;
183183
}
184184
}

src/Support/Collections/DataCollection.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Astral\Serialize\Support\Collections;
44

55
use InvalidArgumentException;
6+
use ReflectionAttribute;
67
use ReflectionProperty;
78

89
class DataCollection
@@ -13,6 +14,7 @@ public function __construct(
1314
private readonly string $name,
1415
private readonly bool $isNullable,
1516
private readonly bool $isReadonly,
17+
/** @var ReflectionAttribute[] */
1618
private readonly array $attributes,
1719
private readonly mixed $defaultValue,
1820
private readonly ReflectionProperty $property,
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
use Astral\Serialize\OpenApi;
4+
use Astral\Serialize\Serialize;
5+
6+
beforeAll(static function () {
7+
8+
enum AnnotationOpenApiEnum
9+
{
10+
case ENUM_1;
11+
case ENUM_2;
12+
}
13+
14+
15+
class AnnotationOpenApiRequest extends Serialize
16+
{
17+
#[OpenApi\Annotations\OpenApi('description test enum')]
18+
public AnnotationOpenApiEnum $test_enum;
19+
20+
#[OpenApi\Annotations\OpenApi(description:'this is object description', example:'1')]
21+
public object $test_object;
22+
23+
#[OpenApi\Annotations\OpenApi(example:'abc')]
24+
public string $test_example;
25+
26+
}
27+
28+
#[\Astral\Serialize\OpenApi\Annotations\Tag('接口测试')]
29+
class AnnotationOpenApiController{
30+
31+
#[\Astral\Serialize\OpenApi\Annotations\Summary('测试方法一')]
32+
#[\Astral\Serialize\OpenApi\Annotations\Route('/test/description-action')]
33+
public function one(AnnotationOpenApiRequest $request): void
34+
{
35+
}
36+
}
37+
38+
});
39+
40+
test('OpenAPI build description', function () {
41+
$api = new OpenApi();
42+
$api->buildByClass(AnnotationOpenApiController::class);
43+
44+
$openApi = $api::$OpenAPI;
45+
$paths = $openApi->paths;
46+
$post = $paths['/test/description-action']['post'];
47+
$requestBody = $post->requestBody;
48+
$schema = $requestBody['content']['application/json']['schema'];
49+
50+
expect(array_keys($schema['properties']))->toMatchArray([
51+
'test_enum',
52+
'test_object',
53+
'test_example',
54+
]);
55+
56+
$enumProp = $schema['properties']['test_enum'];
57+
expect($enumProp['type'])->toBe('string')
58+
->and($enumProp['description'])->toBe('description test enum optional values:ENUM_1、ENUM_2')
59+
->and($enumProp['example'])->toBe('');
60+
61+
$objProp = $schema['properties']['test_object'];
62+
expect($objProp['type'])->toBe('object')
63+
->and($objProp['description'])->toBe('this is object description')
64+
->and($objProp['example'])->toBe('1');
65+
66+
$exProp = $schema['properties']['test_example'];
67+
expect($exProp['type'])->toBe('string')
68+
->and($exProp['description'])->toBe('')
69+
->and($exProp['example'])->toBe('abc')
70+
->and($schema['required'])->toMatchArray([
71+
'test_enum',
72+
'test_object',
73+
'test_example',
74+
]);
75+
});

tests/Openapi/EnumOpenApiTest.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ enum OpenapiUnionEnum
2525
class OpenapiEnumRequest extends Serialize
2626
{
2727
public OpenapiEnum $test_enum;
28+
2829
public OpenapiEnum|OpenapiUnionEnum $test_string_enum;
2930

3031
public OpenapiEnum|OpenapiUnionEnum|string $test_string_2_enum;
@@ -41,7 +42,6 @@ class OpenapiEnumController{
4142
public function one(OpenapiEnumRequest $request): void
4243
{
4344
}
44-
4545
}
4646

4747
});
@@ -68,22 +68,22 @@ public function one(OpenapiEnumRequest $request): void
6868
])
6969
->and($schema['properties']['test_enum'])->toMatchArray([
7070
'type' => 'string',
71-
'description' => 'Optional values:ENUM_1、ENUM_2',
71+
'description' => 'optional values:ENUM_1、ENUM_2',
7272
'example' => '',
7373
])
7474
->and($schema['properties']['test_string_enum'])->toMatchArray([
7575
'type' => 'string',
76-
'description' => 'Optional values:ENUM_1、ENUM_2、ENUM_3、ENUM_4',
76+
'description' => 'optional values:ENUM_1、ENUM_2、ENUM_3、ENUM_4',
7777
'example' => '',
7878
])
7979
->and($schema['properties']['test_string_2_enum'])->toMatchArray([
8080
'type' => 'string',
81-
'description' => 'Optional values:ENUM_1、ENUM_2、ENUM_3、ENUM_4',
81+
'description' => 'optional values:ENUM_1、ENUM_2、ENUM_3、ENUM_4',
8282
'example' => '',
8383
])
8484
->and($schema['properties']['test_one_of_enum'])->toMatchArray([
8585
'type' => 'oneOf',
86-
'description' => 'Optional values:ENUM_1、ENUM_2、ENUM_3、ENUM_4',
86+
'description' => 'optional values:ENUM_1、ENUM_2、ENUM_3、ENUM_4',
8787
'example' => '',
8888
])
8989
->and($schema['properties']['test_one_of_enum']['oneOf'])->toBeArray()->toHaveCount(2)

0 commit comments

Comments
 (0)