22
33namespace rethink \typedphp ;
44
5- use rethink \typedphp \types \BooleanType ;
5+ use InvalidArgumentException ;
6+ use phpDocumentor \Reflection \DocBlockFactory ;
67use rethink \typedphp \types \BinaryType ;
8+ use rethink \typedphp \types \BooleanType ;
79use rethink \typedphp \types \DateType ;
810use rethink \typedphp \types \DictType ;
911use rethink \typedphp \types \InputType ;
1012use rethink \typedphp \types \IntegerType ;
11- use rethink \typedphp \types \ProductType ;
13+ use rethink \typedphp \types \MapType ;
1214use rethink \typedphp \types \NumberType ;
15+ use rethink \typedphp \types \ProductType ;
1316use rethink \typedphp \types \StringType ;
1417use rethink \typedphp \types \SumType ;
1518use rethink \typedphp \types \TimestampType ;
1619use rethink \typedphp \types \TimeType ;
1720use rethink \typedphp \types \Type ;
18- use phpDocumentor \Reflection \DocBlockFactory ;
1921
2022/**
2123 * Class TypeParser
2527class TypeParser
2628{
2729 const MODE_JSON_SCHEMA = 1 ;
28- const MODE_OPEN_API = 2 ;
29- const MODE_REF_SCHEMA = 4 ;
30+ const MODE_OPEN_API = 2 ;
31+ const MODE_REF_SCHEMA = 4 ;
3032
3133 protected $ mode = 0 ;
3234 protected $ builtinTypes = [];
@@ -51,17 +53,17 @@ public function __construct($mode)
5153
5254 public function registerBuiltinType (string $ typeClass )
5355 {
54- if (!is_subclass_of ($ typeClass , Type::class)) {
55- throw new \ InvalidArgumentException ("The type: $ typeClass is invalid, a type should be subclass of Type " );
56+ if (! is_subclass_of ($ typeClass , Type::class)) {
57+ throw new InvalidArgumentException ("The type: $ typeClass is invalid, a type should be subclass of Type " );
5658 }
5759
5860 $ this ->builtinTypes [$ typeClass ::name ()] = $ typeClass ;
5961 }
6062
6163 protected function getValidTypeClass ($ typeName )
6264 {
63- if (!isset ($ this ->builtinTypes [$ typeName ])) {
64- throw new \ InvalidArgumentException ("The type: $ typeName is invalid, not such type existed " );
65+ if (! isset ($ this ->builtinTypes [$ typeName ])) {
66+ throw new InvalidArgumentException ("The type: $ typeName is invalid, not such type existed " );
6567 }
6668
6769 return $ this ->builtinTypes [$ typeName ];
@@ -142,11 +144,13 @@ protected function parseInputField($definition)
142144
143145 list ($ _ , $ schema ) = $ this ->parseField ($ definition );
144146
145- return [
147+ $ result = [
146148 'in ' => $ fetcher ,
147- 'required ' => $ required ,
148149 'schema ' => $ schema ,
149150 ];
151+ if ($ required ) {
152+ $ result ['required ' ] = $ required ;
153+ }
150154 }
151155
152156 private function isNullable (string $ definition ): bool
@@ -195,8 +199,10 @@ protected function parseObject($definition)
195199 $ schema = [
196200 'type ' => 'object ' ,
197201 'properties ' => $ properties ,
198- 'required ' => $ requiredFields ,
199202 ];
203+ if ($ requiredFields ) {
204+ $ schema ['required ' ] = $ requiredFields ;
205+ }
200206
201207 if ($ this ->mode & self ::MODE_REF_SCHEMA ) {
202208 $ this ->schemas [$ definitionName ] = $ schema ;
@@ -242,7 +248,7 @@ protected function makeNullableSchema(array $schema, $nullable)
242248 'anyOf ' => [
243249 ['type ' => 'null ' ],
244250 $ schema ,
245- ]
251+ ],
246252 ];
247253 }
248254
@@ -255,25 +261,59 @@ protected function parseScalar($definition)
255261 }
256262
257263 $ typeClass = $ this ->getValidTypeClass ($ definition );
258-
259264 $ schema = $ typeClass ::toArray ();
260265
261266 if (($ this ->mode & self ::MODE_JSON_SCHEMA ) && $ nullable ) {
262267 $ schema ['type ' ] = [$ schema ['type ' ], 'null ' ];
263- } else if (($ this ->mode & self ::MODE_OPEN_API ) && $ nullable ) {
268+ } elseif (($ this ->mode & self ::MODE_OPEN_API ) && $ nullable ) {
264269 $ schema ['nullable ' ] = $ nullable ;
265270 }
266271
267272 return $ schema ;
268273 }
269274
275+ protected function parseMap (string $ definition ): array
276+ {
277+ $ nullable = false ;
278+ if ($ this ->isNullable ($ definition )) {
279+ $ nullable = true ;
280+ $ definition = trim ($ definition , '? ' );
281+ }
282+
283+ assert (is_subclass_of ($ definition , MapType::class));
284+
285+ $ schema = $ definition ::toArray ();
286+
287+ $ valueDefinition = $ definition ::valueType ();
288+ if ($ valueDefinition ) {
289+ $ schema ['additionalProperties ' ] = $ this ->parseString ($ valueDefinition );
290+ }
291+
292+ $ example = $ definition ::example ();
293+ if ($ example ) {
294+ $ schema ['example ' ] = $ example ;
295+ }
296+
297+ $ definitionName = $ definition ::name ();
298+ if ($ this ->mode & self ::MODE_REF_SCHEMA ) {
299+ $ this ->schemas [$ definitionName ] = $ schema ;
300+ return $ this ->makeNullableSchema ([
301+ '$ref ' => '#/components/schemas/ ' . $ definitionName ,
302+ ], $ nullable );
303+ }
304+
305+ return $ this ->makeNullableSchema ($ schema , $ nullable );
306+ }
307+
270308 protected function parseString ($ definition )
271309 {
272310 $ newDefinition = trim ($ definition , '? ' );
273311 if (is_subclass_of ($ newDefinition , ProductType::class)) {
274312 return $ this ->parseObject ($ definition );
275313 } elseif (is_subclass_of ($ newDefinition , SumType::class)) {
276314 return $ this ->parseEnum ($ definition );
315+ } elseif (is_subclass_of ($ newDefinition , MapType::class)) {
316+ return $ this ->parseMap ($ newDefinition );
277317 } else {
278318 return $ this ->parseScalar ($ definition );
279319 }
@@ -290,9 +330,9 @@ public function parse($definition)
290330 {
291331 if (is_array ($ definition )) {
292332 return $ this ->parseArray ($ definition );
293- } else if (is_string ($ definition )) {
333+ } elseif (is_string ($ definition )) {
294334 return $ this ->parseString ($ definition );
295- } else if (is_object ($ definition ) && $ definition instanceof ProductType) {
335+ } elseif (is_object ($ definition ) && $ definition instanceof ProductType) {
296336 return $ this ->parseObject (get_class ($ definition ));
297337 } else {
298338 throw new \InvalidArgumentException ('The definition is invalid ' );
0 commit comments