Skip to content

Commit

Permalink
Add: Example Generator for NelmioApiDocBundle
Browse files Browse the repository at this point in the history
  • Loading branch information
BenjaminPaap committed Mar 14, 2018
1 parent e96cb17 commit 19a4bc6
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 8 deletions.
29 changes: 21 additions & 8 deletions Resources/config/services.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
parameters:
bpa_apisandbox_controller_listener_class: 'Bpa\ApiSandboxBundle\EventListener\SandboxControllerListener'
bpa_apisandbox_controller_service_class: 'Bpa\ApiSandboxBundle\Service\ControllerService'
bpa_apisandbox_apidoc_listener_class: 'Bpa\ApiSandboxBundle\EventListener\ApiDocListener'
bpa_apisandbox_example_generator_class: 'Bpa\ApiSandboxBundle\Service\ApiDoc\Extractor\ExampleGenerator'

services:
bpa_sandbox.controller_listener:
class: 'Bpa\ApiSandboxBundle\EventListener\SandboxControllerListener'
bpa_apisandbox.controller_listener:
class: %bpa_apisandbox_controller_listener_class%
arguments:
- '%bpa_apisandbox.enabled%'
- '@bpa_sandbox.controller_service'
- '@bpa_apisandbox.controller_service'
- '@request_stack'
tags:
- { name: 'kernel.event_listener', event: 'kernel.controller', method: 'onKernelController' }

bpa_sandbox.controller_service:
class: 'Bpa\ApiSandboxBundle\Service\ControllerService'
bpa_apisandbox.controller_service:
class: %bpa_apisandbox_controller_service_class%
arguments:
- '@request_stack'
- '@annotations.reader'
- '@event_dispatcher'
- '@file_locator'
- '%api_sandbox.response.force'
- %bpa_apisandbox.response.force%

bpa_sandbox.apidoc_listener:
class: 'Bpa\ApiSandboxBundle\EventListener\ApiDocListener'
bpa_apisandbox.apidoc_listener:
class: %bpa_apisandbox_apidoc_listener_class%
tags:
- { name: 'kernel.event_listener', event: 'annotations.loaded', method: 'onAnnotationsLoaded' }

bpa_apisandbox.example_generator:
class: %bpa_apisandbox_example_generator_class%
arguments:
- '@twig'
tags:
- { name: nelmio_api_doc.extractor.handler }
26 changes: 26 additions & 0 deletions Resources/views/doc/example.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
##### Example

```bash
$ curl --header "Authorization: Bearer {token}" \
--header "Accept: application/json" \
{% if route.methods and route.methods[0] != 'GET' %}
--request {{ route.methods[0] }} \
{% endif %}
{{ route.path }}
```

###### Response

```http
HTTP/1.1 {{ response.statusCode }} {{ codes[response.statusCode] }}
{% for header in response.headers -%}
{{ header.name }}: {{ header.value }}{{ constant('PHP_EOL') -}}
{% endfor %}
```
{% if response.content is not empty -%}
```
{%- if response.type == constant('TYPE_JSON', response) %}json{% else %}xml{% endif %}
{{- constant('PHP_EOL') -}}
{% include response.content only -%}
```
{%- endif %}
105 changes: 105 additions & 0 deletions Service/ApiDoc/Extractor/ExampleGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php

namespace Bpa\ApiSandboxBundle\Service\ApiDoc\Extractor;

use Bpa\ApiSandboxBundle\Annotation\SandboxRequest;
use Bpa\ApiSandboxBundle\Annotation\SandboxResponse;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Nelmio\ApiDocBundle\Extractor\HandlerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Route;

/**
* Extracts example informations for NelmioApiDoc
*/
class ExampleGenerator implements HandlerInterface
{
/**
* @var \Twig_Environment
*/
protected $twig;

/**
* @param \Twig_Environment $twig
*/
public function __construct(\Twig_Environment $twig)
{
$this->twig = $twig;
}

/**
* @param ApiDoc $annotation
* @param array $annotations
* @param Route $route
* @param \ReflectionMethod $method
*/
public function handle(ApiDoc $annotation, array $annotations, Route $route, \ReflectionMethod $method)
{
if (null === $sandboxAnnotation = $this->findSandboxAnnotation($annotations)) {
return;
}

if (null !== $example = $this->buildExamples($sandboxAnnotation, $route)) {
$annotation->setDocumentation($annotation->getDocumentation().PHP_EOL.$example);
}
}

/**
* @param array $annotations
*
* @return SandboxRequest|null
*/
private function findSandboxAnnotation(array $annotations)
{
foreach ($annotations as $annotation) {
if ($annotation instanceof SandboxRequest) {
return $annotation;
}
}

return null;
}

/**
* @param SandboxRequest $annotation
*
* @return string
*/
protected function buildExamples(SandboxRequest $annotation, Route $route)
{
$examples = '';

// Iterate over all responses and generate markdown for this example
foreach ($annotation->getResponses() as $response) {
$examples .= $this->buildExample($route, $response);
}

return $examples;
}

/**
* @param Route $route
* @param SandboxResponse $response
*
* @return mixed|string
*/
protected function buildExample(Route $route, SandboxResponse $response)
{
$parameters = [];

// Extract parameters for this response
foreach ($response->getParameters() as $parameter) {
$parameters[$parameter->getName()] = $parameter->getValue();
}

// Render this example
$example = $this->twig->render('ApiSandboxBundle:doc:example.html.twig', [
'response' => $response,
'route' => $route,
'parameters' => $parameters,
'codes' => Response::$statusTexts,
]);

return $example;
}
}

0 comments on commit 19a4bc6

Please sign in to comment.