diff --git a/modules/openapi-generator/src/main/resources/php-nextgen/model_generic.mustache b/modules/openapi-generator/src/main/resources/php-nextgen/model_generic.mustache index 6d6b6ed44138..ddb488c503a0 100644 --- a/modules/openapi-generator/src/main/resources/php-nextgen/model_generic.mustache +++ b/modules/openapi-generator/src/main/resources/php-nextgen/model_generic.mustache @@ -176,17 +176,17 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}}{{/parentSchema}}{{^par public const {{#lambda.uppercase}}{{discriminator.propertyName}}_{{#lambda.snakecase}}{{mappingName}}{{/lambda.snakecase}}{{/lambda.uppercase}} = '{{mappingName}}'; {{/discriminator.mappedModels}} {{/discriminator}} -{{^discriminator}} {{#vars}} {{#isEnum}} + {{^isDiscriminator}} {{#allowableValues}} {{#enumVars}} public const {{enumName}}_{{{name}}} = {{{value}}}; {{/enumVars}} {{/allowableValues}} + {{/isDiscriminator}} {{/isEnum}} {{/vars}} -{{/discriminator}} {{#vars}} {{#isEnum}} @@ -198,15 +198,15 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}}{{/parentSchema}}{{^par public static function {{getter}}AllowableValues() { return [ -{{#discriminator}} +{{#isDiscriminator}} {{#discriminator.mappedModels}} self::{{#lambda.uppercase}}{{discriminator.propertyName}}_{{#lambda.snakecase}}{{mappingName}}{{/lambda.snakecase}}{{/lambda.uppercase}},{{^-last}} {{/-last}}{{/discriminator.mappedModels}} -{{/discriminator}} -{{^discriminator}} +{{/isDiscriminator}} +{{^isDiscriminator}} {{#allowableValues}}{{#enumVars}}self::{{enumName}}_{{{name}}},{{^-last}} {{/-last}}{{/enumVars}}{{/allowableValues}} -{{/discriminator}} +{{/isDiscriminator}} ]; } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/php/PhpNextgenClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/php/PhpNextgenClientCodegenTest.java index 88ad980ac167..edbd3894dfa2 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/php/PhpNextgenClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/php/PhpNextgenClientCodegenTest.java @@ -187,6 +187,110 @@ public void testEnumUnknownDefaultCaseDeserializationDisabled() throws Exception Assert.assertListContains(modelContent, a -> a.equalsIgnoreCase("\"Invalid value '%s' for 'color', must be one of '%s'\","), ""); } + @Test + public void testOneOfDiscriminatorEnumGeneration() throws Exception { + File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); + output.deleteOnExit(); + + OpenAPI openAPI = new OpenAPIParser() + .readLocation("src/test/resources/bugs/issue_23813.yaml", null, new ParseOptions()).getOpenAPI(); + + codegen.setOutputDir(output.getAbsolutePath()); + + ClientOptInput input = new ClientOptInput() + .openAPI(openAPI) + .config(codegen); + + DefaultGenerator generator = new DefaultGenerator(); + Map files = generator.opts(input).generate().stream() + .collect(Collectors.toMap(File::getName, Function.identity())); + + Assert.assertNotNull(files.get("PetAnimal.php")); + + List combinedModelContent = Files + .readAllLines(files.get("PetAnimal.php").toPath()) + .stream() + .map(String::trim) + .collect(Collectors.toList()); + int styleAllowableValuesStart = combinedModelContent.indexOf("public static function getStyleAllowableValues()"); + Assert.assertTrue(styleAllowableValuesStart >= 0, + "Expected combined oneOf wrapper to declare getStyleAllowableValues"); + int styleAllowableValuesEnd = combinedModelContent.subList(styleAllowableValuesStart, combinedModelContent.size()).indexOf("];"); + Assert.assertTrue(styleAllowableValuesEnd >= 0, + "Expected combined oneOf wrapper to close the style allowable-values array"); + List styleAllowableValuesContent = combinedModelContent.subList( + styleAllowableValuesStart, + styleAllowableValuesStart + styleAllowableValuesEnd + 1); + Assert.assertListContains(combinedModelContent, + a -> a.equals("public const STYLE_PAGE = 'page';"), + "Expected combined oneOf wrapper to declare STYLE_PAGE constant"); + Assert.assertListContains(combinedModelContent, + a -> a.equals("public const STYLE_TEXT = 'text';"), + "Expected combined oneOf wrapper to declare STYLE_TEXT constant"); + Assert.assertListContains(combinedModelContent, + a -> a.equals("public const STYLE_VIEWPORT = 'viewport';"), + "Expected combined oneOf wrapper to declare STYLE_VIEWPORT constant"); + Assert.assertListContains(styleAllowableValuesContent, + a -> a.equals("self::STYLE_PAGE,"), + "Expected combined oneOf wrapper to use style enum values"); + Assert.assertListContains(styleAllowableValuesContent, + a -> a.equals("self::STYLE_TEXT,"), + "Expected combined oneOf wrapper to use style enum values"); + Assert.assertListContains(styleAllowableValuesContent, + a -> a.equals("self::STYLE_VIEWPORT,"), + "Expected combined oneOf wrapper to use style enum values"); + Assert.assertListNotContains(styleAllowableValuesContent, + a -> a.equals("self::TYPE_PET_DOG,"), + "Combined oneOf wrapper should not use type enum values for style"); + Assert.assertListNotContains(styleAllowableValuesContent, + a -> a.equals("self::TYPE_PET_CAT,"), + "Combined oneOf wrapper should not use type enum values for style"); + } + + @Test + public void testDiscriminatorConstantsPreservedForNonEnumDiscriminatorModels() throws Exception { + File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); + output.deleteOnExit(); + + OpenAPI openAPI = new OpenAPIParser() + .readLocation("src/test/resources/3_0/php-nextgen/petstore-with-fake-endpoints-models-for-testing.yaml", null, new ParseOptions()) + .getOpenAPI(); + + codegen.setOutputDir(output.getAbsolutePath()); + + ClientOptInput input = new ClientOptInput() + .openAPI(openAPI) + .config(codegen); + + DefaultGenerator generator = new DefaultGenerator(); + Map files = generator.opts(input).generate().stream() + .collect(Collectors.toMap(File::getName, Function.identity())); + + Assert.assertNotNull(files.get("Animal.php")); + Assert.assertNotNull(files.get("DiscriminatorBase.php")); + + List animalModelContent = Files + .readAllLines(files.get("Animal.php").toPath()) + .stream() + .map(String::trim) + .collect(Collectors.toList()); + Assert.assertListContains(animalModelContent, + a -> a.equals("public const CLASS_NAME_DOG = 'DOG';"), + "Expected Animal to preserve discriminator constant CLASS_NAME_DOG"); + Assert.assertListContains(animalModelContent, + a -> a.equals("public const CLASS_NAME_CAT = 'CAT';"), + "Expected Animal to preserve discriminator constant CLASS_NAME_CAT"); + + List discriminatorBaseModelContent = Files + .readAllLines(files.get("DiscriminatorBase.php").toPath()) + .stream() + .map(String::trim) + .collect(Collectors.toList()); + Assert.assertListContains(discriminatorBaseModelContent, + a -> a.equals("public const TYPE_DISCRIMINATOR_CHILD = 'DiscriminatorChild';"), + "Expected DiscriminatorBase to preserve inferred discriminator constants"); + } + @Test public void testDifferentResponseSchemasWithEmpty() throws IOException { File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); diff --git a/modules/openapi-generator/src/test/resources/bugs/issue_23813.yaml b/modules/openapi-generator/src/test/resources/bugs/issue_23813.yaml new file mode 100644 index 000000000000..62ceb3d61984 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/bugs/issue_23813.yaml @@ -0,0 +1,53 @@ +openapi: 3.0.0 +info: + title: php-nextgen oneOf discriminator enum bug + version: 1.0.0 + +components: + schemas: + Pet: + type: object + properties: + id: + type: string + minLength: 1 + animal: + oneOf: + - $ref: '#/components/schemas/Dog' + - $ref: '#/components/schemas/Cat' + discriminator: + propertyName: type + mapping: + pet-dog: '#/components/schemas/Dog' + pet-cat: '#/components/schemas/Cat' + Dog: + type: object + properties: + type: + type: string + enum: ["pet-dog"] + default: "pet-dog" + imageId: + type: string + required: + - type + - imageId + Cat: + type: object + properties: + type: + type: string + enum: ["pet-cat"] + default: "pet-cat" + imageId: + type: string + style: + type: string + enum: + - "page" + - "text" + - "viewport" + required: + - type + - imageId + - style