2
2
3
3
namespace Astral \Serialize \OpenApi \Collections ;
4
4
5
+ use Astral \Serialize \Enums \TypeKindEnum ;
5
6
use Astral \Serialize \OpenApi \Annotations \Headers ;
7
+ use Astral \Serialize \OpenApi \Annotations \RequestBody ;
8
+ use Astral \Serialize \OpenApi \Annotations \Response ;
6
9
use Astral \Serialize \OpenApi \Annotations \Route ;
7
10
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 ;
8
21
9
22
class OpenApiCollection
10
23
{
11
24
public function __construct (
12
25
public string $ controllerClass ,
13
26
public string $ methodName ,
27
+ public reflectionMethod $ reflectionMethod ,
28
+ public Tag $ tag ,
14
29
public Summary $ summary ,
15
30
public Route $ route ,
16
- public Headers $ headers ,
31
+ public Headers | null $ headers ,
17
32
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 ,
25
35
){
26
36
}
27
37
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
+ }
28
172
}
0 commit comments