[PHP-SYMFONY] Support BackedEnum for enum ref (16846) (#16847)

* [PHP-SYMFONY] Support BackedEnum for enumm ref (16846)

* [PHP-SYMFONY] Support BackedEnum for enumm ref (16846)

* [PHP-SYMFONY] Support BackedEnum for enumm ref (16846)

* [PHP-SYMFONY] Support BackedEnum for enumm ref (16846)

* [PHP-SYMFONY] Support BackedEnum for enum ref (16846)

* [PHP-SYMFONY] Support BackedEnum for enum ref (16846)

* [PHP-SYMFONY] Support BackedEnum for enum ref (16846)
This commit is contained in:
loicconan 2023-11-07 15:40:35 +01:00 committed by GitHub
parent 74163f0ac8
commit d945499073
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 288 additions and 90 deletions

View File

@ -58,7 +58,12 @@ interface {{classname}}
*
{{/description}}
{{#allParams}}
{{#isEnumRef}}
* @param \{{modelPackage}}\{{dataType}}{{^required}}{{^defaultValue}}|null{{/defaultValue}}{{/required}} ${{paramName}} {{description}} {{#required}}(required){{/required}}{{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{#isDeprecated}} (deprecated){{/isDeprecated}}
{{/isEnumRef}}
{{^isEnumRef}}
* @param {{vendorExtensions.x-parameter-type}}{{^required}}{{^defaultValue}}|null{{/defaultValue}}{{/required}} ${{paramName}} {{description}} {{#required}}(required){{/required}}{{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{#isDeprecated}} (deprecated){{/isDeprecated}}
{{/isEnumRef}}
{{/allParams}}
* @param int &$responseCode The HTTP Response Code
* @param array $responseHeaders Additional HTTP headers to return with the response ()
@ -68,8 +73,18 @@ interface {{classname}}
* @deprecated
{{/isDeprecated}}
*/
public function {{operationId}}({{#allParams}}{{^required}}{{^defaultValue}}?{{/defaultValue}}{{/required}}{{#vendorExtensions.x-parameter-type}}{{vendorExtensions.x-parameter-type}} {{/vendorExtensions.x-parameter-type}}${{paramName}}, {{/allParams}}int &$responseCode, array &$responseHeaders): {{{vendorExtensions.x-return-type}}};
public function {{operationId}}(
{{#allParams}}
{{#isEnumRef}}
{{^required}}{{^defaultValue}}?{{/defaultValue}}{{/required}}\{{modelPackage}}\{{dataType}} ${{paramName}},
{{/isEnumRef}}
{{^isEnumRef}}
{{^required}}{{^defaultValue}}?{{/defaultValue}}{{/required}}{{#vendorExtensions.x-parameter-type}}{{vendorExtensions.x-parameter-type}} {{/vendorExtensions.x-parameter-type}}${{paramName}},
{{/isEnumRef}}
{{/allParams}}
int &$responseCode,
array &$responseHeaders
): {{{vendorExtensions.x-return-type}}};
{{/operation}}
}
{{/operations}}

View File

@ -149,10 +149,10 @@ class {{controllerName}} extends Controller
{{^isFile}}
{{#isBodyParam}}
$inputFormat = $request->getMimeType($request->getContentType());
${{paramName}} = $this->deserialize(${{paramName}}, '{{#isContainer}}{{#items}}array<{{dataType}}>{{/items}}{{/isContainer}}{{^isContainer}}{{dataType}}{{/isContainer}}', $inputFormat);
${{paramName}} = $this->deserialize(${{paramName}}, '{{#isContainer}}{{#items}}array<{{dataType}}>{{/items}}{{/isContainer}}{{^isContainer}}{{#isEnumRef}}\{{modelPackage}}\{{dataType}}{{/isEnumRef}}{{^isEnumRef}}{{dataType}}{{/isEnumRef}}{{/isContainer}}', $inputFormat);
{{/isBodyParam}}
{{^isBodyParam}}
${{paramName}} = $this->deserialize(${{paramName}}, '{{#isContainer}}array<{{collectionFormat}}{{^collectionFormat}}csv{{/collectionFormat}},{{dataType}}>{{/isContainer}}{{^isContainer}}{{dataType}}{{/isContainer}}', 'string');
${{paramName}} = $this->deserialize(${{paramName}}, '{{#isContainer}}array<{{collectionFormat}}{{^collectionFormat}}csv{{/collectionFormat}},{{dataType}}>{{/isContainer}}{{^isContainer}}{{#isEnumRef}}\{{modelPackage}}\{{dataType}}{{/isEnumRef}}{{^isEnumRef}}{{dataType}}{{/isEnumRef}}{{/isContainer}}', 'string');
{{/isBodyParam}}
{{/isFile}}
{{/allParams}}

View File

@ -38,10 +38,15 @@
$asserts[] = new Assert\File();
{{/isFile}}
{{^isFile}}
{{#isEnumRef}}
$asserts[] = new Assert\Type("\{{modelPackage}}\{{dataType}}");
{{/isEnumRef}}
{{^isEnumRef}}
$asserts[] = new Assert\Type("{{dataType}}");
{{^isPrimitiveType}}
$asserts[] = new Assert\Valid();
{{/isPrimitiveType}}
{{/isEnumRef}}
{{/isFile}}
{{/isDateTime}}
{{/isDate}}

View File

@ -23,6 +23,7 @@ namespace {{modelPackage}};
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\Accessor;
use JMS\Serializer\Annotation\SerializedName;
/**

View File

@ -1,19 +1,8 @@
class {{classname}}
enum {{classname}}: {{dataType}}
{
/**
* Possible values of this enum
*/
{{#allowableValues}}{{#enumVars}}const {{{name}}} = {{{value}}};
{{/enumVars}}{{/allowableValues}}
/**
* Gets allowable values of the enum
* @return string[]
*/
public static function getAllowableEnumValues()
{
return [
{{#allowableValues}}{{#enumVars}}self::{{{name}}},{{^-last}}
{{/-last}}{{/enumVars}}{{/allowableValues}}
];
}
{{#allowableValues}}
{{#enumVars}}
case {{{name}}} = {{{value}}};
{{/enumVars}}
{{/allowableValues}}
}

View File

@ -30,6 +30,37 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}
return $this->{{name}};
}
{{#isEnumRef}}
/**
* Gets {{name}} for serialization.
*
* @return string|null
*/
public function getSerialized{{nameInCamelCase}}(): string|null
{
return $this->{{name}}?->value ? (string) $this->{{name}}->value : null;
}
{{/isEnumRef}}
{{#isContainer}}
{{#items}}
{{#isEnumRef}}
/**
* Gets {{name}} for serialization.
*
* @return array
*/
public function getSerialized{{nameInCamelCase}}(): array
{
return array_map(
static fn ($value) => (string) $value->value,
$this->test ?? []
);
}
{{/isEnumRef}}
{{/items}}
{{/isContainer}}
/**
* Sets {{name}}.
*

View File

@ -36,7 +36,13 @@
{{/isMap}}
{{^isMap}}
{{#items}}
{{#isEnumRef}}
* @Accessor(getter="getSerialized{{nameInCamelCase}}")
* @Type("array<string>")
{{/isEnumRef}}
{{^isEnumRef}}
* @Type("array<{{dataType}}>")
{{/isEnumRef}}
{{/items}}
{{/isMap}}
{{/isContainer}}
@ -49,10 +55,16 @@
* @Assert\Type("\DateTime"))
* @Type("DateTime")
{{/isDateTime}}
{{#isEnumRef}}
* @Accessor(getter="getSerialized{{nameInCamelCase}}")
* @Type("string")
{{/isEnumRef}}
{{^isDate}}
{{^isDateTime}}
{{^isEnumRef}}
* @Assert\Type("{{dataType}}")
* @Type("{{dataType}}")
{{/isEnumRef}}
{{/isDateTime}}
{{/isDate}}
{{/isContainer}}

View File

@ -60,7 +60,7 @@ class JmsSerializer implements SerializerInterface
private function deserializeString($data, string $type)
{
// Figure out if we have an array format
if (1 === preg_match('/array<(csv|ssv|tsv|pipes),(int|string)>/i', $type, $matches)) {
if (1 === preg_match('/array<(csv|ssv|tsv|pipes),(.*)>/i', $type, $matches)) {
return $this->deserializeArrayString($matches[1], $matches[2], $data);
}
@ -104,7 +104,21 @@ class JmsSerializer implements SerializerInterface
case '\DateTime':
return is_null($data) ? null :new DateTime($data);
default:
throw new RuntimeException(sprintf("Type %s is unsupported", $type));
if (!class_exists($type)) {
throw new RuntimeException(sprintf("Type %s is unsupported", $type));
}
$reflectionClass = new \ReflectionClass($type);
if (!$reflectionClass->implementsInterface('\BackedENum')) {
throw new RuntimeException(sprintf("Type %s is unsupported", $type));
}
$enum = $type::tryFrom($data);
if (!$enum) {
throw new RuntimeException(sprintf("Unknown %s value in %s enum", $data, $type));
}
return $enum;
}
// If we end up here, just return data

View File

@ -19,8 +19,9 @@
* Please update the test case below to test the model.
*/
namespace {{modelPackage}};
namespace {{modelTestsPackage}};
use {{modelPackage}}\{{classname}};
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@ -50,7 +51,9 @@ class {{classname}}Test extends TestCase
*/
public function setUp(): void
{
{{^isEnum}}
$this->object = $this->getMockBuilder({{classname}}::class)->getMockForAbstractClass();
{{/isEnum}}
}
/**
@ -73,8 +76,13 @@ class {{classname}}Test extends TestCase
*/
public function testTestClassExists(): void
{
{{#isEnum}}
$this->assertTrue(enum_exists({{classname}}::class));
{{/isEnum}}
{{^isEnum}}
$this->assertTrue(class_exists({{classname}}::class));
$this->assertInstanceOf({{classname}}::class, $this->object);
{{/isEnum}}
}
{{#vars}}

View File

@ -73,8 +73,11 @@ interface PetApiInterface
*
* @return array|object|null
*/
public function addPet(Pet $pet, int &$responseCode, array &$responseHeaders): array|object|null;
public function addPet(
Pet $pet,
int &$responseCode,
array &$responseHeaders
): array|object|null;
/**
* Operation deletePet
@ -88,8 +91,12 @@ interface PetApiInterface
*
* @return void
*/
public function deletePet(int $petId, ?string $apiKey, int &$responseCode, array &$responseHeaders): void;
public function deletePet(
int $petId,
?string $apiKey,
int &$responseCode,
array &$responseHeaders
): void;
/**
* Operation findPetsByStatus
@ -102,8 +109,11 @@ interface PetApiInterface
*
* @return array|object|null
*/
public function findPetsByStatus(array $status, int &$responseCode, array &$responseHeaders): array|object|null;
public function findPetsByStatus(
array $status,
int &$responseCode,
array &$responseHeaders
): array|object|null;
/**
* Operation findPetsByTags
@ -117,8 +127,11 @@ interface PetApiInterface
* @return array|object|null
* @deprecated
*/
public function findPetsByTags(array $tags, int &$responseCode, array &$responseHeaders): array|object|null;
public function findPetsByTags(
array $tags,
int &$responseCode,
array &$responseHeaders
): array|object|null;
/**
* Operation getPetById
@ -131,8 +144,11 @@ interface PetApiInterface
*
* @return array|object|null
*/
public function getPetById(int $petId, int &$responseCode, array &$responseHeaders): array|object|null;
public function getPetById(
int $petId,
int &$responseCode,
array &$responseHeaders
): array|object|null;
/**
* Operation updatePet
@ -145,8 +161,11 @@ interface PetApiInterface
*
* @return array|object|null
*/
public function updatePet(Pet $pet, int &$responseCode, array &$responseHeaders): array|object|null;
public function updatePet(
Pet $pet,
int &$responseCode,
array &$responseHeaders
): array|object|null;
/**
* Operation updatePetWithForm
@ -161,8 +180,13 @@ interface PetApiInterface
*
* @return void
*/
public function updatePetWithForm(int $petId, ?string $name, ?string $status, int &$responseCode, array &$responseHeaders): void;
public function updatePetWithForm(
int $petId,
?string $name,
?string $status,
int &$responseCode,
array &$responseHeaders
): void;
/**
* Operation uploadFile
@ -177,6 +201,11 @@ interface PetApiInterface
*
* @return array|object|null
*/
public function uploadFile(int $petId, ?string $additionalMetadata, ?UploadedFile $file, int &$responseCode, array &$responseHeaders): array|object|null;
public function uploadFile(
int $petId,
?string $additionalMetadata,
?UploadedFile $file,
int &$responseCode,
array &$responseHeaders
): array|object|null;
}

View File

@ -63,8 +63,11 @@ interface StoreApiInterface
*
* @return void
*/
public function deleteOrder(string $orderId, int &$responseCode, array &$responseHeaders): void;
public function deleteOrder(
string $orderId,
int &$responseCode,
array &$responseHeaders
): void;
/**
* Operation getInventory
@ -76,8 +79,10 @@ interface StoreApiInterface
*
* @return array|object|null
*/
public function getInventory(int &$responseCode, array &$responseHeaders): array|object|null;
public function getInventory(
int &$responseCode,
array &$responseHeaders
): array|object|null;
/**
* Operation getOrderById
@ -90,8 +95,11 @@ interface StoreApiInterface
*
* @return array|object|null
*/
public function getOrderById(int $orderId, int &$responseCode, array &$responseHeaders): array|object|null;
public function getOrderById(
int $orderId,
int &$responseCode,
array &$responseHeaders
): array|object|null;
/**
* Operation placeOrder
@ -104,6 +112,9 @@ interface StoreApiInterface
*
* @return array|object|null
*/
public function placeOrder(Order $order, int &$responseCode, array &$responseHeaders): array|object|null;
public function placeOrder(
Order $order,
int &$responseCode,
array &$responseHeaders
): array|object|null;
}

View File

@ -63,8 +63,11 @@ interface UserApiInterface
*
* @return void
*/
public function createUser(User $user, int &$responseCode, array &$responseHeaders): void;
public function createUser(
User $user,
int &$responseCode,
array &$responseHeaders
): void;
/**
* Operation createUsersWithArrayInput
@ -77,8 +80,11 @@ interface UserApiInterface
*
* @return void
*/
public function createUsersWithArrayInput(array $user, int &$responseCode, array &$responseHeaders): void;
public function createUsersWithArrayInput(
array $user,
int &$responseCode,
array &$responseHeaders
): void;
/**
* Operation createUsersWithListInput
@ -91,8 +97,11 @@ interface UserApiInterface
*
* @return void
*/
public function createUsersWithListInput(array $user, int &$responseCode, array &$responseHeaders): void;
public function createUsersWithListInput(
array $user,
int &$responseCode,
array &$responseHeaders
): void;
/**
* Operation deleteUser
@ -105,8 +114,11 @@ interface UserApiInterface
*
* @return void
*/
public function deleteUser(string $username, int &$responseCode, array &$responseHeaders): void;
public function deleteUser(
string $username,
int &$responseCode,
array &$responseHeaders
): void;
/**
* Operation getUserByName
@ -119,8 +131,11 @@ interface UserApiInterface
*
* @return array|object|null
*/
public function getUserByName(string $username, int &$responseCode, array &$responseHeaders): array|object|null;
public function getUserByName(
string $username,
int &$responseCode,
array &$responseHeaders
): array|object|null;
/**
* Operation loginUser
@ -134,8 +149,12 @@ interface UserApiInterface
*
* @return array|object|null
*/
public function loginUser(string $username, string $password, int &$responseCode, array &$responseHeaders): array|object|null;
public function loginUser(
string $username,
string $password,
int &$responseCode,
array &$responseHeaders
): array|object|null;
/**
* Operation logoutUser
@ -147,8 +166,10 @@ interface UserApiInterface
*
* @return void
*/
public function logoutUser(int &$responseCode, array &$responseHeaders): void;
public function logoutUser(
int &$responseCode,
array &$responseHeaders
): void;
/**
* Operation updateUser
@ -162,6 +183,10 @@ interface UserApiInterface
*
* @return void
*/
public function updateUser(string $username, User $user, int &$responseCode, array &$responseHeaders): void;
public function updateUser(
string $username,
User $user,
int &$responseCode,
array &$responseHeaders
): void;
}

View File

@ -31,6 +31,7 @@ namespace OpenAPI\Server\Model;
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\Accessor;
use JMS\Serializer\Annotation\SerializedName;
/**
@ -91,6 +92,8 @@ class ApiResponse
return $this->code;
}
/**
* Sets code.
*
@ -115,6 +118,8 @@ class ApiResponse
return $this->type;
}
/**
* Sets type.
*
@ -139,6 +144,8 @@ class ApiResponse
return $this->message;
}
/**
* Sets message.
*

View File

@ -31,6 +31,7 @@ namespace OpenAPI\Server\Model;
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\Accessor;
use JMS\Serializer\Annotation\SerializedName;
/**
@ -83,6 +84,8 @@ class Category
return $this->id;
}
/**
* Sets id.
*
@ -107,6 +110,8 @@ class Category
return $this->name;
}
/**
* Sets name.
*

View File

@ -31,6 +31,7 @@ namespace OpenAPI\Server\Model;
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\Accessor;
use JMS\Serializer\Annotation\SerializedName;
/**
@ -41,27 +42,11 @@ use JMS\Serializer\Annotation\SerializedName;
* @package OpenAPI\Server\Model
* @author OpenAPI Generator team
*/
class EnumStringModel
enum EnumStringModel: string
{
/**
* Possible values of this enum
*/
const AVAILABLE = "available";
const PENDING = "pending";
const SOLD = "sold";
/**
* Gets allowable values of the enum
* @return string[]
*/
public static function getAllowableEnumValues()
{
return [
self::AVAILABLE,
self::PENDING,
self::SOLD,
];
}
case AVAILABLE = "available";
case PENDING = "pending";
case SOLD = "sold";
}

View File

@ -31,6 +31,7 @@ namespace OpenAPI\Server\Model;
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\Accessor;
use JMS\Serializer\Annotation\SerializedName;
/**
@ -121,6 +122,8 @@ class Order
return $this->id;
}
/**
* Sets id.
*
@ -145,6 +148,8 @@ class Order
return $this->petId;
}
/**
* Sets petId.
*
@ -169,6 +174,8 @@ class Order
return $this->quantity;
}
/**
* Sets quantity.
*
@ -193,6 +200,8 @@ class Order
return $this->shipDate;
}
/**
* Sets shipDate.
*
@ -217,6 +226,8 @@ class Order
return $this->status;
}
/**
* Sets status.
*
@ -241,6 +252,8 @@ class Order
return $this->complete;
}
/**
* Sets complete.
*

View File

@ -31,6 +31,7 @@ namespace OpenAPI\Server\Model;
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\Accessor;
use JMS\Serializer\Annotation\SerializedName;
/**
@ -127,6 +128,8 @@ class Pet
return $this->id;
}
/**
* Sets id.
*
@ -151,6 +154,8 @@ class Pet
return $this->category;
}
/**
* Sets category.
*
@ -175,6 +180,8 @@ class Pet
return $this->name;
}
/**
* Sets name.
*
@ -199,6 +206,8 @@ class Pet
return $this->photoUrls;
}
/**
* Sets photoUrls.
*
@ -223,6 +232,8 @@ class Pet
return $this->tags;
}
/**
* Sets tags.
*
@ -247,6 +258,8 @@ class Pet
return $this->status;
}
/**
* Sets status.
*

View File

@ -31,6 +31,7 @@ namespace OpenAPI\Server\Model;
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\Accessor;
use JMS\Serializer\Annotation\SerializedName;
/**
@ -82,6 +83,8 @@ class Tag
return $this->id;
}
/**
* Sets id.
*
@ -106,6 +109,8 @@ class Tag
return $this->name;
}
/**
* Sets name.
*

View File

@ -31,6 +31,7 @@ namespace OpenAPI\Server\Model;
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\Accessor;
use JMS\Serializer\Annotation\SerializedName;
/**
@ -138,6 +139,8 @@ class User
return $this->id;
}
/**
* Sets id.
*
@ -162,6 +165,8 @@ class User
return $this->username;
}
/**
* Sets username.
*
@ -186,6 +191,8 @@ class User
return $this->firstName;
}
/**
* Sets firstName.
*
@ -210,6 +217,8 @@ class User
return $this->lastName;
}
/**
* Sets lastName.
*
@ -234,6 +243,8 @@ class User
return $this->email;
}
/**
* Sets email.
*
@ -258,6 +269,8 @@ class User
return $this->password;
}
/**
* Sets password.
*
@ -282,6 +295,8 @@ class User
return $this->phone;
}
/**
* Sets phone.
*
@ -306,6 +321,8 @@ class User
return $this->userStatus;
}
/**
* Sets userStatus.
*

View File

@ -60,7 +60,7 @@ class JmsSerializer implements SerializerInterface
private function deserializeString($data, string $type)
{
// Figure out if we have an array format
if (1 === preg_match('/array<(csv|ssv|tsv|pipes),(int|string)>/i', $type, $matches)) {
if (1 === preg_match('/array<(csv|ssv|tsv|pipes),(.*)>/i', $type, $matches)) {
return $this->deserializeArrayString($matches[1], $matches[2], $data);
}
@ -104,7 +104,21 @@ class JmsSerializer implements SerializerInterface
case '\DateTime':
return is_null($data) ? null :new DateTime($data);
default:
throw new RuntimeException(sprintf("Type %s is unsupported", $type));
if (!class_exists($type)) {
throw new RuntimeException(sprintf("Type %s is unsupported", $type));
}
$reflectionClass = new \ReflectionClass($type);
if (!$reflectionClass->implementsInterface('\BackedENum')) {
throw new RuntimeException(sprintf("Type %s is unsupported", $type));
}
$enum = $type::tryFrom($data);
if (!$enum) {
throw new RuntimeException(sprintf("Unknown %s value in %s enum", $data, $type));
}
return $enum;
}
// If we end up here, just return data

View File

@ -27,8 +27,9 @@
* Please update the test case below to test the model.
*/
namespace OpenAPI\Server\Model;
namespace OpenAPI\Server\Tests\Model;
use OpenAPI\Server\Model\EnumStringModel;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@ -58,7 +59,6 @@ class EnumStringModelTest extends TestCase
*/
public function setUp(): void
{
$this->object = $this->getMockBuilder(EnumStringModel::class)->getMockForAbstractClass();
}
/**
@ -81,7 +81,6 @@ class EnumStringModelTest extends TestCase
*/
public function testTestClassExists(): void
{
$this->assertTrue(class_exists(EnumStringModel::class));
$this->assertInstanceOf(EnumStringModel::class, $this->object);
$this->assertTrue(enum_exists(EnumStringModel::class));
}
}