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

View File

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

View File

@ -34,83 +34,209 @@ use Symfony\Component\HttpKernel\Exception\HttpException;
class Controller extends BaseController class Controller extends BaseController
{ {
/** /**
* This will return a response with code 400. Usage example: * This will return a response with code 400. Usage example:
* * return $this->createBadRequestResponse('Unable to access this page!');
* return $this->createBadRequestResponse('Unable to access this page!'); *
* * @param string $message A message
* @param string $message A message *
* * @return Response
* @return Response */
*/ public function createBadRequestResponse($message = 'Bad Request.')
public function createBadRequestResponse($message = 'Bad Request.') {
{ return new Response($message, 400);
return new Response($message, 400); }
}
/** /**
* This will return an error response. Usage example: * This will return an error response. Usage example:
* * return $this->createErrorResponse(new UnauthorizedHttpException());
* return $this->createErrorResponse(new UnauthorizedHttpException()); *
* * @param HttpException $exception An HTTP exception
* @param HttpException $exception An HTTP exception *
* * @return Response
* @return Response */
*/ public function createErrorResponse(HttpException $exception)
public function createErrorResponse(HttpException $exception) {
{ $statusCode = $exception->getStatusCode();
$statusCode = $exception->getStatusCode(); $headers = array_merge($exception->getHeaders(), ['Content-Type' => 'application/json']);
$headers = array_merge($exception->getHeaders(), ['Content-Type' => 'application/json']);
$json = $this->exceptionToArray($exception); $json = $this->exceptionToArray($exception);
$json["statusCode"] = $statusCode; $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. * Serializes data to a given type format.
* *
* @param mixed $data The data to serialize. * @param mixed $data The data to serialize.
* @param string $class The source data class. * @param string $class The source data class.
* @param string $format The target serialization format. * @param string $format The target serialization format.
* @return string A serialized data string. *
*/ * @return string A serialized data string.
public function serialize($data, $format) */
{ public function serialize($data, $format)
return $this->get('{{bundleAlias}}.model.model_serializer')->serialize($data, $format); {
} return $this->get('{{bundleAlias}}.model.model_serializer')->serialize($data, $format);
}
/** /**
* Deserializes data from a given type format. * Deserializes data from a given type format.
* *
* @param string $data The data to deserialize. * @param string $data The data to deserialize.
* @param string $class The target data class. * @param string $class The target data class.
* @param string $format The source serialization format. * @param string $format The source serialization format.
* @return mixed A deserialized data. *
*/ * @return mixed A deserialized data.
public function deserialize($data, $class, $format) */
{ public function deserialize($data, $class, $format)
return $this->get('{{bundleAlias}}.model.model_serializer')->deserialize($data, $class, $format); {
} return $this->get('{{bundleAlias}}.model.model_serializer')->deserialize($data, $class, $format);
}
/** /**
* Converts an exception to a serializable array. * Decodes a string value.
* *
* @param \Exception|null $exception * @param string $string The string value to decode.
* * @param string $dataType The data type of the parameter.
* @return array *
*/ * @return mixed The decoded value.
private function exceptionToArray(\Exception $exception = null) */
{ public function fromString($string, $dataType)
if (null === $exception) { {
return null; if ($dataType === 'integer' || $dataType === 'number') {
} return $this->toNumber($string);
}
if ($dataType === 'bool') {
return $this->toBoolean($string);
}
if ($dataType === '\DateTime') {
return $this->toDateTime($string);
}
return [ return $string;
"message" => $exception->getMessage(), }
"type" => get_class($exception),
"previous" => $this->exceptionToArray($exception->getPrevious()), /**
]; * 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}}} {{{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}} - API version: {{appVersion}}
{{#artifactVersion}} {{#artifactVersion}}
@ -22,7 +22,6 @@ For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
PHP 5.4.0 and later PHP 5.4.0 and later
## Installation & Usage ## Installation & Usage
### Composer
To install the bindings via [Composer](http://getcomposer.org/), add the following to `composer.json`: 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` Then run `composer install`
### Manual Installation
Download the files and include `autoload.php`:
```php
require_once('/path/to/{{packagePath}}/autoload.php');
```
## Tests ## Tests
@ -59,39 +51,93 @@ composer install
./vendor/bin/phpunit ./vendor/bin/phpunit
``` ```
## Getting Started ## 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
<?php <?php
require_once(__DIR__ . '/vendor/autoload.php'); // app/AppKernel.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}}
$api_instance = new {{invokerPackage}}\Api\{{classname}}(); public function registerBundles()
{{#allParams}}${{paramName}} = {{{example}}}; // {{{dataType}}} | {{{description}}} {
{{/allParams}} $bundles = array(
// ...
try { new {{invokerPackage}}\{{bundleClassName}}(),
{{#returnType}}$result = {{/returnType}}$api_instance->{{{operationId}}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} // ...
print_r($result);{{/returnType}} );
} catch (Exception $e) {
echo 'Exception when calling {{classname}}->{{operationId}}: ', $e->getMessage(), PHP_EOL;
} }
{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}}
?>
``` ```
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 ## Documentation for API Endpoints
All URIs are relative to *{{basePath}}* All URIs are relative to *{{basePath}}*

View File

@ -31,6 +31,17 @@ namespace {{apiPackage}};
*/ */
interface {{classname}} 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}} {{#operation}}
/** /**

View File

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

View File

@ -1,4 +1,4 @@
# {{invokerPackage}}\{{classname}}{{#description}} # {{apiPackage}}\{{classname}}{{#description}}
{{description}}{{/description}} {{description}}{{/description}}
All URIs are relative to *{{basePath}}* All URIs are relative to *{{basePath}}*
@ -9,41 +9,66 @@ Method | HTTP request | Description
{{/operation}}{{/operations}} {{/operation}}{{/operations}}
{{#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}} {{#operation}}
# **{{{operationId}}}** ## **{{{operationId}}}**
> {{#returnType}}{{{returnType}}} {{/returnType}}{{{operationId}}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) > {{#returnType}}{{{returnType}}} {{/returnType}}{{{operationId}}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}})
{{{summary}}}{{#notes}} {{{summary}}}{{#notes}}
{{{notes}}}{{/notes}} {{{notes}}}{{/notes}}
### Example ### Example Implementation
```php ```php
<?php <?php
require_once(__DIR__ . '/vendor/autoload.php'); // src/Acme/MyBundle/Api/{{classname}}.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}}
$api_instance = new {{invokerPackage}}\Api\{{classname}}(); namespace Acme\MyBundle\Api;
{{#allParams}}${{paramName}} = {{{example}}}; // {{{dataType}}} | {{{description}}}
{{/allParams}}
try { use {{apiPackage}}\{{classname}};
{{#returnType}}$result = {{/returnType}}$api_instance->{{{operationId}}}({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}}
print_r($result);{{/returnType}} class {{baseName}}Api implements {{classname}}
} catch (Exception $e) { {
echo 'Exception when calling {{classname}}->{{operationId}}: ', $e->getMessage(), PHP_EOL; {{#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 ### Parameters

View File

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