[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 class DumpCommand extends ContainerAwareCommand
{ {
/**
* @var string
*/
protected $annotationClass = 'Nelmio\\ApiBundle\\Annotation\\ApiDoc';
/** /**
* @var array * @var array
*/ */
@ -43,22 +38,13 @@ class DumpCommand extends ContainerAwareCommand
$formatter = $this->getContainer()->get(sprintf('nelmio.api.formatter.%s_formatter', $format)); $formatter = $this->getContainer()->get(sprintf('nelmio.api.formatter.%s_formatter', $format));
} }
$results = array(); $extractedDoc = $this->getContainer()->get('nelmio.api.extractor.api_doc_extractor')->all();
foreach ($routeCollection->all() as $route) { $result = $formatter->format($extractedDoc);
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);
}
}
if ('json' === $format) { if ('json' === $format) {
$output->writeln(json_encode($results)); $output->writeln(json_encode($result));
} else { } 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) public function load(array $configs, ContainerBuilder $container)
{ {
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('formatters.xml');
$loader->load('request_listener.xml'); $loader->load('request_listener.xml');
$loader->load('services.xml'); $loader->load('services.xml');
} }

View File

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

View File

@ -9,9 +9,8 @@
<services> <services>
<service id="nelmio.api.event_listener.request" class="%nelmio.api.event_listener.request.class%"> <service id="nelmio.api.event_listener.request" class="%nelmio.api.event_listener.request.class%">
<argument type="service" id="annotation_reader" /> <argument type="service" id="nelmio.api.extractor.api_doc_extractor" />
<argument type="service" id="router" /> <argument type="service" id="nelmio.api.formatter.html_formatter" />
<argument type="service" id="nelmio.api.formatter.simple_formatter" />
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" /> <tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" />
</service> </service>
</services> </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"> xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters> <parameters>
<parameter key="nelmio.api.parser.form_type_parser.class">Nelmio\ApiBundle\Parser\FormTypeParser</parameter> <parameter key="nelmio.api.extractor.api_doc_extractor.class">Nelmio\ApiBundle\Extractor\ApiDocExtractor</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>
</parameters> </parameters>
<services> <services>
<service id="nelmio.api.parser.form_type_parser" class="%nelmio.api.parser.form_type_parser.class%"> <service id="nelmio.api.extractor.api_doc_extractor" class="%nelmio.api.extractor.api_doc_extractor.class%">
<argument type="service" id="form.factory" /> <argument type="service" id="router" />
<argument type="service" id="annotation_reader" />
</service> </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> </services>
</container> </container>