diff --git a/DependencyInjection/NelmioApiDocExtension.php b/DependencyInjection/NelmioApiDocExtension.php
index ce10263..9c04b28 100644
--- a/DependencyInjection/NelmioApiDocExtension.php
+++ b/DependencyInjection/NelmioApiDocExtension.php
@@ -16,6 +16,7 @@ use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Config\FileLocator;
+use Symfony\Component\DependencyInjection\Reference;
class NelmioApiDocExtension extends Extension
{
@@ -48,5 +49,18 @@ class NelmioApiDocExtension extends Extension
if (isset($config['sandbox']['authentication'])) {
$container->setParameter('nelmio_api_doc.sandbox.authentication', $config['sandbox']['authentication']);
}
+
+ // Adding handlers from tagged services
+ $definition = $container->getDefinition(
+ 'nelmio_api_doc.extractor.api_doc_extractor'
+ );
+ $taggedServices = $container->findTaggedServiceIds(
+ 'nelmio_api_doc.extractor.handler'
+ );
+ $handlers = array();
+ foreach ($taggedServices as $id => $attributes) {
+ $handlers[] = new Reference($id);
+ }
+ $definition->replaceArgument(4, $handlers);
}
}
diff --git a/Extractor/ApiDocExtractor.php b/Extractor/ApiDocExtractor.php
index e338fe9..6682e39 100644
--- a/Extractor/ApiDocExtractor.php
+++ b/Extractor/ApiDocExtractor.php
@@ -19,19 +19,12 @@ use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Nelmio\ApiDocBundle\Util\DocCommentExtractor;
+use Nelmio\ApiDocBundle\Extractor\Handler\HandlerInterface;
class ApiDocExtractor
{
const ANNOTATION_CLASS = 'Nelmio\\ApiDocBundle\\Annotation\\ApiDoc';
- const FOS_REST_QUERY_PARAM_CLASS = 'FOS\\RestBundle\\Controller\\Annotations\\QueryParam';
-
- const FOS_REST_REQUEST_PARAM_CLASS = 'FOS\\RestBundle\\Controller\\Annotations\\RequestParam';
-
- const JMS_SECURITY_EXTRA_SECURE_CLASS = 'JMS\\SecurityExtraBundle\\Annotation\\Secure';
-
- const CACHE_ANNOTATION_CLASS = 'Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Cache';
-
/**
* @var ContainerInterface
*/
@@ -57,12 +50,18 @@ class ApiDocExtractor
*/
protected $parsers = array();
- public function __construct(ContainerInterface $container, RouterInterface $router, Reader $reader, DocCommentExtractor $commentExtractor)
+ /**
+ * @var array HandlerInterface
+ */
+ protected $handlers;
+
+ public function __construct(ContainerInterface $container, RouterInterface $router, Reader $reader, DocCommentExtractor $commentExtractor, $handlers)
{
$this->container = $container;
$this->router = $router;
$this->reader = $reader;
$this->commentExtractor = $commentExtractor;
+ $this->handlers = $handlers;
}
/**
@@ -359,32 +358,9 @@ class ApiDocExtractor
*/
protected function parseAnnotations(ApiDoc $annotation, Route $route, \ReflectionMethod $method)
{
- foreach ($this->reader->getMethodAnnotations($method) as $annot) {
- if (is_a($annot, self::FOS_REST_QUERY_PARAM_CLASS)) {
- if ($annot->strict && $annot->default === null) {
- $annotation->addRequirement($annot->name, array(
- 'requirement' => $annot->requirements,
- 'dataType' => '',
- 'description' => $annot->description,
- ));
- } else {
- $annotation->addFilter($annot->name, array(
- 'requirement' => $annot->requirements,
- 'description' => $annot->description,
- ));
- }
- } elseif (is_a($annot, self::FOS_REST_REQUEST_PARAM_CLASS)) {
- $annotation->addParameter($annot->name, array(
- 'required' => $annot->strict && $annot->default === null,
- 'dataType' => $annot->requirements,
- 'description' => $annot->description,
- 'readonly' => false
- ));
- } elseif (is_a($annot, self::JMS_SECURITY_EXTRA_SECURE_CLASS)) {
- $annotation->setAuthentication(true);
- } elseif (is_a($annot, self::CACHE_ANNOTATION_CLASS)) {
- $annotation->setCache($annot->getMaxAge());
- }
+ $annots = $this->reader->getMethodAnnotations($method);
+ foreach ($this->handlers as $handler) {
+ $handler->handle($annotation, $annots);
}
}
}
diff --git a/Extractor/Handler/EmptyHandler.php b/Extractor/Handler/EmptyHandler.php
new file mode 100644
index 0000000..1b1f958
--- /dev/null
+++ b/Extractor/Handler/EmptyHandler.php
@@ -0,0 +1,22 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Nelmio\ApiDocBundle\Extractor\Handler;
+
+use Nelmio\ApiDocBundle\Extractor\HandlerInterface;
+use \Nelmio\ApiDocBundle\Annotation\ApiDoc;
+
+class EmptyHandler implements HandlerInterface
+{
+ public function handle(ApiDoc $annotation, $annotations)
+ {
+ }
+}
diff --git a/Extractor/Handler/FosRestQueryParamHandler.php b/Extractor/Handler/FosRestQueryParamHandler.php
new file mode 100644
index 0000000..bcbf9db
--- /dev/null
+++ b/Extractor/Handler/FosRestQueryParamHandler.php
@@ -0,0 +1,40 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Nelmio\ApiDocBundle\Extractor\Handler;
+
+use Nelmio\ApiDocBundle\Extractor\HandlerInterface;
+use \Nelmio\ApiDocBundle\Annotation\ApiDoc;
+
+class FosRestQueryParamHandler implements HandlerInterface
+{
+ const FOS_REST_QUERY_PARAM_CLASS = 'FOS\\RestBundle\\Controller\\Annotations\\QueryParam';
+
+ public function handle(ApiDoc $annotation, $annotations)
+ {
+ foreach ($annotations as $annot) {
+ if (is_a($annot, self::FOS_REST_QUERY_PARAM_CLASS)) {
+ if ($annot->strict && $annot->default === null) {
+ $annotation->addRequirement($annot->name, array(
+ 'requirement' => $annot->requirements,
+ 'dataType' => '',
+ 'description' => $annot->description,
+ ));
+ } else {
+ $annotation->addFilter($annot->name, array(
+ 'requirement' => $annot->requirements,
+ 'description' => $annot->description,
+ ));
+ }
+ }
+ }
+ }
+}
diff --git a/Extractor/Handler/FosRestRequestParamHandler.php b/Extractor/Handler/FosRestRequestParamHandler.php
new file mode 100644
index 0000000..1260bd4
--- /dev/null
+++ b/Extractor/Handler/FosRestRequestParamHandler.php
@@ -0,0 +1,34 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Nelmio\ApiDocBundle\Extractor\Handler;
+
+use Nelmio\ApiDocBundle\Extractor\HandlerInterface;
+use \Nelmio\ApiDocBundle\Annotation\ApiDoc;
+
+class FosRestRequestParamHandler implements HandlerInterface
+{
+ const FOS_REST_REQUEST_PARAM_CLASS = 'FOS\\RestBundle\\Controller\\Annotations\\RequestParam';
+
+ public function handle(ApiDoc $annotation, $annotations)
+ {
+ foreach ($annotations as $annot) {
+ if (is_a($annot, self::FOS_REST_REQUEST_PARAM_CLASS)) {
+ $annotation->addParameter($annot->name, array(
+ 'required' => $annot->strict && $annot->default === null,
+ 'dataType' => $annot->requirements,
+ 'description' => $annot->description,
+ 'readonly' => false
+ ));
+ }
+ }
+ }
+}
diff --git a/Extractor/Handler/JmsSecurityExtraSecureHandler.php b/Extractor/Handler/JmsSecurityExtraSecureHandler.php
new file mode 100644
index 0000000..1110ee1
--- /dev/null
+++ b/Extractor/Handler/JmsSecurityExtraSecureHandler.php
@@ -0,0 +1,29 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Nelmio\ApiDocBundle\Extractor\Handler;
+
+use Nelmio\ApiDocBundle\Extractor\HandlerInterface;
+use \Nelmio\ApiDocBundle\Annotation\ApiDoc;
+
+class JmsSecurityExtraSecureHandler implements HandlerInterface
+{
+ const JMS_SECURITY_EXTRA_SECURE_CLASS = 'JMS\\SecurityExtraBundle\\Annotation\\Secure';
+
+ public function handle(ApiDoc $annotation, $annotations)
+ {
+ foreach ($annotations as $annot) {
+ if (is_a($annot, self::JMS_SECURITY_EXTRA_SECURE_CLASS)) {
+ $annotation->setAuthentication(true);
+ }
+ }
+ }
+}
diff --git a/Extractor/Handler/SensioFrameworkExtraCacheHandler.php b/Extractor/Handler/SensioFrameworkExtraCacheHandler.php
new file mode 100644
index 0000000..1b22d86
--- /dev/null
+++ b/Extractor/Handler/SensioFrameworkExtraCacheHandler.php
@@ -0,0 +1,29 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Nelmio\ApiDocBundle\Extractor\Handler;
+
+use Nelmio\ApiDocBundle\Extractor\HandlerInterface;
+use \Nelmio\ApiDocBundle\Annotation\ApiDoc;
+
+class SensioFrameworkExtraCacheHandler implements HandlerInterface
+{
+ const CACHE_ANNOTATION_CLASS = 'Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Cache';
+
+ public function handle(ApiDoc $annotation, $annotations)
+ {
+ foreach ($annotations as $annot) {
+ if (is_a($annot, self::CACHE_ANNOTATION_CLASS)) {
+ $annotation->setCache($annot->getMaxAge());
+ }
+ }
+ }
+}
diff --git a/Extractor/HandlerInterface.php b/Extractor/HandlerInterface.php
new file mode 100644
index 0000000..bedf2ff
--- /dev/null
+++ b/Extractor/HandlerInterface.php
@@ -0,0 +1,19 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Nelmio\ApiDocBundle\Extractor;
+
+use Nelmio\ApiDocBundle\Annotation\ApiDoc;
+
+interface HandlerInterface
+{
+ public function handle(ApiDoc $annotation, $annotations);
+}
diff --git a/README.md b/README.md
index 0668cbb..a146aa2 100644
--- a/README.md
+++ b/README.md
@@ -236,6 +236,20 @@ You can also define your own motd content (above methods list). All you have to
motd:
template: AcmeApiBundle::Components/motd.html.twig
+## Using your own annotations ##
+
+If you have developped your own project-related annotations, and you want to parse them to populate the ApiDoc, you can provide custom handlers as services. You juste have to implements the `Nelmio\ApiDocBundle\Extractor\HandlerInterface` and tag it as `nelmio_api_doc.extractor.handler`.
+
+ #app/config/config.yml
+ services:
+ mybundle.api_doc.extractor.my_annotation_handler:
+ class: MyBundle\AnnotationHandler\MyAnnotationHandler;
+ tags:
+ - {name: nelmio_api_doc.extractor.handler}
+
+Look at examples in [Handlers](https://github.com/nelmio/NelmioApiDocBundle/tree/annotation_handlers/Extractor/Handler)
+
+
## Credits ##
The design is heavily inspired by the [swagger-ui](https://github.com/wordnik/swagger-ui) project.
diff --git a/Resources/config/services.xml b/Resources/config/services.xml
index c1f9f7e..c53998c 100644
--- a/Resources/config/services.xml
+++ b/Resources/config/services.xml
@@ -8,6 +8,11 @@
Nelmio\ApiDocBundle\Form\Extension\DescriptionFormTypeExtension
Nelmio\ApiDocBundle\Twig\Extension\MarkdownExtension
Nelmio\ApiDocBundle\Util\DocCommentExtractor
+
+ Nelmio\ApiDocBundle\Extractor\Handler\FosRestQueryParamHandler
+ Nelmio\ApiDocBundle\Extractor\Handler\FosRestRequestParamHandler
+ Nelmio\ApiDocBundle\Extractor\Handler\JmsSecurityExtraSecureHandler
+ Nelmio\ApiDocBundle\Extractor\Handler\SensioFrameworkExtraCacheHandler
@@ -18,6 +23,7 @@
+
@@ -27,6 +33,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+