This commit is contained in:
wing328
2017-10-29 15:14:46 +08:00
494 changed files with 15346 additions and 3879 deletions

5
.gitignore vendored
View File

@@ -90,6 +90,11 @@ samples/client/petstore/silex/SwaggerServer/venodr/
**/vendor/
**/composer.lock
#PHP-Symfony
samples/server/petstore/php-symfony/SymfonyBundle-php/Tests/cache/
samples/server/petstore/php-symfony/SymfonyBundle-php/Tests/logs/
# Perl
samples/client/petstore/perl/deep_module_test/

View File

@@ -13,7 +13,7 @@
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.swagger/swagger-codegen-project/badge.svg?style=plastic)](https://maven-badges.herokuapp.com/maven-central/io.swagger/swagger-codegen-project)
[![PR Stats](http://issuestats.com/github/swagger-api/swagger-codegen/badge/pr)](http://issuestats.com/github/swagger-api/swagger-codegen) [![Issue Stats](http://issuestats.com/github/swagger-api/swagger-codegen/badge/issue)](http://issuestats.com/github/swagger-api/swagger-codegen)
:star::star::star: If you would like to contribute, please refer to [guidelines](https://github.com/swagger-api/swagger-codegen/blob/master/CONTRIBUTING.md) and a list of [open tasks](https://github.com/swagger-api/swagger-codegen/issues?q=is%3Aopen+is%3Aissue+label%3A%22Need+community+contribution%22).:star::star::star:
:star::star::star: If you would like to contribute, please refer to [guidelines](https://github.com/swagger-api/swagger-codegen/blob/master/CONTRIBUTING.md) and a list of [open tasks](https://github.com/swagger-api/swagger-codegen/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22).:star::star::star:
:notebook_with_decorative_cover: For more information, please refer to the [Wiki page](https://github.com/swagger-api/swagger-codegen/wiki) and [FAQ](https://github.com/swagger-api/swagger-codegen/wiki/FAQ) :notebook_with_decorative_cover:
@@ -730,6 +730,7 @@ Please refer to this [page](https://github.com/swagger-api/swagger-codegen/blob/
Companies/Projects using Swagger Codegen
----------------------------------------
Here are some companies/projects using Swagger Codegen in production. To add your company/project to the list, please visit [README.md](https://github.com/swagger-api/swagger-codegen/blob/master/README.md) and click on the icon to edit the page.
- [Accengage](https://www.accengage.com/)
- [Activehours](https://www.activehours.com/)
- [Acunetix](https://www.acunetix.com/)
- [Atlassian](https://www.atlassian.com/)
@@ -760,6 +761,7 @@ Here are some companies/projects using Swagger Codegen in production. To add you
- [everystory.us](http://everystory.us)
- [Expected Behavior](http://www.expectedbehavior.com/)
- [Fastly](https://www.fastly.com/)
- [FINRA](https://github.com/FINRAOS/herd/)
- [Flat](https://flat.io)
- [Finder](http://en.finder.pl/)
- [Fitwell](https://fitwell.co/)
@@ -793,6 +795,7 @@ Here are some companies/projects using Swagger Codegen in production. To add you
- [LXL Tech](http://lxltech.com)
- [Lyft](https://www.lyft.com/developers)
- [MailMojo](https://mailmojo.no/)
- [Metaswitch](https://www.metaswitch.com/)
- [Mindera](http://mindera.com/)
- [Mporium](http://mporium.com/)
- [Neverfail](https://neverfail.com/)
@@ -1032,7 +1035,7 @@ Here is a list of template creators:
Here are the requirements to become a core team member:
- rank within top 50 in https://github.com/swagger-api/swagger-codegen/graphs/contributors
- to contribute, here are some good [starting points](https://github.com/swagger-api/swagger-codegen/issues?q=is%3Aopen+is%3Aissue+label%3A%22Need+community+contribution%22)
- to contribute, here are some good [starting points](https://github.com/swagger-api/swagger-codegen/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
- regular contributions to the project
- about 3 hours per week
- for contribution, it can be addressing issues, reviewing PRs submitted by others, submitting PR to fix bugs or make enhancements, etc

41
bin/php-symfony-petstore.sh Executable file
View File

@@ -0,0 +1,41 @@
#!/bin/bash
SCRIPT="$0"
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done
# Make sure that the working directory is the root dir
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "${SCRIPT_DIR}/../"
if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi
# Make sure that we are regenerating the sample by removing any existing target directory
TARGET_DIR="$SCRIPT_DIR/../samples/server/petstore/php-symfony"
if [ -d "$TARGET_DIR" ]; then
rm -rf $TARGET_DIR
fi
executable="$SCRIPT_DIR/../modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn clean package
fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="generate -t $SCRIPT_DIR/../modules/swagger-codegen/src/main/resources/php-symfony -i $SCRIPT_DIR/../modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l php-symfony -o $TARGET_DIR $@"
java $JAVA_OPTS -jar $executable $ags

View File

@@ -38,3 +38,11 @@ java $JAVA_OPTS -jar $executable $ags
echo "Typescript Petstore API client (with interfaces generated)"
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l typescript-angular -o samples/client/petstore/typescript-angular-v2/with-interfaces -D withInterfaces=true --additional-properties ngVersion=2"
java $JAVA_OPTS -jar $executable $ags
echo "Typescript Petstore API client (v4 { Adding InjectionToken Over OpaqueToken })"
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l typescript-angular -c bin/typescript-petstore-npm.json -o samples/client/petstore/typescript-angular-v4/npm --additional-properties ngVersion=4"
java $JAVA_OPTS -jar $executable $ags
echo "Typescript Petstore API client (v4.3 { Adding HttpClientModule over HttpModule })"
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l typescript-angular -c bin/typescript-petstore-npm.json -o samples/client/petstore/typescript-angular-v4.3/npm --additional-properties ngVersion=4.3"
java $JAVA_OPTS -jar $executable $ags

View File

@@ -1,3 +1,7 @@
call .\bin\windows\typescript-angular-v2-with-npm.bat
call .\bin\windows\typescript-angular-v2-interfaces.bat
call .\bin\windows\typescript-angular-v2.bat
call .\bin\windows\typescript-angular-v4-with-npm.bat
call .\bin\windows\typescript-angular-v4.3-with-npm.bat

View File

@@ -11,7 +11,7 @@ codegen="${cli}/target/swagger-codegen-cli.jar"
cmdsrc="${cli}/src/main/java/io/swagger/codegen/cmd"
pattern="@Command(name = \"$1\""
if expr "x$1" : 'x[a-z][a-z-]*$' > /dev/null && fgrep -qe "$pattern" "$cmdsrc"/*.java; then
if expr "x$1" : 'x[a-z][a-z-]*$' > /dev/null && fgrep -qe "$pattern" "$cmdsrc"/*.java || expr "$1" = 'help' > /dev/null; then
# If ${GEN_DIR} has been mapped elsewhere from default, and that location has not been built
if [[ ! -f "${codegen}" ]]; then
(cd "${GEN_DIR}" && exec mvn -am -pl "modules/swagger-codegen-cli" -Duser.home=$(dirname MAVEN_CONFIG) package)

View File

@@ -140,6 +140,15 @@ public class CodegenOperation {
return Arrays.asList("PUT", "PATCH").contains(httpMethod.toUpperCase()) && isMemberPath();
}
/**
* Check if body param is allowed for the request method
*
* @return true request method is PUT, PATCH or POST; false otherwise
*/
public boolean isBodyAllowed() {
return Arrays.asList("PUT", "PATCH", "POST").contains(httpMethod.toUpperCase());
}
/**
* Check if act as Restful destroy method
*

View File

@@ -68,9 +68,13 @@ public class InlineModelResolver {
Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) {
am.setItems(new RefProperty(existing));
RefProperty refProperty = new RefProperty(existing);
refProperty.setRequired(op.getRequired());
am.setItems(refProperty);
} else {
am.setItems(new RefProperty(modelName));
RefProperty refProperty = new RefProperty(modelName);
refProperty.setRequired(op.getRequired());
am.setItems(refProperty);
addGenerated(modelName, innerModel);
swagger.addDefinition(modelName, innerModel);
}
@@ -94,9 +98,13 @@ public class InlineModelResolver {
Model model = modelFromProperty(op, modelName);
String existing = matchGenerated(model);
if (existing != null) {
response.setSchema(this.makeRefProperty(existing, property));
Property refProperty = this.makeRefProperty(existing, property);
refProperty.setRequired(op.getRequired());
response.setSchema(refProperty);
} else {
response.setSchema(this.makeRefProperty(modelName, property));
Property refProperty = this.makeRefProperty(modelName, property);
refProperty.setRequired(op.getRequired());
response.setSchema(refProperty);
addGenerated(modelName, model);
swagger.addDefinition(modelName, model);
}
@@ -114,9 +122,13 @@ public class InlineModelResolver {
Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) {
ap.setItems(this.makeRefProperty(existing, op));
Property refProperty = this.makeRefProperty(existing, op);
refProperty.setRequired(op.getRequired());
ap.setItems(refProperty);
} else {
ap.setItems(this.makeRefProperty(modelName, op));
Property refProperty = this.makeRefProperty(modelName, op);
refProperty.setRequired(op.getRequired());
ap.setItems(refProperty);
addGenerated(modelName, innerModel);
swagger.addDefinition(modelName, innerModel);
}
@@ -135,9 +147,13 @@ public class InlineModelResolver {
Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) {
mp.setAdditionalProperties(new RefProperty(existing));
RefProperty refProperty = new RefProperty(existing);
refProperty.setRequired(op.getRequired());
mp.setAdditionalProperties(refProperty);
} else {
mp.setAdditionalProperties(new RefProperty(modelName));
RefProperty refProperty = new RefProperty(modelName);
refProperty.setRequired(op.getRequired());
mp.setAdditionalProperties(refProperty);
addGenerated(modelName, innerModel);
swagger.addDefinition(modelName, innerModel);
}
@@ -174,9 +190,13 @@ public class InlineModelResolver {
if (existing == null) {
swagger.addDefinition(innerModelName, innerModel);
addGenerated(innerModelName, innerModel);
m.setItems(new RefProperty(innerModelName));
RefProperty refProperty = new RefProperty(innerModelName);
refProperty.setRequired(op.getRequired());
m.setItems(refProperty);
} else {
m.setItems(new RefProperty(existing));
RefProperty refProperty = new RefProperty(existing);
refProperty.setRequired(op.getRequired());
m.setItems(refProperty);
}
}
}
@@ -271,9 +291,13 @@ public class InlineModelResolver {
String existing = matchGenerated(model);
if (existing != null) {
propsToUpdate.put(key, new RefProperty(existing));
RefProperty refProperty = new RefProperty(existing);
refProperty.setRequired(op.getRequired());
propsToUpdate.put(key, refProperty);
} else {
propsToUpdate.put(key, new RefProperty(modelName));
RefProperty refProperty = new RefProperty(modelName);
refProperty.setRequired(op.getRequired());
propsToUpdate.put(key, refProperty);
modelsToAdd.put(modelName, model);
addGenerated(modelName, model);
swagger.addDefinition(modelName, model);
@@ -290,9 +314,13 @@ public class InlineModelResolver {
Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) {
ap.setItems(new RefProperty(existing));
RefProperty refProperty = new RefProperty(existing);
refProperty.setRequired(op.getRequired());
ap.setItems(refProperty);
} else {
ap.setItems(new RefProperty(modelName));
RefProperty refProperty = new RefProperty(modelName);
refProperty.setRequired(op.getRequired());
ap.setItems(refProperty);
addGenerated(modelName, innerModel);
swagger.addDefinition(modelName, innerModel);
}
@@ -310,9 +338,13 @@ public class InlineModelResolver {
Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) {
mp.setAdditionalProperties(new RefProperty(existing));
RefProperty refProperty = new RefProperty(existing);
refProperty.setRequired(op.getRequired());
mp.setAdditionalProperties(refProperty);
} else {
mp.setAdditionalProperties(new RefProperty(modelName));
RefProperty refProperty = new RefProperty(modelName);
refProperty.setRequired(op.getRequired());
mp.setAdditionalProperties(refProperty);
addGenerated(modelName, innerModel);
swagger.addDefinition(modelName, innerModel);
}
@@ -399,7 +431,7 @@ public class InlineModelResolver {
/**
* Make a RefProperty
*
*
* @param ref new property name
* @param property Property
* @return
@@ -412,7 +444,7 @@ public class InlineModelResolver {
/**
* Copy vendor extensions from Property to another Property
*
*
* @param source source property
* @param target target property
*/

View File

@@ -248,17 +248,30 @@ public class FinchServerCodegen extends DefaultCodegen implements CodegenConfig
for (CodegenParameter p : op.allParams) {
// TODO: This hacky, should be converted to mappings if possible to keep it clean.
// This could also be done using template imports
if(Boolean.TRUE.equals(p.isPrimitiveType)) {
if(p.isPathParam && p.isPrimitiveType) {
p.vendorExtensions.put("x-codegen-normalized-path-type", p.dataType.toLowerCase());
p.vendorExtensions.put("x-codegen-normalized-input-type", p.dataType);
} else if(Boolean.TRUE.equals(p.isBodyParam)) {
} else if(p.isHeaderParam) {
if(p.required) {
p.vendorExtensions.put("x-codegen-normalized-path-type", "header(\"" + p.baseName + "\")");
p.vendorExtensions.put("x-codegen-normalized-input-type", p.dataType);
} else {
p.vendorExtensions.put("x-codegen-normalized-path-type", "headerOption(\"" + p.baseName + "\")");
p.vendorExtensions.put("x-codegen-normalized-input-type", "Option["+ p.dataType + "]");
}
} else if(p.isQueryParam) {
if(p.isContainer || p.isListContainer) {
p.vendorExtensions.put("x-codegen-normalized-path-type", "params(\"" + p.baseName + "\")");
p.vendorExtensions.put("x-codegen-normalized-input-type", p.dataType.replaceAll("^[^\\[]+", "Seq"));
} else {
p.vendorExtensions.put("x-codegen-normalized-path-type", "param(\"" + p.baseName + "\")");
p.vendorExtensions.put("x-codegen-normalized-input-type", p.dataType);
}
} else if(p.isBodyParam) {
p.vendorExtensions.put("x-codegen-normalized-path-type", "jsonBody["+ p.dataType + "]");
p.vendorExtensions.put("x-codegen-normalized-input-type", p.dataType);
} else if(Boolean.TRUE.equals(p.isContainer) || Boolean.TRUE.equals(p.isListContainer)) {
p.vendorExtensions.put("x-codegen-normalized-path-type", "params(\""+ p.paramName + "\")");
p.vendorExtensions.put("x-codegen-normalized-input-type", p.dataType.replaceAll("^[^\\[]+", "Seq"));
} else if(Boolean.TRUE.equals(p.isFile)) {
p.vendorExtensions.put("x-codegen-normalized-path-type", "fileUpload(\""+ p.paramName + "\")");
} else if(p.isFile) {
p.vendorExtensions.put("x-codegen-normalized-path-type", "fileUpload(\""+ p.baseName + "\")");
p.vendorExtensions.put("x-codegen-normalized-input-type", "FileUpload");
} else {
p.vendorExtensions.put("x-codegen-normalized-path-type", p.dataType);

View File

@@ -32,7 +32,9 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
protected String bundleExtensionName;
protected String bundleAlias;
protected String controllerDirName = "Controller";
protected String serviceDirName = "Service";
protected String controllerPackage;
protected String servicePackage;
protected Boolean phpLegacySupport = Boolean.TRUE;
protected HashSet<String> typeHintable;
@@ -74,7 +76,9 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
modelDocPath = docsBasePath + File.separator + modelDirName;
outputFolder = "generated-code" + File.separator + "php";
apiTemplateFiles.put("api_controller.mustache", ".php");
modelTestTemplateFiles.put("model_test.mustache", ".php");
modelTestTemplateFiles.put("testing/model_test.mustache", ".php");
apiTestTemplateFiles = new HashMap<String, String>();
apiTestTemplateFiles.put("testing/api_test.mustache", ".php");
embeddedTemplateDir = templateDir = "php-symfony";
setReservedWordsLowerCase(
@@ -105,13 +109,10 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
)
);
//instantiationTypes.put("array", "array");
//instantiationTypes.put("map", "map");
defaultIncludes = new HashSet<String>(
Arrays.asList(
"\\DateTime",
"\\SplFileObject"
"UploadedFile"
)
);
@@ -135,7 +136,7 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
typeMapping.put("boolean", "bool");
typeMapping.put("Date", "\\DateTime");
typeMapping.put("DateTime", "\\DateTime");
typeMapping.put("file", "\\SplFileObject");
typeMapping.put("file", "UploadedFile");
typeMapping.put("map", "array");
typeMapping.put("array", "array");
typeMapping.put("list", "array");
@@ -242,6 +243,7 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\"));
additionalProperties.put("controllerPackage", controllerPackage);
additionalProperties.put("servicePackage", servicePackage);
additionalProperties.put("apiTestsPackage", apiTestsPackage);
additionalProperties.put("modelTestsPackage", modelTestsPackage);
@@ -275,14 +277,28 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
supportingFiles.add(new SupportingFile("Extension.mustache", dependencyInjectionDir, bundleExtensionName + ".php"));
supportingFiles.add(new SupportingFile("ApiPass.mustache", dependencyInjectionDir + File.separator + "Compiler", bundleName + "ApiPass.php"));
supportingFiles.add(new SupportingFile("ApiServer.mustache", toPackagePath(apiPackage, srcBasePath), "ApiServer.php"));
supportingFiles.add(new SupportingFile("ModelSerializer.mustache", toPackagePath(modelPackage, srcBasePath), "ModelSerializer.php"));
supportingFiles.add(new SupportingFile("ModelInterface.mustache", toPackagePath(modelPackage, srcBasePath), "ModelInterface.php"));
// Serialization components
supportingFiles.add(new SupportingFile("serialization/SerializerInterface.mustache", toPackagePath(servicePackage, srcBasePath), "SerializerInterface.php"));
supportingFiles.add(new SupportingFile("serialization/JmsSerializer.mustache", toPackagePath(servicePackage, srcBasePath), "JmsSerializer.php"));
supportingFiles.add(new SupportingFile("serialization/StrictJsonDeserializationVisitor.mustache", toPackagePath(servicePackage, srcBasePath), "StrictJsonDeserializationVisitor.php"));
supportingFiles.add(new SupportingFile("serialization/TypeMismatchException.mustache", toPackagePath(servicePackage, srcBasePath), "TypeMismatchException.php"));
// Validation components
supportingFiles.add(new SupportingFile("validation/ValidatorInterface.mustache", toPackagePath(servicePackage, srcBasePath), "ValidatorInterface.php"));
supportingFiles.add(new SupportingFile("validation/SymfonyValidator.mustache", toPackagePath(servicePackage, srcBasePath), "SymfonyValidator.php"));
// Testing components
supportingFiles.add(new SupportingFile("testing/phpunit.xml.mustache", getPackagePath(), "phpunit.xml.dist"));
supportingFiles.add(new SupportingFile("testing/pom.xml", getPackagePath(), "pom.xml"));
supportingFiles.add(new SupportingFile("testing/AppKernel.php", toPackagePath(testsPackage, srcBasePath), "AppKernel.php"));
supportingFiles.add(new SupportingFile("testing/test_config.yml", toPackagePath(testsPackage, srcBasePath), "test_config.yml"));
supportingFiles.add(new SupportingFile("routing.mustache", configDir, "routing.yml"));
supportingFiles.add(new SupportingFile("services.mustache", configDir, "services.yml"));
supportingFiles.add(new SupportingFile("composer.mustache", getPackagePath(), "composer.json"));
supportingFiles.add(new SupportingFile("autoload.mustache", getPackagePath(), "autoload.php"));
supportingFiles.add(new SupportingFile("README.mustache", getPackagePath(), "README.md"));
supportingFiles.add(new SupportingFile("phpunit.xml.mustache", getPackagePath(), "phpunit.xml.dist"));
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"));
@@ -329,6 +345,14 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
if (!typeHint.isEmpty()) {
param.vendorExtensions.put("x-parameterType", typeHint);
}
// Quote default values for strings
// @todo: The default values for headers, forms and query params are handled
// in DefaultCodegen fromParameter with no real possibility to override
// the functionality. Thus we are handling quoting of string values here
if (param.dataType.equals("string") && param.defaultValue != null && !param.defaultValue.isEmpty()) {
param.defaultValue = "'"+param.defaultValue+"'";
}
}
for (CodegenResponse response : op.responses) {
@@ -340,9 +364,6 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
if (response.dataType != null) {
final String dataType = extractSimpleName(response.dataType);
response.vendorExtensions.put("x-simpleName", dataType);
// if (!typeMapping.containsValue(dataType)) {
// imports.add(response.dataType.replaceFirst("\\[\\]$", ""));
// }
}
}
@@ -364,19 +385,15 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
ArrayList<Object> modelsArray = (ArrayList<Object>) objs.get("models");
Map<String, Object> models = (Map<String, Object>) modelsArray.get(0);
CodegenModel model = (CodegenModel) models.get("model");
HashSet<String> imports = new HashSet<>();
// Simplify model var type
for (CodegenProperty var : model.vars) {
if (var.datatype != null) {
final String importType = var.datatype.replaceFirst("\\[\\]$", "");
final String dataType = extractSimpleName(var.datatype);
final boolean isScalarType = typeMapping.containsValue(importType);
var.vendorExtensions.put("x-fullType", var.datatype);
if (!isScalarType) {
var.vendorExtensions.put("x-typeAnnotation", dataType.endsWith("[]") ? "array" : dataType);
imports.add(importType);
var.datatype = dataType;
// Determine if the paramter type is supported as a type hint and make it available
// to the templating engine
String typeHint = getTypeHint(var.datatype);
if (!typeHint.isEmpty()) {
var.vendorExtensions.put("x-parameterType", typeHint);
}
if (var.isBoolean) {
@@ -385,8 +402,6 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
}
}
objs.put("useStatements", new ArrayList<>(imports));
return objs;
}
@@ -425,6 +440,7 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
apiTestsPackage = testsPackage + "\\" + apiDirName;
modelTestsPackage = testsPackage + "\\" + modelDirName;
controllerPackage = invokerPackage + "\\" + controllerDirName;
servicePackage = invokerPackage + "\\" + serviceDirName;
}
@Override
@@ -485,6 +501,26 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
}
}
@Override
public String toEnumValue(String value, String datatype) {
if ("int".equals(datatype) || "double".equals(datatype) || "float".equals(datatype)) {
return value;
} else {
return "\"" + escapeText(value) + "\"";
}
}
/**
* Return the regular expression/JSON schema pattern (http://json-schema.org/latest/json-schema-validation.html#anchor33)
*
* @param pattern the pattern (regular expression)
* @return properly-escaped pattern
*/
@Override
public String toRegularExpression(String pattern) {
return escapeText(pattern);
}
public String toApiName(String name) {
if (name.isEmpty()) {
return "DefaultApiInterface";

View File

@@ -1,6 +1,7 @@
package io.swagger.codegen.languages;
import java.io.File;
import java.lang.StringBuffer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
@@ -82,7 +83,7 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
supportingFiles.add(new SupportingFile("apis.mustache", apiPackage().replace('.', File.separatorChar), "api.ts"));
supportingFiles.add(new SupportingFile("index.mustache", getIndexDirectory(), "index.ts"));
supportingFiles.add(new SupportingFile("api.module.mustache", getIndexDirectory(), "api.module.ts"));
supportingFiles.add(new SupportingFile("rxjs-operators.mustache", getIndexDirectory(), "rxjs-operators.ts"));
supportingFiles.add(new SupportingFile("rxjs-operators.mustache", getIndexDirectory(), "rxjs-operators.ts"));
supportingFiles.add(new SupportingFile("configuration.mustache", getIndexDirectory(), "configuration.ts"));
supportingFiles.add(new SupportingFile("variables.mustache", getIndexDirectory(), "variables.ts"));
supportingFiles.add(new SupportingFile("encoder.mustache", getIndexDirectory(), "encoder.ts"));
@@ -149,7 +150,7 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
public boolean isDataTypeFile(final String dataType) {
return dataType != null && dataType.equals("Blob");
}
@Override
public String getTypeDeclaration(Property p) {
Property inner;
@@ -247,8 +248,54 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
}
}
// Convert path to TypeScript template string, applying URI encoding
op.path = op.path.replaceAll("\\{(.*?)\\}", "\\$\\{encodeURIComponent(String($1))\\}");
// Prep a string buffer where we're going to set up our new version of the string.
StringBuffer pathBuffer = new StringBuffer();
// Set up other variables for tracking the current state of the string.
int insideCurly = 0;
boolean foundUnderscore = false;
// Iterate through existing string, one character at a time.
for(int i = 0; i < op.path.length(); i++) {
switch(op.path.charAt(i)) {
case '{':
// We entered curly braces, so track that.
insideCurly++;
// Add the more complicated component instead of just the brace.
pathBuffer.append("${encodeURIComponent(String(");
break;
case '}':
// We exited curly braces, so track that.
insideCurly--;
// Add the more complicated component instead of just the brace.
pathBuffer.append("))}");
break;
case '_':
// If we're inside the curly brace, the following character will need to be uppercase.
// Otherwise, just add the character.
if (insideCurly > 0) {
foundUnderscore = true;
} else {
pathBuffer.append(op.path.charAt(i));
}
break;
default:
// If we previously found an underscore, we need an uppercase letter.
// Otherwise, just add the character.
if (foundUnderscore) {
pathBuffer.append(Character.toUpperCase(op.path.charAt(i)));
foundUnderscore = false;
} else {
pathBuffer.append(op.path.charAt(i));
}
break;
}
}
// Overwrite path to TypeScript template string, after applying everything we just did.
op.path = pathBuffer.toString();
}
// Add additional filename information for model imports in the services
@@ -272,7 +319,7 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
CodegenModel cm = (CodegenModel) mo.get("model");
mo.put("tsImports", toTsImports(cm,cm.imports));
}
return result;
}

View File

@@ -53,13 +53,16 @@ public class {{classname}} {
{{/returnType}}
* @throws ApiException if fails to make API call
{{#isDeprecated}}
* @Deprecated
* @deprecated
{{/isDeprecated}}
{{#externalDocs}}
* {{description}}
* @see <a href="{{url}}">{{summary}} Documentation</a>
{{/externalDocs}}
*/
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException {
Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
{{#allParams}}{{#required}}

View File

@@ -50,13 +50,16 @@ public class {{classname}} {
{{/returnType}}
* @throws ApiException if fails to make API call
{{#isDeprecated}}
* @Deprecated
* @deprecated
{{/isDeprecated}}
{{#externalDocs}}
* {{description}}
* @see <a href="{{url}}">{{summary}} Documentation</a>
{{/externalDocs}}
*/
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException {
Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
{{#allParams}}{{#required}}

View File

@@ -70,14 +70,20 @@ public class {{classname}} {
* @param progressRequestListener Progress request listener
* @return Call to execute
* @throws ApiException If fail to serialize the request body object
{{#isDeprecated}}
* @deprecated
{{/isDeprecated}}
{{#externalDocs}}
* {{description}}
* @see <a href="{{url}}">{{summary}} Documentation</a>
{{/externalDocs}}
*/
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
public com.squareup.okhttp.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException {
Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
// create path and map variables
String {{localVariablePrefix}}localVarPath = "{{{path}}}"{{#pathParams}}
.replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}};
@@ -122,7 +128,10 @@ public class {{classname}} {
String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };
return {{localVariablePrefix}}apiClient.buildCall({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarCollectionQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAuthNames, progressRequestListener);
}
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
@SuppressWarnings("rawtypes")
private com.squareup.okhttp.Call {{operationId}}ValidateBeforeCall({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException {
{{^performBeanValidation}}
@@ -132,7 +141,7 @@ public class {{classname}} {
throw new ApiException("Missing the required parameter '{{paramName}}' when calling {{operationId}}(Async)");
}
{{/required}}{{/allParams}}
com.squareup.okhttp.Call {{localVariablePrefix}}call = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener);
return {{localVariablePrefix}}call;
@@ -150,7 +159,7 @@ public class {{classname}} {
if (violations.size() == 0) {
com.squareup.okhttp.Call {{localVariablePrefix}}call = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener);
return {{localVariablePrefix}}call;
} else {
throw new BeanValidationException((Set) violations);
}
@@ -161,12 +170,8 @@ public class {{classname}} {
e.printStackTrace();
throw new ApiException(e.getMessage());
}
{{/performBeanValidation}}
}
/**
@@ -175,11 +180,17 @@ public class {{classname}} {
* @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}}{{#returnType}}
* @return {{returnType}}{{/returnType}}
* @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body
{{#isDeprecated}}
* @deprecated
{{/isDeprecated}}
{{#externalDocs}}
* {{description}}
* @see <a href="{{url}}">{{summary}} Documentation</a>
{{/externalDocs}}
*/
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException {
{{#returnType}}ApiResponse<{{{returnType}}}> {{localVariablePrefix}}resp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}}
return {{localVariablePrefix}}resp.getData();{{/returnType}}
@@ -191,11 +202,17 @@ public class {{classname}} {
* @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}}
* @return ApiResponse&lt;{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}&gt;
* @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body
{{#isDeprecated}}
* @deprecated
{{/isDeprecated}}
{{#externalDocs}}
* {{description}}
* @see <a href="{{url}}">{{summary}} Documentation</a>
{{/externalDocs}}
*/
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException {
com.squareup.okhttp.Call {{localVariablePrefix}}call = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null, null);
{{#returnType}}Type {{localVariablePrefix}}localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType();
@@ -209,11 +226,17 @@ public class {{classname}} {
* @param callback The callback to be executed when the API call finishes
* @return The request call
* @throws ApiException If fail to process the API call, e.g. serializing the request body object
{{#isDeprecated}}
* @deprecated
{{/isDeprecated}}
{{#externalDocs}}
* {{description}}
* @see <a href="{{url}}">{{summary}} Documentation</a>
{{/externalDocs}}
*/
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
public com.squareup.okhttp.Call {{operationId}}Async({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{localVariablePrefix}}callback) throws ApiException {
ProgressResponseBody.ProgressListener progressListener = null;

View File

@@ -46,13 +46,16 @@ public class {{classname}} {
* @return {{{returnType}}}{{/returnType}}
* @throws ApiException if fails to make API call
{{#isDeprecated}}
* @Deprecated
* @deprecated
{{/isDeprecated}}
{{#externalDocs}}
* {{description}}
* @see <a href="{{url}}">{{summary}} Documentation</a>
{{/externalDocs}}
*/
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException {
Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
{{#allParams}}{{#required}}

View File

@@ -22,6 +22,16 @@ import javax.validation.constraints.*;
import javax.validation.Valid;
{{/useBeanValidation}}
{{#appName}}
/**
* {{{appName}}}
*
{{#appDescription}}
* <p>{{{appDescription}}}
*
{{/appDescription}}
*/
{{/appName}}
@Path("{{^useAnnotatedBasePath}}/{{/useAnnotatedBasePath}}{{#useAnnotatedBasePath}}{{contextPath}}{{/useAnnotatedBasePath}}")
@Api(value = "/", description = "{{description}}")
{{#addConsumesProducesJson}}
@@ -32,6 +42,16 @@ public interface {{classname}} {
{{#operations}}
{{#operation}}
{{#summary}}
/**
* {{summary}}
*
{{#notes}}
* {{notes}}
*
{{/notes}}
*/
{{/summary}}
@{{httpMethod}}
{{#subresourceOperation}}@Path("{{{path}}}"){{/subresourceOperation}}
{{#hasConsumes}}

View File

@@ -25,9 +25,29 @@ import org.springframework.stereotype.Service;
{{/useSpringAnnotationConfig}}
{{#description}}
{{/description}}
{{#appName}}
/**
* {{{appName}}}
*
{{#appDescription}}
* <p>{{{appDescription}}}
{{/appDescription}}
*
*/
{{/appName}}
public class {{classname}}ServiceImpl implements {{classname}} {
{{#operations}}
{{#operation}}
{{#summary}}
/**
* {{summary}}
*
{{#notes}}
* {{notes}}
*
{{/notes}}
*/
{{/summary}}
public {{>returnTypes}} {{nickname}}({{#allParams}}{{>queryParamsImpl}}{{>pathParamsImpl}}{{>headerParamsImpl}}{{>bodyParamsImpl}}{{>formParamsImpl}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) {
// TODO: Implement...

View File

@@ -42,7 +42,15 @@ import org.springframework.test.context.web.WebAppConfiguration;
/**
* API tests for {{classname}}
{{#appName}}
* {{{appName}}}
*
{{/appName}}
{{#appDescription}}
* <p>{{{appDescription}}}
*
{{/appDescription}}
* API tests for {{classname}}
*/
{{#generateSpringBootApplication}}
@RunWith(SpringJUnit4ClassRunner.class)
@@ -91,10 +99,14 @@ public class {{classname}}Test {
{{#operations}}{{#operation}}
/**
{{#summary}}
* {{summary}}
*
{{#notes}}
* {{notes}}
*
{{/notes}}
{{/summary}}
* @throws ApiException
* if the Api call fails
*/

View File

@@ -17,6 +17,9 @@ import com.fasterxml.jackson.annotation.JsonProperty;
{{^parent}}@XmlRootElement(name="{{classname}}"){{/parent}}
{{/withXml}}
{{#description}}
/**
* {{{description}}}
**/
@ApiModel(description="{{{description}}}")
{{/description}}
public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {
@@ -29,6 +32,11 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {
@XmlElement(name="{{baseName}}"{{#required}}, required = {{required}}{{/required}})
{{/withXml}}
@ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
{{#description}}
/**
* {{{description}}}
**/
{{/description}}
private {{{datatypeWithEnum}}} {{name}} = {{{defaultValue}}};{{/vars}}
{{#vars}}

View File

@@ -4,6 +4,9 @@
<artifactId>{{artifactId}}</artifactId>
<packaging>jar</packaging>
<name>{{artifactId}}</name>
{{#appDescription}}
<description>{{appDescription}}</description>
{{/appDescription}}
<version>{{artifactVersion}}</version>
<build>
<sourceDirectory>src/main/java</sourceDirectory>

View File

@@ -4,6 +4,9 @@
<artifactId>{{artifactId}}</artifactId>
<packaging>war</packaging>
<name>{{artifactId}}</name>
{{#appDescription}}
<description>{{appDescription}}</description>
{{/appDescription}}
<version>{{artifactVersion}}</version>
<build>
<sourceDirectory>src/main/java</sourceDirectory>

View File

@@ -54,7 +54,9 @@ public interface {{classname}} {
@ApiResponse(code = {{{code}}}, message = "{{{message}}}"{{#baseType}}, response = {{{baseType}}}.class{{/baseType}}{{#containerType}}, responseContainer = "{{{containerType}}}"{{/containerType}}){{#hasMore}},{{/hasMore}}{{/responses}} })
{{#implicitHeaders}}
@ApiImplicitParams({
{{#headerParams}}{{>implicitHeader}}{{/headerParams}}
{{#headerParams}}
{{>implicitHeader}}
{{/headerParams}}
})
{{/implicitHeaders}}
@RequestMapping(value = "{{{path}}}",{{#singleContentTypes}}

View File

@@ -1 +1 @@
{{#isPathParam}}{{#useBeanValidation}}{{>beanValidationPathParams}}{{/useBeanValidation}}@ApiParam(value = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}} {{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @PathVariable("{{baseName}}") {{>optionalDataType}} {{paramName}}{{/isPathParam}}
{{#isPathParam}}{{#useBeanValidation}}{{>beanValidationPathParams}}{{/useBeanValidation}}@ApiParam(value = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, allowableValues = "{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @PathVariable("{{baseName}}") {{>optionalDataType}} {{paramName}}{{/isPathParam}}

View File

@@ -1,3 +1,3 @@
{
"presets": ["es2015", "stage-0"]
}
"presets": ["env", "stage-0"]
}

View File

@@ -12,12 +12,12 @@
},
"dependencies": {
"babel": "^6.23.0",
"babel-cli": "^6.24.1",
"babel-cli": "^6.26.0",
"superagent": "3.5.2"
},
"devDependencies": {
"babel-core": "6.18.0",
"babel-preset-es2015": "^6.24.1",
"babel-core": "6.26.0",
"babel-preset-env": "^1.6.1",
"babel-preset-stage-0": "^6.24.1",
"expect.js": "~0.3.1",
"mocha": "~2.3.4",

View File

@@ -4,6 +4,8 @@
-export([request_param_info/2]).
-export([populate_request/3]).
-export([validate_response/4]).
%% exported to silence swagger complains
-export([get_value/3, validate_response_body/4]).
-type operation_id() :: atom().
-type request_param() :: atom().
@@ -212,7 +214,7 @@ validate(Rule = {enum, Values}, Name, Value, _ValidatorState) ->
end;
validate(Rule = {max, Max}, Name, Value, _ValidatorState) ->
case Value >= Max of
case Value =< Max of
true -> ok;
false -> validation_error(Rule, Name)
end;
@@ -224,7 +226,7 @@ validate(Rule = {exclusive_max, ExclusiveMax}, Name, Value, _ValidatorState) ->
end;
validate(Rule = {min, Min}, Name, Value, _ValidatorState) ->
case Value =< Min of
case Value >= Min of
true -> ok;
false -> validation_error(Rule, Name)
end;
@@ -290,6 +292,8 @@ validation_error(ViolatedRule, Name) ->
validation_error(ViolatedRule, Name, Info) ->
throw({wrong_param, Name, ViolatedRule, Info}).
-spec get_value(body | qs_val | header | binding, Name :: any(), Req0 :: cowboy_req:req()) ->
{Value :: any(), Req :: cowboy_req:req()}.
get_value(body, _Name, Req0) ->
{ok, Body, Req} = cowboy_req:body(Req0),
Value = prepare_body(Body),

View File

@@ -24,8 +24,12 @@ authorize_api_key(LogicHandler, OperationID, From, KeyParam, Req0) ->
ApiKey
),
case Result of
{{#authMethods}}
{{#isApiKey}}
{true, Context} ->
{true, Context, Req};
{{/isApiKey}}
{{/authMethods}}
false ->
AuthHeader = <<"">>,
{false, AuthHeader, Req}

View File

@@ -94,13 +94,15 @@ is_authorized(
end;
{{/isApiKey}}
{{/authMethods}}
{{/operation}}{{/operations}}
{{^authMethods}}
is_authorized(Req, State) ->
{true, Req, State};
{true, Req, State}.
{{/authMethods}}
{{/operation}}{{/operations}}
{{#authMethods}}
is_authorized(Req, State) ->
{{false, <<"">>}, Req, State}.
{{/authMethods}}
-spec content_types_accepted(Req :: cowboy_req:req(), State :: state()) ->
{

View File

@@ -1,11 +1,7 @@
-module({{packageName}}_logic_handler).
-export([handle_request/4]).
{{#authMethods}}
{{#isApiKey}}
-export([authorize_api_key/3]).
{{/isApiKey}}
{{/authMethods}}
-type context() :: #{binary() => any()}.
-type handler_response() ::{
Status :: cowboy:http_status(),
@@ -48,3 +44,9 @@ authorize_api_key(Handler, OperationID, ApiKey) ->
Handler:authorize_api_key(OperationID, ApiKey).
{{/isApiKey}}
{{/authMethods}}
{{^authMethods}}
-spec authorize_api_key(Handler :: atom(), OperationID :: {{packageName}}_api:operation_id(), ApiKey :: binary()) ->
Result :: false.
authorize_api_key(_Handler, _OperationID, _ApiKey) ->
false.
{{/authMethods}}

View File

@@ -9,6 +9,7 @@
-spec child_spec( ID :: any(), #{
ip => inet:ip_address(),
port => inet:port_number(),
logic_handler => module(),
net_opts => []
}) -> supervisor:child_spec().

View File

@@ -1,6 +1,7 @@
# coding: utf-8
# flake8: noqa
from __future__ import absolute_import
# import models into model package
{{#models}}{{#model}}from .{{classFilename}} import {{classname}}{{/model}}
{{#models}}{{#model}}from {{modelPackage}}.{{classFilename}} import {{classname}}{{/model}}
{{/models}}

View File

@@ -1,8 +1,10 @@
from flask_testing import TestCase
from ..encoder import JSONEncoder
import connexion
import logging
import connexion
from flask_testing import TestCase
from {{packageName}}.encoder import JSONEncoder
class BaseTestCase(TestCase):

View File

@@ -6,11 +6,16 @@
{{/supportPython2}}
import connexion
from .encoder import JSONEncoder
from {{packageName}} import encoder
def main():
app = connexion.App(__name__, specification_dir='./swagger/')
app.app.json_encoder = encoder.JSONEncoder
app.add_api('swagger.yaml', arguments={'title': '{{appName}}'})
app.run(port={{serverPort}})
if __name__ == '__main__':
app = connexion.App(__name__, specification_dir='./swagger/')
app.app.json_encoder = JSONEncoder
app.add_api('swagger.yaml', arguments={'title': '{{appDescription}}'})
app.run(port={{serverPort}})
main()

View File

@@ -1,38 +1,39 @@
from pprint import pformat
import pprint
import six
{{^supportPython2}}
from typing import TypeVar, Type
import typing
{{/supportPython2}}
from six import iteritems
from ..util import deserialize_model
from {{packageName}} import util
{{^supportPython2}}
T = TypeVar('T')
T = typing.TypeVar('T')
{{/supportPython2}}
class Model(object):
# swaggerTypes: The key is attribute name and the value is attribute type.
# swaggerTypes: The key is attribute name and the
# value is attribute type.
swagger_types = {}
# attributeMap: The key is attribute name and the value is json key in definition.
# attributeMap: The key is attribute name and the
# value is json key in definition.
attribute_map = {}
@classmethod
def from_dict(cls{{^supportPython2}}: Type[T]{{/supportPython2}}, dikt){{^supportPython2}} -> T{{/supportPython2}}:
"""
Returns the dict as a model
"""
return deserialize_model(dikt, cls)
def from_dict(cls{{^supportPython2}}: typing.Type[T]{{/supportPython2}}, dikt){{^supportPython2}} -> T{{/supportPython2}}:
"""Returns the dict as a model"""
return util.deserialize_model(dikt, cls)
def to_dict(self):
"""
Returns the model properties as a dict
"""Returns the model properties as a dict
:rtype: dict
"""
result = {}
for attr, _ in iteritems(self.swagger_types):
for attr, _ in six.iteritems(self.swagger_types):
value = getattr(self, attr)
if isinstance(value, list):
result[attr] = list(map(
@@ -53,27 +54,20 @@ class Model(object):
return result
def to_str(self):
"""
Returns the string representation of the model
"""Returns the string representation of the model
:rtype: str
"""
return pformat(self.to_dict())
return pprint.pformat(self.to_dict())
def __repr__(self):
"""
For `print` and `pprint`
"""
"""For `print` and `pprint`"""
return self.to_str()
def __eq__(self, other):
"""
Returns true if both objects are equal
"""
"""Returns true if both objects are equal"""
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""
Returns true if both objects are not equal
"""
return not self == other
"""Returns true if both objects are not equal"""
return not self == other

View File

@@ -1,18 +1,18 @@
import connexion
{{#imports}}{{import}}
import six
{{#imports}}{{import}} # noqa: E501
{{/imports}}
from datetime import date, datetime
from typing import List, Dict
from six import iteritems
from ..util import deserialize_date, deserialize_datetime
from {{packageName}} import util
{{#operations}}
{{#operation}}
def {{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}):
"""
{{#summary}}{{.}}{{/summary}}{{^summary}}{{operationId}}{{/summary}}
{{#notes}}{{.}}{{/notes}}
def {{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}): # noqa: E501
"""{{#summary}}{{.}}{{/summary}}{{^summary}}{{operationId}}{{/summary}}
{{#notes}}{{.}}{{/notes}} # noqa: E501
{{#allParams}}
:param {{paramName}}: {{description}}
{{^isContainer}}
@@ -55,15 +55,15 @@ def {{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{
{{#allParams}}
{{^isContainer}}
{{#isDate}}
{{paramName}} = deserialize_date({{paramName}})
{{paramName}} = util.deserialize_date({{paramName}})
{{/isDate}}
{{#isDateTime}}
{{paramName}} = deserialize_datetime({{paramName}})
{{paramName}} = util.deserialize_datetime({{paramName}})
{{/isDateTime}}
{{^isPrimitiveType}}
{{^isFile}}
if connexion.request.is_json:
{{paramName}} = {{baseType}}.from_dict(connexion.request.get_json())
{{paramName}} = {{baseType}}.from_dict(connexion.request.get_json()) # noqa: E501
{{/isFile}}
{{/isPrimitiveType}}
{{/isContainer}}
@@ -71,15 +71,15 @@ def {{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{
{{#items}}
{{#isDate}}
if connexion.request.is_json:
{{paramName}} = [deserialize_date(s) for s in connexion.request.get_json()]
{{paramName}} = [util.deserialize_date(s) for s in connexion.request.get_json()] # noqa: E501
{{/isDate}}
{{#isDateTime}}
if connexion.request.is_json:
{{paramName}} = [deserialize_datetime(s) for s in connexion.request.get_json()]
{{paramName}} = [util.deserialize_datetime(s) for s in connexion.request.get_json()] # noqa: E501
{{/isDateTime}}
{{#complexType}}
if connexion.request.is_json:
{{paramName}} = [{{complexType}}.from_dict(d) for d in connexion.request.get_json()]
{{paramName}} = [{{complexType}}.from_dict(d) for d in connexion.request.get_json()] # noqa: E501
{{/complexType}}
{{/items}}
{{/isListContainer}}
@@ -87,15 +87,15 @@ def {{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{
{{#items}}
{{#isDate}}
if connexion.request.is_json:
{{paramName}} = {k: deserialize_date(v) for k, v in iteritems(connexion.request.get_json())}
{{paramName}} = {k: util.deserialize_date(v) for k, v in six.iteritems(connexion.request.get_json())} # noqa: E501
{{/isDate}}
{{#isDateTime}}
if connexion.request.is_json:
{{paramName}} = {k: deserialize_datetime(v) for k, v in iteritems(connexion.request.get_json())}
{{paramName}} = {k: util.deserialize_datetime(v) for k, v in six.iteritems(connexion.request.get_json())} # noqa: E501
{{/isDateTime}}
{{#complexType}}
if connexion.request.is_json:
{{paramName}} = {k: {{baseType}}.from_dict(v) for k, v in iteritems(connexion.request.get_json())}
{{paramName}} = {k: {{baseType}}.from_dict(v) for k, v in six.iteritems(connexion.request.get_json())} # noqa: E501
{{/complexType}}
{{/items}}
{{/isMapContainer}}

View File

@@ -2,20 +2,20 @@
from __future__ import absolute_import
{{#imports}}{{import}}
{{/imports}}
from . import BaseTestCase
from six import BytesIO
from flask import json
from six import BytesIO
{{#imports}}{{import}} # noqa: E501
{{/imports}}
from {{packageName}}.test import BaseTestCase
class {{#operations}}Test{{classname}}(BaseTestCase):
""" {{classname}} integration test stubs """
"""{{classname}} integration test stubs"""
{{#operation}}
def test_{{operationId}}(self):
"""
Test case for {{{operationId}}}
"""Test case for {{{operationId}}}
{{{summary}}}
"""
@@ -31,15 +31,17 @@ class {{#operations}}Test{{classname}}(BaseTestCase):
{{#formParams}}
{{#-first}}data = dict({{/-first}}{{^-first}} {{/-first}}{{paramName}}={{{example}}}{{#hasMore}},{{/hasMore}}{{#-last}}){{/-last}}
{{/formParams}}
response = self.client.open('{{#contextPath}}{{{.}}}{{/contextPath}}{{{path}}}'{{#pathParams}}{{#-first}}.format({{/-first}}{{paramName}}={{{example}}}{{#hasMore}}, {{/hasMore}}{{^hasMore}}){{/hasMore}}{{/pathParams}},
method='{{httpMethod}}'{{#bodyParam}},
data=json.dumps({{paramName}}){{^consumes}},
content_type='application/json'{{/consumes}}{{/bodyParam}}{{#headerParams}}{{#-first}},
headers=headers{{/-first}}{{/headerParams}}{{#formParams}}{{#-first}},
data=data{{/-first}}{{/formParams}}{{#consumes}}{{#-first}},
content_type='{{{mediaType}}}'{{/-first}}{{/consumes}}{{#queryParams}}{{#-first}},
query_string=query_string{{/-first}}{{/queryParams}})
self.assert200(response, "Response body is : " + response.data.decode('utf-8'))
response = self.client.open(
'{{#contextPath}}{{{.}}}{{/contextPath}}{{{path}}}'{{#pathParams}}{{#-first}}.format({{/-first}}{{paramName}}={{{example}}}{{#hasMore}}, {{/hasMore}}{{^hasMore}}){{/hasMore}}{{/pathParams}},
method='{{httpMethod}}'{{#bodyParam}},
data=json.dumps({{paramName}}){{^consumes}},
content_type='application/json'{{/consumes}}{{/bodyParam}}{{#headerParams}}{{#-first}},
headers=headers{{/-first}}{{/headerParams}}{{#formParams}}{{#-first}},
data=data{{/-first}}{{/formParams}}{{#consumes}}{{#-first}},
content_type='{{{mediaType}}}'{{/-first}}{{/consumes}}{{#queryParams}}{{#-first}},
query_string=query_string{{/-first}}{{/queryParams}})
self.assert200(response,
'Response body is : ' + response.data.decode('utf-8'))
{{/operation}}
{{/operations}}

View File

@@ -1,6 +1,8 @@
from six import iteritems
from {{modelPackage}}.base_model_ import Model
from connexion.apps.flask_app import FlaskJSONEncoder
import six
from {{modelPackage}}.base_model_ import Model
class JSONEncoder(FlaskJSONEncoder):
include_nulls = False
@@ -8,11 +10,11 @@ class JSONEncoder(FlaskJSONEncoder):
def default(self, o):
if isinstance(o, Model):
dikt = {}
for attr, _ in iteritems(o.swagger_types):
for attr, _ in six.iteritems(o.swagger_types):
value = getattr(o, attr)
if value is None and not self.include_nulls:
continue
attr = o.attribute_map[attr]
dikt[attr] = value
return dikt
return FlaskJSONEncoder.default(self, o)
return FlaskJSONEncoder.default(self, o)

View File

@@ -28,7 +28,7 @@ git init
# Adds the files in the local repository and stages them for commit.
git add .
# Commits the tracked changes and prepares them to be pushed to a remote repository.
# Commits the tracked changes and prepares them to be pushed to a remote repository.
git commit -m "$release_note"
# Sets the new remote

View File

@@ -1,73 +1,74 @@
# coding: utf-8
from __future__ import absolute_import
{{#imports}}{{import}}
from datetime import date, datetime # noqa: F401
from typing import List, Dict # noqa: F401
from {{modelPackage}}.base_model_ import Model
{{#imports}}{{import}} # noqa: E501
{{/imports}}
from .base_model_ import Model
from datetime import date, datetime
from typing import List, Dict
from ..util import deserialize_model
from {{packageName}} import util
{{#models}}
{{#model}}
class {{classname}}(Model):
"""
NOTE: This class is auto generated by the swagger code generator program.
Do not edit the class manually.
"""
"""NOTE: This class is auto generated by the swagger code generator program.
Do not edit the class manually.
"""{{#allowableValues}}
{{#allowableValues}}
"""
allowed enum values
"""
{{#enumVars}}
{{name}} = {{{value}}}
{{/enumVars}}
{{/allowableValues}}
{{name}} = {{{value}}}{{^-last}}
{{/-last}}
{{/enumVars}}{{/allowableValues}}
def __init__(self{{#vars}}, {{name}}{{^supportPython2}}: {{datatype}}{{/supportPython2}}={{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}None{{/defaultValue}}{{/vars}}):
"""
{{classname}} - a model defined in Swagger
def __init__(self{{#vars}}, {{name}}{{^supportPython2}}: {{datatype}}{{/supportPython2}}={{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}None{{/defaultValue}}{{/vars}}): # noqa: E501
"""{{classname}} - a model defined in Swagger
{{#vars}}
:param {{name}}: The {{name}} of this {{classname}}.
:param {{name}}: The {{name}} of this {{classname}}. # noqa: E501
:type {{name}}: {{datatype}}
{{/vars}}
"""
self.swagger_types = {
{{#vars}}'{{name}}': {{{datatype}}}{{#hasMore}},
{{/hasMore}}{{/vars}}
{{#vars}}
'{{name}}': {{{datatype}}}{{#hasMore}},{{/hasMore}}
{{/vars}}
}
self.attribute_map = {
{{#vars}}'{{name}}': '{{baseName}}'{{#hasMore}},
{{/hasMore}}{{/vars}}
}
{{#vars}}
'{{name}}': '{{baseName}}'{{#hasMore}},{{/hasMore}}
{{/vars}}
}
{{#vars}}{{#-first}}
{{/-first}}
self._{{name}} = {{name}}
{{/vars}}
@classmethod
def from_dict(cls, dikt){{^supportPython2}} -> '{{classname}}'{{/supportPython2}}:
"""
Returns the dict as a model
"""Returns the dict as a model
:param dikt: A dict.
:type: dict
:return: The {{name}} of this {{classname}}.
:return: The {{name}} of this {{classname}}. # noqa: E501
:rtype: {{classname}}
"""
return deserialize_model(dikt, cls)
{{#vars}}{{#-first}}
return util.deserialize_model(dikt, cls){{#vars}}{{#-first}}
{{/-first}}
@property
def {{name}}(self){{^supportPython2}} -> {{datatype}}{{/supportPython2}}:
"""
Gets the {{name}} of this {{classname}}.
"""Gets the {{name}} of this {{classname}}.
{{#description}}
{{{description}}}
{{{description}}} # noqa: E501
{{/description}}
:return: The {{name}} of this {{classname}}.
@@ -77,31 +78,31 @@ class {{classname}}(Model):
@{{name}}.setter
def {{name}}(self, {{name}}{{^supportPython2}}: {{datatype}}{{/supportPython2}}):
"""
Sets the {{name}} of this {{classname}}.
"""Sets the {{name}} of this {{classname}}.
{{#description}}
{{{description}}}
{{{description}}} # noqa: E501
{{/description}}
:param {{name}}: The {{name}} of this {{classname}}.
:type {{name}}: {{datatype}}
"""
{{#isEnum}}
allowed_values = [{{#allowableValues}}{{#values}}"{{{this}}}"{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}]
allowed_values = [{{#allowableValues}}{{#values}}"{{{this}}}"{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501
{{#isContainer}}
{{#isListContainer}}
if not set({{{name}}}).issubset(set(allowed_values)):
raise ValueError(
"Invalid values for `{{{name}}}` [{0}], must be a subset of [{1}]"
.format(", ".join(map(str, set({{{name}}})-set(allowed_values))),
"Invalid values for `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501
.format(", ".join(map(str, set({{{name}}})-set(allowed_values))), # noqa: E501
", ".join(map(str, allowed_values)))
)
{{/isListContainer}}
{{#isMapContainer}}
if not set({{{name}}}.keys()).issubset(set(allowed_values)):
raise ValueError(
"Invalid keys in `{{{name}}}` [{0}], must be a subset of [{1}]"
.format(", ".join(map(str, set({{{name}}}.keys())-set(allowed_values))),
"Invalid keys in `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501
.format(", ".join(map(str, set({{{name}}}.keys())-set(allowed_values))), # noqa: E501
", ".join(map(str, allowed_values)))
)
{{/isMapContainer}}
@@ -117,42 +118,44 @@ class {{classname}}(Model):
{{^isEnum}}
{{#required}}
if {{name}} is None:
raise ValueError("Invalid value for `{{name}}`, must not be `None`")
raise ValueError("Invalid value for `{{name}}`, must not be `None`") # noqa: E501
{{/required}}
{{#hasValidation}}
{{#maxLength}}
if {{name}} is not None and len({{name}}) > {{maxLength}}:
raise ValueError("Invalid value for `{{name}}`, length must be less than or equal to `{{maxLength}}`")
raise ValueError("Invalid value for `{{name}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501
{{/maxLength}}
{{#minLength}}
if {{name}} is not None and len({{name}}) < {{minLength}}:
raise ValueError("Invalid value for `{{name}}`, length must be greater than or equal to `{{minLength}}`")
raise ValueError("Invalid value for `{{name}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501
{{/minLength}}
{{#maximum}}
if {{name}} is not None and {{name}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}:
raise ValueError("Invalid value for `{{name}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`")
if {{name}} is not None and {{name}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501
raise ValueError("Invalid value for `{{name}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501
{{/maximum}}
{{#minimum}}
if {{name}} is not None and {{name}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}:
raise ValueError("Invalid value for `{{name}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`")
if {{name}} is not None and {{name}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501
raise ValueError("Invalid value for `{{name}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501
{{/minimum}}
{{#pattern}}
if {{name}} is not None and not re.search('{{{vendorExtensions.x-regex}}}', {{name}}{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}):
raise ValueError("Invalid value for `{{name}}`, must be a follow pattern or equal to `{{{pattern}}}`")
if {{name}} is not None and not re.search('{{{vendorExtensions.x-regex}}}', {{name}}{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501
raise ValueError("Invalid value for `{{name}}`, must be a follow pattern or equal to `{{{pattern}}}`") # noqa: E501
{{/pattern}}
{{#maxItems}}
if {{name}} is not None and len({{name}}) > {{maxItems}}:
raise ValueError("Invalid value for `{{name}}`, number of items must be less than or equal to `{{maxItems}}`")
raise ValueError("Invalid value for `{{name}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501
{{/maxItems}}
{{#minItems}}
if {{name}} is not None and len({{name}}) < {{minItems}}:
raise ValueError("Invalid value for `{{name}}`, number of items must be greater than or equal to `{{minItems}}`")
raise ValueError("Invalid value for `{{name}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501
{{/minItems}}
{{/hasValidation}}
{{/isEnum}}
self._{{name}} = {{name}}
self._{{name}} = {{name}}{{^-last}}
{{/-last}}
{{/vars}}
{{/model}}
{{/models}}
{{/models}}

View File

@@ -26,6 +26,8 @@ setup(
packages=find_packages(),
package_data={'': ['swagger/swagger.yaml']},
include_package_data=True,
entry_points={
'console_scripts': ['{{packageName}}={{packageName}}.__main__:main']},
long_description="""\
{{appDescription}}
"""

View File

@@ -4,7 +4,7 @@ envlist = {{#supportPython2}}py27, {{/supportPython2}}py35
[testenv]
deps=-r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
commands=
nosetests \
[]

View File

@@ -1,11 +1,11 @@
from typing import GenericMeta
from datetime import datetime, date
from six import integer_types, iteritems
import datetime
import six
import typing
def _deserialize(data, klass):
"""
Deserializes dict, list, str into an object.
"""Deserializes dict, list, str into an object.
:param data: dict, list or str.
:param klass: class literal, or string of class name.
@@ -15,15 +15,15 @@ def _deserialize(data, klass):
if data is None:
return None
if klass in integer_types or klass in (float, str, bool):
if klass in six.integer_types or klass in (float, str, bool):
return _deserialize_primitive(data, klass)
elif klass == object:
return _deserialize_object(data)
elif klass == date:
elif klass == datetime.date:
return deserialize_date(data)
elif klass == datetime:
elif klass == datetime.datetime:
return deserialize_datetime(data)
elif type(klass) == GenericMeta:
elif type(klass) == typing.GenericMeta:
if klass.__extra__ == list:
return _deserialize_list(data, klass.__args__[0])
if klass.__extra__ == dict:
@@ -33,8 +33,7 @@ def _deserialize(data, klass):
def _deserialize_primitive(data, klass):
"""
Deserializes to primitive type.
"""Deserializes to primitive type.
:param data: data to deserialize.
:param klass: class literal.
@@ -52,8 +51,7 @@ def _deserialize_primitive(data, klass):
def _deserialize_object(value):
"""
Return a original value.
"""Return a original value.
:return: object.
"""
@@ -61,8 +59,7 @@ def _deserialize_object(value):
def deserialize_date(string):
"""
Deserializes string to date.
"""Deserializes string to date.
:param string: str.
:type string: str
@@ -77,8 +74,7 @@ def deserialize_date(string):
def deserialize_datetime(string):
"""
Deserializes string to datetime.
"""Deserializes string to datetime.
The string should be in iso8601 datetime format.
@@ -95,8 +91,7 @@ def deserialize_datetime(string):
def deserialize_model(data, klass):
"""
Deserializes list or dict to model.
"""Deserializes list or dict to model.
:param data: dict, list.
:type data: dict | list
@@ -108,7 +103,7 @@ def deserialize_model(data, klass):
if not instance.swagger_types:
return data
for attr, attr_type in iteritems(instance.swagger_types):
for attr, attr_type in six.iteritems(instance.swagger_types):
if data is not None \
and instance.attribute_map[attr] in data \
and isinstance(data, (list, dict)):
@@ -119,8 +114,7 @@ def deserialize_model(data, klass):
def _deserialize_list(data, boxed_type):
"""
Deserializes a list and its elements.
"""Deserializes a list and its elements.
:param data: list to deserialize.
:type data: list
@@ -133,10 +127,8 @@ def _deserialize_list(data, boxed_type):
for sub_data in data]
def _deserialize_dict(data, boxed_type):
"""
Deserializes a dict and its elements.
"""Deserializes a dict and its elements.
:param data: dict to deserialize.
:type data: dict
@@ -146,4 +138,4 @@ def _deserialize_dict(data, boxed_type):
:rtype: dict
"""
return {k: _deserialize(v, boxed_type)
for k, v in iteritems(data)}
for k, v in six.iteritems(data)}

View File

@@ -19,9 +19,10 @@
namespace {{controllerPackage}};
use Symfony\Bundle\FrameworkBundle\Controller\Controller as BaseController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use {{servicePackage}}\SerializerInterface;
use {{servicePackage}}\ValidatorInterface;
/**
* Controller Class Doc Comment
@@ -31,212 +32,141 @@ use Symfony\Component\HttpKernel\Exception\HttpException;
* @author Swagger Codegen team
* @link https://github.com/swagger-api/swagger-codegen
*/
class Controller extends BaseController
class Controller
{
protected $validator;
protected $serializer;
protected $apiServer;
/**
* This will return a response with code 400. Usage example:
* return $this->createBadRequestResponse('Unable to access this page!');
*
* @param string $message A message
*
* @return Response
*/
public function createBadRequestResponse($message = 'Bad Request.')
{
return new Response($message, 400);
}
public function setValidator(ValidatorInterface $validator)
{
$this->validator = $validator;
}
/**
* This will return an error response. Usage example:
* return $this->createErrorResponse(new UnauthorizedHttpException());
*
* @param HttpException $exception An HTTP exception
*
* @return Response
*/
public function createErrorResponse(HttpException $exception)
{
$statusCode = $exception->getStatusCode();
$headers = array_merge($exception->getHeaders(), ['Content-Type' => 'application/json']);
public function setSerializer(SerializerInterface $serializer)
{
$this->serializer = $serializer;
}
$json = $this->exceptionToArray($exception);
$json['statusCode'] = $statusCode;
public function setApiServer($server)
{
$this->apiServer = $server;
}
return new Response(json_encode($json, 15, 512), $statusCode, $headers);
}
/**
* This will return a response with code 400. Usage example:
* return $this->createBadRequestResponse('Unable to access this page!');
*
* @param string $message A message
*
* @return Response
*/
public function createBadRequestResponse($message = 'Bad Request.')
{
return new Response($message, 400);
}
/**
* Serializes data to a given type format.
*
* @param mixed $data The data to serialize.
* @param string $class The source data class.
* @param string $format The target serialization format.
*
* @return string A serialized data string.
*/
public function serialize($data, $format)
{
return $this->get('{{bundleAlias}}.model.model_serializer')->serialize($data, $format);
}
/**
* This will return an error response. Usage example:
* return $this->createErrorResponse(new UnauthorizedHttpException());
*
* @param HttpException $exception An HTTP exception
*
* @return Response
*/
public function createErrorResponse(HttpException $exception)
{
$statusCode = $exception->getStatusCode();
$headers = array_merge($exception->getHeaders(), ['Content-Type' => 'application/json']);
/**
* Deserializes data from a given type format.
*
* @param string $data The data to deserialize.
* @param string $class The target data class.
* @param string $format The source serialization format.
*
* @return mixed A deserialized data.
*/
public function deserialize($data, $class, $format)
{
return $this->get('{{bundleAlias}}.model.model_serializer')->deserialize($data, $class, $format);
}
$json = $this->exceptionToArray($exception);
$json['statusCode'] = $statusCode;
/**
* Decodes a string value.
*
* @param string $string The string value to decode.
* @param string $dataType The data type of the parameter.
*
* @return mixed The decoded value.
*/
public function fromString($string, $dataType)
{
if ($dataType === 'integer' || $dataType === 'number') {
return $this->toNumber($string);
}
if ($dataType === 'bool') {
return $this->toBoolean($string);
}
if ($dataType === '\DateTime') {
return $this->toDateTime($string);
}
return new Response(json_encode($json, 15, 512), $statusCode, $headers);
}
return $string;
}
/**
* Serializes data to a given type format.
*
* @param mixed $data The data to serialize.
* @param string $class The source data class.
* @param string $format The target serialization format.
*
* @return string A serialized data string.
*/
protected function serialize($data, $format)
{
return $this->serializer->serialize($data, $format);
}
/**
* Decodes a header value.
*
* @param string $header The header value to decode.
* @param string $dataType The data type of the parameter.
*
* @return mixed The decoded value.
*/
public function fromHeader($header, $dataType)
{
return $this->fromString($header, $dataType);
}
/**
* Deserializes data from a given type format.
*
* @param string $data The data to deserialize.
* @param string $class The target data class.
* @param string $format The source serialization format.
*
* @return mixed A deserialized data.
*/
protected function deserialize($data, $class, $format)
{
return $this->serializer->deserialize($data, $class, $format);
}
/**
* Decodes a query value.
*
* @param string $query The query value to decode.
* @param string $dataType The data type of the parameter.
*
* @return mixed The decoded value.
*/
public function fromQuery($query, $dataType)
{
return $this->fromString($query, $dataType);
}
protected function validate($data, $asserts = null)
{
$errors = $this->validator->validate($data, $asserts);
/**
* Decodes a path value.
*
* @param string $path The path value to decode.
* @param string $dataType The data type of the parameter.
*
* @return mixed The decoded value.
*/
public function fromPath($path, $dataType)
{
return $this->fromString($path, $dataType);
}
if (count($errors) > 0) {
$errorsString = (string)$errors;
return $this->createBadRequestResponse($errorsString);
}
}
/**
* Decodes a form value.
*
* @param string $form The form value to decode.
* @param string $dataType The data type of the parameter.
*
* @return mixed The decoded value.
*/
public function fromForm($form, $dataType)
{
return $this->fromString($form, $dataType);
}
/**
* Converts an exception to a serializable array.
*
* @param \Exception|null $exception
*
* @return array
*/
private function exceptionToArray(\Exception $exception = null)
{
if (null === $exception) {
return null;
}
/**
* Decoded a string to a number.
*
* @param string $string The string to decode.
*
* @return number|null A decoded number, or null, if not a valid string.
*/
private function toNumber($string)
{
if (is_numeric($string)) {
return $string + 0;
}
return [
'message' => $exception->getMessage(),
'type' => get_class($exception),
'previous' => $this->exceptionToArray($exception->getPrevious()),
];
}
return null;
}
protected function getOutputFormat($accept, array $produced)
{
// Figure out what the client accepts
$accept = preg_split("/[\s,]+/", $accept);
if (in_array('*/*', $accept) || in_array('application/*', $accept)) {
// Prefer JSON if the client has no preference
if (in_array('application/json', $produced)) {
return 'application/json';
}
if (in_array('application/xml', $produced)) {
return 'application/xml';
}
}
/**
* Decoded a string to a boolean.
*
* @param string $string The string to decode.
*
* @return boolean|null A decoded boolean, or null, if not a valid string.
*/
private function toBoolean($string)
{
if ($string === 'true') {
return true;
}
if ($string === 'false') {
return false;
}
if (in_array('application/json', $accept) && in_array('application/json', $produced)) {
return 'application/json';
}
return null;
}
if (in_array('application/xml', $accept) && in_array('application/xml', $produced)) {
return 'application/xml';
}
/**
* Decoded a string to a date time.
*
* @param string $string The string to decode.
*
* @return \DateTime|null A decoded date time, or null, if not a valid string.
*/
private function toDateTime($string)
{
if ($dateTime = date_create($string)) {
return $dateTime;
}
return null;
}
/**
* Converts an exception to a serializable array.
*
* @param \Exception|null $exception
*
* @return array
*/
private function exceptionToArray(\Exception $exception = null)
{
if (null === $exception) {
return null;
}
return [
'message' => $exception->getMessage(),
'type' => get_class($exception),
'previous' => $this->exceptionToArray($exception->getPrevious()),
];
}
// If we reach this point, we don't have a common ground between server and client
return null;
}
}

View File

@@ -1,55 +0,0 @@
<?php
/**
* ModelInterface
*
* PHP version 5
*
* @category Class
* @package {{modelPackage}}
* @author Swagger Codegen team
* @link https://github.com/swagger-api/swagger-codegen
*/
{{>partial_header}}
/**
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen
* Do not edit the class manually.
*/
namespace {{modelPackage}};
/**
* Interface abstracting model access.
*
* @package {{modelPackage}}
* @author Swagger Codegen team
*/
interface ModelInterface
{
/**
* The original name of the model.
*
* @return string
*/
public function modelName();
/**
* Array of property to mappings.
*
* @return array[]
*/
public function modelAttributes();
/**
* Validate all the properties in the model
*
* Return true if all passed.
*
* @return bool True if all properties are valid
*/
public function isValid();
}

View File

@@ -1,174 +0,0 @@
<?php
/**
* ModelSerializer
*
* PHP version 5
*
* @category Class
* @package {{modelPackage}}
* @author Swagger Codegen team
* @link https://github.com/swagger-api/swagger-codegen
*/
{{>partial_header}}
/**
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen
* Do not edit the class manually.
*/
namespace {{modelPackage}};
/**
* ModelSerializer Class Doc Comment
*
* @category Class
* @package {{modelPackage}}
* @author Swagger Codegen team
* @link https://github.com/swagger-api/swagger-codegen
*/
class ModelSerializer
{
/**
* Serializes data to a given type format.
*
* @param mixed $data The data to serialize.
* @param string $format The target serialization format.
*
* @return string A serialized data string.
* @throws \InvalidArgumentException When invalid serialization format was used.
*/
public function serialize($data, $format)
{
$normalized = $this->normalize($data);
if ($format === 'json') {
return json_encode($normalized, 15, 512);
}
throw new \InvalidArgumentException('Unsupported serialization format: '.$format);
}
/**
* Deserializes data from a given type format.
*
* @param string $data The data to deserialize.
* @param string $class The target class to deserialize to.
* @param string $format The source serialization format.
*
* @return mixed A deserialized value.
* @throws \InvalidArgumentException When invalid serialization format was used.
*/
public function deserialize($data, $class, $format)
{
switch ($format) {
case 'json':
$normalized = json_decode($data, true, 512, 15);
break;
default:
throw new \InvalidArgumentException('Unsupported serialization format: '.$format);
}
return $this->denormalize($normalized, $class);
}
public function normalize($data, $format = null)
{
if (is_scalar($data) || null === $data) {
return $data;
}
if (is_array($data)) {
return array_map(function ($value) use ($format) {
return $this->normalize($value, $format);
}, $data);
}
if ($data instanceof \DateTime) {
return ($format === 'date') ? $data->format('Y-m-d') : $data->format(\DateTime::ATOM);
}
if ($data instanceof ModelInterface) {
$values = [];
foreach ($data->modelAttributes() as $name => $attribute) {
list($baseName, , $format, , $getter) = $attribute;
$value = $this->normalize($data->$getter(), $format);
if ($value !== null && method_exists($data, 'getAllowableEnumValues')
&& !in_array($value, $data::getAllowableEnumValues())) {
$imploded = implode("', '", $data::getAllowableEnumValues());
throw new \InvalidArgumentException("Invalid value for enum '$data', must be one of: '$imploded'");
}
if ($value !== null) {
$values[$baseName] = $value;
}
}
return $values;
}
return (string) $data;
}
public function denormalize($data, $class, $format = null)
{
if ($data === null) {
return null;
}
if (in_array($class, ['DateTime', 'bool', 'boolean', 'byte', 'double', 'float', 'int', 'integer', 'mixed', 'number', 'object', 'string', 'void'], true)) {
settype($data, $class);
return $data;
}
// Denormalize array
if (substr($class, -2) === '[]') {
$innerClass = substr($class, 0, -2);
return array_map(function ($value) use ($format, $innerClass) {
return $this->denormalize($value, $innerClass, $format);
}, $data);
}
if (!class_exists($class)) {
return $data;
}
// Denormalize enum
if (method_exists($class, 'getAllowableEnumValues')) {
if (!in_array($data, $class::getAllowableEnumValues())) {
$imploded = implode("', '", $class::getAllowableEnumValues());
throw new \InvalidArgumentException("Invalid value for enum '$class', must be one of: '$imploded'");
}
return $data;
}
// If a discriminator is defined and points to a valid subclass, use it.
$discriminator = $class::DISCRIMINATOR;
if (!empty($discriminator) && isset($data[$discriminator]) && is_string($data[$discriminator])) {
$subclass = '{{modelPackage}}\\'.$data[$discriminator];
if (is_subclass_of($subclass, $class)) {
$class = $subclass;
}
}
// Denormalize another model
$values = new $class();
if ($values instanceof ModelInterface) {
foreach ($values->modelAttributes() as $name => $attribute) {
list($baseName, $innerClass, $format, $setter) = $attribute;
if (!isset($data[$baseName])) {
continue;
}
$value = $this->denormalize($data[$baseName], $innerClass, $format);
$values->$setter($value);
}
return $values;
}
return $data;
}
}

View File

@@ -23,28 +23,28 @@ PHP 5.4.0 and later
## Installation & Usage
To install the bindings via [Composer](http://getcomposer.org/), add the following to `composer.json`:
To install the dependencies via [Composer](http://getcomposer.org/), add the following repository to `composer.json` of your Symfony project:
```
```json
{
"repositories": [
{
"type": "git",
"url": "https://github.com/{{#composerVendorName}}{{.}}{{/composerVendorName}}{{^composerVendorName}}{{gitUserId}}{{/composerVendorName}}/{{#composerProjectName}}{{.}}{{/composerProjectName}}{{^composerProjectName}}{{gitRepoId}}{{/composerProjectName}}.git"
}
],
"require": {
"{{#composerVendorName}}{{.}}{{/composerVendorName}}{{^composerVendorName}}{{gitUserId}}{{/composerVendorName}}/{{#composerProjectName}}{{.}}{{/composerProjectName}}{{^composerProjectName}}{{gitRepoId}}{{/composerProjectName}}": "*@dev"
}
"repositories": [{
"type": "path",
"url": "//Path to your generated swagger bundle"
}],
}
```
Then run `composer install`
Then run:
```
composer require {{#composerVendorName}}{{.}}{{/composerVendorName}}{{^composerVendorName}}{{gitUserId}}{{/composerVendorName}}/{{#composerProjectName}}{{.}}{{/composerProjectName}}{{^composerProjectName}}{{gitRepoId}}{{/composerProjectName}}:dev-master
```
to add the generated swagger bundle as a dependency.
## Tests
To run the unit tests:
To run the unit tests for the generated bundle, first navigate to the directory containing the code, then run the following commands:
```
composer install

View File

@@ -18,6 +18,7 @@
namespace {{apiPackage}};
use Symfony\Component\HttpFoundation\File\UploadedFile;
{{#operations}}{{#imports}}use {{import}};
{{/imports}}
@@ -58,18 +59,15 @@ interface {{classname}}
{{#allParams}}
* @param {{dataType}} ${{paramName}} {{description}} {{#required}}(required){{/required}}{{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}
{{/allParams}}
* @param integer $responseCode The HTTP response code to return
* @param array $responseHeaders Additional HTTP headers to return with the response ()
*
{{#responses}}
{{#vendorExtensions.x-symfonyExceptionSimple}}
* @throws {{vendorExtensions.x-symfonyExceptionSimple}} {{message}}
{{/vendorExtensions.x-symfonyExceptionSimple}}
{{^vendorExtensions.x-symfonyExceptionSimple}}
* @return {{^dataType}}void{{/dataType}}{{#dataType}}{{dataType}}{{/dataType}} {{message}}
{{#returnType}}
* @return {{{returnType}}}
*
{{/vendorExtensions.x-symfonyExceptionSimple}}
{{/responses}}
{{/returnType}}
*/
public function {{operationId}}({{#allParams}}{{#vendorExtensions.x-parameterType}}{{vendorExtensions.x-parameterType}} {{/vendorExtensions.x-parameterType}}${{paramName}}{{^required}} = {{#defaultValue}}'{{{.}}}'{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
public function {{operationId}}({{#allParams}}{{#vendorExtensions.x-parameterType}}{{vendorExtensions.x-parameterType}} {{/vendorExtensions.x-parameterType}}${{paramName}}{{^required}} = {{#defaultValue}}{{{.}}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}}{{/required}}, {{/allParams}}&$responseCode, array &$responseHeaders);
{{/operation}}
}
{{/operations}}

View File

@@ -23,6 +23,7 @@ use \Exception;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\Validator\Constraints as Assert;
use {{apiPackage}}\{{classname}};
{{#imports}}use {{import}};
{{/imports}}
@@ -53,8 +54,28 @@ class {{controllerName}} extends Controller
* @param Request $request The Symfony request to handle.
* @return Response The Symfony response.
*/
public function {{operationId}}Action(Request $request)
public function {{operationId}}Action(Request $request{{#hasPathParams}}{{#pathParams}}, ${{paramName}}{{/pathParams}}{{/hasPathParams}})
{
{{#bodyParams}}
// Make sure that the client is providing something that we can consume
$consumes = [{{#consumes}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}];
$inputFormat = $request->headers->has('Content-Type')?$request->headers->get('Content-Type'):$consumes[0];
if (!in_array($inputFormat, $consumes)) {
// We can't consume the content that the client is sending us
return new Response('', 415);
}
{{/bodyParams}}
// Figure out what data format to return to the client
$produces = [{{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}}];
// Figure out what the client accepts
$clientAccepts = $request->headers->has('Accept')?$request->headers->get('Accept'):'*/*';
$responseFormat = $this->getOutputFormat($clientAccepts, $produces);
if ($responseFormat === null) {
return new Response('', 406);
}
// Handle authentication
{{#authMethods}}
// Authentication '{{name}}' required
{{#isApiKey}}
@@ -76,81 +97,58 @@ class {{controllerName}} extends Controller
$security{{name}} = $request->headers->get('authorization');
{{/isOAuth}}
{{/authMethods}}
// Read out all input parameter values into variables
{{#allParams}}
{{#queryParams}}
// Handle query params
${{paramName}} = $this->fromQuery($request->query->get('{{paramName}}'), '{{dataType}}');
${{paramName}} = $request->query->get('{{paramName}}');
{{/queryParams}}
{{#headerParams}}
// Handle header params
${{paramName}} = $this->fromHeader($request->headers->get('{{paramName}}'), '{{dataType}}');
${{paramName}} = $request->headers->get('{{paramName}}');
{{/headerParams}}
{{#pathParams}}
// Handle path params
${{paramName}} = $this->fromPath($request->attributes->get('{{paramName}}'), '{{dataType}}');
{{/pathParams}}
{{#formParams}}
{{#isFile}}
// Handle file params
${{paramName}} = $request->files->get('{{paramName}}');
{{/isFile}}
{{^isFile}}
// Handle form params
${{paramName}} = $this->fromForm($request->request->get('{{paramName}}'), '{{dataType}}');
${{paramName}} = $request->request->get('{{paramName}}');
{{/isFile}}
{{/formParams}}
{{#bodyParams}}
// Handle body params
${{paramName}} = $this->deserialize($request->getContent(), '{{{dataType}}}', 'json');
${{paramName}} = $request->getContent();
{{/bodyParams}}
// Parse incoming parameters
{{#allParams}}
{{#required}}
// Verify the required parameter '{{paramName}}' is set
if (${{paramName}} === null) {
return $this->createBadRequestResponse('Missing the required parameter ${{paramName}} when calling {{operationId}}');
}
// Use the default value if no value was provided
{{^required}}
{{#isContainer}}
{{#items}}
{{#defaultValue}}
${{paramName}} = ${{paramName}}?:[{{{defaultValue}}}];
{{/defaultValue}}
{{/items}}
{{/isContainer}}
{{^isContainer}}
{{#defaultValue}}
${{paramName}} = ${{paramName}}?:{{{defaultValue}}};
{{/defaultValue}}
{{/isContainer}}
{{/required}}
{{#hasValidation}}
{{#maxLength}}
if ({{^required}}!is_null(${{paramName}}) && {{/required}}(strlen(${{paramName}}) > {{maxLength}})) {
return $this->createBadRequestResponse('Invalid length for "${{paramName}}" when calling {{classname}}.{{operationId}}, must be smaller than or equal to {{maxLength}}.');
}
{{/maxLength}}
{{#minLength}}
if ({{^required}}!is_null(${{paramName}}) && {{/required}}(strlen(${{paramName}}) < {{minLength}})) {
return $this->createBadRequestResponse('Invalid length for "${{paramName}}" when calling {{classname}}.{{operationId}}, must be bigger than or equal to {{minLength}}.');
}
{{/minLength}}
{{#maximum}}
if ({{^required}}!is_null(${{paramName}}) && {{/required}}(${{paramName}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}})) {
return $this->createBadRequestResponse('Invalid value for "${{paramName}}" when calling {{classname}}.{{operationId}}, must be smaller than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}{{maximum}}.');
}
{{/maximum}}
{{#minimum}}
if ({{^required}}!is_null(${{paramName}}) && {{/required}}(${{paramName}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}})) {
return $this->createBadRequestResponse('Invalid value for "${{paramName}}" when calling {{classname}}.{{operationId}}, must be bigger than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}{{minimum}}.');
}
{{/minimum}}
{{#pattern}}
if ({{^required}}!is_null(${{paramName}}) && {{/required}}!preg_match("{{{pattern}}}", ${{paramName}})) {
return $this->createBadRequestResponse("Invalid value for \"{{paramName}}\" when calling {{classname}}.{{operationId}}, must conform to the pattern {{{pattern}}}.");
}
{{/pattern}}
{{#maxItems}}
if ({{^required}}!is_null(${{paramName}}) && {{/required}}(count(${{paramName}}) > {{maxItems}})) {
return $this->createBadRequestResponse('Invalid value for "${{paramName}}" when calling {{classname}}.{{operationId}}, number of items must be less than or equal to {{maxItems}}.');
}
{{/maxItems}}
{{#minItems}}
if ({{^required}}!is_null(${{paramName}}) && {{/required}}(count(${{paramName}}) < {{minItems}})) {
return $this->createBadRequestResponse('Invalid value for "${{paramName}}" when calling {{classname}}.{{operationId}}, number of items must be greater than or equal to {{minItems}}.');
}
{{/minItems}}
{{/hasValidation}}
// Deserialize the input values that needs it
{{^isFile}}
{{#bodyParams}}
${{paramName}} = $this->deserialize(${{paramName}}, '{{{dataType}}}', $inputFormat);
{{/bodyParams}}
{{^bodyParams}}
${{paramName}} = $this->deserialize(${{paramName}}, '{{#isContainer}}array<{{#collectionFormat}}{{collectionFormat}}{{/collectionFormat}}{{^collectionFormat}}csv{{/collectionFormat}}>{{/isContainer}}{{^isContainer}}{{dataType}}{{/isContainer}}', 'string');
{{/bodyParams}}
{{/isFile}}
{{/allParams}}
// Call the API interface
// Validate the input values
{{>api_input_validation}}
try {
$handler = $this->getApiHandler();
@@ -158,31 +156,35 @@ class {{controllerName}} extends Controller
// Set authentication method '{{name}}'
$handler->set{{name}}($security{{name}});
{{/authMethods}}
{{#returnType}}
// Expecting a return value (exception otherwise)
$result = $handler->{{operationId}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
// Make the call to the business logic
$responseCode = {{#returnType}}200{{/returnType}}{{^returnType}}204{{/returnType}};
$responseHeaders = [];
$result = $handler->{{operationId}}({{#allParams}}${{paramName}}, {{/allParams}}$responseCode, $responseHeaders);
// Find default response message
$message = '{{#responses}}{{#isDefault}}{{message}}{{/isDefault}}{{/responses}}';
// Find a more specific message, if available
switch ($responseCode) {
{{#responses}}
{{^vendorExtensions.x-symfonyExceptionSimple}}
// Handle {{code}} response: {{message}}
$content = $this->serialize($result, 'json');
return new Response($content, {{code}}, [
'Content-Type' => 'application/json',
'X-Swagger-Message' => '{{message}}',
]);
{{/vendorExtensions.x-symfonyExceptionSimple}}
case {{code}}:
$message = '{{message}}';
break;
{{/responses}}
{{/returnType}}
{{^returnType}}
// No return type expected; return empty response
$handler->{{operationId}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
return new Response('', 204);
{{/returnType}}
{{#responses}}
} catch (HttpException $exception) {
// {{message}}
return $this->createErrorResponse($exception);
{{/responses}}
}
return new Response(
$result?$this->serialize($result, $responseFormat):'',
$responseCode,
array_merge(
$responseHeaders,
[
'Content-Type' => $responseFormat,
'X-Swagger-Message' => $message
]
)
);
} catch (Exception $fallthrough) {
return $this->createErrorResponse(new HttpException(500, 'An unsuspected error occurred.', $fallthrough));
}
@@ -195,7 +197,7 @@ class {{controllerName}} extends Controller
*/
public function getApiHandler()
{
return $this->get('{{bundleAlias}}.api.api_server')->getApiHandler('{{pathPrefix}}');
return $this->apiServer->getApiHandler('{{pathPrefix}}');
}
}
{{/operations}}

View File

@@ -0,0 +1,88 @@
{{#allParams}}
$asserts = [];
{{#required}}
$asserts[] = new Assert\NotNull();
{{/required}}
{{#isEnum}}
{{#isContainer}}
$asserts[] = new Assert\All([
{{#items}}
new Assert\Choice([ {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}} ])
{{/items}}
]);
{{/isContainer}}
{{^isContainer}}
$asserts[] = new Assert\Choice([ {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}} ]);
{{/isContainer}}
{{/isEnum}}
{{#isContainer}}
$asserts[] = new Assert\All([
{{#items}}
new Assert\Type("{{datatype}}")
{{/items}}
]);
{{/isContainer}}
{{^isContainer}}
{{#isDate}}
$asserts[] = new Assert\Date();
{{/isDate}}
{{#isDateTime}}
$asserts[] = new Assert\DateTime();
{{/isDateTime}}
{{^isDate}}
{{^isDateTime}}
{{#isFile}}
$asserts[] = new Assert\File();
{{/isFile}}
{{^isFile}}
$asserts[] = new Assert\Type("{{dataType}}");
{{/isFile}}
{{/isDateTime}}
{{/isDate}}
{{/isContainer}}
{{#hasValidation}}
{{#maxLength}}
$asserts[] = new Assert\Length([
'max' => {{maxLength}}
]);
{{/maxLength}}
{{#minLength}}
$asserts[] = new Assert\Length([
'min' => {{minLength}}
]);
{{/minLength}}
{{#minimum}}
{{#exclusiveMinimum}}
$asserts[] = new Assert\GreaterThan({{minimum}});
{{/exclusiveMinimum}}
{{^exclusiveMinimum}}
$asserts[] = new Assert\GreaterThanOrEqual({{minimum}});
{{/exclusiveMinimum}}
{{/minimum}}
{{#maximum}}
{{#exclusiveMaximum}}
$asserts[] = new Assert\LessThan({{minimum}});
{{/exclusiveMaximum}}
{{^exclusiveMaximum}}
$asserts[] = new Assert\LessThanOrEqual({{minimum}});
{{/exclusiveMaximum}}
{{/maximum}}
{{#pattern}}
$asserts[] = new Assert\Regex("/{{pattern}}/");
{{/pattern}}
{{#maxItems}}
$asserts[] = new Assert\Count([
'max' => {{maxItems}}
]);
{{/maxItems}}
{{#minItems}}
$asserts[] = new Assert\Count([
'min' => {{minItems}}
]);
{{/minItems}}
{{/hasValidation}}
$response = $this->validate(${{paramName}}, $asserts);
if ($response instanceof Response) {
return $response;
}
{{/allParams}}

View File

@@ -1,77 +0,0 @@
<?php
/**
* {{classname}}Test
* PHP version 5
*
* @category Class
* @package {{apiTestsPackage}}
* @author Swagger Codegen team
* @link https://github.com/swagger-api/swagger-codegen
*/
{{>partial_header}}
/**
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen
* Please update the test case below to test the endpoint.
*/
namespace {{apiTestsPackage}};
use \{{invokerPackage}}\Configuration;
use \{{invokerPackage}}\ApiClient;
use \{{invokerPackage}}\ApiException;
use \{{invokerPackage}}\ObjectSerializer;
/**
* {{classname}}Test Class Doc Comment
*
* @category Class
* @package {{apiTestsPackage}}
* @author Swagger Codegen team
* @link https://github.com/swagger-api/swagger-codegen
*/
{{#operations}}class {{classname}}Test extends \PHPUnit_Framework_TestCase
{
/**
* Setup before running any test cases
*/
public static function setUpBeforeClass()
{
}
/**
* Setup before running each test case
*/
public function setUp()
{
}
/**
* Clean up after running each test case
*/
public function tearDown()
{
}
/**
* Clean up after running all test cases
*/
public static function tearDownAfterClass()
{
}
{{#operation}}
/**
* Test case for {{{operationId}}}
*
* {{{summary}}}.
*
*/
public function test{{operationIdCamelCase}}()
{
}
{{/operation}}
}
{{/operations}}

View File

@@ -23,13 +23,17 @@
"ext-curl": "*",
"ext-json": "*",
"ext-mbstring": "*",
"symfony/validator": "*",
"jms/serializer-bundle": "*",
"symfony/framework-bundle": "^2.3|^3.0"
},
"require-dev": {
"phpunit/phpunit": "~4.8",
"satooshi/php-coveralls": "~1.0",
"squizlabs/php_codesniffer": "~2.6",
"friendsofphp/php-cs-fixer": "~1.12"
"friendsofphp/php-cs-fixer": "~1.12",
"symfony/browser-kit": "*",
"hoa/regex": "~1.0"
},
"autoload": {
"psr-4": { "{{escapedInvokerPackage}}\\" : "{{srcBasePath}}/" }

View File

@@ -21,10 +21,9 @@
namespace {{modelPackage}};
{{^isEnum}}
{{#useStatements}}use {{this}};
{{/useStatements}}
{{/isEnum}}
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\SerializedName;
/**
* Class representing the {{classname}} model.
@@ -36,5 +35,5 @@ namespace {{modelPackage}};
* @package {{modelPackage}}
* @author Swagger Codegen team
*/
{{#isEnum}}{{>model_enum}}{{/isEnum}}{{^isEnum}}{{>model_generic}}{{/isEnum}}
{{>model_generic}}
{{/model}}{{/models}}

View File

@@ -1,49 +1,6 @@
class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}implements ModelInterface, \ArrayAccess
class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}
{
const DISCRIMINATOR = {{#discriminator}}'{{discriminator}}'{{/discriminator}}{{^discriminator}}null{{/discriminator}};
/**
* The original name of the model.
* @var string
*/
protected static $_name = '{{name}}';
/**
* Array of property to type mappings. Used for (de)serialization
* @var array[]
*/
protected static $_attributes = [{{#vars}}
'{{name}}' => ['{{baseName}}', '{{{vendorExtensions.x-fullType}}}', {{#dataFormat}}'{{{dataFormat}}}'{{/dataFormat}}{{^dataFormat}}null{{/dataFormat}}, '{{setter}}', '{{getter}}'],{{/vars}}
];
{{#vars}}{{#isEnum}}
/**
* Allowed values of {{name}}
*/{{#allowableValues}}{{#enumVars}}
const {{enumName}}_{{{name}}} = {{{value}}};{{/enumVars}}{{/allowableValues}}{{/isEnum}}{{/vars}}
{{#vars}}{{#isEnum}}
/**
* Gets allowable values of the enum
* @return string[]
*/
public function {{getter}}AllowableValues()
{
return [
{{#allowableValues}}{{#enumVars}}self::{{enumName}}_{{{name}}},{{^-last}}
{{/-last}}{{/enumVars}}{{/allowableValues}}
];
}
{{/isEnum}}{{/vars}}
{{#vars}}
/**{{#description}}
* {{description}}
*
{{/description}}
* @var {{{datatype}}}{{^required}}|null{{/required}}
*/
protected ${{name}};
{{#vars}}{{>model_variables}}
{{/vars}}
/**
* Constructor
@@ -58,187 +15,7 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}imple
{{#vars}}
$this->{{name}} = isset($data['{{name}}']) ? $data['{{name}}'] : {{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}};
{{/vars}}
{{#discriminator}}
// Initialize discriminator property with the model name.
foreach (self::$_attributes as $_name => $attribute) {
list($baseName) = $attribute;
if ('{{discriminator}}' === $baseName) {
$this->$_name = static::$_name;
}
}
{{/discriminator}}
}
/**
* show all the invalid properties with reasons.
*
* @return array invalid properties with reasons
*/
public function listInvalidProperties()
{
{{#parent}}
$invalid_properties = parent::listInvalidProperties();
{{/parent}}
{{^parent}}
$invalid_properties = [];
{{/parent}}
{{#vars}}
{{#required}}
if ($this->{{name}} === null) {
$invalid_properties[] = "'{{name}}' can't be null";
}
{{/required}}
{{#isEnum}}
{{^isContainer}}
$allowedValues = $this->{{getter}}AllowableValues();
if (!in_array($this->{{name}}, $allowedValues, true)) {
$invalid_properties[] = sprintf(
"invalid value for '{{name}}', must be one of '%s'",
implode("', '", $allowedValues)
);
}
{{/isContainer}}
{{/isEnum}}
{{#hasValidation}}
{{#maxLength}}
if ({{^required}}!is_null($this->{{name}}) && {{/required}}(strlen($this->{{name}}) > {{maxLength}})) {
$invalid_properties[] = "invalid value for '{{name}}', the character length must be smaller than or equal to {{{maxLength}}}.";
}
{{/maxLength}}
{{#minLength}}
if ({{^required}}!is_null($this->{{name}}) && {{/required}}(strlen($this->{{name}}) < {{minLength}})) {
$invalid_properties[] = "invalid value for '{{name}}', the character length must be bigger than or equal to {{{minLength}}}.";
}
{{/minLength}}
{{#maximum}}
if ({{^required}}!is_null($this->{{name}}) && {{/required}}($this->{{name}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}})) {
$invalid_properties[] = "invalid value for '{{name}}', must be smaller than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}{{maximum}}.";
}
{{/maximum}}
{{#minimum}}
if ({{^required}}!is_null($this->{{name}}) && {{/required}}($this->{{name}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}})) {
$invalid_properties[] = "invalid value for '{{name}}', must be bigger than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}{{minimum}}.";
}
{{/minimum}}
{{#pattern}}
if ({{^required}}!is_null($this->{{name}}) && {{/required}}!preg_match("{{{pattern}}}", $this->{{name}})) {
$invalid_properties[] = "invalid value for '{{name}}', must be conform to the pattern {{{pattern}}}.";
}
{{/pattern}}
{{#maxItems}}
if ({{^required}}!is_null($this->{{name}}) && {{/required}}(count($this->{{name}}) > {{maxItems}})) {
$invalid_properties[] = "invalid value for '{{name}}', number of items must be less than or equal to {{{maxItems}}}.";
}
{{/maxItems}}
{{#minItems}}
if ({{^required}}!is_null($this->{{name}}) && {{/required}}(count($this->{{name}}) < {{minItems}})) {
$invalid_properties[] = "invalid value for '{{name}}', number of items must be greater than or equal to {{{minItems}}}.";
}
{{/minItems}}
{{/hasValidation}}
{{/vars}}
return $invalid_properties;
}
/**
* The original name of the model.
*
* @return string
*/
public function modelName() {
return self::$_name;
}
/**
* Array of property to mappings.
*
* @return array[]
*/
public function modelAttributes() {
{{#parentSchema}}return array_merge(parent::$_attributes, self::$_attributes);{{/parentSchema}}
{{^parentSchema}}return self::$_attributes;{{/parentSchema}}
}
/**
* Validate all the properties in the model
*
* Return true if all passed.
*
* @return bool True if all properties are valid
*/
public function isValid()
{
{{#parent}}
if (!parent::isValid()) {
return false;
}
{{/parent}}
{{#vars}}
{{#required}}
if ($this->{{name}} === null) {
return false;
}
{{/required}}
{{#isEnum}}
{{^isContainer}}
$allowedValues = $this->{{getter}}AllowableValues();
if (!in_array($this->{{name}}, $allowedValues)) {
return false;
}
{{/isContainer}}
{{/isEnum}}
{{#hasValidation}}
{{#maxLength}}
if (strlen($this->{{name}}) > {{maxLength}}) {
return false;
}
{{/maxLength}}
{{#minLength}}
if (strlen($this->{{name}}) < {{minLength}}) {
return false;
}
{{/minLength}}
{{#maximum}}
if ($this->{{name}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}) {
return false;
}
{{/maximum}}
{{#minimum}}
if ($this->{{name}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}) {
return false;
}
{{/minimum}}
{{#pattern}}
if (!preg_match("{{{pattern}}}", $this->{{name}})) {
return false;
}
{{/pattern}}
{{#maxItems}}
if (count($this->{{name}}) > {{maxItems}}) {
return false;
}
{{/maxItems}}
{{#minItems}}
if (count($this->{{name}}) < {{minItems}}) {
return false;
}
{{/minItems}}
{{/hasValidation}}
{{/vars}}
return true;
}
{{#vars}}
/**
@@ -258,109 +35,11 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}imple
*
* @return $this
*/
public function {{setter}}({{#vendorExtensions.x-typeAnnotation}}{{vendorExtensions.x-typeAnnotation}} {{/vendorExtensions.x-typeAnnotation}}${{name}}{{^required}} = null{{/required}})
public function {{setter}}({{#vendorExtensions.x-parameterType}}{{vendorExtensions.x-parameterType}} {{/vendorExtensions.x-parameterType}}${{name}}{{^required}} = null{{/required}})
{
{{#isEnum}}
$allowedValues = $this->{{getter}}AllowableValues();
{{^isContainer}}
if ({{^required}}${{name}} !== null && {{/required}}!in_array(${{{name}}}, $allowedValues, true)) {
throw new \InvalidArgumentException(
sprintf(
"Invalid value for '{{name}}', must be one of '%s'",
implode("', '", $allowedValues)
)
);
}
{{/isContainer}}
{{#isContainer}}
if ({{^required}}!is_null(${{name}}) && {{/required}}array_diff(${{{name}}}, $allowedValues)) {
throw new \InvalidArgumentException(
sprintf(
"Invalid value for '{{name}}', must be one of '%s'",
implode("', '", $allowedValues)
)
);
}
{{/isContainer}}
{{/isEnum}}
{{#hasValidation}}
{{#maxLength}}
if ({{^required}}!is_null(${{name}}) && {{/required}}(strlen(${{name}}) > {{maxLength}})) {
throw new \InvalidArgumentException('invalid length for ${{name}} when calling {{classname}}.{{operationId}}, must be smaller than or equal to {{maxLength}}.');
}{{/maxLength}}
{{#minLength}}
if ({{^required}}!is_null(${{name}}) && {{/required}}(strlen(${{name}}) < {{minLength}})) {
throw new \InvalidArgumentException('invalid length for ${{name}} when calling {{classname}}.{{operationId}}, must be bigger than or equal to {{minLength}}.');
}
{{/minLength}}
{{#maximum}}
if ({{^required}}!is_null(${{name}}) && {{/required}}(${{name}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}})) {
throw new \InvalidArgumentException('invalid value for ${{name}} when calling {{classname}}.{{operationId}}, must be smaller than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}{{maximum}}.');
}
{{/maximum}}
{{#minimum}}
if ({{^required}}!is_null(${{name}}) && {{/required}}(${{name}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}})) {
throw new \InvalidArgumentException('invalid value for ${{name}} when calling {{classname}}.{{operationId}}, must be bigger than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}{{minimum}}.');
}
{{/minimum}}
{{#pattern}}
if ({{^required}}!is_null(${{name}}) && {{/required}}(!preg_match("{{{pattern}}}", ${{name}}))) {
throw new \InvalidArgumentException("invalid value for ${{name}} when calling {{classname}}.{{operationId}}, must conform to the pattern {{{pattern}}}.");
}
{{/pattern}}
{{#maxItems}}
if ({{^required}}!is_null(${{name}}) && {{/required}}(count(${{name}}) > {{maxItems}})) {
throw new \InvalidArgumentException('invalid value for ${{name}} when calling {{classname}}.{{operationId}}, number of items must be less than or equal to {{maxItems}}.');
}{{/maxItems}}
{{#minItems}}
if ({{^required}}!is_null(${{name}}) && {{/required}}(count(${{name}}) < {{minItems}})) {
throw new \InvalidArgumentException('invalid length for ${{name}} when calling {{classname}}.{{operationId}}, number of items must be greater than or equal to {{minItems}}.');
}
{{/minItems}}
{{/hasValidation}}
$this->{{name}} = ${{name}};
return $this;
}
{{/vars}}
/**
* Returns true if offset exists. False otherwise.
* @param integer $offset Offset
* @return boolean
*/
public function offsetExists($offset)
{
return isset($this->$offset);
}
/**
* Gets offset.
* @param integer $offset Offset
* @return mixed
*/
public function offsetGet($offset)
{
return isset($this->$offset) ? $this->$offset : null;
}
/**
* Sets value based on offset.
* @param string $offset Offset
* @param mixed $value Value to be set
* @return void
*/
public function offsetSet($offset, $value)
{
$this->$offset = $value;
}
/**
* Unsets offset.
* @param integer $offset Offset
* @return void
*/
public function offsetUnset($offset)
{
$this->$offset = null;
}
}

View File

@@ -0,0 +1,91 @@
/**
{{#description}}
* {{description}}
*
{{/description}}
* @var {{{datatype}}}{{^required}}|null{{/required}}
* @SerializedName("{{baseName}}")
{{#required}}
* @Assert\NotNull()
{{/required}}
{{#isEnum}}
{{#isContainer}}
* @Assert\All({
{{#items}}
* @Assert\Choice({ {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}} })
{{/items}}
* })
{{/isContainer}}
{{^isContainer}}
* @Assert\Choice({ {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}} })
{{/isContainer}}
{{/isEnum}}
{{#isContainer}}
* @Assert\All({
{{#items}}
* @Assert\Type("{{datatype}}")
{{/items}}
* })
{{#items}}
* @Type("array<{{datatype}}>")
{{/items}}
{{/isContainer}}
{{^isContainer}}
{{#isDate}}
* @Assert\Date()
* @Type("DateTime")
{{/isDate}}
{{#isDateTime}}
* @Assert\DateTime()
* @Type("DateTime")
{{/isDateTime}}
{{^isDate}}
{{^isDateTime}}
* @Assert\Type("{{datatype}}")
* @Type("{{datatype}}")
{{/isDateTime}}
{{/isDate}}
{{/isContainer}}
{{#hasValidation}}
{{#maxLength}}
* @Assert\Length(
* max = {{maxLength}}
* )
{{/maxLength}}
{{#minLength}}
* @Assert\Length(
* min = {{minLength}}
* )
{{/minLength}}
{{#minimum}}
{{#exclusiveMinimum}}
* @Assert\GreaterThan({{minimum}})
{{/exclusiveMinimum}}
{{^exclusiveMinimum}}
* @Assert\GreaterThanOrEqual({{minimum}})
{{/exclusiveMinimum}}
{{/minimum}}
{{#maximum}}
{{#exclusiveMaximum}}
* @Assert\LessThan({{minimum}})
{{/exclusiveMaximum}}
{{^exclusiveMaximum}}
* @Assert\LessThanOrEqual({{minimum}})
{{/exclusiveMaximum}}
{{/maximum}}
{{#pattern}}
* @Assert\Regex("/{{pattern}}/")
{{/pattern}}
{{#maxItems}}
* @Assert\Count(
* max = {{maxItems}}
* )
{{/maxItems}}
{{#minItems}}
* @Assert\Count(
* min = {{minItems}}
* )
{{/minItems}}
{{/hasValidation}}
*/
protected ${{name}};

View File

@@ -11,7 +11,29 @@
path: {{path}}
methods: [{{httpMethod}}]
defaults:
_controller: {{bundleClassName}}:{{baseName}}:{{operationId}}
_controller: {{bundleAlias}}.controller.{{pathPrefix}}:{{operationId}}Action
{{#hasPathParams}}
requirements:
{{/hasPathParams}}
{{#pathParams}}
{{#pattern}}
{{paramName}}: '{{pattern}}'
{{/pattern}}
{{^pattern}}
{{#isLong}}
{{paramName}}: '\d+'
{{/isLong}}
{{#isInteger}}
{{paramName}}: '\d+'
{{/isInteger}}
{{#isString}}
{{paramName}}: '[a-z0-9]+'
{{/isString}}
{{#isBoolean}}
{{paramName}}: 'true|false'
{{/isBoolean}}
{{/pattern}}
{{/pathParams}}
{{/operation}}
{{/operations}}

View File

@@ -0,0 +1,91 @@
<?php
namespace {{servicePackage}};
use JMS\Serializer\SerializerBuilder;
use JMS\Serializer\Naming\CamelCaseNamingStrategy;
use JMS\Serializer\Naming\SerializedNameAnnotationStrategy;
use Swagger\Server\Service\StrictJsonDeserializationVisitor;
use JMS\Serializer\XmlDeserializationVisitor;
class JmsSerializer implements SerializerInterface
{
protected $serializer;
public function __construct()
{
$naming_strategy = new SerializedNameAnnotationStrategy(new CamelCaseNamingStrategy());
$this->serializer = SerializerBuilder::create()
->setDeserializationVisitor('json', new StrictJsonDeserializationVisitor($naming_strategy))
->setDeserializationVisitor('xml', new XmlDeserializationVisitor($naming_strategy))
->build();
}
public function serialize($data, $format)
{
return SerializerBuilder::create()->build()->serialize($data, $this->convertFormat($format));
}
public function deserialize($data, $type, $format)
{
if ($format == 'string') {
return $this->deserializeString($data, $type);
}
// If we end up here, let JMS serializer handle the deserialization
return $this->serializer->deserialize($data, $type, $this->convertFormat($format));
}
private function convertFormat($format)
{
switch ($format) {
case 'application/json':
return 'json';
case 'application/xml':
return 'xml';
}
return null;
}
private function deserializeString($data, $type)
{
switch ($type) {
case 'int':
case 'integer':
if (is_int($data)) {
return $data;
}
if (is_numeric($data)) {
return $data + 0;
}
break;
case 'string':
break;
case 'boolean':
case 'bool':
if (strtolower($data) === 'true') {
return true;
}
if (strtolower($data) === 'false') {
return false;
}
break;
case 'array<csv>':
return explode(',', $data);
case 'array<ssv>':
return explode(' ', $data);
case 'array<tsv>':
return explode("\t", $data);
case 'array<pipes>':
return explode('|', $data);
}
// If we end up here, just return data
return $data;
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace {{servicePackage}};
interface SerializerInterface
{
/**
* Serializes the given data to the specified output format.
*
* @param object|array|scalar $data
* @param string $format
*
* @return string
*/
public function serialize($data, $format);
/**
* Deserializes the given data to the specified type.
*
* @param string $data
* @param string $type
* @param string $format
*
* @return object|array|scalar
*/
public function deserialize($data, $type, $format);
}

View File

@@ -0,0 +1,72 @@
<?php
/*
* Copyright 2017 Dmitriy Simushev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace {{servicePackage}};
use JMS\Serializer\Context;
use JMS\Serializer\JsonDeserializationVisitor;
class StrictJsonDeserializationVisitor extends JsonDeserializationVisitor
{
/**
* {@inheritdoc}
*/
public function visitString($data, array $type, Context $context)
{
if (!is_string($data)) {
throw TypeMismatchException::fromValue('string', $data, $context);
}
return parent::visitString($data, $type, $context);
}
/**
* {@inheritdoc}
*/
public function visitBoolean($data, array $type, Context $context)
{
if (!is_bool($data)) {
throw TypeMismatchException::fromValue('boolean', $data, $context);
}
return parent::visitBoolean($data, $type, $context);
}
/**
* {@inheritdoc}
*/
public function visitInteger($data, array $type, Context $context)
{
if (!is_int($data)) {
throw TypeMismatchException::fromValue('integer', $data, $context);
}
return parent::visitInteger($data, $type, $context);
}
/**
* {@inheritdoc}
*/
public function visitDouble($data, array $type, Context $context)
{
if (!is_float($data) && !is_integer($data)) {
throw TypeMismatchException::fromValue('double', $data, $context);
}
return parent::visitDouble($data, $type, $context);
}
}

View File

@@ -0,0 +1,52 @@
<?php
/*
* Copyright 2017 Dmitriy Simushev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace {{servicePackage}};
use JMS\Serializer\DeserializationContext;
use JMS\Serializer\Exception\RuntimeException;
class TypeMismatchException extends RuntimeException
{
/**
* A handy method for building exception instance.
*
* @param string $expected_type
* @param mixed $actual_value
* @param DeserializationContext|null $context
* @return TypeMismatchException
*/
public static function fromValue(
$expected_type,
$actual_value,
DeserializationContext $context = null
) {
if (null !== $context && count($context->getCurrentPath()) > 0) {
$property = sprintf('property "%s" to be ', implode('.', $context->getCurrentPath()));
} else {
$property = '';
}
return new static(sprintf(
'Expected %s%s, but got %s: %s',
$property,
$expected_type,
gettype($actual_value),
json_encode($actual_value)
));
}
}

View File

@@ -2,9 +2,33 @@
# https://github.com/swagger-api/swagger-codegen
# Do not edit the class manually.
parameters:
{{bundleAlias}}.serializer: '{{servicePackage}}\JmsSerializer'
{{bundleAlias}}.validator: '{{servicePackage}}\SymfonyValidator'
services:
{{bundleAlias}}.api.api_server:
class: {{apiPackage}}\ApiServer
{{bundleAlias}}.model.model_serializer:
class: {{modelPackage}}\ModelSerializer
{{bundleAlias}}.service.serializer:
class: %{{bundleAlias}}.serializer%
{{bundleAlias}}.service.validator:
class: %{{bundleAlias}}.validator%
{{#apiInfo}}
{{#apis}}
{{#operations}}
{{bundleAlias}}.controller.{{pathPrefix}}:
class: {{controllerPackage}}\{{baseName}}Controller
calls:
- [setSerializer, ['@{{bundleAlias}}.service.serializer']]
- [setValidator, ['@{{bundleAlias}}.service.validator']]
- [setApiServer, ['@{{bundleAlias}}.api.api_server']]
{{/operations}}
{{/apis}}
{{/apiInfo}}

View File

@@ -0,0 +1,21 @@
<?php
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = array(
new Symfony\Bundle\FrameworkBundle\FrameworkBundle()
);
return $bundles;
}
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load(__DIR__.'/test_config.yml');
}
}

View File

@@ -0,0 +1,116 @@
<?php
/**
* {{classname}}Test
* PHP version 5
*
* @category Class
* @package {{apiTestsPackage}}
* @author Swagger Codegen team
* @link https://github.com/swagger-api/swagger-codegen
*/
{{>partial_header}}
/**
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen
* Please update the test case below to test the endpoint.
*/
namespace {{apiTestsPackage}};
use {{invokerPackage}}\Configuration;
use {{invokerPackage}}\ApiClient;
use {{invokerPackage}}\ApiException;
use {{invokerPackage}}\ObjectSerializer;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* {{classname}}Test Class Doc Comment
*
* @category Class
* @package {{apiTestsPackage}}
* @author Swagger Codegen team
* @link https://github.com/swagger-api/swagger-codegen
*/
{{#operations}}class {{classname}}Test extends WebTestCase
{
/**
* Setup before running any test cases
*/
public static function setUpBeforeClass()
{
}
/**
* Setup before running each test case
*/
public function setUp()
{
}
/**
* Clean up after running each test case
*/
public function tearDown()
{
}
/**
* Clean up after running all test cases
*/
public static function tearDownAfterClass()
{
}
{{#operation}}
/**
* Test case for {{{operationId}}}
*
* {{{summary}}}.
*
*/
public function test{{operationIdCamelCase}}()
{
$client = static::createClient();
$path = '{{path}}';
{{#pathParams}}
{{=<% %>=}}
$pattern = '{<%paramName%>}';
<%={{ }}=%>
{{#pattern}}
$data = $this->genTestData('{{pattern}}');
{{/pattern}}
{{^pattern}}
{{#isLong}}
$data = $this->genTestData('\d+');
{{/isLong}}
{{#isInteger}}
$data = $this->genTestData('\d+');
{{/isInteger}}
{{#isString}}
$data = $this->genTestData('[a-z0-9]+');
{{/isString}}
{{#isBoolean}}
$data = $this->genTestData('true|false');
{{/isBoolean}}
{{/pattern}}
$path = str_replace($pattern, $data, $path);
{{/pathParams}}
$crawler = $client->request('{{httpMethod}}', $path);
}
{{/operation}}
protected function genTestData($regexp)
{
$grammar = new \Hoa\File\Read('hoa://Library/Regex/Grammar.pp');
$compiler = \Hoa\Compiler\Llk\Llk::load($grammar);
$ast = $compiler->parse($regexp);
$generator = new \Hoa\Regex\Visitor\Isotropic(new \Hoa\Math\Sampler\Random());
return $generator->visit($ast);
}
}
{{/operations}}

View File

@@ -19,7 +19,7 @@
* Please update the test case below to test the model.
*/
namespace {{modelTestsPackage}};
namespace {{modelPackage}};
/**
* {{classname}}Test Class Doc Comment
@@ -67,6 +67,7 @@ class {{classname}}Test extends \PHPUnit_Framework_TestCase
*/
public function test{{classname}}()
{
$test{{classname}} = new {{classname}}();
}
{{#vars}}

View File

@@ -12,6 +12,10 @@
</testsuite>
</testsuites>
<php>
<server name="KERNEL_DIR" value="Tests/" />
</php>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">{{apiSrcPath}}</directory>

View File

@@ -0,0 +1,57 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.penneo</groupId>
<artifactId>PhpSymfonyPetstoreServerTests</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>PHP Symfony Swagger Petstore Server</name>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>bundle-install</id>
<phase>pre-integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>composer</executable>
<arguments>
<argument>install</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>bundle-test</id>
<phase>integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>vendor/bin/phpunit</executable>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,8 @@
imports:
- { resource: "../Resources/config/services.yml" }
framework:
secret: "testsecret"
test: ~
router:
resource: "%kernel.root_dir%/../Resources/config/routing.yml"

View File

@@ -0,0 +1,20 @@
<?php
namespace {{servicePackage}};
use Symfony\Component\Validator\Validation;
class SymfonyValidator implements ValidatorInterface
{
protected $validator;
public function __construct()
{
$this->validator = Validation::createValidator();
}
public function validate($value, $constraints = null, $groups = null)
{
return $this->validator->validate($value, $constraints, $groups);
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace {{servicePackage}};
interface ValidatorInterface
{
/**
* Validates a value against a constraint or a list of constraints.
*
* If no constraint is passed, the constraint
* {@link \Symfony\Component\Validator\Constraints\Valid} is assumed.
*
* @param mixed $value The value to validate
* @param Constraint|Constraint[] $constraints The constraint(s) to validate
* against
* @param array|null $groups The validation groups to
* validate. If none is given,
* "Default" is assumed
*
* @return ConstraintViolationListInterface A list of constraint violations
* If the list is empty, validation
* succeeded
*/
public function validate($value, $constraints = null, $groups = null);
}

View File

@@ -36,9 +36,12 @@ class ApiClient(object):
Ref: https://github.com/swagger-api/swagger-codegen
Do not edit the class manually.
:param host: The base path for the server to call.
:param configuration: .Configuration object for this client
:param header_name: a header to pass when making calls to the API.
:param header_value: a header value to pass when making calls to the API.
:param header_value: a header value to pass when making calls to
the API.
:param cookie: a cookie to include in the header when making calls
to the API
"""
PRIMITIVE_TYPES = (float, bool, bytes, text_type) + integer_types
@@ -73,16 +76,11 @@ class ApiClient(object):
@property
def user_agent(self):
"""
Gets user agent.
"""
"""User agent for this API client"""
return self.default_headers['User-Agent']
@user_agent.setter
def user_agent(self, value):
"""
Sets user agent.
"""
self.default_headers['User-Agent'] = value
def set_default_header(self, header_name, header_value):

View File

@@ -100,15 +100,19 @@ class Configuration(with_metaclass(TypeWithDefault, object)):
@property
def logger_file(self):
"""
Gets the logger_file.
"""The logger file.
If the logger_file is None, then add stream handler and remove file handler.
Otherwise, add file handler and remove stream handler.
:param value: The logger_file path.
:type: str
"""
return self.__logger_file
@logger_file.setter
def logger_file(self, value):
"""
Sets the logger_file.
"""The logger file.
If the logger_file is None, then add stream handler and remove file handler.
Otherwise, add file handler and remove stream handler.
@@ -138,15 +142,16 @@ class Configuration(with_metaclass(TypeWithDefault, object)):
@property
def debug(self):
"""
Gets the debug status.
"""Debug status
:param value: The debug status, True or False.
:type: bool
"""
return self.__debug
@debug.setter
def debug(self, value):
"""
Sets the debug status.
"""Debug status
:param value: The debug status, True or False.
:type: bool
@@ -168,15 +173,18 @@ class Configuration(with_metaclass(TypeWithDefault, object)):
@property
def logger_format(self):
"""
Gets the logger_format.
"""The logger format.
The logger_formatter will be updated when sets logger_format.
:param value: The format string.
:type: str
"""
return self.__logger_format
@logger_format.setter
def logger_format(self, value):
"""
Sets the logger_format.
"""The logger format.
The logger_formatter will be updated when sets logger_format.
@@ -187,8 +195,7 @@ class Configuration(with_metaclass(TypeWithDefault, object)):
self.logger_formatter = logging.Formatter(self.__logger_format)
def get_api_key_with_prefix(self, identifier):
"""
Gets API key (with prefix if set).
"""Gets API key (with prefix if set).
:param identifier: The identifier of apiKey.
:return: The token for api key authentication.
@@ -199,8 +206,7 @@ class Configuration(with_metaclass(TypeWithDefault, object)):
return self.api_key[identifier]
def get_basic_auth_token(self):
"""
Gets HTTP basic authentication header (string).
"""Gets HTTP basic authentication header (string).
:return: The token for basic HTTP authentication.
"""
@@ -208,8 +214,7 @@ class Configuration(with_metaclass(TypeWithDefault, object)):
.get('authorization')
def auth_settings(self):
"""
Gets Auth Settings dict for api client.
"""Gets Auth Settings dict for api client.
:return: The Auth Settings information dict.
"""
@@ -244,8 +249,7 @@ class Configuration(with_metaclass(TypeWithDefault, object)):
}
def to_debug_report(self):
"""
Gets the essential information for debugging.
"""Gets the essential information for debugging.
:return: The report for debugging.
"""

View File

@@ -35,14 +35,15 @@
{{#operation}}
{{operationId}} = function({{#allParams}}{{paramName}}, {{/allParams}}...){
args <- list(...)
body <- NULL
queryParams <- list()
headerParams <- character()
{{#hasHeaderParams}}
{{#headerParams}}
if (!missing(`{{paramName}}`)) {
headerParams['{{baseName}}'] <- `{{paramName}}`
}
{{/headerParams}}
{{/hasHeaderParams}}
{{#hasQueryParams}}
@@ -50,6 +51,7 @@
if (!missing(`{{paramName}}`)) {
queryParams['{{baseName}}'] <- {{paramName}}
}
{{/queryParams}}
{{/hasQueryParams}}
{{#hasFormParams}}
@@ -62,25 +64,28 @@
"{{baseName}}" = httr::upload_file({{paramName}}){{#hasMore}},{{/hasMore}}
{{/isFile}}
{{/formParams}}
)
)
{{/hasFormParams}}
{{#hasBodyParam}}
{{#bodyParams}}
if (!missing(`{{paramName}}`)) {
body <- `{{paramName}}`$toJSONString()
} else {
body <- NULL
}
{{/bodyParams}}
{{/hasBodyParam}}
urlPath <- "{{path}}"
{{#hasPathParams}}
{{#pathParams}}
if (!missing(`{{paramName}}`)) {
urlPath <- gsub(paste0("\\{", "{{baseName}}", "\\}"), `{{paramName}}`, urlPath)
}
{{/pathParams}}
{{/hasPathParams}}
resp <- self$apiClient$callApi(url = paste0(self$apiClient$basePath, urlPath),
method = "{{httpMethod}}",
queryParams = queryParams,

View File

@@ -56,11 +56,16 @@
{{#vars}}
if attributes.has_key?(:'{{{baseName}}}')
{{#isContainer}}
{{#isListContainer}}
if (value = attributes[:'{{{baseName}}}']).is_a?(Array)
self.{{{name}}} = value
end
{{/isContainer}}
{{/isListContainer}}
{{#isMapContainer}}
if (value = attributes[:'{{{baseName}}}']).is_a?(Hash)
self.{{{name}}} = value
end
{{/isMapContainer}}
{{^isContainer}}
self.{{{name}}} = attributes[:'{{{baseName}}}']
{{/isContainer}}

View File

@@ -40,36 +40,77 @@ In your project:
npm link {{npmName}}@{{npmVersion}}
```
In your angular2 project:
In your Angular project:
```
import { DefaultApi } from '{{npmName}}/api/api';
// without configuring providers
import { ApiModule } from '{{npmName}}';
@NgModule({
imports: [],
declarations: [],
exports: [],
providers: [AppModule]
imports: [ ApiModule ],
declarations: [ AppComponent ],
providers: [],
bootstrap: [ AppComponent ]
})
export class CoreModule {}
export class AppModule {}
```
```
import { DefaultApi } from '{{npmName}}/api/api';
// configuring providers
import { ApiModule, Configuration, ConfigurationParameters } from '{{npmName}}';
export function apiConfigFactory (): Configuration => {
const params: ConfigurationParameters = {
// set configuration parameters here.
}
return new Configuration(params);
}
@NgModule({
imports: [ ApiModule.forRoot(apiConfigFactory) ],
declarations: [ AppComponent ],
providers: [],
bootstrap: [ AppComponent ]
})
export class AppModule {}
```
```
import { DefaultApi } from '{{npmName}}';
export class AppComponent {
constructor(private apiGateway: DefaultApi) { }
}
```
Note: The ApiModule is restricted to being instantiated once app wide.
This is to ensure that all services are treated as singletons.
### Set service base path
If different than the generated base path, during app bootstrap, you can provide the base path to your service.
```
import { BASE_PATH } from './path-to-swagger-gen-service/index';
import { BASE_PATH } from '{{npmName}}';
bootstrap(AppComponent, [
{ provide: BASE_PATH, useValue: 'https://your-web-service.com' },
]);
```
or
```
import { BASE_PATH } from '{{npmName}}';
@NgModule({
imports: [],
declarations: [ AppComponent ],
providers: [ provide: BASE_PATH, useValue: 'https://your-web-service.com' ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
```
#### Using @angular/cli
First extend your `src/environments/*.ts` files by adding the corresponding base path:
@@ -88,11 +129,11 @@ import { environment } from '../environments/environment';
@NgModule({
declarations: [
AppComponent,
AppComponent
],
imports: [ ],
providers: [{ provide: BASE_PATH, useValue: useValue: environment.API_BASE_PATH }],
bootstrap: [AppComponent]
providers: [{ provide: BASE_PATH, useValue: environment.API_BASE_PATH }],
bootstrap: [ AppComponent ]
})
export class AppModule { }
```

View File

@@ -1,6 +1,11 @@
import { NgModule, ModuleWithProviders } from '@angular/core';
import { NgModule, ModuleWithProviders, SkipSelf, Optional } from '@angular/core';
import { CommonModule } from '@angular/common';
{{#useHttpClient}}
import { HttpClientModule } from '@angular/common/http';
{{/useHttpClient}}
{{^useHttpClient}}
import { HttpModule } from '@angular/http';
{{/useHttpClient}}
import { Configuration } from './configuration';
{{#apiInfo}}
@@ -10,16 +15,24 @@ import { {{classname}} } from './{{importPath}}';
{{/apiInfo}}
@NgModule({
imports: [ CommonModule, HttpModule ],
imports: [ CommonModule, {{#useHttpClient}}HttpClientModule{{/useHttpClient}}{{^useHttpClient}}HttpModule{{/useHttpClient}} ],
declarations: [],
exports: [],
providers: [ {{#apiInfo}}{{#apis}}{{classname}}{{#hasMore}}, {{/hasMore}}{{/apis}}{{/apiInfo}} ]
providers: [
{{#apiInfo}}{{#apis}}{{classname}}{{#hasMore}},
{{/hasMore}}{{/apis}}{{/apiInfo}} ]
})
export class ApiModule {
public static forConfig(configurationFactory: () => Configuration): ModuleWithProviders {
public static forRoot(configurationFactory: () => Configuration): ModuleWithProviders {
return {
ngModule: ApiModule,
providers: [ {provide: Configuration, useFactory: configurationFactory}]
providers: [ { provide: Configuration, useFactory: configurationFactory } ]
}
}
constructor( @Optional() @SkipSelf() parentModule: ApiModule) {
if (parentModule) {
throw new Error('ApiModule is already loaded. Import your base AppModule only.');
}
}
}

View File

@@ -263,17 +263,19 @@ export class {{classname}} {
{{/hasFormParams}}
{{#useHttpClient}}
return this.httpClient.{{httpMethod}}{{^isResponseFile}}<any>{{/isResponseFile}}(`${this.basePath}{{{path}}}`, {{#bodyParam}}{{paramName}}, {{/bodyParam}}
{{#hasFormParams}}convertFormParamsToString ? formParams.toString() : formParams, {{/hasFormParams}}{
return this.httpClient.{{httpMethod}}{{^isResponseFile}}<any>{{/isResponseFile}}(`${this.basePath}{{{path}}}`,{{#isBodyAllowed}}
{{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}{{#hasFormParams}}convertFormParamsToString ? formParams.toString() : formParams{{/hasFormParams}}{{^hasFormParams}}null{{/hasFormParams}}{{/bodyParam}}, {{/isBodyAllowed}}
{
{{#hasQueryParams}}
params: queryParameters,
params: queryParameters,
{{/hasQueryParams}}
headers: headers,
headers: headers,
{{#isResponseFile}}
responseType: "blob",
responseType: "blob",
{{/isResponseFile}}
withCredentials: this.configuration.withCredentials,
});
withCredentials: this.configuration.withCredentials,
}
);
{{/useHttpClient}}
{{^useHttpClient}}
let requestOptions: RequestOptionsArgs = new RequestOptions({

View File

@@ -8,4 +8,4 @@
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
*/

View File

@@ -1,2 +1,9 @@
export type {{classname}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}} | {{/-last}}{{/enumVars}}{{/allowableValues}};
export type {{enumName}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}} | {{/-last}}{{/enumVars}}{{/allowableValues}};
export const {{enumName}} = {
{{#allowableValues}}
{{#enumVars}}
{{name}}: {{{value}}} as {{enumName}}{{^-last}},{{/-last}}
{{/enumVars}}
{{/allowableValues}}
}

View File

@@ -10,14 +10,19 @@ export interface {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{
*/
{{/description}}
{{name}}{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{datatype}}}{{/isEnum}};
{{/vars}}
}{{#hasEnums}}
export namespace {{classname}} {
{{#vars}}
{{#isEnum}}
export type {{enumName}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}} | {{/-last}}{{/enumVars}}{{/allowableValues}};
export const {{enumName}} = {
{{#allowableValues}}
{{#enumVars}}
{{name}}: {{{value}}} as {{enumName}}{{^-last}},{{/-last}}
{{/enumVars}}
{{/allowableValues}}
}
{{/isEnum}}
{{/vars}}
}{{/hasEnums}}
}{{/hasEnums}}

View File

@@ -24,7 +24,7 @@ export const COLLECTION_FORMATS = {
* @interface FetchAPI
*/
export interface FetchAPI {
(url: string, init?: any): Promise<any>;
(url: string, init?: any): Promise<Response>;
}
/**
@@ -253,7 +253,7 @@ export const {{classname}}Fp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
{{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}options?: any): (fetch?: FetchAPI, basePath?: string) => Promise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}any{{/returnType}}> {
{{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}options?: any): (fetch?: FetchAPI, basePath?: string) => Promise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Response{{/returnType}}> {
const localVarFetchArgs = {{classname}}FetchParamCreator(configuration).{{nickname}}({{#allParams}}{{paramName}}, {{/allParams}}options);
return (fetch: FetchAPI = isomorphicFetch, basePath: string = BASE_PATH) => {
return fetch(basePath + localVarFetchArgs.url, localVarFetchArgs.options).then((response) => {

View File

@@ -328,6 +328,48 @@ public class InlineModelResolverTest {
ModelImpl impl = (ModelImpl) body;
assertNotNull(impl.getProperties().get("address"));
}
@Test
public void resolveInlineBodyParameterWithRequired() throws Exception {
Swagger swagger = new Swagger();
swagger.path("/hello", new Path()
.get(new Operation()
.parameter(new BodyParameter()
.name("body")
.schema(new ModelImpl()
.property("address", new ObjectProperty()
.property("street", new StringProperty()
.required(true))
.required(true))
.property("name", new StringProperty())))));
new InlineModelResolver().flatten(swagger);
Operation operation = swagger.getPaths().get("/hello").getGet();
BodyParameter bp = (BodyParameter)operation.getParameters().get(0);
assertTrue(bp.getSchema() instanceof RefModel);
Model body = swagger.getDefinitions().get("body");
assertTrue(body instanceof ModelImpl);
ModelImpl impl = (ModelImpl) body;
assertNotNull(impl.getProperties().get("address"));
Property addressProperty = impl.getProperties().get("address");
assertTrue(addressProperty instanceof RefProperty);
assertTrue(addressProperty.getRequired());
Model helloAddress = swagger.getDefinitions().get("hello_address");
assertTrue(helloAddress instanceof ModelImpl);
ModelImpl addressImpl = (ModelImpl) helloAddress;
assertNotNull(addressImpl);
Property streetProperty = addressImpl.getProperties().get("street");
assertTrue(streetProperty instanceof StringProperty);
assertTrue(streetProperty.getRequired());
}
@Test
public void resolveInlineBodyParameterWithTitle() throws Exception {

View File

@@ -685,7 +685,7 @@
</modules>
</profile>
<profile>
<id>typescript-angular-client</id>
<id>typescript-angularjs-client</id>
<activation>
<property>
<name>env</name>

View File

@@ -685,7 +685,7 @@
</modules>
</profile>
<profile>
<id>typescript-angular-client</id>
<id>typescript-angularjs-client</id>
<activation>
<property>
<name>env</name>

View File

@@ -656,7 +656,7 @@
</modules>
</profile>
<profile>
<id>typescript-angular-client</id>
<id>typescript-angularjs-client</id>
<activation>
<property>
<name>env</name>

View File

@@ -685,7 +685,7 @@
</modules>
</profile>
<profile>
<id>typescript-angular-client</id>
<id>typescript-angularjs-client</id>
<activation>
<property>
<name>env</name>

View File

@@ -181,6 +181,18 @@ public interface FakeApi extends ApiClient.Api {
}
}
/**
* test inline additionalProperties
*
* @param param request body (required)
*/
@RequestLine("POST /fake/inline-additionalProperties")
@Headers({
"Content-Type: application/json",
"Accept: application/json",
})
void testInlineAdditionalProperties(Object param);
/**
* test json serialization of form data
*

View File

@@ -11,6 +11,7 @@ Method | HTTP request | Description
[**testClientModel**](FakeApi.md#testClientModel) | **PATCH** /fake | To test \&quot;client\&quot; model
[**testEndpointParameters**](FakeApi.md#testEndpointParameters) | **POST** /fake | Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트
[**testEnumParameters**](FakeApi.md#testEnumParameters) | **GET** /fake | To test enum parameters
[**testInlineAdditionalProperties**](FakeApi.md#testInlineAdditionalProperties) | **POST** /fake/inline-additionalProperties | test inline additionalProperties
[**testJsonFormData**](FakeApi.md#testJsonFormData) | **GET** /fake/jsonFormData | test json serialization of form data
@@ -376,6 +377,50 @@ No authorization required
- **Content-Type**: */*
- **Accept**: */*
<a name="testInlineAdditionalProperties"></a>
# **testInlineAdditionalProperties**
> testInlineAdditionalProperties(param)
test inline additionalProperties
### Example
```java
// Import classes:
//import io.swagger.client.ApiException;
//import io.swagger.client.api.FakeApi;
FakeApi apiInstance = new FakeApi();
Object param = null; // Object | request body
try {
apiInstance.testInlineAdditionalProperties(param);
} catch (ApiException e) {
System.err.println("Exception when calling FakeApi#testInlineAdditionalProperties");
e.printStackTrace();
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**param** | **Object**| request body |
### Return type
null (empty response body)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: Not defined
<a name="testJsonFormData"></a>
# **testJsonFormData**
> testJsonFormData(param, param2)

View File

@@ -395,6 +395,47 @@ if (enumQueryDouble != null)
apiClient.invokeAPI(localVarPath, "GET", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null);
}
/**
* test inline additionalProperties
*
* @param param request body (required)
* @throws ApiException if fails to make API call
*/
public void testInlineAdditionalProperties(Object param) throws ApiException {
Object localVarPostBody = param;
// verify the required parameter 'param' is set
if (param == null) {
throw new ApiException(400, "Missing the required parameter 'param' when calling testInlineAdditionalProperties");
}
// create path and map variables
String localVarPath = "/fake/inline-additionalProperties";
// query params
List<Pair> localVarQueryParams = new ArrayList<Pair>();
List<Pair> localVarCollectionQueryParams = new ArrayList<Pair>();
Map<String, String> localVarHeaderParams = new HashMap<String, String>();
Map<String, Object> localVarFormParams = new HashMap<String, Object>();
final String[] localVarAccepts = {
};
final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
final String[] localVarContentTypes = {
"application/json"
};
final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
String[] localVarAuthNames = new String[] { };
apiClient.invokeAPI(localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null);
}
/**
* test json serialization of form data
*

View File

@@ -185,8 +185,9 @@ public class PetApi {
* @param tags Tags to filter by (required)
* @return List&lt;Pet&gt;
* @throws ApiException if fails to make API call
* @Deprecated
* @deprecated
*/
@Deprecated
public List<Pet> findPetsByTags(List<String> tags) throws ApiException {
Object localVarPostBody = null;

View File

@@ -11,6 +11,7 @@ Method | HTTP request | Description
[**testClientModel**](FakeApi.md#testClientModel) | **PATCH** /fake | To test \&quot;client\&quot; model
[**testEndpointParameters**](FakeApi.md#testEndpointParameters) | **POST** /fake | Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트
[**testEnumParameters**](FakeApi.md#testEnumParameters) | **GET** /fake | To test enum parameters
[**testInlineAdditionalProperties**](FakeApi.md#testInlineAdditionalProperties) | **POST** /fake/inline-additionalProperties | test inline additionalProperties
[**testJsonFormData**](FakeApi.md#testJsonFormData) | **GET** /fake/jsonFormData | test json serialization of form data
@@ -376,6 +377,50 @@ No authorization required
- **Content-Type**: */*
- **Accept**: */*
<a name="testInlineAdditionalProperties"></a>
# **testInlineAdditionalProperties**
> testInlineAdditionalProperties(param)
test inline additionalProperties
### Example
```java
// Import classes:
//import io.swagger.client.ApiException;
//import io.swagger.client.api.FakeApi;
FakeApi apiInstance = new FakeApi();
Object param = null; // Object | request body
try {
apiInstance.testInlineAdditionalProperties(param);
} catch (ApiException e) {
System.err.println("Exception when calling FakeApi#testInlineAdditionalProperties");
e.printStackTrace();
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**param** | **Object**| request body |
### Return type
null (empty response body)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: Not defined
<a name="testJsonFormData"></a>
# **testJsonFormData**
> testJsonFormData(param, param2)

View File

@@ -374,6 +374,46 @@ if (enumQueryDouble != null)
apiClient.invokeAPI(localVarPath, "GET", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null);
}
/**
* test inline additionalProperties
*
* @param param request body (required)
* @throws ApiException if fails to make API call
*/
public void testInlineAdditionalProperties(Object param) throws ApiException {
Object localVarPostBody = param;
// verify the required parameter 'param' is set
if (param == null) {
throw new ApiException(400, "Missing the required parameter 'param' when calling testInlineAdditionalProperties");
}
// create path and map variables
String localVarPath = "/fake/inline-additionalProperties";
// query params
List<Pair> localVarQueryParams = new ArrayList<Pair>();
Map<String, String> localVarHeaderParams = new HashMap<String, String>();
Map<String, Object> localVarFormParams = new HashMap<String, Object>();
final String[] localVarAccepts = {
};
final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
final String[] localVarContentTypes = {
"application/json"
};
final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
String[] localVarAuthNames = new String[] { };
apiClient.invokeAPI(localVarPath, "POST", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null);
}
/**
* test json serialization of form data
*

View File

@@ -168,8 +168,9 @@ public class PetApi {
* @param tags Tags to filter by (required)
* @return List&lt;Pet&gt;
* @throws ApiException if fails to make API call
* @Deprecated
* @deprecated
*/
@Deprecated
public List<Pet> findPetsByTags(List<String> tags) throws ApiException {
Object localVarPostBody = null;

View File

@@ -11,6 +11,7 @@ Method | HTTP request | Description
[**testClientModel**](FakeApi.md#testClientModel) | **PATCH** /fake | To test \&quot;client\&quot; model
[**testEndpointParameters**](FakeApi.md#testEndpointParameters) | **POST** /fake | Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트
[**testEnumParameters**](FakeApi.md#testEnumParameters) | **GET** /fake | To test enum parameters
[**testInlineAdditionalProperties**](FakeApi.md#testInlineAdditionalProperties) | **POST** /fake/inline-additionalProperties | test inline additionalProperties
[**testJsonFormData**](FakeApi.md#testJsonFormData) | **GET** /fake/jsonFormData | test json serialization of form data
@@ -376,6 +377,50 @@ No authorization required
- **Content-Type**: */*
- **Accept**: */*
<a name="testInlineAdditionalProperties"></a>
# **testInlineAdditionalProperties**
> testInlineAdditionalProperties(param)
test inline additionalProperties
### Example
```java
// Import classes:
//import io.swagger.client.ApiException;
//import io.swagger.client.api.FakeApi;
FakeApi apiInstance = new FakeApi();
Object param = null; // Object | request body
try {
apiInstance.testInlineAdditionalProperties(param);
} catch (ApiException e) {
System.err.println("Exception when calling FakeApi#testInlineAdditionalProperties");
e.printStackTrace();
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**param** | **Object**| request body |
### Return type
null (empty response body)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: Not defined
<a name="testJsonFormData"></a>
# **testJsonFormData**
> testJsonFormData(param, param2)

View File

@@ -374,6 +374,46 @@ if (enumQueryDouble != null)
apiClient.invokeAPI(localVarPath, "GET", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null);
}
/**
* test inline additionalProperties
*
* @param param request body (required)
* @throws ApiException if fails to make API call
*/
public void testInlineAdditionalProperties(Object param) throws ApiException {
Object localVarPostBody = param;
// verify the required parameter 'param' is set
if (param == null) {
throw new ApiException(400, "Missing the required parameter 'param' when calling testInlineAdditionalProperties");
}
// create path and map variables
String localVarPath = "/fake/inline-additionalProperties";
// query params
List<Pair> localVarQueryParams = new ArrayList<Pair>();
Map<String, String> localVarHeaderParams = new HashMap<String, String>();
Map<String, Object> localVarFormParams = new HashMap<String, Object>();
final String[] localVarAccepts = {
};
final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
final String[] localVarContentTypes = {
"application/json"
};
final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
String[] localVarAuthNames = new String[] { };
apiClient.invokeAPI(localVarPath, "POST", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null);
}
/**
* test json serialization of form data
*

View File

@@ -168,8 +168,9 @@ public class PetApi {
* @param tags Tags to filter by (required)
* @return List&lt;Pet&gt;
* @throws ApiException if fails to make API call
* @Deprecated
* @deprecated
*/
@Deprecated
public List<Pet> findPetsByTags(List<String> tags) throws ApiException {
Object localVarPostBody = null;

View File

@@ -41,7 +41,7 @@ public class AdditionalPropertiesClass {
public AdditionalPropertiesClass putMapPropertyItem(String key, String mapPropertyItem) {
if (this.mapProperty == null) {
this.mapProperty = new HashMap<String, String>();
this.mapProperty = new HashMap<>();
}
this.mapProperty.put(key, mapPropertyItem);
return this;
@@ -67,7 +67,7 @@ public class AdditionalPropertiesClass {
public AdditionalPropertiesClass putMapOfMapPropertyItem(String key, Map<String, String> mapOfMapPropertyItem) {
if (this.mapOfMapProperty == null) {
this.mapOfMapProperty = new HashMap<String, Map<String, String>>();
this.mapOfMapProperty = new HashMap<>();
}
this.mapOfMapProperty.put(key, mapOfMapPropertyItem);
return this;

View File

@@ -38,7 +38,7 @@ public class ArrayOfArrayOfNumberOnly {
public ArrayOfArrayOfNumberOnly addArrayArrayNumberItem(List<BigDecimal> arrayArrayNumberItem) {
if (this.arrayArrayNumber == null) {
this.arrayArrayNumber = new ArrayList<List<BigDecimal>>();
this.arrayArrayNumber = new ArrayList<>();
}
this.arrayArrayNumber.add(arrayArrayNumberItem);
return this;

View File

@@ -38,7 +38,7 @@ public class ArrayOfNumberOnly {
public ArrayOfNumberOnly addArrayNumberItem(BigDecimal arrayNumberItem) {
if (this.arrayNumber == null) {
this.arrayNumber = new ArrayList<BigDecimal>();
this.arrayNumber = new ArrayList<>();
}
this.arrayNumber.add(arrayNumberItem);
return this;

View File

@@ -44,7 +44,7 @@ public class ArrayTest {
public ArrayTest addArrayOfStringItem(String arrayOfStringItem) {
if (this.arrayOfString == null) {
this.arrayOfString = new ArrayList<String>();
this.arrayOfString = new ArrayList<>();
}
this.arrayOfString.add(arrayOfStringItem);
return this;
@@ -70,7 +70,7 @@ public class ArrayTest {
public ArrayTest addArrayArrayOfIntegerItem(List<Long> arrayArrayOfIntegerItem) {
if (this.arrayArrayOfInteger == null) {
this.arrayArrayOfInteger = new ArrayList<List<Long>>();
this.arrayArrayOfInteger = new ArrayList<>();
}
this.arrayArrayOfInteger.add(arrayArrayOfIntegerItem);
return this;
@@ -96,7 +96,7 @@ public class ArrayTest {
public ArrayTest addArrayArrayOfModelItem(List<ReadOnlyFirst> arrayArrayOfModelItem) {
if (this.arrayArrayOfModel == null) {
this.arrayArrayOfModel = new ArrayList<List<ReadOnlyFirst>>();
this.arrayArrayOfModel = new ArrayList<>();
}
this.arrayArrayOfModel.add(arrayArrayOfModelItem);
return this;

View File

@@ -128,7 +128,7 @@ public class EnumArrays {
public EnumArrays addArrayEnumItem(ArrayEnumEnum arrayEnumItem) {
if (this.arrayEnum == null) {
this.arrayEnum = new ArrayList<ArrayEnumEnum>();
this.arrayEnum = new ArrayList<>();
}
this.arrayEnum.add(arrayEnumItem);
return this;

View File

@@ -76,7 +76,7 @@ public class MapTest {
public MapTest putMapMapOfStringItem(String key, Map<String, String> mapMapOfStringItem) {
if (this.mapMapOfString == null) {
this.mapMapOfString = new HashMap<String, Map<String, String>>();
this.mapMapOfString = new HashMap<>();
}
this.mapMapOfString.put(key, mapMapOfStringItem);
return this;
@@ -102,7 +102,7 @@ public class MapTest {
public MapTest putMapOfEnumStringItem(String key, InnerEnum mapOfEnumStringItem) {
if (this.mapOfEnumString == null) {
this.mapOfEnumString = new HashMap<String, InnerEnum>();
this.mapOfEnumString = new HashMap<>();
}
this.mapOfEnumString.put(key, mapOfEnumStringItem);
return this;

Some files were not shown because too many files have changed in this diff Show More