Merge pull request #469 from bezhermoso/collections

Support collections on output (including named collections)
This commit is contained in:
William Durand 2014-09-06 11:33:45 +02:00
commit 4b163e1b80
11 changed files with 1230 additions and 354 deletions

View File

@ -373,6 +373,24 @@ class ApiDocExtractor
$input = array('class' => $input); $input = array('class' => $input);
} }
$collectionData = array();
/*
* Match array<Fully\Qualified\ClassName> as alias; "as alias" optional.
*/
if (preg_match_all("/^array<([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*)>(?:\\s+as\\s+(.+))?$/", $input['class'], $collectionData)) {
$input['class'] = $collectionData[1][0];
$input['collection'] = true;
$input['collectionName'] = $collectionData[2][0];
} elseif (preg_match('/^array</', $input['class'])) { //See if a collection directive was attempted. Must be malformed.
throw new \InvalidArgumentException(
sprintf(
'Malformed collection directive: %s. Proper format is: array<Fully\\Qualified\\ClassName> or array<Fully\\Qualified\\ClassName> as collectionName',
$input['class']
)
);
}
// normalize groups // normalize groups
if (isset($input['groups']) && is_string($input['groups'])) { if (isset($input['groups']) && is_string($input['groups'])) {
$input['groups'] = array_map('trim', explode(',', $input['groups'])); $input['groups'] = array_map('trim', explode(',', $input['groups']));
@ -390,6 +408,9 @@ class ApiDocExtractor
* - Array parameters are recursively merged. * - Array parameters are recursively merged.
* - Non-null default values prevail over null default values. Later values overrides previous defaults. * - Non-null default values prevail over null default values. Later values overrides previous defaults.
* *
* However, if newly-returned parameter array contains a parameter with NULL, the parameter is removed from the merged results.
* If the parameter is not present in the newly-returned array, then it is left as-is.
*
* @param array $p1 The pre-existing parameters array. * @param array $p1 The pre-existing parameters array.
* @param array $p2 The newly-returned parameters array. * @param array $p2 The newly-returned parameters array.
* @return array The resulting, merged array. * @return array The resulting, merged array.
@ -399,9 +420,15 @@ class ApiDocExtractor
$params = $p1; $params = $p1;
foreach ($p2 as $propname => $propvalue) { foreach ($p2 as $propname => $propvalue) {
if ($propvalue === null) {
unset($params[$propname]);
continue;
}
if (!isset($p1[$propname])) { if (!isset($p1[$propname])) {
$params[$propname] = $propvalue; $params[$propname] = $propvalue;
} else { } elseif (is_array($propvalue)) {
$v1 = $p1[$propname]; $v1 = $p1[$propname];
foreach ($propvalue as $name => $value) { foreach ($propvalue as $name => $value) {

View File

@ -11,7 +11,6 @@
namespace Nelmio\ApiDocBundle\Formatter; namespace Nelmio\ApiDocBundle\Formatter;
use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Nelmio\ApiDocBundle\DataTypes; use Nelmio\ApiDocBundle\DataTypes;
use Nelmio\ApiDocBundle\Swagger\ModelRegistry; use Nelmio\ApiDocBundle\Swagger\ModelRegistry;
@ -276,11 +275,44 @@ class SwaggerFormatter implements FormatterInterface
$message = sprintf('See standard HTTP status code reason for %s', $statusCode); $message = sprintf('See standard HTTP status code reason for %s', $statusCode);
} }
$responseModel = array( if (isset($prop['type']['collection']) && $prop['type']['collection'] === true) {
'code' => $statusCode,
'message' => $message, /*
'responseModel' => $this->registerModel($prop['type']['class'], $prop['model'], ''), * Without alias: Fully\Qualified\Class\Name[]
); * With alias: Fully\Qualified\Class\Name[alias]
*/
$alias = $prop['type']['collectionName'];
$newName = sprintf('%s[%s]', $prop['type']['class'], $alias);
$collId =
$this->registerModel(
$newName,
array(
$alias => array(
'dataType' => null,
'subType' => $prop['type']['class'],
'actualType' => DataTypes::COLLECTION,
'required' => true,
'readonly' => true,
'description' => null,
'default' => null,
'children' => $prop['model'][$alias]['children'],
)
),
''
);
$responseModel = array(
'code' => $statusCode,
'message' => $message,
'responseModel' => $collId
);
} else {
$responseModel = array(
'code' => $statusCode,
'message' => $message,
'responseModel' => $this->registerModel($prop['type']['class'], $prop['model'], ''),
);
}
$responseMessages[$statusCode] = $responseModel; $responseMessages[$statusCode] = $responseModel;
} }
@ -416,19 +448,20 @@ class SwaggerFormatter implements FormatterInterface
case DataTypes::COLLECTION: case DataTypes::COLLECTION:
$type = 'array'; $type = 'array';
if ($prop['subType'] === DataTypes::MODEL) { if ($prop['subType'] === null) {
$ref = $this->registerModel( $items = array('type' => 'string');
$prop['subType'],
isset($prop['children']) ? $prop['children'] : null,
$prop['description'] ?: $prop['dataType']
);
$items = array(
'$ref' => $ref,
);
} elseif (isset($this->typeMap[$prop['subType']])) { } elseif (isset($this->typeMap[$prop['subType']])) {
$items = array('type' => $this->typeMap[$prop['subType']]); $items = array('type' => $this->typeMap[$prop['subType']]);
} else { } else {
$items = array('type' => 'string'); $ref =
$this->registerModel(
$prop['subType'],
isset($prop['children']) ? $prop['children'] : null,
$prop['description'] ?: $prop['dataType']
);
$items = array(
'$ref' => $ref,
);
} }
break; break;
} }

View File

@ -0,0 +1,77 @@
<?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\Parser;
use Nelmio\ApiDocBundle\DataTypes;
/**
* Handles models that are specified as collections.
*
* @author Bez Hermoso <bez@activelamp.com>
*/
class CollectionParser implements ParserInterface, PostParserInterface
{
/**
* Return true/false whether this class supports parsing the given class.
*
* @param array $item containing the following fields: class, groups. Of which groups is optional
*
* @return boolean
*/
public function supports(array $item)
{
return isset($item['collection']) && $item['collection'] === true;
}
/**
* This doesn't parse anything at this stage.
*
* @param array $item
*
* @return array
*/
public function parse(array $item)
{
return array();
}
/**
* @param array|string $item The string type of input to parse.
* @param array $parameters The previously-parsed parameters array.
*
* @return array
*/
public function postParse(array $item, array $parameters)
{
$origParameters = $parameters;
foreach ($parameters as $name => $body) {
$parameters[$name] = null;
}
$collectionName = isset($item['collectionName']) ? $item['collectionName'] : '';
$parameters[$collectionName] = array(
'dataType' => null, // Delegates to ApiDocExtractor#generateHumanReadableTypes
'subType' => $item['class'],
'actualType' => DataTypes::COLLECTION,
'readonly' => true,
'required' => true,
'default' => true,
'description' => '',
'children' => $origParameters,
);
return $parameters;
}
}

View File

@ -13,6 +13,8 @@
<parameter key="nelmio_api_doc.extractor.handler.jms_security.class">Nelmio\ApiDocBundle\Extractor\Handler\JmsSecurityExtraHandler</parameter> <parameter key="nelmio_api_doc.extractor.handler.jms_security.class">Nelmio\ApiDocBundle\Extractor\Handler\JmsSecurityExtraHandler</parameter>
<parameter key="nelmio_api_doc.extractor.handler.sensio_framework_extra.class">Nelmio\ApiDocBundle\Extractor\Handler\SensioFrameworkExtraHandler</parameter> <parameter key="nelmio_api_doc.extractor.handler.sensio_framework_extra.class">Nelmio\ApiDocBundle\Extractor\Handler\SensioFrameworkExtraHandler</parameter>
<parameter key="nelmio_api_doc.extractor.handler.phpdoc.class">Nelmio\ApiDocBundle\Extractor\Handler\PhpDocHandler</parameter> <parameter key="nelmio_api_doc.extractor.handler.phpdoc.class">Nelmio\ApiDocBundle\Extractor\Handler\PhpDocHandler</parameter>
<parameter key="nelmio_api_doc.parser.collection_parser.class">Nelmio\ApiDocBundle\Parser\CollectionParser</parameter>
</parameters> </parameters>
<services> <services>
@ -52,6 +54,10 @@
<argument type="service" id="nelmio_api_doc.doc_comment_extractor" /> <argument type="service" id="nelmio_api_doc.doc_comment_extractor" />
<tag name="nelmio_api_doc.extractor.handler"/> <tag name="nelmio_api_doc.extractor.handler"/>
</service> </service>
<service id="nelmio_api_doc.parser.collection_parser" class="%nelmio_api_doc.parser.collection_parser.class%">
<tag name="nelmio_api_doc.extractor.parser" />
</service>
</services> </services>
</container> </container>

View File

@ -130,14 +130,13 @@ class ModelRegistry
case DataTypes::COLLECTION: case DataTypes::COLLECTION:
$type = 'array'; $type = 'array';
if ($prop['subType'] === DataTypes::MODEL) { if ($prop['subType'] === null) {
$items = array(
} else { 'type' => 'string',
);
if ($prop['subType'] === null } elseif (isset($this->typeMap[$prop['subType']])) {
|| isset($this->typeMap[$prop['subType']])) {
$items = array( $items = array(
'type' => 'string', 'type' => $this->typeMap[$prop['subType']]
); );
} elseif (!isset($this->typeMap[$prop['subType']])) { } elseif (!isset($this->typeMap[$prop['subType']])) {
$items = array( $items = array(
@ -149,7 +148,6 @@ class ModelRegistry
) )
); );
} }
}
/* @TODO: Handle recursion if subtype is a model. */ /* @TODO: Handle recursion if subtype is a model. */
break; break;
@ -213,8 +211,9 @@ class ModelRegistry
{ {
/* /*
* Converts \Fully\Qualified\Class\Name to Fully.Qualified.Class.Name * Converts \Fully\Qualified\Class\Name to Fully.Qualified.Class.Name
* "[...]" in aliased and non-aliased collections preserved.
*/ */
$id = preg_replace('#(\\\|[^A-Za-z0-9])#', '.', $className); $id = preg_replace('#(\\\|[^A-Za-z0-9\[\]])#', '.', $className);
//Replace duplicate dots. //Replace duplicate dots.
$id = preg_replace('/\.+/', '.', $id); $id = preg_replace('/\.+/', '.', $id);
//Replace trailing dots. //Replace trailing dots.

View File

@ -0,0 +1,107 @@
<?php
namespace Nelmio\ApiDocBundle\Tests\Extractor;
class CollectionDirectiveTest extends \PHPUnit_Framework_TestCase
{
/**
* @var TestExtractor
*/
private $testExtractor;
public function setUp()
{
$this->testExtractor = new TestExtractor();
}
private function normalize($input)
{
return $this->testExtractor->getNormalization($input);
}
/**
* @dataProvider dataNormalizationTests
*/
public function testNormalizations($input, callable $callable)
{
call_user_func($callable, $this->normalize($input), $this);
}
public function dataNormalizationTests()
{
return array(
'test_simple_notation' => array(
'array<User>',
function ($actual, \PHPUnit_Framework_TestCase $case) {
$case->assertArrayHasKey('collection', $actual);
$case->assertArrayHasKey('collectionName', $actual);
$case->assertArrayHasKey('class', $actual);
$case->assertTrue($actual['collection']);
$case->assertEquals('', $actual['collectionName']);
$case->assertEquals('User', $actual['class']);
}
),
'test_simple_notation_with_namespaces' => array(
'array<Vendor0_2\\_Namespace1\\Namespace_2\\User>',
function ($actual, \PHPUnit_Framework_TestCase $case) {
$case->assertArrayHasKey('collection', $actual);
$case->assertArrayHasKey('collectionName', $actual);
$case->assertArrayHasKey('class', $actual);
$case->assertTrue($actual['collection']);
$case->assertEquals('', $actual['collectionName']);
$case->assertEquals('Vendor0_2\\_Namespace1\\Namespace_2\\User', $actual['class']);
}
),
'test_simple_named_collections' => array(
'array<Group> as groups',
function ($actual, \PHPUnit_Framework_TestCase $case) {
$case->assertArrayHasKey('collection', $actual);
$case->assertArrayHasKey('collectionName', $actual);
$case->assertArrayHasKey('class', $actual);
$case->assertTrue($actual['collection']);
$case->assertEquals('groups', $actual['collectionName']);
$case->assertEquals('Group', $actual['class']);
}
),
'test_namespaced_named_collections' => array(
'array<_Vendor\\Namespace0\\Namespace_2F3\\Group> as groups',
function ($actual, \PHPUnit_Framework_TestCase $case) {
$case->assertArrayHasKey('collection', $actual);
$case->assertArrayHasKey('collectionName', $actual);
$case->assertArrayHasKey('class', $actual);
$case->assertTrue($actual['collection']);
$case->assertEquals('groups', $actual['collectionName']);
$case->assertEquals('_Vendor\\Namespace0\\Namespace_2F3\\Group', $actual['class']);
}
),
);
}
/**
* @expectedException \InvalidArgumentException
* @dataProvider dataInvalidDirectives
* @param $input
*/
public function testInvalidDirectives($input)
{
$this->normalize($input);
}
public function dataInvalidDirectives()
{
return array(
array('array<>'),
array('array<Vendor\\>'),
array('array<2Vendor\\>'),
array('array<Vendor\\2Class>'),
array('array<User> as'),
array('array<User> as '),
);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Nelmio\ApiDocBundle\Tests\Extractor;
use Nelmio\ApiDocBundle\Extractor\ApiDocExtractor;
class TestExtractor extends ApiDocExtractor
{
public function __construct()
{
}
public function getNormalization($input)
{
return $this->normalizeClassParameter($input);
}
}

View File

@ -19,6 +19,7 @@ class ResourceController
* resource=true, * resource=true,
* resourceDescription="Operations on resource.", * resourceDescription="Operations on resource.",
* description="List resources.", * description="List resources.",
* output="array<Nelmio\ApiDocBundle\Tests\Fixtures\Model\Test> as tests",
* statusCodes={200 = "Returned on success.", 404 = "Returned if resource cannot be found."} * statusCodes={200 = "Returned on success.", 404 = "Returned if resource cannot be found."}
* ) * )
*/ */
@ -56,7 +57,12 @@ class ResourceController
} }
/** /**
* @ApiDoc(resource=true, description="List another resource.", resourceDescription="Operations on another resource.") * @ApiDoc(
* resource=true,
* description="List another resource.",
* resourceDescription="Operations on another resource.",
* output="array<Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest>"
* )
*/ */
public function listAnotherResourcesAction() public function listAnotherResourcesAction()
{ {

View File

@ -38,6 +38,98 @@ _List another resource._
- Requirement: json|xml|html - Requirement: json|xml|html
#### Response ####
[]:
* type: array of objects (JmsTest)
[][foo]:
* type: string
[][bar]:
* type: DateTime
[][number]:
* type: double
[][arr]:
* type: array
[][nested]:
* type: object (JmsNested)
[][nested][foo]:
* type: DateTime
[][nested][bar]:
* type: string
[][nested][baz][]:
* type: array of integers
* description: Epic description.
With multiple lines.
[][nested][circular]:
* type: object (JmsNested)
[][nested][parent]:
* type: object (JmsTest)
[][nested][parent][foo]:
* type: string
[][nested][parent][bar]:
* type: DateTime
[][nested][parent][number]:
* type: double
[][nested][parent][arr]:
* type: array
[][nested][parent][nested]:
* type: object (JmsNested)
[][nested][parent][nested_array][]:
* type: array of objects (JmsNested)
[][nested][since]:
* type: string
* versions: >=0.2
[][nested][until]:
* type: string
* versions: <=0.3
[][nested][since_and_until]:
* type: string
* versions: >=0.4,<=0.5
[][nested_array][]:
* type: array of objects (JmsNested)
### `PUT|PATCH` /api/other-resources/{id}.{_format} ### ### `PUT|PATCH` /api/other-resources/{id}.{_format} ###
@ -64,6 +156,20 @@ _List resources._
- Requirement: json|xml|html - Requirement: json|xml|html
#### Response ####
tests[]:
* type: array of objects (Test)
tests[][a]:
* type: string
tests[][b]:
* type: DateTime
### `POST` /api/resources.{_format} ### ### `POST` /api/resources.{_format} ###

View File

@ -1333,6 +1333,269 @@ With multiple lines.',
'authenticationRoles' => 'authenticationRoles' =>
array(), array(),
'deprecated' => false, 'deprecated' => false,
'response' => array(
'' =>
array(
'dataType' => 'array of objects (JmsTest)',
'subType' => 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsTest',
'actualType' => 'collection',
'readonly' => true,
'required' => true,
'default' => true,
'description' => '',
'children' =>
array(
'foo' =>
array(
'dataType' => 'string',
'actualType' => 'string',
'subType' => null,
'required' => false,
'default' => null,
'description' => '',
'readonly' => false,
'sinceVersion' => null,
'untilVersion' => null,
),
'bar' =>
array(
'dataType' => 'DateTime',
'actualType' => 'datetime',
'subType' => null,
'required' => false,
'default' => null,
'description' => '',
'readonly' => true,
'sinceVersion' => null,
'untilVersion' => null,
),
'number' =>
array(
'dataType' => 'double',
'actualType' => 'float',
'subType' => null,
'required' => false,
'default' => null,
'description' => '',
'readonly' => false,
'sinceVersion' => null,
'untilVersion' => null,
),
'arr' =>
array(
'dataType' => 'array',
'actualType' => 'collection',
'subType' => null,
'required' => false,
'default' => null,
'description' => '',
'readonly' => false,
'sinceVersion' => null,
'untilVersion' => null,
),
'nested' =>
array(
'dataType' => 'object (JmsNested)',
'actualType' => 'model',
'subType' => 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsNested',
'required' => false,
'default' => null,
'description' => '',
'readonly' => false,
'sinceVersion' => null,
'untilVersion' => null,
'children' =>
array(
'foo' =>
array(
'dataType' => 'DateTime',
'actualType' => 'datetime',
'subType' => null,
'required' => false,
'default' => null,
'description' => '',
'readonly' => true,
'sinceVersion' => null,
'untilVersion' => null,
),
'bar' =>
array(
'dataType' => 'string',
'actualType' => 'string',
'subType' => null,
'required' => false,
'default' => 'baz',
'description' => '',
'readonly' => false,
'sinceVersion' => null,
'untilVersion' => null,
),
'baz' =>
array(
'dataType' => 'array of integers',
'actualType' => 'collection',
'subType' => 'integer',
'required' => false,
'default' => null,
'description' => 'Epic description.
With multiple lines.',
'readonly' => false,
'sinceVersion' => null,
'untilVersion' => null,
),
'circular' =>
array(
'dataType' => 'object (JmsNested)',
'actualType' => 'model',
'subType' => 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsNested',
'required' => false,
'default' => null,
'description' => '',
'readonly' => false,
'sinceVersion' => null,
'untilVersion' => null,
),
'parent' =>
array(
'dataType' => 'object (JmsTest)',
'actualType' => 'model',
'subType' => 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsTest',
'required' => false,
'default' => null,
'description' => '',
'readonly' => false,
'sinceVersion' => null,
'untilVersion' => null,
'children' =>
array(
'foo' =>
array(
'dataType' => 'string',
'actualType' => 'string',
'subType' => null,
'required' => false,
'default' => null,
'description' => '',
'readonly' => false,
'sinceVersion' => null,
'untilVersion' => null,
),
'bar' =>
array(
'dataType' => 'DateTime',
'actualType' => 'datetime',
'subType' => null,
'required' => false,
'default' => null,
'description' => '',
'readonly' => true,
'sinceVersion' => null,
'untilVersion' => null,
),
'number' =>
array(
'dataType' => 'double',
'actualType' => 'float',
'subType' => null,
'required' => false,
'default' => null,
'description' => '',
'readonly' => false,
'sinceVersion' => null,
'untilVersion' => null,
),
'arr' =>
array(
'dataType' => 'array',
'actualType' => 'collection',
'subType' => null,
'required' => false,
'default' => null,
'description' => '',
'readonly' => false,
'sinceVersion' => null,
'untilVersion' => null,
),
'nested' =>
array(
'dataType' => 'object (JmsNested)',
'actualType' => 'model',
'subType' => 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsNested',
'required' => false,
'default' => null,
'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,
'default' => null,
'description' => '',
'readonly' => false,
'sinceVersion' => null,
'untilVersion' => null,
),
),
),
'since' =>
array(
'dataType' => 'string',
'actualType' => 'string',
'subType' => null,
'required' => false,
'default' => null,
'description' => '',
'readonly' => false,
'sinceVersion' => '0.2',
'untilVersion' => null,
),
'until' =>
array(
'dataType' => 'string',
'actualType' => 'string',
'subType' => null,
'required' => false,
'default' => null,
'description' => '',
'readonly' => false,
'sinceVersion' => null,
'untilVersion' => '0.3',
),
'since_and_until' =>
array(
'dataType' => 'string',
'actualType' => 'string',
'subType' => null,
'required' => false,
'default' => null,
'description' => '',
'readonly' => false,
'sinceVersion' => '0.4',
'untilVersion' => '0.5',
),
),
),
'nested_array' =>
array(
'dataType' => 'array of objects (JmsNested)',
'actualType' => 'collection',
'subType' => 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsNested',
'required' => false,
'default' => null,
'description' => '',
'readonly' => false,
'sinceVersion' => null,
'untilVersion' => null,
),
),
),
),
), ),
array( array(
'method' => 'PUT|PATCH', 'method' => 'PUT|PATCH',
@ -1392,6 +1655,41 @@ With multiple lines.',
'authenticationRoles' => 'authenticationRoles' =>
array(), array(),
'deprecated' => false, 'deprecated' => false,
'response' =>
array (
'tests' =>
array (
'dataType' => 'array of objects (Test)',
'subType' => 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\Test',
'actualType' => 'collection',
'readonly' => true,
'required' => true,
'default' => true,
'description' => '',
'children' =>
array (
'a' =>
array (
'default' => 'nelmio',
'actualType' => 'string',
'subType' => NULL,
'format' => '{length: min: foo}, {not blank}',
'required' => true,
'dataType' => 'string',
'readonly' => NULL,
),
'b' =>
array (
'default' => NULL,
'actualType' => 'datetime',
'subType' => NULL,
'dataType' => 'DateTime',
'readonly' => NULL,
'required' => NULL,
),
),
),
),
), ),
array( array(
'method' => 'POST', 'method' => 'POST',

View File

@ -47,7 +47,6 @@ class SwaggerFormatterTest extends WebTestCase
$actual = $this->formatter->format($data, null); $actual = $this->formatter->format($data, null);
$expected = array( $expected = array(
'swaggerVersion' => '1.2', 'swaggerVersion' => '1.2',
'apiVersion' => '3.14', 'apiVersion' => '3.14',
@ -122,441 +121,640 @@ class SwaggerFormatterTest extends WebTestCase
return array( return array(
array( array(
'/resources', '/resources',
array( array (
'swaggerVersion' => '1.2', 'swaggerVersion' => '1.2',
'apiVersion' => '3.14', 'apiVersion' => '3.14',
'basePath' => '/api', 'basePath' => '/api',
'resourcePath' => '/resources', 'resourcePath' => '/resources',
'apis' => 'apis' =>
array( array (
0 =>
array( array (
'path' => '/resources.{_format}', 'path' => '/resources.{_format}',
'operations' => 'operations' =>
array( array (
array( 0 =>
'method' => 'GET', array (
'summary' => 'List resources.', 'method' => 'GET',
'nickname' => 'get_resources', 'summary' => 'List resources.',
'parameters' => 'nickname' => 'get_resources',
array( 'parameters' =>
array (
array( 0 =>
'paramType' => 'path', array (
'name' => '_format', 'paramType' => 'path',
'type' => 'string', 'name' => '_format',
'required' => true, 'type' => 'string',
'enum' => 'required' => true,
array( 'enum' =>
'json', array (
'xml', 0 => 'json',
'html', 1 => 'xml',
), 2 => 'html',
), ),
),
),
'responseMessages' =>
array (
0 =>
array (
'code' => 200,
'message' => 'Returned on success.',
'responseModel' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.Test[tests]',
),
1 =>
array (
'code' => 404,
'message' => 'Returned if resource cannot be found.',
),
),
'type' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.Test[tests]',
), ),
'responseMessages' => 1 =>
array( array (
'method' => 'POST',
array( 'summary' => 'Create a new resource.',
'code' => 200, 'nickname' => 'post_resources',
'message' => 'Returned on success.', 'parameters' =>
), array (
0 =>
array( array (
'code' => 404, 'paramType' => 'path',
'message' => 'Returned if resource cannot be found.', 'name' => '_format',
), 'type' => 'string',
'required' => true,
'enum' =>
array (
0 => 'json',
1 => 'xml',
2 => 'html',
),
),
1 =>
array (
'paramType' => 'form',
'name' => 'a',
'type' => 'string',
),
2 =>
array (
'paramType' => 'form',
'name' => 'b',
'type' => 'number',
'format' => 'float',
),
3 =>
array (
'paramType' => 'form',
'name' => 'c',
'type' => 'string',
'enum' =>
array (
0 => 'x',
1 => 'y',
2 => 'z',
),
),
4 =>
array (
'paramType' => 'form',
'name' => 'd',
'type' => 'string',
'format' => 'date-time',
),
5 =>
array (
'paramType' => 'form',
'name' => 'e',
'type' => 'string',
'format' => 'date',
),
6 =>
array (
'paramType' => 'form',
'name' => 'g',
'type' => 'string',
),
),
'responseMessages' =>
array (
0 =>
array (
'code' => 200,
'message' => 'See standard HTTP status code reason for 200',
'responseModel' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested',
),
),
'type' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested',
), ),
), ),
),
array( 1 =>
'method' => 'POST', array (
'summary' => 'Create a new resource.', 'path' => '/resources/{id}.{_format}',
'nickname' => 'post_resources', 'operations' =>
'parameters' => array (
array( 0 =>
array (
array( 'method' => 'GET',
'paramType' => 'path', 'summary' => 'Retrieve a resource by ID.',
'name' => '_format', 'nickname' => 'get_resources',
'type' => 'string', 'parameters' =>
'required' => true, array (
'enum' => 0 =>
array( array (
'json', 'paramType' => 'path',
'xml', 'name' => 'id',
'html', 'type' => 'string',
), 'required' => true,
), ),
1 =>
array( array (
'paramType' => 'form', 'paramType' => 'path',
'name' => 'a', 'name' => '_format',
'type' => 'string', 'type' => 'string',
), 'required' => true,
'enum' =>
array( array (
'paramType' => 'form', 0 => 'json',
'name' => 'b', 1 => 'xml',
'type' => 'number', 2 => 'html',
'format' => 'float', ),
), ),
),
array( 'responseMessages' =>
'paramType' => 'form', array (
'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' => 1 =>
array( array (
array( 'method' => 'DELETE',
'code' => 200, 'summary' => 'Delete a resource by ID.',
'message' => 'See standard HTTP status code reason for 200', 'nickname' => 'delete_resources',
'responseModel' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested', 'parameters' =>
), array (
0 =>
array (
'paramType' => 'path',
'name' => 'id',
'type' => 'string',
'required' => true,
),
1 =>
array (
'paramType' => 'path',
'name' => '_format',
'type' => 'string',
'required' => true,
'enum' =>
array (
0 => 'json',
1 => 'xml',
2 => 'html',
),
),
),
'responseMessages' =>
array (
),
), ),
'type' => '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' => 'models' =>
array( array (
'Nelmio.ApiDocBundle.Tests.Fixtures.Model.Test' =>
array (
'id' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.Test',
'description' => NULL,
'properties' =>
array (
'a' =>
array (
'type' => 'string',
'description' => 'string',
),
'b' =>
array (
'type' => 'string',
'description' => 'DateTime',
'format' => 'date-time',
),
),
'required' =>
array (
0 => 'a',
),
),
'Nelmio.ApiDocBundle.Tests.Fixtures.Model.Test[tests]' =>
array (
'id' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.Test[tests]',
'description' => '',
'properties' =>
array (
'tests' =>
array (
'type' => 'array',
'description' => NULL,
'items' =>
array (
'$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.Test',
),
),
),
'required' =>
array (
0 => 'tests',
),
),
'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest' =>
array( array (
'id' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest', 'id' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest',
'description' => 'object (JmsTest)', 'description' => 'object (JmsTest)',
'properties' => 'properties' =>
array( array (
'foo' => 'foo' =>
array( array (
'type' => 'string', 'type' => 'string',
'description' => 'string', 'description' => 'string',
), ),
'bar' => 'bar' =>
array( array (
'type' => 'string', 'type' => 'string',
'description' => 'DateTime', 'description' => 'DateTime',
'format' => 'date-time', 'format' => 'date-time',
), ),
'number' => 'number' =>
array( array (
'type' => 'number', 'type' => 'number',
'description' => 'double', 'description' => 'double',
'format' => 'float', 'format' => 'float',
), ),
'arr' => 'arr' =>
array( array (
'type' => 'array', 'type' => 'array',
'description' => 'array', 'description' => 'array',
'items' => array( 'items' =>
'type' => 'string', array (
) 'type' => 'string',
),
), ),
'nested' => 'nested' =>
array( array (
'$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested', '$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested',
), ),
'nested_array' => 'nested_array' =>
array( array (
'type' => 'array', 'type' => 'array',
'description' => 'array of objects (JmsNested)', 'description' => 'array of objects (JmsNested)',
'items' => array( 'items' =>
'$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested', array (
) '$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested',
),
), ),
), ),
'required' => 'required' =>
array(), array (
),
), ),
'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested' =>
array( array (
'id' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested', 'id' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested',
'description' => '', 'description' => '',
'properties' => 'properties' =>
array( array (
'foo' => 'foo' =>
array( array (
'type' => 'string', 'type' => 'string',
'description' => 'DateTime', 'description' => 'DateTime',
'format' => 'date-time', 'format' => 'date-time',
), ),
'bar' => 'bar' =>
array( array (
'type' => 'string', 'type' => 'string',
'description' => 'string', 'description' => 'string',
), ),
'baz' => 'baz' =>
array( array (
'type' => 'array', 'type' => 'array',
'description' => 'Epic description. 'description' => 'Epic description.
With multiple lines.', With multiple lines.',
'items' => array( 'items' =>
'type' => 'string', array (
) 'type' => 'integer',
),
), ),
'circular' => 'circular' =>
array( array (
'$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested', '$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested',
), ),
'parent' => 'parent' =>
array( array (
'$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest', '$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest',
), ),
'since' => 'since' =>
array( array (
'type' => 'string', 'type' => 'string',
'description' => 'string', 'description' => 'string',
), ),
'until' => 'until' =>
array( array (
'type' => 'string', 'type' => 'string',
'description' => 'string', 'description' => 'string',
), ),
'since_and_until' => 'since_and_until' =>
array( array (
'type' => 'string', 'type' => 'string',
'description' => 'string', 'description' => 'string',
), ),
), ),
'required' => 'required' =>
array(), array (
),
), ),
), ),
'produces' => 'produces' =>
array(), array (
),
'consumes' => 'consumes' =>
array(), array (
),
'authorizations' => 'authorizations' =>
array( array (
'apiKey' => array( 'apiKey' =>
'type' => 'apiKey', array (
'passAs' => 'header', 'type' => 'apiKey',
'keyname' => 'access_token', 'passAs' => 'header',
) 'keyname' => 'access_token',
),
), ),
), ),
), ),
array( array(
'/other-resources', '/other-resources',
array( array (
'swaggerVersion' => '1.2', 'swaggerVersion' => '1.2',
'apiVersion' => '3.14', 'apiVersion' => '3.14',
'basePath' => '/api', 'basePath' => '/api',
'resourcePath' => '/other-resources', 'resourcePath' => '/other-resources',
'apis' => 'apis' =>
array( array (
0 =>
array( array (
'path' => '/other-resources.{_format}', 'path' => '/other-resources.{_format}',
'operations' => 'operations' =>
array( array (
0 =>
array( array (
'method' => 'GET', 'method' => 'GET',
'summary' => 'List another resource.', 'summary' => 'List another resource.',
'nickname' => 'get_other-resources', 'nickname' => 'get_other-resources',
'parameters' => 'parameters' =>
array( array (
0 =>
array( array (
'paramType' => 'path', 'paramType' => 'path',
'name' => '_format', 'name' => '_format',
'type' => 'string', 'type' => 'string',
'required' => true, 'required' => true,
'enum' => 'enum' =>
array( array (
'json', 0 => 'json',
'xml', 1 => 'xml',
'html', 2 => 'html',
), ),
), ),
),
'responseMessages' =>
array (
0 =>
array (
'code' => 200,
'message' => 'See standard HTTP status code reason for 200',
'responseModel' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest[]',
),
),
'type' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest[]',
), ),
'responseMessages' =>
array(),
), ),
), ),
), 1 =>
array (
array( 'path' => '/other-resources/{id}.{_format}',
'path' => '/other-resources/{id}.{_format}', 'operations' =>
'operations' => array (
array( 0 =>
array (
array( 'method' => 'PUT',
'method' => 'PUT', 'summary' => 'Update a resource bu ID.',
'summary' => 'Update a resource bu ID.', 'nickname' => 'put_other-resources',
'nickname' => 'put_other-resources', 'parameters' =>
'parameters' => array (
array( 0 =>
array (
array( 'paramType' => 'path',
'paramType' => 'path', 'name' => 'id',
'name' => 'id', 'type' => 'string',
'type' => 'string', 'required' => true,
'required' => true, ),
), 1 =>
array (
array( 'paramType' => 'path',
'paramType' => 'path', 'name' => '_format',
'name' => '_format', 'type' => 'string',
'type' => 'string', 'required' => true,
'required' => true, 'enum' =>
'enum' => array (
array( 0 => 'json',
'json', 1 => 'xml',
'xml', 2 => 'html',
'html', ),
), ),
), ),
'responseMessages' =>
array (
),
), ),
'responseMessages' => 1 =>
array(), array (
), 'method' => 'PATCH',
'summary' => 'Update a resource bu ID.',
array( 'nickname' => 'patch_other-resources',
'method' => 'PATCH', 'parameters' =>
'summary' => 'Update a resource bu ID.', array (
'nickname' => 'patch_other-resources', 0 =>
'parameters' => array (
array( 'paramType' => 'path',
'name' => 'id',
array( 'type' => 'string',
'paramType' => 'path', 'required' => true,
'name' => 'id', ),
'type' => 'string', 1 =>
'required' => true, array (
), 'paramType' => 'path',
'name' => '_format',
array( 'type' => 'string',
'paramType' => 'path', 'required' => true,
'name' => '_format', 'enum' =>
'type' => 'string', array (
'required' => true, 0 => 'json',
'enum' => 1 => 'xml',
array( 2 => 'html',
'json', ),
'xml', ),
'html', ),
), 'responseMessages' =>
), array (
),
), ),
'responseMessages' =>
array(),
), ),
), ),
),
), ),
'models' => 'models' =>
array(), array (
'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest' =>
array (
'id' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest',
'description' => NULL,
'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' => 'object (JmsNested)',
'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' => 'integer',
),
),
'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 (
),
),
'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest[]' =>
array (
'id' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest[]',
'description' => '',
'properties' =>
array (
'' =>
array (
'type' => 'array',
'description' => NULL,
'items' =>
array (
'$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest',
),
),
),
'required' =>
array (
0 => '',
),
),
),
'produces' => 'produces' =>
array(), array (
),
'consumes' => 'consumes' =>
array(), array (
),
'authorizations' => 'authorizations' =>
array( array (
'apiKey' => array( 'apiKey' =>
'type' => 'apiKey', array (
'passAs' => 'header', 'type' => 'apiKey',
'keyname' => 'access_token', 'passAs' => 'header',
) 'keyname' => 'access_token',
),
), ),
), ),
), ),