From 8e78b14e2826eeaa22f233b5b6a320b2a6083343 Mon Sep 17 00:00:00 2001 From: Yuriy Belenko Date: Mon, 21 Oct 2019 19:20:12 +0500 Subject: [PATCH] New PHP Slim4 Server Generator (#3658) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Slim4] Copy Slim3 generator as starting point * [Slim4] Add psr7Implementation generator option Slim supports PSR-7 interfaces for its Request and Response objects. Slim provides its own PSR-7 implementation so that it works out of the box. However, you are free to replace Slim’s default PSR-7 objects with a third-party implementation. [Ref] https://www.slimframework.com/docs/v4/concepts/value-objects.html * [Slim4] Handle psr7Implementation generator option It somehow ended up with composerPackages and composerDevPackages codegen variables and two additional functions. Hope, it's not too much. * [Slim4] Extend from Slim3 generator * [Slim4] Bump PHP Slim Framework version to 4.0.0 * [Slim4] Bump required PHP version to 7.1 [Upgrade Guide](https://www.slimframework.com/docs/v4/start/upgrade.html) * [Slim4] Remove app settings Slim’s App settings used to be a part of the container and they have now been decoupled from it. [Upgrade Guide](https://www.slimframework.com/docs/v4/start/upgrade.html) * [Slim4] Set container argument optional Slim uses an optional dependency container to prepare, manage, and inject application dependencies. Slim supports containers that implement PSR-11 like [PHP-DI](http://php-di.org/doc/frameworks/slim.html). [Upgrade Guide](https://www.slimframework.com/docs/v4/start/upgrade.html) * [Slim4] Change response body write You can't write to response instance directly anymore, need to retrieve body object first. [Doc](https://www.slimframework.com/docs/v4/objects/response.html#the-response-body) * [Slim4] Change Slim\App constructor [Upgrade Guide](https://www.slimframework.com/docs/v4/start/upgrade.html) * [Slim4] Refactor token authentication options User can provide array or Container as constructor argument from now. Small refactoring required to retrieve authentication options from that argument. * [Slim4] Add PSR-7 implementation codegen flags This approach seems more flexible to me. User can customize templates in favor of chosen PSR7 implementation. It's easier to change Composer packages and their versions. * [Slim4] Add JsonBodyParserMiddleware Slim4 doesn't parse JSON body, need to add suggested middleware. Ref: https://www.slimframework.com/docs/v4/objects/request.html#the-request-body * [Slim4] Remove request's deprecated methods usage Since Slim 4.0.0 ServerRequest implementation doesn't have getQueryParam and getParsedBodyParam methods anymore. * [Slim4] Use getUploadedFiles for multipart request isMultipart codegen property is always false so far. Hope that bug will be fixed soon. * [Slim4] Add samples --- bin/openapi3/php-slim4-server-petstore.sh | 32 + bin/php-slim4-server-petstore.sh | 32 + bin/utils/ensure-up-to-date | 1 + bin/windows/php-slim4-server-petstore.bat | 10 + docs/generators.md | 1 + docs/generators/php-slim4.md | 19 + .../languages/PhpSlim4ServerCodegen.java | 143 ++++ .../org.openapitools.codegen.CodegenConfig | 1 + .../resources/php-slim4-server/.gitignore | 17 + .../main/resources/php-slim4-server/.htaccess | 6 + .../php-slim4-server/README.mustache | 189 +++++ .../php-slim4-server/SlimRouter.mustache | 294 +++++++ .../abstract_authenticator.mustache | 117 +++ .../resources/php-slim4-server/api.mustache | 134 +++ .../php-slim4-server/api_test.mustache | 92 +++ .../php-slim4-server/composer.mustache | 52 ++ .../resources/php-slim4-server/index.mustache | 75 ++ .../json_body_parser_middleware.mustache | 74 ++ .../resources/php-slim4-server/model.mustache | 33 + .../php-slim4-server/model_test.mustache | 98 +++ .../php-slim4-server/phpcs.xml.mustache | 31 + .../php-slim4-server/phpunit.xml.mustache | 30 + .../PhpSlim4ServerOptionsProvider.java | 69 ++ .../slim4/PhpSlim4ServerCodegenTest.java | 89 ++ .../slim4/PhpSlim4ServerOptionsTest.java | 66 ++ samples/server/petstore/php-slim4/.gitignore | 17 + samples/server/petstore/php-slim4/.htaccess | 6 + .../php-slim4/.openapi-generator-ignore | 23 + .../php-slim4/.openapi-generator/VERSION | 1 + samples/server/petstore/php-slim4/README.md | 238 ++++++ .../server/petstore/php-slim4/composer.json | 39 + samples/server/petstore/php-slim4/index.php | 74 ++ .../lib/Api/AbstractAnotherFakeApi.php | 80 ++ .../php-slim4/lib/Api/AbstractFakeApi.php | 400 +++++++++ .../Api/AbstractFakeClassnameTags123Api.php | 80 ++ .../php-slim4/lib/Api/AbstractPetApi.php | 267 ++++++ .../php-slim4/lib/Api/AbstractStoreApi.php | 146 ++++ .../php-slim4/lib/Api/AbstractUserApi.php | 232 ++++++ .../lib/Auth/AbstractAuthenticator.php | 108 +++ .../Middleware/JsonBodyParserMiddleware.php | 65 ++ .../lib/Model/AdditionalPropertiesAnyType.php | 30 + .../lib/Model/AdditionalPropertiesArray.php | 30 + .../lib/Model/AdditionalPropertiesBoolean.php | 30 + .../lib/Model/AdditionalPropertiesClass.php | 60 ++ .../lib/Model/AdditionalPropertiesInteger.php | 30 + .../lib/Model/AdditionalPropertiesNumber.php | 30 + .../lib/Model/AdditionalPropertiesObject.php | 30 + .../lib/Model/AdditionalPropertiesString.php | 30 + .../petstore/php-slim4/lib/Model/Animal.php | 33 + .../php-slim4/lib/Model/ApiResponse.php | 36 + .../lib/Model/ArrayOfArrayOfNumberOnly.php | 30 + .../php-slim4/lib/Model/ArrayOfNumberOnly.php | 30 + .../php-slim4/lib/Model/ArrayTest.php | 36 + .../php-slim4/lib/Model/Capitalization.php | 45 ++ .../petstore/php-slim4/lib/Model/Cat.php | 36 + .../petstore/php-slim4/lib/Model/CatAllOf.php | 30 + .../petstore/php-slim4/lib/Model/Category.php | 33 + .../php-slim4/lib/Model/ClassModel.php | 30 + .../petstore/php-slim4/lib/Model/Client.php | 30 + .../petstore/php-slim4/lib/Model/Dog.php | 36 + .../petstore/php-slim4/lib/Model/DogAllOf.php | 30 + .../php-slim4/lib/Model/EnumArrays.php | 33 + .../php-slim4/lib/Model/EnumClass.php | 27 + .../petstore/php-slim4/lib/Model/EnumTest.php | 42 + .../petstore/php-slim4/lib/Model/File.php | 30 + .../lib/Model/FileSchemaTestClass.php | 33 + .../php-slim4/lib/Model/FormatTest.php | 69 ++ .../php-slim4/lib/Model/HasOnlyReadOnly.php | 33 + .../petstore/php-slim4/lib/Model/MapTest.php | 39 + ...PropertiesAndAdditionalPropertiesClass.php | 36 + .../php-slim4/lib/Model/Model200Response.php | 33 + .../php-slim4/lib/Model/ModelList.php | 30 + .../php-slim4/lib/Model/ModelReturn.php | 30 + .../petstore/php-slim4/lib/Model/Name.php | 39 + .../php-slim4/lib/Model/NumberOnly.php | 30 + .../petstore/php-slim4/lib/Model/Order.php | 45 ++ .../php-slim4/lib/Model/OuterComposite.php | 36 + .../php-slim4/lib/Model/OuterEnum.php | 27 + .../petstore/php-slim4/lib/Model/Pet.php | 45 ++ .../php-slim4/lib/Model/ReadOnlyFirst.php | 33 + .../php-slim4/lib/Model/SpecialModelName.php | 30 + .../petstore/php-slim4/lib/Model/Tag.php | 33 + .../php-slim4/lib/Model/TypeHolderDefault.php | 42 + .../php-slim4/lib/Model/TypeHolderExample.php | 45 ++ .../petstore/php-slim4/lib/Model/User.php | 51 ++ .../petstore/php-slim4/lib/Model/XmlItem.php | 114 +++ .../petstore/php-slim4/lib/SlimRouter.php | 761 ++++++++++++++++++ .../server/petstore/php-slim4/phpcs.xml.dist | 31 + .../petstore/php-slim4/phpunit.xml.dist | 30 + .../php-slim4/test/Api/AnotherFakeApiTest.php | 80 ++ .../php-slim4/test/Api/FakeApiTest.php | 223 +++++ .../test/Api/FakeClassnameTags123ApiTest.php | 80 ++ .../php-slim4/test/Api/PetApiTest.php | 168 ++++ .../php-slim4/test/Api/StoreApiTest.php | 113 +++ .../php-slim4/test/Api/UserApiTest.php | 157 ++++ .../Model/AdditionalPropertiesAnyTypeTest.php | 84 ++ .../Model/AdditionalPropertiesArrayTest.php | 84 ++ .../Model/AdditionalPropertiesBooleanTest.php | 84 ++ .../Model/AdditionalPropertiesClassTest.php | 154 ++++ .../Model/AdditionalPropertiesIntegerTest.php | 84 ++ .../Model/AdditionalPropertiesNumberTest.php | 84 ++ .../Model/AdditionalPropertiesObjectTest.php | 84 ++ .../Model/AdditionalPropertiesStringTest.php | 84 ++ .../php-slim4/test/Model/AnimalTest.php | 91 +++ .../php-slim4/test/Model/ApiResponseTest.php | 98 +++ .../Model/ArrayOfArrayOfNumberOnlyTest.php | 84 ++ .../test/Model/ArrayOfNumberOnlyTest.php | 84 ++ .../php-slim4/test/Model/ArrayTestTest.php | 98 +++ .../test/Model/CapitalizationTest.php | 119 +++ .../php-slim4/test/Model/CatAllOfTest.php | 84 ++ .../petstore/php-slim4/test/Model/CatTest.php | 98 +++ .../php-slim4/test/Model/CategoryTest.php | 91 +++ .../php-slim4/test/Model/ClassModelTest.php | 84 ++ .../php-slim4/test/Model/ClientTest.php | 84 ++ .../php-slim4/test/Model/DogAllOfTest.php | 84 ++ .../petstore/php-slim4/test/Model/DogTest.php | 98 +++ .../php-slim4/test/Model/EnumArraysTest.php | 91 +++ .../php-slim4/test/Model/EnumClassTest.php | 77 ++ .../php-slim4/test/Model/EnumTestTest.php | 112 +++ .../test/Model/FileSchemaTestClassTest.php | 91 +++ .../php-slim4/test/Model/FileTest.php | 84 ++ .../php-slim4/test/Model/FormatTestTest.php | 175 ++++ .../test/Model/HasOnlyReadOnlyTest.php | 91 +++ .../php-slim4/test/Model/MapTestTest.php | 105 +++ ...ertiesAndAdditionalPropertiesClassTest.php | 98 +++ .../test/Model/Model200ResponseTest.php | 91 +++ .../php-slim4/test/Model/ModelListTest.php | 84 ++ .../php-slim4/test/Model/ModelReturnTest.php | 84 ++ .../php-slim4/test/Model/NameTest.php | 105 +++ .../php-slim4/test/Model/NumberOnlyTest.php | 84 ++ .../php-slim4/test/Model/OrderTest.php | 119 +++ .../test/Model/OuterCompositeTest.php | 98 +++ .../php-slim4/test/Model/OuterEnumTest.php | 77 ++ .../petstore/php-slim4/test/Model/PetTest.php | 119 +++ .../test/Model/ReadOnlyFirstTest.php | 91 +++ .../test/Model/SpecialModelNameTest.php | 84 ++ .../petstore/php-slim4/test/Model/TagTest.php | 91 +++ .../test/Model/TypeHolderDefaultTest.php | 112 +++ .../test/Model/TypeHolderExampleTest.php | 119 +++ .../php-slim4/test/Model/UserTest.php | 133 +++ .../php-slim4/test/Model/XmlItemTest.php | 280 +++++++ 141 files changed, 11468 insertions(+) create mode 100755 bin/openapi3/php-slim4-server-petstore.sh create mode 100755 bin/php-slim4-server-petstore.sh create mode 100644 bin/windows/php-slim4-server-petstore.bat create mode 100644 docs/generators/php-slim4.md create mode 100644 modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSlim4ServerCodegen.java create mode 100644 modules/openapi-generator/src/main/resources/php-slim4-server/.gitignore create mode 100644 modules/openapi-generator/src/main/resources/php-slim4-server/.htaccess create mode 100644 modules/openapi-generator/src/main/resources/php-slim4-server/README.mustache create mode 100644 modules/openapi-generator/src/main/resources/php-slim4-server/SlimRouter.mustache create mode 100644 modules/openapi-generator/src/main/resources/php-slim4-server/abstract_authenticator.mustache create mode 100644 modules/openapi-generator/src/main/resources/php-slim4-server/api.mustache create mode 100644 modules/openapi-generator/src/main/resources/php-slim4-server/api_test.mustache create mode 100644 modules/openapi-generator/src/main/resources/php-slim4-server/composer.mustache create mode 100644 modules/openapi-generator/src/main/resources/php-slim4-server/index.mustache create mode 100644 modules/openapi-generator/src/main/resources/php-slim4-server/json_body_parser_middleware.mustache create mode 100644 modules/openapi-generator/src/main/resources/php-slim4-server/model.mustache create mode 100644 modules/openapi-generator/src/main/resources/php-slim4-server/model_test.mustache create mode 100644 modules/openapi-generator/src/main/resources/php-slim4-server/phpcs.xml.mustache create mode 100644 modules/openapi-generator/src/main/resources/php-slim4-server/phpunit.xml.mustache create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpSlim4ServerOptionsProvider.java create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/slim4/PhpSlim4ServerCodegenTest.java create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/slim4/PhpSlim4ServerOptionsTest.java create mode 100644 samples/server/petstore/php-slim4/.gitignore create mode 100644 samples/server/petstore/php-slim4/.htaccess create mode 100644 samples/server/petstore/php-slim4/.openapi-generator-ignore create mode 100644 samples/server/petstore/php-slim4/.openapi-generator/VERSION create mode 100644 samples/server/petstore/php-slim4/README.md create mode 100644 samples/server/petstore/php-slim4/composer.json create mode 100644 samples/server/petstore/php-slim4/index.php create mode 100644 samples/server/petstore/php-slim4/lib/Api/AbstractAnotherFakeApi.php create mode 100644 samples/server/petstore/php-slim4/lib/Api/AbstractFakeApi.php create mode 100644 samples/server/petstore/php-slim4/lib/Api/AbstractFakeClassnameTags123Api.php create mode 100644 samples/server/petstore/php-slim4/lib/Api/AbstractPetApi.php create mode 100644 samples/server/petstore/php-slim4/lib/Api/AbstractStoreApi.php create mode 100644 samples/server/petstore/php-slim4/lib/Api/AbstractUserApi.php create mode 100644 samples/server/petstore/php-slim4/lib/Auth/AbstractAuthenticator.php create mode 100644 samples/server/petstore/php-slim4/lib/Middleware/JsonBodyParserMiddleware.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/AdditionalPropertiesAnyType.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/AdditionalPropertiesArray.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/AdditionalPropertiesBoolean.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/AdditionalPropertiesClass.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/AdditionalPropertiesInteger.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/AdditionalPropertiesNumber.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/AdditionalPropertiesObject.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/AdditionalPropertiesString.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/Animal.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/ApiResponse.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/ArrayOfArrayOfNumberOnly.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/ArrayOfNumberOnly.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/ArrayTest.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/Capitalization.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/Cat.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/CatAllOf.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/Category.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/ClassModel.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/Client.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/Dog.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/DogAllOf.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/EnumArrays.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/EnumClass.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/EnumTest.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/File.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/FileSchemaTestClass.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/FormatTest.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/HasOnlyReadOnly.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/MapTest.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/MixedPropertiesAndAdditionalPropertiesClass.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/Model200Response.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/ModelList.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/ModelReturn.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/Name.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/NumberOnly.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/Order.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/OuterComposite.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/OuterEnum.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/Pet.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/ReadOnlyFirst.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/SpecialModelName.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/Tag.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/TypeHolderDefault.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/TypeHolderExample.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/User.php create mode 100644 samples/server/petstore/php-slim4/lib/Model/XmlItem.php create mode 100644 samples/server/petstore/php-slim4/lib/SlimRouter.php create mode 100644 samples/server/petstore/php-slim4/phpcs.xml.dist create mode 100644 samples/server/petstore/php-slim4/phpunit.xml.dist create mode 100644 samples/server/petstore/php-slim4/test/Api/AnotherFakeApiTest.php create mode 100644 samples/server/petstore/php-slim4/test/Api/FakeApiTest.php create mode 100644 samples/server/petstore/php-slim4/test/Api/FakeClassnameTags123ApiTest.php create mode 100644 samples/server/petstore/php-slim4/test/Api/PetApiTest.php create mode 100644 samples/server/petstore/php-slim4/test/Api/StoreApiTest.php create mode 100644 samples/server/petstore/php-slim4/test/Api/UserApiTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/AdditionalPropertiesAnyTypeTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/AdditionalPropertiesArrayTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/AdditionalPropertiesBooleanTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/AdditionalPropertiesClassTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/AdditionalPropertiesIntegerTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/AdditionalPropertiesNumberTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/AdditionalPropertiesObjectTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/AdditionalPropertiesStringTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/AnimalTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/ApiResponseTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/ArrayOfArrayOfNumberOnlyTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/ArrayOfNumberOnlyTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/ArrayTestTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/CapitalizationTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/CatAllOfTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/CatTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/CategoryTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/ClassModelTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/ClientTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/DogAllOfTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/DogTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/EnumArraysTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/EnumClassTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/EnumTestTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/FileSchemaTestClassTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/FileTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/FormatTestTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/HasOnlyReadOnlyTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/MapTestTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/MixedPropertiesAndAdditionalPropertiesClassTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/Model200ResponseTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/ModelListTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/ModelReturnTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/NameTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/NumberOnlyTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/OrderTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/OuterCompositeTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/OuterEnumTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/PetTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/ReadOnlyFirstTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/SpecialModelNameTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/TagTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/TypeHolderDefaultTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/TypeHolderExampleTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/UserTest.php create mode 100644 samples/server/petstore/php-slim4/test/Model/XmlItemTest.php diff --git a/bin/openapi3/php-slim4-server-petstore.sh b/bin/openapi3/php-slim4-server-petstore.sh new file mode 100755 index 000000000000..904c4675b3fa --- /dev/null +++ b/bin/openapi3/php-slim4-server-petstore.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +SCRIPT="$0" +echo "# START SCRIPT: $SCRIPT" + +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/openapi-generator-cli/target/openapi-generator-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} -Xmx1024M -DloggerPath=conf/log4j.properties" +ags="generate -t modules/openapi-generator/src/main/resources/php-slim4-server -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -g php-slim4 -o samples/server/petstore/php-slim4 $@" + +java $JAVA_OPTS -jar $executable $ags diff --git a/bin/php-slim4-server-petstore.sh b/bin/php-slim4-server-petstore.sh new file mode 100755 index 000000000000..a87ebbcc7ac9 --- /dev/null +++ b/bin/php-slim4-server-petstore.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +SCRIPT="$0" +echo "# START SCRIPT: $SCRIPT" + +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/openapi-generator-cli/target/openapi-generator-cli.jar" + +if [ ! -f "$executable" ] +then + mvn -B clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" +ags="generate -t modules/openapi-generator/src/main/resources/php-slim4-server -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g php-slim4 -o samples/server/petstore/php-slim4 $@" + +java $JAVA_OPTS -jar $executable $ags diff --git a/bin/utils/ensure-up-to-date b/bin/utils/ensure-up-to-date index adc1993015f1..4793470bf221 100755 --- a/bin/utils/ensure-up-to-date +++ b/bin/utils/ensure-up-to-date @@ -39,6 +39,7 @@ declare -a scripts=( "./bin/php-symfony-petstore.sh" "./bin/php-lumen-petstore-server.sh" "./bin/php-slim-server-petstore.sh" +"./bin/php-slim4-server-petstore.sh" "./bin/php-ze-ph-petstore-server.sh" "./bin/openapi3/php-petstore.sh" "./bin/typescript-angularjs-petstore.sh" diff --git a/bin/windows/php-slim4-server-petstore.bat b/bin/windows/php-slim4-server-petstore.bat new file mode 100644 index 000000000000..c1ac0ef7325d --- /dev/null +++ b/bin/windows/php-slim4-server-petstore.bat @@ -0,0 +1,10 @@ +set executable=.\modules\openapi-generator-cli\target\openapi-generator-cli.jar + +If Not Exist %executable% ( + mvn clean package +) + +REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M +set ags=generate -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g php-slim4 -o samples\server\petstore\php-slim4 + +java %JAVA_OPTS% -jar %executable% %ags% diff --git a/docs/generators.md b/docs/generators.md index 849200fecb3f..91b859ca707e 100644 --- a/docs/generators.md +++ b/docs/generators.md @@ -104,6 +104,7 @@ The following generators are available: * [php-lumen](generators/php-lumen.md) * [php-silex](generators/php-silex.md) * [php-slim](generators/php-slim.md) +* [php-slim4](generators/php-slim4.md) * [php-symfony](generators/php-symfony.md) * [php-ze-ph](generators/php-ze-ph.md) * [python-aiohttp](generators/python-aiohttp.md) diff --git a/docs/generators/php-slim4.md b/docs/generators/php-slim4.md new file mode 100644 index 000000000000..05307722bbb9 --- /dev/null +++ b/docs/generators/php-slim4.md @@ -0,0 +1,19 @@ +--- +title: Config Options for php-slim4 +sidebar_label: php-slim4 +--- + +| Option | Description | Values | Default | +| ------ | ----------- | ------ | ------- | +|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true| +|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false| +|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| +|modelPackage|package for generated models| |null| +|apiPackage|package for generated api classes| |null| +|variableNamingConvention|naming convention of variable name, e.g. camelCase.| |camelCase| +|invokerPackage|The main namespace to use for all classes. e.g. Yay\Pets| |null| +|packageName|The main package name for classes. e.g. GeneratedPetstore| |null| +|srcBasePath|The directory to serve as source root.| |null| +|artifactVersion|The version to use in the composer package version field. e.g. 1.2.3| |null| +|psr7Implementation|Slim 4 provides its own PSR-7 implementation so that it works out of the box. However, you are free to replace Slim’s default PSR-7 objects with a third-party implementation. Ref: https://www.slimframework.com/docs/v4/concepts/value-objects.html|
**slim-psr7**
Slim PSR-7 Message implementation
**nyholm-psr7**
Nyholm PSR-7 Message implementation
**guzzle-psr7**
Guzzle PSR-7 Message implementation
**zend-diactoros**
Zend Diactoros PSR-7 Message implementation
|slim-psr7| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSlim4ServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSlim4ServerCodegen.java new file mode 100644 index 000000000000..c5d07d07eb25 --- /dev/null +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSlim4ServerCodegen.java @@ -0,0 +1,143 @@ +/* + * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openapitools.codegen.languages; + +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.servers.Server; +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.commons.lang3.StringUtils; +import org.openapitools.codegen.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.*; + +import static org.openapitools.codegen.utils.StringUtils.*; + +public class PhpSlim4ServerCodegen extends PhpSlimServerCodegen { + private static final Logger LOGGER = LoggerFactory.getLogger(PhpSlim4ServerCodegen.class); + + public static final String PSR7_IMPLEMENTATION = "psr7Implementation"; + + protected String psr7Implementation = "slim-psr7"; + protected List> composerPackages = new ArrayList>(); + protected List> composerDevPackages = new ArrayList>(); + + public PhpSlim4ServerCodegen() { + super(); + + outputFolder = "generated-code" + File.separator + "slim4"; + embeddedTemplateDir = templateDir = "php-slim4-server"; + + // override cliOptions from AbstractPhpCodegen + updateOption(AbstractPhpCodegen.VARIABLE_NAMING_CONVENTION, "camelCase"); + + // Slim 4 can use any PSR-7 implementation + // https://www.slimframework.com/docs/v4/concepts/value-objects.html + CliOption psr7Option = new CliOption(PSR7_IMPLEMENTATION, + "Slim 4 provides its own PSR-7 implementation so that it works out of the box. However, you are free to replace Slim’s default PSR-7 objects with a third-party implementation. Ref: https://www.slimframework.com/docs/v4/concepts/value-objects.html"); + + psr7Option.addEnum("slim-psr7", "Slim PSR-7 Message implementation") + .addEnum("nyholm-psr7", "Nyholm PSR-7 Message implementation") + .addEnum("guzzle-psr7", "Guzzle PSR-7 Message implementation") + .addEnum("zend-diactoros", "Zend Diactoros PSR-7 Message implementation") + .setDefault("slim-psr7"); + + cliOptions.add(psr7Option); + } + + @Override + public String getName() { + return "php-slim4"; + } + + @Override + public String getHelp() { + return "Generates a PHP Slim 4 Framework server library."; + } + + @Override + public void processOpts() { + super.processOpts(); + + if (additionalProperties.containsKey(PSR7_IMPLEMENTATION)) { + this.setPsr7Implementation((String) additionalProperties.get(PSR7_IMPLEMENTATION)); + } + + // reset implementation flags + additionalProperties.put("isSlimPsr7", Boolean.FALSE); + additionalProperties.put("isNyholmPsr7", Boolean.FALSE); + additionalProperties.put("isGuzzlePsr7", Boolean.FALSE); + additionalProperties.put("isZendDiactoros", Boolean.FALSE); + + // set specific PSR-7 implementation flag + switch (getPsr7Implementation()) { + case "slim-psr7": + additionalProperties.put("isSlimPsr7", Boolean.TRUE); + break; + case "nyholm-psr7": + additionalProperties.put("isNyholmPsr7", Boolean.TRUE); + break; + case "guzzle-psr7": + additionalProperties.put("isGuzzlePsr7", Boolean.TRUE); + break; + case "zend-diactoros": + additionalProperties.put("isZendDiactoros", Boolean.TRUE); + break; + default: + LOGGER.warn("\"" + getPsr7Implementation() + "\" is invalid \"psr7Implementation\" codegen option. Default \"slim-psr7\" used instead."); + additionalProperties.put("isSlimPsr7", Boolean.TRUE); + } + + // Slim 4 doesn't parse JSON body anymore we need to add suggested middleware + // ref: https://www.slimframework.com/docs/v4/objects/request.html#the-request-body + supportingFiles.add(new SupportingFile("json_body_parser_middleware.mustache", toSrcPath(invokerPackage + "\\Middleware", srcBasePath), "JsonBodyParserMiddleware.php")); + } + + /** + * Set PSR-7 implementation package. + * Ref: https://www.slimframework.com/docs/v4/concepts/value-objects.html + * + * @param psr7Implementation PSR-7 implementation package + */ + public void setPsr7Implementation(String psr7Implementation) { + switch (psr7Implementation) { + case "slim-psr7": + case "nyholm-psr7": + case "guzzle-psr7": + case "zend-diactoros": + this.psr7Implementation = psr7Implementation; + break; + default: + this.psr7Implementation = "slim-psr7"; + LOGGER.warn("\"" + (String) psr7Implementation + "\" is invalid \"psr7Implementation\" argument. Default \"slim-psr7\" used instead."); + } + } + + /** + * Returns PSR-7 implementation package. + * + * @return PSR-7 implementation package + */ + public String getPsr7Implementation() { + return this.psr7Implementation; + } +} diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig index 3313be307ce8..057b3c72e051 100644 --- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig +++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig @@ -76,6 +76,7 @@ org.openapitools.codegen.languages.PhpClientCodegen org.openapitools.codegen.languages.PhpLaravelServerCodegen org.openapitools.codegen.languages.PhpLumenServerCodegen org.openapitools.codegen.languages.PhpSlimServerCodegen +org.openapitools.codegen.languages.PhpSlim4ServerCodegen org.openapitools.codegen.languages.PhpSilexServerCodegen org.openapitools.codegen.languages.PhpSymfonyServerCodegen org.openapitools.codegen.languages.PhpZendExpressivePathHandlerServerCodegen diff --git a/modules/openapi-generator/src/main/resources/php-slim4-server/.gitignore b/modules/openapi-generator/src/main/resources/php-slim4-server/.gitignore new file mode 100644 index 000000000000..db204792ea34 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/php-slim4-server/.gitignore @@ -0,0 +1,17 @@ +# ref: https://github.com/github/gitignore/blob/master/Composer.gitignore + +composer.phar +/vendor/ + +# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control +# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file +# composer.lock + +# phplint tool creates cache file which is not necessary in a codebase +/.phplint-cache + +# Do not commit local PHPUnit config +/phpunit.xml + +# Do not commit local PHP_CodeSniffer config +/phpcs.xml \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/php-slim4-server/.htaccess b/modules/openapi-generator/src/main/resources/php-slim4-server/.htaccess new file mode 100644 index 000000000000..f6a2ceb3952b --- /dev/null +++ b/modules/openapi-generator/src/main/resources/php-slim4-server/.htaccess @@ -0,0 +1,6 @@ + + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^ index.php [QSA,L] + \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/php-slim4-server/README.mustache b/modules/openapi-generator/src/main/resources/php-slim4-server/README.mustache new file mode 100644 index 000000000000..8788d0d4676e --- /dev/null +++ b/modules/openapi-generator/src/main/resources/php-slim4-server/README.mustache @@ -0,0 +1,189 @@ +# {{packageName}} - PHP Slim 4 Server library for {{appName}} + +* [OpenAPI Generator](https://openapi-generator.tech) +* [Slim 4 Documentation](https://www.slimframework.com/docs/v4/) + +{{#isSlimPsr7}} +This server has been generated with [Slim PSR-7](https://github.com/slimphp/Slim-Psr7) implementation. +{{/isSlimPsr7}} +{{#isNyholmPsr7}} +This server has been generated with [Nyholm PSR-7](https://github.com/Nyholm/psr7) implementation and [Nyholm PSR-7 Server](https://github.com/Nyholm/psr7-server). +{{/isNyholmPsr7}} +{{#isGuzzlePsr7}} +This server has been generated with [Guzzle PSR-7](https://github.com/guzzle/psr7) implementation and [Guzzle HTTP Factory](https://github.com/http-interop/http-factory-guzzle). +{{/isGuzzlePsr7}} +{{#isZendDiactoros}} +This server has been generated with [Zend Diactoros](https://github.com/zendframework/zend-diactoros). +{{/isZendDiactoros}} + +## Requirements + +* Web server with URL rewriting +* PHP 7.1 or newer + +This package contains `.htaccess` for Apache configuration. +If you use another server(Nginx, HHVM, IIS, lighttpd) check out [Web Servers](https://www.slimframework.com/docs/v3/start/web-servers.html) doc. + +## Installation via [Composer](https://getcomposer.org/) + +Navigate into your project's root directory and execute the bash command shown below. +This command downloads the Slim Framework and its third-party dependencies into your project's `vendor/` directory. +```bash +$ composer install +``` + +## Start devserver + +Run the following command in terminal to start localhost web server, assuming `./php-slim-server/` is public-accessible directory with `index.php` file: +```bash +$ php -S localhost:8888 -t php-slim-server +``` +> **Warning** This web server was designed to aid application development. +> It may also be useful for testing purposes or for application demonstrations that are run in controlled environments. +> It is not intended to be a full-featured web server. It should not be used on a public network. + +## Tests + +### PHPUnit + +This package uses PHPUnit 6 or 7(depends from your PHP version) for unit testing. +[Test folder]({{testBasePath}}) contains templates which you can fill with real test assertions. +How to write tests read at [PHPUnit Manual - Chapter 2. Writing Tests for PHPUnit](https://phpunit.de/manual/6.5/en/writing-tests-for-phpunit.html). + +#### Run + +Command | Target +---- | ---- +`$ composer test` | All tests +`$ composer test-apis` | Apis tests +`$ composer test-models` | Models tests + +#### Config + +Package contains fully functional config `./phpunit.xml.dist` file. Create `./phpunit.xml` in root folder to override it. + +Quote from [3. The Command-Line Test Runner — PHPUnit 7.4 Manual](https://phpunit.readthedocs.io/en/7.4/textui.html#command-line-options): + +> If phpunit.xml or phpunit.xml.dist (in that order) exist in the current working directory and --configuration is not used, the configuration will be automatically read from that file. + +### PHP CodeSniffer + +[PHP CodeSniffer Documentation](https://github.com/squizlabs/PHP_CodeSniffer/wiki). This tool helps to follow coding style and avoid common PHP coding mistakes. + +#### Run + +```bash +$ composer phpcs +``` + +#### Config + +Package contains fully functional config `./phpcs.xml.dist` file. It checks source code against PSR-1 and PSR-2 coding standards. +Create `./phpcs.xml` in root folder to override it. More info at [Using a Default Configuration File](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Advanced-Usage#using-a-default-configuration-file) + +### PHPLint + +[PHPLint Documentation](https://github.com/overtrue/phplint). Checks PHP syntax only. + +#### Run + +```bash +$ composer phplint +``` + +## Show errors + +Switch on option in `./index.php`: +```diff +/** + * Add Error Handling Middleware + * + * @param bool $displayErrorDetails -> Should be set to false in production + * @param bool $logErrors -> Parameter is passed to the default ErrorHandler + * @param bool $logErrorDetails -> Display error details in error log + * which can be replaced by a callable of your choice. + + * Note: This middleware should be added last. It will not handle any exceptions/errors + * for middleware added after it. + */ +--- $app->addErrorMiddleware(false, true, true); ++++ $app->addErrorMiddleware(true, true, true); +``` + +{{#generateApiDocs}} +## API Endpoints + +All URIs are relative to *{{{basePath}}}* + +> Important! Do not modify abstract API controllers directly! Instead extend them by implementation classes like: + +```php +// src/Api/PetApi.php + +namespace {{apiPackage}}; + +use {{apiPackage}}\AbstractPetApi; + +class PetApi extends AbstractPetApi +{ + + public function addPet($request, $response, $args) + { + // your implementation of addPet method here + } +} +``` + +Place all your implementation classes in `./src` folder accordingly. +For instance, when abstract class located at `./lib/Api/AbstractPetApi.php` you need to create implementation class at `./src/Api/PetApi.php`. + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | **{{operationId}}** | **{{httpMethod}}** {{path}} | {{#summary}}{{{summary}}}{{/summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} +{{/generateApiDocs}} + +{{#generateModelDocs}} +## Models + +{{#modelPackage}} +{{#models}}{{#model}}* {{{modelPackage}}}\{{{classname}}} +{{/model}}{{/models}} +{{/modelPackage}} +{{^modelPackage}} +No model defined in this package +{{/modelPackage}} +{{/generateModelDocs}} + +{{#hasAuthMethods}} +{{#authMethods}} +{{^hasMore}} +## Authentication + +{{/hasMore}} +{{/authMethods}} +{{#authMethods}} +{{#isBasic}} +### Security schema `{{name}}` +> Important! To make Basic authentication work you need to extend [\{{authPackage}}\{{abstractNamePrefix}}Authenticator{{abstractNameSuffix}}]({{authSrcPath}}/{{abstractNamePrefix}}Authenticator{{abstractNameSuffix}}.php) class by [\{{authPackage}}\BasicAuthenticator](./src/Auth/BasicAuthenticator.php) class. + +{{/isBasic}} +{{#isApiKey}} +### Security schema `{{name}}` +> Important! To make ApiKey authentication work you need to extend [\{{authPackage}}\{{abstractNamePrefix}}Authenticator{{abstractNameSuffix}}]({{authSrcPath}}/{{abstractNamePrefix}}Authenticator{{abstractNameSuffix}}.php) class by [\{{authPackage}}\ApiKeyAuthenticator](./src/Auth/ApiKeyAuthenticator.php) class. + +{{/isApiKey}} +{{#isOAuth}} +### Security schema `{{name}}` +> Important! To make OAuth authentication work you need to extend [\{{authPackage}}\{{abstractNamePrefix}}Authenticator{{abstractNameSuffix}}]({{authSrcPath}}/{{abstractNamePrefix}}Authenticator{{abstractNameSuffix}}.php) class by [\{{authPackage}}\OAuthAuthenticator](./src/Auth/OAuthAuthenticator.php) class. + +Scope list: +{{#scopes}} +* `{{scope}}`{{#description}} - {{description}}{{/description}} +{{/scopes}} + +{{/isOAuth}} +{{/authMethods}} +### Advanced middleware configuration +Ref to used Slim Token Middleware [dyorg/slim-token-authentication](https://github.com/dyorg/slim-token-authentication/tree/1.x#readme) +{{/hasAuthMethods}} diff --git a/modules/openapi-generator/src/main/resources/php-slim4-server/SlimRouter.mustache b/modules/openapi-generator/src/main/resources/php-slim4-server/SlimRouter.mustache new file mode 100644 index 000000000000..d7ddf7b23847 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/php-slim4-server/SlimRouter.mustache @@ -0,0 +1,294 @@ + '{{httpMethod}}', + 'basePathWithoutHost' => '{{{basePathWithoutHost}}}', + 'path' => '{{{path}}}', + 'apiPackage' => '{{apiPackage}}', + 'classname' => '{{classname}}', + 'userClassname' => '{{userClassname}}', + 'operationId' => '{{operationId}}', + 'authMethods' => [ + {{#hasAuthMethods}} + {{#authMethods}} + // {{type}} security schema named '{{name}}' + {{#isBasicBasic}} + [ + 'type' => '{{type}}', + 'isBasic' => true, + 'isBearer' => false, + 'isApiKey' => false, + 'isOAuth' => false, + ], + {{/isBasicBasic}} + {{#isBasicBearer}} + [ + 'type' => '{{type}}', + 'isBasic' => true, + 'isBearer' => true, + 'isApiKey' => false, + 'isOAuth' => false, + ], + {{/isBasicBearer}} + {{#isApiKey}} + [ + 'type' => '{{type}}', + 'isBasic' => false, + 'isBearer' => false, + 'isApiKey' => true, + 'isOAuth' => false, + 'keyParamName' => '{{keyParamName}}', + 'isKeyInHeader' => {{#isKeyInHeader}}true{{/isKeyInHeader}}{{^isKeyInHeader}}false{{/isKeyInHeader}}, + 'isKeyInQuery' => {{#isKeyInQuery}}true{{/isKeyInQuery}}{{^isKeyInQuery}}false{{/isKeyInQuery}}, + 'isKeyInCookie' => {{#isKeyInCookie}}true{{/isKeyInCookie}}{{^isKeyInCookie}}false{{/isKeyInCookie}}, + ], + {{/isApiKey}} + {{#isOAuth}} + [ + 'type' => '{{type}}', + 'isBasic' => false, + 'isBearer' => false, + 'isApiKey' => false, + 'isOAuth' => true, + 'scopes' => [ + {{#scopes}} + '{{scope}}',{{#description}} // {{description}}{{/description}} + {{/scopes}} + ], + ], + {{/isOAuth}} + {{/authMethods}} + {{/hasAuthMethods}} + ], + ], + {{/operation}} + {{/operations}} + {{/apis}} + ]; + + /** + * Class constructor + * + * @param ContainerInterface|array $settings Either a ContainerInterface or an associative array of app settings + * + * @throws Exception When implementation class doesn't exists + */ + public function __construct($settings = []) + { + if ($settings instanceof ContainerInterface) { + // Set container to create App with on AppFactory + AppFactory::setContainer($settings); + } + $this->slimApp = AppFactory::create(); + + // middlewares requires Psr\Container\ContainerInterface + $container = $this->slimApp->getContainer(); + + {{#hasAuthMethods}} + $authPackage = '{{authPackage}}'; + $basicAuthenticator = function (ServerRequestInterface &$request, TokenSearch $tokenSearch) use ($authPackage) { + $message = "How about extending {{abstractNamePrefix}}Authenticator{{abstractNameSuffix}} class by {$authPackage}\BasicAuthenticator?"; + throw new Exception($message); + }; + $apiKeyAuthenticator = function (ServerRequestInterface &$request, TokenSearch $tokenSearch) use ($authPackage) { + $message = "How about extending {{abstractNamePrefix}}Authenticator{{abstractNameSuffix}} class by {$authPackage}\ApiKeyAuthenticator?"; + throw new Exception($message); + }; + $oAuthAuthenticator = function (ServerRequestInterface &$request, TokenSearch $tokenSearch) use ($authPackage) { + $message = "How about extending {{abstractNamePrefix}}Authenticator{{abstractNameSuffix}} class by {$authPackage}\OAuthAuthenticator?"; + throw new Exception($message); + }; + {{/hasAuthMethods}} + + $userOptions = null; + if ($settings instanceof ContainerInterface && $settings->has('tokenAuthenticationOptions')) { + $userOptions = $settings->get('tokenAuthenticationOptions'); + } elseif (is_array($settings) && isset($settings['tokenAuthenticationOptions'])) { + $userOptions = $settings['tokenAuthenticationOptions']; + } + + foreach ($this->operations as $operation) { + $callback = function ($request, $response, $arguments) use ($operation) { + $message = "How about extending {$operation['classname']} by {$operation['apiPackage']}\\{$operation['userClassname']} class implementing {$operation['operationId']} as a {$operation['httpMethod']} method?"; + throw new Exception($message); + $response->getBody()->write($message); + return $response->withStatus(501); + }; + $middlewares = [new JsonBodyParserMiddleware()]; + + if (class_exists("\\{$operation['apiPackage']}\\{$operation['userClassname']}")) { + $callback = "\\{$operation['apiPackage']}\\{$operation['userClassname']}:{$operation['operationId']}"; + } + + {{#hasAuthMethods}} + foreach ($operation['authMethods'] as $authMethod) { + switch ($authMethod['type']) { + case 'http': + $authenticatorClassname = "\\{$authPackage}\\BasicAuthenticator"; + if (class_exists($authenticatorClassname)) { + $basicAuthenticator = new $authenticatorClassname($container); + } + + $middlewares[] = new TokenAuthentication($this->getTokenAuthenticationOptions([ + 'authenticator' => $basicAuthenticator, + 'regex' => $authMethod['isBearer'] ? '/Bearer\s+(.*)$/i' : '/Basic\s+(.*)$/i', + 'header' => 'Authorization', + 'parameter' => null, + 'cookie' => null, + 'argument' => null, + ], $userOptions)); + break; + case 'apiKey': + $authenticatorClassname = "\\{$authPackage}\\ApiKeyAuthenticator"; + if (class_exists($authenticatorClassname)) { + $apiKeyAuthenticator = new $authenticatorClassname($container); + } + + $middlewares[] = new TokenAuthentication($this->getTokenAuthenticationOptions([ + 'authenticator' => $apiKeyAuthenticator, + 'regex' => '/^(.*)$/i', + 'header' => $authMethod['isKeyInHeader'] ? $authMethod['keyParamName'] : null, + 'parameter' => $authMethod['isKeyInQuery'] ? $authMethod['keyParamName'] : null, + 'cookie' => $authMethod['isKeyInCookie'] ? $authMethod['keyParamName'] : null, + 'argument' => null, + ], $userOptions)); + break; + case 'oauth2': + $authenticatorClassname = "\\{$authPackage}\\OAuthAuthenticator"; + if (class_exists($authenticatorClassname)) { + $oAuthAuthenticator = new $authenticatorClassname($container, $authMethod['scopes']); + } + + $middlewares[] = new TokenAuthentication($this->getTokenAuthenticationOptions([ + 'authenticator' => $oAuthAuthenticator, + 'regex' => '/Bearer\s+(.*)$/i', + 'header' => 'Authorization', + 'parameter' => null, + 'cookie' => null, + 'argument' => null, + ], $userOptions)); + break; + default: + throw new Exception('Unknown authorization schema type'); + } + } + {{/hasAuthMethods}} + + $this->addRoute( + [$operation['httpMethod']], + "{$operation['basePathWithoutHost']}{$operation['path']}", + $callback, + $middlewares + )->setName($operation['operationId']); + } + } + + /** + * Merges user defined options with dynamic params + * + * @param array $staticOptions Required static options + * @param array $userOptions User options + * + * @return array Merged array + */ + private function getTokenAuthenticationOptions(array $staticOptions, array $userOptions = null) + { + if (is_array($userOptions) === false) { + return $staticOptions; + } + + return array_merge($userOptions, $staticOptions); + } + + /** + * Add route with multiple methods + * + * @param string[] $methods Numeric array of HTTP method names + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * @param array|null $middlewares List of middlewares + * + * @return RouteInterface + * + * @throws InvalidArgumentException If the route pattern isn't a string + */ + public function addRoute(array $methods, string $pattern, $callable, $middlewares = []) + { + $route = $this->slimApp->map($methods, $pattern, $callable); + foreach ($middlewares as $middleware) { + $route->add($middleware); + } + return $route; + } + + /** + * Returns Slim Framework instance + * + * @return App + */ + public function getSlimApp() + { + return $this->slimApp; + } +} +{{/apiInfo}} diff --git a/modules/openapi-generator/src/main/resources/php-slim4-server/abstract_authenticator.mustache b/modules/openapi-generator/src/main/resources/php-slim4-server/abstract_authenticator.mustache new file mode 100644 index 000000000000..fc6f69f2ebca --- /dev/null +++ b/modules/openapi-generator/src/main/resources/php-slim4-server/abstract_authenticator.mustache @@ -0,0 +1,117 @@ +container = $container; + $this->requiredScope = $requiredScope; + } + + /** + * Makes the api key validation of your application + * + * Just an example of implementation. Override this method to fit your needs + * + * @param ServerRequestInterface $request HTTP request + * @param TokenSearch $tokenSearch Middleware instance which contains api key in token + * + * @return bool Must return either true or false + * @throws UnauthorizedExceptionInterface when cannot parse token + */ + public function __invoke(ServerRequestInterface &$request, TokenSearch $tokenSearch) + { + /** + * Try find authorization token via header, parameters, cookie or attribute + * If token not found, return response with status 401 (unauthorized) + */ + $token = $tokenSearch->getToken($request); + + /** + * Verify if token is valid on database + * If token isn't valid, expired or has insufficient scope must throw an UnauthorizedExceptionInterface + */ + $user = $this->getUserByToken($token); + + /** + * Set authenticated user at attributes + */ + $request = $request->withAttribute('authenticated_user', $user); + + return true; + } +} +{{/apiInfo}} diff --git a/modules/openapi-generator/src/main/resources/php-slim4-server/api.mustache b/modules/openapi-generator/src/main/resources/php-slim4-server/api.mustache new file mode 100644 index 000000000000..3ed8ca75ed0c --- /dev/null +++ b/modules/openapi-generator/src/main/resources/php-slim4-server/api.mustache @@ -0,0 +1,134 @@ +container = $container; + } + + {{#operations}} + {{#operation}} + + /** + * {{httpMethod}} {{operationId}} + {{#summary}} + * Summary: {{summary}} + {{/summary}} + {{#notes}} + * Notes: {{notes}} + {{/notes}} + {{#hasProduces}} + * Output-Formats: [{{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}] + {{/hasProduces}} + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function {{operationId}}(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + {{#hasHeaderParams}} + $headers = $request->getHeaders(); + {{#headerParams}} + ${{paramName}} = $request->hasHeader('{{baseName}}') ? $headers['{{baseName}}'] : null; + {{/headerParams}} + {{/hasHeaderParams}} + {{#hasPathParams}} + {{#pathParams}} + ${{paramName}} = $args['{{baseName}}']; + {{/pathParams}} + {{/hasPathParams}} + {{#hasQueryParams}} + $queryParams = $request->getQueryParams(); + {{#queryParams}} + ${{paramName}} = (key_exists('{{baseName}}', $queryParams)) ? $queryParams['{{baseName}}'] : null; + {{/queryParams}} + {{/hasQueryParams}} + {{#hasFormParams}} + $body = $request->getParsedBody(); + {{#formParams}} + {{^isFile}} + ${{paramName}} = (isset($body['{{baseName}}'])) ? $body['{{baseName}}'] : null; + {{/isFile}} + {{#isFile}} + {{#isMultipart}} + ${{paramName}} = (key_exists('{{baseName}}', $request->getUploadedFiles())) ? $request->getUploadedFiles()['{{baseName}}'] : null; + {{/isMultipart}} + {{^isMultipart}} + ${{paramName}} = (isset($body['{{baseName}}'])) ? $body['{{baseName}}'] : null; + {{/isMultipart}} + {{/isFile}} + {{/formParams}} + {{/hasFormParams}} + {{#hasBodyParam}} + $body = $request->getParsedBody(); + {{/hasBodyParam}} + $message = "How about implementing {{nickname}} as a {{httpMethod}} method in {{apiPackage}}\{{userClassname}} class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + {{/operation}} + {{/operations}} +} diff --git a/modules/openapi-generator/src/main/resources/php-slim4-server/api_test.mustache b/modules/openapi-generator/src/main/resources/php-slim4-server/api_test.mustache new file mode 100644 index 000000000000..8fdc30affbf2 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/php-slim4-server/api_test.mustache @@ -0,0 +1,92 @@ + true, + + /** + * Alternatively you can list your development host to have relaxed security. + * Default: ['localhost', '127.0.0.1'] + */ + // 'relaxed' => ['localhost', '127.0.0.1'], + + /** + * By default on ocurred a fail on authentication, is sent a response on json format with a + * message (`Invalid Token` or `Not found Token`) and with the token (if found), with status + * `401 Unauthorized`. You can customize it by setting a callable function on error option. + * Default: null + */ + // 'error' => null, +]; + +$router = new SlimRouter($config); +$app = $router->getSlimApp(); + +/** + * The routing middleware should be added before the ErrorMiddleware + * Otherwise exceptions thrown from it will not be handled + */ +$app->addRoutingMiddleware(); + +/** + * Add Error Handling Middleware + * + * @param bool $displayErrorDetails -> Should be set to false in production + * @param bool $logErrors -> Parameter is passed to the default ErrorHandler + * @param bool $logErrorDetails -> Display error details in error log + * which can be replaced by a callable of your choice. + + * Note: This middleware should be added last. It will not handle any exceptions/errors + * for middleware added after it. + */ +$app->addErrorMiddleware(false, true, true); + +$app->run(); diff --git a/modules/openapi-generator/src/main/resources/php-slim4-server/json_body_parser_middleware.mustache b/modules/openapi-generator/src/main/resources/php-slim4-server/json_body_parser_middleware.mustache new file mode 100644 index 000000000000..276dd864d8df --- /dev/null +++ b/modules/openapi-generator/src/main/resources/php-slim4-server/json_body_parser_middleware.mustache @@ -0,0 +1,74 @@ +getHeaderLine('Content-Type'); + + if (strstr($contentType, 'application/json')) { + $contents = json_decode(file_get_contents('php://input'), true); + if (json_last_error() === JSON_ERROR_NONE) { + $request = $request->withParsedBody($contents); + } + } + + return $handler->handle($request); + } +} +{{/apiInfo}} diff --git a/modules/openapi-generator/src/main/resources/php-slim4-server/model.mustache b/modules/openapi-generator/src/main/resources/php-slim4-server/model.mustache new file mode 100644 index 000000000000..e1b4f5119ea3 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/php-slim4-server/model.mustache @@ -0,0 +1,33 @@ + + + PHP_CodeSniffer config for {{appName}} + + + ./ + + + ./vendor + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/php-slim4-server/phpunit.xml.mustache b/modules/openapi-generator/src/main/resources/php-slim4-server/phpunit.xml.mustache new file mode 100644 index 000000000000..b8852944a12d --- /dev/null +++ b/modules/openapi-generator/src/main/resources/php-slim4-server/phpunit.xml.mustache @@ -0,0 +1,30 @@ + + + + + {{apiTestPath}} + + + {{modelTestPath}} + + + + + {{apiSrcPath}} + {{modelSrcPath}} + + + + + + diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpSlim4ServerOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpSlim4ServerOptionsProvider.java new file mode 100644 index 000000000000..23de2476689b --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpSlim4ServerOptionsProvider.java @@ -0,0 +1,69 @@ +/* + * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * Copyright 2018 SmartBear Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openapitools.codegen.options; + +import com.google.common.collect.ImmutableMap; +import org.openapitools.codegen.CodegenConstants; +import org.openapitools.codegen.languages.AbstractPhpCodegen; +import org.openapitools.codegen.languages.PhpSlim4ServerCodegen; + +import java.util.Map; + +public class PhpSlim4ServerOptionsProvider implements OptionsProvider { + public static final String MODEL_PACKAGE_VALUE = "package"; + public static final String API_PACKAGE_VALUE = "apiPackage"; + public static final String VARIABLE_NAMING_CONVENTION_VALUE = "camelCase"; + public static final String INVOKER_PACKAGE_VALUE = "OpenAPIServer"; + public static final String PACKAGE_NAME_VALUE = ""; + public static final String SRC_BASE_PATH_VALUE = "src"; + public static final String ARTIFACT_VERSION_VALUE = "1.0.0"; + public static final String SORT_PARAMS_VALUE = "false"; + public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true"; + public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false"; + public static final String PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = "true"; + public static final String PSR7_IMPLEMENTATION_VALUE = "zend-diactoros"; + + @Override + public String getLanguage() { + return "php-slim4"; + } + + @Override + public Map createOptions() { + ImmutableMap.Builder builder = new ImmutableMap.Builder(); + return builder.put(CodegenConstants.MODEL_PACKAGE, MODEL_PACKAGE_VALUE) + .put(AbstractPhpCodegen.VARIABLE_NAMING_CONVENTION, VARIABLE_NAMING_CONVENTION_VALUE) + .put(AbstractPhpCodegen.PACKAGE_NAME, PACKAGE_NAME_VALUE) + .put(AbstractPhpCodegen.SRC_BASE_PATH, SRC_BASE_PATH_VALUE) + .put(CodegenConstants.API_PACKAGE, API_PACKAGE_VALUE) + .put(CodegenConstants.INVOKER_PACKAGE, INVOKER_PACKAGE_VALUE) + .put(CodegenConstants.ARTIFACT_VERSION, ARTIFACT_VERSION_VALUE) + .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) + .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) + .put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE) + .put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, PREPEND_FORM_OR_BODY_PARAMETERS_VALUE) + .put(PhpSlim4ServerCodegen.PSR7_IMPLEMENTATION, PSR7_IMPLEMENTATION_VALUE) + .build(); + } + + @Override + public boolean isServer() { + return true; + } +} + diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/slim4/PhpSlim4ServerCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/slim4/PhpSlim4ServerCodegenTest.java new file mode 100644 index 000000000000..820ed851c01c --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/slim4/PhpSlim4ServerCodegenTest.java @@ -0,0 +1,89 @@ +/* + * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openapitools.codegen.slim4; + +import org.openapitools.codegen.languages.PhpSlim4ServerCodegen; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.File; + +public class PhpSlim4ServerCodegenTest { + + @Test + public void testEncodePath() { + final PhpSlim4ServerCodegen codegen = new PhpSlim4ServerCodegen(); + + Assert.assertEquals(codegen.encodePath("/ ' \" =end -- \\r\\n \\n \\r/v2 *_/ ' \" =end -- \\r\\n \\n \\r/fake"), "/%20%27%20%22%20%3Dend%20--%20%5C%5Cr%5C%5Cn%20%5C%5Cn%20%5C%5Cr/v2%20*_/%20%27%20%22%20%3Dend%20--%20%5C%5Cr%5C%5Cn%20%5C%5Cn%20%5C%5Cr/fake"); + Assert.assertEquals(codegen.encodePath("/o\'\"briens/v2/o\'\"henry/fake"), "/o%27%22briens/v2/o%27%22henry/fake"); + Assert.assertEquals(codegen.encodePath("/comedians/Chris D\'Elia"), "/comedians/Chris%20D%27Elia"); + Assert.assertEquals(codegen.encodePath("/разработчики/Юрий Беленко"), "/%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D0%B8/%D0%AE%D1%80%D0%B8%D0%B9%20%D0%91%D0%B5%D0%BB%D0%B5%D0%BD%D0%BA%D0%BE"); + Assert.assertEquals(codegen.encodePath("/text with multilines \\\n\\\t\\\r"), "/text%20with%20multilines%20%5C%5C%20%5C%5C%20%5C%5C"); + Assert.assertEquals(codegen.encodePath("/path with argument {value}"), "/path%20with%20argument%20{value}"); + + // few examples from Slim documentation + Assert.assertEquals(codegen.encodePath("/users[/{id}]"), "/users[/{id}]"); + Assert.assertEquals(codegen.encodePath("/news[/{year}[/{month}]]"), "/news[/{year}[/{month}]]"); + Assert.assertEquals(codegen.encodePath("/news[/{params:.*}]"), "/news[/{params:.*}]"); + Assert.assertEquals(codegen.encodePath("/users/{id:[0-9]+}"), "/users/{id:[0-9]+}"); + + // from FastRoute\RouteParser\Std.php + Assert.assertEquals(codegen.encodePath("/user/{name}[/{id:[0-9]+}]"), "/user/{name}[/{id:[0-9]+}]"); + Assert.assertEquals(codegen.encodePath("/fixedRoutePart/{varName}[/moreFixed/{varName2:\\d+}]"), "/fixedRoutePart/{varName}[/moreFixed/{varName2:\\d+}]"); + } + + @Test(dataProvider = "modelFileFolderProvider") + public void modelFileFolder(String modelPackage, String invokerPackage, String expected) { + final PhpSlim4ServerCodegen codegen = new PhpSlim4ServerCodegen(); + codegen.setModelPackage(modelPackage); + codegen.setInvokerPackage(invokerPackage); + + Assert.assertEquals(codegen.modelFileFolder(), expected); + } + + @DataProvider(name = "modelFileFolderProvider") + public Object[][] modelFileFolderProvider() { + return new Object[][] { + // {modelPackage, invokerPackage, expected} + {"Model", "Invoker", "generated-code/slim4/lib/Model".replace('/', File.separatorChar)}, + {"Petstore", "Petstore", "generated-code/slim4/lib".replace('/', File.separatorChar)}, + {"Package\\SubPackage\\Model", "Package\\SubPackage", "generated-code/slim4/lib/Model".replace('/', File.separatorChar)}, + {"Websupport\\InvoiceValidation\\Model", "Websupport\\InvoiceValidation", "generated-code/slim4/lib/Model".replace('/', File.separatorChar)}, + }; + } + + @Test(dataProvider = "apiFileFolderProvider") + public void apiFileFolder(String modelPackage, String invokerPackage, String expected) { + final PhpSlim4ServerCodegen codegen = new PhpSlim4ServerCodegen(); + codegen.setApiPackage(modelPackage); + codegen.setInvokerPackage(invokerPackage); + + Assert.assertEquals(codegen.apiFileFolder(), expected); + } + + @DataProvider(name = "apiFileFolderProvider") + public Object[][] apiFileFolderProvider() { + return new Object[][] { + // {apiPackage, invokerPackage, expected} + {"Api", "Invoker", "generated-code/slim4/lib/Api".replace('/', File.separatorChar)}, + {"Petstore", "Petstore", "generated-code/slim4/lib".replace('/', File.separatorChar)}, + {"Package\\SubPackage\\Api", "Package\\SubPackage", "generated-code/slim4/lib/Api".replace('/', File.separatorChar)}, + {"Websupport\\InvoiceValidation\\Api", "Websupport\\InvoiceValidation", "generated-code/slim4/lib/Api".replace('/', File.separatorChar)}, + }; + } +} diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/slim4/PhpSlim4ServerOptionsTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/slim4/PhpSlim4ServerOptionsTest.java new file mode 100644 index 000000000000..fa45cb6fbcdc --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/slim4/PhpSlim4ServerOptionsTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * Copyright 2018 SmartBear Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openapitools.codegen.slim4; + +import mockit.Expectations; +import mockit.Tested; +import org.openapitools.codegen.AbstractOptionsTest; +import org.openapitools.codegen.CodegenConfig; +import org.openapitools.codegen.languages.PhpSlim4ServerCodegen; +import org.openapitools.codegen.options.PhpSlim4ServerOptionsProvider; + +public class PhpSlim4ServerOptionsTest extends AbstractOptionsTest { + + @Tested + private PhpSlim4ServerCodegen clientCodegen; + + public PhpSlim4ServerOptionsTest() { + super(new PhpSlim4ServerOptionsProvider()); + } + + @Override + protected CodegenConfig getCodegenConfig() { + return clientCodegen; + } + + @SuppressWarnings("unused") + @Override + protected void setExpectations() { + new Expectations(clientCodegen) {{ + clientCodegen.setModelPackage(PhpSlim4ServerOptionsProvider.MODEL_PACKAGE_VALUE); + times = 1; + clientCodegen.setApiPackage(PhpSlim4ServerOptionsProvider.API_PACKAGE_VALUE); + times = 1; + clientCodegen.setParameterNamingConvention(PhpSlim4ServerOptionsProvider.VARIABLE_NAMING_CONVENTION_VALUE); + times = 1; + clientCodegen.setInvokerPackage(PhpSlim4ServerOptionsProvider.INVOKER_PACKAGE_VALUE); + times = 1; + clientCodegen.setPackageName(PhpSlim4ServerOptionsProvider.PACKAGE_NAME_VALUE); + times = 1; + clientCodegen.setSrcBasePath(PhpSlim4ServerOptionsProvider.SRC_BASE_PATH_VALUE); + times = 1; + clientCodegen.setArtifactVersion(PhpSlim4ServerOptionsProvider.ARTIFACT_VERSION_VALUE); + times = 1; + clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(PhpSlim4ServerOptionsProvider.SORT_PARAMS_VALUE)); + times = 1; + clientCodegen.setPsr7Implementation(PhpSlim4ServerOptionsProvider.PSR7_IMPLEMENTATION_VALUE); + times = 1; + }}; + } +} + diff --git a/samples/server/petstore/php-slim4/.gitignore b/samples/server/petstore/php-slim4/.gitignore new file mode 100644 index 000000000000..db204792ea34 --- /dev/null +++ b/samples/server/petstore/php-slim4/.gitignore @@ -0,0 +1,17 @@ +# ref: https://github.com/github/gitignore/blob/master/Composer.gitignore + +composer.phar +/vendor/ + +# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control +# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file +# composer.lock + +# phplint tool creates cache file which is not necessary in a codebase +/.phplint-cache + +# Do not commit local PHPUnit config +/phpunit.xml + +# Do not commit local PHP_CodeSniffer config +/phpcs.xml \ No newline at end of file diff --git a/samples/server/petstore/php-slim4/.htaccess b/samples/server/petstore/php-slim4/.htaccess new file mode 100644 index 000000000000..f6a2ceb3952b --- /dev/null +++ b/samples/server/petstore/php-slim4/.htaccess @@ -0,0 +1,6 @@ + + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^ index.php [QSA,L] + \ No newline at end of file diff --git a/samples/server/petstore/php-slim4/.openapi-generator-ignore b/samples/server/petstore/php-slim4/.openapi-generator-ignore new file mode 100644 index 000000000000..7484ee590a38 --- /dev/null +++ b/samples/server/petstore/php-slim4/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# 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 OpenAPI Generator 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/php-slim4/.openapi-generator/VERSION b/samples/server/petstore/php-slim4/.openapi-generator/VERSION new file mode 100644 index 000000000000..c3a2c7076fa8 --- /dev/null +++ b/samples/server/petstore/php-slim4/.openapi-generator/VERSION @@ -0,0 +1 @@ +4.2.0-SNAPSHOT \ No newline at end of file diff --git a/samples/server/petstore/php-slim4/README.md b/samples/server/petstore/php-slim4/README.md new file mode 100644 index 000000000000..cda41d8c57ea --- /dev/null +++ b/samples/server/petstore/php-slim4/README.md @@ -0,0 +1,238 @@ +# php-base - PHP Slim 4 Server library for OpenAPI Petstore + +* [OpenAPI Generator](https://openapi-generator.tech) +* [Slim 4 Documentation](https://www.slimframework.com/docs/v4/) + +This server has been generated with [Slim PSR-7](https://github.com/slimphp/Slim-Psr7) implementation. + +## Requirements + +* Web server with URL rewriting +* PHP 7.1 or newer + +This package contains `.htaccess` for Apache configuration. +If you use another server(Nginx, HHVM, IIS, lighttpd) check out [Web Servers](https://www.slimframework.com/docs/v3/start/web-servers.html) doc. + +## Installation via [Composer](https://getcomposer.org/) + +Navigate into your project's root directory and execute the bash command shown below. +This command downloads the Slim Framework and its third-party dependencies into your project's `vendor/` directory. +```bash +$ composer install +``` + +## Start devserver + +Run the following command in terminal to start localhost web server, assuming `./php-slim-server/` is public-accessible directory with `index.php` file: +```bash +$ php -S localhost:8888 -t php-slim-server +``` +> **Warning** This web server was designed to aid application development. +> It may also be useful for testing purposes or for application demonstrations that are run in controlled environments. +> It is not intended to be a full-featured web server. It should not be used on a public network. + +## Tests + +### PHPUnit + +This package uses PHPUnit 6 or 7(depends from your PHP version) for unit testing. +[Test folder](test) contains templates which you can fill with real test assertions. +How to write tests read at [PHPUnit Manual - Chapter 2. Writing Tests for PHPUnit](https://phpunit.de/manual/6.5/en/writing-tests-for-phpunit.html). + +#### Run + +Command | Target +---- | ---- +`$ composer test` | All tests +`$ composer test-apis` | Apis tests +`$ composer test-models` | Models tests + +#### Config + +Package contains fully functional config `./phpunit.xml.dist` file. Create `./phpunit.xml` in root folder to override it. + +Quote from [3. The Command-Line Test Runner — PHPUnit 7.4 Manual](https://phpunit.readthedocs.io/en/7.4/textui.html#command-line-options): + +> If phpunit.xml or phpunit.xml.dist (in that order) exist in the current working directory and --configuration is not used, the configuration will be automatically read from that file. + +### PHP CodeSniffer + +[PHP CodeSniffer Documentation](https://github.com/squizlabs/PHP_CodeSniffer/wiki). This tool helps to follow coding style and avoid common PHP coding mistakes. + +#### Run + +```bash +$ composer phpcs +``` + +#### Config + +Package contains fully functional config `./phpcs.xml.dist` file. It checks source code against PSR-1 and PSR-2 coding standards. +Create `./phpcs.xml` in root folder to override it. More info at [Using a Default Configuration File](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Advanced-Usage#using-a-default-configuration-file) + +### PHPLint + +[PHPLint Documentation](https://github.com/overtrue/phplint). Checks PHP syntax only. + +#### Run + +```bash +$ composer phplint +``` + +## Show errors + +Switch on option in `./index.php`: +```diff +/** + * Add Error Handling Middleware + * + * @param bool $displayErrorDetails -> Should be set to false in production + * @param bool $logErrors -> Parameter is passed to the default ErrorHandler + * @param bool $logErrorDetails -> Display error details in error log + * which can be replaced by a callable of your choice. + + * Note: This middleware should be added last. It will not handle any exceptions/errors + * for middleware added after it. + */ +--- $app->addErrorMiddleware(false, true, true); ++++ $app->addErrorMiddleware(true, true, true); +``` + +## API Endpoints + +All URIs are relative to *http://petstore.swagger.io:80/v2* + +> Important! Do not modify abstract API controllers directly! Instead extend them by implementation classes like: + +```php +// src/Api/PetApi.php + +namespace OpenAPIServer\Api; + +use OpenAPIServer\Api\AbstractPetApi; + +class PetApi extends AbstractPetApi +{ + + public function addPet($request, $response, $args) + { + // your implementation of addPet method here + } +} +``` + +Place all your implementation classes in `./src` folder accordingly. +For instance, when abstract class located at `./lib/Api/AbstractPetApi.php` you need to create implementation class at `./src/Api/PetApi.php`. + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +*AbstractAnotherFakeApi* | **call123TestSpecialTags** | **PATCH** /another-fake/dummy | To test special tags +*AbstractFakeApi* | **createXmlItem** | **POST** /fake/create_xml_item | creates an XmlItem +*AbstractFakeApi* | **fakeOuterBooleanSerialize** | **POST** /fake/outer/boolean | +*AbstractFakeApi* | **fakeOuterCompositeSerialize** | **POST** /fake/outer/composite | +*AbstractFakeApi* | **fakeOuterNumberSerialize** | **POST** /fake/outer/number | +*AbstractFakeApi* | **fakeOuterStringSerialize** | **POST** /fake/outer/string | +*AbstractFakeApi* | **testBodyWithFileSchema** | **PUT** /fake/body-with-file-schema | +*AbstractFakeApi* | **testBodyWithQueryParams** | **PUT** /fake/body-with-query-params | +*AbstractFakeApi* | **testClientModel** | **PATCH** /fake | To test \"client\" model +*AbstractFakeApi* | **testEndpointParameters** | **POST** /fake | Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 +*AbstractFakeApi* | **testEnumParameters** | **GET** /fake | To test enum parameters +*AbstractFakeApi* | **testGroupParameters** | **DELETE** /fake | Fake endpoint to test group parameters (optional) +*AbstractFakeApi* | **testInlineAdditionalProperties** | **POST** /fake/inline-additionalProperties | test inline additionalProperties +*AbstractFakeApi* | **testJsonFormData** | **GET** /fake/jsonFormData | test json serialization of form data +*AbstractFakeApi* | **testQueryParameterCollectionFormat** | **PUT** /fake/test-query-paramters | +*AbstractFakeClassnameTags123Api* | **testClassname** | **PATCH** /fake_classname_test | To test class name in snake case +*AbstractPetApi* | **addPet** | **POST** /pet | Add a new pet to the store +*AbstractPetApi* | **findPetsByStatus** | **GET** /pet/findByStatus | Finds Pets by status +*AbstractPetApi* | **findPetsByTags** | **GET** /pet/findByTags | Finds Pets by tags +*AbstractPetApi* | **updatePet** | **PUT** /pet | Update an existing pet +*AbstractPetApi* | **deletePet** | **DELETE** /pet/{petId} | Deletes a pet +*AbstractPetApi* | **getPetById** | **GET** /pet/{petId} | Find pet by ID +*AbstractPetApi* | **updatePetWithForm** | **POST** /pet/{petId} | Updates a pet in the store with form data +*AbstractPetApi* | **uploadFile** | **POST** /pet/{petId}/uploadImage | uploads an image +*AbstractPetApi* | **uploadFileWithRequiredFile** | **POST** /fake/{petId}/uploadImageWithRequiredFile | uploads an image (required) +*AbstractStoreApi* | **getInventory** | **GET** /store/inventory | Returns pet inventories by status +*AbstractStoreApi* | **placeOrder** | **POST** /store/order | Place an order for a pet +*AbstractStoreApi* | **deleteOrder** | **DELETE** /store/order/{order_id} | Delete purchase order by ID +*AbstractStoreApi* | **getOrderById** | **GET** /store/order/{order_id} | Find purchase order by ID +*AbstractUserApi* | **createUser** | **POST** /user | Create user +*AbstractUserApi* | **createUsersWithArrayInput** | **POST** /user/createWithArray | Creates list of users with given input array +*AbstractUserApi* | **createUsersWithListInput** | **POST** /user/createWithList | Creates list of users with given input array +*AbstractUserApi* | **loginUser** | **GET** /user/login | Logs user into the system +*AbstractUserApi* | **logoutUser** | **GET** /user/logout | Logs out current logged in user session +*AbstractUserApi* | **deleteUser** | **DELETE** /user/{username} | Delete user +*AbstractUserApi* | **getUserByName** | **GET** /user/{username} | Get user by user name +*AbstractUserApi* | **updateUser** | **PUT** /user/{username} | Updated user + + +## Models + +* OpenAPIServer\Model\AdditionalPropertiesAnyType +* OpenAPIServer\Model\AdditionalPropertiesArray +* OpenAPIServer\Model\AdditionalPropertiesBoolean +* OpenAPIServer\Model\AdditionalPropertiesClass +* OpenAPIServer\Model\AdditionalPropertiesInteger +* OpenAPIServer\Model\AdditionalPropertiesNumber +* OpenAPIServer\Model\AdditionalPropertiesObject +* OpenAPIServer\Model\AdditionalPropertiesString +* OpenAPIServer\Model\Animal +* OpenAPIServer\Model\ApiResponse +* OpenAPIServer\Model\ArrayOfArrayOfNumberOnly +* OpenAPIServer\Model\ArrayOfNumberOnly +* OpenAPIServer\Model\ArrayTest +* OpenAPIServer\Model\Capitalization +* OpenAPIServer\Model\Cat +* OpenAPIServer\Model\CatAllOf +* OpenAPIServer\Model\Category +* OpenAPIServer\Model\ClassModel +* OpenAPIServer\Model\Client +* OpenAPIServer\Model\Dog +* OpenAPIServer\Model\DogAllOf +* OpenAPIServer\Model\EnumArrays +* OpenAPIServer\Model\EnumClass +* OpenAPIServer\Model\EnumTest +* OpenAPIServer\Model\File +* OpenAPIServer\Model\FileSchemaTestClass +* OpenAPIServer\Model\FormatTest +* OpenAPIServer\Model\HasOnlyReadOnly +* OpenAPIServer\Model\MapTest +* OpenAPIServer\Model\MixedPropertiesAndAdditionalPropertiesClass +* OpenAPIServer\Model\Model200Response +* OpenAPIServer\Model\ModelList +* OpenAPIServer\Model\ModelReturn +* OpenAPIServer\Model\Name +* OpenAPIServer\Model\NumberOnly +* OpenAPIServer\Model\Order +* OpenAPIServer\Model\OuterComposite +* OpenAPIServer\Model\OuterEnum +* OpenAPIServer\Model\Pet +* OpenAPIServer\Model\ReadOnlyFirst +* OpenAPIServer\Model\SpecialModelName +* OpenAPIServer\Model\Tag +* OpenAPIServer\Model\TypeHolderDefault +* OpenAPIServer\Model\TypeHolderExample +* OpenAPIServer\Model\User +* OpenAPIServer\Model\XmlItem + + +## Authentication + +### Security schema `api_key` +> Important! To make ApiKey authentication work you need to extend [\OpenAPIServer\Auth\AbstractAuthenticator](./lib/Auth/AbstractAuthenticator.php) class by [\OpenAPIServer\Auth\ApiKeyAuthenticator](./src/Auth/ApiKeyAuthenticator.php) class. + +### Security schema `api_key_query` +> Important! To make ApiKey authentication work you need to extend [\OpenAPIServer\Auth\AbstractAuthenticator](./lib/Auth/AbstractAuthenticator.php) class by [\OpenAPIServer\Auth\ApiKeyAuthenticator](./src/Auth/ApiKeyAuthenticator.php) class. + +### Security schema `http_basic_test` +> Important! To make Basic authentication work you need to extend [\OpenAPIServer\Auth\AbstractAuthenticator](./lib/Auth/AbstractAuthenticator.php) class by [\OpenAPIServer\Auth\BasicAuthenticator](./src/Auth/BasicAuthenticator.php) class. + +### Security schema `petstore_auth` +> Important! To make OAuth authentication work you need to extend [\OpenAPIServer\Auth\AbstractAuthenticator](./lib/Auth/AbstractAuthenticator.php) class by [\OpenAPIServer\Auth\OAuthAuthenticator](./src/Auth/OAuthAuthenticator.php) class. + +Scope list: +* `write:pets` - modify pets in your account +* `read:pets` - read your pets + +### Advanced middleware configuration +Ref to used Slim Token Middleware [dyorg/slim-token-authentication](https://github.com/dyorg/slim-token-authentication/tree/1.x#readme) diff --git a/samples/server/petstore/php-slim4/composer.json b/samples/server/petstore/php-slim4/composer.json new file mode 100644 index 000000000000..cc3c4ef754a4 --- /dev/null +++ b/samples/server/petstore/php-slim4/composer.json @@ -0,0 +1,39 @@ +{ + "minimum-stability": "RC", + "repositories": [ + { + "type": "github", + "url": "https://github.com/ybelenko/slim-token-authentication" + } + ], + "require": { + "php": "^7.1", + "slim/slim": "^4.0", + "dyorg/slim-token-authentication": "dev-slim4", + "slim/psr7": "^0.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0 || ^7.0", + "overtrue/phplint": "^1.0", + "squizlabs/php_codesniffer": "^3.0" + }, + "autoload": { + "psr-4": { "OpenAPIServer\\": [ + "lib/", + "src/" + ]} + }, + "autoload-dev": { + "psr-4": { "OpenAPIServer\\": "test/" } + }, + "scripts": { + "test": [ + "@test-apis", + "@test-models" + ], + "test-apis": "phpunit --testsuite Apis", + "test-models": "phpunit --testsuite Models", + "phpcs": "phpcs", + "phplint": "phplint ./ --exclude=vendor" + } +} diff --git a/samples/server/petstore/php-slim4/index.php b/samples/server/petstore/php-slim4/index.php new file mode 100644 index 000000000000..6a2dfac09736 --- /dev/null +++ b/samples/server/petstore/php-slim4/index.php @@ -0,0 +1,74 @@ + true, + + /** + * Alternatively you can list your development host to have relaxed security. + * Default: ['localhost', '127.0.0.1'] + */ + // 'relaxed' => ['localhost', '127.0.0.1'], + + /** + * By default on ocurred a fail on authentication, is sent a response on json format with a + * message (`Invalid Token` or `Not found Token`) and with the token (if found), with status + * `401 Unauthorized`. You can customize it by setting a callable function on error option. + * Default: null + */ + // 'error' => null, +]; + +$router = new SlimRouter($config); +$app = $router->getSlimApp(); + +/** + * The routing middleware should be added before the ErrorMiddleware + * Otherwise exceptions thrown from it will not be handled + */ +$app->addRoutingMiddleware(); + +/** + * Add Error Handling Middleware + * + * @param bool $displayErrorDetails -> Should be set to false in production + * @param bool $logErrors -> Parameter is passed to the default ErrorHandler + * @param bool $logErrorDetails -> Display error details in error log + * which can be replaced by a callable of your choice. + + * Note: This middleware should be added last. It will not handle any exceptions/errors + * for middleware added after it. + */ +$app->addErrorMiddleware(false, true, true); + +$app->run(); diff --git a/samples/server/petstore/php-slim4/lib/Api/AbstractAnotherFakeApi.php b/samples/server/petstore/php-slim4/lib/Api/AbstractAnotherFakeApi.php new file mode 100644 index 000000000000..8104591966b6 --- /dev/null +++ b/samples/server/petstore/php-slim4/lib/Api/AbstractAnotherFakeApi.php @@ -0,0 +1,80 @@ +container = $container; + } + + + /** + * PATCH call123TestSpecialTags + * Summary: To test special tags + * Notes: To test special tags and operation ID starting with number + * Output-Formats: [application/json] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function call123TestSpecialTags(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $message = "How about implementing call123TestSpecialTags as a PATCH method in OpenAPIServer\Api\AnotherFakeApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } +} diff --git a/samples/server/petstore/php-slim4/lib/Api/AbstractFakeApi.php b/samples/server/petstore/php-slim4/lib/Api/AbstractFakeApi.php new file mode 100644 index 000000000000..53dbd4dad216 --- /dev/null +++ b/samples/server/petstore/php-slim4/lib/Api/AbstractFakeApi.php @@ -0,0 +1,400 @@ +container = $container; + } + + + /** + * POST createXmlItem + * Summary: creates an XmlItem + * Notes: this route creates an XmlItem + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function createXmlItem(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $message = "How about implementing createXmlItem as a POST method in OpenAPIServer\Api\FakeApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * POST fakeOuterBooleanSerialize + * Notes: Test serialization of outer boolean types + * Output-Formats: [*_/_*] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function fakeOuterBooleanSerialize(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $message = "How about implementing fakeOuterBooleanSerialize as a POST method in OpenAPIServer\Api\FakeApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * POST fakeOuterCompositeSerialize + * Notes: Test serialization of object with outer number type + * Output-Formats: [*_/_*] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function fakeOuterCompositeSerialize(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $message = "How about implementing fakeOuterCompositeSerialize as a POST method in OpenAPIServer\Api\FakeApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * POST fakeOuterNumberSerialize + * Notes: Test serialization of outer number types + * Output-Formats: [*_/_*] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function fakeOuterNumberSerialize(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $message = "How about implementing fakeOuterNumberSerialize as a POST method in OpenAPIServer\Api\FakeApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * POST fakeOuterStringSerialize + * Notes: Test serialization of outer string types + * Output-Formats: [*_/_*] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function fakeOuterStringSerialize(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $message = "How about implementing fakeOuterStringSerialize as a POST method in OpenAPIServer\Api\FakeApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * PUT testBodyWithFileSchema + * Notes: For this test, the body for this request much reference a schema named `File`. + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function testBodyWithFileSchema(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $message = "How about implementing testBodyWithFileSchema as a PUT method in OpenAPIServer\Api\FakeApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * PUT testBodyWithQueryParams + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function testBodyWithQueryParams(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $queryParams = $request->getQueryParams(); + $query = (key_exists('query', $queryParams)) ? $queryParams['query'] : null; + $body = $request->getParsedBody(); + $message = "How about implementing testBodyWithQueryParams as a PUT method in OpenAPIServer\Api\FakeApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * PATCH testClientModel + * Summary: To test \"client\" model + * Notes: To test \"client\" model + * Output-Formats: [application/json] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function testClientModel(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $message = "How about implementing testClientModel as a PATCH method in OpenAPIServer\Api\FakeApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * POST testEndpointParameters + * Summary: Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 + * Notes: Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function testEndpointParameters(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $integer = (isset($body['integer'])) ? $body['integer'] : null; + $int32 = (isset($body['int32'])) ? $body['int32'] : null; + $int64 = (isset($body['int64'])) ? $body['int64'] : null; + $number = (isset($body['number'])) ? $body['number'] : null; + $float = (isset($body['float'])) ? $body['float'] : null; + $double = (isset($body['double'])) ? $body['double'] : null; + $string = (isset($body['string'])) ? $body['string'] : null; + $patternWithoutDelimiter = (isset($body['pattern_without_delimiter'])) ? $body['pattern_without_delimiter'] : null; + $byte = (isset($body['byte'])) ? $body['byte'] : null; + $binary = (isset($body['binary'])) ? $body['binary'] : null; + $date = (isset($body['date'])) ? $body['date'] : null; + $dateTime = (isset($body['dateTime'])) ? $body['dateTime'] : null; + $password = (isset($body['password'])) ? $body['password'] : null; + $callback = (isset($body['callback'])) ? $body['callback'] : null; + $message = "How about implementing testEndpointParameters as a POST method in OpenAPIServer\Api\FakeApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * GET testEnumParameters + * Summary: To test enum parameters + * Notes: To test enum parameters + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function testEnumParameters(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $headers = $request->getHeaders(); + $enumHeaderStringArray = $request->hasHeader('enum_header_string_array') ? $headers['enum_header_string_array'] : null; + $enumHeaderString = $request->hasHeader('enum_header_string') ? $headers['enum_header_string'] : null; + $queryParams = $request->getQueryParams(); + $enumQueryStringArray = (key_exists('enum_query_string_array', $queryParams)) ? $queryParams['enum_query_string_array'] : null; + $enumQueryString = (key_exists('enum_query_string', $queryParams)) ? $queryParams['enum_query_string'] : null; + $enumQueryInteger = (key_exists('enum_query_integer', $queryParams)) ? $queryParams['enum_query_integer'] : null; + $enumQueryDouble = (key_exists('enum_query_double', $queryParams)) ? $queryParams['enum_query_double'] : null; + $body = $request->getParsedBody(); + $enumFormStringArray = (isset($body['enum_form_string_array'])) ? $body['enum_form_string_array'] : null; + $enumFormString = (isset($body['enum_form_string'])) ? $body['enum_form_string'] : null; + $message = "How about implementing testEnumParameters as a GET method in OpenAPIServer\Api\FakeApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * DELETE testGroupParameters + * Summary: Fake endpoint to test group parameters (optional) + * Notes: Fake endpoint to test group parameters (optional) + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function testGroupParameters(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $headers = $request->getHeaders(); + $requiredBooleanGroup = $request->hasHeader('required_boolean_group') ? $headers['required_boolean_group'] : null; + $booleanGroup = $request->hasHeader('boolean_group') ? $headers['boolean_group'] : null; + $queryParams = $request->getQueryParams(); + $requiredStringGroup = (key_exists('required_string_group', $queryParams)) ? $queryParams['required_string_group'] : null; + $requiredInt64Group = (key_exists('required_int64_group', $queryParams)) ? $queryParams['required_int64_group'] : null; + $stringGroup = (key_exists('string_group', $queryParams)) ? $queryParams['string_group'] : null; + $int64Group = (key_exists('int64_group', $queryParams)) ? $queryParams['int64_group'] : null; + $message = "How about implementing testGroupParameters as a DELETE method in OpenAPIServer\Api\FakeApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * POST testInlineAdditionalProperties + * Summary: test inline additionalProperties + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function testInlineAdditionalProperties(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $message = "How about implementing testInlineAdditionalProperties as a POST method in OpenAPIServer\Api\FakeApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * GET testJsonFormData + * Summary: test json serialization of form data + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function testJsonFormData(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $param = (isset($body['param'])) ? $body['param'] : null; + $param2 = (isset($body['param2'])) ? $body['param2'] : null; + $message = "How about implementing testJsonFormData as a GET method in OpenAPIServer\Api\FakeApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * PUT testQueryParameterCollectionFormat + * Notes: To test the collection format in query parameters + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function testQueryParameterCollectionFormat(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $queryParams = $request->getQueryParams(); + $pipe = (key_exists('pipe', $queryParams)) ? $queryParams['pipe'] : null; + $ioutil = (key_exists('ioutil', $queryParams)) ? $queryParams['ioutil'] : null; + $http = (key_exists('http', $queryParams)) ? $queryParams['http'] : null; + $url = (key_exists('url', $queryParams)) ? $queryParams['url'] : null; + $context = (key_exists('context', $queryParams)) ? $queryParams['context'] : null; + $message = "How about implementing testQueryParameterCollectionFormat as a PUT method in OpenAPIServer\Api\FakeApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } +} diff --git a/samples/server/petstore/php-slim4/lib/Api/AbstractFakeClassnameTags123Api.php b/samples/server/petstore/php-slim4/lib/Api/AbstractFakeClassnameTags123Api.php new file mode 100644 index 000000000000..762829ededfa --- /dev/null +++ b/samples/server/petstore/php-slim4/lib/Api/AbstractFakeClassnameTags123Api.php @@ -0,0 +1,80 @@ +container = $container; + } + + + /** + * PATCH testClassname + * Summary: To test class name in snake case + * Notes: To test class name in snake case + * Output-Formats: [application/json] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function testClassname(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $message = "How about implementing testClassname as a PATCH method in OpenAPIServer\Api\FakeClassnameTags123Api class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } +} diff --git a/samples/server/petstore/php-slim4/lib/Api/AbstractPetApi.php b/samples/server/petstore/php-slim4/lib/Api/AbstractPetApi.php new file mode 100644 index 000000000000..2e641c259dd9 --- /dev/null +++ b/samples/server/petstore/php-slim4/lib/Api/AbstractPetApi.php @@ -0,0 +1,267 @@ +container = $container; + } + + + /** + * POST addPet + * Summary: Add a new pet to the store + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function addPet(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $message = "How about implementing addPet as a POST method in OpenAPIServer\Api\PetApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * DELETE deletePet + * Summary: Deletes a pet + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function deletePet(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $headers = $request->getHeaders(); + $apiKey = $request->hasHeader('api_key') ? $headers['api_key'] : null; + $petId = $args['petId']; + $message = "How about implementing deletePet as a DELETE method in OpenAPIServer\Api\PetApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * GET findPetsByStatus + * Summary: Finds Pets by status + * Notes: Multiple status values can be provided with comma separated strings + * Output-Formats: [application/xml, application/json] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function findPetsByStatus(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $queryParams = $request->getQueryParams(); + $status = (key_exists('status', $queryParams)) ? $queryParams['status'] : null; + $message = "How about implementing findPetsByStatus as a GET method in OpenAPIServer\Api\PetApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * GET findPetsByTags + * Summary: Finds Pets by tags + * Notes: Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + * Output-Formats: [application/xml, application/json] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function findPetsByTags(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $queryParams = $request->getQueryParams(); + $tags = (key_exists('tags', $queryParams)) ? $queryParams['tags'] : null; + $message = "How about implementing findPetsByTags as a GET method in OpenAPIServer\Api\PetApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * GET getPetById + * Summary: Find pet by ID + * Notes: Returns a single pet + * Output-Formats: [application/xml, application/json] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function getPetById(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $petId = $args['petId']; + $message = "How about implementing getPetById as a GET method in OpenAPIServer\Api\PetApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * PUT updatePet + * Summary: Update an existing pet + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function updatePet(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $message = "How about implementing updatePet as a PUT method in OpenAPIServer\Api\PetApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * POST updatePetWithForm + * Summary: Updates a pet in the store with form data + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function updatePetWithForm(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $petId = $args['petId']; + $body = $request->getParsedBody(); + $name = (isset($body['name'])) ? $body['name'] : null; + $status = (isset($body['status'])) ? $body['status'] : null; + $message = "How about implementing updatePetWithForm as a POST method in OpenAPIServer\Api\PetApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * POST uploadFile + * Summary: uploads an image + * Output-Formats: [application/json] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function uploadFile(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $petId = $args['petId']; + $body = $request->getParsedBody(); + $additionalMetadata = (isset($body['additionalMetadata'])) ? $body['additionalMetadata'] : null; + $file = (key_exists('file', $request->getUploadedFiles())) ? $request->getUploadedFiles()['file'] : null; + $message = "How about implementing uploadFile as a POST method in OpenAPIServer\Api\PetApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * POST uploadFileWithRequiredFile + * Summary: uploads an image (required) + * Output-Formats: [application/json] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function uploadFileWithRequiredFile(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $petId = $args['petId']; + $body = $request->getParsedBody(); + $additionalMetadata = (isset($body['additionalMetadata'])) ? $body['additionalMetadata'] : null; + $requiredFile = (key_exists('requiredFile', $request->getUploadedFiles())) ? $request->getUploadedFiles()['requiredFile'] : null; + $message = "How about implementing uploadFileWithRequiredFile as a POST method in OpenAPIServer\Api\PetApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } +} diff --git a/samples/server/petstore/php-slim4/lib/Api/AbstractStoreApi.php b/samples/server/petstore/php-slim4/lib/Api/AbstractStoreApi.php new file mode 100644 index 000000000000..590dfc152372 --- /dev/null +++ b/samples/server/petstore/php-slim4/lib/Api/AbstractStoreApi.php @@ -0,0 +1,146 @@ +container = $container; + } + + + /** + * DELETE deleteOrder + * Summary: Delete purchase order by ID + * Notes: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function deleteOrder(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $orderId = $args['order_id']; + $message = "How about implementing deleteOrder as a DELETE method in OpenAPIServer\Api\StoreApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * GET getInventory + * Summary: Returns pet inventories by status + * Notes: Returns a map of status codes to quantities + * Output-Formats: [application/json] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function getInventory(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $message = "How about implementing getInventory as a GET method in OpenAPIServer\Api\StoreApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * GET getOrderById + * Summary: Find purchase order by ID + * Notes: For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + * Output-Formats: [application/xml, application/json] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function getOrderById(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $orderId = $args['order_id']; + $message = "How about implementing getOrderById as a GET method in OpenAPIServer\Api\StoreApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * POST placeOrder + * Summary: Place an order for a pet + * Output-Formats: [application/xml, application/json] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function placeOrder(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $message = "How about implementing placeOrder as a POST method in OpenAPIServer\Api\StoreApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } +} diff --git a/samples/server/petstore/php-slim4/lib/Api/AbstractUserApi.php b/samples/server/petstore/php-slim4/lib/Api/AbstractUserApi.php new file mode 100644 index 000000000000..9e0e5e410dad --- /dev/null +++ b/samples/server/petstore/php-slim4/lib/Api/AbstractUserApi.php @@ -0,0 +1,232 @@ +container = $container; + } + + + /** + * POST createUser + * Summary: Create user + * Notes: This can only be done by the logged in user. + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function createUser(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $message = "How about implementing createUser as a POST method in OpenAPIServer\Api\UserApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * POST createUsersWithArrayInput + * Summary: Creates list of users with given input array + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function createUsersWithArrayInput(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $message = "How about implementing createUsersWithArrayInput as a POST method in OpenAPIServer\Api\UserApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * POST createUsersWithListInput + * Summary: Creates list of users with given input array + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function createUsersWithListInput(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $body = $request->getParsedBody(); + $message = "How about implementing createUsersWithListInput as a POST method in OpenAPIServer\Api\UserApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * DELETE deleteUser + * Summary: Delete user + * Notes: This can only be done by the logged in user. + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function deleteUser(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $username = $args['username']; + $message = "How about implementing deleteUser as a DELETE method in OpenAPIServer\Api\UserApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * GET getUserByName + * Summary: Get user by user name + * Output-Formats: [application/xml, application/json] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function getUserByName(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $username = $args['username']; + $message = "How about implementing getUserByName as a GET method in OpenAPIServer\Api\UserApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * GET loginUser + * Summary: Logs user into the system + * Output-Formats: [application/xml, application/json] + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function loginUser(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $queryParams = $request->getQueryParams(); + $username = (key_exists('username', $queryParams)) ? $queryParams['username'] : null; + $password = (key_exists('password', $queryParams)) ? $queryParams['password'] : null; + $message = "How about implementing loginUser as a GET method in OpenAPIServer\Api\UserApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * GET logoutUser + * Summary: Logs out current logged in user session + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function logoutUser(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $message = "How about implementing logoutUser as a GET method in OpenAPIServer\Api\UserApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } + + /** + * PUT updateUser + * Summary: Updated user + * Notes: This can only be done by the logged in user. + * + * @param ServerRequestInterface $request Request + * @param ResponseInterface $response Response + * @param array|null $args Path arguments + * + * @return ResponseInterface + * @throws Exception to force implementation class to override this method + */ + public function updateUser(ServerRequestInterface $request, ResponseInterface $response, array $args) + { + $username = $args['username']; + $body = $request->getParsedBody(); + $message = "How about implementing updateUser as a PUT method in OpenAPIServer\Api\UserApi class?"; + throw new Exception($message); + + $response->getBody()->write($message); + return $response->withStatus(501); + } +} diff --git a/samples/server/petstore/php-slim4/lib/Auth/AbstractAuthenticator.php b/samples/server/petstore/php-slim4/lib/Auth/AbstractAuthenticator.php new file mode 100644 index 000000000000..a7d1304f4f28 --- /dev/null +++ b/samples/server/petstore/php-slim4/lib/Auth/AbstractAuthenticator.php @@ -0,0 +1,108 @@ +container = $container; + $this->requiredScope = $requiredScope; + } + + /** + * Makes the api key validation of your application + * + * Just an example of implementation. Override this method to fit your needs + * + * @param ServerRequestInterface $request HTTP request + * @param TokenSearch $tokenSearch Middleware instance which contains api key in token + * + * @return bool Must return either true or false + * @throws UnauthorizedExceptionInterface when cannot parse token + */ + public function __invoke(ServerRequestInterface &$request, TokenSearch $tokenSearch) + { + /** + * Try find authorization token via header, parameters, cookie or attribute + * If token not found, return response with status 401 (unauthorized) + */ + $token = $tokenSearch->getToken($request); + + /** + * Verify if token is valid on database + * If token isn't valid, expired or has insufficient scope must throw an UnauthorizedExceptionInterface + */ + $user = $this->getUserByToken($token); + + /** + * Set authenticated user at attributes + */ + $request = $request->withAttribute('authenticated_user', $user); + + return true; + } +} diff --git a/samples/server/petstore/php-slim4/lib/Middleware/JsonBodyParserMiddleware.php b/samples/server/petstore/php-slim4/lib/Middleware/JsonBodyParserMiddleware.php new file mode 100644 index 000000000000..35ef73f6bd72 --- /dev/null +++ b/samples/server/petstore/php-slim4/lib/Middleware/JsonBodyParserMiddleware.php @@ -0,0 +1,65 @@ +getHeaderLine('Content-Type'); + + if (strstr($contentType, 'application/json')) { + $contents = json_decode(file_get_contents('php://input'), true); + if (json_last_error() === JSON_ERROR_NONE) { + $request = $request->withParsedBody($contents); + } + } + + return $handler->handle($request); + } +} diff --git a/samples/server/petstore/php-slim4/lib/Model/AdditionalPropertiesAnyType.php b/samples/server/petstore/php-slim4/lib/Model/AdditionalPropertiesAnyType.php new file mode 100644 index 000000000000..c413ce6f611b --- /dev/null +++ b/samples/server/petstore/php-slim4/lib/Model/AdditionalPropertiesAnyType.php @@ -0,0 +1,30 @@ + 'PATCH', + 'basePathWithoutHost' => '/v2', + 'path' => '/another-fake/dummy', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractAnotherFakeApi', + 'userClassname' => 'AnotherFakeApi', + 'operationId' => 'call123TestSpecialTags', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'POST', + 'basePathWithoutHost' => '/v2', + 'path' => '/fake/create_xml_item', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractFakeApi', + 'userClassname' => 'FakeApi', + 'operationId' => 'createXmlItem', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'POST', + 'basePathWithoutHost' => '/v2', + 'path' => '/fake/outer/boolean', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractFakeApi', + 'userClassname' => 'FakeApi', + 'operationId' => 'fakeOuterBooleanSerialize', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'POST', + 'basePathWithoutHost' => '/v2', + 'path' => '/fake/outer/composite', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractFakeApi', + 'userClassname' => 'FakeApi', + 'operationId' => 'fakeOuterCompositeSerialize', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'POST', + 'basePathWithoutHost' => '/v2', + 'path' => '/fake/outer/number', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractFakeApi', + 'userClassname' => 'FakeApi', + 'operationId' => 'fakeOuterNumberSerialize', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'POST', + 'basePathWithoutHost' => '/v2', + 'path' => '/fake/outer/string', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractFakeApi', + 'userClassname' => 'FakeApi', + 'operationId' => 'fakeOuterStringSerialize', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'PUT', + 'basePathWithoutHost' => '/v2', + 'path' => '/fake/body-with-file-schema', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractFakeApi', + 'userClassname' => 'FakeApi', + 'operationId' => 'testBodyWithFileSchema', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'PUT', + 'basePathWithoutHost' => '/v2', + 'path' => '/fake/body-with-query-params', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractFakeApi', + 'userClassname' => 'FakeApi', + 'operationId' => 'testBodyWithQueryParams', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'PATCH', + 'basePathWithoutHost' => '/v2', + 'path' => '/fake', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractFakeApi', + 'userClassname' => 'FakeApi', + 'operationId' => 'testClientModel', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'POST', + 'basePathWithoutHost' => '/v2', + 'path' => '/fake', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractFakeApi', + 'userClassname' => 'FakeApi', + 'operationId' => 'testEndpointParameters', + 'authMethods' => [ + // http security schema named 'http_basic_test' + [ + 'type' => 'http', + 'isBasic' => true, + 'isBearer' => false, + 'isApiKey' => false, + 'isOAuth' => false, + ], + ], + ], + [ + 'httpMethod' => 'GET', + 'basePathWithoutHost' => '/v2', + 'path' => '/fake', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractFakeApi', + 'userClassname' => 'FakeApi', + 'operationId' => 'testEnumParameters', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'DELETE', + 'basePathWithoutHost' => '/v2', + 'path' => '/fake', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractFakeApi', + 'userClassname' => 'FakeApi', + 'operationId' => 'testGroupParameters', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'POST', + 'basePathWithoutHost' => '/v2', + 'path' => '/fake/inline-additionalProperties', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractFakeApi', + 'userClassname' => 'FakeApi', + 'operationId' => 'testInlineAdditionalProperties', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'GET', + 'basePathWithoutHost' => '/v2', + 'path' => '/fake/jsonFormData', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractFakeApi', + 'userClassname' => 'FakeApi', + 'operationId' => 'testJsonFormData', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'PUT', + 'basePathWithoutHost' => '/v2', + 'path' => '/fake/test-query-paramters', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractFakeApi', + 'userClassname' => 'FakeApi', + 'operationId' => 'testQueryParameterCollectionFormat', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'PATCH', + 'basePathWithoutHost' => '/v2', + 'path' => '/fake_classname_test', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractFakeClassnameTags123Api', + 'userClassname' => 'FakeClassnameTags123Api', + 'operationId' => 'testClassname', + 'authMethods' => [ + // apiKey security schema named 'api_key_query' + [ + 'type' => 'apiKey', + 'isBasic' => false, + 'isBearer' => false, + 'isApiKey' => true, + 'isOAuth' => false, + 'keyParamName' => 'api_key_query', + 'isKeyInHeader' => false, + 'isKeyInQuery' => true, + 'isKeyInCookie' => false, + ], + ], + ], + [ + 'httpMethod' => 'POST', + 'basePathWithoutHost' => '/v2', + 'path' => '/pet', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractPetApi', + 'userClassname' => 'PetApi', + 'operationId' => 'addPet', + 'authMethods' => [ + // oauth2 security schema named 'petstore_auth' + [ + 'type' => 'oauth2', + 'isBasic' => false, + 'isBearer' => false, + 'isApiKey' => false, + 'isOAuth' => true, + 'scopes' => [ + 'write:pets', // modify pets in your account + 'read:pets', // read your pets + ], + ], + ], + ], + [ + 'httpMethod' => 'GET', + 'basePathWithoutHost' => '/v2', + 'path' => '/pet/findByStatus', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractPetApi', + 'userClassname' => 'PetApi', + 'operationId' => 'findPetsByStatus', + 'authMethods' => [ + // oauth2 security schema named 'petstore_auth' + [ + 'type' => 'oauth2', + 'isBasic' => false, + 'isBearer' => false, + 'isApiKey' => false, + 'isOAuth' => true, + 'scopes' => [ + 'write:pets', // modify pets in your account + 'read:pets', // read your pets + ], + ], + ], + ], + [ + 'httpMethod' => 'GET', + 'basePathWithoutHost' => '/v2', + 'path' => '/pet/findByTags', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractPetApi', + 'userClassname' => 'PetApi', + 'operationId' => 'findPetsByTags', + 'authMethods' => [ + // oauth2 security schema named 'petstore_auth' + [ + 'type' => 'oauth2', + 'isBasic' => false, + 'isBearer' => false, + 'isApiKey' => false, + 'isOAuth' => true, + 'scopes' => [ + 'write:pets', // modify pets in your account + 'read:pets', // read your pets + ], + ], + ], + ], + [ + 'httpMethod' => 'PUT', + 'basePathWithoutHost' => '/v2', + 'path' => '/pet', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractPetApi', + 'userClassname' => 'PetApi', + 'operationId' => 'updatePet', + 'authMethods' => [ + // oauth2 security schema named 'petstore_auth' + [ + 'type' => 'oauth2', + 'isBasic' => false, + 'isBearer' => false, + 'isApiKey' => false, + 'isOAuth' => true, + 'scopes' => [ + 'write:pets', // modify pets in your account + 'read:pets', // read your pets + ], + ], + ], + ], + [ + 'httpMethod' => 'DELETE', + 'basePathWithoutHost' => '/v2', + 'path' => '/pet/{petId}', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractPetApi', + 'userClassname' => 'PetApi', + 'operationId' => 'deletePet', + 'authMethods' => [ + // oauth2 security schema named 'petstore_auth' + [ + 'type' => 'oauth2', + 'isBasic' => false, + 'isBearer' => false, + 'isApiKey' => false, + 'isOAuth' => true, + 'scopes' => [ + 'write:pets', // modify pets in your account + 'read:pets', // read your pets + ], + ], + ], + ], + [ + 'httpMethod' => 'GET', + 'basePathWithoutHost' => '/v2', + 'path' => '/pet/{petId}', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractPetApi', + 'userClassname' => 'PetApi', + 'operationId' => 'getPetById', + 'authMethods' => [ + // apiKey security schema named 'api_key' + [ + 'type' => 'apiKey', + 'isBasic' => false, + 'isBearer' => false, + 'isApiKey' => true, + 'isOAuth' => false, + 'keyParamName' => 'api_key', + 'isKeyInHeader' => true, + 'isKeyInQuery' => false, + 'isKeyInCookie' => false, + ], + ], + ], + [ + 'httpMethod' => 'POST', + 'basePathWithoutHost' => '/v2', + 'path' => '/pet/{petId}', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractPetApi', + 'userClassname' => 'PetApi', + 'operationId' => 'updatePetWithForm', + 'authMethods' => [ + // oauth2 security schema named 'petstore_auth' + [ + 'type' => 'oauth2', + 'isBasic' => false, + 'isBearer' => false, + 'isApiKey' => false, + 'isOAuth' => true, + 'scopes' => [ + 'write:pets', // modify pets in your account + 'read:pets', // read your pets + ], + ], + ], + ], + [ + 'httpMethod' => 'POST', + 'basePathWithoutHost' => '/v2', + 'path' => '/pet/{petId}/uploadImage', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractPetApi', + 'userClassname' => 'PetApi', + 'operationId' => 'uploadFile', + 'authMethods' => [ + // oauth2 security schema named 'petstore_auth' + [ + 'type' => 'oauth2', + 'isBasic' => false, + 'isBearer' => false, + 'isApiKey' => false, + 'isOAuth' => true, + 'scopes' => [ + 'write:pets', // modify pets in your account + 'read:pets', // read your pets + ], + ], + ], + ], + [ + 'httpMethod' => 'POST', + 'basePathWithoutHost' => '/v2', + 'path' => '/fake/{petId}/uploadImageWithRequiredFile', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractPetApi', + 'userClassname' => 'PetApi', + 'operationId' => 'uploadFileWithRequiredFile', + 'authMethods' => [ + // oauth2 security schema named 'petstore_auth' + [ + 'type' => 'oauth2', + 'isBasic' => false, + 'isBearer' => false, + 'isApiKey' => false, + 'isOAuth' => true, + 'scopes' => [ + 'write:pets', // modify pets in your account + 'read:pets', // read your pets + ], + ], + ], + ], + [ + 'httpMethod' => 'GET', + 'basePathWithoutHost' => '/v2', + 'path' => '/store/inventory', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractStoreApi', + 'userClassname' => 'StoreApi', + 'operationId' => 'getInventory', + 'authMethods' => [ + // apiKey security schema named 'api_key' + [ + 'type' => 'apiKey', + 'isBasic' => false, + 'isBearer' => false, + 'isApiKey' => true, + 'isOAuth' => false, + 'keyParamName' => 'api_key', + 'isKeyInHeader' => true, + 'isKeyInQuery' => false, + 'isKeyInCookie' => false, + ], + ], + ], + [ + 'httpMethod' => 'POST', + 'basePathWithoutHost' => '/v2', + 'path' => '/store/order', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractStoreApi', + 'userClassname' => 'StoreApi', + 'operationId' => 'placeOrder', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'DELETE', + 'basePathWithoutHost' => '/v2', + 'path' => '/store/order/{order_id}', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractStoreApi', + 'userClassname' => 'StoreApi', + 'operationId' => 'deleteOrder', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'GET', + 'basePathWithoutHost' => '/v2', + 'path' => '/store/order/{order_id}', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractStoreApi', + 'userClassname' => 'StoreApi', + 'operationId' => 'getOrderById', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'POST', + 'basePathWithoutHost' => '/v2', + 'path' => '/user', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractUserApi', + 'userClassname' => 'UserApi', + 'operationId' => 'createUser', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'POST', + 'basePathWithoutHost' => '/v2', + 'path' => '/user/createWithArray', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractUserApi', + 'userClassname' => 'UserApi', + 'operationId' => 'createUsersWithArrayInput', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'POST', + 'basePathWithoutHost' => '/v2', + 'path' => '/user/createWithList', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractUserApi', + 'userClassname' => 'UserApi', + 'operationId' => 'createUsersWithListInput', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'GET', + 'basePathWithoutHost' => '/v2', + 'path' => '/user/login', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractUserApi', + 'userClassname' => 'UserApi', + 'operationId' => 'loginUser', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'GET', + 'basePathWithoutHost' => '/v2', + 'path' => '/user/logout', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractUserApi', + 'userClassname' => 'UserApi', + 'operationId' => 'logoutUser', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'DELETE', + 'basePathWithoutHost' => '/v2', + 'path' => '/user/{username}', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractUserApi', + 'userClassname' => 'UserApi', + 'operationId' => 'deleteUser', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'GET', + 'basePathWithoutHost' => '/v2', + 'path' => '/user/{username}', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractUserApi', + 'userClassname' => 'UserApi', + 'operationId' => 'getUserByName', + 'authMethods' => [ + ], + ], + [ + 'httpMethod' => 'PUT', + 'basePathWithoutHost' => '/v2', + 'path' => '/user/{username}', + 'apiPackage' => 'OpenAPIServer\Api', + 'classname' => 'AbstractUserApi', + 'userClassname' => 'UserApi', + 'operationId' => 'updateUser', + 'authMethods' => [ + ], + ], + ]; + + /** + * Class constructor + * + * @param ContainerInterface|array $settings Either a ContainerInterface or an associative array of app settings + * + * @throws Exception When implementation class doesn't exists + */ + public function __construct($settings = []) + { + if ($settings instanceof ContainerInterface) { + // Set container to create App with on AppFactory + AppFactory::setContainer($settings); + } + $this->slimApp = AppFactory::create(); + + // middlewares requires Psr\Container\ContainerInterface + $container = $this->slimApp->getContainer(); + + $authPackage = 'OpenAPIServer\Auth'; + $basicAuthenticator = function (ServerRequestInterface &$request, TokenSearch $tokenSearch) use ($authPackage) { + $message = "How about extending AbstractAuthenticator class by {$authPackage}\BasicAuthenticator?"; + throw new Exception($message); + }; + $apiKeyAuthenticator = function (ServerRequestInterface &$request, TokenSearch $tokenSearch) use ($authPackage) { + $message = "How about extending AbstractAuthenticator class by {$authPackage}\ApiKeyAuthenticator?"; + throw new Exception($message); + }; + $oAuthAuthenticator = function (ServerRequestInterface &$request, TokenSearch $tokenSearch) use ($authPackage) { + $message = "How about extending AbstractAuthenticator class by {$authPackage}\OAuthAuthenticator?"; + throw new Exception($message); + }; + + $userOptions = null; + if ($settings instanceof ContainerInterface && $settings->has('tokenAuthenticationOptions')) { + $userOptions = $settings->get('tokenAuthenticationOptions'); + } elseif (is_array($settings) && isset($settings['tokenAuthenticationOptions'])) { + $userOptions = $settings['tokenAuthenticationOptions']; + } + + foreach ($this->operations as $operation) { + $callback = function ($request, $response, $arguments) use ($operation) { + $message = "How about extending {$operation['classname']} by {$operation['apiPackage']}\\{$operation['userClassname']} class implementing {$operation['operationId']} as a {$operation['httpMethod']} method?"; + throw new Exception($message); + $response->getBody()->write($message); + return $response->withStatus(501); + }; + $middlewares = [new JsonBodyParserMiddleware()]; + + if (class_exists("\\{$operation['apiPackage']}\\{$operation['userClassname']}")) { + $callback = "\\{$operation['apiPackage']}\\{$operation['userClassname']}:{$operation['operationId']}"; + } + + foreach ($operation['authMethods'] as $authMethod) { + switch ($authMethod['type']) { + case 'http': + $authenticatorClassname = "\\{$authPackage}\\BasicAuthenticator"; + if (class_exists($authenticatorClassname)) { + $basicAuthenticator = new $authenticatorClassname($container); + } + + $middlewares[] = new TokenAuthentication($this->getTokenAuthenticationOptions([ + 'authenticator' => $basicAuthenticator, + 'regex' => $authMethod['isBearer'] ? '/Bearer\s+(.*)$/i' : '/Basic\s+(.*)$/i', + 'header' => 'Authorization', + 'parameter' => null, + 'cookie' => null, + 'argument' => null, + ], $userOptions)); + break; + case 'apiKey': + $authenticatorClassname = "\\{$authPackage}\\ApiKeyAuthenticator"; + if (class_exists($authenticatorClassname)) { + $apiKeyAuthenticator = new $authenticatorClassname($container); + } + + $middlewares[] = new TokenAuthentication($this->getTokenAuthenticationOptions([ + 'authenticator' => $apiKeyAuthenticator, + 'regex' => '/^(.*)$/i', + 'header' => $authMethod['isKeyInHeader'] ? $authMethod['keyParamName'] : null, + 'parameter' => $authMethod['isKeyInQuery'] ? $authMethod['keyParamName'] : null, + 'cookie' => $authMethod['isKeyInCookie'] ? $authMethod['keyParamName'] : null, + 'argument' => null, + ], $userOptions)); + break; + case 'oauth2': + $authenticatorClassname = "\\{$authPackage}\\OAuthAuthenticator"; + if (class_exists($authenticatorClassname)) { + $oAuthAuthenticator = new $authenticatorClassname($container, $authMethod['scopes']); + } + + $middlewares[] = new TokenAuthentication($this->getTokenAuthenticationOptions([ + 'authenticator' => $oAuthAuthenticator, + 'regex' => '/Bearer\s+(.*)$/i', + 'header' => 'Authorization', + 'parameter' => null, + 'cookie' => null, + 'argument' => null, + ], $userOptions)); + break; + default: + throw new Exception('Unknown authorization schema type'); + } + } + + $this->addRoute( + [$operation['httpMethod']], + "{$operation['basePathWithoutHost']}{$operation['path']}", + $callback, + $middlewares + )->setName($operation['operationId']); + } + } + + /** + * Merges user defined options with dynamic params + * + * @param array $staticOptions Required static options + * @param array $userOptions User options + * + * @return array Merged array + */ + private function getTokenAuthenticationOptions(array $staticOptions, array $userOptions = null) + { + if (is_array($userOptions) === false) { + return $staticOptions; + } + + return array_merge($userOptions, $staticOptions); + } + + /** + * Add route with multiple methods + * + * @param string[] $methods Numeric array of HTTP method names + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * @param array|null $middlewares List of middlewares + * + * @return RouteInterface + * + * @throws InvalidArgumentException If the route pattern isn't a string + */ + public function addRoute(array $methods, string $pattern, $callable, $middlewares = []) + { + $route = $this->slimApp->map($methods, $pattern, $callable); + foreach ($middlewares as $middleware) { + $route->add($middleware); + } + return $route; + } + + /** + * Returns Slim Framework instance + * + * @return App + */ + public function getSlimApp() + { + return $this->slimApp; + } +} diff --git a/samples/server/petstore/php-slim4/phpcs.xml.dist b/samples/server/petstore/php-slim4/phpcs.xml.dist new file mode 100644 index 000000000000..69f4ddac71c3 --- /dev/null +++ b/samples/server/petstore/php-slim4/phpcs.xml.dist @@ -0,0 +1,31 @@ + + + PHP_CodeSniffer config for OpenAPI Petstore + + + ./ + + + ./vendor + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/server/petstore/php-slim4/phpunit.xml.dist b/samples/server/petstore/php-slim4/phpunit.xml.dist new file mode 100644 index 000000000000..6af1442ee653 --- /dev/null +++ b/samples/server/petstore/php-slim4/phpunit.xml.dist @@ -0,0 +1,30 @@ + + + + + ./test/Api + + + ./test/Model + + + + + ./lib/Api + ./lib/Model + + + + + + diff --git a/samples/server/petstore/php-slim4/test/Api/AnotherFakeApiTest.php b/samples/server/petstore/php-slim4/test/Api/AnotherFakeApiTest.php new file mode 100644 index 000000000000..fc8c82eedaa9 --- /dev/null +++ b/samples/server/petstore/php-slim4/test/Api/AnotherFakeApiTest.php @@ -0,0 +1,80 @@ +