Symfony generator enhancements (#6016)

* Fix error in Symfony models #5985

* Parse Symfony params #5985

* Implement auth metods in Symfony #5985

* Make "get" to "is" in Symfony's booleans #5985

* Use `camelize` instead of `initialCaps` in Symfony #5985

* Use File.separator instead of "/" in PHP/Symfony #5985

* Improve README generation for Symfony #5985

* Create an options test for Symfony #5985
This commit is contained in:
Konstantin Simon Maria Möllers 2017-07-10 18:34:43 +02:00 committed by wing328
parent ca988039cc
commit d522236cec
10 changed files with 547 additions and 183 deletions

View File

@ -45,8 +45,8 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg
protected String apiDirName = "Api";
protected String modelDirName = "Model";
protected String variableNamingConvention= "snake_case";
protected String apiDocPath = docsBasePath + "/" + apiDirName;
protected String modelDocPath = docsBasePath + "/" + modelDirName;
protected String apiDocPath = docsBasePath + File.separator + apiDirName;
protected String modelDocPath = docsBasePath + File.separator + modelDirName;
public AbstractPhpCodegen() {
super();
@ -198,10 +198,10 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg
additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\"));
// make api and model src path available in mustache template
additionalProperties.put("apiSrcPath", "./" + toSrcPath(apiPackage, srcBasePath));
additionalProperties.put("modelSrcPath", "./" + toSrcPath(modelPackage, srcBasePath));
additionalProperties.put("apiTestPath", "./" + testBasePath + "/" + apiDirName);
additionalProperties.put("modelTestPath", "./" + testBasePath + "/" + modelDirName);
additionalProperties.put("apiSrcPath", "." + File.separator + toSrcPath(apiPackage, srcBasePath));
additionalProperties.put("modelSrcPath", "." + File.separator + toSrcPath(modelPackage, srcBasePath));
additionalProperties.put("apiTestPath", "." + File.separator + testBasePath + File.separator + apiDirName);
additionalProperties.put("modelTestPath", "." + File.separator + testBasePath + File.separator + modelDirName);
// make api and model doc path available in mustache template
additionalProperties.put("apiDocPath", apiDocPath);
@ -261,32 +261,32 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg
@Override
public String apiFileFolder() {
return (outputFolder + "/" + toPackagePath(apiPackage, srcBasePath));
return (outputFolder + File.separator + toPackagePath(apiPackage, srcBasePath));
}
@Override
public String modelFileFolder() {
return (outputFolder + "/" + toPackagePath(modelPackage, srcBasePath));
return (outputFolder + File.separator + toPackagePath(modelPackage, srcBasePath));
}
@Override
public String apiTestFileFolder() {
return (outputFolder + "/" + getPackagePath() + "/" + testBasePath + "/" + apiDirName);
return (outputFolder + File.separator + getPackagePath() + File.separator + testBasePath + File.separator + apiDirName);
}
@Override
public String modelTestFileFolder() {
return (outputFolder + "/" + getPackagePath() + "/" + testBasePath + "/" + modelDirName);
return (outputFolder + File.separator + getPackagePath() + File.separator + testBasePath + File.separator + modelDirName);
}
@Override
public String apiDocFileFolder() {
return (outputFolder + "/" + getPackagePath() + "/" + apiDocPath);
return (outputFolder + File.separator + getPackagePath() + File.separator + apiDocPath);
}
@Override
public String modelDocFileFolder() {
return (outputFolder + "/" + getPackagePath() + "/" + modelDocPath);
return (outputFolder + File.separator + getPackagePath() + File.separator + modelDocPath);
}
@Override

View File

@ -16,7 +16,6 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
@SuppressWarnings("hiding")
static Logger LOGGER = LoggerFactory.getLogger(SymfonyServerCodegen.class);
public static final String VARIABLE_NAMING_CONVENTION = "variableNamingConvention";
public static final String BUNDLE_NAME = "bundleName";
public static final String COMPOSER_VENDOR_NAME = "composerVendorName";
public static final String COMPOSER_PROJECT_NAME = "composerProjectName";
@ -66,9 +65,9 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
setBundleName("SwaggerServer");
packagePath = "SymfonyBundle-php";
modelDirName = "Model";
docsBasePath = "Resources/docs";
apiDocPath = docsBasePath + "/" + apiDirName;
modelDocPath = docsBasePath + "/" + modelDirName;
docsBasePath = "Resources" + File.separator + "docs";
apiDocPath = docsBasePath + File.separator + apiDirName;
modelDocPath = docsBasePath + File.separator + modelDirName;
outputFolder = "generated-code" + File.separator + "php";
apiTemplateFiles.put("api_controller.mustache", ".php");
modelTestTemplateFiles.put("model_test.mustache", ".php");
@ -153,7 +152,7 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
public String controllerFileFolder() {
return (outputFolder + "/" + toPackagePath(controllerPackage, srcBasePath));
return (outputFolder + File.separator + toPackagePath(controllerPackage, srcBasePath));
}
@Override
@ -219,16 +218,6 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
additionalProperties.put(COMPOSER_VENDOR_NAME, composerVendorName);
}
if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_VERSION)) {
this.setArtifactVersion((String) additionalProperties.get(CodegenConstants.ARTIFACT_VERSION));
} else {
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
}
if (additionalProperties.containsKey(VARIABLE_NAMING_CONVENTION)) {
this.setParameterNamingConvention((String) additionalProperties.get(VARIABLE_NAMING_CONVENTION));
}
additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\"));
additionalProperties.put("controllerPackage", controllerPackage);
additionalProperties.put("apiTestsPackage", apiTestsPackage);
@ -241,13 +230,13 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
additionalProperties.put("bundleAlias", bundleAlias);
// make api and model src path available in mustache template
additionalProperties.put("apiSrcPath", "./" + toSrcPath(apiPackage, srcBasePath));
additionalProperties.put("modelSrcPath", "./" + toSrcPath(modelPackage, srcBasePath));
additionalProperties.put("testsSrcPath", "./" + toSrcPath(testsPackage, srcBasePath));
additionalProperties.put("apiTestsSrcPath", "./" + toSrcPath(apiTestsPackage, srcBasePath));
additionalProperties.put("modelTestsSrcPath", "./" + toSrcPath(modelTestsPackage, srcBasePath));
additionalProperties.put("apiTestPath", "./" + testsDirName + "/" + apiDirName);
additionalProperties.put("modelTestPath", "./" + testsDirName + "/" + modelDirName);
additionalProperties.put("apiSrcPath", "." + File.separator + toSrcPath(apiPackage, srcBasePath));
additionalProperties.put("modelSrcPath", "." + File.separator + toSrcPath(modelPackage, srcBasePath));
additionalProperties.put("testsSrcPath", "." + File.separator + toSrcPath(testsPackage, srcBasePath));
additionalProperties.put("apiTestsSrcPath", "." + File.separator + toSrcPath(apiTestsPackage, srcBasePath));
additionalProperties.put("modelTestsSrcPath", "." + File.separator + toSrcPath(modelTestsPackage, srcBasePath));
additionalProperties.put("apiTestPath", "." + File.separator + testsDirName + File.separator + apiDirName);
additionalProperties.put("modelTestPath", "." + File.separator + testsDirName + File.separator + modelDirName);
// make api and model doc path available in mustache template
additionalProperties.put("apiDocPath", apiDocPath);
@ -256,15 +245,18 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
// make test path available in mustache template
additionalProperties.put("testsDirName", testsDirName);
final String configDir = getPackagePath() + File.separator + "Resources" + File.separator + "config";
final String dependencyInjectionDir = getPackagePath() + File.separator + "DependencyInjection";
supportingFiles.add(new SupportingFile("Controller.mustache", toPackagePath(controllerPackage, srcBasePath), "Controller.php"));
supportingFiles.add(new SupportingFile("Bundle.mustache", getPackagePath(), bundleClassName + ".php"));
supportingFiles.add(new SupportingFile("Extension.mustache", getPackagePath() + "/DependencyInjection", bundleExtensionName + ".php"));
supportingFiles.add(new SupportingFile("ApiPass.mustache", getPackagePath() + "/DependencyInjection/Compiler", bundleName + "ApiPass.php"));
supportingFiles.add(new SupportingFile("Extension.mustache", dependencyInjectionDir, bundleExtensionName + ".php"));
supportingFiles.add(new SupportingFile("ApiPass.mustache", dependencyInjectionDir + File.separator + "Compiler", bundleName + "ApiPass.php"));
supportingFiles.add(new SupportingFile("ApiServer.mustache", toPackagePath(apiPackage, srcBasePath), "ApiServer.php"));
supportingFiles.add(new SupportingFile("ModelSerializer.mustache", toPackagePath(modelPackage, srcBasePath), "ModelSerializer.php"));
supportingFiles.add(new SupportingFile("ModelInterface.mustache", toPackagePath(modelPackage, srcBasePath), "ModelInterface.php"));
supportingFiles.add(new SupportingFile("routing.mustache", getPackagePath() + "/Resources/config", "routing.yml"));
supportingFiles.add(new SupportingFile("services.mustache", getPackagePath() + "/Resources/config", "services.yml"));
supportingFiles.add(new SupportingFile("routing.mustache", configDir, "routing.yml"));
supportingFiles.add(new SupportingFile("services.mustache", configDir, "services.yml"));
supportingFiles.add(new SupportingFile("composer.mustache", getPackagePath(), "composer.json"));
supportingFiles.add(new SupportingFile("autoload.mustache", getPackagePath(), "autoload.php"));
supportingFiles.add(new SupportingFile("README.mustache", getPackagePath(), "README.md"));
@ -281,6 +273,7 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
operations.put("controllerName", toControllerName((String) operations.get("pathPrefix")));
operations.put("symfonyService", toSymfonyService((String) operations.get("pathPrefix")));
HashSet<CodegenSecurity> authMethods = new HashSet<>();
HashSet<String> imports = new HashSet<>();
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation op : operationList) {
@ -310,9 +303,15 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
imports.add(exception);
}
}
// Add operation's authentication methods to whole interface
if (op.authMethods != null) {
authMethods.addAll(op.authMethods);
}
}
operations.put("imports", new ArrayList<>(imports));
operations.put("authMethods", authMethods);
return objs;
}
@ -332,11 +331,16 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
final String importType = var.datatype.replaceFirst("\\[\\]$", "");
final String dataType = extractSimpleName(var.datatype);
final boolean isScalarType = typeMapping.containsValue(importType);
var.vendorExtensions.put("x-fullType", var.datatype);
if (!isScalarType) {
var.vendorExtensions.put("x-typeAnnotation", dataType.endsWith("[]") ? "array" : dataType);
imports.add(importType);
var.datatype = dataType;
}
if (var.isBoolean) {
var.getter = var.getter.replaceAll("^get", "is");
}
}
}
@ -355,12 +359,12 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
@Override
public String apiTestFileFolder() {
return (outputFolder + "/" + toPackagePath(apiTestsPackage, srcBasePath));
return (outputFolder + File.separator + toPackagePath(apiTestsPackage, srcBasePath));
}
@Override
public String modelTestFileFolder() {
return (outputFolder + "/" + toPackagePath(modelTestsPackage, srcBasePath));
return (outputFolder + File.separator + toPackagePath(modelTestsPackage, srcBasePath));
}
public void setComposerVendorName(String composerVendorName) {
@ -429,14 +433,14 @@ public class SymfonyServerCodegen extends AbstractPhpCodegen implements CodegenC
if (name.isEmpty()) {
return "DefaultApiInterface";
}
return initialCaps(name) + "ApiInterface";
return camelize(name, false) + "ApiInterface";
}
protected String toControllerName(String name) {
if (name.isEmpty()) {
return "DefaultController";
}
return initialCaps(name) + "Controller";
return camelize(name, false) + "Controller";
}
protected String toSymfonyService(String name) {

View File

@ -34,83 +34,209 @@ use Symfony\Component\HttpKernel\Exception\HttpException;
class Controller extends BaseController
{
/**
* This will return a response with code 400. Usage example:
*
* return $this->createBadRequestResponse('Unable to access this page!');
*
* @param string $message A message
*
* @return Response
*/
public function createBadRequestResponse($message = 'Bad Request.')
{
return new Response($message, 400);
}
/**
* This will return a response with code 400. Usage example:
* return $this->createBadRequestResponse('Unable to access this page!');
*
* @param string $message A message
*
* @return Response
*/
public function createBadRequestResponse($message = 'Bad Request.')
{
return new Response($message, 400);
}
/**
* This will return an error response. Usage example:
*
* return $this->createErrorResponse(new UnauthorizedHttpException());
*
* @param HttpException $exception An HTTP exception
*
* @return Response
*/
public function createErrorResponse(HttpException $exception)
{
$statusCode = $exception->getStatusCode();
$headers = array_merge($exception->getHeaders(), ['Content-Type' => 'application/json']);
/**
* This will return an error response. Usage example:
* return $this->createErrorResponse(new UnauthorizedHttpException());
*
* @param HttpException $exception An HTTP exception
*
* @return Response
*/
public function createErrorResponse(HttpException $exception)
{
$statusCode = $exception->getStatusCode();
$headers = array_merge($exception->getHeaders(), ['Content-Type' => 'application/json']);
$json = $this->exceptionToArray($exception);
$json["statusCode"] = $statusCode;
$json = $this->exceptionToArray($exception);
$json['statusCode'] = $statusCode;
return new Response(json_encode($json, 15, 512), $statusCode, $headers);
}
return new Response(json_encode($json, 15, 512), $statusCode, $headers);
}
/**
* Serializes data to a given type format.
*
* @param mixed $data The data to serialize.
* @param string $class The source data class.
* @param string $format The target serialization format.
* @return string A serialized data string.
*/
public function serialize($data, $format)
{
return $this->get('{{bundleAlias}}.model.model_serializer')->serialize($data, $format);
}
/**
* Serializes data to a given type format.
*
* @param mixed $data The data to serialize.
* @param string $class The source data class.
* @param string $format The target serialization format.
*
* @return string A serialized data string.
*/
public function serialize($data, $format)
{
return $this->get('{{bundleAlias}}.model.model_serializer')->serialize($data, $format);
}
/**
* Deserializes data from a given type format.
*
* @param string $data The data to deserialize.
* @param string $class The target data class.
* @param string $format The source serialization format.
* @return mixed A deserialized data.
*/
public function deserialize($data, $class, $format)
{
return $this->get('{{bundleAlias}}.model.model_serializer')->deserialize($data, $class, $format);
}
/**
* Deserializes data from a given type format.
*
* @param string $data The data to deserialize.
* @param string $class The target data class.
* @param string $format The source serialization format.
*
* @return mixed A deserialized data.
*/
public function deserialize($data, $class, $format)
{
return $this->get('{{bundleAlias}}.model.model_serializer')->deserialize($data, $class, $format);
}
/**
* Converts an exception to a serializable array.
*
* @param \Exception|null $exception
*
* @return array
*/
private function exceptionToArray(\Exception $exception = null)
{
if (null === $exception) {
return null;
}
/**
* Decodes a string value.
*
* @param string $string The string value to decode.
* @param string $dataType The data type of the parameter.
*
* @return mixed The decoded value.
*/
public function fromString($string, $dataType)
{
if ($dataType === 'integer' || $dataType === 'number') {
return $this->toNumber($string);
}
if ($dataType === 'bool') {
return $this->toBoolean($string);
}
if ($dataType === '\DateTime') {
return $this->toDateTime($string);
}
return [
"message" => $exception->getMessage(),
"type" => get_class($exception),
"previous" => $this->exceptionToArray($exception->getPrevious()),
];
}
return $string;
}
/**
* Decodes a header value.
*
* @param string $header The header value to decode.
* @param string $dataType The data type of the parameter.
*
* @return mixed The decoded value.
*/
public function fromHeader($header, $dataType)
{
return $this->fromString($header, $dataType);
}
/**
* Decodes a query value.
*
* @param string $query The query value to decode.
* @param string $dataType The data type of the parameter.
*
* @return mixed The decoded value.
*/
public function fromQuery($query, $dataType)
{
return $this->fromString($query, $dataType);
}
/**
* Decodes a path value.
*
* @param string $path The path value to decode.
* @param string $dataType The data type of the parameter.
*
* @return mixed The decoded value.
*/
public function fromPath($path, $dataType)
{
return $this->fromString($path, $dataType);
}
/**
* Decodes a form value.
*
* @param string $form The form value to decode.
* @param string $dataType The data type of the parameter.
*
* @return mixed The decoded value.
*/
public function fromForm($form, $dataType)
{
return $this->fromString($form, $dataType);
}
/**
* Decoded a string to a number.
*
* @param string $string The string to decode.
*
* @return number|null A decoded number, or null, if not a valid string.
*/
private function toNumber($string)
{
if (is_numeric($string)) {
return $string + 0;
}
return null;
}
/**
* Decoded a string to a boolean.
*
* @param string $string The string to decode.
*
* @return boolean|null A decoded boolean, or null, if not a valid string.
*/
private function toBoolean($string)
{
if ($string === 'true') {
return true;
}
if ($string === 'false') {
return false;
}
return null;
}
/**
* Decoded a string to a date time.
*
* @param string $string The string to decode.
*
* @return \DateTime|null A decoded date time, or null, if not a valid string.
*/
private function toDateTime($string)
{
if ($dateTime = date_create($string)) {
return $dateTime;
}
return null;
}
/**
* Converts an exception to a serializable array.
*
* @param \Exception|null $exception
*
* @return array
*/
private function exceptionToArray(\Exception $exception = null)
{
if (null === $exception) {
return null;
}
return [
'message' => $exception->getMessage(),
'type' => get_class($exception),
'previous' => $this->exceptionToArray($exception->getPrevious()),
];
}
}

View File

@ -1,9 +1,9 @@
# {{packagePath}}
# {{bundleName}}
{{#appDescription}}
{{{appDescription}}}
{{/appDescription}}
This PHP package is automatically generated by the [Swagger Codegen](https://github.com/swagger-api/swagger-codegen) project:
This [Symfony](https://symfony.com/) bundle is automatically generated by the [Swagger Codegen](https://github.com/swagger-api/swagger-codegen) project:
- API version: {{appVersion}}
{{#artifactVersion}}
@ -22,7 +22,6 @@ For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
PHP 5.4.0 and later
## Installation & Usage
### Composer
To install the bindings via [Composer](http://getcomposer.org/), add the following to `composer.json`:
@ -42,13 +41,6 @@ To install the bindings via [Composer](http://getcomposer.org/), add the followi
Then run `composer install`
### Manual Installation
Download the files and include `autoload.php`:
```php
require_once('/path/to/{{packagePath}}/autoload.php');
```
## Tests
@ -59,39 +51,93 @@ composer install
./vendor/bin/phpunit
```
## Getting Started
Please follow the [installation procedure](#installation--usage) and then run the following:
Step 1: Please follow the [installation procedure](#installation--usage) first.
Step 2: Enable the bundle in the kernel:
```php
<?php
require_once(__DIR__ . '/vendor/autoload.php');
{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}}{{#hasAuthMethods}}{{#authMethods}}{{#isBasic}}
// Configure HTTP basic authorization: {{{name}}}
{{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setUsername('YOUR_USERNAME');
{{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setPassword('YOUR_PASSWORD');{{/isBasic}}{{#isApiKey}}
// Configure API key authorization: {{{name}}}
{{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setApiKey('{{{keyParamName}}}', 'YOUR_API_KEY');
// Uncomment below to setup prefix (e.g. Bearer) for API key, if needed
// {{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setApiKeyPrefix('{{{keyParamName}}}', 'Bearer');{{/isApiKey}}{{#isOAuth}}
// Configure OAuth2 access token for authorization: {{{name}}}
{{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setAccessToken('YOUR_ACCESS_TOKEN');{{/isOAuth}}{{/authMethods}}
{{/hasAuthMethods}}
// app/AppKernel.php
$api_instance = new {{invokerPackage}}\Api\{{classname}}();
{{#allParams}}${{paramName}} = {{{example}}}; // {{{dataType}}} | {{{description}}}
{{/allParams}}
try {
{{#returnType}}$result = {{/returnType}}$api_instance->{{{operationId}}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}}
print_r($result);{{/returnType}}
} catch (Exception $e) {
echo 'Exception when calling {{classname}}->{{operationId}}: ', $e->getMessage(), PHP_EOL;
public function registerBundles()
{
$bundles = array(
// ...
new {{invokerPackage}}\{{bundleClassName}}(),
// ...
);
}
{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}}
?>
```
Step 3: Register the routes:
```yaml
# app/config/routing.yml
{{bundleAlias}}:
resource: "@{{bundleName}}Bundle/Resources/config/routing.yml"
```
Step 4: Implement the API calls:
```php
<?php{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}
// src/Acme/MyBundle/Api/{{classname}}.php
namespace Acme\MyBundle\Api;
use {{apiPackage}}\{{classname}};
class {{baseName}}Api implements {{classname}} // An interface is autogenerated
{
{{#operation}}{{#-first}}{{#hasAuthMethods}}{{#authMethods}}{{#isApiKey}}
/**
* Configure API key authorization: {{{name}}}
*/
public function set{{name}}($apiKey)
{
// Retrieve logged in user from $apiKey ...
}
{{/isApiKey}}{{#isOAuth}}
/**
* Configure OAuth2 access token for authorization: {{{name}}}
*/
public function set{{name}}($oauthToken)
{
// Retrieve logged in user from $oauthToken ...
}
{{/isOAuth}}{{/authMethods}}
/**
* Implementation of {{classname}}#{{operationId}}
*/
public function {{operationId}}({{#allParams}}{{#vendorExtensions.x-parameterType}}{{vendorExtensions.x-parameterType}} {{/vendorExtensions.x-parameterType}}${{paramName}}{{^required}} = {{#defaultValue}}'{{{.}}}'{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}})
{
// Implement the operation ...
}
{{/hasAuthMethods}}
{{/-first}}{{/operation}}
// Other operation methods ...
}
```
Step 5: Tag your API implementation:
```yaml
# src/Acme/MyBundle/Resources/services.yml
services:
# ...
acme.my_bundle.api.{{pathPrefix}}:
class: Acme\MyBundle\Api\{{baseName}}Api
tags:
- { name: "{{bundleAlias}}.api", api: "{{pathPrefix}}" }
# ...
```
{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}}
Now you can start using the bundle!
## Documentation for API Endpoints
All URIs are relative to *{{basePath}}*

View File

@ -31,6 +31,17 @@ namespace {{apiPackage}};
*/
interface {{classname}}
{
{{#authMethods}}
/**
* Sets authentication method {{name}}
*
* @param string $value Value of the {{name}} authentication method.
*
* @return void
*/
public function set{{name}}($value);
{{/authMethods}}
{{#operation}}
/**

View File

@ -55,17 +55,38 @@ class {{controllerName}} extends Controller
*/
public function {{operationId}}Action(Request $request)
{
{{#authMethods}}
// Authentication '{{name}}' required
{{#isApiKey}}
{{#isKeyInHeader}}
// Set key with prefix in header
$security{{name}} = $request->headers->get('{{keyParamName}}');
{{/isKeyInHeader}}
{{#isKeyInQuery}}
// Set key with prefix in query string
$security{{name}} = $request->query->get('{{keyParamName}}');
{{/isKeyInQuery}}
{{/isApiKey}}
{{#isBasic}}
// HTTP basic authentication required
$security{{name}} = $request->headers->get('authorization');
{{/isBasic}}
{{#isOAuth}}
// Oauth required
$security{{name}} = $request->headers->get('authorization');
{{/isOAuth}}
{{/authMethods}}
{{#queryParams}}
// Handle query params
${{paramName}} = $request->query->get('{{paramName}}');
${{paramName}} = $this->fromQuery($request->query->get('{{paramName}}'), '{{dataType}}');
{{/queryParams}}
{{#headerParams}}
// Handle header params
${{paramName}} = $request->headers->get('{{paramName}}');
${{paramName}} = $this->fromHeader($request->headers->get('{{paramName}}'), '{{dataType}}');
{{/headerParams}}
{{#pathParams}}
// Handle path params
${{paramName}} = $request->attributes->get('{{paramName}}');
${{paramName}} = $this->fromPath($request->attributes->get('{{paramName}}'), '{{dataType}}');
{{/pathParams}}
{{#formParams}}
{{#isFile}}
@ -74,7 +95,7 @@ class {{controllerName}} extends Controller
{{/isFile}}
{{^isFile}}
// Handle form params
${{paramName}} = $request->request->get('{{paramName}}');
${{paramName}} = $this->fromForm($request->request->get('{{paramName}}'), '{{dataType}}');
{{/isFile}}
{{/formParams}}
{{#bodyParams}}
@ -131,9 +152,15 @@ class {{controllerName}} extends Controller
// Call the API interface
try {
$handler = $this->getApiHandler();
{{#authMethods}}
// Set authentication method '{{name}}'
$handler->set{{name}}($security{{name}});
{{/authMethods}}
{{#returnType}}
// Expecting a return value (exception otherwise)
$result = $this->getApiHandler()->{{operationId}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
$result = $handler->{{operationId}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
{{#responses}}
{{^vendorExtensions.x-symfonyExceptionSimple}}
@ -148,7 +175,7 @@ class {{controllerName}} extends Controller
{{/returnType}}
{{^returnType}}
// No return type expected; return empty response
$this->getApiHandler()->{{operationId}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
$handler->{{operationId}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
return new Response('', 204);
{{/returnType}}
{{#responses}}

View File

@ -1,4 +1,4 @@
# {{invokerPackage}}\{{classname}}{{#description}}
# {{apiPackage}}\{{classname}}{{#description}}
{{description}}{{/description}}
All URIs are relative to *{{basePath}}*
@ -9,41 +9,66 @@ Method | HTTP request | Description
{{/operation}}{{/operations}}
{{#operations}}
## Service Declaration
```yaml
# src/Acme/MyBundle/Resources/services.yml
services:
# ...
acme.my_bundle.api.{{pathPrefix}}:
class: Acme\MyBundle\Api\{{baseName}}Api
tags:
- { name: "{{bundleAlias}}.api", api: "{{pathPrefix}}" }
# ...
```
{{#operation}}
# **{{{operationId}}}**
## **{{{operationId}}}**
> {{#returnType}}{{{returnType}}} {{/returnType}}{{{operationId}}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}})
{{{summary}}}{{#notes}}
{{{notes}}}{{/notes}}
### Example
### Example Implementation
```php
<?php
require_once(__DIR__ . '/vendor/autoload.php');
{{#hasAuthMethods}}{{#authMethods}}{{#isBasic}}
// Configure HTTP basic authorization: {{{name}}}
{{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setUsername('YOUR_USERNAME');
{{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setPassword('YOUR_PASSWORD');{{/isBasic}}{{#isApiKey}}
// Configure API key authorization: {{{name}}}
{{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setApiKey('{{{keyParamName}}}', 'YOUR_API_KEY');
// Uncomment below to setup prefix (e.g. Bearer) for API key, if needed
// {{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setApiKeyPrefix('{{{keyParamName}}}', 'Bearer');{{/isApiKey}}{{#isOAuth}}
// Configure OAuth2 access token for authorization: {{{name}}}
{{{invokerPackage}}}\Configuration::getDefaultConfiguration()->setAccessToken('YOUR_ACCESS_TOKEN');{{/isOAuth}}{{/authMethods}}
{{/hasAuthMethods}}
// src/Acme/MyBundle/Api/{{classname}}.php
$api_instance = new {{invokerPackage}}\Api\{{classname}}();
{{#allParams}}${{paramName}} = {{{example}}}; // {{{dataType}}} | {{{description}}}
{{/allParams}}
namespace Acme\MyBundle\Api;
try {
{{#returnType}}$result = {{/returnType}}$api_instance->{{{operationId}}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}}
print_r($result);{{/returnType}}
} catch (Exception $e) {
echo 'Exception when calling {{classname}}->{{operationId}}: ', $e->getMessage(), PHP_EOL;
use {{apiPackage}}\{{classname}};
class {{baseName}}Api implements {{classname}}
{
{{#authMethods}}{{#isApiKey}}
/**
* Configure API key authorization: {{{name}}}
*/
public function set{{name}}($apiKey)
{
// Retrieve logged in user from $apiKey ...
}
{{/isApiKey}}{{#isOAuth}}
/**
* Configure OAuth2 access token for authorization: {{{name}}}
*/
public function set{{name}}($oauthToken)
{
// Retrieve logged in user from $oauthToken ...
}
{{/isOAuth}}{{/authMethods}}
// ...
/**
* Implementation of {{classname}}#{{operationId}}
*/
public function {{operationId}}({{#allParams}}{{#vendorExtensions.x-parameterType}}{{vendorExtensions.x-parameterType}} {{/vendorExtensions.x-parameterType}}${{paramName}}{{^required}} = {{#defaultValue}}'{{{.}}}'{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}})
{
// Implement the operation ...
}
// ...
}
?>
```
### Parameters

View File

@ -13,11 +13,14 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}imple
* @var array[]
*/
protected static $_attributes = [{{#vars}}
'{{name}}' => ['{{baseName}}', '{{{datatype}}}', {{#dataFormat}}'{{{dataFormat}}}'{{/dataFormat}}{{^dataFormat}}null{{/dataFormat}}, '{{setter}}', '{{getter}}'],{{/vars}}
'{{name}}' => ['{{baseName}}', '{{{vendorExtensions.x-fullType}}}', {{#dataFormat}}'{{{dataFormat}}}'{{/dataFormat}}{{^dataFormat}}null{{/dataFormat}}, '{{setter}}', '{{getter}}'],{{/vars}}
];
{{#vars}}{{#isEnum}}{{#allowableValues}}{{#enumVars}}
const {{enumName}}_{{{name}}} = {{{value}}};
{{/enumVars}}{{/allowableValues}}{{/isEnum}}{{/vars}}
{{#vars}}{{#isEnum}}
/**
* Allowed values of {{name}}
*/{{#allowableValues}}{{#enumVars}}
const {{enumName}}_{{{name}}} = {{{value}}};{{/enumVars}}{{/allowableValues}}{{/isEnum}}{{/vars}}
{{#vars}}{{#isEnum}}
/**
@ -33,7 +36,10 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}imple
}
{{/isEnum}}{{/vars}}
{{#vars}}
/**
/**{{#description}}
* {{description}}
*
{{/description}}
* @var {{{datatype}}}{{^required}}|null{{/required}}
*/
protected ${{name}};
@ -237,6 +243,7 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}imple
/**
* Gets {{name}}.
*
* @return {{{datatype}}}{{^required}}|null{{/required}}
*/
public function {{getter}}()
@ -246,7 +253,9 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}imple
/**
* Sets {{name}}.
*
* @param {{{datatype}}}{{^required}}|null{{/required}} ${{name}}{{#description}} {{{description}}}{{/description}}
*
* @return $this
*/
public function {{setter}}({{#vendorExtensions.x-typeAnnotation}}{{vendorExtensions.x-typeAnnotation}} {{/vendorExtensions.x-typeAnnotation}}${{name}}{{^required}} = null{{/required}})

View File

@ -0,0 +1,59 @@
package io.swagger.codegen.options;
import com.google.common.collect.ImmutableMap;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.languages.SymfonyServerCodegen;
import io.swagger.codegen.languages.SymfonyServerCodegen;
import java.util.Map;
public class SymfonyServerOptionsProvider implements OptionsProvider {
public static final String BUNDLE_NAME_VALUE = "AcmeSwagger";
public static final String MODEL_PACKAGE_VALUE = "package";
public static final String API_PACKAGE_VALUE = "apiPackage";
public static final String SORT_PARAMS_VALUE = "false";
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final String VARIABLE_NAMING_CONVENTION_VALUE = "snake_case";
public static final String INVOKER_PACKAGE_VALUE = "Acme\\Bundle\\SwaggerBundle";
public static final String PACKAGE_PATH_VALUE = "SwaggerClient-php";
public static final String SRC_BASE_PATH_VALUE = "libPhp";
public static final String COMPOSER_VENDOR_NAME_VALUE = "swaggerPhp";
public static final String COMPOSER_PROJECT_NAME_VALUE = "swagger-client-php";
public static final String GIT_USER_ID_VALUE = "gitSwaggerPhp";
public static final String GIT_REPO_ID_VALUE = "git-swagger-client-php";
public static final String ARTIFACT_VERSION_VALUE = "1.0.0-SNAPSHOT";
public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false";
@Override
public String getLanguage() {
return "php-symfony";
}
@Override
public Map<String, String> createOptions() {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
return builder.put(CodegenConstants.MODEL_PACKAGE, MODEL_PACKAGE_VALUE)
.put(SymfonyServerCodegen.BUNDLE_NAME, BUNDLE_NAME_VALUE)
.put(CodegenConstants.API_PACKAGE, API_PACKAGE_VALUE)
.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(SymfonyServerCodegen.VARIABLE_NAMING_CONVENTION, VARIABLE_NAMING_CONVENTION_VALUE)
.put(CodegenConstants.INVOKER_PACKAGE, INVOKER_PACKAGE_VALUE)
.put(SymfonyServerCodegen.PACKAGE_PATH, PACKAGE_PATH_VALUE)
.put(SymfonyServerCodegen.SRC_BASE_PATH, SRC_BASE_PATH_VALUE)
.put(SymfonyServerCodegen.COMPOSER_VENDOR_NAME, COMPOSER_VENDOR_NAME_VALUE)
.put(CodegenConstants.GIT_USER_ID, GIT_USER_ID_VALUE)
.put(SymfonyServerCodegen.COMPOSER_PROJECT_NAME, COMPOSER_PROJECT_NAME_VALUE)
.put(CodegenConstants.GIT_REPO_ID, GIT_REPO_ID_VALUE)
.put(CodegenConstants.ARTIFACT_VERSION, ARTIFACT_VERSION_VALUE)
.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "true")
.put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE)
.build();
}
@Override
public boolean isServer() {
return true;
}
}

View File

@ -0,0 +1,57 @@
package io.swagger.codegen.phpsymfony;
import io.swagger.codegen.AbstractOptionsTest;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.languages.AbstractPhpCodegen;
import io.swagger.codegen.languages.SymfonyServerCodegen;
import io.swagger.codegen.options.SymfonyServerOptionsProvider;
import mockit.Expectations;
import mockit.Tested;
public class PhpSymfonyServerOptionsTest extends AbstractOptionsTest {
@Tested
private SymfonyServerCodegen symfonyCodegen;
public PhpSymfonyServerOptionsTest() {
super(new SymfonyServerOptionsProvider());
}
@Override
protected CodegenConfig getCodegenConfig() {
return symfonyCodegen;
}
@SuppressWarnings("unused")
@Override
protected void setExpectations() {
new Expectations(symfonyCodegen) {{
symfonyCodegen.setBundleName(SymfonyServerOptionsProvider.BUNDLE_NAME_VALUE);
times = 1;
symfonyCodegen.setModelPackage(SymfonyServerOptionsProvider.MODEL_PACKAGE_VALUE);
times = 1;
symfonyCodegen.setApiPackage(SymfonyServerOptionsProvider.API_PACKAGE_VALUE);
times = 1;
symfonyCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(SymfonyServerOptionsProvider.SORT_PARAMS_VALUE));
times = 1;
symfonyCodegen.setParameterNamingConvention(SymfonyServerOptionsProvider.VARIABLE_NAMING_CONVENTION_VALUE);
times = 1;
symfonyCodegen.setInvokerPackage(SymfonyServerOptionsProvider.INVOKER_PACKAGE_VALUE);
times = 1;
symfonyCodegen.setPackagePath(SymfonyServerOptionsProvider.PACKAGE_PATH_VALUE);
times = 1;
symfonyCodegen.setSrcBasePath(SymfonyServerOptionsProvider.SRC_BASE_PATH_VALUE);
times = 1;
symfonyCodegen.setComposerVendorName(SymfonyServerOptionsProvider.COMPOSER_VENDOR_NAME_VALUE);
times = 1;
symfonyCodegen.setGitUserId(SymfonyServerOptionsProvider.GIT_USER_ID_VALUE);
times = 1;
symfonyCodegen.setComposerProjectName(SymfonyServerOptionsProvider.COMPOSER_PROJECT_NAME_VALUE);
times = 1;
symfonyCodegen.setGitRepoId(SymfonyServerOptionsProvider.GIT_REPO_ID_VALUE);
times = 1;
symfonyCodegen.setArtifactVersion(SymfonyServerOptionsProvider.ARTIFACT_VERSION_VALUE);
times = 1;
}};
}
}