mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-07-03 06:00:52 +00:00
[PHP][Symfony] Generate valid PHP code (#6578)
Fixes #5985 We were experiencing syntax issues when generating the Petstore example. See some of the examples below: StoreApiInterface.php namespace Swagger\Server\Api; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Swagger\Server\Model\Order; **use maparray<string,int>;** use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; UserApiInterface.php public function createUsersWithArrayInput(**User[]** $body); public function createUsersWithListInput(User[] $body); As far as I know, it is not possible to use array of objects in this way. PetApiInterface.php namespace Swagger\Server\Api; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Swagger\Server\Model\Pet; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; use Swagger\Server\Model\ApiResponse; **use string[];** use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; public function findPetsByStatus(string[] $status); public function findPetsByTags(string[] $tags);
This commit is contained in:
parent
b716b378c4
commit
5ffdee4479
@ -19,6 +19,7 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
|
||||
public static final String BUNDLE_NAME = "bundleName";
|
||||
public static final String COMPOSER_VENDOR_NAME = "composerVendorName";
|
||||
public static final String COMPOSER_PROJECT_NAME = "composerProjectName";
|
||||
public static final String PHP_LEGACY_SUPPORT = "phpLegacySupport";
|
||||
public static final Map<String, String> SYMFONY_EXCEPTIONS;
|
||||
protected String testsPackage;
|
||||
protected String apiTestsPackage;
|
||||
@ -32,6 +33,9 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
|
||||
protected String bundleAlias;
|
||||
protected String controllerDirName = "Controller";
|
||||
protected String controllerPackage;
|
||||
protected Boolean phpLegacySupport = Boolean.TRUE;
|
||||
|
||||
protected HashSet<String> typeHintable;
|
||||
|
||||
static {
|
||||
SYMFONY_EXCEPTIONS = new HashMap<>();
|
||||
@ -74,36 +78,44 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
|
||||
embeddedTemplateDir = templateDir = "php-symfony";
|
||||
|
||||
setReservedWordsLowerCase(
|
||||
Arrays.asList(
|
||||
// local variables used in api methods (endpoints)
|
||||
"resourcePath", "httpBody", "queryParams", "headerParams",
|
||||
"formParams", "_header_accept", "_tempBody",
|
||||
Arrays.asList(
|
||||
// local variables used in api methods (endpoints)
|
||||
"resourcePath", "httpBody", "queryParams", "headerParams",
|
||||
"formParams", "_header_accept", "_tempBody",
|
||||
|
||||
// PHP reserved words
|
||||
"__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor")
|
||||
// PHP reserved words
|
||||
"__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor"
|
||||
)
|
||||
);
|
||||
|
||||
// ref: http://php.net/manual/en/language.types.intro.php
|
||||
languageSpecificPrimitives = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"bool",
|
||||
"boolean",
|
||||
"int",
|
||||
"integer",
|
||||
"double",
|
||||
"float",
|
||||
"string",
|
||||
"object",
|
||||
"DateTime",
|
||||
"mixed",
|
||||
"number",
|
||||
"void",
|
||||
"byte")
|
||||
Arrays.asList(
|
||||
"bool",
|
||||
"int",
|
||||
"double",
|
||||
"float",
|
||||
"string",
|
||||
"object",
|
||||
"mixed",
|
||||
"number",
|
||||
"void",
|
||||
"byte",
|
||||
"array"
|
||||
)
|
||||
);
|
||||
|
||||
instantiationTypes.put("array", "array");
|
||||
instantiationTypes.put("map", "map");
|
||||
//instantiationTypes.put("array", "array");
|
||||
//instantiationTypes.put("map", "map");
|
||||
|
||||
defaultIncludes = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"\\DateTime",
|
||||
"\\SplFileObject"
|
||||
)
|
||||
);
|
||||
|
||||
variableNamingConvention = "camelCase";
|
||||
|
||||
// provide primitives to mustache template
|
||||
List sortedLanguageSpecificPrimitives= new ArrayList(languageSpecificPrimitives);
|
||||
@ -124,7 +136,7 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
|
||||
typeMapping.put("Date", "\\DateTime");
|
||||
typeMapping.put("DateTime", "\\DateTime");
|
||||
typeMapping.put("file", "\\SplFileObject");
|
||||
typeMapping.put("map", "map");
|
||||
typeMapping.put("map", "array");
|
||||
typeMapping.put("array", "array");
|
||||
typeMapping.put("list", "array");
|
||||
typeMapping.put("object", "object");
|
||||
@ -137,6 +149,7 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
|
||||
cliOptions.add(new CliOption(COMPOSER_PROJECT_NAME, "The project name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. petstore-client. IMPORTANT NOTE (2016/03): composerProjectName will be deprecated and replaced by gitRepoId in the next swagger-codegen release"));
|
||||
cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "hides the timestamp when files were generated")
|
||||
.defaultValue(Boolean.TRUE.toString()));
|
||||
cliOptions.add(new CliOption(PHP_LEGACY_SUPPORT, "Should the generated code be compatible with PHP 5.x?").defaultValue(Boolean.TRUE.toString()));
|
||||
}
|
||||
|
||||
public String getBundleName() {
|
||||
@ -150,6 +163,9 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
|
||||
this.bundleAlias = snakeCase(bundleName).replaceAll("([A-Z]+)", "\\_$1").toLowerCase();
|
||||
}
|
||||
|
||||
public void setPhpLegacySupport(Boolean support) {
|
||||
this.phpLegacySupport = support;
|
||||
}
|
||||
|
||||
public String controllerFileFolder() {
|
||||
return (outputFolder + File.separator + toPackagePath(controllerPackage, srcBasePath));
|
||||
@ -218,6 +234,12 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
|
||||
additionalProperties.put(COMPOSER_VENDOR_NAME, composerVendorName);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(PHP_LEGACY_SUPPORT)) {
|
||||
this.setPhpLegacySupport(Boolean.valueOf((String) additionalProperties.get(PHP_LEGACY_SUPPORT)));
|
||||
} else {
|
||||
additionalProperties.put(PHP_LEGACY_SUPPORT, phpLegacySupport);
|
||||
}
|
||||
|
||||
additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\"));
|
||||
additionalProperties.put("controllerPackage", controllerPackage);
|
||||
additionalProperties.put("apiTestsPackage", apiTestsPackage);
|
||||
@ -264,26 +286,48 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
|
||||
supportingFiles.add(new SupportingFile(".travis.yml", getPackagePath(), ".travis.yml"));
|
||||
supportingFiles.add(new SupportingFile(".php_cs", getPackagePath(), ".php_cs"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", getPackagePath(), "git_push.sh"));
|
||||
|
||||
// Type-hintable primitive types
|
||||
// ref: http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration
|
||||
if (phpLegacySupport) {
|
||||
typeHintable = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"array"
|
||||
)
|
||||
);
|
||||
} else {
|
||||
typeHintable = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"array",
|
||||
"bool",
|
||||
"float",
|
||||
"int",
|
||||
"string"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||
objs = super.postProcessOperations(objs);
|
||||
|
||||
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
|
||||
operations.put("controllerName", toControllerName((String) operations.get("pathPrefix")));
|
||||
operations.put("symfonyService", toSymfonyService((String) operations.get("pathPrefix")));
|
||||
|
||||
HashSet<CodegenSecurity> authMethods = new HashSet<>();
|
||||
HashSet<String> imports = new HashSet<>();
|
||||
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
|
||||
|
||||
for (CodegenOperation op : operationList) {
|
||||
// Loop through all input parameters to determine, whether we have to import something to
|
||||
// make the input type available.
|
||||
for (CodegenParameter param : op.allParams) {
|
||||
final String simpleName = extractSimpleName(param.dataType);
|
||||
param.vendorExtensions.put("x-simpleName", simpleName);
|
||||
final boolean isScalarType = typeMapping.containsValue(param.dataType);
|
||||
param.vendorExtensions.put("x-parameterType", isScalarType ? null : simpleName);
|
||||
if (!isScalarType) {
|
||||
imports.add(param.dataType);
|
||||
// Determine if the paramter type is supported as a type hint and make it available
|
||||
// to the templating engine
|
||||
String typeHint = getTypeHint(param.dataType);
|
||||
if (!typeHint.isEmpty()) {
|
||||
param.vendorExtensions.put("x-parameterType", typeHint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -296,11 +340,9 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
|
||||
if (response.dataType != null) {
|
||||
final String dataType = extractSimpleName(response.dataType);
|
||||
response.vendorExtensions.put("x-simpleName", dataType);
|
||||
imports.add(response.dataType.replaceFirst("\\[\\]$", ""));
|
||||
}
|
||||
|
||||
if (exception != null) {
|
||||
imports.add(exception);
|
||||
// if (!typeMapping.containsValue(dataType)) {
|
||||
// imports.add(response.dataType.replaceFirst("\\[\\]$", ""));
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -310,7 +352,6 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
|
||||
}
|
||||
}
|
||||
|
||||
operations.put("imports", new ArrayList<>(imports));
|
||||
operations.put("authMethods", authMethods);
|
||||
|
||||
return objs;
|
||||
@ -397,13 +438,13 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
|
||||
if (p instanceof MapProperty) {
|
||||
MapProperty mp = (MapProperty) p;
|
||||
Property inner = mp.getAdditionalProperties();
|
||||
return getSwaggerType(p) + "array<string," + getTypeDeclaration(inner) + ">";
|
||||
return getTypeDeclaration(inner) + "[]";
|
||||
}
|
||||
|
||||
|
||||
if (p instanceof RefProperty) {
|
||||
return getTypeDeclaration(getPropertyTypeDeclaration(p));
|
||||
}
|
||||
|
||||
|
||||
return getPropertyTypeDeclaration(p);
|
||||
}
|
||||
|
||||
@ -429,6 +470,21 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
|
||||
return super.getTypeDeclaration(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the fully-qualified "Model" name for import
|
||||
*
|
||||
* @param name the name of the "Model"
|
||||
* @return the fully-qualified "Model" name for import
|
||||
*/
|
||||
@Override
|
||||
public String toModelImport(String name) {
|
||||
if ("".equals(modelPackage())) {
|
||||
return name;
|
||||
} else {
|
||||
return modelPackage() + "\\" + name;
|
||||
}
|
||||
}
|
||||
|
||||
public String toApiName(String name) {
|
||||
if (name.isEmpty()) {
|
||||
return "DefaultApiInterface";
|
||||
@ -451,4 +507,34 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
|
||||
|
||||
return prefix + name;
|
||||
}
|
||||
|
||||
protected String getTypeHint(String type) {
|
||||
// Type hint array types
|
||||
if (type.endsWith("[]")) {
|
||||
return "array";
|
||||
}
|
||||
|
||||
// Check if the type is a native type that is type hintable in PHP
|
||||
if (typeHintable.contains(type)) {
|
||||
return type;
|
||||
}
|
||||
|
||||
// Default includes are referenced by their fully-qualified class name (including namespace)
|
||||
if (defaultIncludes.contains(type)) {
|
||||
return type;
|
||||
}
|
||||
|
||||
// Model classes are assumed to be imported and we reference them by their class name
|
||||
if (isModelClass(type)) {
|
||||
// This parameter is an instance of a model
|
||||
return extractSimpleName(type);
|
||||
}
|
||||
|
||||
// PHP does not support type hinting for this parameter data type
|
||||
return "";
|
||||
}
|
||||
|
||||
protected Boolean isModelClass(String type) {
|
||||
return Boolean.valueOf(type.contains(modelPackage()));
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
namespace {{apiPackage}};
|
||||
|
||||
{{#operations}}{{#imports}}use {{this}};
|
||||
{{#operations}}{{#imports}}use {{import}};
|
||||
{{/imports}}
|
||||
|
||||
/**
|
||||
@ -56,7 +56,7 @@ interface {{classname}}
|
||||
*
|
||||
{{/description}}
|
||||
{{#allParams}}
|
||||
* @param {{vendorExtensions.x-simpleName}} ${{paramName}} {{description}} {{#required}}(required){{/required}}{{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}
|
||||
* @param {{dataType}} ${{paramName}} {{description}} {{#required}}(required){{/required}}{{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}
|
||||
{{/allParams}}
|
||||
*
|
||||
{{#responses}}
|
||||
@ -64,7 +64,7 @@ interface {{classname}}
|
||||
* @throws {{vendorExtensions.x-symfonyExceptionSimple}} {{message}}
|
||||
{{/vendorExtensions.x-symfonyExceptionSimple}}
|
||||
{{^vendorExtensions.x-symfonyExceptionSimple}}
|
||||
* @return {{^dataType}}void{{/dataType}}{{#dataType}}{{vendorExtensions.x-simpleName}}{{/dataType}} {{message}}
|
||||
* @return {{^dataType}}void{{/dataType}}{{#dataType}}{{dataType}}{{/dataType}} {{message}}
|
||||
*
|
||||
{{/vendorExtensions.x-symfonyExceptionSimple}}
|
||||
{{/responses}}
|
||||
|
@ -24,7 +24,7 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use {{apiPackage}}\{{classname}};
|
||||
{{#imports}}use {{this}};
|
||||
{{#imports}}use {{import}};
|
||||
{{/imports}}
|
||||
|
||||
/**
|
||||
@ -179,11 +179,9 @@ class {{controllerName}} extends Controller
|
||||
return new Response('', 204);
|
||||
{{/returnType}}
|
||||
{{#responses}}
|
||||
{{#vendorExtensions.x-symfonyExceptionSimple}}
|
||||
} catch ({{vendorExtensions.x-symfonyExceptionSimple}} $exception) {
|
||||
} catch (HttpException $exception) {
|
||||
// {{message}}
|
||||
return $this->createErrorResponse($exception);
|
||||
{{/vendorExtensions.x-symfonyExceptionSimple}}
|
||||
{{/responses}}
|
||||
} catch (Exception $fallthrough) {
|
||||
return $this->createErrorResponse(new HttpException(500, 'An unsuspected error occurred.', $fallthrough));
|
||||
|
@ -20,9 +20,8 @@
|
||||
*/
|
||||
|
||||
namespace {{modelPackage}};
|
||||
{{^isEnum}}
|
||||
|
||||
use \ArrayAccess;
|
||||
{{^isEnum}}
|
||||
{{#useStatements}}use {{this}};
|
||||
{{/useStatements}}
|
||||
{{/isEnum}}
|
||||
|
@ -1,4 +1,4 @@
|
||||
class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}implements ModelInterface, ArrayAccess
|
||||
class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}implements ModelInterface, \ArrayAccess
|
||||
{
|
||||
const DISCRIMINATOR = {{#discriminator}}'{{discriminator}}'{{/discriminator}}{{^discriminator}}null{{/discriminator}};
|
||||
|
||||
|
@ -49,6 +49,7 @@ public class SymfonyServerOptionsProvider implements OptionsProvider {
|
||||
.put(CodegenConstants.ARTIFACT_VERSION, ARTIFACT_VERSION_VALUE)
|
||||
.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "true")
|
||||
.put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE)
|
||||
.put(SymfonyServerCodegen.PHP_LEGACY_SUPPORT, "true")
|
||||
.build();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user