Introduce the concept of 'views'

Rewrite #619
This commit is contained in:
William Durand 2015-05-16 12:17:59 +02:00
parent 94ba751848
commit c71fa155d5
No known key found for this signature in database
GPG Key ID: A509BCF1C1274F3B
12 changed files with 149 additions and 101 deletions

View File

@ -18,6 +18,8 @@ use Symfony\Component\Routing\Route;
*/ */
class ApiDoc class ApiDoc
{ {
const DEFAULT_VIEW = 'default';
/** /**
* Requirements are mandatory parameters in a route. * Requirements are mandatory parameters in a route.
* *
@ -26,11 +28,11 @@ class ApiDoc
private $requirements = array(); private $requirements = array();
/** /**
* Which APIs is this route used. Defaults to "default" * Which views is this route used. Defaults to "Default"
* *
* @var array * @var array
*/ */
private $apis = array(); private $views = array();
/** /**
* Filters are optional parameters in the query string. * Filters are optional parameters in the query string.
@ -198,12 +200,13 @@ class ApiDoc
} }
} }
if (isset($data['api'])) { if (isset($data['views'])) {
if (! is_array($data['api'])) { if (! is_array($data['views'])) {
$data['api'] = array($data['api']); $data['views'] = array($data['views']);
} }
foreach ($data['api'] as $api) {
$this->addApi($api); foreach ($data['views'] as $view) {
$this->addView($view);
} }
} }
@ -392,17 +395,17 @@ class ApiDoc
/** /**
* @return array * @return array
*/ */
public function addApi($api) public function addView($view)
{ {
$this->apis[] = $api; $this->views[] = $view;
} }
/** /**
* @return array * @return array
*/ */
public function getApis() public function getViews()
{ {
return $this->apis; return $this->views;
} }
/** /**
@ -657,8 +660,8 @@ class ApiDoc
$data['requirements'] = $requirements; $data['requirements'] = $requirements;
} }
if ($apis = $this->apis) { if ($views = $this->views) {
$data['apis'] = $apis; $data['views'] = $views;
} }
if ($response = $this->response) { if ($response = $this->response) {

View File

@ -12,6 +12,7 @@
namespace Nelmio\ApiDocBundle\Controller; namespace Nelmio\ApiDocBundle\Controller;
use Nelmio\ApiDocBundle\Formatter\RequestAwareSwaggerFormatter; use Nelmio\ApiDocBundle\Formatter\RequestAwareSwaggerFormatter;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
@ -19,9 +20,9 @@ use Symfony\Component\HttpFoundation\Response;
class ApiDocController extends Controller class ApiDocController extends Controller
{ {
public function indexAction($api = "default") public function indexAction($view = ApiDoc::DEFAULT_VIEW)
{ {
$extractedDoc = $this->get('nelmio_api_doc.extractor.api_doc_extractor')->all($api); $extractedDoc = $this->get('nelmio_api_doc.extractor.api_doc_extractor')->all($view);
$htmlContent = $this->get('nelmio_api_doc.formatter.html_formatter')->format($extractedDoc); $htmlContent = $this->get('nelmio_api_doc.formatter.html_formatter')->format($extractedDoc);
return new Response($htmlContent, 200, array('Content-Type' => 'text/html')); return new Response($htmlContent, 200, array('Content-Type' => 'text/html'));

View File

@ -96,9 +96,9 @@ class ApiDocExtractor
* *
* @return array * @return array
*/ */
public function all($api = "default") public function all($view = ApiDoc::DEFAULT_VIEW)
{ {
return $this->extractAnnotations($this->getRoutes(), $api); return $this->extractAnnotations($this->getRoutes(), $view);
} }
/** /**
@ -110,7 +110,7 @@ class ApiDocExtractor
* *
* @return array * @return array
*/ */
public function extractAnnotations(array $routes, $api = "default") public function extractAnnotations(array $routes, $view = ApiDoc::DEFAULT_VIEW)
{ {
$array = array(); $array = array();
$resources = array(); $resources = array();
@ -123,10 +123,10 @@ class ApiDocExtractor
if ($method = $this->getReflectionMethod($route->getDefault('_controller'))) { if ($method = $this->getReflectionMethod($route->getDefault('_controller'))) {
$annotation = $this->reader->getMethodAnnotation($method, self::ANNOTATION_CLASS); $annotation = $this->reader->getMethodAnnotation($method, self::ANNOTATION_CLASS);
if ($annotation && if (
! in_array($annotation->getSection(), $excludeSections) && $annotation && !in_array($annotation->getSection(), $excludeSections) &&
( in_array($api, $annotation->getApis()) || (count($annotation->getApis()) == 0 && $api == "default")) (in_array($view, $annotation->getViews()) || (0 === count($annotation->getViews()) && $view === ApiDoc::DEFAULT_VIEW))
) { ) {
if ($annotation->isResource()) { if ($annotation->isResource()) {
if ($resource = $annotation->getResource()) { if ($resource = $annotation->getResource()) {
$resources[] = $resource; $resources[] = $resource;

View File

@ -13,6 +13,7 @@ namespace Nelmio\ApiDocBundle\Extractor;
use Doctrine\Common\Annotations\Reader; use Doctrine\Common\Annotations\Reader;
use Nelmio\ApiDocBundle\Util\DocCommentExtractor; use Nelmio\ApiDocBundle\Util\DocCommentExtractor;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser; use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
use Symfony\Component\Config\ConfigCache; use Symfony\Component\Config\ConfigCache;
use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Resource\FileResource;
@ -49,7 +50,7 @@ class CachingApiDocExtractor extends ApiDocExtractor
$this->cache = new ConfigCache($this->cacheFile, $debug); $this->cache = new ConfigCache($this->cacheFile, $debug);
} }
public function all($api = "default") public function all($view = ApiDoc::DEFAULT_VIEW)
{ {
if ($this->cache->isFresh() === false) { if ($this->cache->isFresh() === false) {
@ -65,7 +66,7 @@ class CachingApiDocExtractor extends ApiDocExtractor
$resources = array_merge($resources, $this->router->getRouteCollection()->getResources()); $resources = array_merge($resources, $this->router->getRouteCollection()->getResources());
$data = parent::all($api); $data = parent::all($view);
$this->cache->write(serialize($data), $resources); $this->cache->write(serialize($data), $resources);
return $data; return $data;

View File

@ -1,5 +1,5 @@
nelmio_api_doc_index: nelmio_api_doc_index:
pattern: /{api} pattern: /{view}
defaults: { _controller: NelmioApiDocBundle:ApiDoc:index, api: "default" } defaults: { _controller: NelmioApiDocBundle:ApiDoc:index, view: 'Default' }
requirements: requirements:
_method: GET _method: GET

View File

@ -8,7 +8,8 @@ for your APIs.
Installation Installation
------------ ------------
Require the `nelmio/api-doc-bundle` package in your composer.json and update your dependencies. Require the `nelmio/api-doc-bundle` package in your composer.json and update
your dependencies.
$ composer require nelmio/api-doc-bundle $ composer require nelmio/api-doc-bundle
@ -26,19 +27,24 @@ public function registerBundles()
``` ```
Import the routing definition in `routing.yml`: Import the routing definition in `routing.yml`:
```yaml ```yaml
# app/config/routing.yml # app/config/routing.yml
NelmioApiDocBundle: NelmioApiDocBundle:
resource: "@NelmioApiDocBundle/Resources/config/routing.yml" resource: "@NelmioApiDocBundle/Resources/config/routing.yml"
prefix: /api/doc prefix: /api/doc
``` ```
Enable the bundle's configuration in `app/config/config.yml`: Enable the bundle's configuration in `app/config/config.yml`:
```yaml ```yaml
# app/config/config.yml # app/config/config.yml
nelmio_api_doc: ~ nelmio_api_doc: ~
``` ```
The **NelmioApiDocBundle** requires Twig as a template engine so do not forget to enable it: The **NelmioApiDocBundle** requires Twig as a template engine so do not forget
to enable it:
```yaml ```yaml
# app/config/config.yml # app/config/config.yml
framework: framework:
@ -49,8 +55,9 @@ framework:
Usage Usage
----- -----
The main problem with documentation is to keep it up to date. That's why the **NelmioApiDocBundle** The main problem with documentation is to keep it up to date. That's why the
uses introspection a lot. Thanks to an annotation, it's really easy to document an API method. **NelmioApiDocBundle** uses introspection a lot. Thanks to an annotation, it's
really easy to document an API method.
### The ApiDoc() Annotation ### The ApiDoc() Annotation
@ -188,8 +195,8 @@ class YourController
} }
``` ```
* `api`: the api under which this resource will be shown. Leave empty to specify the default api. Either a single api, or * `views`: the view(s) under which this resource will be shown. Leave empty to
an array of apis. specify the default view. Either a single view, or an array of views.
Each _filter_ has to define a `name` parameter, but other parameters are free. Filters are often optional Each _filter_ has to define a `name` parameter, but other parameters are free. Filters are often optional
parameters, and you can document them as you want, but keep in mind to be consistent for the whole documentation. parameters, and you can document them as you want, but keep in mind to be consistent for the whole documentation.
@ -220,13 +227,19 @@ class YourType extends AbstractType
} }
``` ```
The bundle will also get information from the routing definition (`requirements`, `pattern`, etc), so to get the The bundle will also get information from the routing definition
best out of it you should define strict _method requirements etc. (`requirements`, `pattern`, etc), so to get the best out of it you should
define strict _method requirements etc.
### Multiple API documentations ### ### Multiple API Documentation ("Views")
With the `api` tag in the `@apidoc` annotation, it's possible to create different sets of api documentations. Without
the tag, all methods are located in the `default` api and can be found under the normal api documentation url. With the With the `views` tag in the `@ApiDoc` annotation, it is possible to create
`api` tag you can specify one or more api names under which the method will be visible. different views of your API documentation. Without the tag, all methods are
located in the `Default` view, and can be found under the normal API
documentation url.
You can specify one or more _view_ names under which the method will be
visible.
An example: An example:
``` ```
@ -236,7 +249,7 @@ An example:
* @ApiDoc( * @ApiDoc(
* resource=true, * resource=true,
* description="This is a description of your API method", * description="This is a description of your API method",
* api = { "default", "premium" } * views = { "Default", "premium" }
* ) * )
*/ */
public function getAction() public function getAction()
@ -249,7 +262,7 @@ An example:
* @ApiDoc( * @ApiDoc(
* resource=true, * resource=true,
* description="This is a description of another API method", * description="This is a description of another API method",
* api = { "premium" } * views = { "premium" }
* ) * )
*/ */
public function getAnotherAction() public function getAnotherAction()
@ -257,22 +270,23 @@ An example:
} }
``` ```
In this case, only the first resource will be available under the default api documentation, while both methods will In this case, only the first resource will be available under the default view,
be available under the `premium` api documentation. while both methods will be available under the `premium` view.
#### Accessing API documentation #### #### Accessing Specific API Views
The normal `default` documentation can be found at the normal location. Other sets of documentation can be found at `documentationurl/<tagname>`.
For instance, if your documenation is located at The `Default` view can be found at the normal location. Other views can be
found at `http://your.documentation/<view name>`.
For instance, if your documentation is located at:
http://example.org/doc/api/v1/ http://example.org/doc/api/v1/
then the `premium` api will be located at: then the `premium` view will be located at:
http://example.org/doc/api/v1/premium http://example.org/doc/api/v1/premium
### Other Bundle Annotations ### Other Bundle Annotations
Also bundle will get information from the other annotations: Also bundle will get information from the other annotations:
@ -518,9 +532,11 @@ nelmio_api_doc:
exclude_sections: ["privateapi", "testapi"] exclude_sections: ["privateapi", "testapi"]
``` ```
Note that `exclude_sections` will literally exclude a section from your api documentation. It's possible however to create Note that `exclude_sections` will literally exclude a section from your api
multiple apis by specifying the `api` within the `@apidoc` annotations. This allows you to move private or test methods to a documentation. It's possible however to create multiple views by specifying the
complete different set of api documentation instead. `views` parameter within the `@ApiDoc` annotations. This allows you to move
private or test methods to a complete different view of your documentation
instead.
The bundle provides a way to register multiple `input` parsers. The first parser The bundle provides a way to register multiple `input` parsers. The first parser
that can handle the specified input is used, so you can configure their that can handle the specified input is used, so you can configure their

0
Resources/views/layout.html.twig Executable file → Normal file
View File

View File

@ -26,7 +26,7 @@ class ApiDocTest extends TestCase
$this->assertTrue(is_array($array)); $this->assertTrue(is_array($array));
$this->assertFalse(isset($array['filters'])); $this->assertFalse(isset($array['filters']));
$this->assertFalse($annot->isResource()); $this->assertFalse($annot->isResource());
$this->assertEmpty($annot->getApis()); $this->assertEmpty($annot->getViews());
$this->assertFalse($annot->getDeprecated()); $this->assertFalse($annot->getDeprecated());
$this->assertFalse(isset($array['description'])); $this->assertFalse(isset($array['description']));
$this->assertFalse(isset($array['requirements'])); $this->assertFalse(isset($array['requirements']));

View File

@ -17,9 +17,9 @@ use Nelmio\ApiDocBundle\Tests\WebTestCase;
class ApiDocExtractorTest extends WebTestCase class ApiDocExtractorTest extends WebTestCase
{ {
const ROUTES_QUANTITY_DEFAULT = 33; // Routes in the default api private static $ROUTES_QUANTITY_DEFAULT = 38; // Routes in the default view
const ROUTES_QUANTITY_PREMIUM = 6; // Routes tagged with premium api private static $ROUTES_QUANTITY_PREMIUM = 11; // Routes in the premium view
const ROUTES_QUANTITY_TEST = 2; // Routes tagged with test api private static $ROUTES_QUANTITY_TEST = 7; // Routes in the test view
public function testAll() public function testAll()
{ {
@ -29,13 +29,8 @@ class ApiDocExtractorTest extends WebTestCase
$data = $extractor->all(); $data = $extractor->all();
restore_error_handler(); restore_error_handler();
if (class_exists('Dunglas\ApiBundle\DunglasApiBundle')) { $routesQuantity = self::$ROUTES_QUANTITY_DEFAULT;
$routesQuantity = 38; $httpsKey = 25;
$httpsKey = 25;
} else {
$routesQuantity = self::ROUTES_QUANTITY_DEFAULT;
$httpsKey = 20;
}
$this->assertTrue(is_array($data)); $this->assertTrue(is_array($data));
$this->assertCount($routesQuantity, $data); $this->assertCount($routesQuantity, $data);
@ -292,19 +287,20 @@ class ApiDocExtractorTest extends WebTestCase
$this->assertFalse($parameters['required_field']['required']); $this->assertFalse($parameters['required_field']['required']);
} }
public function multiDocProvider() public static function viewsProvider()
{ {
return array( return array(
array('default', self::ROUTES_QUANTITY_DEFAULT), array('default', self::$ROUTES_QUANTITY_DEFAULT),
array('premium', self::ROUTES_QUANTITY_PREMIUM), array('premium', self::$ROUTES_QUANTITY_PREMIUM),
array('test', self::ROUTES_QUANTITY_TEST), array('test', self::$ROUTES_QUANTITY_TEST),
array('foobar', 0), // 5 = DunglasApiBundle
array("", 0), array('foobar', 5),
array(null, 0), array("", 5),
array(null, 5),
); );
} }
public function testAllMultiDocsForTest() public function testViewNamedTest()
{ {
$container = $this->getContainer(); $container = $this->getContainer();
$extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor'); $extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor');
@ -313,18 +309,18 @@ class ApiDocExtractorTest extends WebTestCase
restore_error_handler(); restore_error_handler();
$this->assertTrue(is_array($data)); $this->assertTrue(is_array($data));
$this->assertCount(self::ROUTES_QUANTITY_TEST, $data); $this->assertCount(self::$ROUTES_QUANTITY_TEST, $data);
$a1 = $data[0]['annotation']; $a1 = $data[0]['annotation'];
$this->assertCount(3, $a1->getApis()); $this->assertCount(3, $a1->getViews());
$this->assertEquals('List resources.', $a1->getDescription()); $this->assertEquals('List resources.', $a1->getDescription());
$a2 = $data[1]['annotation']; $a2 = $data[1]['annotation'];
$this->assertCount(2, $a2->getApis()); $this->assertCount(2, $a2->getViews());
$this->assertEquals('create another test', $a2->getDescription()); $this->assertEquals('create another test', $a2->getDescription());
} }
public function testAllMultiDocsForPremium() public function testViewNamedPremium()
{ {
$container = $this->getContainer(); $container = $this->getContainer();
$extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor'); $extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor');
@ -333,34 +329,33 @@ class ApiDocExtractorTest extends WebTestCase
restore_error_handler(); restore_error_handler();
$this->assertTrue(is_array($data)); $this->assertTrue(is_array($data));
$this->assertCount(self::ROUTES_QUANTITY_PREMIUM, $data); $this->assertCount(self::$ROUTES_QUANTITY_PREMIUM, $data);
$a1 = $data[0]['annotation']; $a1 = $data[0]['annotation'];
$this->assertCount(2, $a1->getApis()); $this->assertCount(2, $a1->getViews());
$this->assertEquals('List another resource.', $a1->getDescription()); $this->assertEquals('List another resource.', $a1->getDescription());
$a2 = $data[1]['annotation']; $a2 = $data[1]['annotation'];
$this->assertCount(3, $a2->getApis()); $this->assertCount(3, $a2->getViews());
$this->assertEquals('List resources.', $a2->getDescription()); $this->assertEquals('List resources.', $a2->getDescription());
$a3 = $data[4]['annotation']; $a3 = $data[9]['annotation'];
$this->assertCount(2, $a3->getApis()); $this->assertCount(2, $a3->getViews());
$this->assertEquals('create test', $a3->getDescription()); $this->assertEquals('create test', $a3->getDescription());
} }
/** /**
* @dataProvider multiDocProvider * @dataProvider viewsProvider
*/ */
public function testAllMultiDocs($api, $count) public function testForViews($view, $count)
{ {
$container = $this->getContainer(); $container = $this->getContainer();
$extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor'); $extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor');
set_error_handler(array($this, 'handleDeprecation')); set_error_handler(array($this, 'handleDeprecation'));
$data = $extractor->all($api); $data = $extractor->all($view);
restore_error_handler(); restore_error_handler();
$this->assertTrue(is_array($data)); $this->assertTrue(is_array($data));
$this->assertCount($count, $data); $this->assertCount($count, $data);
} }
} }

View File

@ -17,7 +17,7 @@ class ResourceController
/** /**
* @ApiDoc( * @ApiDoc(
* resource=true, * resource=true,
* api={ "test", "premium", "default" }, * views={ "test", "premium", "default" },
* resourceDescription="Operations on resource.", * resourceDescription="Operations on resource.",
* description="List resources.", * description="List resources.",
* output="array<Nelmio\ApiDocBundle\Tests\Fixtures\Model\Test> as tests", * output="array<Nelmio\ApiDocBundle\Tests\Fixtures\Model\Test> as tests",
@ -48,7 +48,7 @@ class ResourceController
/** /**
* @ApiDoc( * @ApiDoc(
* description="Create a new resource.", * description="Create a new resource.",
* api={ "default", "premium" }, * views={ "default", "premium" },
* input={"class" = "Nelmio\ApiDocBundle\Tests\Fixtures\Form\SimpleType", "name" = ""}, * input={"class" = "Nelmio\ApiDocBundle\Tests\Fixtures\Form\SimpleType", "name" = ""},
* output="Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsNested", * output="Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsNested",
* responseMap={ * responseMap={
@ -64,7 +64,7 @@ class ResourceController
/** /**
* @ApiDoc( * @ApiDoc(
* resource=true, * resource=true,
* api={ "default", "premium" }, * views={ "default", "premium" },
* description="List another resource.", * description="List another resource.",
* resourceDescription="Operations on another resource.", * resourceDescription="Operations on another resource.",
* output="array<Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest>" * output="array<Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest>"

View File

@ -24,7 +24,7 @@ class TestController
/** /**
* @ApiDoc( * @ApiDoc(
* resource="TestResource", * resource="TestResource",
* api="default" * views="default"
* ) * )
*/ */
public function namedResourceAction() public function namedResourceAction()
@ -49,7 +49,7 @@ class TestController
/** /**
* @ApiDoc( * @ApiDoc(
* description="create test", * description="create test",
* api={ "default", "premium" }, * views={ "default", "premium" },
* input="Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType" * input="Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType"
* ) * )
*/ */
@ -60,7 +60,7 @@ class TestController
/** /**
* @ApiDoc( * @ApiDoc(
* description="post test 2", * description="post test 2",
* api={ "default", "premium" }, * views={ "default", "premium" },
* resource=true * resource=true
* ) * )
*/ */
@ -112,7 +112,7 @@ class TestController
/** /**
* @ApiDoc( * @ApiDoc(
* api= { "default", "test" }, * views= { "default", "test" },
* description="create another test", * description="create another test",
* input="dependency_type" * input="dependency_type"
* ) * )

View File

@ -315,6 +315,10 @@ With multiple lines.',
array ( array (
), ),
'deprecated' => false, 'deprecated' => false,
'views' => array(
'default',
'premium',
),
), ),
1 => 1 =>
array ( array (
@ -413,6 +417,11 @@ With multiple lines.',
array ( array (
), ),
'deprecated' => false, 'deprecated' => false,
'views' => array(
'test',
'premium',
'default',
),
), ),
1 => 1 =>
array ( array (
@ -850,6 +859,10 @@ With multiple lines.',
array ( array (
), ),
'deprecated' => false, 'deprecated' => false,
'views' => array(
'default',
'premium',
),
), ),
2 => 2 =>
array ( array (
@ -1046,6 +1059,10 @@ With multiple lines.',
array ( array (
), ),
'deprecated' => false, 'deprecated' => false,
'views' => array(
'default',
'premium',
),
), ),
3 => 3 =>
array ( array (
@ -1111,6 +1128,10 @@ With multiple lines.',
array ( array (
), ),
'deprecated' => false, 'deprecated' => false,
'views' => array(
'default',
'premium',
),
), ),
), ),
'/tests2' => '/tests2' =>
@ -1135,6 +1156,10 @@ With multiple lines.',
array ( array (
), ),
'deprecated' => false, 'deprecated' => false,
'views' => array(
'default',
'premium',
),
), ),
), ),
'TestResource' => 'TestResource' =>
@ -1149,6 +1174,9 @@ With multiple lines.',
array ( array (
), ),
'deprecated' => false, 'deprecated' => false,
'views' => array(
'default',
),
), ),
), ),
'others' => 'others' =>
@ -1190,6 +1218,10 @@ With multiple lines.',
array ( array (
), ),
'deprecated' => false, 'deprecated' => false,
'views' => array(
'default',
'test',
),
), ),
1 => 1 =>
array ( array (
@ -2557,7 +2589,7 @@ With multiple lines.',
'authentication' => false, 'authentication' => false,
'authenticationRoles' => array(), 'authenticationRoles' => array(),
'deprecated' => false, 'deprecated' => false,
'apis' => 'views' =>
array( array(
'default', 'default',
'premium', 'premium',
@ -2621,7 +2653,7 @@ With multiple lines.',
'authentication' => false, 'authentication' => false,
'authenticationRoles' => array(), 'authenticationRoles' => array(),
'deprecated' => false, 'deprecated' => false,
'apis' => 'views' =>
array( array(
'default', 'default',
'premium', 'premium',
@ -2662,7 +2694,7 @@ With multiple lines.',
'authentication' => false, 'authentication' => false,
'authenticationRoles' => array(), 'authenticationRoles' => array(),
'deprecated' => false, 'deprecated' => false,
'apis' => 'views' =>
array( array(
'default', 'default',
'test', 'test',
@ -3691,7 +3723,7 @@ With multiple lines.',
'authentication' => false, 'authentication' => false,
'authenticationRoles' => array(), 'authenticationRoles' => array(),
'deprecated' => false, 'deprecated' => false,
'apis' => 'views' =>
array( array(
'default', 'default',
'premium', 'premium',
@ -3717,7 +3749,7 @@ With multiple lines.',
'authentication' => false, 'authentication' => false,
'authenticationRoles' => array(), 'authenticationRoles' => array(),
'deprecated' => false, 'deprecated' => false,
'apis' => 'views' =>
array( array(
'default', 'default',
'premium', 'premium',
@ -3734,7 +3766,7 @@ With multiple lines.',
'authentication' => false, 'authentication' => false,
'authenticationRoles' => array(), 'authenticationRoles' => array(),
'deprecated' => false, 'deprecated' => false,
'apis' => 'views' =>
array( array(
'default', 'default',
), ),
@ -3761,7 +3793,7 @@ With multiple lines.',
'authenticationRoles' => 'authenticationRoles' =>
array(), array(),
'deprecated' => false, 'deprecated' => false,
'apis' => array( 'views' => array(
'default', 'default',
'premium', 'premium',
), ),
@ -4087,7 +4119,7 @@ With multiple lines.',
'authenticationRoles' => 'authenticationRoles' =>
array(), array(),
'deprecated' => false, 'deprecated' => false,
'apis' => array( 'views' => array(
'test', 'test',
'default', 'default',
'premium', 'premium',
@ -4205,7 +4237,7 @@ With multiple lines.',
'description' => '', 'description' => '',
), ),
), ),
'apis' => 'views' =>
array( array(
'default', 'default',
'premium', 'premium',