Refactoring

Move logic to extract data in the Extractor
Remove logic in the AbstractFormatter
Use ApiDoc class as data container
Update tests
Add test to prove the bug with FOSRestBundle annotations (\\d+ instead of \d+)
This commit is contained in:
William DURAND 2012-07-20 00:58:58 +02:00
parent 8f3327b376
commit cca97cf6af
14 changed files with 371 additions and 256 deletions

View File

@ -11,6 +11,8 @@
namespace Nelmio\ApiDocBundle\Annotation;
use Symfony\Component\Routing\Route;
/**
* @Annotation
*/
@ -41,6 +43,31 @@ class ApiDoc
*/
private $isResource = false;
/**
* @var array
*/
private $requirements = array();
/**
* @var string
*/
private $method;
/**
* @var string
*/
private $uri;
/**
* @var array
*/
private $parameters = array();
/**
* @var Route
*/
private $route;
public function __construct(array $data)
{
if (isset($data['formType'])) {
@ -65,14 +92,6 @@ class ApiDoc
$this->isResource = isset($data['resource']) && $data['resource'];
}
/**
* @return array
*/
public function getFilters()
{
return $this->filters;
}
/**
* @param string $name
* @param array $filter
@ -82,6 +101,23 @@ class ApiDoc
$this->filters[$name] = $filter;
}
/**
* @param string $name
* @param array $requirement
*/
public function addRequirement($name, array $requirement)
{
$this->requirements[$name] = $requirement;
}
/**
* @param array $requirements
*/
public function setRequirements(array $requirements)
{
$this->requirements = array_merge($this->requirements, $requirements);
}
/**
* @return string|null
*/
@ -91,7 +127,7 @@ class ApiDoc
}
/**
* @return string|null
* @return string
*/
public function getDescription()
{
@ -106,14 +142,6 @@ class ApiDoc
$this->description = $description;
}
/**
* @return string|null
*/
public function getDocumentation()
{
return $this->documentation;
}
/**
* @param string $documentation
*/
@ -129,4 +157,77 @@ class ApiDoc
{
return $this->isResource;
}
/**
* @var string $method
*/
public function setMethod($method)
{
$this->method = $method;
}
/**
* @var string $uri
*/
public function setUri($uri)
{
$this->uri = $uri;
}
/**
* @param array $parameters
*/
public function setParameters(array $parameters)
{
$this->parameters = $parameters;
}
/**
* @param Route $route
*/
public function setRoute(Route $route)
{
$this->route = $route;
}
/**
* @return Route
*/
public function getRoute()
{
return $this->route;
}
/**
* @return array
*/
public function toArray()
{
$data = array(
'method' => $this->method,
'uri' => $this->uri,
);
if ($description = $this->description) {
$data['description'] = $description;
}
if ($documentation = $this->documentation) {
$data['documentation'] = $documentation;
}
if ($filters = $this->filters) {
$data['filters'] = $filters;
}
if ($parameters = $this->parameters) {
$data['parameters'] = $parameters;
}
if ($requirements = $this->requirements) {
$data['requirements'] = $requirements;
}
return $data;
}
}

View File

@ -54,8 +54,8 @@ class RequestListener
$controller = $request->attributes->get('_controller');
$route = $request->attributes->get('_route');
if (null !== $array = $this->extractor->get($controller, $route)) {
$result = $this->formatter->formatOne($array['annotation'], $array['route']);
if (null !== $annotation = $this->extractor->get($controller, $route)) {
$result = $this->formatter->formatOne($annotation);
$event->setResponse(new Response($result, 200, array(
'Content-Type' => 'text/html'

View File

@ -13,6 +13,7 @@ namespace Nelmio\ApiDocBundle\Extractor;
use Doctrine\Common\Annotations\Reader;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Nelmio\ApiDocBundle\Parser\FormTypeParser;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
@ -39,17 +40,22 @@ class ApiDocExtractor
*/
private $reader;
public function __construct(ContainerInterface $container, RouterInterface $router, Reader $reader)
/**
* @var \Nelmio\ApiDocBundle\Parser\FormTypeParser
*/
private $parser;
public function __construct(ContainerInterface $container, RouterInterface $router, Reader $reader, FormTypeParser $parser)
{
$this->container = $container;
$this->router = $router;
$this->reader = $reader;
$this->router = $router;
$this->reader = $reader;
$this->parser = $parser;
}
/**
* Returns an array of data where each data is an array with the following keys:
* - annotation
* - route
* - resource
*
* @return array
@ -61,12 +67,12 @@ class ApiDocExtractor
foreach ($this->router->getRouteCollection()->all() as $route) {
if ($method = $this->getReflectionMethod($route->getDefault('_controller'))) {
if ($annot = $this->reader->getMethodAnnotation($method, self::ANNOTATION_CLASS)) {
if ($annot->isResource()) {
if ($annotation = $this->reader->getMethodAnnotation($method, self::ANNOTATION_CLASS)) {
if ($annotation->isResource()) {
$resources[] = $route->getPattern();
}
$array[] = $this->parseAnnotations($annot, $method, $route);
$array[] = array('annotation' => $this->extractData($annotation, $route, $method));
}
}
}
@ -74,7 +80,7 @@ class ApiDocExtractor
rsort($resources);
foreach ($array as $index => $element) {
$hasResource = false;
$pattern = $element['route']->getPattern();
$pattern = $element['annotation']->getRoute()->getPattern();
foreach ($resources as $resource) {
if (0 === strpos($pattern, $resource)) {
@ -91,31 +97,38 @@ class ApiDocExtractor
}
$methodOrder = array('GET', 'POST', 'PUT', 'DELETE');
usort($array, function($a, $b) use ($methodOrder) {
if ($a['resource'] === $b['resource']) {
if ($a['route']->getPattern() === $b['route']->getPattern()) {
$methodA = array_search($a['route']->getRequirement('_method'), $methodOrder);
$methodB = array_search($b['route']->getRequirement('_method'), $methodOrder);
if ($a['annotation']->getRoute()->getPattern() === $b['annotation']->getRoute()->getPattern()) {
$methodA = array_search($a['annotation']->getRoute()->getRequirement('_method'), $methodOrder);
$methodB = array_search($b['annotation']->getRoute()->getRequirement('_method'), $methodOrder);
if ($methodA === $methodB) {
return strcmp($a['route']->getRequirement('_method'), $b['route']->getRequirement('_method'));
return strcmp(
$a['annotation']->getRoute()->getRequirement('_method'),
$b['annotation']->getRoute()->getRequirement('_method')
);
}
return $methodA > $methodB ? 1 : -1;
}
return strcmp($a['route']->getPattern(), $b['route']->getPattern());
return strcmp(
$a['annotation']->getRoute()->getPattern(),
$b['annotation']->getRoute()->getPattern()
);
}
return strcmp($a['resource'], $b['resource']);
});
return $array;
}
/**
* Returns the ReflectionMethod for the given controller string
* Returns the ReflectionMethod for the given controller string.
*
* @param string $controller
* @return \ReflectionMethod|null
@ -130,7 +143,7 @@ class ApiDocExtractor
$method = $matches[2];
if ($this->container->has($controller)) {
$this->container->enterScope('request');
$this->container->set('request', new Request);
$this->container->set('request', new Request());
$class = get_class($this->container->get($controller));
$this->container->leaveScope('request');
}
@ -147,20 +160,18 @@ class ApiDocExtractor
}
/**
* Returns an array containing two values with the following keys:
* - annotation
* - route
* Returns an ApiDoc annotation.
*
* @param string $controller
* @param Route $route
* @return array|null
* @return ApiDoc|null
*/
public function get($controller, $route)
{
if ($method = $this->getReflectionMethod($controller)) {
if ($annot = $this->reader->getMethodAnnotation($method, self::ANNOTATION_CLASS)) {
if ($annotation = $this->reader->getMethodAnnotation($method, self::ANNOTATION_CLASS)) {
if ($route = $this->router->getRouteCollection()->get($route)) {
return $this->parseAnnotations($annot, $method, $route);
return $this->extractData($annotation, $route, $method);
}
}
}
@ -168,45 +179,26 @@ class ApiDocExtractor
return null;
}
protected function parseAnnotations($annotation, $method, $route)
{
$data = $this->getData($annotation, $route, $method);
foreach ($this->reader->getMethodAnnotations($method) as $annot) {
if (is_subclass_of($annot, self::FOS_REST_PARAM_CLASS)) {
if ($annot->strict) {
$data['requirements'][$annot->name] = array(
'requirement' => $annot->requirements,
'type' => '',
'description' => $annot->description,
);
} else {
$data['annotation']->addFilter($annot->name, array(
'requirement' => $annot->requirements,
'description' => $annot->description,
));
}
}
}
return $data;
}
/**
* Allows to add more data to the ApiDoc object, and
* returns an array containing the following keys:
* - annotation
* - route
* Returns a new ApiDoc instance with more data.
*
* @param ApiDoc $annotation
* @param Route $route
* @param \ReflectionMethod $method
* @return array
* @return ApiDoc
*/
protected function getData(ApiDoc $annotation, Route $route, \ReflectionMethod $method)
protected function extractData(ApiDoc $annotation, Route $route, \ReflectionMethod $method)
{
$docblock = $this->getDocComment($method);
// create a new annotation
$annotation = clone $annotation;
// parse annotations
$this->parseAnnotations($annotation, $route, $method);
// route
$annotation->setRoute($route);
// description
if (null === $annotation->getDescription()) {
$comments = explode("\n", $this->getDocCommentText($method));
// just set the first line
@ -220,20 +212,77 @@ class ApiDocExtractor
}
}
// doc
$annotation->setDocumentation($this->getDocCommentText($method));
// formType
if (null !== $formType = $annotation->getFormType()) {
$parameters = $this->parser->parse($formType);
if ('PUT' === $method) {
// All parameters are optional with PUT (update)
array_walk($parameters, function($val, $key) use (&$data) {
$parameters[$key]['required'] = false;
});
}
$annotation->setParameters($parameters);
}
// requirements
$requirements = array();
foreach ($route->compile()->getRequirements() as $name => $value) {
if ('_method' !== $name) {
$requirements[$name] = array(
'requirement' => $value,
'type' => '',
'description' => '',
);
}
}
$paramDocs = array();
foreach (explode("\n", $docblock) as $line) {
foreach (explode("\n", $this->getDocComment($method)) as $line) {
if (preg_match('{^@param (.+)}', trim($line), $matches)) {
$paramDocs[] = $matches[1];
}
}
$route->setOptions(array_merge($route->getOptions(), array('_paramDocs' => $paramDocs)));
$regexp = '{(\w*) *\$%s *(.*)}i';
foreach ($route->compile()->getVariables() as $var) {
$found = false;
foreach ($paramDocs as $paramDoc) {
if (preg_match(sprintf($regexp, preg_quote($var)), $paramDoc, $matches)) {
$requirements[$var]['type'] = isset($matches[1]) ? $matches[1] : '';
$requirements[$var]['description'] = $matches[2];
return array('annotation' => $annotation, 'route' => $route, 'requirements' => array());
if (!isset($requirements[$var]['requirement'])) {
$requirements[$var]['requirement'] = '';
}
$found = true;
break;
}
}
if (!isset($requirements[$var]) && false === $found) {
$requirements[$var] = array('requirement' => '', 'type' => '', 'description' => '');
}
}
$annotation->setRequirements($requirements);
// method/uri
$annotation->setMethod($route->getRequirement('_method') ?: 'ANY');
$annotation->setUri($route->compile()->getPattern());
return $annotation;
}
/**
* @param Reflector $reflected
* @return string
*/
protected function getDocComment(\Reflector $reflected)
{
$comment = $reflected->getDocComment();
@ -250,6 +299,10 @@ class ApiDocExtractor
return $comment;
}
/**
* @param Reflector $reflected
* @return string
*/
protected function getDocCommentText(\Reflector $reflected)
{
$comment = $reflected->getDocComment();
@ -264,4 +317,32 @@ class ApiDocExtractor
return trim($comment);
}
/**
* Parses annotations for a given method, and adds new information to the given ApiDoc
* annotation. Useful to extract information from the FOSRestBundle annotations.
*
* @param ApiDoc $annotation
* @param Route $route
* @param ReflectionMethod $method
*/
protected function parseAnnotations(ApiDoc $annotation, Route $route, \ReflectionMethod $method)
{
foreach ($this->reader->getMethodAnnotations($method) as $annot) {
if (is_subclass_of($annot, self::FOS_REST_PARAM_CLASS)) {
if ($annot->strict) {
$annotation->addRequirement($annot->name, array(
'requirement' => $annot->requirements,
'type' => '',
'description' => $annot->description,
));
} else {
$annotation->addFilter($annot->name, array(
'requirement' => $annot->requirements,
'description' => $annot->description,
));
}
}
}
}
}

View File

@ -12,27 +12,15 @@
namespace Nelmio\ApiDocBundle\Formatter;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Nelmio\ApiDocBundle\Parser\FormTypeParser;
use Symfony\Component\Routing\Route;
abstract class AbstractFormatter implements FormatterInterface
{
/**
* @var \Nelmio\ApiDocBundle\Parser\FormTypeParser
*/
protected $parser;
public function __construct(FormTypeParser $parser)
{
$this->parser = $parser;
}
/**
* {@inheritdoc}
*/
public function formatOne(ApiDoc $apiDoc, Route $route)
public function formatOne(ApiDoc $annotation)
{
return $this->renderOne($this->getData($apiDoc, $route));
return $this->renderOne($annotation->toArray());
}
/**
@ -42,12 +30,7 @@ abstract class AbstractFormatter implements FormatterInterface
{
$array = array();
foreach ($collection as $coll) {
$resource = $coll['resource'];
if (!isset($array[$resource])) {
$array[$resource] = array();
}
$array[$resource][] = $this->getData($coll['annotation'], $coll['route'], $coll['requirements']);
$array[$coll['resource']][] = $coll['annotation']->toArray();
}
return $this->render($array);
@ -68,80 +51,4 @@ abstract class AbstractFormatter implements FormatterInterface
* @return string|array
*/
abstract protected function render(array $collection);
/**
* @param ApiDoc $apiDoc
* @param Route $route
* @param array $requirements
* @return array
*/
protected function getData(ApiDoc $apiDoc, Route $route, array $requirements = array())
{
$method = $route->getRequirement('_method');
$data = array(
'method' => $method ?: 'ANY',
'uri' => $route->compile()->getPattern(),
);
foreach ($route->compile()->getRequirements() as $name => $value) {
if ('_method' !== $name) {
$requirements[$name] = array(
'requirement' => $value,
'type' => '',
'description' => '',
);
}
}
if (null !== $paramDocs = $route->getOption('_paramDocs')) {
$regexp = '{(\w*) *\$%s *(.*)}i';
foreach ($route->compile()->getVariables() as $var) {
$found = false;
foreach ($paramDocs as $paramDoc) {
if (preg_match(sprintf($regexp, preg_quote($var)), $paramDoc, $matches)) {
$requirements[$var]['type'] = isset($matches[1]) ? $matches[1] : '';
$requirements[$var]['description'] = $matches[2];
if (!isset($requirements[$var]['requirement'])) {
$requirements[$var]['requirement'] = '';
}
$found = true;
break;
}
}
if (!isset($requirements[$var]) && false === $found) {
$requirements[$var] = array('requirement' => '', 'type' => '', 'description' => '');
}
}
}
$data['requirements'] = $requirements;
if (null !== $formType = $apiDoc->getFormType()) {
$data['parameters'] = $this->parser->parse($formType);
if ('PUT' === $method) {
// All parameters are optional with PUT (update)
array_walk($data['parameters'], function($val, $key) use (&$data) {
$data['parameters'][$key]['required'] = false;
});
}
}
if ($filters = $apiDoc->getFilters()) {
$data['filters'] = $filters;
}
if ($description = $apiDoc->getDescription()) {
$data['description'] = $description;
}
if ($documentation = $apiDoc->getDocumentation()) {
$data['documentation'] = $documentation;
}
return $data;
}
}

View File

@ -12,7 +12,6 @@
namespace Nelmio\ApiDocBundle\Formatter;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Symfony\Component\Routing\Route;
interface FormatterInterface
{
@ -27,9 +26,8 @@ interface FormatterInterface
/**
* Format documentation data for one route.
*
* @param ApiDoc $apiDoc
* @param Route $route
* @param ApiDoc $annotation
* return string|array
*/
public function formatOne(ApiDoc $apiDoc, Route $route);
public function formatOne(ApiDoc $annotation);
}

View File

@ -1,4 +1,4 @@
Copyright (c) 2011 Nelmio
Copyright (c) 2012 Nelmio
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
THE SOFTWARE.

View File

@ -15,9 +15,7 @@
<service id="nelmio_api_doc.parser.form_type_parser" class="%nelmio_api_doc.parser.form_type_parser.class%">
<argument type="service" id="form.factory" />
</service>
<service id="nelmio_api_doc.formatter.abstract_formatter" class="%nelmio_api_doc.formatter.abstract_formatter.class%">
<argument type="service" id="nelmio_api_doc.parser.form_type_parser" />
</service>
<service id="nelmio_api_doc.formatter.abstract_formatter" class="%nelmio_api_doc.formatter.abstract_formatter.class%" />
<service id="nelmio_api_doc.formatter.markdown_formatter" class="%nelmio_api_doc.formatter.markdown_formatter.class%"
parent="nelmio_api_doc.formatter.abstract_formatter" />
<service id="nelmio_api_doc.formatter.simple_formatter" class="%nelmio_api_doc.formatter.simple_formatter.class%"

View File

@ -13,6 +13,7 @@
<argument type="service" id="service_container"/>
<argument type="service" id="router" />
<argument type="service" id="annotation_reader" />
<argument type="service" id="nelmio_api_doc.parser.form_type_parser" />
</service>
<service id="nelmio_api_doc.form.extension.description_form_type_extension" class="%nelmio_api_doc.form.extension.description_form_type_extension.class%">
<tag name="form.type_extension" alias="form" />

View File

@ -21,11 +21,12 @@ class ApiDocTest extends TestCase
$data = array();
$annot = new ApiDoc($data);
$array = $annot->toArray();
$this->assertTrue(is_array($annot->getFilters()));
$this->assertCount(0, $annot->getFilters());
$this->assertTrue(is_array($array));
$this->assertFalse(isset($array['filters']));
$this->assertFalse($annot->isResource());
$this->assertNull($annot->getDescription());
$this->assertFalse(isset($array['description']));
$this->assertNull($annot->getFormType());
}
@ -37,11 +38,12 @@ class ApiDocTest extends TestCase
);
$annot = new ApiDoc($data);
$array = $annot->toArray();
$this->assertTrue(is_array($annot->getFilters()));
$this->assertCount(0, $annot->getFilters());
$this->assertTrue(is_array($array));
$this->assertFalse(isset($array['filters']));
$this->assertFalse($annot->isResource());
$this->assertNull($annot->getDescription());
$this->assertFalse(isset($array['description']));
$this->assertNull($annot->getFormType());
}
@ -52,11 +54,12 @@ class ApiDocTest extends TestCase
);
$annot = new ApiDoc($data);
$array = $annot->toArray();
$this->assertTrue(is_array($annot->getFilters()));
$this->assertCount(0, $annot->getFilters());
$this->assertTrue(is_array($array));
$this->assertFalse(isset($array['filters']));
$this->assertFalse($annot->isResource());
$this->assertEquals($data['description'], $annot->getDescription());
$this->assertEquals($data['description'], $array['description']);
$this->assertNull($annot->getFormType());
}
@ -68,11 +71,12 @@ class ApiDocTest extends TestCase
);
$annot = new ApiDoc($data);
$array = $annot->toArray();
$this->assertTrue(is_array($annot->getFilters()));
$this->assertCount(0, $annot->getFilters());
$this->assertTrue(is_array($array));
$this->assertFalse(isset($array['filters']));
$this->assertFalse($annot->isResource());
$this->assertEquals($data['description'], $annot->getDescription());
$this->assertEquals($data['description'], $array['description']);
$this->assertEquals($data['formType'], $annot->getFormType());
}
@ -85,11 +89,12 @@ class ApiDocTest extends TestCase
);
$annot = new ApiDoc($data);
$array = $annot->toArray();
$this->assertTrue(is_array($annot->getFilters()));
$this->assertCount(0, $annot->getFilters());
$this->assertTrue(is_array($array));
$this->assertFalse(isset($array['filters']));
$this->assertTrue($annot->isResource());
$this->assertEquals($data['description'], $annot->getDescription());
$this->assertEquals($data['description'], $array['description']);
$this->assertEquals($data['formType'], $annot->getFormType());
}
@ -102,11 +107,12 @@ class ApiDocTest extends TestCase
);
$annot = new ApiDoc($data);
$array = $annot->toArray();
$this->assertTrue(is_array($annot->getFilters()));
$this->assertCount(0, $annot->getFilters());
$this->assertTrue(is_array($array));
$this->assertFalse(isset($array['filters']));
$this->assertFalse($annot->isResource());
$this->assertEquals($data['description'], $annot->getDescription());
$this->assertEquals($data['description'], $array['description']);
$this->assertEquals($data['formType'], $annot->getFormType());
}
@ -121,12 +127,14 @@ class ApiDocTest extends TestCase
);
$annot = new ApiDoc($data);
$array = $annot->toArray();
$this->assertTrue(is_array($annot->getFilters()));
$this->assertCount(1, $annot->getFilters());
$this->assertEquals(array('a-filter' => array()), $annot->getFilters());
$this->assertTrue(is_array($array));
$this->assertTrue(is_array($array['filters']));
$this->assertCount(1, $array['filters']);
$this->assertEquals(array('a-filter' => array()), $array['filters']);
$this->assertTrue($annot->isResource());
$this->assertEquals($data['description'], $annot->getDescription());
$this->assertEquals($data['description'], $array['description']);
$this->assertNull($annot->getFormType());
}
@ -157,12 +165,12 @@ class ApiDocTest extends TestCase
);
$annot = new ApiDoc($data);
$array = $annot->toArray();
$this->assertTrue(is_array($annot->getFilters()));
$this->assertCount(0, $annot->getFilters());
$this->assertEquals(array(), $annot->getFilters());
$this->assertTrue(is_array($array));
$this->assertFalse(isset($array['filters']));
$this->assertTrue($annot->isResource());
$this->assertEquals($data['description'], $annot->getDescription());
$this->assertEquals($data['description'], $array['description']);
$this->assertEquals($data['formType'], $annot->getFormType());
}
}

View File

@ -22,62 +22,67 @@ class ApiDocExtractorTest extends WebTestCase
$data = $extractor->all();
$this->assertTrue(is_array($data));
$this->assertCount(9, $data);
$this->assertCount(10, $data);
foreach ($data as $d) {
$this->assertTrue(is_array($d));
$this->assertArrayHasKey('annotation', $d);
$this->assertArrayHasKey('route', $d);
$this->assertArrayHasKey('resource', $d);
$this->assertInstanceOf('Nelmio\ApiDocBundle\Annotation\ApiDoc', $d['annotation']);
$this->assertInstanceOf('Symfony\Component\Routing\Route', $d['route']);
$this->assertInstanceOf('Symfony\Component\Routing\Route', $d['annotation']->getRoute());
$this->assertNotNull($d['resource']);
}
$a1 = $data[0]['annotation'];
$array1 = $a1->toArray();
$this->assertTrue($a1->isResource());
$this->assertEquals('index action', $a1->getDescription());
$this->assertTrue(is_array($a1->getFilters()));
$this->assertTrue(is_array($array1['filters']));
$this->assertNull($a1->getFormType());
$a1 = $data[1]['annotation'];
$array1 = $a1->toArray();
$this->assertTrue($a1->isResource());
$this->assertEquals('index action', $a1->getDescription());
$this->assertTrue(is_array($a1->getFilters()));
$this->assertTrue(is_array($array1['filters']));
$this->assertNull($a1->getFormType());
$a2 = $data[2]['annotation'];
$array2 = $a2->toArray();
$this->assertFalse($a2->isResource());
$this->assertEquals('create test', $a2->getDescription());
$this->assertTrue(is_array($a2->getFilters()));
$this->assertFalse(isset($array2['filters']));
$this->assertEquals('Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType', $a2->getFormType());
$a2 = $data[3]['annotation'];
$array2 = $a2->toArray();
$this->assertFalse($a2->isResource());
$this->assertEquals('create test', $a2->getDescription());
$this->assertTrue(is_array($a2->getFilters()));
$this->assertFalse(isset($array2['filters']));
$this->assertEquals('Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType', $a2->getFormType());
}
public function testGet()
{
$container = $this->getContainer();
$extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor');
$data = $extractor->get('Nelmio\ApiDocBundle\Tests\Fixtures\Controller\TestController::indexAction', 'test_route_1');
$container = $this->getContainer();
$extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor');
$annotation = $extractor->get('Nelmio\ApiDocBundle\Tests\Fixtures\Controller\TestController::indexAction', 'test_route_1');
$this->assertTrue(isset($data['route']));
$this->assertTrue(isset($data['annotation']));
$this->assertInstanceOf('Nelmio\ApiDocBundle\Annotation\ApiDoc', $annotation);
$a = $data['annotation'];
$this->assertTrue($a->isResource());
$this->assertEquals('index action', $a->getDescription());
$this->assertTrue(is_array($a->getFilters()));
$this->assertNull($a->getFormType());
$this->assertTrue($annotation->isResource());
$this->assertEquals('index action', $annotation->getDescription());
$data2 = $extractor->get('nemlio.test.controller:indexAction', 'test_service_route_1');
$data2['route']->setDefault('_controller', $data['route']->getDefault('_controller'));
$this->assertEquals($data, $data2);
$array = $annotation->toArray();
$this->assertTrue(is_array($array['filters']));
$this->assertNull($annotation->getFormType());
$annotation2 = $extractor->get('nemlio.test.controller:indexAction', 'test_service_route_1');
$annotation2->getRoute()
->setDefault('_controller', $annotation->getRoute()->getDefault('_controller'))
->compile(); // compile as we changed a default value
$this->assertEquals($annotation, $annotation2);
}
public function testGetWithBadController()
@ -134,14 +139,14 @@ class ApiDocExtractorTest extends WebTestCase
public function testGetWithDocComment()
{
$container = $this->getContainer();
$extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor');
$data = $extractor->get('Nelmio\ApiDocBundle\Tests\Fixtures\Controller\TestController::myCommentedAction', 'test_route_5');
$container = $this->getContainer();
$extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor');
$annotation = $extractor->get('Nelmio\ApiDocBundle\Tests\Fixtures\Controller\TestController::myCommentedAction', 'test_route_5');
$this->assertNotNull($data);
$this->assertNotNull($annotation);
$this->assertEquals(
"This method is useful to test if the getDocComment works.",
$data['annotation']->getDescription()
$annotation->getDescription()
);
}
}

View File

@ -11,6 +11,7 @@
namespace Nelmio\ApiDocBundle\Tests\Fixtures\Controller;
use FOS\RestBundle\Controller\Annotations\QueryParam;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Symfony\Component\HttpFoundation\Response;
@ -81,4 +82,12 @@ class TestController
public function anotherPostAction()
{
}
/**
* @ApiDoc()
* @QueryParam(name="page", requirements="\d+", default="1", description="Page of the overview.")
*/
public function zActionWithQueryParamAction()
{
}
}

View File

@ -34,6 +34,12 @@ test_route_7:
requirements:
_method: POST
test_route_8:
pattern: /z-action-with-query-param
defaults: { _controller: NelmioApiDocTestBundle:Test:zActionWithQueryParam }
requirements:
_method: GET
test_service_route_1:
pattern: /tests
defaults: { _controller: nemlio.test.controller:indexAction, _format: json }

View File

@ -158,6 +158,17 @@ _This method is useful to test if the getDocComment works._
**id**
- Requirement: \d+
### `GET` /z-action-with-query-param ###
#### Filters ####
page:
* requirement: \d+
* description: Page of the overview.
MARKDOWN;
$this->assertEquals($expected, $result);
@ -167,9 +178,9 @@ MARKDOWN;
{
$container = $this->getContainer();
$extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor');
$data = $extractor->get('Nelmio\ApiDocBundle\Tests\Fixtures\Controller\TestController::indexAction', 'test_route_1');
$result = $container->get('nelmio_api_doc.formatter.markdown_formatter')->formatOne($data['annotation'], $data['route']);
$extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor');
$annotation = $extractor->get('Nelmio\ApiDocBundle\Tests\Fixtures\Controller\TestController::indexAction', 'test_route_1');
$result = $container->get('nelmio_api_doc.formatter.markdown_formatter')->formatOne($annotation);
$expected = <<<MARKDOWN
### `GET` /tests ###

View File

@ -30,9 +30,6 @@ class SimpleFormatterTest extends WebTestCase
array(
'method' => 'GET',
'uri' => '/tests',
'requirements' =>
array(
),
'filters' =>
array(
'a' =>
@ -55,9 +52,6 @@ class SimpleFormatterTest extends WebTestCase
array(
'method' => 'GET',
'uri' => '/tests',
'requirements' =>
array(
),
'filters' =>
array(
'a' =>
@ -80,9 +74,6 @@ class SimpleFormatterTest extends WebTestCase
array(
'method' => 'POST',
'uri' => '/tests',
'requirements' =>
array(
),
'parameters' =>
array(
'a' =>
@ -110,9 +101,6 @@ class SimpleFormatterTest extends WebTestCase
array(
'method' => 'POST',
'uri' => '/tests',
'requirements' =>
array(
),
'parameters' =>
array(
'a' =>
@ -143,9 +131,6 @@ class SimpleFormatterTest extends WebTestCase
array(
'method' => 'POST',
'uri' => '/another-post',
'requirements' =>
array(
),
'parameters' =>
array(
'a' =>
@ -161,9 +146,6 @@ class SimpleFormatterTest extends WebTestCase
array(
'method' => 'ANY',
'uri' => '/any',
'requirements' =>
array(
),
'description' => 'Action without HTTP verb',
),
2 =>
@ -197,6 +179,15 @@ class SimpleFormatterTest extends WebTestCase
'id' => array('type' => '', 'description' => '', 'requirement' => '\d+')
),
),
5 =>
array(
'method' => 'GET',
'uri' => '/z-action-with-query-param',
'filters' =>
array(
'page' => array('description' => 'Page of the overview.', 'requirement' => '\d+')
),
),
),
);
@ -207,14 +198,13 @@ class SimpleFormatterTest extends WebTestCase
{
$container = $this->getContainer();
$extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor');
$data = $extractor->get('Nelmio\ApiDocBundle\Tests\Fixtures\Controller\TestController::indexAction', 'test_route_1');
$result = $container->get('nelmio_api_doc.formatter.simple_formatter')->formatOne($data['annotation'], $data['route']);
$extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor');
$annotation = $extractor->get('Nelmio\ApiDocBundle\Tests\Fixtures\Controller\TestController::indexAction', 'test_route_1');
$result = $container->get('nelmio_api_doc.formatter.simple_formatter')->formatOne($annotation);
$expected = array(
'method' => 'GET',
'uri' => '/tests',
'requirements' => array(),
'filters' => array(
'a' => array(
'dataType' => 'integer',