From 8e62ef7b8c75f28cfe325f149e9a7c84cc49aa31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Simon=20Maria=20M=C3=B6llers?= Date: Wed, 5 Jul 2017 10:43:56 +0200 Subject: [PATCH] [PHP][Symfony] Add a Symfony server generator #3486 (#5973) --- .../codegen/languages/AbstractPhpCodegen.java | 8 + .../languages/SymfonyServerCodegen.java | 450 ++++++++++++++++++ .../services/io.swagger.codegen.CodegenConfig | 1 + .../src/main/resources/php-symfony/.php_cs | 18 + .../main/resources/php-symfony/.travis.yml | 10 + .../resources/php-symfony/ApiPass.mustache | 60 +++ .../resources/php-symfony/ApiServer.mustache | 70 +++ .../resources/php-symfony/Bundle.mustache | 40 ++ .../resources/php-symfony/Controller.mustache | 116 +++++ .../resources/php-symfony/Extension.mustache | 47 ++ .../php-symfony/ModelInterface.mustache | 55 +++ .../php-symfony/ModelSerializer.mustache | 174 +++++++ .../resources/php-symfony/README.mustache | 135 ++++++ .../main/resources/php-symfony/api.mustache | 64 +++ .../php-symfony/api_controller.mustache | 176 +++++++ .../resources/php-symfony/api_doc.mustache | 72 +++ .../resources/php-symfony/api_test.mustache | 77 +++ .../resources/php-symfony/autoload.mustache | 44 ++ .../resources/php-symfony/composer.mustache | 37 ++ .../php-symfony/git_push.sh.mustache | 52 ++ .../main/resources/php-symfony/model.mustache | 41 ++ .../resources/php-symfony/model_doc.mustache | 11 + .../resources/php-symfony/model_enum.mustache | 19 + .../php-symfony/model_generic.mustache | 357 ++++++++++++++ .../resources/php-symfony/model_test.mustache | 82 ++++ .../php-symfony/partial_header.mustache | 14 + .../php-symfony/phpunit.xml.mustache | 21 + .../resources/php-symfony/routing.mustache | 19 + .../resources/php-symfony/services.mustache | 10 + 29 files changed, 2280 insertions(+) create mode 100644 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SymfonyServerCodegen.java create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/.php_cs create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/.travis.yml create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/ApiPass.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/ApiServer.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/Bundle.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/Controller.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/Extension.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/ModelInterface.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/ModelSerializer.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/README.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/api.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/api_controller.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/api_doc.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/api_test.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/autoload.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/composer.mustache create mode 100755 modules/swagger-codegen/src/main/resources/php-symfony/git_push.sh.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/model.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/model_doc.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/model_enum.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/model_generic.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/model_test.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/partial_header.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/phpunit.xml.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/routing.mustache create mode 100644 modules/swagger-codegen/src/main/resources/php-symfony/services.mustache diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java index a7c339d90f..f38e692c6b 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractPhpCodegen.java @@ -660,4 +660,12 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg return input.replace("*/", ""); } + protected String extractSimpleName(String phpClassName) { + if (phpClassName == null) { + return null; + } + + final int lastBackslashIndex = phpClassName.lastIndexOf('\\'); + return phpClassName.substring(lastBackslashIndex + 1); + } } diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SymfonyServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SymfonyServerCodegen.java new file mode 100644 index 0000000000..cbac5e779a --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SymfonyServerCodegen.java @@ -0,0 +1,450 @@ +package io.swagger.codegen.languages; + +import io.swagger.codegen.*; +import io.swagger.models.properties.ArrayProperty; +import io.swagger.models.properties.MapProperty; +import io.swagger.models.properties.Property; +import io.swagger.models.properties.RefProperty; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.*; + +public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenConfig { + @SuppressWarnings("hiding") + static Logger LOGGER = LoggerFactory.getLogger(SymfonyServerCodegen.class); + + public static final String VARIABLE_NAMING_CONVENTION = "variableNamingConvention"; + public static final String BUNDLE_NAME = "bundleName"; + public static final String COMPOSER_VENDOR_NAME = "composerVendorName"; + public static final String COMPOSER_PROJECT_NAME = "composerProjectName"; + public static final Map SYMFONY_EXCEPTIONS; + protected String testsPackage; + protected String apiTestsPackage; + protected String modelTestsPackage; + protected String composerVendorName = "swagger"; + protected String composerProjectName = "server-bundle"; + protected String testsDirName = "Tests"; + protected String bundleName; + protected String bundleClassName; + protected String bundleExtensionName; + protected String bundleAlias; + protected String controllerDirName = "Controller"; + protected String controllerPackage; + + static { + SYMFONY_EXCEPTIONS = new HashMap<>(); + SYMFONY_EXCEPTIONS.put("400", "Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException"); + SYMFONY_EXCEPTIONS.put("401", "Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException"); + SYMFONY_EXCEPTIONS.put("403", "Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException"); + SYMFONY_EXCEPTIONS.put("404", "Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException"); + SYMFONY_EXCEPTIONS.put("405", "Symfony\\Component\\HttpKernel\\Exception\\MethodNotAllowedHttpException"); + SYMFONY_EXCEPTIONS.put("406", "Symfony\\Component\\HttpKernel\\Exception\\NotAcceptableHttpException"); + SYMFONY_EXCEPTIONS.put("409", "Symfony\\Component\\HttpKernel\\Exception\\ConflictHttpException"); + SYMFONY_EXCEPTIONS.put("410", "Symfony\\Component\\HttpKernel\\Exception\\GoneHttpException"); + SYMFONY_EXCEPTIONS.put("411", "Symfony\\Component\\HttpKernel\\Exception\\LengthRequiredHttpException"); + SYMFONY_EXCEPTIONS.put("412", "Symfony\\Component\\HttpKernel\\Exception\\PreconditionFailedHttpException"); + SYMFONY_EXCEPTIONS.put("415", "Symfony\\Component\\HttpKernel\\Exception\\UnsupportedMediaTypeHttpException"); + SYMFONY_EXCEPTIONS.put("422", "Symfony\\Component\\HttpKernel\\Exception\\UnprocessableEntityHttpException"); + SYMFONY_EXCEPTIONS.put("428", "Symfony\\Component\\HttpKernel\\Exception\\PreconditionRequiredHttpException"); + SYMFONY_EXCEPTIONS.put("429", "Symfony\\Component\\HttpKernel\\Exception\\TooManyRequestsHttpException"); + SYMFONY_EXCEPTIONS.put("503", "Symfony\\Component\\HttpKernel\\Exception\\ServiceUnavailableHttpException"); + } + + public SymfonyServerCodegen() { + super(); + + // clear import mapping (from default generator) as php does not use it + // at the moment + importMapping.clear(); + + supportsInheritance = true; + srcBasePath = "."; + setInvokerPackage("Swagger\\Server"); + setBundleName("SwaggerServer"); + packagePath = "SymfonyBundle-php"; + modelDirName = "Model"; + docsBasePath = "Resources/docs"; + apiDocPath = docsBasePath + "/" + apiDirName; + modelDocPath = docsBasePath + "/" + modelDirName; + outputFolder = "generated-code" + File.separator + "php"; + apiTemplateFiles.put("api_controller.mustache", ".php"); + modelTestTemplateFiles.put("model_test.mustache", ".php"); + embeddedTemplateDir = templateDir = "php-symfony"; + + setReservedWordsLowerCase( + Arrays.asList( + // local variables used in api methods (endpoints) + "resourcePath", "httpBody", "queryParams", "headerParams", + "formParams", "_header_accept", "_tempBody", + + // PHP reserved words + "__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor") + ); + + // ref: http://php.net/manual/en/language.types.intro.php + languageSpecificPrimitives = new HashSet( + Arrays.asList( + "bool", + "boolean", + "int", + "integer", + "double", + "float", + "string", + "object", + "DateTime", + "mixed", + "number", + "void", + "byte") + ); + + instantiationTypes.put("array", "array"); + instantiationTypes.put("map", "map"); + + + // provide primitives to mustache template + List sortedLanguageSpecificPrimitives= new ArrayList(languageSpecificPrimitives); + Collections.sort(sortedLanguageSpecificPrimitives); + String primitives = "'" + StringUtils.join(sortedLanguageSpecificPrimitives, "', '") + "'"; + additionalProperties.put("primitives", primitives); + + // ref: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types + typeMapping = new HashMap(); + typeMapping.put("integer", "int"); + typeMapping.put("long", "int"); + typeMapping.put("number", "float"); + typeMapping.put("float", "float"); + typeMapping.put("double", "double"); + typeMapping.put("string", "string"); + typeMapping.put("byte", "int"); + typeMapping.put("boolean", "bool"); + typeMapping.put("Date", "\\DateTime"); + typeMapping.put("DateTime", "\\DateTime"); + typeMapping.put("file", "\\SplFileObject"); + typeMapping.put("map", "map"); + typeMapping.put("array", "array"); + typeMapping.put("list", "array"); + typeMapping.put("object", "object"); + typeMapping.put("binary", "string"); + typeMapping.put("ByteArray", "string"); + typeMapping.put("UUID", "string"); + + cliOptions.add(new CliOption(COMPOSER_VENDOR_NAME, "The vendor name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. yaypets. IMPORTANT NOTE (2016/03): composerVendorName will be deprecated and replaced by gitUserId in the next swagger-codegen release")); + cliOptions.add(new CliOption(BUNDLE_NAME, "The name of the Symfony bundle. The template uses {{bundleName}}")); + cliOptions.add(new CliOption(COMPOSER_PROJECT_NAME, "The project name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. petstore-client. IMPORTANT NOTE (2016/03): composerProjectName will be deprecated and replaced by gitRepoId in the next swagger-codegen release")); + cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "hides the timestamp when files were generated") + .defaultValue(Boolean.TRUE.toString())); + } + + public String getBundleName() { + return bundleName; + } + + public void setBundleName(String bundleName) { + this.bundleName = bundleName; + this.bundleClassName = bundleName + "Bundle"; + this.bundleExtensionName = bundleName + "Extension"; + this.bundleAlias = snakeCase(bundleName).replaceAll("([A-Z]+)", "\\_$1").toLowerCase(); + } + + + public String controllerFileFolder() { + return (outputFolder + "/" + toPackagePath(controllerPackage, srcBasePath)); + } + + @Override + public String escapeText(String input) { + if (input != null) { + // Trim the string to avoid leading and trailing spaces. + return super.escapeText(input).trim(); + } + return input; + } + + @Override + public CodegenType getTag() { + return CodegenType.SERVER; + } + + @Override + public String getName() { + return "php-symfony"; + } + + @Override + public String getHelp() { + return "Generates a Symfony server bundle."; + } + + @Override + public String apiFilename(String templateName, String tag) { + String suffix = apiTemplateFiles().get(templateName); + if (templateName.equals("api_controller.mustache")) + return controllerFileFolder() + '/' + toControllerName(tag) + suffix; + + return apiFileFolder() + '/' + toApiFilename(tag) + suffix; + } + + @Override + public void processOpts() { + super.processOpts(); + + // default HIDE_GENERATION_TIMESTAMP to true + if (!additionalProperties.containsKey(CodegenConstants.HIDE_GENERATION_TIMESTAMP)) { + additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, Boolean.TRUE.toString()); + } else { + additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, + Boolean.valueOf(additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP).toString())); + } + + if (additionalProperties.containsKey(BUNDLE_NAME)) { + this.setBundleName((String) additionalProperties.get(BUNDLE_NAME)); + } else { + additionalProperties.put(BUNDLE_NAME, bundleName); + } + + if (additionalProperties.containsKey(COMPOSER_PROJECT_NAME)) { + this.setComposerProjectName((String) additionalProperties.get(COMPOSER_PROJECT_NAME)); + } else { + additionalProperties.put(COMPOSER_PROJECT_NAME, composerProjectName); + } + + if (additionalProperties.containsKey(COMPOSER_VENDOR_NAME)) { + this.setComposerVendorName((String) additionalProperties.get(COMPOSER_VENDOR_NAME)); + } else { + additionalProperties.put(COMPOSER_VENDOR_NAME, composerVendorName); + } + + if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_VERSION)) { + this.setArtifactVersion((String) additionalProperties.get(CodegenConstants.ARTIFACT_VERSION)); + } else { + additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); + } + + if (additionalProperties.containsKey(VARIABLE_NAMING_CONVENTION)) { + this.setParameterNamingConvention((String) additionalProperties.get(VARIABLE_NAMING_CONVENTION)); + } + + additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\")); + additionalProperties.put("controllerPackage", controllerPackage); + additionalProperties.put("apiTestsPackage", apiTestsPackage); + additionalProperties.put("modelTestsPackage", modelTestsPackage); + + // make Symonfy-specific properties available + additionalProperties.put("bundleName", bundleName); + additionalProperties.put("bundleClassName", bundleClassName); + additionalProperties.put("bundleExtensionName", bundleExtensionName); + additionalProperties.put("bundleAlias", bundleAlias); + + // make api and model src path available in mustache template + additionalProperties.put("apiSrcPath", "./" + toSrcPath(apiPackage, srcBasePath)); + additionalProperties.put("modelSrcPath", "./" + toSrcPath(modelPackage, srcBasePath)); + additionalProperties.put("testsSrcPath", "./" + toSrcPath(testsPackage, srcBasePath)); + additionalProperties.put("apiTestsSrcPath", "./" + toSrcPath(apiTestsPackage, srcBasePath)); + additionalProperties.put("modelTestsSrcPath", "./" + toSrcPath(modelTestsPackage, srcBasePath)); + additionalProperties.put("apiTestPath", "./" + testsDirName + "/" + apiDirName); + additionalProperties.put("modelTestPath", "./" + testsDirName + "/" + modelDirName); + + // make api and model doc path available in mustache template + additionalProperties.put("apiDocPath", apiDocPath); + additionalProperties.put("modelDocPath", modelDocPath); + + // make test path available in mustache template + additionalProperties.put("testsDirName", testsDirName); + + supportingFiles.add(new SupportingFile("Controller.mustache", toPackagePath(controllerPackage, srcBasePath), "Controller.php")); + supportingFiles.add(new SupportingFile("Bundle.mustache", getPackagePath(), bundleClassName + ".php")); + supportingFiles.add(new SupportingFile("Extension.mustache", getPackagePath() + "/DependencyInjection", bundleExtensionName + ".php")); + supportingFiles.add(new SupportingFile("ApiPass.mustache", getPackagePath() + "/DependencyInjection/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")); + supportingFiles.add(new SupportingFile("routing.mustache", getPackagePath() + "/Resources/config", "routing.yml")); + supportingFiles.add(new SupportingFile("services.mustache", getPackagePath() + "/Resources/config", "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")); + } + + @Override + public Map postProcessOperations(Map objs) { + objs = super.postProcessOperations(objs); + Map operations = (Map) objs.get("operations"); + operations.put("controllerName", toControllerName((String) operations.get("pathPrefix"))); + operations.put("symfonyService", toSymfonyService((String) operations.get("pathPrefix"))); + + HashSet imports = new HashSet<>(); + List operationList = (List) operations.get("operation"); + for (CodegenOperation op : operationList) { + for (CodegenParameter param : op.allParams) { + final String simpleName = extractSimpleName(param.dataType); + param.vendorExtensions.put("x-simpleName", simpleName); + final boolean isScalarType = typeMapping.containsValue(param.dataType); + param.vendorExtensions.put("x-parameterType", isScalarType ? null : simpleName); + if (!isScalarType) { + imports.add(param.dataType); + } + } + + for (CodegenResponse response : op.responses) { + final String exception = SYMFONY_EXCEPTIONS.get(response.code); + response.vendorExtensions.put("x-symfonyException", exception); + response.vendorExtensions.put("x-symfonyExceptionSimple", extractSimpleName(exception)); + + // Add simple return type to response + if (response.dataType != null) { + final String dataType = extractSimpleName(response.dataType); + response.vendorExtensions.put("x-simpleName", dataType); + imports.add(response.dataType.replaceFirst("\\[\\]$", "")); + } + + if (exception != null) { + imports.add(exception); + } + } + } + + operations.put("imports", new ArrayList<>(imports)); + + return objs; + } + + @Override + public Map postProcessModels(Map objs) { + objs = super.postProcessModels(objs); + + ArrayList modelsArray = (ArrayList) objs.get("models"); + Map models = (Map) modelsArray.get(0); + CodegenModel model = (CodegenModel) models.get("model"); + HashSet 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); + if (!isScalarType) { + var.vendorExtensions.put("x-typeAnnotation", dataType.endsWith("[]") ? "array" : dataType); + imports.add(importType); + var.datatype = dataType; + } + } + } + + objs.put("useStatements", new ArrayList<>(imports)); + + return objs; + } + + @Override + public String escapeReservedWord(String name) { + if(this.reservedWordsMappings().containsKey(name)) { + return this.reservedWordsMappings().get(name); + } + return "_" + name; + } + + @Override + public String apiTestFileFolder() { + return (outputFolder + "/" + toPackagePath(apiTestsPackage, srcBasePath)); + } + + @Override + public String modelTestFileFolder() { + return (outputFolder + "/" + toPackagePath(modelTestsPackage, srcBasePath)); + } + + public void setComposerVendorName(String composerVendorName) { + this.composerVendorName = composerVendorName; + } + + public void setComposerProjectName(String composerProjectName) { + this.composerProjectName = composerProjectName; + } + + @Override + public void setInvokerPackage(String invokerPackage) { + super.setInvokerPackage(invokerPackage); + apiPackage = invokerPackage + "\\" + apiDirName; + modelPackage = invokerPackage + "\\" + modelDirName; + testsPackage = invokerPackage + "\\" + testsDirName; + apiTestsPackage = testsPackage + "\\" + apiDirName; + modelTestsPackage = testsPackage + "\\" + modelDirName; + controllerPackage = invokerPackage + "\\" + controllerDirName; + } + + @Override + public String getTypeDeclaration(Property p) { + if (p instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) p; + Property inner = ap.getItems(); + return getTypeDeclaration(inner) + "[]"; + } + + if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + return getSwaggerType(p) + "array"; + } + + if (p instanceof RefProperty) { + return getTypeDeclaration(getPropertyTypeDeclaration(p)); + } + + return getPropertyTypeDeclaration(p); + } + + /** + * Output the type declaration of the property + * + * @param p Swagger Property object + * @return a string presentation of the property type + */ + public String getPropertyTypeDeclaration(Property p) { + String swaggerType = getSwaggerType(p); + if (typeMapping.containsKey(swaggerType)) { + return typeMapping.get(swaggerType); + } + return swaggerType; + } + + @Override + public String getTypeDeclaration(String name) { + if (!languageSpecificPrimitives.contains(name)) { + return modelPackage + "\\" + name; + } + return super.getTypeDeclaration(name); + } + + public String toApiName(String name) { + if (name.isEmpty()) { + return "DefaultApiInterface"; + } + return initialCaps(name) + "ApiInterface"; + } + + protected String toControllerName(String name) { + if (name.isEmpty()) { + return "DefaultController"; + } + return initialCaps(name) + "Controller"; + } + + protected String toSymfonyService(String name) { + String prefix = composerVendorName + ".api."; + if (name.isEmpty()) { + return prefix + "default"; + } + + return prefix + name; + } +} diff --git a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig index 0242440fba..dec42fb401 100644 --- a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig +++ b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig @@ -43,6 +43,7 @@ io.swagger.codegen.languages.NodeJSServerCodegen io.swagger.codegen.languages.ObjcClientCodegen io.swagger.codegen.languages.PerlClientCodegen io.swagger.codegen.languages.PhpClientCodegen +io.swagger.codegen.languages.SymfonyServerCodegen io.swagger.codegen.languages.PowerShellClientCodegen io.swagger.codegen.languages.PistacheServerCodegen io.swagger.codegen.languages.PythonClientCodegen diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/.php_cs b/modules/swagger-codegen/src/main/resources/php-symfony/.php_cs new file mode 100644 index 0000000000..6b8e23c818 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/.php_cs @@ -0,0 +1,18 @@ +level(Symfony\CS\FixerInterface::PSR2_LEVEL) + ->setUsingCache(true) + ->fixers( + [ + 'ordered_use', + 'phpdoc_order', + 'short_array_syntax', + 'strict', + 'strict_param' + ] + ) + ->finder( + Symfony\CS\Finder\DefaultFinder::create() + ->in(__DIR__) + ); diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/.travis.yml b/modules/swagger-codegen/src/main/resources/php-symfony/.travis.yml new file mode 100644 index 0000000000..d77f3825f6 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/.travis.yml @@ -0,0 +1,10 @@ +language: php +sudo: false +php: + - 5.4 + - 5.5 + - 5.6 + - 7.0 + - hhvm +before_install: "composer install" +script: "vendor/bin/phpunit" diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/ApiPass.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/ApiPass.mustache new file mode 100644 index 0000000000..069db48d3e --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/ApiPass.mustache @@ -0,0 +1,60 @@ +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 {{invokerPackage}}\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * {{bundleName}}ApiPass Class Doc Comment + * + * @category Class + * @package {{invokerPackage}}\DependencyInjection\Compiler + * @author Swagger Codegen team + * @link https://github.com/swagger-api/swagger-codegen + */ +class {{bundleName}}ApiPass implements CompilerPassInterface +{ + + /** + * You can modify the container here before it is dumped to PHP code. + * + * @param ContainerBuilder $container + */ + public function process(ContainerBuilder $container) { + // always first check if the primary service is defined + if (!$container->has('{{bundleAlias}}.api.api_server')) { + return; + } + + $definition = $container->findDefinition('{{bundleAlias}}.api.api_server'); + + // find all service IDs with the {{bundleAlias}}.api tag + $taggedServices = $container->findTaggedServiceIds('{{bundleAlias}}.api'); + + foreach ($taggedServices as $id => $tags) { + foreach ($tags as $tag) { + // add the transport service to the ChainTransport service + $definition->addMethodCall('addApiHandler', [$tag['api'], new Reference($id)]); + } + } + } +} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/ApiServer.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/ApiServer.mustache new file mode 100644 index 0000000000..c50b787a23 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/ApiServer.mustache @@ -0,0 +1,70 @@ +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 {{apiPackage}}; + +/** + * ApiServer Class Doc Comment + * + * PHP version 5 + * + * @category Class + * @package {{apiPackage}} + * @author Swagger Codegen team + * @link https://github.com/swagger-api/swagger-codegen + */ +class ApiServer +{ + + /** + * @var array + */ + private $apis = array(); + + /** + * Adds an API handler to the server. + * + * @param string $api An API name of the handle + * @param mixed $handler A handler to set for the given API + */ + public function addApiHandler($api, $handler) + { + if (isset($this->apis[$api])) { + throw new \InvalidArgumentException('API has already a handler: '.$api); + } + + $this->apis[$api] = $handler; + } + + /** + * Returns an API handler. + * + * @param string $api An API name of the handle + * @return mixed Returns a handler + * @throws \InvalidArgumentException When no such handler exists + */ + public function getApiHandler($api) + { + if (!isset($this->apis[$api])) { + throw new \InvalidArgumentException('No handler for '.$api.' implemented.'); + } + + return $this->apis[$api]; + } +} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/Bundle.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/Bundle.mustache new file mode 100644 index 0000000000..72f105e7b7 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/Bundle.mustache @@ -0,0 +1,40 @@ +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 {{invokerPackage}}; + +use Symfony\Component\HttpKernel\Bundle\Bundle; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use {{invokerPackage}}\DependencyInjection\Compiler\{{bundleName}}ApiPass; + +/** + * {{bundleClassName}} Class Doc Comment + * + * @category Class + * @package {{invokerPackage}} + * @author Swagger Codegen team + * @link https://github.com/swagger-api/swagger-codegen + */ +class {{bundleClassName}} extends Bundle +{ + public function build(ContainerBuilder $container) + { + $container->addCompilerPass(new {{bundleName}}ApiPass()); + } +} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/Controller.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/Controller.mustache new file mode 100644 index 0000000000..e5561f0134 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/Controller.mustache @@ -0,0 +1,116 @@ +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 {{controllerPackage}}; + +use Symfony\Bundle\FrameworkBundle\Controller\Controller as BaseController; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\HttpException; + +/** + * Controller Class Doc Comment + * + * @category Class + * @package {{controllerPackage}} + * @author Swagger Codegen team + * @link https://github.com/swagger-api/swagger-codegen + */ +class Controller extends BaseController +{ + + /** + * 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); + } + + /** + * 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']); + + $json = $this->exceptionToArray($exception); + $json["statusCode"] = $statusCode; + + return new Response(json_encode($json, 15, 512), $statusCode, $headers); + } + + /** + * 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); + } + + /** + * 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); + } + + /** + * 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()), + ]; + } +} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/Extension.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/Extension.mustache new file mode 100644 index 0000000000..25b99c8ed5 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/Extension.mustache @@ -0,0 +1,47 @@ +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 {{invokerPackage}}\DependencyInjection; + +use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\Extension; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; + +/** + * {{bundleExtensionName}} Class Doc Comment + * + * @category Class + * @package {{invokerPackage}}\DependencyInjection + * @author Swagger Codegen team + * @link https://github.com/swagger-api/swagger-codegen + */ +class {{bundleExtensionName}} extends Extension +{ + public function load(array $configs, ContainerBuilder $container) + { + $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + $loader->load('services.yml'); + } + + public function getAlias() + { + return '{{bundleAlias}}'; + } +} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/ModelInterface.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/ModelInterface.mustache new file mode 100644 index 0000000000..a568374d6d --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/ModelInterface.mustache @@ -0,0 +1,55 @@ +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(); +} + + diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/ModelSerializer.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/ModelSerializer.mustache new file mode 100644 index 0000000000..c2064b60a8 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/ModelSerializer.mustache @@ -0,0 +1,174 @@ +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; + } +} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/README.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/README.mustache new file mode 100644 index 0000000000..ab0da1711f --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/README.mustache @@ -0,0 +1,135 @@ +# {{packagePath}} +{{#appDescription}} +{{{appDescription}}} +{{/appDescription}} + +This PHP package is automatically generated by the [Swagger Codegen](https://github.com/swagger-api/swagger-codegen) project: + +- API version: {{appVersion}} +{{#artifactVersion}} +- Package version: {{artifactVersion}} +{{/artifactVersion}} +{{^hideGenerationTimestamp}} +- Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} +- Build package: {{generatorClass}} +{{#infoUrl}} +For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) +{{/infoUrl}} + +## Requirements + +PHP 5.4.0 and later + +## Installation & Usage +### Composer + +To install the bindings via [Composer](http://getcomposer.org/), add the following to `composer.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" + } +} +``` + +Then run `composer install` + +### Manual Installation + +Download the files and include `autoload.php`: + +```php + require_once('/path/to/{{packagePath}}/autoload.php'); +``` + +## Tests + +To run the unit tests: + +``` +composer install +./vendor/bin/phpunit +``` + +## Getting Started + +Please follow the [installation procedure](#installation--usage) and then run the following: + +```php +setUsername('YOUR_USERNAME'); +{{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setPassword('YOUR_PASSWORD');{{/isBasic}}{{#isApiKey}} +// Configure API key authorization: {{{name}}} +{{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setApiKey('{{{keyParamName}}}', 'YOUR_API_KEY'); +// Uncomment below to setup prefix (e.g. Bearer) for API key, if needed +// {{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setApiKeyPrefix('{{{keyParamName}}}', 'Bearer');{{/isApiKey}}{{#isOAuth}} +// Configure OAuth2 access token for authorization: {{{name}}} +{{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setAccessToken('YOUR_ACCESS_TOKEN');{{/isOAuth}}{{/authMethods}} +{{/hasAuthMethods}} + +$api_instance = new {{invokerPackage}}\Api\{{classname}}(); +{{#allParams}}${{paramName}} = {{{example}}}; // {{{dataType}}} | {{{description}}} +{{/allParams}} + +try { + {{#returnType}}$result = {{/returnType}}$api_instance->{{{operationId}}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + print_r($result);{{/returnType}} +} catch (Exception $e) { + echo 'Exception when calling {{classname}}->{{operationId}}: ', $e->getMessage(), PHP_EOL; +} +{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} +?> +``` + +## Documentation for API Endpoints + +All URIs are relative to *{{basePath}}* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}/{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + +## Documentation For Models + +{{#models}}{{#model}} - [{{{classname}}}]({{modelDocPath}}/{{{classname}}}.md) +{{/model}}{{/models}} + +## Documentation For Authorization + +{{^authMethods}} All endpoints do not require authorization. +{{/authMethods}}{{#authMethods}}{{#last}} Authentication schemes defined for the API:{{/last}}{{/authMethods}} +{{#authMethods}}## {{{name}}} + +{{#isApiKey}}- **Type**: API key +- **API key parameter name**: {{{keyParamName}}} +- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} +{{/isApiKey}} +{{#isBasic}}- **Type**: HTTP basic authentication +{{/isBasic}} +{{#isOAuth}}- **Type**: OAuth +- **Flow**: {{{flow}}} +- **Authorization URL**: {{{authorizationUrl}}} +- **Scopes**: {{^scopes}}N/A{{/scopes}} +{{#scopes}} - **{{{scope}}}**: {{{description}}} +{{/scopes}} +{{/isOAuth}} + +{{/authMethods}} + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} + diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/api.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/api.mustache new file mode 100644 index 0000000000..a55569a383 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/api.mustache @@ -0,0 +1,64 @@ +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 {{apiPackage}}; + +{{#operations}}{{#imports}}use {{this}}; +{{/imports}} + +/** + * {{classname}} Interface Doc Comment + * + * @category Interface + * @package {{apiPackage}} + * @author Swagger Codegen team + * @link https://github.com/swagger-api/swagger-codegen + */ +interface {{classname}} +{ + {{#operation}} + + /** + * Operation {{{operationId}}} + {{#summary}} + * + * {{{summary}}} + {{/summary}} + * + {{#description}} + * {{.}} + * + {{/description}} + {{#allParams}} + * @param {{vendorExtensions.x-simpleName}} ${{paramName}} {{description}} {{#required}}(required){{/required}}{{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + * + {{#responses}} + {{#vendorExtensions.x-symfonyExceptionSimple}} + * @throws {{vendorExtensions.x-symfonyExceptionSimple}} {{message}} + {{/vendorExtensions.x-symfonyExceptionSimple}} + {{^vendorExtensions.x-symfonyExceptionSimple}} + * @return {{^dataType}}void{{/dataType}}{{#dataType}}{{vendorExtensions.x-simpleName}}{{/dataType}} {{message}} + * + {{/vendorExtensions.x-symfonyExceptionSimple}} + {{/responses}} + */ + public function {{operationId}}({{#allParams}}{{#vendorExtensions.x-parameterType}}{{vendorExtensions.x-parameterType}} {{/vendorExtensions.x-parameterType}}${{paramName}}{{^required}} = {{#defaultValue}}'{{{.}}}'{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); +{{/operation}} +} +{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/api_controller.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/api_controller.mustache new file mode 100644 index 0000000000..e28cb5908e --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/api_controller.mustache @@ -0,0 +1,176 @@ +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 {{controllerPackage}}; + +use \Exception; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\HttpException; +use {{apiPackage}}\{{classname}}; +{{#imports}}use {{this}}; +{{/imports}} + +/** + * {{controllerName}} Class Doc Comment + * + * @category Class + * @package {{controllerPackage}} + * @author Swagger Codegen team + * @link https://github.com/swagger-api/swagger-codegen + */ +class {{controllerName}} extends Controller +{ + {{#operation}} + + /** + * Operation {{{operationId}}} +{{#summary}} + * + * {{{summary}}} +{{/summary}} + * +{{#description}} + * {{.}} + * +{{/description}} + * @param Request $request The Symfony request to handle. + * @return Response The Symfony response. + */ + public function {{operationId}}Action(Request $request) + { + {{#queryParams}} + // Handle query params + ${{paramName}} = $request->query->get('{{paramName}}'); + {{/queryParams}} + {{#headerParams}} + // Handle header params + ${{paramName}} = $request->headers->get('{{paramName}}'); + {{/headerParams}} + {{#pathParams}} + // Handle path params + ${{paramName}} = $request->attributes->get('{{paramName}}'); + {{/pathParams}} + {{#formParams}} + {{#isFile}} + // Handle file params + ${{paramName}} = $request->files->get('{{paramName}}'); + {{/isFile}} + {{^isFile}} + // Handle form params + ${{paramName}} = $request->request->get('{{paramName}}'); + {{/isFile}} + {{/formParams}} + {{#bodyParams}} + // Handle body params + ${{paramName}} = $this->deserialize($request->getContent(), '{{{dataType}}}', 'json'); + {{/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}}'); + } + {{/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}} + {{/allParams}} + + // Call the API interface + try { + {{#returnType}} + // Expecting a return value (exception otherwise) + $result = $this->getApiHandler()->{{operationId}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + + {{#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}} + {{/responses}} + {{/returnType}} + {{^returnType}} + // No return type expected; return empty response + $this->getApiHandler()->{{operationId}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + return new Response('', 204); + {{/returnType}} + {{#responses}} + {{#vendorExtensions.x-symfonyExceptionSimple}} + } catch ({{vendorExtensions.x-symfonyExceptionSimple}} $exception) { + // {{message}} + return $this->createErrorResponse($exception); + {{/vendorExtensions.x-symfonyExceptionSimple}} + {{/responses}} + } catch (Exception $fallthrough) { + return $this->createErrorResponse(new HttpException(500, 'An unsuspected error occurred.', $fallthrough)); + } + } + {{/operation}} + + /** + * Returns the handler for this API controller. + * @return {{classname}} + */ + public function getApiHandler() + { + return $this->get('{{bundleAlias}}.api.api_server')->getApiHandler('{{pathPrefix}}'); + } +} +{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/api_doc.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/api_doc.mustache new file mode 100644 index 0000000000..75ec5f8acd --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/api_doc.mustache @@ -0,0 +1,72 @@ +# {{invokerPackage}}\{{classname}}{{#description}} +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} +# **{{{operationId}}}** +> {{#returnType}}{{{returnType}}} {{/returnType}}{{{operationId}}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) + +{{{summary}}}{{#notes}} + +{{{notes}}}{{/notes}} + +### Example +```php +setUsername('YOUR_USERNAME'); +{{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setPassword('YOUR_PASSWORD');{{/isBasic}}{{#isApiKey}} +// Configure API key authorization: {{{name}}} +{{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setApiKey('{{{keyParamName}}}', 'YOUR_API_KEY'); +// Uncomment below to setup prefix (e.g. Bearer) for API key, if needed +// {{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setApiKeyPrefix('{{{keyParamName}}}', 'Bearer');{{/isApiKey}}{{#isOAuth}} +// Configure OAuth2 access token for authorization: {{{name}}} +{{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setAccessToken('YOUR_ACCESS_TOKEN');{{/isOAuth}}{{/authMethods}} +{{/hasAuthMethods}} + +$api_instance = new {{invokerPackage}}\Api\{{classname}}(); +{{#allParams}}${{paramName}} = {{{example}}}; // {{{dataType}}} | {{{description}}} +{{/allParams}} + +try { + {{#returnType}}$result = {{/returnType}}$api_instance->{{{operationId}}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + print_r($result);{{/returnType}} +} catch (Exception $e) { + echo 'Exception when calling {{classname}}->{{operationId}}: ', $e->getMessage(), PHP_EOL; +} +?> +``` + +### Parameters +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} +Name | Type | Description | Notes +------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} +{{#allParams}} **{{paramName}}** | {{#isFile}}**{{dataType}}**{{/isFile}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{^isFile}}[**{{dataType}}**](../Model/{{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}} +{{/allParams}} + +### Return type + +{{#returnType}}{{#returnTypeIsPrimitive}}**{{{returnType}}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{{returnType}}}**](../Model/{{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}void (empty response body){{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{{name}}}](../../README.md#{{{name}}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +[[Back to top]](#) [[Back to API list]](../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../README.md#documentation-for-models) [[Back to README]](../../README.md) + +{{/operation}} +{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/api_test.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/api_test.mustache new file mode 100644 index 0000000000..c1f16c70ce --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/api_test.mustache @@ -0,0 +1,77 @@ +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}} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/autoload.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/autoload.mustache new file mode 100644 index 0000000000..28ce32ae50 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/autoload.mustache @@ -0,0 +1,44 @@ +partial_header}} +/** + * An example of a project-specific implementation. + * + * After registering this autoload function with SPL, the following line + * would cause the function to attempt to load the \{{invokerPackage}}\Baz\Qux class + * from /path/to/project/{{srcBasePath}}/Baz/Qux.php: + * + * new \{{invokerPackage}}\Baz\Qux; + * + * @param string $class The fully-qualified class name. + * + * @return void + */ +spl_autoload_register(function ($class) { + + // project-specific namespace prefix + $prefix = '{{escapedInvokerPackage}}\\'; + + // base directory for the namespace prefix + $base_dir = __DIR__ . '/{{srcBasePath}}/'; + + // does the class use the namespace prefix? + $len = strlen($prefix); + if (strncmp($prefix, $class, $len) !== 0) { + // no, move to the next registered autoloader + return; + } + + // get the relative class name + $relative_class = substr($class, $len); + + // replace the namespace prefix with the base directory, replace namespace + // separators with directory separators in the relative class name, append + // with .php + $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php'; + + // if the file exists, require it + if (file_exists($file)) { + require $file; + } +}); diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/composer.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/composer.mustache new file mode 100644 index 0000000000..eda7618bf6 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/composer.mustache @@ -0,0 +1,37 @@ +{ + "name": "{{#composerVendorName}}{{.}}{{/composerVendorName}}{{^composerVendorName}}{{gitUserId}}{{/composerVendorName}}/{{#composerProjectName}}{{.}}{{/composerProjectName}}{{^composerProjectName}}{{gitRepoId}}{{/composerProjectName}}", + {{#artifactVersion}} + "version": "{{artifactVersion}}", + {{/artifactVersion}} + "description": "{{description}}", + "keywords": [ + "swagger", + "php", + "sdk", + "api" + ], + "homepage": "http://swagger.io", + "license": "proprietary", + "authors": [ + { + "name": "Swagger and contributors", + "homepage": "https://github.com/swagger-api/swagger-codegen" + } + ], + "require": { + "php": ">=5.4", + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "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" + }, + "autoload": { + "psr-4": { "{{escapedInvokerPackage}}\\" : "{{srcBasePath}}/" } + } +} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/git_push.sh.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/git_push.sh.mustache new file mode 100755 index 0000000000..a9b0f28edf --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/git_push.sh.mustache @@ -0,0 +1,52 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 swagger-petstore-perl "minor update" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 + +if [ "$git_user_id" = "" ]; then + git_user_id="{{{gitUserId}}}" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="{{{gitRepoId}}}" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="{{{releaseNote}}}" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +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. +git commit -m "$release_note" + +# Sets the new remote +git_remote=`git remote` +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git crediential in your environment." + git remote add origin https://github.com/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:${GIT_TOKEN}@github.com/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://github.com/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' + diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/model.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/model.mustache new file mode 100644 index 0000000000..52b0934530 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/model.mustache @@ -0,0 +1,41 @@ +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}}; +{{^isEnum}} + +use \ArrayAccess; +{{#useStatements}}use {{this}}; +{{/useStatements}} +{{/isEnum}} + +/** + * Class representing the {{classname}} model. + * +{{#description}} + * {{description}} + * +{{/description}} + * @package {{modelPackage}} + * @author Swagger Codegen team + */ +{{#isEnum}}{{>model_enum}}{{/isEnum}}{{^isEnum}}{{>model_generic}}{{/isEnum}} +{{/model}}{{/models}} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/model_doc.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/model_doc.mustache new file mode 100644 index 0000000000..569550df37 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/model_doc.mustache @@ -0,0 +1,11 @@ +{{#models}}{{#model}}# {{classname}} + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +{{#vars}}**{{name}}** | {{#isPrimitiveType}}**{{datatype}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{datatype}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}} +{{/vars}} + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + +{{/model}}{{/models}} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/model_enum.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/model_enum.mustache new file mode 100644 index 0000000000..5e6b2aea21 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/model_enum.mustache @@ -0,0 +1,19 @@ +class {{classname}} +{ + /** + * Possible values of this enum + */ + {{#allowableValues}}{{#enumVars}}const {{{name}}} = {{{value}}}; + {{/enumVars}}{{/allowableValues}} + /** + * Gets allowable values of the enum + * @return string[] + */ + public static function getAllowableEnumValues() + { + return [ + {{#allowableValues}}{{#enumVars}}self::{{{name}}},{{^-last}} + {{/-last}}{{/enumVars}}{{/allowableValues}} + ]; + } +} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/model_generic.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/model_generic.mustache new file mode 100644 index 0000000000..b00366590c --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/model_generic.mustache @@ -0,0 +1,357 @@ +class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}implements ModelInterface, ArrayAccess +{ + 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}}', '{{{datatype}}}', {{#dataFormat}}'{{{dataFormat}}}'{{/dataFormat}}{{^dataFormat}}null{{/dataFormat}}, '{{setter}}', '{{getter}}'],{{/vars}} + ]; + {{#vars}}{{#isEnum}}{{#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}} + /** + * @var {{{datatype}}}{{^required}}|null{{/required}} + */ + protected ${{name}}; + + {{/vars}} + /** + * Constructor + * @param mixed[] $data Associated array of property values initializing the model + */ + public function __construct(array $data = null) + { + {{#parentSchema}} + parent::__construct($data); + + {{/parentSchema}} + {{#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}} + + /** + * Gets {{name}}. + * @return {{{datatype}}}{{^required}}|null{{/required}} + */ + public function {{getter}}() + { + return $this->{{name}}; + } + + /** + * Sets {{name}}. + * @param {{{datatype}}}{{^required}}|null{{/required}} ${{name}}{{#description}} {{{description}}}{{/description}} + * @return $this + */ + public function {{setter}}({{#vendorExtensions.x-typeAnnotation}}{{vendorExtensions.x-typeAnnotation}} {{/vendorExtensions.x-typeAnnotation}}${{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; + } +} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/model_test.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/model_test.mustache new file mode 100644 index 0000000000..797f9a2af2 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/model_test.mustache @@ -0,0 +1,82 @@ +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 model. + */ + +namespace {{modelTestsPackage}}; + +/** + * {{classname}}Test Class Doc Comment + * + * @category Class */ +// * @description {{#description}}{{description}}{{/description}}{{^description}}{{classname}}{{/description}} +/** + * @package {{modelTestsPackage}} + * @author Swagger Codegen team + * @link https://github.com/swagger-api/swagger-codegen + */ +class {{classname}}Test extends \PHPUnit_Framework_TestCase +{ + + /** + * Setup before running any test case + */ + 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() + { + } + + /** + * Test "{{classname}}" + */ + public function test{{classname}}() + { + } +{{#vars}} + + /** + * Test attribute "{{name}}" + */ + public function testProperty{{nameInCamelCase}}() + { + } +{{/vars}} +} +{{/model}} +{{/models}} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/partial_header.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/partial_header.mustache new file mode 100644 index 0000000000..810c48d312 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/partial_header.mustache @@ -0,0 +1,14 @@ +/** + {{#appName}} + * {{{appName}}} + * + {{/appName}} + {{#appDescription}} + * {{{appDescription}}} + * + {{/appDescription}} + * {{#version}}OpenAPI spec version: {{{version}}}{{/version}} + * {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} + * Generated by: https://github.com/swagger-api/swagger-codegen.git + * + */ diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/phpunit.xml.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/phpunit.xml.mustache new file mode 100644 index 0000000000..5de6fea575 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/phpunit.xml.mustache @@ -0,0 +1,21 @@ + + + + + {{apiTestPath}} + {{modelTestPath}} + + + + + + {{apiSrcPath}} + {{modelSrcPath}} + + + diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/routing.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/routing.mustache new file mode 100644 index 0000000000..e91e9349c0 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/routing.mustache @@ -0,0 +1,19 @@ +# NOTE: This file is auto generated by the swagger code generator program. +# https://github.com/swagger-api/swagger-codegen +# Do not edit the class manually. + +{{#apiInfo}} +{{#apis}} +{{#operations}} +# {{pathPrefix}} +{{#operation}} +{{bundleAlias}}_{{pathPrefix}}_{{operationIdLowerCase}}: + path: {{path}} + methods: [{{httpMethod}}] + defaults: + _controller: {{bundleClassName}}:{{baseName}}:{{operationId}} + +{{/operation}} +{{/operations}} +{{/apis}} +{{/apiInfo}} diff --git a/modules/swagger-codegen/src/main/resources/php-symfony/services.mustache b/modules/swagger-codegen/src/main/resources/php-symfony/services.mustache new file mode 100644 index 0000000000..89e2bb8a96 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php-symfony/services.mustache @@ -0,0 +1,10 @@ +# NOTE: This file is auto generated by the swagger code generator program. +# https://github.com/swagger-api/swagger-codegen +# Do not edit the class manually. + +services: + {{bundleAlias}}.api.api_server: + class: {{apiPackage}}\ApiServer + + {{bundleAlias}}.model.model_serializer: + class: {{modelPackage}}\ModelSerializer