Skip to content

Commit 928df42

Browse files
committed
add group and ignore tests
1 parent ed67905 commit 928df42

File tree

6 files changed

+255
-37
lines changed

6 files changed

+255
-37
lines changed

src/OpenApi.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public function buildByClass(string $className): void
7777
attributes: $methodAttributes,
7878
requestBody: $instances[RequestBody::class],
7979
response: $instances[Response::class],
80+
groupResolver: SerializeContainer::get()->groupResolver(),
8081
);
8182

8283
self::$openAPI->addPath($openApiCollection);

src/OpenApi/Annotations/Response.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ class Response
1111
{
1212
public function __construct(
1313
/** @var class-string $className */
14-
public string $className,
15-
public ?int $code = 200,
14+
public string $className = '',
1615
public ?array $groups = null,
16+
public ?int $code = 200,
1717
) {
1818
}
1919
}

src/OpenApi/Collections/OpenApiCollection.php

Lines changed: 106 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Astral\Serialize\OpenApi\Collections;
44

5+
use Astral\Serialize\Exceptions\NotFoundGroupException;
56
use Astral\Serialize\OpenApi\Annotations\Headers;
67
use Astral\Serialize\OpenApi\Annotations\OpenApi;
78
use Astral\Serialize\OpenApi\Annotations\RequestBody;
@@ -15,7 +16,9 @@
1516
use Astral\Serialize\OpenApi\Storage\OpenAPI\RequestBodyStorage;
1617
use Astral\Serialize\OpenApi\Storage\OpenAPI\ResponseStorage;
1718
use Astral\Serialize\OpenApi\Storage\OpenAPI\SchemaStorage;
19+
use Astral\Serialize\Resolvers\GroupResolver;
1820
use Astral\Serialize\Serialize;
21+
use Astral\Serialize\SerializeContainer;
1922
use Astral\Serialize\Support\Factories\ContextFactory;
2023
use Psr\SimpleCache\InvalidArgumentException;
2124
use ReflectionMethod;
@@ -34,6 +37,7 @@ public function __construct(
3437
public array $attributes,
3538
public RequestBody|null $requestBody,
3639
public Response|null $response,
40+
public GroupResolver $groupResolver,
3741
) {
3842
}
3943

@@ -50,81 +54,149 @@ public function build(): Method
5054
description:$this->summary->description ?: ''
5155
);
5256

53-
$openAPIMethod->withRequestBody($this->requestBody !== null ? $this->buildRequestBodyByAttribute() : $this->buildRequestBodyByParameters());
54-
$openAPIMethod->addResponse(200, $this->buildResponse());
57+
$requestBody = $this->buildRequestBody(
58+
className:$this->getRequestBodyClass(),
59+
contentType:$this->requestBody->contentType ?? ContentTypeEnum::JSON,
60+
groups: $this->requestBody->groups ?? []
61+
);
62+
63+
$response = $this->buildResponse(
64+
className:$this->getResponseClass(),
65+
groups:$this->response->groups ?? []
66+
);
67+
68+
$openAPIMethod->withRequestBody($requestBody);
69+
$openAPIMethod->addResponse(200, $response);
5570
return $openAPIMethod;
5671
}
5772

58-
/**
59-
* @throws InvalidArgumentException
60-
*/
61-
public function buildRequestBodyByAttribute(): RequestBodyStorage
62-
{
63-
$openAPIRequestBody = new RequestBodyStorage($this->requestBody->contentType);
64-
$schemaStorage = (new SchemaStorage())->build($this->buildParameterCollections($this->requestBody->className, $this->requestBody->groups));
65-
$openAPIRequestBody->withParameter($schemaStorage);
66-
return $openAPIRequestBody;
67-
}
6873

69-
/**
70-
* @throws InvalidArgumentException
71-
*/
72-
public function buildRequestBodyByParameters(): RequestBodyStorage
74+
public function getRequestBodyClass(): string
7375
{
74-
$openAPIRequestBody = new RequestBodyStorage(ContentTypeEnum::JSON);
76+
if($this->requestBody?->className){
77+
return $this->requestBody->className;
78+
}
79+
7580
$methodParam = $this->reflectionMethod->getParameters()[0] ?? null;
7681
$type = $methodParam?->getType();
7782
$requestBodyClass = $type instanceof ReflectionNamedType ? $type->getName() : '';
7883
if (is_subclass_of($requestBodyClass, Serialize::class)) {
79-
$schemaStorage = (new SchemaStorage())->build($this->buildParameterCollections($requestBodyClass));
84+
return $requestBodyClass;
85+
}
86+
87+
return '';
88+
}
89+
90+
91+
public function buildRequestBody(string $className,ContentTypeEnum $contentType,array $groups = []): RequestBodyStorage
92+
{
93+
$openAPIRequestBody = new RequestBodyStorage($contentType);
94+
if (is_subclass_of($className, Serialize::class)) {
95+
$schemaStorage = (new SchemaStorage())->build($this->buildRequestParameterCollections($className,$groups));
8096
$openAPIRequestBody->withParameter($schemaStorage);
8197
}
8298

8399
return $openAPIRequestBody;
84100
}
85101

86-
/**
87-
* @throws InvalidArgumentException
88-
*/
89-
public function buildResponse(): ResponseStorage
102+
public function getResponseClass(): string
90103
{
104+
if($this->response?->className){
105+
return $this->response->className;
106+
}
107+
91108
$returnClass = $this->reflectionMethod->getReturnType();
92109
$returnClass = $returnClass instanceof ReflectionNamedType ? $returnClass->getName() : null;
93-
$responseClass = match(true) {
94-
$this->response !== null => $this->response->className,
95-
$returnClass && is_subclass_of($returnClass, Serialize::class) => $returnClass,
96-
default => null,
97-
};
110+
if (is_subclass_of($returnClass, Serialize::class)) {
111+
return $returnClass;
112+
}
98113

99-
$responseStorage = new ResponseStorage();
114+
return '';
115+
}
100116

117+
/**
118+
* @throws InvalidArgumentException
119+
*/
120+
public function buildResponse(string $className,array $groups = []): ResponseStorage
121+
{
122+
$responseStorage = new ResponseStorage();
101123

102-
if ($responseClass) {
103-
$groups = $this->response && is_array($this->response->groups) ? $this->response->groups : ['default'];
104-
$schemaStorage = (new SchemaStorage())->build($this->buildParameterCollections($responseClass, $groups));
124+
if ($className) {
125+
$schemaStorage = (new SchemaStorage())->build($this->buildResponseParameterCollections($className,$groups));
105126
$responseStorage->withParameter($schemaStorage);
106127
}
107128

108129
return $responseStorage;
109130
}
110131

132+
/**
133+
* @param string $className
134+
* @param array $groups
135+
* @return array<ParameterCollection>
136+
* @throws InvalidArgumentException|NotFoundGroupException
137+
*/
138+
public function buildRequestParameterCollections(string $className, array $groups = []): array
139+
{
140+
141+
$serializeContext = ContextFactory::build($className);
142+
$serializeContext->setGroups($groups)->from();
143+
$properties = $serializeContext->getGroupCollection()->getProperties();
144+
$groups = $groups ?: [$className];
145+
146+
$vols = [];
147+
foreach ($properties as $property) {
148+
149+
150+
if($property->isInputIgnoreByGroups($groups) || !$this->groupResolver->resolveExistsGroupsByDataCollection($property, $groups, $className)){
151+
continue;
152+
}
153+
154+
$vol = new ParameterCollection(
155+
className: $className,
156+
name: current($property->getInputNamesByGroups($groups, $className)),
157+
types: $property->getTypes(),
158+
type: ParameterTypeEnum::getByTypes($property->getTypes()),
159+
openApiAnnotation: $this->getOpenApiAnnotation($property->getAttributes()),
160+
required: !$property->isNullable(),
161+
ignore: false,
162+
);
163+
164+
if ($property->getChildren()) {
165+
foreach ($property->getChildren() as $children) {
166+
$className = $children->getClassName();
167+
$vol->children[$className] = $this->buildRequestParameterCollections($className);
168+
}
169+
}
170+
171+
$vols[] = $vol;
172+
}
173+
174+
return $vols;
175+
}
176+
111177
/**
112178
* @param string $className
113179
* @param array $groups
114180
* @return array<ParameterCollection>
115181
* @throws InvalidArgumentException
116182
*/
117-
public function buildParameterCollections(string $className, array $groups = ['default']): array
183+
public function buildResponseParameterCollections(string $className, array $groups = []): array
118184
{
119185
$serializeContext = ContextFactory::build($className);
120186
$serializeContext->from();
121187
$properties = $serializeContext->getGroupCollection()->getProperties();
188+
$groups = $groups ?: [$className];
122189

123190
$vols = [];
124191
foreach ($properties as $property) {
192+
193+
if($property->isOutIgnoreByGroups($groups) || !$this->groupResolver->resolveExistsGroupsByDataCollection($property, $groups, $className)){
194+
continue;
195+
}
196+
125197
$vol = new ParameterCollection(
126198
className: $className,
127-
name: current($property->getInputNamesByGroups($groups, $className)),
199+
name: current($property->getOutNamesByGroups($groups, $className)),
128200
types: $property->getTypes(),
129201
type: ParameterTypeEnum::getByTypes($property->getTypes()),
130202
openApiAnnotation: $this->getOpenApiAnnotation($property->getAttributes()),
@@ -135,7 +207,7 @@ className: $className,
135207
if ($property->getChildren()) {
136208
foreach ($property->getChildren() as $children) {
137209
$className = $children->getClassName();
138-
$vol->children[$className] = $this->buildParameterCollections($className);
210+
$vol->children[$className] = $this->buildResponseParameterCollections($className);
139211
}
140212
}
141213

src/Support/Collections/DataCollection.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public function getInputNamesByGroups(array $groups, string $defaultGroup): arra
114114
$vols = isset($this->inputNames[$group]) ? array_merge($vols, $this->inputNames[$group]) : $vols;
115115
}
116116

117-
return array_unique($vols);
117+
return $vols ? array_unique($vols) : [$this->name];
118118
}
119119

120120
public function getInputIgnoreGroups(): array
@@ -140,6 +140,7 @@ public function getOutIgnoreGroups(): array
140140

141141
public function getOutNamesByGroups(array $groups, string $defaultGroup): array
142142
{
143+
143144
if (count($groups) === 1 && current($groups) === $defaultGroup) {
144145
return $this->outNames[$defaultGroup] ?? $this->outNames['default'] ?? [$this->name];
145146
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
3+
use Astral\Serialize\OpenApi;
4+
use Astral\Serialize\Serialize;
5+
6+
beforeAll(static function () {
7+
8+
9+
class TestBaseGroupRequest extends Serialize
10+
{
11+
12+
public int $input_group_0;
13+
14+
#[\Astral\Serialize\Annotations\Groups('group_1')]
15+
public int $input_group_1_11;
16+
17+
#[\Astral\Serialize\Annotations\Groups('group_1')]
18+
public string $input_group_1_22;
19+
20+
#[\Astral\Serialize\Annotations\Groups('group_1','group_2')]
21+
#[\Astral\Serialize\Annotations\DataCollection\InputName('input_change_group_1_33_2_11',['group_2'])]
22+
public string $input_group_1_33_2_11;
23+
24+
#[\Astral\Serialize\Annotations\Groups('group_2')]
25+
public string $input_group_2_22;
26+
27+
#[\Astral\Serialize\Annotations\Groups('group_2')]
28+
public string $input_group_2_33;
29+
30+
}
31+
32+
class TestBaseGroupResponse extends Serialize
33+
{
34+
public int $out_group_0;
35+
36+
#[\Astral\Serialize\Annotations\Groups('group_1')]
37+
public int $out_group_1_11;
38+
39+
#[\Astral\Serialize\Annotations\Groups('group_1')]
40+
public string $out_group_1_22;
41+
42+
#[\Astral\Serialize\Annotations\Groups('group_1','group_2')]
43+
public string $out_group_1_33_2_11;
44+
45+
#[\Astral\Serialize\Annotations\Groups('group_2')]
46+
public string $out_group_2_22;
47+
48+
#[\Astral\Serialize\Annotations\Groups('group_2')]
49+
public string $out_group_2_33;
50+
}
51+
52+
53+
#[\Astral\Serialize\OpenApi\Annotations\Tag('接口测试')]
54+
class TestBaseGroupController
55+
{
56+
#[\Astral\Serialize\OpenApi\Annotations\Summary('测试方法一')]
57+
#[OpenApi\Annotations\Route('/test/base-group')]
58+
#[OpenApi\Annotations\Response(TestBaseGroupResponse::class, groups:['group_1'])]
59+
#[OpenApi\Annotations\RequestBody(groups: ['group_2'])]
60+
public function one(TestBaseGroupRequest $request): void
61+
{
62+
}
63+
}
64+
65+
});
66+
67+
test('OpenAPI customer route', function () {
68+
69+
$api = new OpenApi();
70+
$api->buildByClass(TestBaseGroupController::class);
71+
72+
$openApi = $api::$openAPI;
73+
74+
$paths = $openApi->paths;
75+
$post = $paths['/test/base-group']['post'];
76+
$requestBody = $post->requestBody;
77+
$schema = $requestBody['content']['application/json']['schema'];
78+
expect($schema['properties'])->toHaveCount(3)->toHaveKeys(['input_change_group_1_33_2_11', 'input_group_2_22', 'input_group_2_33']);
79+
80+
81+
$schema = $post->responses[200]['content']['application/json']['schema'];
82+
expect($schema['properties'])->toHaveCount(3)->toHaveKeys(['out_group_1_11', 'out_group_1_22', 'out_group_1_33_2_11']);
83+
84+
});

0 commit comments

Comments
 (0)