diff --git a/Extractor/ApiDocExtractor.php b/Extractor/ApiDocExtractor.php index 133a2d5..9241516 100644 --- a/Extractor/ApiDocExtractor.php +++ b/Extractor/ApiDocExtractor.php @@ -373,6 +373,24 @@ class ApiDocExtractor $input = array('class' => $input); } + $collectionData = array(); + + /* + * Match array 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 or array as collectionName', + $input['class'] + ) + ); + } + // normalize groups if (isset($input['groups']) && is_string($input['groups'])) { $input['groups'] = array_map('trim', explode(',', $input['groups'])); @@ -390,6 +408,9 @@ class ApiDocExtractor * - Array parameters are recursively merged. * - 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 $p2 The newly-returned parameters array. * @return array The resulting, merged array. @@ -399,9 +420,15 @@ class ApiDocExtractor $params = $p1; foreach ($p2 as $propname => $propvalue) { + + if ($propvalue === null) { + unset($params[$propname]); + continue; + } + if (!isset($p1[$propname])) { $params[$propname] = $propvalue; - } else { + } elseif (is_array($propvalue)) { $v1 = $p1[$propname]; foreach ($propvalue as $name => $value) { diff --git a/Formatter/SwaggerFormatter.php b/Formatter/SwaggerFormatter.php index a8bfe7c..8599959 100644 --- a/Formatter/SwaggerFormatter.php +++ b/Formatter/SwaggerFormatter.php @@ -11,7 +11,6 @@ namespace Nelmio\ApiDocBundle\Formatter; - use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\DataTypes; use Nelmio\ApiDocBundle\Swagger\ModelRegistry; @@ -276,11 +275,44 @@ class SwaggerFormatter implements FormatterInterface $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'], ''), - ); + if (isset($prop['type']['collection']) && $prop['type']['collection'] === true) { + + /* + * 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; } @@ -416,19 +448,20 @@ class SwaggerFormatter implements FormatterInterface case DataTypes::COLLECTION: $type = 'array'; - if ($prop['subType'] === DataTypes::MODEL) { - $ref = $this->registerModel( - $prop['subType'], - isset($prop['children']) ? $prop['children'] : null, - $prop['description'] ?: $prop['dataType'] - ); - $items = array( - '$ref' => $ref, - ); + if ($prop['subType'] === null) { + $items = array('type' => 'string'); } elseif (isset($this->typeMap[$prop['subType']])) { $items = array('type' => $this->typeMap[$prop['subType']]); } 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; } diff --git a/Parser/CollectionParser.php b/Parser/CollectionParser.php new file mode 100644 index 0000000..0ef9c66 --- /dev/null +++ b/Parser/CollectionParser.php @@ -0,0 +1,77 @@ + + * + * 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 + */ +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; + } +} \ No newline at end of file diff --git a/Resources/config/services.xml b/Resources/config/services.xml index da00c21..dbd694b 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -13,6 +13,8 @@ Nelmio\ApiDocBundle\Extractor\Handler\JmsSecurityExtraHandler Nelmio\ApiDocBundle\Extractor\Handler\SensioFrameworkExtraHandler Nelmio\ApiDocBundle\Extractor\Handler\PhpDocHandler + + Nelmio\ApiDocBundle\Parser\CollectionParser @@ -52,6 +54,10 @@ + + + + diff --git a/Swagger/ModelRegistry.php b/Swagger/ModelRegistry.php index 327a274..3f4ea23 100644 --- a/Swagger/ModelRegistry.php +++ b/Swagger/ModelRegistry.php @@ -130,14 +130,13 @@ class ModelRegistry case DataTypes::COLLECTION: $type = 'array'; - if ($prop['subType'] === DataTypes::MODEL) { - - } else { - - if ($prop['subType'] === null - || isset($this->typeMap[$prop['subType']])) { + if ($prop['subType'] === null) { + $items = array( + 'type' => 'string', + ); + } elseif (isset($this->typeMap[$prop['subType']])) { $items = array( - 'type' => 'string', + 'type' => $this->typeMap[$prop['subType']] ); } elseif (!isset($this->typeMap[$prop['subType']])) { $items = array( @@ -149,7 +148,6 @@ class ModelRegistry ) ); } - } /* @TODO: Handle recursion if subtype is a model. */ break; @@ -213,8 +211,9 @@ class ModelRegistry { /* * 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. $id = preg_replace('/\.+/', '.', $id); //Replace trailing dots. diff --git a/Tests/Extractor/CollectionDirectiveTest.php b/Tests/Extractor/CollectionDirectiveTest.php new file mode 100644 index 0000000..1666dc8 --- /dev/null +++ b/Tests/Extractor/CollectionDirectiveTest.php @@ -0,0 +1,107 @@ +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', + 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', + 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 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'), + array('array<2Vendor\\>'), + array('array'), + array('array as'), + array('array as '), + ); + } +} diff --git a/Tests/Extractor/TestExtractor.php b/Tests/Extractor/TestExtractor.php new file mode 100644 index 0000000..da043b5 --- /dev/null +++ b/Tests/Extractor/TestExtractor.php @@ -0,0 +1,19 @@ +normalizeClassParameter($input); + } +} diff --git a/Tests/Fixtures/Controller/ResourceController.php b/Tests/Fixtures/Controller/ResourceController.php index 502f9c2..ec75544 100644 --- a/Tests/Fixtures/Controller/ResourceController.php +++ b/Tests/Fixtures/Controller/ResourceController.php @@ -19,6 +19,7 @@ class ResourceController * resource=true, * resourceDescription="Operations on resource.", * description="List resources.", + * output="array as tests", * 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" + * ) */ public function listAnotherResourcesAction() { diff --git a/Tests/Formatter/MarkdownFormatterTest.php b/Tests/Formatter/MarkdownFormatterTest.php index c86379e..7b5caa1 100644 --- a/Tests/Formatter/MarkdownFormatterTest.php +++ b/Tests/Formatter/MarkdownFormatterTest.php @@ -38,6 +38,98 @@ _List another resource._ - 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} ### @@ -64,6 +156,20 @@ _List resources._ - Requirement: json|xml|html +#### Response #### + +tests[]: + + * type: array of objects (Test) + +tests[][a]: + + * type: string + +tests[][b]: + + * type: DateTime + ### `POST` /api/resources.{_format} ### diff --git a/Tests/Formatter/SimpleFormatterTest.php b/Tests/Formatter/SimpleFormatterTest.php index 5fa2734..380b813 100644 --- a/Tests/Formatter/SimpleFormatterTest.php +++ b/Tests/Formatter/SimpleFormatterTest.php @@ -1333,6 +1333,269 @@ With multiple lines.', 'authenticationRoles' => array(), '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( 'method' => 'PUT|PATCH', @@ -1392,6 +1655,41 @@ With multiple lines.', 'authenticationRoles' => array(), '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( 'method' => 'POST', diff --git a/Tests/Formatter/SwaggerFormatterTest.php b/Tests/Formatter/SwaggerFormatterTest.php index cc79cb4..47d4e56 100644 --- a/Tests/Formatter/SwaggerFormatterTest.php +++ b/Tests/Formatter/SwaggerFormatterTest.php @@ -47,7 +47,6 @@ class SwaggerFormatterTest extends WebTestCase $actual = $this->formatter->format($data, null); - $expected = array( 'swaggerVersion' => '1.2', 'apiVersion' => '3.14', @@ -122,441 +121,640 @@ class SwaggerFormatterTest extends WebTestCase return array( array( '/resources', - array( + 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', - ), - ), + array ( + 0 => + array ( + 'path' => '/resources.{_format}', + 'operations' => + array ( + 0 => + array ( + 'method' => 'GET', + 'summary' => 'List resources.', + 'nickname' => 'get_resources', + 'parameters' => + array ( + 0 => + array ( + 'paramType' => 'path', + 'name' => '_format', + 'type' => 'string', + 'required' => true, + 'enum' => + array ( + 0 => 'json', + 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' => - array( - - array( - 'code' => 200, - 'message' => 'Returned on success.', - ), - - array( - 'code' => 404, - 'message' => 'Returned if resource cannot be found.', - ), + 1 => + array ( + 'method' => 'POST', + 'summary' => 'Create a new resource.', + 'nickname' => 'post_resources', + 'parameters' => + array ( + 0 => + array ( + 'paramType' => 'path', + '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( - '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', - ), + ), + 1 => + array ( + 'path' => '/resources/{id}.{_format}', + 'operations' => + array ( + 0 => + array ( + 'method' => 'GET', + 'summary' => 'Retrieve a resource by ID.', + 'nickname' => 'get_resources', + '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 ( + ), ), - 'responseMessages' => - array( - array( - 'code' => 200, - 'message' => 'See standard HTTP status code reason for 200', - 'responseModel' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested', - ), + 1 => + array ( + 'method' => 'DELETE', + 'summary' => 'Delete a resource by ID.', + 'nickname' => 'delete_resources', + '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' => - 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' => - array( + array ( 'id' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest', 'description' => 'object (JmsTest)', 'properties' => - array( + array ( 'foo' => - array( + array ( 'type' => 'string', 'description' => 'string', ), 'bar' => - array( + array ( 'type' => 'string', 'description' => 'DateTime', 'format' => 'date-time', ), 'number' => - array( + array ( 'type' => 'number', 'description' => 'double', 'format' => 'float', ), 'arr' => - array( + array ( 'type' => 'array', 'description' => 'array', - 'items' => array( - 'type' => 'string', - ) + 'items' => + array ( + 'type' => 'string', + ), ), 'nested' => - array( + array ( '$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested', ), 'nested_array' => - array( + array ( 'type' => 'array', 'description' => 'array of objects (JmsNested)', - 'items' => array( - '$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested', - ) + 'items' => + array ( + '$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested', + ), ), ), 'required' => - array(), + array ( + ), ), 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested' => - array( + array ( 'id' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested', 'description' => '', 'properties' => - array( + array ( 'foo' => - array( + array ( 'type' => 'string', 'description' => 'DateTime', 'format' => 'date-time', ), 'bar' => - array( + array ( 'type' => 'string', 'description' => 'string', ), 'baz' => - array( + array ( 'type' => 'array', 'description' => 'Epic description. With multiple lines.', - 'items' => array( - 'type' => 'string', - ) + 'items' => + array ( + 'type' => 'integer', + ), ), 'circular' => - array( + array ( '$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsNested', ), 'parent' => - array( + array ( '$ref' => 'Nelmio.ApiDocBundle.Tests.Fixtures.Model.JmsTest', ), 'since' => - array( + array ( 'type' => 'string', 'description' => 'string', ), 'until' => - array( + array ( 'type' => 'string', 'description' => 'string', ), 'since_and_until' => - array( + array ( 'type' => 'string', 'description' => 'string', ), ), 'required' => - array(), + array ( + ), ), ), 'produces' => - array(), + array ( + ), 'consumes' => - array(), + array ( + ), 'authorizations' => - array( - 'apiKey' => array( - 'type' => 'apiKey', - 'passAs' => 'header', - 'keyname' => 'access_token', - ) + array ( + 'apiKey' => + array ( + 'type' => 'apiKey', + 'passAs' => 'header', + 'keyname' => 'access_token', + ), ), ), ), array( '/other-resources', - array( + 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', - ), - ), + array ( + 0 => + array ( + 'path' => '/other-resources.{_format}', + 'operations' => + array ( + 0 => + array ( + 'method' => 'GET', + 'summary' => 'List another resource.', + 'nickname' => 'get_other-resources', + 'parameters' => + array ( + 0 => + array ( + 'paramType' => 'path', + 'name' => '_format', + 'type' => 'string', + 'required' => true, + 'enum' => + array ( + 0 => 'json', + 1 => 'xml', + 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(), ), - ), - ), - - 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', - ), - ), + ), + 1 => + array ( + 'path' => '/other-resources/{id}.{_format}', + 'operations' => + array ( + 0 => + array ( + 'method' => 'PUT', + 'summary' => 'Update a resource bu ID.', + 'nickname' => 'put_other-resources', + '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 ( + ), ), - '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', - ), - ), + 1 => + array ( + 'method' => 'PATCH', + 'summary' => 'Update a resource bu ID.', + 'nickname' => 'patch_other-resources', + '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 ( + ), ), - 'responseMessages' => - array(), ), - ), - ), + ), ), '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' => - array(), + array ( + ), 'consumes' => - array(), + array ( + ), 'authorizations' => - array( - 'apiKey' => array( - 'type' => 'apiKey', - 'passAs' => 'header', - 'keyname' => 'access_token', - ) + array ( + 'apiKey' => + array ( + 'type' => 'apiKey', + 'passAs' => 'header', + 'keyname' => 'access_token', + ), ), ), ),