[ApiBundle] Added a controller to get a complete documentation

* Added an Extractor to get the documentation from all annotated
controllers
* Refactored some parts (command, event listener, ...)
This commit is contained in:
William DURAND 2012-04-12 12:50:20 +02:00
parent 72b8976006
commit c4c7d14354
9 changed files with 102 additions and 55 deletions

View File

@ -9,11 +9,6 @@ use Symfony\Component\Console\Output\OutputInterface;
class DumpCommand extends ContainerAwareCommand
{
/**
* @var string
*/
protected $annotationClass = 'Nelmio\\ApiBundle\\Annotation\\ApiDoc';
/**
* @var array
*/
@ -43,22 +38,13 @@ class DumpCommand extends ContainerAwareCommand
$formatter = $this->getContainer()->get(sprintf('nelmio.api.formatter.%s_formatter', $format));
}
$results = array();
foreach ($routeCollection->all() as $route) {
preg_match('#(.+)::([\w]+)#', $route->getDefault('_controller'), $matches);
$method = new \ReflectionMethod($matches[1], $matches[2]);
if ($annot = $this->getContainer()->get('annotation_reader')->getMethodAnnotation($method, $this->annotationClass)) {
$results[] = $formatter->format($annot, $route);
}
}
$extractedDoc = $this->getContainer()->get('nelmio.api.extractor.api_doc_extractor')->all();
$result = $formatter->format($extractedDoc);
if ('json' === $format) {
$output->writeln(json_encode($results));
$output->writeln(json_encode($result));
} else {
foreach ($results as $result) {
$output->writeln($result);
}
$output->writeln($result);
}
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace Nelmio\ApiBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class ApiDocController extends Controller
{
public function indexAction()
{
$extractedDoc = $this->get('nelmio.api.extractor.api_doc_extractor')->all();
$htmlContent = $this->get('nelmio.api.formatter.html_formatter')->format($extractedDoc);
return new Response($htmlContent);
}
}

View File

@ -15,6 +15,7 @@ class NelmioApiExtension extends Extension
public function load(array $configs, ContainerBuilder $container)
{
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('formatters.xml');
$loader->load('request_listener.xml');
$loader->load('services.xml');
}

View File

@ -2,28 +2,22 @@
namespace Nelmio\ApiBundle\EventListener;
use Doctrine\Common\Annotations\Reader;
use Nelmio\ApiBundle\Extractor\ApiDocExtractor;
use Nelmio\ApiBundle\Formatter\FormatterInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Routing\RouterInterface;
class RequestListener
{
protected $annotationClass = 'Nelmio\\ApiBundle\\Annotation\\ApiDoc';
protected $reader;
protected $router;
protected $extractor;
protected $formatter;
public function __construct(Reader $reader, RouterInterface $router, FormatterInterface $formatter)
public function __construct(ApiDocExtractor $extractor, FormatterInterface $formatter)
{
$this->reader = $reader;
$this->router = $router;
$this->extractor = $extractor;
$this->formatter = $formatter;
}
@ -42,16 +36,15 @@ class RequestListener
return;
}
preg_match('#(.+)::([\w]+)#', $request->get('_controller'), $matches);
$method = new \ReflectionMethod($matches[1], $matches[2]);
$route = $request->get('_route');
$controller = $request->get('_controller');
$route = $request->get('_route');
if ($annot = $this->reader->getMethodAnnotation($method, $this->annotationClass)) {
if ($route = $this->router->getRouteCollection()->get($route)) {
$result = $this->formatter->format($annot, $route);
if (null !== $array = $this->extractor->get($controller, $route)) {
$result = $this->formatter->formatOne($array['annotation'], $array['route']);
$event->setResponse(new JsonResponse($result));
}
$event->setResponse(new Response($result, 200, array(
'Content-Type' => 'text/html'
)));
}
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace Nelmio\ApiBundle\Extractor;
use Doctrine\Common\Annotations\Reader;
use Symfony\Component\Routing\RouterInterface;
class ApiDocExtractor
{
const ANNOTATION_CLASS = 'Nelmio\\ApiBundle\\Annotation\\ApiDoc';
/**
* @var
*/
private $router;
/**
* @var \Doctrine\Common\Annotations\Reader
*/
private $reader;
public function __construct(RouterInterface $router, Reader $reader)
{
$this->router = $router;
$this->reader = $reader;
}
public function all()
{
$array = array();
foreach ($this->router->getRouteCollection()->all() as $route) {
preg_match('#(.+)::([\w]+)#', $route->getDefault('_controller'), $matches);
$method = new \ReflectionMethod($matches[1], $matches[2]);
if ($annot = $this->reader->getMethodAnnotation($method, self::ANNOTATION_CLASS)) {
$array[] = array('annotation' => $annot, 'route' => $route);
}
}
return $array;
}
public function get($controller, $route)
{
preg_match('#(.+)::([\w]+)#', $controller, $matches);
$method = new \ReflectionMethod($matches[1], $matches[2]);
if ($annot = $this->reader->getMethodAnnotation($method, self::ANNOTATION_CLASS)) {
if ($route = $this->router->getRouteCollection()->get($route)) {
return array('annotation' => $annot, 'route' => $route);
}
}
return null;
}
}

View File

@ -41,8 +41,7 @@ class FormTypeParser
}
}
$parameters[] = array(
'name' => $name,
$parameters[$name] = array(
'type' => $bestType,
'is_required' => $b->getRequired()
);

View File

@ -9,9 +9,8 @@
<services>
<service id="nelmio.api.event_listener.request" class="%nelmio.api.event_listener.request.class%">
<argument type="service" id="annotation_reader" />
<argument type="service" id="router" />
<argument type="service" id="nelmio.api.formatter.simple_formatter" />
<argument type="service" id="nelmio.api.extractor.api_doc_extractor" />
<argument type="service" id="nelmio.api.formatter.html_formatter" />
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" />
</service>
</services>

View File

@ -0,0 +1,5 @@
nelmio_api_api_doc_index:
pattern: /api/doc
defaults: { _controller: NelmioApiBundle:ApiDoc:index }
requirements:
_method: GET

View File

@ -4,23 +4,14 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="nelmio.api.parser.form_type_parser.class">Nelmio\ApiBundle\Parser\FormTypeParser</parameter>
<parameter key="nelmio.api.formatter.abstract_formatter.class">Nelmio\ApiBundle\Formatter\AbstractFormatter</parameter>
<parameter key="nelmio.api.formatter.markdown_formatter.class">Nelmio\ApiBundle\Formatter\MarkdownFormatter</parameter>
<parameter key="nelmio.api.formatter.simple_formatter.class">Nelmio\ApiBundle\Formatter\SimpleFormatter</parameter>
<parameter key="nelmio.api.extractor.api_doc_extractor.class">Nelmio\ApiBundle\Extractor\ApiDocExtractor</parameter>
</parameters>
<services>
<service id="nelmio.api.parser.form_type_parser" class="%nelmio.api.parser.form_type_parser.class%">
<argument type="service" id="form.factory" />
<service id="nelmio.api.extractor.api_doc_extractor" class="%nelmio.api.extractor.api_doc_extractor.class%">
<argument type="service" id="router" />
<argument type="service" id="annotation_reader" />
</service>
<service id="nelmio.api.formatter.abstract_formatter" class="%nelmio.api.formatter.abstract_formatter.class%">
<argument type="service" id="nelmio.api.parser.form_type_parser" />
</service>
<service id="nelmio.api.formatter.markdown_formatter" class="%nelmio.api.formatter.markdown_formatter.class%"
parent="nelmio.api.formatter.abstract_formatter" />
<service id="nelmio.api.formatter.simple_formatter" class="%nelmio.api.formatter.simple_formatter.class%"
parent="nelmio.api.formatter.abstract_formatter" />
</services>
</container>