mirror of
https://github.com/retailcrm/NelmioApiDocBundle.git
synced 2025-02-02 15:51:48 +03:00
Swagger support:
Unified data types [actualType and subType] Updated tests. JMS parsing fixes; updated {Validator,FormType}Parser, FOSRestHandler, and AbstractFormatter, and updated DataTypes enum. Modified dataType checking. Updated tests. Updated DataTypes enum. Quick fix and added doc comments. CS fixes. Refactored FormTypeParser to produce nested parameters. Updated tests accordingly. Logical and CS fixes. Sub-forms and more tests. Logical and CS fixes. Swagger support: created formatter. Configuration and resourcePath logic update. ApiDoc annotation update. Updated formatter and added tests. Parameter formatting. Added tests for SwaggerFormatter. Added option in annotation, and the corresponding logic for parsing the supplied values and processing them in the formatter. Routing update. Updated tests. Removed unused dependency and updated doc comments. Renamed 'responseModels' to 'responseMap' Update the resource filtering and formatting of response messages. Updated check for 200 response model. Ignore data_class and always use form-type to avoid conflicts. Fix: add 'type' even if '' is specified. Refactored responseMap; added parsedResponseMap. Added tests and updated some. Fix: add 'type' even if '' is specified. Initial commit of command. Finished logic for dumping files. Updated doc comment; added license and added more meaningful class comment. Array of models support.
This commit is contained in:
parent
c03d35bee4
commit
6f85aed33c
@ -135,6 +135,21 @@ class ApiDoc
|
||||
*/
|
||||
private $statusCodes = array();
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $resourceDescription = null;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $responseMap = array();
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $parsedResponseMap = array();
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
@ -241,6 +256,17 @@ class ApiDoc
|
||||
if (isset($data['https'])) {
|
||||
$this->https = $data['https'];
|
||||
}
|
||||
|
||||
if (isset($data['resourceDescription'])) {
|
||||
$this->resourceDescription = $data['resourceDescription'];
|
||||
}
|
||||
|
||||
if (isset($data['responseMap'])) {
|
||||
$this->responseMap = $data['responseMap'];
|
||||
if (isset($this->responseMap[200])) {
|
||||
$this->output = $this->responseMap[200];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -606,6 +632,10 @@ class ApiDoc
|
||||
$data['tags'] = $tags;
|
||||
}
|
||||
|
||||
if ($resourceDescription = $this->resourceDescription) {
|
||||
$data['resourceDescription'] = $resourceDescription;
|
||||
}
|
||||
|
||||
$data['https'] = $this->https;
|
||||
$data['authentication'] = $this->authentication;
|
||||
$data['authenticationRoles'] = $this->authenticationRoles;
|
||||
@ -613,4 +643,45 @@ class ApiDoc
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|string
|
||||
*/
|
||||
public function getResourceDescription()
|
||||
{
|
||||
return $this->resourceDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getResponseMap()
|
||||
{
|
||||
if (!isset($this->responseMap[200]) && null !== $this->output) {
|
||||
$this->responseMap[200] = $this->output;
|
||||
}
|
||||
|
||||
return $this->responseMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getParsedResponseMap()
|
||||
{
|
||||
return $this->parsedResponseMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $model
|
||||
* @param $type
|
||||
* @param int $statusCode
|
||||
*/
|
||||
public function setResponseForStatusCode($model, $type, $statusCode = 200)
|
||||
{
|
||||
$this->parsedResponseMap[$statusCode] = array('type' => $type, 'model' => $model);
|
||||
if ($statusCode == 200 && $this->response !== $model) {
|
||||
$this->response = $model;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
132
Command/SwaggerDumpCommand.php
Normal file
132
Command/SwaggerDumpCommand.php
Normal file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the NelmioApiDocBundle.
|
||||
*
|
||||
* (c) Nelmio <hello@nelm.io>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nelmio\ApiDocBundle\Command;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Filesystem\Exception\IOException;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
|
||||
/**
|
||||
* Symfony2 command to dump Swagger-compliant JSON files.
|
||||
*
|
||||
* @author Bez Hermoso <bez@activelamp.com>
|
||||
*/
|
||||
class SwaggerDumpCommand extends ContainerAwareCommand
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setDescription('Dump Swagger-compliant JSON files.')
|
||||
->addOption('resource', '', InputOption::VALUE_OPTIONAL, 'A specific resource API declaration to dump.')
|
||||
->addOption('all', '', InputOption::VALUE_NONE, 'Dump resource list and all API declarations.')
|
||||
->addOption('list-only', '', InputOption::VALUE_NONE, 'Dump resource list only.')
|
||||
->addArgument('destination', InputOption::VALUE_REQUIRED, 'Directory to dump JSON files in.', null)
|
||||
->setName('api:swagger:dump');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$container = $this->getContainer();
|
||||
$destination = $input->getArgument('destination');
|
||||
|
||||
$rootDir = $container->get('kernel')->getRootDir();
|
||||
$rootDir = $rootDir . '/..';
|
||||
|
||||
if (null === $destination) {
|
||||
$destination = realpath($rootDir . '/' . $destination);
|
||||
}
|
||||
|
||||
$fs = new Filesystem();
|
||||
|
||||
if (!$fs->exists($destination)) {
|
||||
$fs->mkdir($destination);
|
||||
}
|
||||
|
||||
$destination = realpath($destination);
|
||||
|
||||
if ($input->getOption('all') && $input->getOption('resource')) {
|
||||
throw new \RuntimeException('Cannot selectively dump a resource with the --all flag.');
|
||||
}
|
||||
|
||||
if ($input->getOption('list-only') && $input->getOption('resource')) {
|
||||
throw new \RuntimeException('Cannot selectively dump a resource with the --list-only flag.');
|
||||
}
|
||||
|
||||
if ($input->getOption('all') && $input->getOption('list-only')) {
|
||||
throw new \RuntimeException('Cannot selectively dump resource list with the --all flag.');
|
||||
}
|
||||
|
||||
$output->writeln('');
|
||||
$output->writeln('Reading annotations...');
|
||||
$extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor');
|
||||
$data = $extractor->all();
|
||||
|
||||
if ($input->getOption('list-only')) {
|
||||
$this->dumpResourceList($destination, $data, $output);
|
||||
}
|
||||
|
||||
if (false != ($resource = $input->getOption('resource'))) {
|
||||
$this->dumpApiDeclaration($destination, $data, $resource, $output);
|
||||
}
|
||||
|
||||
if ($input->getOption('all')) {
|
||||
$formatter = $container->get('nelmio_api_doc.formatter.swagger_formatter');
|
||||
$this->dumpResourceList($destination, $data, $output);
|
||||
$list = $formatter->format($data);
|
||||
foreach ($list['apis'] as $api) {
|
||||
$this->dumpApiDeclaration($destination, $data, substr($api['path'], 1), $output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function dumpResourceList($destination, array $data, OutputInterface $output)
|
||||
{
|
||||
$container = $this->getContainer();
|
||||
$formatter = $container->get('nelmio_api_doc.formatter.swagger_formatter');
|
||||
|
||||
$list = $formatter->format($data);
|
||||
|
||||
$fs = new Filesystem();
|
||||
$path = $destination . '/api-docs.json';
|
||||
|
||||
$string = sprintf('<comment>Dump resource list to %s: </comment>', $path);
|
||||
try {
|
||||
$fs->dumpFile($path, json_encode($list));
|
||||
} catch (IOException $e) {
|
||||
$output->writeln($string . ' <error>NOT OK</error>');
|
||||
}
|
||||
$output->writeln($string . '<info>OK</info>');
|
||||
}
|
||||
|
||||
protected function dumpApiDeclaration($destination, array $data, $resource, OutputInterface $output)
|
||||
{
|
||||
$container = $this->getContainer();
|
||||
$formatter = $container->get('nelmio_api_doc.formatter.swagger_formatter');
|
||||
|
||||
$list = $formatter->format($data, '/' . $resource);
|
||||
|
||||
$fs = new Filesystem();
|
||||
$path = sprintf($destination . '/%s.json', $resource);
|
||||
|
||||
$string = sprintf('<comment>Dump API declaration to %s: </comment>', $path);
|
||||
try {
|
||||
$fs->dumpFile($path, json_encode($list));
|
||||
} catch (IOException $e) {
|
||||
$output->writeln($string . ' <error>NOT OK</error>');
|
||||
}
|
||||
$output->writeln($string . '<info>OK</info>');
|
||||
}
|
||||
}
|
@ -12,6 +12,8 @@
|
||||
namespace Nelmio\ApiDocBundle\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class ApiDocController extends Controller
|
||||
@ -23,4 +25,12 @@ class ApiDocController extends Controller
|
||||
|
||||
return new Response($htmlContent, 200, array('Content-Type' => 'text/html'));
|
||||
}
|
||||
|
||||
public function swaggerAction(Request $request, $resource = null)
|
||||
{
|
||||
$docs = $this->get('nelmio_api_doc.extractor.api_doc_extractor')->all();
|
||||
$formatter = $this->get('nelmio_api_doc.formatter.swagger_formatter');
|
||||
$spec = $formatter->format($docs, $resource ? '/' . $resource : null);
|
||||
return new JsonResponse($spec);
|
||||
}
|
||||
}
|
||||
|
@ -99,6 +99,25 @@ class Configuration implements ConfigurationInterface
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->arrayNode('swagger')
|
||||
->addDefaultsIfNotSet()
|
||||
->children()
|
||||
->scalarNode('api_base_path')->defaultValue('/api')->end()
|
||||
->scalarNode('swagger_version')->defaultValue('1.2')->end()
|
||||
->scalarNode('api_version')->defaultValue('0.1')->end()
|
||||
->arrayNode('info')
|
||||
->addDefaultsIfNotSet()
|
||||
->children()
|
||||
->scalarNode('title')->defaultValue('Symfony2')->end()
|
||||
->scalarNode('description')->defaultValue('My awesome Symfony2 app!')->end()
|
||||
->scalarNode('TermsOfServiceUrl')->defaultValue(null)->end()
|
||||
->scalarNode('contact')->defaultValue(null)->end()
|
||||
->scalarNode('license')->defaultValue(null)->end()
|
||||
->scalarNode('licenseUrl')->defaultValue(null)->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end();
|
||||
|
||||
return $treeBuilder;
|
||||
|
@ -57,6 +57,12 @@ class NelmioApiDocExtension extends Extension
|
||||
if (!interface_exists('\Symfony\Component\Validator\MetadataFactoryInterface')) {
|
||||
$container->setParameter('nelmio_api_doc.parser.validation_parser.class', 'Nelmio\ApiDocBundle\Parser\ValidationParserLegacy');
|
||||
}
|
||||
|
||||
$container->setParameter('nelmio_api_doc.swagger.base_path', $config['swagger']['api_base_path']);
|
||||
$container->setParameter('nelmio_api_doc.swagger.swagger_version', $config['swagger']['swagger_version']);
|
||||
$container->setParameter('nelmio_api_doc.swagger.api_version', $config['swagger']['api_version']);
|
||||
$container->setParameter('nelmio_api_doc.swagger.info', $config['swagger']['info']);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
43
DependencyInjection/SwaggerConfigCompilerPass.php
Normal file
43
DependencyInjection/SwaggerConfigCompilerPass.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nelmio\ApiDocBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
|
||||
/**
|
||||
* Compiler pass that configures the SwaggerFormatter instance.
|
||||
*
|
||||
* @author Bez Hermoso <bez@activelamp.com>
|
||||
*/
|
||||
class SwaggerConfigCompilerPass implements CompilerPassInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* You can modify the container here before it is dumped to PHP code.
|
||||
*
|
||||
* @param ContainerBuilder $container
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$formatter = $container->getDefinition('nelmio_api_doc.formatter.swagger_formatter');
|
||||
|
||||
$formatter->addMethodCall('setBasePath', array($container->getParameter('nelmio_api_doc.swagger.base_path')));
|
||||
$formatter->addMethodCall('setApiVersion', array($container->getParameter('nelmio_api_doc.swagger.api_version')));
|
||||
$formatter->addMethodCall('setSwaggerVersion', array($container->getParameter('nelmio_api_doc.swagger.swagger_version')));
|
||||
$formatter->addMethodCall('setInfo', array($container->getParameter('nelmio_api_doc.swagger.info')));
|
||||
|
||||
}
|
||||
}
|
@ -317,6 +317,36 @@ class ApiDocExtractor
|
||||
$response = $this->generateHumanReadableTypes($response);
|
||||
|
||||
$annotation->setResponse($response);
|
||||
$annotation->setResponseForStatusCode($response, $normalizedOutput, 200);
|
||||
}
|
||||
|
||||
if (count($annotation->getResponseMap()) > 0) {
|
||||
|
||||
foreach ($annotation->getResponseMap() as $code => $modelName) {
|
||||
|
||||
if ('200' === (string) $code && isset($modelName['type']) && isset($modelName['model'])) {
|
||||
/*
|
||||
* Model was already parsed as the default `output` for this ApiDoc.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
$normalizedModel = $this->normalizeClassParameter($modelName);
|
||||
|
||||
$parameters = array();
|
||||
foreach ($this->getParsers($normalizedModel) as $parser) {
|
||||
if ($parser->supports($normalizedModel)) {
|
||||
$parameters = $this->mergeParameters($parameters, $parser->parse($normalizedModel));
|
||||
}
|
||||
}
|
||||
|
||||
$parameters = $this->clearClasses($parameters);
|
||||
$parameters = $this->generateHumanReadableTypes($parameters);
|
||||
|
||||
$annotation->setResponseForStatusCode($parameters, $normalizedModel, $code);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $annotation;
|
||||
@ -462,11 +492,15 @@ class ApiDocExtractor
|
||||
protected function generateHumanReadableType($actualType, $subType)
|
||||
{
|
||||
if ($actualType == DataTypes::MODEL) {
|
||||
$parts = explode('\\', $subType);
|
||||
|
||||
if (class_exists($subType)) {
|
||||
$parts = explode('\\', $subType);
|
||||
return sprintf('object (%s)', end($parts));
|
||||
}
|
||||
|
||||
return sprintf('object (%s)', $subType);
|
||||
}
|
||||
|
||||
if ($actualType == DataTypes::COLLECTION) {
|
||||
|
||||
if (DataTypes::isPrimitive($subType)) {
|
||||
@ -475,7 +509,6 @@ class ApiDocExtractor
|
||||
|
||||
if (class_exists($subType)) {
|
||||
$parts = explode('\\', $subType);
|
||||
|
||||
return sprintf('array of objects (%s)', end($parts));
|
||||
}
|
||||
|
||||
|
595
Formatter/SwaggerFormatter.php
Normal file
595
Formatter/SwaggerFormatter.php
Normal file
@ -0,0 +1,595 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the NelmioApiDocBundle.
|
||||
*
|
||||
* (c) Nelmio <hello@nelm.io>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nelmio\ApiDocBundle\Formatter;
|
||||
|
||||
|
||||
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
||||
use Nelmio\ApiDocBundle\DataTypes;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Router;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
|
||||
/**
|
||||
* Produces Swagger-compliant resource lists and API declarations as defined here:
|
||||
* https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md
|
||||
*
|
||||
* This formatter produces an array. Therefore output still needs to be `json_encode`d before passing on as HTTP response.
|
||||
*
|
||||
* @author Bezalel Hermoso <bezalelhermoso@gmail.com>
|
||||
*/
|
||||
class SwaggerFormatter implements FormatterInterface
|
||||
{
|
||||
protected $basePath;
|
||||
|
||||
protected $apiVersion;
|
||||
|
||||
protected $swaggerVersion;
|
||||
|
||||
protected $info = array();
|
||||
|
||||
protected $typeMap = array(
|
||||
DataTypes::INTEGER => 'integer',
|
||||
DataTypes::FLOAT => 'number',
|
||||
DataTypes::STRING => 'string',
|
||||
DataTypes::BOOLEAN => 'boolean',
|
||||
DataTypes::FILE => 'string',
|
||||
DataTypes::DATE => 'string',
|
||||
DataTypes::DATETIME => 'string',
|
||||
);
|
||||
|
||||
protected $formatMap = array(
|
||||
DataTypes::INTEGER => 'int32',
|
||||
DataTypes::FLOAT => 'float',
|
||||
DataTypes::FILE => 'byte',
|
||||
DataTypes::DATE => 'date',
|
||||
DataTypes::DATETIME => 'date-time',
|
||||
);
|
||||
|
||||
/**
|
||||
* Format a collection of documentation data.
|
||||
*
|
||||
* If resource is provided, an API declaration for that resource is produced. Otherwise, a resource listing is returned.
|
||||
*
|
||||
* @param array|ApiDoc[] $collection
|
||||
* @param null|string $resource
|
||||
* @return string|array
|
||||
*/
|
||||
public function format(array $collection, $resource = null)
|
||||
{
|
||||
if ($resource === null) {
|
||||
return $this->produceResourceListing($collection);
|
||||
} else {
|
||||
return $this->produceApiDeclaration($collection, $resource);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the collection into Swagger-compliant output.
|
||||
*
|
||||
* @param array $collection
|
||||
* @return array
|
||||
*/
|
||||
public function produceResourceListing(array $collection)
|
||||
{
|
||||
$resourceList = array(
|
||||
'swaggerVersion' => (string) $this->swaggerVersion,
|
||||
'apis' => array(),
|
||||
'apiVersion' => (string) $this->apiVersion,
|
||||
'info' => $this->getInfo(),
|
||||
'authorizations' => $this->getAuthorizations(),
|
||||
);
|
||||
|
||||
$apis = &$resourceList['apis'];
|
||||
|
||||
foreach ($collection as $item) {
|
||||
|
||||
/** @var $apiDoc ApiDoc */
|
||||
$apiDoc = $item['annotation'];
|
||||
$resource = $item['resource'];
|
||||
|
||||
if (!$apiDoc->isResource()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$subPath = $this->stripBasePath($resource);
|
||||
$normalizedName = $this->normalizeResourcePath($subPath);
|
||||
|
||||
$apis[] = array(
|
||||
'path' => '/' . $normalizedName,
|
||||
'description' => $apiDoc->getResourceDescription(),
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
return $resourceList;
|
||||
}
|
||||
|
||||
protected function getAuthorizations()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getInfo()
|
||||
{
|
||||
return $this->info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format documentation data for one route.
|
||||
*
|
||||
* @param ApiDoc $annotation
|
||||
* return string|array
|
||||
*/
|
||||
public function formatOne(ApiDoc $annotation)
|
||||
{
|
||||
// TODO: Implement formatOne() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats collection to produce a Swagger-compliant API declaration for the given resource.
|
||||
*
|
||||
* @param array $collection
|
||||
* @param string $resource
|
||||
* @return array
|
||||
*/
|
||||
private function produceApiDeclaration(array $collection, $resource)
|
||||
{
|
||||
|
||||
$apiDeclaration = array(
|
||||
'swaggerVersion' => (string) $this->swaggerVersion,
|
||||
'apiVersion' => (string) $this->apiVersion,
|
||||
'basePath' => $this->basePath,
|
||||
'resourcePath' => $resource,
|
||||
'apis' => array(),
|
||||
'models' => array(),
|
||||
'produces' => array(),
|
||||
'consumes' => array(),
|
||||
'authorizations' => array(),
|
||||
);
|
||||
|
||||
$main = null;
|
||||
|
||||
$apiBag = array();
|
||||
|
||||
$models = array();
|
||||
|
||||
|
||||
foreach ($collection as $item) {
|
||||
|
||||
/** @var $apiDoc ApiDoc */
|
||||
$apiDoc = $item['annotation'];
|
||||
$itemResource = $this->stripBasePath($item['resource']);
|
||||
|
||||
$route = $apiDoc->getRoute();
|
||||
|
||||
$itemResource = $this->normalizeResourcePath($itemResource);
|
||||
|
||||
if ('/' . $itemResource !== $resource) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$compiled = $route->compile();
|
||||
|
||||
$path = $this->stripBasePath($route->getPath());
|
||||
|
||||
if (!isset($apiBag[$path])) {
|
||||
$apiBag[$path] = array();
|
||||
}
|
||||
|
||||
$parameters = array();
|
||||
$responseMessages = array();
|
||||
|
||||
foreach ($compiled->getPathVariables() as $paramValue) {
|
||||
$parameter = array(
|
||||
'paramType' => 'path',
|
||||
'name' => $paramValue,
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
);
|
||||
|
||||
if ($paramValue === '_format' && false != ($req = $route->getRequirement('_format'))) {
|
||||
$parameter['enum'] = explode('|', $req);
|
||||
}
|
||||
|
||||
$parameters[] = $parameter;
|
||||
}
|
||||
|
||||
if (isset($data['filters'])) {
|
||||
$parameters = array_merge($parameters, $this->deriveQueryParameters($data['filters']));
|
||||
}
|
||||
|
||||
$data = $apiDoc->toArray();
|
||||
|
||||
if (isset($data['parameters'])) {
|
||||
$parameters = array_merge($parameters, $this->deriveParameters($data['parameters'], $models));
|
||||
}
|
||||
|
||||
$responseMap = $apiDoc->getParsedResponseMap();
|
||||
|
||||
$statusMessages = isset($data['statusCodes']) ? $data['statusCodes'] : array();
|
||||
|
||||
foreach ($responseMap as $statusCode => $prop) {
|
||||
|
||||
if (isset($statusMessages[$statusCode])) {
|
||||
$message = is_array($statusMessages[$statusCode]) ? implode('; ', $statusMessages[$statusCode]) : $statusCode[$statusCode];
|
||||
} else {
|
||||
$message = sprintf('See standard HTTP status code reason for %s', $statusCode);
|
||||
}
|
||||
|
||||
$responseModel = array(
|
||||
'code' => $statusCode,
|
||||
'message' => $message,
|
||||
'responseModel' => $this->registerModel($prop['type']['class'], $prop['model'], '', $models),
|
||||
);
|
||||
$responseMessages[$statusCode] = $responseModel;
|
||||
}
|
||||
|
||||
$unmappedMessages = array_diff(array_keys($statusMessages), array_keys($responseMessages));
|
||||
|
||||
foreach ($unmappedMessages as $code) {
|
||||
$responseMessages[$code] = array(
|
||||
'code' => $code,
|
||||
'message' => is_array($statusMessages[$code]) ? implode('; ', $statusMessages[$code]) : $statusMessages[$code],
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($apiDoc->getRoute()->getMethods() as $method) {
|
||||
$operation = array(
|
||||
'method' => $method,
|
||||
'summary' => $apiDoc->getDescription(),
|
||||
'nickname' => $this->generateNickname($method, $itemResource),
|
||||
'parameters' => $parameters,
|
||||
'responseMessages' => array_values($responseMessages),
|
||||
);
|
||||
|
||||
$apiBag[$path][] = $operation;
|
||||
}
|
||||
}
|
||||
|
||||
$apiDeclaration['resourcePath'] = $resource;
|
||||
|
||||
foreach ($apiBag as $path => $operations) {
|
||||
$apiDeclaration['apis'][] = array(
|
||||
'path' => $path,
|
||||
'operations' => $operations,
|
||||
);
|
||||
}
|
||||
|
||||
$apiDeclaration['models'] = $models;
|
||||
|
||||
return $apiDeclaration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Slugify a URL path. Trims out path parameters wrapped in curly brackets.
|
||||
*
|
||||
* @param $path
|
||||
* @return string
|
||||
*/
|
||||
protected function normalizeResourcePath($path)
|
||||
{
|
||||
$path = preg_replace('/({.*?})/', '', $path);
|
||||
$path = trim(preg_replace('/[^0-9a-zA-Z]/', '-', $path), '-');
|
||||
$path = preg_replace('/-+/', '-', $path);
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*/
|
||||
public function setBasePath($path)
|
||||
{
|
||||
$this->basePath = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats query parameters to Swagger-compliant form.
|
||||
*
|
||||
* @param array $input
|
||||
* @return array
|
||||
*/
|
||||
protected function deriveQueryParameters(array $input)
|
||||
{
|
||||
$parameters = array();
|
||||
|
||||
foreach ($input as $name => $prop) {
|
||||
$parameters[] = array(
|
||||
'paramType' => 'query',
|
||||
'name' => $name,
|
||||
'type' => isset($this->typeMap[$prop['dataType']]) ? $this->typeMap[$prop['dataType']] : 'string',
|
||||
);
|
||||
}
|
||||
|
||||
return $parameters;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a Swagger-compliant parameter list from the provided parameter array. Models are built when necessary.
|
||||
*
|
||||
* @param array $input
|
||||
* @param array $models
|
||||
* @return array
|
||||
*/
|
||||
protected function deriveParameters(array $input, array &$models)
|
||||
{
|
||||
|
||||
$parameters = array();
|
||||
|
||||
foreach ($input as $name => $prop) {
|
||||
|
||||
$type = null;
|
||||
$format = null;
|
||||
$ref = null;
|
||||
$enum = null;
|
||||
$items = null;
|
||||
|
||||
if (isset ($this->typeMap[$prop['actualType']])) {
|
||||
$type = $this->typeMap[$prop['actualType']];
|
||||
} else {
|
||||
switch ($prop['actualType']) {
|
||||
case DataTypes::ENUM:
|
||||
$type = 'string';
|
||||
$enum = array_keys(json_decode($prop['format'], true));
|
||||
break;
|
||||
|
||||
case DataTypes::MODEL:
|
||||
$ref =
|
||||
$this->registerModel(
|
||||
$prop['subType'],
|
||||
isset($prop['children']) ? $prop['children'] : null,
|
||||
$prop['description'] ?: $prop['dataType'],
|
||||
$models);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->formatMap[$prop['actualType']])) {
|
||||
$format = $this->formatMap[$prop['actualType']];
|
||||
}
|
||||
|
||||
if (null === $type && null === $ref) {
|
||||
/* `type` or `$ref` is required. Continue to next of none of these was determined. */
|
||||
continue;
|
||||
}
|
||||
|
||||
$parameter = array(
|
||||
'paramType' => 'form',
|
||||
'name' => $name,
|
||||
);
|
||||
|
||||
if (null !== $type) {
|
||||
$parameter['type'] = $type;
|
||||
}
|
||||
|
||||
if (null !== $ref) {
|
||||
$parameter['$ref'] = $ref;
|
||||
$parameter['type'] = $ref;
|
||||
}
|
||||
|
||||
if (null !== $format) {
|
||||
$parameter['format'] = $format;
|
||||
}
|
||||
|
||||
if (is_array($enum) && count($enum) > 0) {
|
||||
$parameter['enum'] = $enum;
|
||||
}
|
||||
|
||||
$parameters[] = $parameter;
|
||||
}
|
||||
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a model into the model array. Returns a unique identifier for the model to be used in `$ref` properties.
|
||||
*
|
||||
* @param $className
|
||||
* @param array $parameters
|
||||
* @param string $description
|
||||
* @param $models
|
||||
* @return mixed
|
||||
*/
|
||||
public function registerModel($className, array $parameters = null, $description = '', &$models)
|
||||
{
|
||||
if (isset ($models[$className])) {
|
||||
return $models[$className]['id'];
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts \Fully\Qualified\Class\Name to Fully.Qualified.Class.Name
|
||||
*/
|
||||
$id = preg_replace('#(\\\|[^A-Za-z0-9])#', '.', $className);
|
||||
//Replace duplicate dots.
|
||||
$id = preg_replace('/\.+/', '.', $id);
|
||||
//Replace trailing dots.
|
||||
$id = preg_replace('/^\./', '', $id);
|
||||
|
||||
$model = array(
|
||||
'id' => $id,
|
||||
'description' => $description,
|
||||
);
|
||||
|
||||
if (is_array($parameters)) {
|
||||
|
||||
$required = array();
|
||||
$properties = array();
|
||||
|
||||
foreach ($parameters as $name => $prop) {
|
||||
|
||||
$subParam = array();
|
||||
|
||||
if ($prop['actualType'] === DataTypes::MODEL) {
|
||||
|
||||
$subParam['$ref'] = $this->registerModel(
|
||||
$prop['subType'],
|
||||
isset($prop['children']) ? $prop['children'] : null,
|
||||
$prop['description'] ?: $prop['dataType'],
|
||||
$models
|
||||
);
|
||||
|
||||
} else {
|
||||
|
||||
$type = null;
|
||||
$format = null;
|
||||
$items = null;
|
||||
$enum = null;
|
||||
$ref = null;
|
||||
|
||||
if (isset($this->typeMap[$prop['actualType']])) {
|
||||
$type = $this->typeMap[$prop['actualType']];
|
||||
} else{
|
||||
|
||||
switch ($prop['actualType']) {
|
||||
case DataTypes::ENUM:
|
||||
$type = 'string';
|
||||
if (isset($prop['format'])) {
|
||||
$enum = array_keys(json_decode($prop['format'], true));
|
||||
}
|
||||
break;
|
||||
|
||||
case DataTypes::COLLECTION:
|
||||
$type = 'array';
|
||||
|
||||
if ($prop['subType'] === DataTypes::MODEL) {
|
||||
|
||||
} else {
|
||||
|
||||
if ($prop['subType'] === null
|
||||
|| isset($this->typeMap[$prop['subType']])) {
|
||||
$items = array(
|
||||
'type' => 'string',
|
||||
);
|
||||
} elseif (!isset($this->typeMap[$prop['subType']])) {
|
||||
$items = array(
|
||||
'$ref' =>
|
||||
$this->registerModel(
|
||||
$prop['subType'],
|
||||
isset($prop['children']) ? $prop['children'] : null,
|
||||
$prop['description'] ?: $prop['dataType'],
|
||||
$models
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
/* @TODO: Handle recursion if subtype is a model. */
|
||||
break;
|
||||
|
||||
case DataTypes::MODEL:
|
||||
$ref = $this->registerModel(
|
||||
$prop['subType'],
|
||||
isset($prop['children']) ? $prop['children'] : null,
|
||||
$prop['description'] ?: $prop['dataType'],
|
||||
$models
|
||||
);
|
||||
$type = $ref;
|
||||
/* @TODO: Handle recursion. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->formatMap[$prop['actualType']])) {
|
||||
$format = $this->formatMap[$prop['actualType']];
|
||||
}
|
||||
|
||||
$subParam = array(
|
||||
'type' => $type,
|
||||
'description' => empty($prop['description']) === false ? (string) $prop['description'] : $prop['dataType'],
|
||||
);
|
||||
|
||||
if ($format !== null) {
|
||||
$subParam['format'] = $format;
|
||||
}
|
||||
|
||||
if ($enum !== null) {
|
||||
$subParam['enum'] = $enum;
|
||||
}
|
||||
|
||||
if ($ref !== null) {
|
||||
$subParam['$ref'] = $ref;
|
||||
}
|
||||
|
||||
if ($items !== null) {
|
||||
$subParam['items'] = $items;
|
||||
}
|
||||
|
||||
if ($prop['required']) {
|
||||
$required[] = $name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$properties[$name] = $subParam;
|
||||
}
|
||||
|
||||
$model['properties'] = $properties;
|
||||
$model['required'] = $required;
|
||||
$models[$id] = $model;
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $swaggerVersion
|
||||
*/
|
||||
public function setSwaggerVersion($swaggerVersion)
|
||||
{
|
||||
$this->swaggerVersion = $swaggerVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $apiVersion
|
||||
*/
|
||||
public function setApiVersion($apiVersion)
|
||||
{
|
||||
$this->apiVersion = $apiVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $info
|
||||
*/
|
||||
public function setInfo($info)
|
||||
{
|
||||
$this->info = $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips the base path from a URL path.
|
||||
*
|
||||
* @param $path
|
||||
* @return mixed
|
||||
*/
|
||||
protected function stripBasePath($path)
|
||||
{
|
||||
$pattern = sprintf('#%s#', preg_quote($this->basePath));
|
||||
$subPath = preg_replace($pattern, '', $path);
|
||||
return $subPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate nicknames based on support HTTP methods and the resource name.
|
||||
*
|
||||
* @param $method
|
||||
* @param $resource
|
||||
* @return string
|
||||
*/
|
||||
protected function generateNickname($method, $resource)
|
||||
{
|
||||
$resource = preg_replace('#/^#', '', $resource);
|
||||
$resource = $this->normalizeResourcePath($resource);
|
||||
return sprintf('%s_%s', strtolower($method), $resource);
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace Nelmio\ApiDocBundle;
|
||||
|
||||
use Nelmio\ApiDocBundle\DependencyInjection\SwaggerConfigCompilerPass;
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Nelmio\ApiDocBundle\DependencyInjection\LoadExtractorParsersPass;
|
||||
@ -17,5 +18,6 @@ class NelmioApiDocBundle extends Bundle
|
||||
$container->addCompilerPass(new LoadExtractorParsersPass());
|
||||
$container->addCompilerPass(new RegisterExtractorParsersPass());
|
||||
$container->addCompilerPass(new ExtractorHandlerCompilerPass());
|
||||
$container->addCompilerPass(new SwaggerConfigCompilerPass());
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
<parameter key="nelmio_api_doc.formatter.markdown_formatter.class">Nelmio\ApiDocBundle\Formatter\MarkdownFormatter</parameter>
|
||||
<parameter key="nelmio_api_doc.formatter.simple_formatter.class">Nelmio\ApiDocBundle\Formatter\SimpleFormatter</parameter>
|
||||
<parameter key="nelmio_api_doc.formatter.html_formatter.class">Nelmio\ApiDocBundle\Formatter\HtmlFormatter</parameter>
|
||||
<parameter key="nelmio_api_doc.formatter.swagger_formatter.class">Nelmio\ApiDocBundle\Formatter\SwaggerFormatter</parameter>
|
||||
<parameter key="nelmio_api_doc.sandbox.authentication">null</parameter>
|
||||
</parameters>
|
||||
|
||||
@ -56,6 +57,7 @@
|
||||
<argument>%nelmio_api_doc.sandbox.authentication%</argument>
|
||||
</call>
|
||||
</service>
|
||||
<service id="nelmio_api_doc.formatter.swagger_formatter" class="%nelmio_api_doc.formatter.swagger_formatter.class%" />
|
||||
</services>
|
||||
|
||||
</container>
|
||||
|
11
Resources/config/swagger_routing.yml
Normal file
11
Resources/config/swagger_routing.yml
Normal file
@ -0,0 +1,11 @@
|
||||
nelmio_api_doc_swagger_resource_list:
|
||||
pattern: /
|
||||
defaults: { _controller: NelmioApiDocBundle:ApiDoc:swagger }
|
||||
requirements:
|
||||
_method: GET
|
||||
|
||||
nelmio_api_doc_swagger_api_declaration:
|
||||
pattern: /{resource}
|
||||
defaults: { _controller: NelmioApiDocBundle:ApiDoc:swagger }
|
||||
requirements:
|
||||
_method: GET
|
@ -319,4 +319,41 @@ class ApiDocTest extends TestCase
|
||||
$this->assertTrue(is_array($array['tags']), 'Tags should be in array');
|
||||
$this->assertEquals($data['tags'], $array['tags']);
|
||||
}
|
||||
|
||||
public function testAlignmentOfOutputAndResponseModels()
|
||||
{
|
||||
$data = array(
|
||||
'output' => 'FooBar',
|
||||
'responseMap' => array(
|
||||
400 => 'Foo\\ValidationErrorCollection',
|
||||
),
|
||||
);
|
||||
|
||||
$apiDoc = new ApiDoc($data);
|
||||
|
||||
$map = $apiDoc->getResponseMap();
|
||||
|
||||
$this->assertCount(2, $map);
|
||||
$this->assertArrayHasKey(200, $map);
|
||||
$this->assertArrayHasKey(400, $map);
|
||||
$this->assertEquals($data['output'], $map[200]);
|
||||
}
|
||||
|
||||
public function testAlignmentOfOutputAndResponseModels2()
|
||||
{
|
||||
$data = array(
|
||||
'responseMap' => array(
|
||||
200 => 'FooBar',
|
||||
400 => 'Foo\\ValidationErrorCollection',
|
||||
),
|
||||
);
|
||||
|
||||
$apiDoc = new ApiDoc($data);
|
||||
$map = $apiDoc->getResponseMap();
|
||||
|
||||
$this->assertCount(2, $map);
|
||||
$this->assertArrayHasKey(200, $map);
|
||||
$this->assertArrayHasKey(400, $map);
|
||||
$this->assertEquals($apiDoc->getOutput(), $map[200]);
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ use Nelmio\ApiDocBundle\Tests\WebTestCase;
|
||||
|
||||
class ApiDocExtractorTest extends WebTestCase
|
||||
{
|
||||
const ROUTES_QUANTITY = 25;
|
||||
const ROUTES_QUANTITY = 31;
|
||||
|
||||
public function testAll()
|
||||
{
|
||||
@ -38,39 +38,39 @@ class ApiDocExtractorTest extends WebTestCase
|
||||
$this->assertNotNull($d['resource']);
|
||||
}
|
||||
|
||||
$a1 = $data[0]['annotation'];
|
||||
$a1 = $data[7]['annotation'];
|
||||
$array1 = $a1->toArray();
|
||||
$this->assertTrue($a1->isResource());
|
||||
$this->assertEquals('index action', $a1->getDescription());
|
||||
$this->assertTrue(is_array($array1['filters']));
|
||||
$this->assertNull($a1->getInput());
|
||||
|
||||
$a1 = $data[1]['annotation'];
|
||||
$a1 = $data[7]['annotation'];
|
||||
$array1 = $a1->toArray();
|
||||
$this->assertTrue($a1->isResource());
|
||||
$this->assertEquals('index action', $a1->getDescription());
|
||||
$this->assertTrue(is_array($array1['filters']));
|
||||
$this->assertNull($a1->getInput());
|
||||
|
||||
$a2 = $data[2]['annotation'];
|
||||
$a2 = $data[8]['annotation'];
|
||||
$array2 = $a2->toArray();
|
||||
$this->assertFalse($a2->isResource());
|
||||
$this->assertEquals('create test', $a2->getDescription());
|
||||
$this->assertFalse(isset($array2['filters']));
|
||||
$this->assertEquals('Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType', $a2->getInput());
|
||||
|
||||
$a2 = $data[3]['annotation'];
|
||||
$a2 = $data[9]['annotation'];
|
||||
$array2 = $a2->toArray();
|
||||
$this->assertFalse($a2->isResource());
|
||||
$this->assertEquals('create test', $a2->getDescription());
|
||||
$this->assertFalse(isset($array2['filters']));
|
||||
$this->assertEquals('Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType', $a2->getInput());
|
||||
|
||||
$a4 = $data[5]['annotation'];
|
||||
$a4 = $data[11]['annotation'];
|
||||
$this->assertTrue($a4->isResource());
|
||||
$this->assertEquals('TestResource', $a4->getResource());
|
||||
|
||||
$a3 = $data['14']['annotation'];
|
||||
$a3 = $data[20]['annotation'];
|
||||
$this->assertTrue($a3->getHttps());
|
||||
|
||||
}
|
||||
@ -224,6 +224,7 @@ class ApiDocExtractorTest extends WebTestCase
|
||||
|
||||
$this->assertNotNull($annotation);
|
||||
$output = $annotation->getOutput();
|
||||
|
||||
$parsers = $output['parsers'];
|
||||
$this->assertEquals(
|
||||
"Nelmio\\ApiDocBundle\\Parser\\JmsMetadataParser",
|
||||
|
85
Tests/Fixtures/Controller/ResourceController.php
Normal file
85
Tests/Fixtures/Controller/ResourceController.php
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: bezalelhermoso
|
||||
* Date: 6/20/14
|
||||
* Time: 3:21 PM
|
||||
*/
|
||||
|
||||
namespace Nelmio\ApiDocBundle\Tests\Fixtures\Controller;
|
||||
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
||||
|
||||
|
||||
/**
|
||||
* Class ResourceController
|
||||
*
|
||||
* @package Nelmio\ApiDocBundle\Tests\Fixtures\Controller
|
||||
* @author Bez Hermoso <bez@activelamp.com>
|
||||
*/
|
||||
class ResourceController
|
||||
{
|
||||
/**
|
||||
* @ApiDoc(
|
||||
* resource=true,
|
||||
* resourceDescription="Operations on resource.",
|
||||
* description="List resources.",
|
||||
* statusCodes={200 = "Returned on success.", 404 = "Returned if resource cannot be found."}
|
||||
* )
|
||||
*/
|
||||
public function listResourcesAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @ApiDoc(description="Retrieve a resource by ID.")
|
||||
*/
|
||||
public function getResourceAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @ApiDoc(description="Delete a resource by ID.")
|
||||
*/
|
||||
public function deleteResourceAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @ApiDoc(
|
||||
* description="Create a new resource.",
|
||||
* input={"class" = "Nelmio\ApiDocBundle\Tests\Fixtures\Form\SimpleType", "name" = ""},
|
||||
* output="Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsNested"
|
||||
* )
|
||||
*/
|
||||
public function createResourceAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @ApiDoc(resource=true, description="List another resource.", resourceDescription="Operations on another resource.")
|
||||
*/
|
||||
public function listAnotherResourcesAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @ApiDoc(description="Retrieve another resource by ID.")
|
||||
*/
|
||||
public function getAnotherResourceAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @ApiDoc(description="Update a resource bu ID.")
|
||||
*/
|
||||
public function updateAnotherResourceAction()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Nelmio\ApiDocBundle\Tests\Fixtures\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
|
@ -54,3 +54,14 @@ jms_serializer:
|
||||
|
||||
nelmio_api_doc:
|
||||
exclude_sections: ["private", "exclusive"]
|
||||
swagger:
|
||||
api_base_path: /api
|
||||
swagger_version: 1.2
|
||||
api_version: 3.14
|
||||
info:
|
||||
title: Nelmio Swagger
|
||||
description: Testing Swagger integration.
|
||||
TermsOfServiceUrl: https://github.com
|
||||
contact: user@domain.tld
|
||||
license: MIT
|
||||
licenseUrl: http://opensource.org/licenses/MIT
|
||||
|
@ -161,3 +161,45 @@ test_route_22:
|
||||
defaults: { _controller: NelmioApiDocTestBundle:Test:zActionWithNullableRequestParam }
|
||||
requirements:
|
||||
_method: POST
|
||||
|
||||
test_route_list_resource:
|
||||
pattern: /api/resources.{_format}
|
||||
defaults: { _controller: NelmioApiDocTestBundle:Resource:listResources, _format: json }
|
||||
requirements:
|
||||
_method: GET
|
||||
_format: json|xml|html
|
||||
|
||||
test_route_get_resource:
|
||||
pattern: /api/resources/{id}.{_format}
|
||||
defaults: { _controller: NelmioApiDocTestBundle:Resource:getResource, _format: json }
|
||||
requirements:
|
||||
_method: GET
|
||||
_format: json|xml|html
|
||||
|
||||
test_route_delete_resource:
|
||||
pattern: /api/resources/{id}.{_format}
|
||||
defaults: { _controller: NelmioApiDocTestBundle:Resource:deleteResource, _format: json }
|
||||
requirements:
|
||||
_method: DELETE
|
||||
_format: json|xml|html
|
||||
|
||||
test_route_create_resource:
|
||||
pattern: /api/resources.{_format}
|
||||
defaults: { _controller: NelmioApiDocTestBundle:Resource:createResource, _format: json }
|
||||
requirements:
|
||||
_method: POST
|
||||
_format: json|xml|html
|
||||
|
||||
test_route_list_another_resource:
|
||||
pattern: /api/other-resources.{_format}
|
||||
defaults: { _controller: NelmioApiDocTestBundle:Resource:listAnotherResources, _format: json }
|
||||
requirements:
|
||||
_method: GET
|
||||
_format: json|xml|html
|
||||
|
||||
test_route_update_another_resource:
|
||||
pattern: /api/other-resources/{id}.{_format}
|
||||
defaults: { _controller: NelmioApiDocTestBundle:Resource:updateAnotherResource, _format: json }
|
||||
requirements:
|
||||
_method: PUT|PATCH
|
||||
_format: json|xml|html
|
||||
|
@ -26,6 +26,241 @@ class MarkdownFormatterTest extends WebTestCase
|
||||
$result = $container->get('nelmio_api_doc.formatter.markdown_formatter')->format($data);
|
||||
|
||||
$expected = <<<MARKDOWN
|
||||
## /api/other-resources ##
|
||||
|
||||
### `GET` /api/other-resources.{_format} ###
|
||||
|
||||
_List another resource._
|
||||
|
||||
#### Requirements ####
|
||||
|
||||
**_format**
|
||||
|
||||
- Requirement: json|xml|html
|
||||
|
||||
|
||||
### `PUT|PATCH` /api/other-resources/{id}.{_format} ###
|
||||
|
||||
_Update a resource bu ID._
|
||||
|
||||
#### Requirements ####
|
||||
|
||||
**_format**
|
||||
|
||||
- Requirement: json|xml|html
|
||||
**id**
|
||||
|
||||
|
||||
|
||||
## /api/resources ##
|
||||
|
||||
### `GET` /api/resources.{_format} ###
|
||||
|
||||
_List resources._
|
||||
|
||||
#### Requirements ####
|
||||
|
||||
**_format**
|
||||
|
||||
- Requirement: json|xml|html
|
||||
|
||||
|
||||
### `POST` /api/resources.{_format} ###
|
||||
|
||||
_Create a new resource._
|
||||
|
||||
#### Requirements ####
|
||||
|
||||
**_format**
|
||||
|
||||
- Requirement: json|xml|html
|
||||
|
||||
#### Parameters ####
|
||||
|
||||
a:
|
||||
|
||||
* type: string
|
||||
* required: true
|
||||
* description: Something that describes A.
|
||||
|
||||
b:
|
||||
|
||||
* type: float
|
||||
* required: true
|
||||
|
||||
c:
|
||||
|
||||
* type: choice
|
||||
* required: true
|
||||
|
||||
d:
|
||||
|
||||
* type: datetime
|
||||
* required: true
|
||||
|
||||
e:
|
||||
|
||||
* type: date
|
||||
* required: true
|
||||
|
||||
g:
|
||||
|
||||
* type: string
|
||||
* required: true
|
||||
|
||||
#### Response ####
|
||||
|
||||
foo:
|
||||
|
||||
* type: DateTime
|
||||
|
||||
bar:
|
||||
|
||||
* type: string
|
||||
|
||||
baz[]:
|
||||
|
||||
* type: array of integers
|
||||
* description: Epic description.
|
||||
|
||||
With multiple lines.
|
||||
|
||||
circular:
|
||||
|
||||
* type: object (JmsNested)
|
||||
|
||||
circular[foo]:
|
||||
|
||||
* type: DateTime
|
||||
|
||||
circular[bar]:
|
||||
|
||||
* type: string
|
||||
|
||||
circular[baz][]:
|
||||
|
||||
* type: array of integers
|
||||
* description: Epic description.
|
||||
|
||||
With multiple lines.
|
||||
|
||||
circular[circular]:
|
||||
|
||||
* type: object (JmsNested)
|
||||
|
||||
circular[parent]:
|
||||
|
||||
* type: object (JmsTest)
|
||||
|
||||
circular[parent][foo]:
|
||||
|
||||
* type: string
|
||||
|
||||
circular[parent][bar]:
|
||||
|
||||
* type: DateTime
|
||||
|
||||
circular[parent][number]:
|
||||
|
||||
* type: double
|
||||
|
||||
circular[parent][arr]:
|
||||
|
||||
* type: array
|
||||
|
||||
circular[parent][nested]:
|
||||
|
||||
* type: object (JmsNested)
|
||||
|
||||
circular[parent][nested_array][]:
|
||||
|
||||
* type: array of objects (JmsNested)
|
||||
|
||||
circular[since]:
|
||||
|
||||
* type: string
|
||||
* versions: >=0.2
|
||||
|
||||
circular[until]:
|
||||
|
||||
* type: string
|
||||
* versions: <=0.3
|
||||
|
||||
circular[since_and_until]:
|
||||
|
||||
* type: string
|
||||
* versions: >=0.4,<=0.5
|
||||
|
||||
parent:
|
||||
|
||||
* type: object (JmsTest)
|
||||
|
||||
parent[foo]:
|
||||
|
||||
* type: string
|
||||
|
||||
parent[bar]:
|
||||
|
||||
* type: DateTime
|
||||
|
||||
parent[number]:
|
||||
|
||||
* type: double
|
||||
|
||||
parent[arr]:
|
||||
|
||||
* type: array
|
||||
|
||||
parent[nested]:
|
||||
|
||||
* type: object (JmsNested)
|
||||
|
||||
parent[nested_array][]:
|
||||
|
||||
* type: array of objects (JmsNested)
|
||||
|
||||
since:
|
||||
|
||||
* type: string
|
||||
* versions: >=0.2
|
||||
|
||||
until:
|
||||
|
||||
* type: string
|
||||
* versions: <=0.3
|
||||
|
||||
since_and_until:
|
||||
|
||||
* type: string
|
||||
* versions: >=0.4,<=0.5
|
||||
|
||||
|
||||
### `GET` /api/resources/{id}.{_format} ###
|
||||
|
||||
_Retrieve a resource by ID._
|
||||
|
||||
#### Requirements ####
|
||||
|
||||
**_format**
|
||||
|
||||
- Requirement: json|xml|html
|
||||
**id**
|
||||
|
||||
|
||||
|
||||
### `DELETE` /api/resources/{id}.{_format} ###
|
||||
|
||||
_Delete a resource by ID._
|
||||
|
||||
#### Requirements ####
|
||||
|
||||
**_format**
|
||||
|
||||
- Requirement: json|xml|html
|
||||
**id**
|
||||
|
||||
|
||||
|
||||
## /tests ##
|
||||
|
||||
### `GET` /tests.{_format} ###
|
||||
@ -431,7 +666,7 @@ nested_array[]:
|
||||
|
||||
**id**
|
||||
|
||||
- Requirement: \\d+
|
||||
- Requirement: \d+
|
||||
|
||||
|
||||
### `GET` /z-action-with-deprecated-indicator ###
|
||||
@ -459,7 +694,7 @@ param1:
|
||||
|
||||
page:
|
||||
|
||||
* Requirement: \\d+
|
||||
* Requirement: \d+
|
||||
* Description: Page of the overview.
|
||||
* Default: 1
|
||||
|
||||
@ -527,14 +762,6 @@ related:
|
||||
|
||||
* type: object (Test)
|
||||
|
||||
related[a]:
|
||||
|
||||
* type: string
|
||||
|
||||
related[b]:
|
||||
|
||||
* type: DateTime
|
||||
|
||||
|
||||
### `ANY` /z-return-selected-parsers-input ###
|
||||
|
||||
@ -592,14 +819,6 @@ number:
|
||||
related:
|
||||
|
||||
* type: object (Test)
|
||||
|
||||
related[a]:
|
||||
|
||||
* type: string
|
||||
|
||||
related[b]:
|
||||
|
||||
* type: DateTime
|
||||
MARKDOWN;
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
|
@ -198,7 +198,6 @@ class SimpleFormatterTest extends WebTestCase
|
||||
'dataType' => 'string',
|
||||
'actualType' => DataTypes::STRING,
|
||||
'subType' => null,
|
||||
'default' => null,
|
||||
'default' => "DefaultTest",
|
||||
'required' => true,
|
||||
'description' => '',
|
||||
@ -622,8 +621,6 @@ And, it supports multilines until the first \'@\' char.',
|
||||
),
|
||||
),
|
||||
'https' => false,
|
||||
'description' => 'This method is useful to test if the getDocComment works.',
|
||||
'documentation' => "This method is useful to test if the getDocComment works.\nAnd, it supports multilines until the first '@' char.",
|
||||
'authentication' => false,
|
||||
'authenticationRoles' => array(),
|
||||
'deprecated' => false,
|
||||
@ -1069,39 +1066,21 @@ With multiple lines.',
|
||||
'subType' => null,
|
||||
'default' => null,
|
||||
'required' => null,
|
||||
'readonly' => null
|
||||
'readonly' => null,
|
||||
)
|
||||
)
|
||||
),
|
||||
'related' => array(
|
||||
'dataType' => 'object (Test)',
|
||||
'actualType' => DataTypes::MODEL,
|
||||
'subType' => 'Nelmio\ApiDocBundle\Tests\Fixtures\Model\Test',
|
||||
'default' => null,
|
||||
'readonly' => false,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'sinceVersion' => null,
|
||||
'untilVersion' => null,
|
||||
'actualType' => DataTypes::MODEL,
|
||||
'subType' => 'Nelmio\ApiDocBundle\Tests\Fixtures\Model\Test',
|
||||
'default' => null,
|
||||
'children' => array(
|
||||
'a' => array(
|
||||
'dataType' => 'string',
|
||||
'format' => '{length: min: foo}, {not blank}',
|
||||
'required' => true,
|
||||
'readonly' => null,
|
||||
'actualType' => DataTypes::STRING,
|
||||
'subType' => null,
|
||||
'default' => 'nelmio',
|
||||
),
|
||||
'b' => array(
|
||||
'dataType' => 'DateTime',
|
||||
'required' => null,
|
||||
'readonly' => null,
|
||||
'actualType' => DataTypes::DATETIME,
|
||||
'subType' => null,
|
||||
'default' => null,
|
||||
)
|
||||
)
|
||||
'children' => array(),
|
||||
)
|
||||
),
|
||||
'authenticationRoles' => array(),
|
||||
@ -1147,7 +1126,6 @@ With multiple lines.',
|
||||
'dataType' => 'string',
|
||||
'actualType' => DataTypes::STRING,
|
||||
'subType' => null,
|
||||
'default' => null,
|
||||
'default' => "DefaultTest",
|
||||
'required' => true,
|
||||
'description' => '',
|
||||
@ -1211,33 +1189,15 @@ With multiple lines.',
|
||||
),
|
||||
'related' => array(
|
||||
'dataType' => 'object (Test)',
|
||||
'subType' => 'Nelmio\ApiDocBundle\Tests\Fixtures\Model\Test',
|
||||
'actualType' => DataTypes::MODEL,
|
||||
'default' => null,
|
||||
'readonly' => false,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'sinceVersion' => null,
|
||||
'untilVersion' => null,
|
||||
'actualType' => DataTypes::MODEL,
|
||||
'subType' => 'Nelmio\ApiDocBundle\Tests\Fixtures\Model\Test',
|
||||
'default' => null,
|
||||
'children' => array(
|
||||
'a' => array(
|
||||
'dataType' => 'string',
|
||||
'format' => '{length: min: foo}, {not blank}',
|
||||
'required' => true,
|
||||
'readonly' => null,
|
||||
'actualType' => DataTypes::STRING,
|
||||
'subType' => null,
|
||||
'default' => 'nelmio',
|
||||
),
|
||||
'b' => array(
|
||||
'dataType' => 'DateTime',
|
||||
'required' => null,
|
||||
'readonly' => null,
|
||||
'actualType' => DataTypes::DATETIME,
|
||||
'subType' => null,
|
||||
'default' => null,
|
||||
)
|
||||
)
|
||||
'children' => array(),
|
||||
)
|
||||
),
|
||||
'authenticationRoles' => array(),
|
||||
@ -1245,7 +1205,6 @@ With multiple lines.',
|
||||
),
|
||||
'/tests2' =>
|
||||
array(
|
||||
0 =>
|
||||
array(
|
||||
'method' => 'POST',
|
||||
'uri' => '/tests2.{_format}',
|
||||
@ -1267,7 +1226,6 @@ With multiple lines.',
|
||||
),
|
||||
'/tests2' =>
|
||||
array(
|
||||
0 =>
|
||||
array(
|
||||
'method' => 'POST',
|
||||
'uri' => '/tests2.{_format}',
|
||||
@ -1299,6 +1257,573 @@ With multiple lines.',
|
||||
'deprecated' => false,
|
||||
),
|
||||
),
|
||||
'/api/other-resources' =>
|
||||
array(
|
||||
array(
|
||||
'method' => 'GET',
|
||||
'uri' => '/api/other-resources.{_format}',
|
||||
'description' => 'List another resource.',
|
||||
'requirements' =>
|
||||
array(
|
||||
'_format' =>
|
||||
array(
|
||||
'requirement' => 'json|xml|html',
|
||||
'dataType' => '',
|
||||
'description' => '',
|
||||
),
|
||||
),
|
||||
'resourceDescription' => 'Operations on another resource.',
|
||||
'https' => false,
|
||||
'authentication' => false,
|
||||
'authenticationRoles' =>
|
||||
array(),
|
||||
'deprecated' => false,
|
||||
),
|
||||
array(
|
||||
'method' => 'PUT|PATCH',
|
||||
'uri' => '/api/other-resources/{id}.{_format}',
|
||||
'description' => 'Update a resource bu ID.',
|
||||
'requirements' =>
|
||||
array(
|
||||
'_format' =>
|
||||
array(
|
||||
'requirement' => 'json|xml|html',
|
||||
'dataType' => '',
|
||||
'description' => '',
|
||||
),
|
||||
'id' =>
|
||||
array(
|
||||
'requirement' => '',
|
||||
'dataType' => '',
|
||||
'description' => '',
|
||||
),
|
||||
),
|
||||
'https' => false,
|
||||
'authentication' => false,
|
||||
'authenticationRoles' =>
|
||||
array(),
|
||||
'deprecated' => false,
|
||||
),
|
||||
),
|
||||
'/api/resources' =>
|
||||
array(
|
||||
array(
|
||||
'method' => 'GET',
|
||||
'uri' => '/api/resources.{_format}',
|
||||
'description' => 'List resources.',
|
||||
'requirements' =>
|
||||
array(
|
||||
'_format' =>
|
||||
array(
|
||||
'requirement' => 'json|xml|html',
|
||||
'dataType' => '',
|
||||
'description' => '',
|
||||
),
|
||||
),
|
||||
'statusCodes' =>
|
||||
array(
|
||||
200 =>
|
||||
array(
|
||||
'Returned on success.',
|
||||
),
|
||||
404 =>
|
||||
array(
|
||||
'Returned if resource cannot be found.',
|
||||
),
|
||||
),
|
||||
'resourceDescription' => 'Operations on resource.',
|
||||
'https' => false,
|
||||
'authentication' => false,
|
||||
'authenticationRoles' =>
|
||||
array(),
|
||||
'deprecated' => false,
|
||||
),
|
||||
array(
|
||||
'method' => 'POST',
|
||||
'uri' => '/api/resources.{_format}',
|
||||
'description' => 'Create a new resource.',
|
||||
'parameters' =>
|
||||
array(
|
||||
'a' =>
|
||||
array(
|
||||
'dataType' => 'string',
|
||||
'actualType' => 'string',
|
||||
'subType' => NULL,
|
||||
'required' => true,
|
||||
'description' => 'Something that describes A.',
|
||||
'readonly' => false,
|
||||
'default' => null,
|
||||
),
|
||||
'b' =>
|
||||
array(
|
||||
'dataType' => 'float',
|
||||
'actualType' => 'float',
|
||||
'subType' => NULL,
|
||||
'required' => true,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'default' => null,
|
||||
),
|
||||
'c' =>
|
||||
array(
|
||||
'dataType' => 'choice',
|
||||
'actualType' => 'choice',
|
||||
'subType' => NULL,
|
||||
'required' => true,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'format' => '{"x":"X","y":"Y","z":"Z"}',
|
||||
'default' => null,
|
||||
),
|
||||
'd' =>
|
||||
array(
|
||||
'dataType' => 'datetime',
|
||||
'actualType' => 'datetime',
|
||||
'subType' => NULL,
|
||||
'required' => true,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'default' => null,
|
||||
),
|
||||
'e' =>
|
||||
array(
|
||||
'dataType' => 'date',
|
||||
'actualType' => 'date',
|
||||
'subType' => NULL,
|
||||
'required' => true,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'default' => null,
|
||||
),
|
||||
'g' =>
|
||||
array(
|
||||
'dataType' => 'string',
|
||||
'actualType' => 'string',
|
||||
'subType' => NULL,
|
||||
'required' => true,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'default' => null,
|
||||
),
|
||||
),
|
||||
'requirements' =>
|
||||
array(
|
||||
'_format' =>
|
||||
array(
|
||||
'requirement' => 'json|xml|html',
|
||||
'dataType' => '',
|
||||
'description' => '',
|
||||
),
|
||||
),
|
||||
'response' =>
|
||||
array(
|
||||
'foo' =>
|
||||
array(
|
||||
'dataType' => 'DateTime',
|
||||
'actualType' => 'datetime',
|
||||
'default' => null,
|
||||
'subType' => NULL,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => true,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
),
|
||||
'bar' =>
|
||||
array(
|
||||
'dataType' => 'string',
|
||||
'actualType' => 'string',
|
||||
'default' => 'baz',
|
||||
'subType' => NULL,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
),
|
||||
'baz' =>
|
||||
array(
|
||||
'dataType' => 'array of integers',
|
||||
'actualType' => 'collection',
|
||||
'subType' => 'integer',
|
||||
'required' => false,
|
||||
'description' => 'Epic description.
|
||||
|
||||
With multiple lines.',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'default' => null,
|
||||
'untilVersion' => NULL,
|
||||
),
|
||||
'circular' =>
|
||||
array(
|
||||
'dataType' => 'object (JmsNested)',
|
||||
'actualType' => 'model',
|
||||
'default' => null,
|
||||
'subType' => 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsNested',
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
'children' =>
|
||||
array(
|
||||
'foo' =>
|
||||
array(
|
||||
'dataType' => 'DateTime',
|
||||
'actualType' => 'datetime',
|
||||
'default' => null,
|
||||
'subType' => NULL,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => true,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
),
|
||||
'bar' =>
|
||||
array(
|
||||
'dataType' => 'string',
|
||||
'actualType' => 'string',
|
||||
'subType' => NULL,
|
||||
'default' => 'baz',
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
),
|
||||
'baz' =>
|
||||
array(
|
||||
'dataType' => 'array of integers',
|
||||
'actualType' => 'collection',
|
||||
'subType' => 'integer',
|
||||
'required' => false,
|
||||
'description' => 'Epic description.
|
||||
|
||||
With multiple lines.',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
'default' => null,
|
||||
),
|
||||
'circular' =>
|
||||
array(
|
||||
'dataType' => 'object (JmsNested)',
|
||||
'actualType' => 'model',
|
||||
'default' => null,
|
||||
'subType' => 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsNested',
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
),
|
||||
'parent' =>
|
||||
array(
|
||||
'dataType' => 'object (JmsTest)',
|
||||
'actualType' => 'model',
|
||||
'default' => null,
|
||||
'subType' => 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsTest',
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
'children' =>
|
||||
array(
|
||||
'foo' =>
|
||||
array(
|
||||
'dataType' => 'string',
|
||||
'actualType' => 'string',
|
||||
'subType' => NULL,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
'default' => null,
|
||||
),
|
||||
'bar' =>
|
||||
array(
|
||||
'dataType' => 'DateTime',
|
||||
'actualType' => 'datetime',
|
||||
'subType' => NULL,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => true,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
'default' => null,
|
||||
),
|
||||
'number' =>
|
||||
array(
|
||||
'dataType' => 'double',
|
||||
'actualType' => 'float',
|
||||
'subType' => NULL,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
'default' => null,
|
||||
),
|
||||
'arr' =>
|
||||
array(
|
||||
'dataType' => 'array',
|
||||
'actualType' => 'collection',
|
||||
'subType' => NULL,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
'default' => null,
|
||||
),
|
||||
'nested' =>
|
||||
array(
|
||||
'dataType' => 'object (JmsNested)',
|
||||
'actualType' => 'model',
|
||||
'default' => null,
|
||||
'subType' => 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsNested',
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
),
|
||||
'nested_array' =>
|
||||
array(
|
||||
'dataType' => 'array of objects (JmsNested)',
|
||||
'actualType' => 'collection',
|
||||
'subType' => 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsNested',
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
'default' => null,
|
||||
),
|
||||
),
|
||||
),
|
||||
'since' =>
|
||||
array(
|
||||
'dataType' => 'string',
|
||||
'actualType' => 'string',
|
||||
'subType' => NULL,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => '0.2',
|
||||
'untilVersion' => NULL,
|
||||
'default' => null,
|
||||
),
|
||||
'until' =>
|
||||
array(
|
||||
'dataType' => 'string',
|
||||
'actualType' => 'string',
|
||||
'subType' => NULL,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => '0.3',
|
||||
'default' => null,
|
||||
),
|
||||
'since_and_until' =>
|
||||
array(
|
||||
'dataType' => 'string',
|
||||
'actualType' => 'string',
|
||||
'subType' => NULL,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => '0.4',
|
||||
'untilVersion' => '0.5',
|
||||
'default' => null,
|
||||
),
|
||||
),
|
||||
),
|
||||
'parent' =>
|
||||
array(
|
||||
'dataType' => 'object (JmsTest)',
|
||||
'actualType' => 'model',
|
||||
'default' => null,
|
||||
'subType' => 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsTest',
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
'children' =>
|
||||
array(
|
||||
'foo' =>
|
||||
array(
|
||||
'dataType' => 'string',
|
||||
'actualType' => 'string',
|
||||
'subType' => NULL,
|
||||
'default' => null,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
),
|
||||
'bar' =>
|
||||
array(
|
||||
'dataType' => 'DateTime',
|
||||
'actualType' => 'datetime',
|
||||
'subType' => NULL,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => true,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
'default' => null,
|
||||
),
|
||||
'number' =>
|
||||
array(
|
||||
'dataType' => 'double',
|
||||
'actualType' => 'float',
|
||||
'subType' => NULL,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
'default' => null,
|
||||
),
|
||||
'arr' =>
|
||||
array(
|
||||
'dataType' => 'array',
|
||||
'actualType' => 'collection',
|
||||
'subType' => NULL,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
'default' => null,
|
||||
),
|
||||
'nested' =>
|
||||
array(
|
||||
'dataType' => 'object (JmsNested)',
|
||||
'actualType' => 'model',
|
||||
'default' => null,
|
||||
'subType' => 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsNested',
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
),
|
||||
'nested_array' =>
|
||||
array(
|
||||
'dataType' => 'array of objects (JmsNested)',
|
||||
'actualType' => 'collection',
|
||||
'subType' => 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsNested',
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => NULL,
|
||||
'default' => null,
|
||||
),
|
||||
),
|
||||
),
|
||||
'since' =>
|
||||
array(
|
||||
'dataType' => 'string',
|
||||
'actualType' => 'string',
|
||||
'subType' => NULL,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => '0.2',
|
||||
'untilVersion' => NULL,
|
||||
'default' => null,
|
||||
),
|
||||
'until' =>
|
||||
array(
|
||||
'dataType' => 'string',
|
||||
'actualType' => 'string',
|
||||
'subType' => NULL,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => NULL,
|
||||
'untilVersion' => '0.3',
|
||||
'default' => null,
|
||||
),
|
||||
'since_and_until' =>
|
||||
array(
|
||||
'dataType' => 'string',
|
||||
'actualType' => 'string',
|
||||
'subType' => NULL,
|
||||
'required' => false,
|
||||
'description' => '',
|
||||
'readonly' => false,
|
||||
'sinceVersion' => '0.4',
|
||||
'untilVersion' => '0.5',
|
||||
'default' => null,
|
||||
),
|
||||
),
|
||||
'https' => false,
|
||||
'authentication' => false,
|
||||
'authenticationRoles' =>
|
||||
array(),
|
||||
'deprecated' => false,
|
||||
),
|
||||
array(
|
||||
'method' => 'GET',
|
||||
'uri' => '/api/resources/{id}.{_format}',
|
||||
'description' => 'Retrieve a resource by ID.',
|
||||
'requirements' =>
|
||||
array(
|
||||
'_format' =>
|
||||
array(
|
||||
'requirement' => 'json|xml|html',
|
||||
'dataType' => '',
|
||||
'description' => '',
|
||||
),
|
||||
'id' =>
|
||||
array(
|
||||
'requirement' => '',
|
||||
'dataType' => '',
|
||||
'description' => '',
|
||||
),
|
||||
),
|
||||
'https' => false,
|
||||
'authentication' => false,
|
||||
'authenticationRoles' =>
|
||||
array(),
|
||||
'deprecated' => false,
|
||||
),
|
||||
array(
|
||||
'method' => 'DELETE',
|
||||
'uri' => '/api/resources/{id}.{_format}',
|
||||
'description' => 'Delete a resource by ID.',
|
||||
'requirements' =>
|
||||
array(
|
||||
'_format' =>
|
||||
array(
|
||||
'requirement' => 'json|xml|html',
|
||||
'dataType' => '',
|
||||
'description' => '',
|
||||
),
|
||||
'id' =>
|
||||
array(
|
||||
'requirement' => '',
|
||||
'dataType' => '',
|
||||
'description' => '',
|
||||
),
|
||||
),
|
||||
'https' => false,
|
||||
'authentication' => false,
|
||||
'authenticationRoles' =>
|
||||
array(),
|
||||
'deprecated' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
|
726
Tests/Formatter/SwaggerFormatterTest.php
Normal file
726
Tests/Formatter/SwaggerFormatterTest.php
Normal file
@ -0,0 +1,726 @@
|
||||
<?php
|
||||
|
||||
namespace Nelmio\ApiDocBundle\Tests\Formatter;
|
||||
|
||||
|
||||
use Nelmio\ApiDocBundle\Extractor\ApiDocExtractor;
|
||||
use Nelmio\ApiDocBundle\Formatter\SwaggerFormatter;
|
||||
use Nelmio\ApiDocBundle\Tests\WebTestCase;
|
||||
|
||||
|
||||
/**
|
||||
* Class SwaggerFormatterTest
|
||||
*
|
||||
* @package Nelmio\ApiDocBundle\Tests\Formatter
|
||||
* @author Bez Hermoso <bez@activelamp.com>
|
||||
*/
|
||||
class SwaggerFormatterTest extends WebTestCase
|
||||
{
|
||||
/**
|
||||
* @var ApiDocExtractor
|
||||
*/
|
||||
protected $extractor;
|
||||
|
||||
/**
|
||||
* @var SwaggerFormatter
|
||||
*/
|
||||
protected $formatter;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$container = $this->getContainer();
|
||||
$this->extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor');
|
||||
$this->formatter = $container->get('nelmio_api_doc.formatter.swagger_formatter');
|
||||
}
|
||||
|
||||
|
||||
public function testResourceListing()
|
||||
{
|
||||
|
||||
set_error_handler(array($this, 'handleDeprecation'));
|
||||
$data = $this->extractor->all();
|
||||
restore_error_handler();
|
||||
|
||||
/** @var $formatter SwaggerFormatter */
|
||||
|
||||
$actual = $this->formatter->format($data, null);
|
||||
|
||||
|
||||
$expected = array(
|
||||
'swaggerVersion' => '1.2',
|
||||
'apiVersion' => '3.14',
|
||||
'info' =>
|
||||
array(
|
||||
'title' => 'Nelmio Swagger',
|
||||
'description' => 'Testing Swagger integration.',
|
||||
'TermsOfServiceUrl' => 'https://github.com',
|
||||
'contact' => 'user@domain.tld',
|
||||
'license' => 'MIT',
|
||||
'licenseUrl' => 'http://opensource.org/licenses/MIT',
|
||||
),
|
||||
'authorizations' =>
|
||||
array(),
|
||||
'apis' =>
|
||||
array(
|
||||
array(
|
||||
'path' => '/other-resources',
|
||||
'description' => 'Operations on another resource.',
|
||||
),
|
||||
array(
|
||||
'path' => '/resources',
|
||||
'description' => 'Operations on resource.',
|
||||
),
|
||||
array(
|
||||
'path' => '/tests',
|
||||
'description' => NULL,
|
||||
),
|
||||
array(
|
||||
'path' => '/tests',
|
||||
'description' => NULL,
|
||||
),
|
||||
array(
|
||||
'path' => '/tests2',
|
||||
'description' => NULL,
|
||||
),
|
||||
array(
|
||||
'path' => '/TestResource',
|
||||
'description' => NULL,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataTestApiDeclaration
|
||||
*/
|
||||
public function testApiDeclaration($resource, $expected)
|
||||
{
|
||||
set_error_handler(array($this, 'handleDeprecation'));
|
||||
$data = $this->extractor->all();
|
||||
restore_error_handler();
|
||||
|
||||
$actual = $this->formatter->format($data, $resource);
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
|
||||
}
|
||||
|
||||
public function dataTestApiDeclaration()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
'/resources',
|
||||
array(
|
||||
'swaggerVersion' => '1.2',
|
||||
'apiVersion' => '3.14',
|
||||
'basePath' => '/api',
|
||||
'resourcePath' => '/resources',
|
||||
'apis' =>
|
||||
array(
|
||||
|
||||
array(
|
||||
'path' => '/resources.{_format}',
|
||||
'operations' =>
|
||||
array(
|
||||
array(
|
||||
'method' => 'GET',
|
||||
'summary' => 'List resources.',
|
||||
'nickname' => 'get_resources',
|
||||
'parameters' =>
|
||||
array(
|
||||
|
||||
array(
|
||||
'paramType' => 'path',
|
||||
'name' => '_format',
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
'enum' =>
|
||||
array(
|
||||
'json',
|
||||
'xml',
|
||||
'html',
|
||||
),
|
||||
),
|
||||
),
|
||||
'responseMessages' =>
|
||||
array(
|
||||
|
||||
array(
|
||||
'code' => 200,
|
||||
'message' => 'Returned on success.',
|
||||
),
|
||||
|
||||
array(
|
||||
'code' => 404,
|
||||
'message' => 'Returned if resource cannot be found.',
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
array(
|
||||
'method' => 'POST',
|
||||
'summary' => 'Create a new resource.',
|
||||
'nickname' => 'post_resources',
|
||||
'parameters' =>
|
||||
array(
|
||||
|
||||
array(
|
||||
'paramType' => 'path',
|
||||
'name' => '_format',
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
'enum' =>
|
||||
array(
|
||||
'json',
|
||||
'xml',
|
||||
'html',
|
||||
),
|
||||
),
|
||||
|
||||
array(
|
||||
'paramType' => 'form',
|
||||
'name' => 'a',
|
||||
'type' => 'string',
|
||||
),
|
||||
|
||||
array(
|
||||
'paramType' => 'form',
|
||||
'name' => 'b',
|
||||
'type' => 'number',
|
||||
'format' => 'float',
|
||||
),
|
||||
|
||||
array(
|
||||
'paramType' => 'form',
|
||||
'name' => 'c',
|
||||
'type' => 'string',
|
||||
'enum' =>
|
||||
array(
|
||||
'x',
|
||||
'y',
|
||||
'z',
|
||||
),
|
||||
),
|
||||
|
||||
array(
|
||||
'paramType' => 'form',
|
||||
'name' => 'd',
|
||||
'type' => 'string',
|
||||
'format' => 'date-time',
|
||||
),
|
||||
|
||||
array(
|
||||
'paramType' => 'form',
|
||||
'name' => 'e',
|
||||
'type' => 'string',
|
||||
'format' => 'date',
|
||||
),
|
||||
|
||||
array(
|
||||
'paramType' => 'form',
|
||||
'name' => 'g',
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
'responseMessages' =>
|
||||
array(
|
||||
|
||||
array(
|
||||
'code' => 200,
|
||||
'message' => 'See standard HTTP status code reason for 200',
|
||||
'responseModel' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
array(
|
||||
'path' => '/resources/{id}.{_format}',
|
||||
'operations' =>
|
||||
array(
|
||||
|
||||
array(
|
||||
'method' => 'GET',
|
||||
'summary' => 'Retrieve a resource by ID.',
|
||||
'nickname' => 'get_resources',
|
||||
'parameters' =>
|
||||
array(
|
||||
|
||||
array(
|
||||
'paramType' => 'path',
|
||||
'name' => 'id',
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
),
|
||||
|
||||
array(
|
||||
'paramType' => 'path',
|
||||
'name' => '_format',
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
'enum' =>
|
||||
array(
|
||||
'json',
|
||||
'xml',
|
||||
'html',
|
||||
),
|
||||
),
|
||||
),
|
||||
'responseMessages' =>
|
||||
array(),
|
||||
),
|
||||
|
||||
array(
|
||||
'method' => 'DELETE',
|
||||
'summary' => 'Delete a resource by ID.',
|
||||
'nickname' => 'delete_resources',
|
||||
'parameters' =>
|
||||
array(
|
||||
|
||||
array(
|
||||
'paramType' => 'path',
|
||||
'name' => 'id',
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
),
|
||||
|
||||
array(
|
||||
'paramType' => 'path',
|
||||
'name' => '_format',
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
'enum' =>
|
||||
array(
|
||||
'json',
|
||||
'xml',
|
||||
'html',
|
||||
),
|
||||
),
|
||||
),
|
||||
'responseMessages' =>
|
||||
array(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
'models' =>
|
||||
array(
|
||||
'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest' =>
|
||||
array(
|
||||
'id' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest',
|
||||
'description' => 'object (JmsTest)',
|
||||
'properties' =>
|
||||
array(
|
||||
'foo' =>
|
||||
array(
|
||||
'type' => 'string',
|
||||
'description' => 'string',
|
||||
),
|
||||
'bar' =>
|
||||
array(
|
||||
'type' => 'string',
|
||||
'description' => 'DateTime',
|
||||
'format' => 'date-time',
|
||||
),
|
||||
'number' =>
|
||||
array(
|
||||
'type' => 'number',
|
||||
'description' => 'double',
|
||||
'format' => 'float',
|
||||
),
|
||||
'arr' =>
|
||||
array(
|
||||
'type' => 'array',
|
||||
'description' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'string',
|
||||
)
|
||||
),
|
||||
'nested' =>
|
||||
array(
|
||||
'$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested',
|
||||
),
|
||||
'nested_array' =>
|
||||
array(
|
||||
'type' => 'array',
|
||||
'description' => 'array of objects (JmsNested)',
|
||||
'items' => array(
|
||||
'$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested',
|
||||
)
|
||||
),
|
||||
),
|
||||
'required' =>
|
||||
array(),
|
||||
),
|
||||
'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested' =>
|
||||
array(
|
||||
'id' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested',
|
||||
'description' => '',
|
||||
'properties' =>
|
||||
array(
|
||||
'foo' =>
|
||||
array(
|
||||
'type' => 'string',
|
||||
'description' => 'DateTime',
|
||||
'format' => 'date-time',
|
||||
),
|
||||
'bar' =>
|
||||
array(
|
||||
'type' => 'string',
|
||||
'description' => 'string',
|
||||
),
|
||||
'baz' =>
|
||||
array(
|
||||
'type' => 'array',
|
||||
'description' => 'Epic description.
|
||||
|
||||
With multiple lines.',
|
||||
'items' => array(
|
||||
'type' => 'string',
|
||||
)
|
||||
),
|
||||
'circular' =>
|
||||
array(
|
||||
'$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested',
|
||||
),
|
||||
'parent' =>
|
||||
array(
|
||||
'$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest',
|
||||
),
|
||||
'since' =>
|
||||
array(
|
||||
'type' => 'string',
|
||||
'description' => 'string',
|
||||
),
|
||||
'until' =>
|
||||
array(
|
||||
'type' => 'string',
|
||||
'description' => 'string',
|
||||
),
|
||||
'since_and_until' =>
|
||||
array(
|
||||
'type' => 'string',
|
||||
'description' => 'string',
|
||||
),
|
||||
),
|
||||
'required' =>
|
||||
array(),
|
||||
),
|
||||
),
|
||||
'produces' =>
|
||||
array(),
|
||||
'consumes' =>
|
||||
array(),
|
||||
'authorizations' =>
|
||||
array(),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'/other-resources',
|
||||
array(
|
||||
'swaggerVersion' => '1.2',
|
||||
'apiVersion' => '3.14',
|
||||
'basePath' => '/api',
|
||||
'resourcePath' => '/other-resources',
|
||||
'apis' =>
|
||||
array(
|
||||
|
||||
array(
|
||||
'path' => '/other-resources.{_format}',
|
||||
'operations' =>
|
||||
array(
|
||||
|
||||
array(
|
||||
'method' => 'GET',
|
||||
'summary' => 'List another resource.',
|
||||
'nickname' => 'get_other-resources',
|
||||
'parameters' =>
|
||||
array(
|
||||
|
||||
array(
|
||||
'paramType' => 'path',
|
||||
'name' => '_format',
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
'enum' =>
|
||||
array(
|
||||
'json',
|
||||
'xml',
|
||||
'html',
|
||||
),
|
||||
),
|
||||
),
|
||||
'responseMessages' =>
|
||||
array(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
array(
|
||||
'path' => '/other-resources/{id}.{_format}',
|
||||
'operations' =>
|
||||
array(
|
||||
|
||||
array(
|
||||
'method' => 'PUT',
|
||||
'summary' => 'Update a resource bu ID.',
|
||||
'nickname' => 'put_other-resources',
|
||||
'parameters' =>
|
||||
array(
|
||||
|
||||
array(
|
||||
'paramType' => 'path',
|
||||
'name' => 'id',
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
),
|
||||
|
||||
array(
|
||||
'paramType' => 'path',
|
||||
'name' => '_format',
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
'enum' =>
|
||||
array(
|
||||
'json',
|
||||
'xml',
|
||||
'html',
|
||||
),
|
||||
),
|
||||
),
|
||||
'responseMessages' =>
|
||||
array(),
|
||||
),
|
||||
|
||||
array(
|
||||
'method' => 'PATCH',
|
||||
'summary' => 'Update a resource bu ID.',
|
||||
'nickname' => 'patch_other-resources',
|
||||
'parameters' =>
|
||||
array(
|
||||
|
||||
array(
|
||||
'paramType' => 'path',
|
||||
'name' => 'id',
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
),
|
||||
|
||||
array(
|
||||
'paramType' => 'path',
|
||||
'name' => '_format',
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
'enum' =>
|
||||
array(
|
||||
'json',
|
||||
'xml',
|
||||
'html',
|
||||
),
|
||||
),
|
||||
),
|
||||
'responseMessages' =>
|
||||
array(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
'models' =>
|
||||
array(),
|
||||
'produces' =>
|
||||
array(),
|
||||
'consumes' =>
|
||||
array(),
|
||||
'authorizations' =>
|
||||
array(),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'/tests',
|
||||
array (
|
||||
'swaggerVersion' => '1.2',
|
||||
'apiVersion' => '3.14',
|
||||
'basePath' => '/api',
|
||||
'resourcePath' => '/tests',
|
||||
'apis' =>
|
||||
array (
|
||||
|
||||
array (
|
||||
'path' => '/tests.{_format}',
|
||||
'operations' =>
|
||||
array (
|
||||
|
||||
array (
|
||||
'method' => 'GET',
|
||||
'summary' => 'index action',
|
||||
'nickname' => 'get_tests',
|
||||
'parameters' =>
|
||||
array (
|
||||
|
||||
array (
|
||||
'paramType' => 'path',
|
||||
'name' => '_format',
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
),
|
||||
),
|
||||
'responseMessages' =>
|
||||
array (
|
||||
),
|
||||
),
|
||||
|
||||
array (
|
||||
'method' => 'GET',
|
||||
'summary' => 'index action',
|
||||
'nickname' => 'get_tests',
|
||||
'parameters' =>
|
||||
array (
|
||||
|
||||
array (
|
||||
'paramType' => 'path',
|
||||
'name' => '_format',
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
),
|
||||
|
||||
array (
|
||||
'paramType' => 'query',
|
||||
'name' => 'a',
|
||||
'type' => 'integer',
|
||||
),
|
||||
|
||||
array (
|
||||
'paramType' => 'query',
|
||||
'name' => 'b',
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
'responseMessages' =>
|
||||
array (
|
||||
),
|
||||
),
|
||||
|
||||
array (
|
||||
'method' => 'POST',
|
||||
'summary' => 'create test',
|
||||
'nickname' => 'post_tests',
|
||||
'parameters' =>
|
||||
array (
|
||||
|
||||
array (
|
||||
'paramType' => 'path',
|
||||
'name' => '_format',
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
),
|
||||
|
||||
array (
|
||||
'paramType' => 'query',
|
||||
'name' => 'a',
|
||||
'type' => 'integer',
|
||||
),
|
||||
|
||||
array (
|
||||
'paramType' => 'query',
|
||||
'name' => 'b',
|
||||
'type' => 'string',
|
||||
),
|
||||
|
||||
array (
|
||||
'paramType' => 'form',
|
||||
'name' => 'a',
|
||||
'type' => 'string',
|
||||
),
|
||||
|
||||
array (
|
||||
'paramType' => 'form',
|
||||
'name' => 'b',
|
||||
'type' => 'string',
|
||||
),
|
||||
|
||||
array (
|
||||
'paramType' => 'form',
|
||||
'name' => 'c',
|
||||
'type' => 'boolean',
|
||||
),
|
||||
|
||||
array (
|
||||
'paramType' => 'form',
|
||||
'name' => 'd',
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
'responseMessages' =>
|
||||
array (
|
||||
),
|
||||
),
|
||||
|
||||
array (
|
||||
'method' => 'POST',
|
||||
'summary' => 'create test',
|
||||
'nickname' => 'post_tests',
|
||||
'parameters' =>
|
||||
array (
|
||||
|
||||
array (
|
||||
'paramType' => 'path',
|
||||
'name' => '_format',
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
),
|
||||
|
||||
array (
|
||||
'paramType' => 'form',
|
||||
'name' => 'a',
|
||||
'type' => 'string',
|
||||
),
|
||||
|
||||
array (
|
||||
'paramType' => 'form',
|
||||
'name' => 'b',
|
||||
'type' => 'string',
|
||||
),
|
||||
|
||||
array (
|
||||
'paramType' => 'form',
|
||||
'name' => 'c',
|
||||
'type' => 'boolean',
|
||||
),
|
||||
|
||||
array (
|
||||
'paramType' => 'form',
|
||||
'name' => 'd',
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
'responseMessages' =>
|
||||
array (
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
'models' =>
|
||||
array (
|
||||
),
|
||||
'produces' =>
|
||||
array (
|
||||
),
|
||||
'consumes' =>
|
||||
array (
|
||||
),
|
||||
'authorizations' =>
|
||||
array (
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user