Skip to content

Commit 578e3be

Browse files
committed
ref v2
1 parent 70abf1e commit 578e3be

25 files changed

+782
-437
lines changed

src/Enums/TypeKindEnum.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
namespace Astral\Serialize\Enums;
44

5-
use http\Exception\RuntimeException;
5+
6+
use RuntimeException;
67

78
enum TypeKindEnum
89
{
@@ -68,4 +69,16 @@ public static function getNameTo(string $type, ?string $className = null): self
6869
default => throw new RuntimeException("not found type $type"),
6970
};
7071
}
72+
73+
public function getOpenApiName(): string
74+
{
75+
return match ($this) {
76+
self::INT => 'integer',
77+
self::FLOAT => 'number',
78+
self::BOOLEAN => 'boolean',
79+
self::OBJECT, self::CLASS_OBJECT => 'object',
80+
self::ARRAY, self::COLLECT_SINGLE_OBJECT , self::COLLECT_UNION_OBJECT => 'array',
81+
default => 'string',
82+
};
83+
}
7184
}

src/OpenApi/Annotations/RequestBody.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public function __construct(
1414
/** @var class-string $className */
1515
public string $className = '',
1616
public ContentTypeEnum $contentType = ContentTypeEnum::JSON,
17-
public ?string $group = null
17+
public array|null $group = null
1818
){
1919
}
2020
}

src/OpenApi/Annotations/Response.php

Lines changed: 3 additions & 3 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 ?string $group = null,
16-
public ?int $code = 200
14+
public string $className,
15+
public ?int $code = 200,
16+
public ?array $groups = null,
1717
){
1818
}
1919
}

src/OpenApi/Annotations/Route.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,4 @@ public function __construct(
1616
public array $attributes = [],
1717
) {
1818
}
19-
20-
public function getMethod(): string
21-
{
22-
return 'April\\ApiDoc\\Storage\\OpenAPI\\Method\\' . $this->method->name;
23-
}
2419
}

src/OpenApi/Annotations/Tag.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,4 @@ public function __construct(
1919
) {
2020
}
2121

22-
public function buildTagStorage(): TagStorage
23-
{
24-
return new TagStorage($this->value, $this->description);
25-
}
2622
}

src/OpenApi/Collections/OpenApiCollection.php

Lines changed: 152 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,171 @@
22

33
namespace Astral\Serialize\OpenApi\Collections;
44

5+
use Astral\Serialize\Enums\TypeKindEnum;
56
use Astral\Serialize\OpenApi\Annotations\Headers;
7+
use Astral\Serialize\OpenApi\Annotations\RequestBody;
8+
use Astral\Serialize\OpenApi\Annotations\Response;
69
use Astral\Serialize\OpenApi\Annotations\Route;
710
use Astral\Serialize\OpenApi\Annotations\Summary;
11+
use Astral\Serialize\OpenApi\Annotations\Tag;
12+
use Astral\Serialize\OpenApi\Enum\ContentTypeEnum;
13+
use Astral\Serialize\OpenApi\Storage\OpenAPI\Method\Method;
14+
use Astral\Serialize\OpenApi\Storage\OpenAPI\RequestBodyStorage;
15+
use Astral\Serialize\OpenApi\Storage\OpenAPI\ResponseStorage;
16+
use Astral\Serialize\OpenApi\Storage\OpenAPI\SchemaStorage;
17+
use Astral\Serialize\Serialize;
18+
use Astral\Serialize\Support\Factories\ContextFactory;
19+
use Psr\SimpleCache\InvalidArgumentException;
20+
use ReflectionMethod;
821

922
class OpenApiCollection
1023
{
1124
public function __construct(
1225
public string $controllerClass,
1326
public string $methodName,
27+
public reflectionMethod $reflectionMethod,
28+
public Tag $tag,
1429
public Summary $summary,
1530
public Route $route,
16-
public Headers $headers,
31+
public Headers|null $headers,
1732
public array $attributes,
18-
/** @var array<string, ParameterCollection> $parameters, */
19-
public array $parameters = [],
20-
/** @var array<string, ParameterCollection|mixed> $requestBody, */
21-
public array $requestBody = [],
22-
/** @var array<string, ParameterCollection|mixed> $responses, */
23-
public array $response = [],
24-
33+
public RequestBody|null $requestBody,
34+
public Response|null $response,
2535
){
2636
}
2737

38+
/**
39+
* @throws InvalidArgumentException
40+
*/
41+
public function build() : Method
42+
{
43+
$methodClass = $this->route->method->value;
44+
/** @var Method $openAPIMethod */
45+
$openAPIMethod = new $methodClass(
46+
tags:[$this->tag->value ?: ''],
47+
summary:$this->summary->value,
48+
description:$this->summary->description ?: ''
49+
);
50+
51+
$openAPIMethod->withRequestBody($this->requestBody !== null ? $this->buildRequestBodyByAttribute() : $this->buildRequestBodyByParameters());
52+
$openAPIMethod->addResponse(200, $this->buildResponse());
53+
54+
return $openAPIMethod;
55+
}
56+
57+
/**
58+
* @throws InvalidArgumentException
59+
*/
60+
public function buildRequestBodyByAttribute(): RequestBodyStorage
61+
{
62+
$openAPIRequestBody = new RequestBodyStorage($this->requestBody->contentType);
63+
$schemaStorage = (new SchemaStorage())->build($this->buildRequestBodyParameterCollections($this->requestBody->className,$this->requestBody->group),$n);
64+
$openAPIRequestBody->withParameter($schemaStorage);
65+
return $openAPIRequestBody;
66+
}
67+
68+
/**
69+
* @throws InvalidArgumentException
70+
*/
71+
public function buildRequestBodyByParameters(): RequestBodyStorage
72+
{
73+
$openAPIRequestBody = new RequestBodyStorage(ContentTypeEnum::JSON);
74+
$methodParam = $this->reflectionMethod->getParameters()[0] ?? null;
75+
$requestBodyClass = $methodParam ? $methodParam->getType()?->getName() : '';
76+
if (is_subclass_of($requestBodyClass, Serialize::class)) {
77+
$schemaStorage = (new SchemaStorage())->build($this->buildRequestBodyParameterCollections($requestBodyClass),$node);
78+
$openAPIRequestBody->withParameter($schemaStorage);
79+
}
80+
81+
return $openAPIRequestBody;
82+
}
83+
84+
/**
85+
* @throws InvalidArgumentException
86+
*/
87+
public function buildResponse(): ResponseStorage
88+
{
89+
$responseStorage = new ResponseStorage();
90+
$schemaStorage = (new SchemaStorage())->build($this->buildResponseParameterCollections());
91+
$responseStorage->withParameter($schemaStorage);
92+
return $responseStorage;
93+
}
94+
95+
/**
96+
* @param string $className
97+
* @param array $groups
98+
* @return array<string, ParameterCollection>
99+
* @throws InvalidArgumentException
100+
*/
101+
public function buildRequestBodyParameterCollections(string $className, array $groups = ['default']): array
102+
{
103+
$serializeContext = ContextFactory::build($className);
104+
$serializeContext->from();
105+
$properties = $serializeContext->getGroupCollection()->getProperties();
106+
107+
$vols = [];
108+
foreach ($properties as $property){
109+
$vol = new ParameterCollection(
110+
name: current($property->getInputNamesByGroups($groups,$className)),
111+
descriptions: '',
112+
type: current($property->getTypes())->kind ?: TypeKindEnum::STRING,
113+
required: !$property->isNullable(),
114+
ignore: false,
115+
);
116+
117+
if($property->getChildren()){
118+
foreach ($property->getChildren() as $children){
119+
$vol->children[] = $this->buildRequestBodyParameterCollections($children->getClassName());
120+
}
121+
}
122+
123+
$vols[] = $vol;
124+
}
125+
126+
return $vols;
127+
}
128+
129+
/**
130+
* @return array<string, ParameterCollection>
131+
* @throws InvalidArgumentException
132+
*/
133+
public function buildResponseParameterCollections(): array
134+
{
135+
$returnClass = $this->reflectionMethod->getReturnType();
136+
$responseClass = match(true){
137+
$this->response !== null => $this->response->className,
138+
$returnClass && is_subclass_of($returnClass,Serialize::class) => $returnClass,
139+
default => null,
140+
};
141+
142+
if(!$responseClass){
143+
return [];
144+
}
145+
146+
$groups = $this->response ? $this->response->groups : ['default'];
147+
$serializeContext = ContextFactory::build($responseClass);
148+
$serializeContext->from();
149+
$properties = $serializeContext->getGroupCollection()->getProperties();
150+
151+
$vols = [];
152+
foreach ($properties as $property){
153+
$vol = new ParameterCollection(
154+
name:current($property->getOutNamesByGroups($groups,$responseClass)),
155+
descriptions: '',
156+
type: current($property->getTypes())->kind ?: TypeKindEnum::STRING,
157+
required: !$property->isNullable(),
158+
ignore: false,
159+
);
160+
161+
if($property->getChildren()){
162+
foreach ($property->getChildren() as $children){
163+
$vol->children[] = $this->buildRequestBodyParameterCollections($children->getClassName());
164+
}
165+
}
166+
167+
$vols[] = $vol;
168+
}
169+
170+
return $vols;
171+
}
28172
}

src/OpenApi/Collections/ParameterCollection.php

Lines changed: 8 additions & 8 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;
78
use Attribute;
89

910
class ParameterCollection
1011
{
1112
public function __construct(
1213
/** @var string 元素变量名 */
13-
public string $name,
14+
public string $name,
1415
/** @var string descriptions */
15-
public string $descriptions = '',
16-
/** @var string 元素类型 */
17-
public string $type = 'string',
16+
public string $descriptions = '',
17+
public TypeKindEnum $type = TypeKindEnum::STRING,
1818
/** @var mixed 示例值 */
19-
public mixed $example = '',
19+
public mixed $example = '',
2020
/** @var bool 是否必填 */
21-
public bool $required = false,
21+
public bool $required = false,
2222
/** @var bool 是否忽略显示 */
23-
public bool $ignore = false,
23+
public bool $ignore = false,
2424
/** @var array<string, ParameterCollection> $children */
25-
public array $children = [],
25+
public array $children = [],
2626
){
2727
}
2828
}

src/OpenApi/Enum/MethodEnum.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,16 @@
22

33
namespace Astral\Serialize\OpenApi\Enum;
44

5-
enum MethodEnum
5+
use Astral\Serialize\OpenApi\Storage\OpenAPI\Method\Delete;
6+
use Astral\Serialize\OpenApi\Storage\OpenAPI\Method\Get;
7+
use Astral\Serialize\OpenApi\Storage\OpenAPI\Method\Post;
8+
use Astral\Serialize\OpenApi\Storage\OpenAPI\Method\Put;
9+
10+
enum MethodEnum:string
611
{
7-
case POST;
8-
case GET;
12+
case POST = Post::class;
13+
case GET = Get::class;
14+
case PUT = Put::class;
15+
case DELETE = Delete::class;
16+
917
}

0 commit comments

Comments
 (0)