Merge pull request #49 from willdurand/refactoring

Refactoring
This commit is contained in:
Jordi Boggiano 2012-07-20 01:19:52 -07:00
commit b49ea21c36
17 changed files with 383 additions and 269 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

@ -46,6 +46,7 @@ class MarkdownFormatter extends AbstractFormatter
if (!empty($infos['type'])) {
$markdown .= sprintf(" - Type: %s\n", $infos['type']);
}
if (!empty($infos['description'])) {
$markdown .= sprintf(" - Description: %s\n", $infos['description']);
}
@ -61,7 +62,7 @@ class MarkdownFormatter extends AbstractFormatter
$markdown .= sprintf("%s:\n\n", $name);
foreach ($filter as $key => $value) {
$markdown .= sprintf(" * %s: %s\n", $key, trim(json_encode($value), '"'));
$markdown .= sprintf(" * %s: %s\n", ucwords($key), trim(str_replace('\\\\', '\\', json_encode($value)), '"'));
}
$markdown .= "\n";

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

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

@ -262,7 +262,6 @@ li.operation div.heading h3 span.path {
li.operation div.content {
border: 1px solid black;
border-top: none;
padding: 10px;
-moz-border-radius-bottomleft: 6px;
-webkit-border-bottom-left-radius: 6px;
@ -445,7 +444,6 @@ li.operation.patch div.content h4 {
.panes {
clear: both;
border-top: 1px solid #C3D9EC;
}
.pane.sandbox {

View File

@ -72,7 +72,7 @@
{% for key, value in infos %}
<tr>
<td>{{ key|title }}</td>
<td>{{ value|json_encode|trim('"') }}</td>
<td>{{ value|json_encode|replace({'\\\\': '\\'})|trim('"') }}</td>
</tr>
{% endfor %}
</table>

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

@ -34,12 +34,12 @@ _index action_
a:
* dataType: integer
* DataType: integer
b:
* dataType: string
* arbitrary: ["arg1","arg2"]
* DataType: string
* Arbitrary: ["arg1","arg2"]
### `GET` /tests ###
@ -50,12 +50,12 @@ _index action_
a:
* dataType: integer
* DataType: integer
b:
* dataType: string
* arbitrary: ["arg1","arg2"]
* DataType: string
* Arbitrary: ["arg1","arg2"]
### `POST` /tests ###
@ -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 ###
@ -180,12 +191,12 @@ _index action_
a:
* dataType: integer
* DataType: integer
b:
* dataType: string
* arbitrary: ["arg1","arg2"]
* DataType: string
* Arbitrary: ["arg1","arg2"]
MARKDOWN;

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',