From efb98bcbc2f0e017badb7fc841fee1b7b9321c99 Mon Sep 17 00:00:00 2001 From: abcsun Date: Sat, 2 Jul 2016 19:01:29 +0800 Subject: [PATCH 1/7] add abstractPhpCodegen --- .../codegen/languages/AbstractPhpCodegen.java | 57 +++++++++++++++++++ .../codegen/languages/LumenServerCodegen.java | 3 +- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java new file mode 100644 index 00000000000..1a7a858a3b2 --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java @@ -0,0 +1,57 @@ +package io.swagger.codegen.languages; + +import io.swagger.codegen.CliOption; +import io.swagger.codegen.CodegenConfig; +import io.swagger.codegen.CodegenConstants; +import io.swagger.codegen.CodegenOperation; +import io.swagger.codegen.CodegenParameter; +import io.swagger.codegen.CodegenProperty; +import io.swagger.codegen.CodegenType; +import io.swagger.codegen.DefaultCodegen; +import io.swagger.codegen.SupportingFile; +import io.swagger.models.properties.*; + +import java.io.File; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.HashSet; +import java.util.regex.Matcher; + +import org.apache.commons.lang3.StringUtils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class AbstractPhpCodegen extends DefaultCodegen implements CodegenConfig { + // @SuppressWarnings("hiding") + // static Logger LOGGER = LoggerFactory.getLogger(AbstractPhpCodegen.class); + + // public static final String VARIABLE_NAMING_CONVENTION = "variableNamingConvention"; + // public static final String PACKAGE_PATH = "packagePath"; + // public static final String SRC_BASE_PATH = "srcBasePath"; + // public static final String COMPOSER_VENDOR_NAME = "composerVendorName"; + // public static final String COMPOSER_PROJECT_NAME = "composerProjectName"; + // protected String invokerPackage = "Swagger\\Client"; + // protected String composerVendorName = null; + // protected String composerProjectName = null; + // protected String packagePath = "SwaggerClient-php"; + // protected String artifactVersion = null; + // protected String srcBasePath = "lib"; + // protected String testBasePath = "test"; + // protected String docsBasePath = "docs"; + // protected String apiDirName = "Api"; + // protected String modelDirName = "Model"; + // protected String variableNamingConvention= "snake_case"; + // protected String apiDocPath = docsBasePath + "/" + apiDirName; + // protected String modelDocPath = docsBasePath + "/" + modelDirName; + + public AbstractPhpCodegen() { + super(); + + } + + + +} diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/LumenServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/LumenServerCodegen.java index 8ce97eb9dd8..d2b31c55025 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/LumenServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/LumenServerCodegen.java @@ -10,7 +10,8 @@ import java.util.Map; import java.util.TreeMap; -public class LumenServerCodegen extends DefaultCodegen implements CodegenConfig { +public class LumenServerCodegen extends AbstractPhpCodegen//DefaultCodegen implements CodegenConfig +{ // source folder where to write the files protected String sourceFolder = ""; From 3e5efb88dc4589638ef2a0a8de05a552e9a9fc9b Mon Sep 17 00:00:00 2001 From: abcsun Date: Wed, 6 Jul 2016 10:01:09 +0800 Subject: [PATCH 2/7] This base class should provide common functions to PHP-related generators so that the same enhancements or bug fixes can be applied to all clients. Most source be moved from the PhpClientCodegen. --- .../codegen/languages/AbstractPhpCodegen.java | 628 +++++++++++++++++- 1 file changed, 606 insertions(+), 22 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java index 1a7a858a3b2..b1124f7ca71 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java @@ -25,33 +25,617 @@ import org.slf4j.LoggerFactory; public abstract class AbstractPhpCodegen extends DefaultCodegen implements CodegenConfig { - // @SuppressWarnings("hiding") - // static Logger LOGGER = LoggerFactory.getLogger(AbstractPhpCodegen.class); - - // public static final String VARIABLE_NAMING_CONVENTION = "variableNamingConvention"; - // public static final String PACKAGE_PATH = "packagePath"; - // public static final String SRC_BASE_PATH = "srcBasePath"; - // public static final String COMPOSER_VENDOR_NAME = "composerVendorName"; - // public static final String COMPOSER_PROJECT_NAME = "composerProjectName"; - // protected String invokerPackage = "Swagger\\Client"; - // protected String composerVendorName = null; - // protected String composerProjectName = null; - // protected String packagePath = "SwaggerClient-php"; - // protected String artifactVersion = null; - // protected String srcBasePath = "lib"; - // protected String testBasePath = "test"; - // protected String docsBasePath = "docs"; - // protected String apiDirName = "Api"; - // protected String modelDirName = "Model"; - // protected String variableNamingConvention= "snake_case"; - // protected String apiDocPath = docsBasePath + "/" + apiDirName; - // protected String modelDocPath = docsBasePath + "/" + modelDirName; + + static Logger LOGGER = LoggerFactory.getLogger(AbstractPhpCodegen.class); + + public static final String VARIABLE_NAMING_CONVENTION = "variableNamingConvention"; + public static final String PACKAGE_PATH = "packagePath"; + public static final String SRC_BASE_PATH = "srcBasePath"; + public static final String COMPOSER_VENDOR_NAME = "composerVendorName"; + public static final String COMPOSER_PROJECT_NAME = "composerProjectName"; + protected String invokerPackage = "php"; + protected String composerVendorName = null; + protected String composerProjectName = null; + protected String packagePath = "php-base"; + protected String artifactVersion = null; + protected String srcBasePath = "lib"; + protected String testBasePath = "test"; + protected String docsBasePath = "docs"; + protected String apiDirName = "Api"; + protected String modelDirName = "Model"; + protected String variableNamingConvention= "snake_case"; + protected String apiDocPath = docsBasePath + "/" + apiDirName; + protected String modelDocPath = docsBasePath + "/" + modelDirName; public AbstractPhpCodegen() { super(); + modelTemplateFiles.put("model.mustache", ".php"); + apiTemplateFiles.put("api.mustache", ".php"); + apiTestTemplateFiles.put("api_test.mustache", ".php"); + modelDocTemplateFiles.put("model_doc.mustache", ".md"); + apiDocTemplateFiles.put("api_doc.mustache", ".md"); + + apiPackage = invokerPackage + "\\" + apiDirName; + modelPackage = invokerPackage + "\\" + modelDirName; + + setReservedWordsLowerCase( + 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") + ); + + // ref: http://php.net/manual/en/language.types.intro.php + languageSpecificPrimitives = new HashSet( + Arrays.asList( + "bool", + "boolean", + "int", + "integer", + "double", + "float", + "string", + "object", + "DateTime", + "mixed", + "number", + "void", + "byte") + ); + + instantiationTypes.put("array", "array"); + instantiationTypes.put("map", "map"); + + + // provide primitives to mustache template + String primitives = "'" + StringUtils.join(languageSpecificPrimitives, "', '") + "'"; + additionalProperties.put("primitives", primitives); + + // ref: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types + typeMapping = new HashMap(); + typeMapping.put("integer", "int"); + typeMapping.put("long", "int"); + typeMapping.put("number", "float"); + typeMapping.put("float", "float"); + typeMapping.put("double", "double"); + typeMapping.put("string", "string"); + typeMapping.put("byte", "int"); + typeMapping.put("boolean", "bool"); + typeMapping.put("Date", "\\DateTime"); + typeMapping.put("DateTime", "\\DateTime"); + typeMapping.put("file", "\\SplFileObject"); + typeMapping.put("map", "map"); + typeMapping.put("array", "array"); + typeMapping.put("list", "array"); + typeMapping.put("object", "object"); + typeMapping.put("binary", "string"); + typeMapping.put("ByteArray", "string"); + typeMapping.put("UUID", "string"); + + cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC)); + cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC)); + cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC)); + cliOptions.add(new CliOption(VARIABLE_NAMING_CONVENTION, "naming convention of variable name, e.g. camelCase.") + .defaultValue("snake_case")); + cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, "The main namespace to use for all classes. e.g. Yay\\Pets")); + cliOptions.add(new CliOption(PACKAGE_PATH, "The main package name for classes. e.g. GeneratedPetstore")); + cliOptions.add(new CliOption(SRC_BASE_PATH, "The directory under packagePath to serve as source root.")); + cliOptions.add(new CliOption(COMPOSER_VENDOR_NAME, "The vendor name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. yaypets. IMPORTANT NOTE (2016/03): composerVendorName will be deprecated and replaced by gitUserId in the next swagger-codegen release")); + cliOptions.add(new CliOption(CodegenConstants.GIT_USER_ID, CodegenConstants.GIT_USER_ID_DESC)); + 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.GIT_REPO_ID, CodegenConstants.GIT_REPO_ID_DESC)); + cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, "The version to use in the composer package version field. e.g. 1.2.3")); } - + @Override + public void processOpts() { + super.processOpts(); + + if (additionalProperties.containsKey(PACKAGE_PATH)) { + this.setPackagePath((String) additionalProperties.get(PACKAGE_PATH)); + } else { + additionalProperties.put(PACKAGE_PATH, packagePath); + } + + if (additionalProperties.containsKey(SRC_BASE_PATH)) { + this.setSrcBasePath((String) additionalProperties.get(SRC_BASE_PATH)); + } else { + additionalProperties.put(SRC_BASE_PATH, srcBasePath); + } + + if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) { + this.setInvokerPackage((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE)); + } else { + additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); + } + + if (!additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) { + additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage); + } + + if (!additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) { + additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); + } + + if (additionalProperties.containsKey(COMPOSER_PROJECT_NAME)) { + this.setComposerProjectName((String) additionalProperties.get(COMPOSER_PROJECT_NAME)); + } else { + additionalProperties.put(COMPOSER_PROJECT_NAME, composerProjectName); + } + + if (additionalProperties.containsKey(CodegenConstants.GIT_USER_ID)) { + this.setGitUserId((String) additionalProperties.get(CodegenConstants.GIT_USER_ID)); + } else { + additionalProperties.put(CodegenConstants.GIT_USER_ID, gitUserId); + } + + if (additionalProperties.containsKey(COMPOSER_VENDOR_NAME)) { + this.setComposerVendorName((String) additionalProperties.get(COMPOSER_VENDOR_NAME)); + } else { + additionalProperties.put(COMPOSER_VENDOR_NAME, composerVendorName); + } + + if (additionalProperties.containsKey(CodegenConstants.GIT_REPO_ID)) { + this.setGitRepoId((String) additionalProperties.get(CodegenConstants.GIT_REPO_ID)); + } else { + additionalProperties.put(CodegenConstants.GIT_REPO_ID, gitRepoId); + } + + if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_VERSION)) { + this.setArtifactVersion((String) additionalProperties.get(CodegenConstants.ARTIFACT_VERSION)); + } else { + additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); + } + + if (additionalProperties.containsKey(VARIABLE_NAMING_CONVENTION)) { + this.setParameterNamingConvention((String) additionalProperties.get(VARIABLE_NAMING_CONVENTION)); + } + + // additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\")); + + // // make api and model doc path available in mustache template + // additionalProperties.put("apiDocPath", apiDocPath); + // additionalProperties.put("modelDocPath", modelDocPath); + + // // make test path available in mustache template + // additionalProperties.put("testBasePath", testBasePath); + + // // apache v2 license + // supportingFiles.add(new SupportingFile("LICENSE", getPackagePath(), "LICENSE")); + } + + public String getPackagePath() { + return packagePath; + } + + public String toPackagePath(String packageName, String basePath) { + packageName = packageName.replace(invokerPackage, ""); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. + if (basePath != null && basePath.length() > 0) { + basePath = basePath.replaceAll("[\\\\/]?$", "") + File.separatorChar; // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. + } + + String regFirstPathSeparator; + if ("/".equals(File.separator)) { // for mac, linux + regFirstPathSeparator = "^/"; + } else { // for windows + regFirstPathSeparator = "^\\\\"; + } + + String regLastPathSeparator; + if ("/".equals(File.separator)) { // for mac, linux + regLastPathSeparator = "/$"; + } else { // for windows + regLastPathSeparator = "\\\\$"; + } + + return (getPackagePath() + File.separatorChar + basePath + // Replace period, backslash, forward slash with file separator in package name + + packageName.replaceAll("[\\.\\\\/]", Matcher.quoteReplacement(File.separator)) + // Trim prefix file separators from package path + .replaceAll(regFirstPathSeparator, "")) + // Trim trailing file separators from the overall path + .replaceAll(regLastPathSeparator+ "$", ""); + } + + @Override + public String escapeReservedWord(String name) { + return "_" + name; + } + + @Override + public String apiFileFolder() { + return (outputFolder + "/" + toPackagePath(apiPackage, srcBasePath)); + } + + @Override + public String modelFileFolder() { + return (outputFolder + "/" + toPackagePath(modelPackage, srcBasePath)); + } + + @Override + public String apiTestFileFolder() { + return (outputFolder + "/" + getPackagePath() + "/" + testBasePath + "/" + apiDirName); + } + + @Override + public String modelTestFileFolder() { + return (outputFolder + "/" + getPackagePath() + "/" + testBasePath + "/" + modelDirName); + } + + @Override + public String apiDocFileFolder() { + return (outputFolder + "/" + getPackagePath() + "/" + apiDocPath); + } + + @Override + public String modelDocFileFolder() { + return (outputFolder + "/" + getPackagePath() + "/" + modelDocPath); + } + + @Override + public String toModelDocFilename(String name) { + return toModelName(name); + } + + @Override + public String toApiDocFilename(String name) { + return toApiName(name); + } + + @Override + public String getTypeDeclaration(Property p) { + if (p instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) p; + Property inner = ap.getItems(); + return getTypeDeclaration(inner) + "[]"; + } else if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + return getSwaggerType(p) + "[string," + getTypeDeclaration(inner) + "]"; + } else if (p instanceof RefProperty) { + String type = super.getTypeDeclaration(p); + return (!languageSpecificPrimitives.contains(type)) + ? "\\" + modelPackage + "\\" + type : type; + } + return super.getTypeDeclaration(p); + } + + @Override + public String getTypeDeclaration(String name) { + if (!languageSpecificPrimitives.contains(name)) { + return "\\" + modelPackage + "\\" + name; + } + return super.getTypeDeclaration(name); + } + + @Override + public String getSwaggerType(Property p) { + String swaggerType = super.getSwaggerType(p); + String type = null; + if (typeMapping.containsKey(swaggerType)) { + type = typeMapping.get(swaggerType); + if (languageSpecificPrimitives.contains(type)) { + return type; + } else if (instantiationTypes.containsKey(type)) { + return type; + } + } else { + type = swaggerType; + } + if (type == null) { + return null; + } + return toModelName(type); + } + + public void setInvokerPackage(String invokerPackage) { + this.invokerPackage = invokerPackage; + } + + public void setArtifactVersion(String artifactVersion) { + this.artifactVersion = artifactVersion; + } + public void setPackagePath(String packagePath) { + this.packagePath = packagePath; + } + + public void setSrcBasePath(String srcBasePath) { + this.srcBasePath = srcBasePath; + } + + public void setParameterNamingConvention(String variableNamingConvention) { + this.variableNamingConvention = variableNamingConvention; + } + + public void setComposerVendorName(String composerVendorName) { + this.composerVendorName = composerVendorName; + } + + public void setComposerProjectName(String composerProjectName) { + this.composerProjectName = composerProjectName; + } + + @Override + public String toVarName(String name) { + // sanitize name + name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. + + if ("camelCase".equals(variableNamingConvention)) { + // return the name in camelCase style + // phone_number => phoneNumber + name = camelize(name, true); + } else { // default to snake case + // return the name in underscore style + // PhoneNumber => phone_number + name = underscore(name); + } + + // parameter name starting with number won't compile + // need to escape it by appending _ at the beginning + if (name.matches("^\\d.*")) { + name = "_" + name; + } + + return name; + } + + @Override + public String toParamName(String name) { + // should be the same as variable name + return toVarName(name); + } + + @Override + public String toModelName(String name) { + // remove [ + name = name.replaceAll("\\]", ""); + + // Note: backslash ("\\") is allowed for e.g. "\\DateTime" + name = name.replaceAll("[^\\w\\\\]+", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. + + // remove dollar sign + name = name.replaceAll("$", ""); + + // model name cannot use reserved keyword + if (isReservedWord(name)) { + LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + name)); + name = "model_" + name; // e.g. return => ModelReturn (after camelize) + } + + // model name starts with number + if (name.matches("^\\d.*")) { + LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name)); + name = "model_" + name; // e.g. 200Response => Model200Response (after camelize) + } + + // add prefix and/or suffic only if name does not start wth \ (e.g. \DateTime) + if (!name.matches("^\\\\.*")) { + name = modelNamePrefix + name + modelNameSuffix; + } + + // camelize the model name + // phone_number => PhoneNumber + return camelize(name); + } + + @Override + public String toModelFilename(String name) { + // should be the same as the model name + return toModelName(name); + } + + @Override + public String toModelTestFilename(String name) { + // should be the same as the model name + return toModelName(name) + "Test"; + } + + @Override + public String toOperationId(String operationId) { + // throw exception if method name is empty + if (StringUtils.isEmpty(operationId)) { + throw new RuntimeException("Empty method name (operationId) not allowed"); + } + + // method name cannot use reserved keyword, e.g. return + if (isReservedWord(operationId)) { + LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + camelize(sanitizeName("call_" + operationId), true)); + operationId = "call_" + operationId; + } + + return camelize(sanitizeName(operationId), true); + } + + /** + * Return the default value of the property + * + * @param p Swagger property object + * @return string presentation of the default value of the property + */ + @Override + public String toDefaultValue(Property p) { + if (p instanceof StringProperty) { + StringProperty dp = (StringProperty) p; + if (dp.getDefault() != null) { + return "'" + dp.getDefault().toString() + "'"; + } + } else if (p instanceof BooleanProperty) { + BooleanProperty dp = (BooleanProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + } else if (p instanceof DateProperty) { + // TODO + } else if (p instanceof DateTimeProperty) { + // TODO + } else if (p instanceof DoubleProperty) { + DoubleProperty dp = (DoubleProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + } else if (p instanceof FloatProperty) { + FloatProperty dp = (FloatProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + } else if (p instanceof IntegerProperty) { + IntegerProperty dp = (IntegerProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + } else if (p instanceof LongProperty) { + LongProperty dp = (LongProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + } + + return null; + } + + @Override + public void setParameterExampleValue(CodegenParameter p) { + String example; + + if (p.defaultValue == null) { + example = p.example; + } else { + example = p.defaultValue; + } + + String type = p.baseType; + if (type == null) { + type = p.dataType; + } + + if ("String".equalsIgnoreCase(type)) { + if (example == null) { + example = p.paramName + "_example"; + } + example = "\"" + escapeText(example) + "\""; + } else if ("Integer".equals(type) || "int".equals(type)) { + if (example == null) { + example = "56"; + } + } else if ("Float".equalsIgnoreCase(type) || "Double".equalsIgnoreCase(type)) { + if (example == null) { + example = "3.4"; + } + } else if ("BOOLEAN".equalsIgnoreCase(type) || "bool".equalsIgnoreCase(type)) { + if (example == null) { + example = "True"; + } + } else if ("\\SplFileObject".equalsIgnoreCase(type)) { + if (example == null) { + example = "/path/to/file"; + } + example = "\"" + escapeText(example) + "\""; + } else if ("Date".equalsIgnoreCase(type)) { + if (example == null) { + example = "2013-10-20"; + } + example = "new \\DateTime(\"" + escapeText(example) + "\")"; + } else if ("DateTime".equalsIgnoreCase(type)) { + if (example == null) { + example = "2013-10-20T19:20:30+01:00"; + } + example = "new \\DateTime(\"" + escapeText(example) + "\")"; + } else if (!languageSpecificPrimitives.contains(type)) { + // type is a model class, e.g. User + example = "new " + type + "()"; + } else { + LOGGER.warn("Type " + type + " not handled properly in setParameterExampleValue"); + } + + if (example == null) { + example = "NULL"; + } else if (Boolean.TRUE.equals(p.isListContainer)) { + example = "array(" + example + ")"; + } else if (Boolean.TRUE.equals(p.isMapContainer)) { + example = "array('key' => " + example + ")"; + } + + p.example = example; + } + + @Override + public String toEnumValue(String value, String datatype) { + if ("int".equals(datatype) || "double".equals(datatype) || "float".equals(datatype)) { + return value; + } else { + return "\'" + escapeText(value) + "\'"; + } + } + + @Override + public String toEnumDefaultValue(String value, String datatype) { + return datatype + "_" + value; + } + + @Override + public String toEnumVarName(String name, String datatype) { + // number + if ("int".equals(datatype) || "double".equals(datatype) || "float".equals(datatype)) { + String varName = new String(name); + varName = varName.replaceAll("-", "MINUS_"); + varName = varName.replaceAll("\\+", "PLUS_"); + varName = varName.replaceAll("\\.", "_DOT_"); + return varName; + } + + // string + String enumName = sanitizeName(underscore(name).toUpperCase()); + enumName = enumName.replaceFirst("^_", ""); + enumName = enumName.replaceFirst("_$", ""); + + if (enumName.matches("\\d.*")) { // starts with number + return "_" + enumName; + } else { + return enumName; + } + } + + @Override + public String toEnumName(CodegenProperty property) { + String enumName = underscore(toModelName(property.name)).toUpperCase(); + + if (enumName.matches("\\d.*")) { // starts with number + return "_" + enumName; + } else { + return enumName; + } + } + + @Override + public Map postProcessModels(Map objs) { + // process enum in models + return postProcessModelsEnum(objs); + } + + @Override + public Map postProcessOperations(Map objs) { + Map operations = (Map) objs.get("operations"); + List operationList = (List) operations.get("operation"); + for (CodegenOperation op : operationList) { + op.vendorExtensions.put("x-testOperationId", camelize(op.operationId)); + } + return objs; + } + + @Override + public String escapeQuotationMark(String input) { + // remove ' to avoid code injection + return input.replace("'", ""); + } + + @Override + public String escapeUnsafeCharacters(String input) { + return input.replace("*/", ""); + } + } From 60c7ef1174a8be6dd3fe80a00790ea8a7d6b6009 Mon Sep 17 00:00:00 2001 From: abcsun Date: Wed, 6 Jul 2016 11:01:28 +0800 Subject: [PATCH 3/7] change Lumen codegen to use the AbstractPhpCodegen --- .../codegen/languages/LumenServerCodegen.java | 169 +++--------------- .../petstore/lumen/.swagger-codegen-ignore | 2 +- .../lumen/{ => lib}/app/Console/Kernel.php | 0 .../{ => lib}/app/Exceptions/Handler.php | 0 .../app/Http/Controllers}/Controller.php | 0 .../app/Http/Controllers}/FakeApi.php | 8 +- .../app/Http/Controllers}/PetApi.php | 16 +- .../app/Http/Controllers}/StoreApi.php | 20 +-- .../app/Http/Controllers}/UserApi.php | 6 +- .../app/Http/Middleware/Authenticate.php | 0 .../lumen/{ => lib}/app/Http/routes.php | 0 .../petstore/lumen/{ => lib}/app/User.php | 0 .../lumen/{ => lib}/bootstrap/app.php | 0 .../petstore/lumen/{ => lib}/composer.json | 0 .../petstore/lumen/{ => lib}/public/index.php | 0 .../server/petstore/lumen/{ => lib}/readme.md | 0 16 files changed, 48 insertions(+), 173 deletions(-) rename samples/server/petstore/lumen/{ => lib}/app/Console/Kernel.php (100%) rename samples/server/petstore/lumen/{ => lib}/app/Exceptions/Handler.php (100%) rename samples/server/petstore/lumen/{app/Http/controllers => lib/app/Http/Controllers}/Controller.php (100%) rename samples/server/petstore/lumen/{app/Http/controllers => lib/app/Http/Controllers}/FakeApi.php (96%) rename samples/server/petstore/lumen/{app/Http/controllers => lib/app/Http/Controllers}/PetApi.php (92%) rename samples/server/petstore/lumen/{app/Http/controllers => lib/app/Http/Controllers}/StoreApi.php (84%) rename samples/server/petstore/lumen/{app/Http/controllers => lib/app/Http/Controllers}/UserApi.php (96%) rename samples/server/petstore/lumen/{ => lib}/app/Http/Middleware/Authenticate.php (100%) rename samples/server/petstore/lumen/{ => lib}/app/Http/routes.php (100%) rename samples/server/petstore/lumen/{ => lib}/app/User.php (100%) rename samples/server/petstore/lumen/{ => lib}/bootstrap/app.php (100%) rename samples/server/petstore/lumen/{ => lib}/composer.json (100%) rename samples/server/petstore/lumen/{ => lib}/public/index.php (100%) rename samples/server/petstore/lumen/{ => lib}/readme.md (100%) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/LumenServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/LumenServerCodegen.java index d2b31c55025..17069c84f65 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/LumenServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/LumenServerCodegen.java @@ -10,11 +10,8 @@ import java.util.Map; import java.util.TreeMap; -public class LumenServerCodegen extends AbstractPhpCodegen//DefaultCodegen implements CodegenConfig +public class LumenServerCodegen extends AbstractPhpCodegen { - - // source folder where to write the files - protected String sourceFolder = ""; protected String apiVersion = "1.0.0"; /** @@ -24,7 +21,7 @@ public class LumenServerCodegen extends AbstractPhpCodegen//DefaultCodegen imple * @see io.swagger.codegen.CodegenType */ public CodegenType getTag() { - return CodegenType.CLIENT; + return CodegenType.SERVER; } /** @@ -44,47 +41,17 @@ public String getName() { * @return A string value for the help message */ public String getHelp() { - return "Generates a LumenServerCodegen client library."; + return "Generates a LumenServerCodegen server library."; } public LumenServerCodegen() { super(); - // set the output folder here - outputFolder = "lumen"; - String packagePath = ""; - - /** - * Models. You can write model files using the modelTemplateFiles map. - * if you want to create one template for file, you can do so here. - * for multiple files for model, just put another entry in the `modelTemplateFiles` with - * a different extension - */ - // modelTemplateFiles.put( - // "model.mustache", // the template to use - // ".sample"); // the extension for each file to write - - /** - * Api classes. You can write classes for each Api file with the apiTemplateFiles map. - * as with models, add multiple entries with different extensions for multiple files per - * class - */ - // apiTemplateFiles.put( - // "api.mustache", // the template to use - // ".sample"); // the extension for each file to write - - - // no api files - // apiTemplateFiles.clear(); - apiTemplateFiles.put("api.mustache", ".php"); - - // embeddedTemplateDir = templateDir = "slim"; - /** - * Template Location. This is the location which templates will be read from. The generator - * will use the resource stream to attempt to read the templates. + * packPath */ - templateDir = "lumen"; + invokerPackage = "lumen"; + packagePath = ""; /** * Api Package. Optional, if needed, this can be used in templates @@ -96,14 +63,11 @@ public LumenServerCodegen() { */ modelPackage = "models"; - /** - * Reserved words. Override this with reserved words specific to your language - */ - reservedWords = new HashSet ( - Arrays.asList( - "sample1", // replace with static values - "sample2") - ); + // template files want to be ignored + modelTemplateFiles.clear(); + apiTestTemplateFiles.clear(); + apiDocTemplateFiles.clear(); + modelDocTemplateFiles.clear(); /** * Additional Properties. These values can be passed to the templates and @@ -116,55 +80,18 @@ public LumenServerCodegen() { * entire object tree available. If the input file has a suffix of `.mustache * it will be processed by the template engine. Otherwise, it will be copied */ - supportingFiles.add(new SupportingFile("composer.mustache", packagePath, "composer.json")); - supportingFiles.add(new SupportingFile("readme.md", packagePath, "readme.md")); - supportingFiles.add(new SupportingFile("app.php", packagePath + File.separator + "bootstrap", "app.php")); - supportingFiles.add(new SupportingFile("index.php", packagePath + File.separator + "public", "index.php")); - supportingFiles.add(new SupportingFile("User.php", packagePath + File.separator + "app", "User.php")); - supportingFiles.add(new SupportingFile("Kernel.php", packagePath + File.separator + "app" + File.separator + "Console", "Kernel.php")); - supportingFiles.add(new SupportingFile("Handler.php", packagePath + File.separator + "app" + File.separator + "Exceptions", "Handler.php")); - supportingFiles.add(new SupportingFile("routes.mustache", packagePath + File.separator + "app" + File.separator + "Http", "routes.php")); + supportingFiles.add(new SupportingFile("composer.mustache", packagePath + File.separator + srcBasePath, "composer.json")); + supportingFiles.add(new SupportingFile("readme.md", packagePath + File.separator + srcBasePath, "readme.md")); + supportingFiles.add(new SupportingFile("app.php", packagePath + File.separator + srcBasePath + File.separator + "bootstrap", "app.php")); + supportingFiles.add(new SupportingFile("index.php", packagePath + File.separator + srcBasePath + File.separator + "public", "index.php")); + supportingFiles.add(new SupportingFile("User.php", packagePath + File.separator + srcBasePath + File.separator + "app", "User.php")); + supportingFiles.add(new SupportingFile("Kernel.php", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Console", "Kernel.php")); + supportingFiles.add(new SupportingFile("Handler.php", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Exceptions", "Handler.php")); + supportingFiles.add(new SupportingFile("routes.mustache", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Http", "routes.php")); - supportingFiles.add(new SupportingFile("Controller.php", packagePath + File.separator + "app" + File.separator + "Http" + File.separator + "Controllers" + File.separator, "Controller.php")); - supportingFiles.add(new SupportingFile("Authenticate.php", packagePath + File.separator + "app" + File.separator + "Http" + File.separator + "Middleware" + File.separator, "Authenticate.php")); + supportingFiles.add(new SupportingFile("Controller.php", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Http" + File.separator + "Controllers" + File.separator, "Controller.php")); + supportingFiles.add(new SupportingFile("Authenticate.php", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Http" + File.separator + "Middleware" + File.separator, "Authenticate.php")); - /** - * Language Specific Primitives. These types will not trigger imports by - * the client generator - */ - languageSpecificPrimitives = new HashSet( - Arrays.asList( - "Type1", // replace these with your types - "Type2") - ); - } - - /** - * Escapes a reserved word as defined in the `reservedWords` array. Handle escaping - * those terms here. This logic is only called if a variable matches the reseved words - * - * @return the escaped term - */ - @Override - public String escapeReservedWord(String name) { - return "_" + name; // add an underscore to the name - } - - /** - * Location to write model files. You can use the modelPackage() as defined when the class is - * instantiated - */ - public String modelFileFolder() { - return outputFolder + "/" + modelPackage().replace('.', File.separatorChar); - } - - /** - * Location to write api files. You can use the apiPackage() as defined when the class is - * instantiated - */ - @Override - public String apiFileFolder() { - return outputFolder + "/" + apiPackage().replace('.', File.separatorChar);//"/app/Http/controllers"; } // override with any special post-processing @@ -186,57 +113,5 @@ public int compare(CodegenOperation lhs, CodegenOperation rhs) { return objs; } - /** - * Optional - type declaration. This is a String which is used by the templates to instantiate your - * types. There is typically special handling for different property types - * - * @return a string value used as the `dataType` field for model templates, `returnType` for api templates - */ - @Override - public String getTypeDeclaration(Property p) { - if(p instanceof ArrayProperty) { - ArrayProperty ap = (ArrayProperty) p; - Property inner = ap.getItems(); - return getSwaggerType(p) + "[" + getTypeDeclaration(inner) + "]"; - } - else if (p instanceof MapProperty) { - MapProperty mp = (MapProperty) p; - Property inner = mp.getAdditionalProperties(); - return getSwaggerType(p) + "[String, " + getTypeDeclaration(inner) + "]"; - } - return super.getTypeDeclaration(p); - } - - /** - * Optional - swagger type conversion. This is used to map swagger types in a `Property` into - * either language specific types via `typeMapping` or into complex models if there is not a mapping. - * - * @return a string value of the type or complex model for this property - * @see io.swagger.models.properties.Property - */ - @Override - public String getSwaggerType(Property p) { - String swaggerType = super.getSwaggerType(p); - String type = null; - if(typeMapping.containsKey(swaggerType)) { - type = typeMapping.get(swaggerType); - if(languageSpecificPrimitives.contains(type)) - return toModelName(type); - } - else - type = swaggerType; - return toModelName(type); - } - - @Override - public String escapeQuotationMark(String input) { - // remove ' to avoid code injection - return input.replace("'", ""); - } - - @Override - public String escapeUnsafeCharacters(String input) { - return input.replace("*/", ""); - } - + } diff --git a/samples/server/petstore/lumen/.swagger-codegen-ignore b/samples/server/petstore/lumen/.swagger-codegen-ignore index 19d3377182e..c5fa491b4c5 100644 --- a/samples/server/petstore/lumen/.swagger-codegen-ignore +++ b/samples/server/petstore/lumen/.swagger-codegen-ignore @@ -14,7 +14,7 @@ # You can recursively match patterns against a directory, file or extension with a double asterisk (**): #foo/**/qux -# Thsi matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux # You can also negate patterns with an exclamation (!). # For example, you can ignore all files in a docs folder with the file extension .md: diff --git a/samples/server/petstore/lumen/app/Console/Kernel.php b/samples/server/petstore/lumen/lib/app/Console/Kernel.php similarity index 100% rename from samples/server/petstore/lumen/app/Console/Kernel.php rename to samples/server/petstore/lumen/lib/app/Console/Kernel.php diff --git a/samples/server/petstore/lumen/app/Exceptions/Handler.php b/samples/server/petstore/lumen/lib/app/Exceptions/Handler.php similarity index 100% rename from samples/server/petstore/lumen/app/Exceptions/Handler.php rename to samples/server/petstore/lumen/lib/app/Exceptions/Handler.php diff --git a/samples/server/petstore/lumen/app/Http/controllers/Controller.php b/samples/server/petstore/lumen/lib/app/Http/Controllers/Controller.php similarity index 100% rename from samples/server/petstore/lumen/app/Http/controllers/Controller.php rename to samples/server/petstore/lumen/lib/app/Http/Controllers/Controller.php diff --git a/samples/server/petstore/lumen/app/Http/controllers/FakeApi.php b/samples/server/petstore/lumen/lib/app/Http/Controllers/FakeApi.php similarity index 96% rename from samples/server/petstore/lumen/app/Http/controllers/FakeApi.php rename to samples/server/petstore/lumen/lib/app/Http/Controllers/FakeApi.php index 11c9e2dc4c4..3e8fd2a867c 100644 --- a/samples/server/petstore/lumen/app/Http/controllers/FakeApi.php +++ b/samples/server/petstore/lumen/lib/app/Http/Controllers/FakeApi.php @@ -116,7 +116,7 @@ public function testEndpointParameters() $date = $input['date']; - $dateTime = $input['dateTime']; + $date_time = $input['date_time']; if (strlen($input['password']) > 64) { throw new \InvalidArgumentException('invalid length for $password when calling FakeApi.testEndpointParameters, must be smaller than or equal to 64.'); @@ -145,11 +145,11 @@ public function testEnumQueryParameters() //not path params validation - $enumQueryString = $input['enumQueryString']; + $enum_query_string = $input['enum_query_string']; - $enumQueryInteger = $input['enumQueryInteger']; + $enum_query_integer = $input['enum_query_integer']; - $enumQueryDouble = $input['enumQueryDouble']; + $enum_query_double = $input['enum_query_double']; return response('How about implementing testEnumQueryParameters as a GET method ?'); diff --git a/samples/server/petstore/lumen/app/Http/controllers/PetApi.php b/samples/server/petstore/lumen/lib/app/Http/Controllers/PetApi.php similarity index 92% rename from samples/server/petstore/lumen/app/Http/controllers/PetApi.php rename to samples/server/petstore/lumen/lib/app/Http/Controllers/PetApi.php index bd06e75fa6e..107f8892bf6 100644 --- a/samples/server/petstore/lumen/app/Http/controllers/PetApi.php +++ b/samples/server/petstore/lumen/lib/app/Http/Controllers/PetApi.php @@ -139,11 +139,11 @@ public function findPetsByTags() * * Deletes a pet. * - * @param Long $petId Pet id to delete (required) + * @param int $pet_id Pet id to delete (required) * * @return Http response */ - public function deletePet($petId) + public function deletePet($pet_id) { $input = Request::all(); @@ -159,11 +159,11 @@ public function deletePet($petId) * * Find pet by ID. * - * @param Long $petId ID of pet to return (required) + * @param int $pet_id ID of pet to return (required) * * @return Http response */ - public function getPetById($petId) + public function getPetById($pet_id) { $input = Request::all(); @@ -179,11 +179,11 @@ public function getPetById($petId) * * Updates a pet in the store with form data. * - * @param Long $petId ID of pet that needs to be updated (required) + * @param int $pet_id ID of pet that needs to be updated (required) * * @return Http response */ - public function updatePetWithForm($petId) + public function updatePetWithForm($pet_id) { $input = Request::all(); @@ -199,11 +199,11 @@ public function updatePetWithForm($petId) * * uploads an image. * - * @param Long $petId ID of pet to update (required) + * @param int $pet_id ID of pet to update (required) * * @return Http response */ - public function uploadFile($petId) + public function uploadFile($pet_id) { $input = Request::all(); diff --git a/samples/server/petstore/lumen/app/Http/controllers/StoreApi.php b/samples/server/petstore/lumen/lib/app/Http/Controllers/StoreApi.php similarity index 84% rename from samples/server/petstore/lumen/app/Http/controllers/StoreApi.php rename to samples/server/petstore/lumen/lib/app/Http/Controllers/StoreApi.php index 4eae1e17c9f..24cd6936225 100644 --- a/samples/server/petstore/lumen/app/Http/controllers/StoreApi.php +++ b/samples/server/petstore/lumen/lib/app/Http/Controllers/StoreApi.php @@ -86,17 +86,17 @@ public function placeOrder() * * Delete purchase order by ID. * - * @param String $orderId ID of the order that needs to be deleted (required) + * @param string $order_id ID of the order that needs to be deleted (required) * * @return Http response */ - public function deleteOrder($orderId) + public function deleteOrder($order_id) { $input = Request::all(); //path params validation - if ($orderId] < 1.0) { - throw new \InvalidArgumentException('invalid value for $orderId when calling StoreApi.deleteOrder, must be bigger than or equal to 1.0.'); + if ($order_id] < 1.0) { + throw new \InvalidArgumentException('invalid value for $order_id when calling StoreApi.deleteOrder, must be bigger than or equal to 1.0.'); } @@ -109,20 +109,20 @@ public function deleteOrder($orderId) * * Find purchase order by ID. * - * @param Long $orderId ID of pet that needs to be fetched (required) + * @param int $order_id ID of pet that needs to be fetched (required) * * @return Http response */ - public function getOrderById($orderId) + public function getOrderById($order_id) { $input = Request::all(); //path params validation - if ($orderId] > 5.0) { - throw new \InvalidArgumentException('invalid value for $orderId when calling StoreApi.getOrderById, must be smaller than or equal to 5.0.'); + if ($order_id] > 5.0) { + throw new \InvalidArgumentException('invalid value for $order_id when calling StoreApi.getOrderById, must be smaller than or equal to 5.0.'); } - if ($orderId] < 1.0) { - throw new \InvalidArgumentException('invalid value for $orderId when calling StoreApi.getOrderById, must be bigger than or equal to 1.0.'); + if ($order_id] < 1.0) { + throw new \InvalidArgumentException('invalid value for $order_id when calling StoreApi.getOrderById, must be bigger than or equal to 1.0.'); } diff --git a/samples/server/petstore/lumen/app/Http/controllers/UserApi.php b/samples/server/petstore/lumen/lib/app/Http/Controllers/UserApi.php similarity index 96% rename from samples/server/petstore/lumen/app/Http/controllers/UserApi.php rename to samples/server/petstore/lumen/lib/app/Http/Controllers/UserApi.php index 331c90525e9..92869eddab4 100644 --- a/samples/server/petstore/lumen/app/Http/controllers/UserApi.php +++ b/samples/server/petstore/lumen/lib/app/Http/Controllers/UserApi.php @@ -163,7 +163,7 @@ public function logoutUser() * * Delete user. * - * @param String $username The name that needs to be deleted (required) + * @param string $username The name that needs to be deleted (required) * * @return Http response */ @@ -183,7 +183,7 @@ public function deleteUser($username) * * Get user by user name. * - * @param String $username The name that needs to be fetched. Use user1 for testing. (required) + * @param string $username The name that needs to be fetched. Use user1 for testing. (required) * * @return Http response */ @@ -203,7 +203,7 @@ public function getUserByName($username) * * Updated user. * - * @param String $username name that need to be deleted (required) + * @param string $username name that need to be deleted (required) * * @return Http response */ diff --git a/samples/server/petstore/lumen/app/Http/Middleware/Authenticate.php b/samples/server/petstore/lumen/lib/app/Http/Middleware/Authenticate.php similarity index 100% rename from samples/server/petstore/lumen/app/Http/Middleware/Authenticate.php rename to samples/server/petstore/lumen/lib/app/Http/Middleware/Authenticate.php diff --git a/samples/server/petstore/lumen/app/Http/routes.php b/samples/server/petstore/lumen/lib/app/Http/routes.php similarity index 100% rename from samples/server/petstore/lumen/app/Http/routes.php rename to samples/server/petstore/lumen/lib/app/Http/routes.php diff --git a/samples/server/petstore/lumen/app/User.php b/samples/server/petstore/lumen/lib/app/User.php similarity index 100% rename from samples/server/petstore/lumen/app/User.php rename to samples/server/petstore/lumen/lib/app/User.php diff --git a/samples/server/petstore/lumen/bootstrap/app.php b/samples/server/petstore/lumen/lib/bootstrap/app.php similarity index 100% rename from samples/server/petstore/lumen/bootstrap/app.php rename to samples/server/petstore/lumen/lib/bootstrap/app.php diff --git a/samples/server/petstore/lumen/composer.json b/samples/server/petstore/lumen/lib/composer.json similarity index 100% rename from samples/server/petstore/lumen/composer.json rename to samples/server/petstore/lumen/lib/composer.json diff --git a/samples/server/petstore/lumen/public/index.php b/samples/server/petstore/lumen/lib/public/index.php similarity index 100% rename from samples/server/petstore/lumen/public/index.php rename to samples/server/petstore/lumen/lib/public/index.php diff --git a/samples/server/petstore/lumen/readme.md b/samples/server/petstore/lumen/lib/readme.md similarity index 100% rename from samples/server/petstore/lumen/readme.md rename to samples/server/petstore/lumen/lib/readme.md From 917ab52785378a5609e053a6d4360e2b8672d549 Mon Sep 17 00:00:00 2001 From: abcsun Date: Wed, 6 Jul 2016 15:13:59 +0800 Subject: [PATCH 4/7] remove the composerVendorName/composerProjectName. modify the LumenServerOptionsTest for unit test --- .../codegen/languages/AbstractPhpCodegen.java | 46 +++++++++---------- .../codegen/languages/LumenServerCodegen.java | 1 + .../codegen/lumen/LumenServerOptionsTest.java | 18 ++++++++ .../options/LumenServerOptionsProvider.java | 21 ++++++++- 4 files changed, 62 insertions(+), 24 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java index b1124f7ca71..3af1f9825f7 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java @@ -31,11 +31,12 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg public static final String VARIABLE_NAMING_CONVENTION = "variableNamingConvention"; public static final String PACKAGE_PATH = "packagePath"; public static final String SRC_BASE_PATH = "srcBasePath"; - public static final String COMPOSER_VENDOR_NAME = "composerVendorName"; - public static final String COMPOSER_PROJECT_NAME = "composerProjectName"; + // composerVendorName/composerProjectName has be replaced by gitUserId/gitRepoId. prepare to remove these. + // public static final String COMPOSER_VENDOR_NAME = "composerVendorName"; + // public static final String COMPOSER_PROJECT_NAME = "composerProjectName"; + // protected String composerVendorName = null; + // protected String composerProjectName = null; protected String invokerPackage = "php"; - protected String composerVendorName = null; - protected String composerProjectName = null; protected String packagePath = "php-base"; protected String artifactVersion = null; protected String srcBasePath = "lib"; @@ -116,7 +117,6 @@ public AbstractPhpCodegen() { typeMapping.put("ByteArray", "string"); typeMapping.put("UUID", "string"); - cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC)); cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC)); cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC)); cliOptions.add(new CliOption(VARIABLE_NAMING_CONVENTION, "naming convention of variable name, e.g. camelCase.") @@ -124,9 +124,9 @@ public AbstractPhpCodegen() { cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, "The main namespace to use for all classes. e.g. Yay\\Pets")); cliOptions.add(new CliOption(PACKAGE_PATH, "The main package name for classes. e.g. GeneratedPetstore")); cliOptions.add(new CliOption(SRC_BASE_PATH, "The directory under packagePath to serve as source root.")); - cliOptions.add(new CliOption(COMPOSER_VENDOR_NAME, "The vendor name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. yaypets. IMPORTANT NOTE (2016/03): composerVendorName will be deprecated and replaced by gitUserId in the next swagger-codegen release")); + // cliOptions.add(new CliOption(COMPOSER_VENDOR_NAME, "The vendor name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. yaypets. IMPORTANT NOTE (2016/03): composerVendorName will be deprecated and replaced by gitUserId in the next swagger-codegen release")); cliOptions.add(new CliOption(CodegenConstants.GIT_USER_ID, CodegenConstants.GIT_USER_ID_DESC)); - 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(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.GIT_REPO_ID, CodegenConstants.GIT_REPO_ID_DESC)); cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, "The version to use in the composer package version field. e.g. 1.2.3")); } @@ -161,11 +161,11 @@ public void processOpts() { additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); } - if (additionalProperties.containsKey(COMPOSER_PROJECT_NAME)) { - this.setComposerProjectName((String) additionalProperties.get(COMPOSER_PROJECT_NAME)); - } else { - additionalProperties.put(COMPOSER_PROJECT_NAME, composerProjectName); - } + // if (additionalProperties.containsKey(COMPOSER_PROJECT_NAME)) { + // this.setComposerProjectName((String) additionalProperties.get(COMPOSER_PROJECT_NAME)); + // } else { + // additionalProperties.put(COMPOSER_PROJECT_NAME, composerProjectName); + // } if (additionalProperties.containsKey(CodegenConstants.GIT_USER_ID)) { this.setGitUserId((String) additionalProperties.get(CodegenConstants.GIT_USER_ID)); @@ -173,11 +173,11 @@ public void processOpts() { additionalProperties.put(CodegenConstants.GIT_USER_ID, gitUserId); } - if (additionalProperties.containsKey(COMPOSER_VENDOR_NAME)) { - this.setComposerVendorName((String) additionalProperties.get(COMPOSER_VENDOR_NAME)); - } else { - additionalProperties.put(COMPOSER_VENDOR_NAME, composerVendorName); - } + // if (additionalProperties.containsKey(COMPOSER_VENDOR_NAME)) { + // this.setComposerVendorName((String) additionalProperties.get(COMPOSER_VENDOR_NAME)); + // } else { + // additionalProperties.put(COMPOSER_VENDOR_NAME, composerVendorName); + // } if (additionalProperties.containsKey(CodegenConstants.GIT_REPO_ID)) { this.setGitRepoId((String) additionalProperties.get(CodegenConstants.GIT_REPO_ID)); @@ -352,13 +352,13 @@ public void setParameterNamingConvention(String variableNamingConvention) { this.variableNamingConvention = variableNamingConvention; } - public void setComposerVendorName(String composerVendorName) { - this.composerVendorName = composerVendorName; - } + // public void setComposerVendorName(String composerVendorName) { + // this.composerVendorName = composerVendorName; + // } - public void setComposerProjectName(String composerProjectName) { - this.composerProjectName = composerProjectName; - } + // public void setComposerProjectName(String composerProjectName) { + // this.composerProjectName = composerProjectName; + // } @Override public String toVarName(String name) { diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/LumenServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/LumenServerCodegen.java index 17069c84f65..98c68dd2f18 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/LumenServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/LumenServerCodegen.java @@ -12,6 +12,7 @@ public class LumenServerCodegen extends AbstractPhpCodegen { + @SuppressWarnings("hiding") protected String apiVersion = "1.0.0"; /** diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/lumen/LumenServerOptionsTest.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/lumen/LumenServerOptionsTest.java index dcb89d263cc..434e318f593 100644 --- a/modules/swagger-codegen/src/test/java/io/swagger/codegen/lumen/LumenServerOptionsTest.java +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/lumen/LumenServerOptionsTest.java @@ -28,6 +28,24 @@ protected void setExpectations() { new Expectations(clientCodegen) {{ clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(LumenServerOptionsProvider.SORT_PARAMS_VALUE)); times = 1; + clientCodegen.setParameterNamingConvention(LumenServerOptionsProvider.VARIABLE_NAMING_CONVENTION_VALUE); + clientCodegen.setModelPackage(LumenServerOptionsProvider.MODEL_PACKAGE_VALUE); + times = 1; + clientCodegen.setApiPackage(LumenServerOptionsProvider.API_PACKAGE_VALUE); + times = 1; + times = 1; + clientCodegen.setInvokerPackage(LumenServerOptionsProvider.INVOKER_PACKAGE_VALUE); + times = 1; + clientCodegen.setPackagePath(LumenServerOptionsProvider.PACKAGE_PATH_VALUE); + times = 1; + clientCodegen.setSrcBasePath(LumenServerOptionsProvider.SRC_BASE_PATH_VALUE); + times = 1; + clientCodegen.setGitUserId(LumenServerOptionsProvider.GIT_USER_ID_VALUE); + times = 1; + clientCodegen.setGitRepoId(LumenServerOptionsProvider.GIT_REPO_ID_VALUE); + times = 1; + clientCodegen.setArtifactVersion(LumenServerOptionsProvider.ARTIFACT_VERSION_VALUE); + times = 1; }}; } } diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/LumenServerOptionsProvider.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/LumenServerOptionsProvider.java index 1ffc290ee46..6edc611b59e 100644 --- a/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/LumenServerOptionsProvider.java +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/LumenServerOptionsProvider.java @@ -1,14 +1,24 @@ package io.swagger.codegen.options; import io.swagger.codegen.CodegenConstants; +import io.swagger.codegen.languages.AbstractPhpCodegen; import com.google.common.collect.ImmutableMap; import java.util.Map; public class LumenServerOptionsProvider implements OptionsProvider { + public static final String MODEL_PACKAGE_VALUE = "package"; + public static final String API_PACKAGE_VALUE = "apiPackage"; public static final String SORT_PARAMS_VALUE = "false"; public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true"; + public static final String VARIABLE_NAMING_CONVENTION_VALUE = "snake_case"; + public static final String INVOKER_PACKAGE_VALUE = "lumen"; + public static final String PACKAGE_PATH_VALUE = "php"; + public static final String SRC_BASE_PATH_VALUE = "libPhp"; + public static final String GIT_USER_ID_VALUE = "gitSwaggerPhp"; + public static final String GIT_REPO_ID_VALUE = "git-swagger-php"; + public static final String ARTIFACT_VERSION_VALUE = "1.0.0-SNAPSHOT"; @Override public String getLanguage() { @@ -18,8 +28,17 @@ public String getLanguage() { @Override public Map createOptions() { ImmutableMap.Builder builder = new ImmutableMap.Builder(); - return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) + return builder.put(CodegenConstants.MODEL_PACKAGE, MODEL_PACKAGE_VALUE) + .put(AbstractPhpCodegen.VARIABLE_NAMING_CONVENTION, VARIABLE_NAMING_CONVENTION_VALUE) + .put(AbstractPhpCodegen.PACKAGE_PATH, PACKAGE_PATH_VALUE) + .put(AbstractPhpCodegen.SRC_BASE_PATH, SRC_BASE_PATH_VALUE) + .put(CodegenConstants.API_PACKAGE, API_PACKAGE_VALUE) + .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) + .put(CodegenConstants.INVOKER_PACKAGE, INVOKER_PACKAGE_VALUE) + .put(CodegenConstants.GIT_USER_ID, GIT_USER_ID_VALUE) + .put(CodegenConstants.GIT_REPO_ID, GIT_REPO_ID_VALUE) + .put(CodegenConstants.ARTIFACT_VERSION, ARTIFACT_VERSION_VALUE) .build(); } From 5dc12aafae738f9177a6b0659d26419821fc2a2e Mon Sep 17 00:00:00 2001 From: abcsun Date: Wed, 20 Jul 2016 18:27:45 +0800 Subject: [PATCH 5/7] add context path --- .../src/main/resources/lumen/routes.mustache | 2 +- .../lumen/app/Http/controllers/FakeApi.php | 24 +++++++++ .../server/petstore/lumen/app/Http/routes.php | 51 +++++++++++-------- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/lumen/routes.mustache b/modules/swagger-codegen/src/main/resources/lumen/routes.mustache index c5f3bdf858a..4b9631fd9a5 100644 --- a/modules/swagger-codegen/src/main/resources/lumen/routes.mustache +++ b/modules/swagger-codegen/src/main/resources/lumen/routes.mustache @@ -19,7 +19,7 @@ $app->get('/', function () use ($app) { * Notes: {{notes}} {{#hasProduces}} * Output-Formats: [{{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}]{{/hasProduces}} */ -$app->{{httpMethod}}('{{path}}', '{{classname}}@{{operationId}}'); +$app->{{httpMethod}}('{{basePathWithoutHost}}{{path}}', '{{classname}}@{{operationId}}'); {{/operation}} {{/operations}} {{/apis}} diff --git a/samples/server/petstore/lumen/app/Http/controllers/FakeApi.php b/samples/server/petstore/lumen/app/Http/controllers/FakeApi.php index 11c9e2dc4c4..a55492b90f1 100644 --- a/samples/server/petstore/lumen/app/Http/controllers/FakeApi.php +++ b/samples/server/petstore/lumen/app/Http/controllers/FakeApi.php @@ -38,6 +38,30 @@ public function __construct() { } + /** + * Operation testClientModel + * + * To test \"client\" model. + * + * + * @return Http response + */ + public function testClientModel() + { + $input = Request::all(); + + //path params validation + + + //not path params validation + if (!isset($input['body'])) { + throw new \InvalidArgumentException('Missing the required parameter $body when calling testClientModel'); + } + $body = $input['body']; + + + return response('How about implementing testClientModel as a PATCH method ?'); + } /** * Operation testEndpointParameters * diff --git a/samples/server/petstore/lumen/app/Http/routes.php b/samples/server/petstore/lumen/app/Http/routes.php index c61d6d3c4d3..ea9b463bffa 100644 --- a/samples/server/petstore/lumen/app/Http/routes.php +++ b/samples/server/petstore/lumen/app/Http/routes.php @@ -33,158 +33,165 @@ return $app->version(); }); +/** + * PATCH testClientModel + * Summary: To test \"client\" model + * Notes: + * Output-Formats: [application/json] + */ +$app->PATCH('/v2/fake', 'FakeApi@testClientModel'); /** * POST testEndpointParameters * Summary: Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 * Notes: Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 * Output-Formats: [application/xml; charset=utf-8, application/json; charset=utf-8] */ -$app->POST('/fake', 'FakeApi@testEndpointParameters'); +$app->POST('/v2/fake', 'FakeApi@testEndpointParameters'); /** * GET testEnumQueryParameters * Summary: To test enum query parameters * Notes: * Output-Formats: [application/json] */ -$app->GET('/fake', 'FakeApi@testEnumQueryParameters'); +$app->GET('/v2/fake', 'FakeApi@testEnumQueryParameters'); /** * POST addPet * Summary: Add a new pet to the store * Notes: * Output-Formats: [application/xml, application/json] */ -$app->POST('/pet', 'PetApi@addPet'); +$app->POST('/v2/pet', 'PetApi@addPet'); /** * PUT updatePet * Summary: Update an existing pet * Notes: * Output-Formats: [application/xml, application/json] */ -$app->PUT('/pet', 'PetApi@updatePet'); +$app->PUT('/v2/pet', 'PetApi@updatePet'); /** * GET findPetsByStatus * Summary: Finds Pets by status * Notes: Multiple status values can be provided with comma separated strings * Output-Formats: [application/xml, application/json] */ -$app->GET('/pet/findByStatus', 'PetApi@findPetsByStatus'); +$app->GET('/v2/pet/findByStatus', 'PetApi@findPetsByStatus'); /** * GET findPetsByTags * Summary: Finds Pets by tags * Notes: Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. * Output-Formats: [application/xml, application/json] */ -$app->GET('/pet/findByTags', 'PetApi@findPetsByTags'); +$app->GET('/v2/pet/findByTags', 'PetApi@findPetsByTags'); /** * DELETE deletePet * Summary: Deletes a pet * Notes: * Output-Formats: [application/xml, application/json] */ -$app->DELETE('/pet/{petId}', 'PetApi@deletePet'); +$app->DELETE('/v2/pet/{petId}', 'PetApi@deletePet'); /** * GET getPetById * Summary: Find pet by ID * Notes: Returns a single pet * Output-Formats: [application/xml, application/json] */ -$app->GET('/pet/{petId}', 'PetApi@getPetById'); +$app->GET('/v2/pet/{petId}', 'PetApi@getPetById'); /** * POST updatePetWithForm * Summary: Updates a pet in the store with form data * Notes: * Output-Formats: [application/xml, application/json] */ -$app->POST('/pet/{petId}', 'PetApi@updatePetWithForm'); +$app->POST('/v2/pet/{petId}', 'PetApi@updatePetWithForm'); /** * POST uploadFile * Summary: uploads an image * Notes: * Output-Formats: [application/json] */ -$app->POST('/pet/{petId}/uploadImage', 'PetApi@uploadFile'); +$app->POST('/v2/pet/{petId}/uploadImage', 'PetApi@uploadFile'); /** * GET getInventory * Summary: Returns pet inventories by status * Notes: Returns a map of status codes to quantities * Output-Formats: [application/json] */ -$app->GET('/store/inventory', 'StoreApi@getInventory'); +$app->GET('/v2/store/inventory', 'StoreApi@getInventory'); /** * POST placeOrder * Summary: Place an order for a pet * Notes: * Output-Formats: [application/xml, application/json] */ -$app->POST('/store/order', 'StoreApi@placeOrder'); +$app->POST('/v2/store/order', 'StoreApi@placeOrder'); /** * DELETE deleteOrder * Summary: Delete purchase order by ID * Notes: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors * Output-Formats: [application/xml, application/json] */ -$app->DELETE('/store/order/{orderId}', 'StoreApi@deleteOrder'); +$app->DELETE('/v2/store/order/{orderId}', 'StoreApi@deleteOrder'); /** * GET getOrderById * Summary: Find purchase order by ID * Notes: For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions * Output-Formats: [application/xml, application/json] */ -$app->GET('/store/order/{orderId}', 'StoreApi@getOrderById'); +$app->GET('/v2/store/order/{orderId}', 'StoreApi@getOrderById'); /** * POST createUser * Summary: Create user * Notes: This can only be done by the logged in user. * Output-Formats: [application/xml, application/json] */ -$app->POST('/user', 'UserApi@createUser'); +$app->POST('/v2/user', 'UserApi@createUser'); /** * POST createUsersWithArrayInput * Summary: Creates list of users with given input array * Notes: * Output-Formats: [application/xml, application/json] */ -$app->POST('/user/createWithArray', 'UserApi@createUsersWithArrayInput'); +$app->POST('/v2/user/createWithArray', 'UserApi@createUsersWithArrayInput'); /** * POST createUsersWithListInput * Summary: Creates list of users with given input array * Notes: * Output-Formats: [application/xml, application/json] */ -$app->POST('/user/createWithList', 'UserApi@createUsersWithListInput'); +$app->POST('/v2/user/createWithList', 'UserApi@createUsersWithListInput'); /** * GET loginUser * Summary: Logs user into the system * Notes: * Output-Formats: [application/xml, application/json] */ -$app->GET('/user/login', 'UserApi@loginUser'); +$app->GET('/v2/user/login', 'UserApi@loginUser'); /** * GET logoutUser * Summary: Logs out current logged in user session * Notes: * Output-Formats: [application/xml, application/json] */ -$app->GET('/user/logout', 'UserApi@logoutUser'); +$app->GET('/v2/user/logout', 'UserApi@logoutUser'); /** * DELETE deleteUser * Summary: Delete user * Notes: This can only be done by the logged in user. * Output-Formats: [application/xml, application/json] */ -$app->DELETE('/user/{username}', 'UserApi@deleteUser'); +$app->DELETE('/v2/user/{username}', 'UserApi@deleteUser'); /** * GET getUserByName * Summary: Get user by user name * Notes: * Output-Formats: [application/xml, application/json] */ -$app->GET('/user/{username}', 'UserApi@getUserByName'); +$app->GET('/v2/user/{username}', 'UserApi@getUserByName'); /** * PUT updateUser * Summary: Updated user * Notes: This can only be done by the logged in user. * Output-Formats: [application/xml, application/json] */ -$app->PUT('/user/{username}', 'UserApi@updateUser'); +$app->PUT('/v2/user/{username}', 'UserApi@updateUser'); From faf5b9252cd196372ebc8988ef9e78cada4bbfa5 Mon Sep 17 00:00:00 2001 From: abcsun Date: Thu, 21 Jul 2016 14:43:07 +0800 Subject: [PATCH 6/7] reserve the apiDocPath and modelDocPath --- .../codegen/languages/AbstractPhpCodegen.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java index 3af1f9825f7..f826f55d82c 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java @@ -195,14 +195,14 @@ public void processOpts() { this.setParameterNamingConvention((String) additionalProperties.get(VARIABLE_NAMING_CONVENTION)); } - // additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\")); + additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\")); - // // make api and model doc path available in mustache template - // additionalProperties.put("apiDocPath", apiDocPath); - // additionalProperties.put("modelDocPath", modelDocPath); + // make api and model doc path available in mustache template + additionalProperties.put("apiDocPath", apiDocPath); + additionalProperties.put("modelDocPath", modelDocPath); - // // make test path available in mustache template - // additionalProperties.put("testBasePath", testBasePath); + // make test path available in mustache template + additionalProperties.put("testBasePath", testBasePath); // // apache v2 license // supportingFiles.add(new SupportingFile("LICENSE", getPackagePath(), "LICENSE")); From 9ae428278ab144d2bec0375b305bf214e1550057 Mon Sep 17 00:00:00 2001 From: abcsun Date: Mon, 1 Aug 2016 11:43:06 +0800 Subject: [PATCH 7/7] add the templateDir for lumen --- .../java/io/swagger/codegen/languages/LumenServerCodegen.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/LumenServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/LumenServerCodegen.java index bb83d2025ea..b2a2db3def3 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/LumenServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/LumenServerCodegen.java @@ -48,6 +48,8 @@ public String getHelp() { public LumenServerCodegen() { super(); + embeddedTemplateDir = templateDir = "lumen"; + /** * packPath */