From 4001503e63f7524160f9f252830d4e2bcbbfec57 Mon Sep 17 00:00:00 2001 From: Articus Date: Sun, 15 Jan 2017 21:05:04 +0400 Subject: [PATCH] PHP server generator ze-ph (Zend Expressive + Path Handler) (#4559) * Server generator ze-ph (Zend Expressive + Path Handler) * Command line scripts for new ze-ph generator --- bin/windows/ze-ph-petstore.bat | 10 + bin/ze-ph-petstore-server.sh | 31 +++ ...endExpressivePathHandlerServerCodegen.java | 216 ++++++++++++++++++ .../services/io.swagger.codegen.CodegenConfig | 1 + .../main/resources/ze-ph/Date.php.mustache | 17 ++ .../resources/ze-ph/DateTime.php.mustache | 44 ++++ .../ze-ph/ErrorMiddleware.php.mustache | 20 ++ .../main/resources/ze-ph/README.md.mustache | 10 + .../main/resources/ze-ph/Type.php.mustache | 71 ++++++ .../src/main/resources/ze-ph/api.mustache | 60 +++++ .../src/main/resources/ze-ph/app.yml.mustache | 19 ++ .../resources/ze-ph/composer.json.mustache | 22 ++ .../src/main/resources/ze-ph/config.yml | 2 + .../src/main/resources/ze-ph/container.php | 46 ++++ .../ze-ph/data_transfer.yml.mustache | 28 +++ .../src/main/resources/ze-ph/index.php | 10 + .../src/main/resources/ze-ph/model.mustache | 131 +++++++++++ .../resources/ze-ph/path_handler.yml.mustache | 27 +++ .../src/main/resources/ze-ph/route.mustache | 15 ++ .../petstore/ze-ph/.swagger-codegen-ignore | 23 ++ samples/server/petstore/ze-ph/README.md | 10 + .../petstore/ze-ph/application/config.yml | 2 + .../petstore/ze-ph/application/config/app.yml | 19 ++ .../application/config/data_transfer.yml | 28 +++ .../ze-ph/application/config/path_handler.yml | 131 +++++++++++ .../petstore/ze-ph/application/container.php | 46 ++++ samples/server/petstore/ze-ph/composer.json | 22 ++ .../server/petstore/ze-ph/public/index.php | 10 + .../ze-ph/src/App/DTO/ApiResponse.php | 30 +++ .../petstore/ze-ph/src/App/DTO/Category.php | 24 ++ .../petstore/ze-ph/src/App/DTO/Order.php | 50 ++++ .../server/petstore/ze-ph/src/App/DTO/Pet.php | 55 +++++ .../server/petstore/ze-ph/src/App/DTO/Tag.php | 24 ++ .../petstore/ze-ph/src/App/DTO/User.php | 61 +++++ .../ze-ph/src/App/ErrorMiddleware.php | 20 ++ .../petstore/ze-ph/src/App/Handler/Pet.php | 54 +++++ .../ze-ph/src/App/Handler/PetFindByStatus.php | 29 +++ .../ze-ph/src/App/Handler/PetFindByTags.php | 29 +++ .../ze-ph/src/App/Handler/PetPetId.php | 53 +++++ .../src/App/Handler/PetPetIdUploadImage.php | 27 +++ .../ze-ph/src/App/Handler/StoreInventory.php | 27 +++ .../ze-ph/src/App/Handler/StoreOrder.php | 32 +++ .../src/App/Handler/StoreOrderOrderId.php | 41 ++++ .../petstore/ze-ph/src/App/Handler/User.php | 31 +++ .../src/App/Handler/UserCreateWithArray.php | 31 +++ .../src/App/Handler/UserCreateWithList.php | 31 +++ .../ze-ph/src/App/Handler/UserLogin.php | 29 +++ .../ze-ph/src/App/Handler/UserLogout.php | 28 +++ .../ze-ph/src/App/Handler/UserUsername.php | 56 +++++ .../petstore/ze-ph/src/App/Strategy/Date.php | 17 ++ .../ze-ph/src/App/Strategy/DateTime.php | 44 ++++ .../petstore/ze-ph/src/App/Validator/Type.php | 71 ++++++ 52 files changed, 1965 insertions(+) create mode 100644 bin/windows/ze-ph-petstore.bat create mode 100644 bin/ze-ph-petstore-server.sh create mode 100644 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/ZendExpressivePathHandlerServerCodegen.java create mode 100644 modules/swagger-codegen/src/main/resources/ze-ph/Date.php.mustache create mode 100644 modules/swagger-codegen/src/main/resources/ze-ph/DateTime.php.mustache create mode 100644 modules/swagger-codegen/src/main/resources/ze-ph/ErrorMiddleware.php.mustache create mode 100644 modules/swagger-codegen/src/main/resources/ze-ph/README.md.mustache create mode 100644 modules/swagger-codegen/src/main/resources/ze-ph/Type.php.mustache create mode 100644 modules/swagger-codegen/src/main/resources/ze-ph/api.mustache create mode 100644 modules/swagger-codegen/src/main/resources/ze-ph/app.yml.mustache create mode 100644 modules/swagger-codegen/src/main/resources/ze-ph/composer.json.mustache create mode 100644 modules/swagger-codegen/src/main/resources/ze-ph/config.yml create mode 100644 modules/swagger-codegen/src/main/resources/ze-ph/container.php create mode 100644 modules/swagger-codegen/src/main/resources/ze-ph/data_transfer.yml.mustache create mode 100644 modules/swagger-codegen/src/main/resources/ze-ph/index.php create mode 100644 modules/swagger-codegen/src/main/resources/ze-ph/model.mustache create mode 100644 modules/swagger-codegen/src/main/resources/ze-ph/path_handler.yml.mustache create mode 100644 modules/swagger-codegen/src/main/resources/ze-ph/route.mustache create mode 100644 samples/server/petstore/ze-ph/.swagger-codegen-ignore create mode 100644 samples/server/petstore/ze-ph/README.md create mode 100644 samples/server/petstore/ze-ph/application/config.yml create mode 100644 samples/server/petstore/ze-ph/application/config/app.yml create mode 100644 samples/server/petstore/ze-ph/application/config/data_transfer.yml create mode 100644 samples/server/petstore/ze-ph/application/config/path_handler.yml create mode 100644 samples/server/petstore/ze-ph/application/container.php create mode 100644 samples/server/petstore/ze-ph/composer.json create mode 100644 samples/server/petstore/ze-ph/public/index.php create mode 100644 samples/server/petstore/ze-ph/src/App/DTO/ApiResponse.php create mode 100644 samples/server/petstore/ze-ph/src/App/DTO/Category.php create mode 100644 samples/server/petstore/ze-ph/src/App/DTO/Order.php create mode 100644 samples/server/petstore/ze-ph/src/App/DTO/Pet.php create mode 100644 samples/server/petstore/ze-ph/src/App/DTO/Tag.php create mode 100644 samples/server/petstore/ze-ph/src/App/DTO/User.php create mode 100644 samples/server/petstore/ze-ph/src/App/ErrorMiddleware.php create mode 100644 samples/server/petstore/ze-ph/src/App/Handler/Pet.php create mode 100644 samples/server/petstore/ze-ph/src/App/Handler/PetFindByStatus.php create mode 100644 samples/server/petstore/ze-ph/src/App/Handler/PetFindByTags.php create mode 100644 samples/server/petstore/ze-ph/src/App/Handler/PetPetId.php create mode 100644 samples/server/petstore/ze-ph/src/App/Handler/PetPetIdUploadImage.php create mode 100644 samples/server/petstore/ze-ph/src/App/Handler/StoreInventory.php create mode 100644 samples/server/petstore/ze-ph/src/App/Handler/StoreOrder.php create mode 100644 samples/server/petstore/ze-ph/src/App/Handler/StoreOrderOrderId.php create mode 100644 samples/server/petstore/ze-ph/src/App/Handler/User.php create mode 100644 samples/server/petstore/ze-ph/src/App/Handler/UserCreateWithArray.php create mode 100644 samples/server/petstore/ze-ph/src/App/Handler/UserCreateWithList.php create mode 100644 samples/server/petstore/ze-ph/src/App/Handler/UserLogin.php create mode 100644 samples/server/petstore/ze-ph/src/App/Handler/UserLogout.php create mode 100644 samples/server/petstore/ze-ph/src/App/Handler/UserUsername.php create mode 100644 samples/server/petstore/ze-ph/src/App/Strategy/Date.php create mode 100644 samples/server/petstore/ze-ph/src/App/Strategy/DateTime.php create mode 100644 samples/server/petstore/ze-ph/src/App/Validator/Type.php diff --git a/bin/windows/ze-ph-petstore.bat b/bin/windows/ze-ph-petstore.bat new file mode 100644 index 00000000000..288870edc70 --- /dev/null +++ b/bin/windows/ze-ph-petstore.bat @@ -0,0 +1,10 @@ +set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar + +If Not Exist %executable% ( + mvn clean package +) + +REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M +set ags=generate -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l ze-ph -o samples\client\petstore\ze-ph + +java %JAVA_OPTS% -jar %executable% %ags% diff --git a/bin/ze-ph-petstore-server.sh b/bin/ze-ph-petstore-server.sh new file mode 100644 index 00000000000..9289ed2f55d --- /dev/null +++ b/bin/ze-ph-petstore-server.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +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 + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=`dirname "$SCRIPT"`/.. + APP_DIR=`cd "${APP_DIR}"; pwd` +fi + +executable="./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 modules/swagger-codegen/src/main/resources/ze-ph -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l ze-ph -o samples/server/petstore/ze-ph" + +java $JAVA_OPTS -jar $executable $ags diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/ZendExpressivePathHandlerServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/ZendExpressivePathHandlerServerCodegen.java new file mode 100644 index 00000000000..12328c64d58 --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/ZendExpressivePathHandlerServerCodegen.java @@ -0,0 +1,216 @@ +package io.swagger.codegen.languages; + +import io.swagger.codegen.*; +import io.swagger.models.Operation; +import org.apache.commons.lang3.StringUtils; + + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ZendExpressivePathHandlerServerCodegen extends AbstractPhpCodegen { + @Override + public CodegenType getTag() { + return CodegenType.SERVER; + } + + @Override + public String getName() { + return "ze-ph"; + } + + @Override + public String getHelp() { + return "Generates PHP server stub using Zend Expressive ( https://zendframework.github.io/zend-expressive ) and Path Handler ( https://github.com/Articus/PathHandler )."; + } + + public ZendExpressivePathHandlerServerCodegen() { + super(); + + embeddedTemplateDir = templateDir = "ze-ph"; + invokerPackage = "App"; + packagePath = ""; + srcBasePath = "src" + File.separator + "App"; + apiDirName = "Handler"; + modelDirName = "DTO"; + apiPackage = invokerPackage + "\\" + apiDirName; + modelPackage = invokerPackage + "\\" + modelDirName; + + apiTestTemplateFiles.clear(); + modelTestTemplateFiles.clear(); + apiDocTemplateFiles.clear(); + modelDocTemplateFiles.clear(); + + supportingFiles.add(new SupportingFile("README.md.mustache", packagePath, "README.md")); + supportingFiles.add(new SupportingFile("composer.json.mustache", packagePath, "composer.json")); + supportingFiles.add(new SupportingFile("index.php", packagePath + File.separator + "public", "index.php")); + supportingFiles.add(new SupportingFile("container.php", packagePath + File.separator + "application", "container.php")); + supportingFiles.add(new SupportingFile("config.yml", packagePath + File.separator + "application", "config.yml")); + supportingFiles.add(new SupportingFile("app.yml.mustache", packagePath + File.separator + "application" + File.separator + "config", "app.yml")); + supportingFiles.add(new SupportingFile("path_handler.yml.mustache", packagePath + File.separator + "application" + File.separator + "config", "path_handler.yml")); + supportingFiles.add(new SupportingFile("data_transfer.yml.mustache", packagePath + File.separator + "application" + File.separator + "config", "data_transfer.yml")); + supportingFiles.add(new SupportingFile("Date.php.mustache", packagePath + File.separator + srcBasePath + File.separator + "Strategy", "Date.php")); + supportingFiles.add(new SupportingFile("DateTime.php.mustache", packagePath + File.separator + srcBasePath + File.separator + "Strategy", "DateTime.php")); + supportingFiles.add(new SupportingFile("Type.php.mustache", packagePath + File.separator + srcBasePath + File.separator + "Validator", "Type.php")); + supportingFiles.add(new SupportingFile("ErrorMiddleware.php.mustache", packagePath + File.separator + srcBasePath, "ErrorMiddleware.php")); + + additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, "1.0.0"); + } + + /** + * Add operation to group + * Override of default grouping - group by resource path, not tag + * + * @param tag name of the tag + * @param resourcePath path of the resource + * @param operation Swagger Operation object + * @param co Codegen Operation object + * @param operations map of Codegen operations + */ + @Override + public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map> operations) { + List opList = operations.get(resourcePath); + if (opList == null) { + opList = new ArrayList(); + operations.put(resourcePath, opList); + } + //ignore duplicate operation ids - that means that operation has several tags + int counter = 0; + for (CodegenOperation op : opList) { + if (co.operationId.equals(op.operationId)) { + counter++; + } + } + if (counter == 0) { + co.operationIdLowerCase = co.operationId.toLowerCase(); + opList.add(co); + co.baseName = tag; + } + } + + /** + * Return the file name of the Api Test + * + * @param name the file name of the Api + * @return the file name of the Api + */ + @Override + public String toApiFilename(String name) { + return toApiName(name); + } + + /** + * Output the API (class) name (capitalized) ending with "Api" + * Return DefaultApi if name is empty + * + * @param name the name of the Api + * @return capitalized Api name ending with "Api" + */ + @Override + public String toApiName(String name) { + //Remove } + name = name.replaceAll("[\\}]", ""); + return super.toModelName(name); + } + + @Override + public Map postProcessOperations(Map objs) { + objs = super.postProcessOperations(objs); + Map operations = (Map) objs.get("operations"); + List operationList = (List) operations.get("operation"); + String interfaceToImplement; + StringBuilder interfacesToImplement = new StringBuilder(); + String classMethod; + for (CodegenOperation op : operationList) { + switch (op.httpMethod) { + case "GET": + interfaceToImplement = "Operation\\GetInterface"; + classMethod = "handleGet"; + break; + case "POST": + interfaceToImplement = "Operation\\PostInterface"; + classMethod = "handlePost"; + break; + case "PATCH": + interfaceToImplement = "Operation\\PatchInterface"; + classMethod = "handlePatch"; + break; + case "PUT": + interfaceToImplement = "Operation\\PutInterface"; + classMethod = "handlePut"; + break; + case "DELETE": + interfaceToImplement = "Operation\\DeleteInterface"; + classMethod = "handleDelete"; + break; + default: + throw new RuntimeException("Unknown HTTP Method " + op.httpMethod + " not allowed"); + } + if (interfacesToImplement.length() > 0) { + interfacesToImplement.append(", "); + } + interfacesToImplement.append(interfaceToImplement); + op.httpMethod = classMethod; + } + operations.put("interfacesToImplement", interfacesToImplement.toString()); + + return objs; + } + + @Override + public Map postProcessSupportingFileData(Map objs) { + objs = super.postProcessSupportingFileData(objs); + + Map apiInfo = (Map) objs.get("apiInfo"); + List> apis = (List>) apiInfo.get("apis"); + + List> routes = new ArrayList>(); + for (Map api : apis) { + String handler = (String) api.get("classname"); + String url = (String) api.get("baseName"); + if (url.charAt(0) == '/') { + url = url.substring(1); + } + insertRoute(routes, url.split("/"), 0, handler); + } + + objs.put("routes", routes); + return objs; + } + + private void insertRoute(List> routes, String[] urlParts, int currentUrlPartIndex, String handler) { + if (urlParts.length > currentUrlPartIndex) { + String urlPart = urlParts[currentUrlPartIndex]; + //List> subRoutes = null; + Map currentRoute = null; + for (Map route : routes) { + if (urlPart.equals(route.get("name"))) { + currentRoute = route; + break; + } + } + if (currentRoute == null) { + currentRoute = new HashMap(); + + String routePart = urlPart.replaceAll("^\\{(\\w+)\\}$", ":$1"); + boolean isLastUrlPart = currentUrlPartIndex == urlParts.length - 1; + + currentRoute.put("name", urlPart); + currentRoute.put("route", "/" + routePart); + currentRoute.put("type", (urlPart == routePart) ? "Literal" : "Segment"); + currentRoute.put("handler", isLastUrlPart ? handler : null); + currentRoute.put("hasChildren", false); + currentRoute.put("children", new ArrayList>()); + currentRoute.put("padding", StringUtils.repeat(' ', 4 * currentUrlPartIndex)); + + routes.add(currentRoute); + } + List> subRoutes = (List>) currentRoute.get("children"); + insertRoute(subRoutes, urlParts, currentUrlPartIndex + 1, handler); + currentRoute.put("hasChildren", !subRoutes.isEmpty()); + } + } +} 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 9b36d8c527a..8da47e907a3 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 @@ -59,3 +59,4 @@ io.swagger.codegen.languages.GoServerCodegen io.swagger.codegen.languages.ErlangServerCodegen io.swagger.codegen.languages.UndertowCodegen io.swagger.codegen.languages.JavaMSF4JServerCodegen +io.swagger.codegen.languages.ZendExpressivePathHandlerServerCodegen \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/ze-ph/Date.php.mustache b/modules/swagger-codegen/src/main/resources/ze-ph/Date.php.mustache new file mode 100644 index 00000000000..89bcf5ba0ec --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/ze-ph/Date.php.mustache @@ -0,0 +1,17 @@ +format(static::DATE_TIME_FORMAT); + } + return $result; + } + + /** + * @inheritDoc + */ + public function hydrate($arrayValue, $objectValue, array $array = null) + { + $result = null; + if (!empty($arrayValue)) { + $date = $this->parseDateString($arrayValue); + if ($date instanceof \DateTime) { + $result = $date; + } + } + return $result; + } + + /** + * @param $arrayValue + * @return \DateTime + */ + protected function parseDateString($arrayValue) + { + return \DateTime::createFromFormat(static::DATE_TIME_FORMAT, $arrayValue, new \DateTimeZone('UTC')); + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/ze-ph/ErrorMiddleware.php.mustache b/modules/swagger-codegen/src/main/resources/ze-ph/ErrorMiddleware.php.mustache new file mode 100644 index 00000000000..d9696c081c9 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/ze-ph/ErrorMiddleware.php.mustache @@ -0,0 +1,20 @@ +withStatus(500, 'Internal server error'); + $response->getBody()->write((string)$error); + error_log((string) $error); + return ($out === null)? $response : $out($request, $response); + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/ze-ph/README.md.mustache b/modules/swagger-codegen/src/main/resources/ze-ph/README.md.mustache new file mode 100644 index 00000000000..81eb543af3a --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/ze-ph/README.md.mustache @@ -0,0 +1,10 @@ +# Swagger generated server + +## Overview +This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the +[OpenAPI-Spec](https://github.com/swagger-api/swagger-core/wiki) from a remote server, you can easily generate a server stub. This +is an example of building a PHP server. + +This example uses the [Zend Expressive](https://zendframework.github.io/zend-expressive) micro framework and [Path Handler](https://github.com/Articus/PathHandler) library. To see how to make this your own, please take a look at the template here: + +[TEMPLATES](https://github.com/swagger-api/swagger-codegen/tree/master/modules/swagger-codegen/src/main/resources/ze-ph/) diff --git a/modules/swagger-codegen/src/main/resources/ze-ph/Type.php.mustache b/modules/swagger-codegen/src/main/resources/ze-ph/Type.php.mustache new file mode 100644 index 00000000000..050fbbef54b --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/ze-ph/Type.php.mustache @@ -0,0 +1,71 @@ + 'Invalid type given.', + ]; + + /** + * @var string + */ + protected $type; + + /** + * @return mixed + */ + public function getType() + { + return $this->type; + } + + /** + * @param string $type + * @return self + */ + public function setType($type) + { + $this->type = $type; + return $this; + } + + /** + * @inheritDoc + */ + public function isValid($value) + { + $result = true; + if (!$this->checkType($value)) { + $this->error(self::INVALID); + $result = false; + } + return $result; + } + + protected function checkType($value) + { + switch ($this->type) { + case 'int': + return is_int($value); + case 'bool': + return is_bool($value); + case 'float': + return is_float($value) || is_int($value); + case 'string': + return is_string($value); + default: + throw new \InvalidArgumentException(sprintf('Can not check for type %s.', $this->type)); + } + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/ze-ph/api.mustache b/modules/swagger-codegen/src/main/resources/ze-ph/api.mustache new file mode 100644 index 00000000000..a2463ccfb65 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/ze-ph/api.mustache @@ -0,0 +1,60 @@ +getAttribute("{{paramName}}"); +{{/isPrimitiveType}} +{{/bodyParam}} + throw new PHException\HttpCode(500, "Not implemented"); + } +{{/operation}} +} +{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/ze-ph/app.yml.mustache b/modules/swagger-codegen/src/main/resources/ze-ph/app.yml.mustache new file mode 100644 index 00000000000..1cabd291fd6 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/ze-ph/app.yml.mustache @@ -0,0 +1,19 @@ +dependencies: + invokables: + #Has to add this line because currently router is strict requirement for Zend\Expressive\Application even if only middleware_pipeline is used + Zend\Expressive\Router\RouterInterface: Zend\Expressive\Router\ZendRouter + Zend\Diactoros\Response\EmitterInterface: Zend\Diactoros\Response\SapiStreamEmitter + {{invokerPackage}}\ErrorMiddleware: {{invokerPackage}}\ErrorMiddleware + factories: + Zend\Expressive\Application: Zend\Expressive\Container\ApplicationFactory + Articus\PathHandler\Middleware: Articus\PathHandler\MiddlewareFactory + Articus\DataTransfer\Service: Articus\DataTransfer\ServiceFactory + +middleware_pipeline: + api: + middleware: Articus\PathHandler\Middleware + path: {{basePathWithoutHost}} + error: + middleware: {{invokerPackage}}\ErrorMiddleware + error: true + priority: -10000 diff --git a/modules/swagger-codegen/src/main/resources/ze-ph/composer.json.mustache b/modules/swagger-codegen/src/main/resources/ze-ph/composer.json.mustache new file mode 100644 index 00000000000..df263a37b8e --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/ze-ph/composer.json.mustache @@ -0,0 +1,22 @@ +{ + "name": "{{gitUserId}}/{{gitRepoId}}", + "description": "{{description}}", + "license": "proprietary", + "version": "{{artifactVersion}}", + "type": "project", + "require": { + "php": "^5.6 || ^7.0", + "ext-yaml" : "^1.2 || ^2.0", + "zendframework/zend-expressive": "^1.0", + "zendframework/zend-expressive-router": "1.2.*", + "articus/path-handler": "0.1.*", + "articus/data-transfer": "*", + "zendframework/zend-serializer": "*", + "zendframework/zend-config": "*" + }, + "autoload": { + "psr-4": { + "": "src/" + } + } +} diff --git a/modules/swagger-codegen/src/main/resources/ze-ph/config.yml b/modules/swagger-codegen/src/main/resources/ze-ph/config.yml new file mode 100644 index 00000000000..dce9c534bcd --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/ze-ph/config.yml @@ -0,0 +1,2 @@ +#App +cache_configuration: false diff --git a/modules/swagger-codegen/src/main/resources/ze-ph/container.php b/modules/swagger-codegen/src/main/resources/ze-ph/container.php new file mode 100644 index 00000000000..e70a0663cf3 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/ze-ph/container.php @@ -0,0 +1,46 @@ +setService('config', $config); +$container->setAlias('Config', 'config'); + +return $container; diff --git a/modules/swagger-codegen/src/main/resources/ze-ph/data_transfer.yml.mustache b/modules/swagger-codegen/src/main/resources/ze-ph/data_transfer.yml.mustache new file mode 100644 index 00000000000..8c9fb5bfceb --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/ze-ph/data_transfer.yml.mustache @@ -0,0 +1,28 @@ +data_transfer: + metadata_cache: + adapter: + name: blackhole +# adapter: +# name: filesystem +# options: +# cache_dir: data/cache/data_transfer +# namespace: dt + + strategies: + invokables: + {{invokerPackage}}\Strategy\Date: {{invokerPackage}}\Strategy\Date + {{invokerPackage}}\Strategy\DateTime: {{invokerPackage}}\Strategy\DateTime +# factories: + aliases: + Date: {{invokerPackage}}\Strategy\Date + DateTime: {{invokerPackage}}\Strategy\DateTime + validators: + invokables: + {{invokerPackage}}\Validator\Type: {{invokerPackage}}\Validator\Type + factories: + Articus\DataTransfer\Validator\Dictionary: Articus\DataTransfer\Validator\Factory + Articus\DataTransfer\Validator\Collection: Articus\DataTransfer\Validator\Factory + aliases: + Dictionary: Articus\DataTransfer\Validator\Dictionary + Collection: Articus\DataTransfer\Validator\Collection + Type: {{invokerPackage}}\Validator\Type diff --git a/modules/swagger-codegen/src/main/resources/ze-ph/index.php b/modules/swagger-codegen/src/main/resources/ze-ph/index.php new file mode 100644 index 00000000000..09e8b0233e4 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/ze-ph/index.php @@ -0,0 +1,10 @@ +get(\Zend\Expressive\Application::class); +$app->run(); \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/ze-ph/model.mustache b/modules/swagger-codegen/src/main/resources/ze-ph/model.mustache new file mode 100644 index 00000000000..69201b27e5a --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/ze-ph/model.mustache @@ -0,0 +1,131 @@ +route}}{{/routes}} + default_params: + middleware: '' + metadata_cache: + adapter: + name: blackhole +# adapter: +# name: filesystem +# options: +# cache_dir: data/cache/path_handler +# namespace: ph + + handlers: + invokables: +{{#apiInfo}} +{{#apis}} +{{#operations}} + {{classname}}: {{package}}\{{classname}} +{{/operations}} +{{/apis}} +{{/apiInfo}} +# consumers: +# attributes: +# producers: diff --git a/modules/swagger-codegen/src/main/resources/ze-ph/route.mustache b/modules/swagger-codegen/src/main/resources/ze-ph/route.mustache new file mode 100644 index 00000000000..cfb73260540 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/ze-ph/route.mustache @@ -0,0 +1,15 @@ + {{padding}}'{{name}}': + {{padding}} type: {{type}} + {{padding}} options: + {{padding}} route: {{route}} +{{#handler}} + {{padding}} defaults: + {{padding}} handler: {{handler}} +{{/handler}} +{{#hasChildren}} +{{#handler}} + {{padding}} may_terminate: true +{{/handler}} + {{padding}} child_routes: +{{/hasChildren}} +{{#children}}{{>route}}{{/children}} \ No newline at end of file diff --git a/samples/server/petstore/ze-ph/.swagger-codegen-ignore b/samples/server/petstore/ze-ph/.swagger-codegen-ignore new file mode 100644 index 00000000000..c5fa491b4c5 --- /dev/null +++ b/samples/server/petstore/ze-ph/.swagger-codegen-ignore @@ -0,0 +1,23 @@ +# Swagger Codegen Ignore +# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/server/petstore/ze-ph/README.md b/samples/server/petstore/ze-ph/README.md new file mode 100644 index 00000000000..81eb543af3a --- /dev/null +++ b/samples/server/petstore/ze-ph/README.md @@ -0,0 +1,10 @@ +# Swagger generated server + +## Overview +This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the +[OpenAPI-Spec](https://github.com/swagger-api/swagger-core/wiki) from a remote server, you can easily generate a server stub. This +is an example of building a PHP server. + +This example uses the [Zend Expressive](https://zendframework.github.io/zend-expressive) micro framework and [Path Handler](https://github.com/Articus/PathHandler) library. To see how to make this your own, please take a look at the template here: + +[TEMPLATES](https://github.com/swagger-api/swagger-codegen/tree/master/modules/swagger-codegen/src/main/resources/ze-ph/) diff --git a/samples/server/petstore/ze-ph/application/config.yml b/samples/server/petstore/ze-ph/application/config.yml new file mode 100644 index 00000000000..dce9c534bcd --- /dev/null +++ b/samples/server/petstore/ze-ph/application/config.yml @@ -0,0 +1,2 @@ +#App +cache_configuration: false diff --git a/samples/server/petstore/ze-ph/application/config/app.yml b/samples/server/petstore/ze-ph/application/config/app.yml new file mode 100644 index 00000000000..d91bcd21339 --- /dev/null +++ b/samples/server/petstore/ze-ph/application/config/app.yml @@ -0,0 +1,19 @@ +dependencies: + invokables: + #Has to add this line because currently router is strict requirement for Zend\Expressive\Application even if only middleware_pipeline is used + Zend\Expressive\Router\RouterInterface: Zend\Expressive\Router\ZendRouter + Zend\Diactoros\Response\EmitterInterface: Zend\Diactoros\Response\SapiStreamEmitter + App\ErrorMiddleware: App\ErrorMiddleware + factories: + Zend\Expressive\Application: Zend\Expressive\Container\ApplicationFactory + Articus\PathHandler\Middleware: Articus\PathHandler\MiddlewareFactory + Articus\DataTransfer\Service: Articus\DataTransfer\ServiceFactory + +middleware_pipeline: + api: + middleware: Articus\PathHandler\Middleware + path: /v2 + error: + middleware: App\ErrorMiddleware + error: true + priority: -10000 diff --git a/samples/server/petstore/ze-ph/application/config/data_transfer.yml b/samples/server/petstore/ze-ph/application/config/data_transfer.yml new file mode 100644 index 00000000000..6040af29208 --- /dev/null +++ b/samples/server/petstore/ze-ph/application/config/data_transfer.yml @@ -0,0 +1,28 @@ +data_transfer: + metadata_cache: + adapter: + name: blackhole +# adapter: +# name: filesystem +# options: +# cache_dir: data/cache/data_transfer +# namespace: dt + + strategies: + invokables: + App\Strategy\Date: App\Strategy\Date + App\Strategy\DateTime: App\Strategy\DateTime +# factories: + aliases: + Date: App\Strategy\Date + DateTime: App\Strategy\DateTime + validators: + invokables: + App\Validator\Type: App\Validator\Type + factories: + Articus\DataTransfer\Validator\Dictionary: Articus\DataTransfer\Validator\Factory + Articus\DataTransfer\Validator\Collection: Articus\DataTransfer\Validator\Factory + aliases: + Dictionary: Articus\DataTransfer\Validator\Dictionary + Collection: Articus\DataTransfer\Validator\Collection + Type: App\Validator\Type diff --git a/samples/server/petstore/ze-ph/application/config/path_handler.yml b/samples/server/petstore/ze-ph/application/config/path_handler.yml new file mode 100644 index 00000000000..39048ff6f48 --- /dev/null +++ b/samples/server/petstore/ze-ph/application/config/path_handler.yml @@ -0,0 +1,131 @@ +path_handler: + routes: + routes: + 'pet': + type: Literal + options: + route: /pet + defaults: + handler: Pet + may_terminate: true + child_routes: + 'findByStatus': + type: Literal + options: + route: /findByStatus + defaults: + handler: PetFindByStatus + 'findByTags': + type: Literal + options: + route: /findByTags + defaults: + handler: PetFindByTags + '{petId}': + type: Segment + options: + route: /:petId + defaults: + handler: PetPetId + may_terminate: true + child_routes: + 'uploadImage': + type: Literal + options: + route: /uploadImage + defaults: + handler: PetPetIdUploadImage + 'store': + type: Literal + options: + route: /store + child_routes: + 'inventory': + type: Literal + options: + route: /inventory + defaults: + handler: StoreInventory + 'order': + type: Literal + options: + route: /order + defaults: + handler: StoreOrder + may_terminate: true + child_routes: + '{orderId}': + type: Segment + options: + route: /:orderId + defaults: + handler: StoreOrderOrderId + 'user': + type: Literal + options: + route: /user + defaults: + handler: User + may_terminate: true + child_routes: + 'createWithArray': + type: Literal + options: + route: /createWithArray + defaults: + handler: UserCreateWithArray + 'createWithList': + type: Literal + options: + route: /createWithList + defaults: + handler: UserCreateWithList + 'login': + type: Literal + options: + route: /login + defaults: + handler: UserLogin + 'logout': + type: Literal + options: + route: /logout + defaults: + handler: UserLogout + '{username}': + type: Segment + options: + route: /:username + defaults: + handler: UserUsername + + default_params: + middleware: '' + metadata_cache: + adapter: + name: blackhole +# adapter: +# name: filesystem +# options: +# cache_dir: data/cache/path_handler +# namespace: ph + + handlers: + invokables: + Pet: App\Handler\Pet + PetFindByStatus: App\Handler\PetFindByStatus + PetFindByTags: App\Handler\PetFindByTags + PetPetId: App\Handler\PetPetId + PetPetIdUploadImage: App\Handler\PetPetIdUploadImage + StoreInventory: App\Handler\StoreInventory + StoreOrder: App\Handler\StoreOrder + StoreOrderOrderId: App\Handler\StoreOrderOrderId + User: App\Handler\User + UserCreateWithArray: App\Handler\UserCreateWithArray + UserCreateWithList: App\Handler\UserCreateWithList + UserLogin: App\Handler\UserLogin + UserLogout: App\Handler\UserLogout + UserUsername: App\Handler\UserUsername +# consumers: +# attributes: +# producers: diff --git a/samples/server/petstore/ze-ph/application/container.php b/samples/server/petstore/ze-ph/application/container.php new file mode 100644 index 00000000000..e70a0663cf3 --- /dev/null +++ b/samples/server/petstore/ze-ph/application/container.php @@ -0,0 +1,46 @@ +setService('config', $config); +$container->setAlias('Config', 'config'); + +return $container; diff --git a/samples/server/petstore/ze-ph/composer.json b/samples/server/petstore/ze-ph/composer.json new file mode 100644 index 00000000000..5cad52b27e2 --- /dev/null +++ b/samples/server/petstore/ze-ph/composer.json @@ -0,0 +1,22 @@ +{ + "name": "GIT_USER_ID/GIT_REPO_ID", + "description": "", + "license": "proprietary", + "version": "1.0.0", + "type": "project", + "require": { + "php": "^5.6 || ^7.0", + "ext-yaml" : "^1.2 || ^2.0", + "zendframework/zend-expressive": "^1.0", + "zendframework/zend-expressive-router": "1.2.*", + "articus/path-handler": "0.1.*", + "articus/data-transfer": "*", + "zendframework/zend-serializer": "*", + "zendframework/zend-config": "*" + }, + "autoload": { + "psr-4": { + "": "src/" + } + } +} diff --git a/samples/server/petstore/ze-ph/public/index.php b/samples/server/petstore/ze-ph/public/index.php new file mode 100644 index 00000000000..09e8b0233e4 --- /dev/null +++ b/samples/server/petstore/ze-ph/public/index.php @@ -0,0 +1,10 @@ +get(\Zend\Expressive\Application::class); +$app->run(); \ No newline at end of file diff --git a/samples/server/petstore/ze-ph/src/App/DTO/ApiResponse.php b/samples/server/petstore/ze-ph/src/App/DTO/ApiResponse.php new file mode 100644 index 00000000000..9d978986b06 --- /dev/null +++ b/samples/server/petstore/ze-ph/src/App/DTO/ApiResponse.php @@ -0,0 +1,30 @@ +withStatus(500, 'Internal server error'); + $response->getBody()->write((string)$error); + error_log((string) $error); + return ($out === null)? $response : $out($request, $response); + } +} \ No newline at end of file diff --git a/samples/server/petstore/ze-ph/src/App/Handler/Pet.php b/samples/server/petstore/ze-ph/src/App/Handler/Pet.php new file mode 100644 index 00000000000..035e9b19b83 --- /dev/null +++ b/samples/server/petstore/ze-ph/src/App/Handler/Pet.php @@ -0,0 +1,54 @@ +getAttribute("body"); + throw new PHException\HttpCode(500, "Not implemented"); + } + /** + * Update an existing pet + * TODO check if consumer is valid, if it has correct priority and if it can be moved to class annotation + * @PHA\Consumer(name=PHConsumer\Json::class, mediaType="application/json") + * TODO check if consumer is valid, if it has correct priority and if it can be moved to class annotation + * @PHA\Consumer(name=PHConsumer\Json::class, mediaType="application/xml") + * @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":\App\DTO\Pet::class,"objectAttr":"body"}) + * TODO check if producer is valid, if it has correct priority and if it can be moved to class annotation + * @PHA\Producer(name=PHProducer\Transfer::class, mediaType="application/xml") + * TODO check if producer is valid, if it has correct priority and if it can be moved to class annotation + * @PHA\Producer(name=PHProducer\Transfer::class, mediaType="application/json") + */ + public function handlePut(ServerRequestInterface $request) + { + //TODO implement method + /** @var \App\DTO\Pet $body */ + $body = $request->getAttribute("body"); + throw new PHException\HttpCode(500, "Not implemented"); + } +} diff --git a/samples/server/petstore/ze-ph/src/App/Handler/PetFindByStatus.php b/samples/server/petstore/ze-ph/src/App/Handler/PetFindByStatus.php new file mode 100644 index 00000000000..3c9ae5149cc --- /dev/null +++ b/samples/server/petstore/ze-ph/src/App/Handler/PetFindByStatus.php @@ -0,0 +1,29 @@ +getAttribute("body"); + throw new PHException\HttpCode(500, "Not implemented"); + } +} diff --git a/samples/server/petstore/ze-ph/src/App/Handler/StoreOrderOrderId.php b/samples/server/petstore/ze-ph/src/App/Handler/StoreOrderOrderId.php new file mode 100644 index 00000000000..4bb3c7e8444 --- /dev/null +++ b/samples/server/petstore/ze-ph/src/App/Handler/StoreOrderOrderId.php @@ -0,0 +1,41 @@ +getAttribute("body"); + throw new PHException\HttpCode(500, "Not implemented"); + } +} diff --git a/samples/server/petstore/ze-ph/src/App/Handler/UserCreateWithArray.php b/samples/server/petstore/ze-ph/src/App/Handler/UserCreateWithArray.php new file mode 100644 index 00000000000..cc0f119db3f --- /dev/null +++ b/samples/server/petstore/ze-ph/src/App/Handler/UserCreateWithArray.php @@ -0,0 +1,31 @@ +getAttribute("body"); + throw new PHException\HttpCode(500, "Not implemented"); + } +} diff --git a/samples/server/petstore/ze-ph/src/App/Handler/UserCreateWithList.php b/samples/server/petstore/ze-ph/src/App/Handler/UserCreateWithList.php new file mode 100644 index 00000000000..7cd3e2cc649 --- /dev/null +++ b/samples/server/petstore/ze-ph/src/App/Handler/UserCreateWithList.php @@ -0,0 +1,31 @@ +getAttribute("body"); + throw new PHException\HttpCode(500, "Not implemented"); + } +} diff --git a/samples/server/petstore/ze-ph/src/App/Handler/UserLogin.php b/samples/server/petstore/ze-ph/src/App/Handler/UserLogin.php new file mode 100644 index 00000000000..657218c99e8 --- /dev/null +++ b/samples/server/petstore/ze-ph/src/App/Handler/UserLogin.php @@ -0,0 +1,29 @@ +getAttribute("body"); + throw new PHException\HttpCode(500, "Not implemented"); + } +} diff --git a/samples/server/petstore/ze-ph/src/App/Strategy/Date.php b/samples/server/petstore/ze-ph/src/App/Strategy/Date.php new file mode 100644 index 00000000000..91c83c363a8 --- /dev/null +++ b/samples/server/petstore/ze-ph/src/App/Strategy/Date.php @@ -0,0 +1,17 @@ +format(static::DATE_TIME_FORMAT); + } + return $result; + } + + /** + * @inheritDoc + */ + public function hydrate($arrayValue, $objectValue, array $array = null) + { + $result = null; + if (!empty($arrayValue)) { + $date = $this->parseDateString($arrayValue); + if ($date instanceof \DateTime) { + $result = $date; + } + } + return $result; + } + + /** + * @param $arrayValue + * @return \DateTime + */ + protected function parseDateString($arrayValue) + { + return \DateTime::createFromFormat(static::DATE_TIME_FORMAT, $arrayValue, new \DateTimeZone('UTC')); + } +} \ No newline at end of file diff --git a/samples/server/petstore/ze-ph/src/App/Validator/Type.php b/samples/server/petstore/ze-ph/src/App/Validator/Type.php new file mode 100644 index 00000000000..79644bacf06 --- /dev/null +++ b/samples/server/petstore/ze-ph/src/App/Validator/Type.php @@ -0,0 +1,71 @@ + 'Invalid type given.', + ]; + + /** + * @var string + */ + protected $type; + + /** + * @return mixed + */ + public function getType() + { + return $this->type; + } + + /** + * @param string $type + * @return self + */ + public function setType($type) + { + $this->type = $type; + return $this; + } + + /** + * @inheritDoc + */ + public function isValid($value) + { + $result = true; + if (!$this->checkType($value)) { + $this->error(self::INVALID); + $result = false; + } + return $result; + } + + protected function checkType($value) + { + switch ($this->type) { + case 'int': + return is_int($value); + case 'bool': + return is_bool($value); + case 'float': + return is_float($value) || is_int($value); + case 'string': + return is_string($value); + default: + throw new \InvalidArgumentException(sprintf('Can not check for type %s.', $this->type)); + } + } +} \ No newline at end of file