Skip to content

Commit 71bec68

Browse files
committed
feat(OpenApiType): Suggest creating aliases for enums
Signed-off-by: provokateurin <[email protected]>
1 parent d0e29bd commit 71bec68

File tree

7 files changed

+480
-3
lines changed

7 files changed

+480
-3
lines changed

generate-spec.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@
150150
}
151151
}
152152
foreach (array_keys($definitions) as $name) {
153-
$schemas[Helpers::cleanSchemaName($name)] = OpenApiType::resolve('Response definitions: ' . $name, $definitions, $definitions[$name])->toArray();
153+
$schemas[Helpers::cleanSchemaName($name)] = OpenApiType::resolve('Response definitions: ' . $name, $definitions, $definitions[$name], true)->toArray();
154154
}
155155
} else {
156156
Logger::debug('Response definitions', 'No response definitions were loaded');

src/OpenApiType.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ enum: [0, 1],
156156
return $values !== [] ? $values : new stdClass();
157157
}
158158

159-
public static function resolve(string $context, array $definitions, ParamTagValueNode|NodeAbstract|TypeNode $node): OpenApiType {
159+
public static function resolve(string $context, array $definitions, ParamTagValueNode|NodeAbstract|TypeNode $node, ?bool $isResponseDefinition = false): OpenApiType {
160160
if ($node instanceof ParamTagValueNode) {
161161
$type = self::resolve($context, $definitions, $node->type);
162162
$type->description = $node->description;
@@ -276,6 +276,10 @@ public static function resolve(string $context, array $definitions, ParamTagValu
276276
);
277277
}
278278

279+
if (!$isResponseDefinition) {
280+
Logger::warning($context, 'Consider using a Response definition for this enum to improve readability and reusability.');
281+
}
282+
279283
return new OpenApiType(
280284
context: $context,
281285
type: 'string',
@@ -298,6 +302,10 @@ enum: $values,
298302
);
299303
}
300304

305+
if (!$isResponseDefinition) {
306+
Logger::warning($context, 'Consider using a Response definition for this enum to improve readability and reusability.');
307+
}
308+
301309
return new OpenApiType(
302310
context: $context,
303311
type: 'integer',
@@ -420,7 +428,8 @@ private static function mergeEnums(string $context, array $types): array {
420428

421429
return array_merge($nonEnums, array_map(static fn (string $type): \OpenAPIExtractor\OpenApiType => new OpenApiType(
422430
context: $context,
423-
type: $type, enum: $enums[$type],
431+
type: $type,
432+
enum: $enums[$type],
424433
), array_keys($enums)));
425434
}
426435

tests/appinfo/routes.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,7 @@
7676
['name' => 'Settings#whitespace', 'url' => '/api/{apiVersion}/whitespace', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']],
7777
['name' => 'Settings#withCorsAnnotation', 'url' => '/api/{apiVersion}/cors/annotation', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']],
7878
['name' => 'Settings#withCorsAttribute', 'url' => '/api/{apiVersion}/cors/attribute', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']],
79+
['name' => 'Settings#enumNotAliased', 'url' => '/api/{apiVersion}/enum/not-aliased', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']],
80+
['name' => 'Settings#enumAliased', 'url' => '/api/{apiVersion}/enum/aliased', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']],
7981
],
8082
];

tests/lib/Controller/SettingsController.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
* @psalm-import-type NotificationsPushDevice from ResponseDefinitions
2424
* @psalm-import-type NotificationsNotification from ResponseDefinitions
2525
* @psalm-import-type NotificationsCollection from ResponseDefinitions
26+
* @psalm-import-type NotificationsEnumString from ResponseDefinitions
27+
* @psalm-import-type NotificationsEnumInt from ResponseDefinitions
2628
*/
2729
class SettingsController extends OCSController {
2830
/**
@@ -596,4 +598,32 @@ public function withCorsAnnotation(): DataResponse {
596598
public function withCorsAttribute(): DataResponse {
597599
return new DataResponse();
598600
}
601+
602+
/**
603+
* Not aliased enum
604+
*
605+
* @param 'a'|'b' $string A string enum without alias
606+
* @param 0|1 $int An int enum without alias
607+
*
608+
* @return DataResponse<Http::STATUS_OK, list<empty>, array{}>
609+
*
610+
* 200: OK
611+
*/
612+
public function enumNotAliased(string $string, int $int): DataResponse {
613+
return new DataResponse();
614+
}
615+
616+
/**
617+
* Aliased enum
618+
*
619+
* @param NotificationsEnumString $string A string enum with alias
620+
* @param NotificationsEnumInt $int An int enum with alias
621+
*
622+
* @return DataResponse<Http::STATUS_OK, list<empty>, array{}>
623+
*
624+
* 200: OK
625+
*/
626+
public function enumAliased(string $string, int $int): DataResponse {
627+
return new DataResponse();
628+
}
599629
}

tests/lib/ResponseDefinitions.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@
5959
* publicKey: string,
6060
* signature: string,
6161
* }
62+
*
63+
* @psalm-type NotificationsEnumString = 'a'|'b'
64+
*
65+
* @psalm-type NotificationsEnumInt = 0|1
6266
*/
6367
class ResponseDefinitions {
6468
}

tests/openapi-administration.json

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,21 @@
4040
}
4141
}
4242
},
43+
"EnumInt": {
44+
"type": "integer",
45+
"format": "int64",
46+
"enum": [
47+
0,
48+
1
49+
]
50+
},
51+
"EnumString": {
52+
"type": "string",
53+
"enum": [
54+
"a",
55+
"b"
56+
]
57+
},
4358
"OCSMeta": {
4459
"type": "object",
4560
"required": [
@@ -4638,6 +4653,207 @@
46384653
}
46394654
}
46404655
},
4656+
"/ocs/v2.php/apps/notifications/api/{apiVersion}/enum/not-aliased": {
4657+
"post": {
4658+
"operationId": "settings-enum-not-aliased",
4659+
"summary": "Not aliased enum",
4660+
"description": "This endpoint requires admin access",
4661+
"tags": [
4662+
"settings"
4663+
],
4664+
"security": [
4665+
{
4666+
"bearer_auth": []
4667+
},
4668+
{
4669+
"basic_auth": []
4670+
}
4671+
],
4672+
"requestBody": {
4673+
"required": true,
4674+
"content": {
4675+
"application/json": {
4676+
"schema": {
4677+
"type": "object",
4678+
"required": [
4679+
"string",
4680+
"int"
4681+
],
4682+
"properties": {
4683+
"string": {
4684+
"type": "string",
4685+
"enum": [
4686+
"a",
4687+
"b"
4688+
],
4689+
"description": "A string enum without alias"
4690+
},
4691+
"int": {
4692+
"type": "integer",
4693+
"format": "int64",
4694+
"enum": [
4695+
0,
4696+
1
4697+
],
4698+
"description": "An int enum without alias"
4699+
}
4700+
}
4701+
}
4702+
}
4703+
}
4704+
},
4705+
"parameters": [
4706+
{
4707+
"name": "apiVersion",
4708+
"in": "path",
4709+
"required": true,
4710+
"schema": {
4711+
"type": "string",
4712+
"enum": [
4713+
"v2"
4714+
],
4715+
"default": "v2"
4716+
}
4717+
},
4718+
{
4719+
"name": "OCS-APIRequest",
4720+
"in": "header",
4721+
"description": "Required to be true for the API request to pass",
4722+
"required": true,
4723+
"schema": {
4724+
"type": "boolean",
4725+
"default": true
4726+
}
4727+
}
4728+
],
4729+
"responses": {
4730+
"200": {
4731+
"description": "OK",
4732+
"content": {
4733+
"application/json": {
4734+
"schema": {
4735+
"type": "object",
4736+
"required": [
4737+
"ocs"
4738+
],
4739+
"properties": {
4740+
"ocs": {
4741+
"type": "object",
4742+
"required": [
4743+
"meta",
4744+
"data"
4745+
],
4746+
"properties": {
4747+
"meta": {
4748+
"$ref": "#/components/schemas/OCSMeta"
4749+
},
4750+
"data": {}
4751+
}
4752+
}
4753+
}
4754+
}
4755+
}
4756+
}
4757+
}
4758+
}
4759+
}
4760+
},
4761+
"/ocs/v2.php/apps/notifications/api/{apiVersion}/enum/aliased": {
4762+
"post": {
4763+
"operationId": "settings-enum-aliased",
4764+
"summary": "Aliased enum",
4765+
"description": "This endpoint requires admin access",
4766+
"tags": [
4767+
"settings"
4768+
],
4769+
"security": [
4770+
{
4771+
"bearer_auth": []
4772+
},
4773+
{
4774+
"basic_auth": []
4775+
}
4776+
],
4777+
"requestBody": {
4778+
"required": true,
4779+
"content": {
4780+
"application/json": {
4781+
"schema": {
4782+
"type": "object",
4783+
"required": [
4784+
"string",
4785+
"int"
4786+
],
4787+
"properties": {
4788+
"string": {
4789+
"$ref": "#/components/schemas/EnumString",
4790+
"description": "A string enum with alias"
4791+
},
4792+
"int": {
4793+
"$ref": "#/components/schemas/EnumInt",
4794+
"description": "An int enum with alias"
4795+
}
4796+
}
4797+
}
4798+
}
4799+
}
4800+
},
4801+
"parameters": [
4802+
{
4803+
"name": "apiVersion",
4804+
"in": "path",
4805+
"required": true,
4806+
"schema": {
4807+
"type": "string",
4808+
"enum": [
4809+
"v2"
4810+
],
4811+
"default": "v2"
4812+
}
4813+
},
4814+
{
4815+
"name": "OCS-APIRequest",
4816+
"in": "header",
4817+
"description": "Required to be true for the API request to pass",
4818+
"required": true,
4819+
"schema": {
4820+
"type": "boolean",
4821+
"default": true
4822+
}
4823+
}
4824+
],
4825+
"responses": {
4826+
"200": {
4827+
"description": "OK",
4828+
"content": {
4829+
"application/json": {
4830+
"schema": {
4831+
"type": "object",
4832+
"required": [
4833+
"ocs"
4834+
],
4835+
"properties": {
4836+
"ocs": {
4837+
"type": "object",
4838+
"required": [
4839+
"meta",
4840+
"data"
4841+
],
4842+
"properties": {
4843+
"meta": {
4844+
"$ref": "#/components/schemas/OCSMeta"
4845+
},
4846+
"data": {}
4847+
}
4848+
}
4849+
}
4850+
}
4851+
}
4852+
}
4853+
}
4854+
}
4855+
}
4856+
},
46414857
"/ocs/v2.php/tests/attribute-ocs/{param}": {
46424858
"get": {
46434859
"operationId": "routing-attributeocs-route",

0 commit comments

Comments
 (0)