Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added two new parameters to the ApiDoc Annotation

- 'responseCodes' allows to define the HTTP response codes and the situations when they are returned. (Think of Docblocks and Exceptions).
- 'include' allows to include a Markdown file with a long description.
- Minor tweaks: Made the Filters actually display as Markdown as well.
- When 'default' is included in filters, use this instead of the description for the sandbox.
  • Loading branch information...
commit bcd37d5ee1203b63674349f2f97bf19b057cc6f3 1 parent cbdddfe
Baldur Rensch authored baldurrensch committed
68  Annotation/ApiDoc.php
@@ -12,6 +12,7 @@
12 12
 namespace Nelmio\ApiDocBundle\Annotation;
13 13
 
14 14
 use Symfony\Component\Routing\Route;
  15
+use dflydev\markdown\MarkdownParser;
15 16
 
16 17
 /**
17 18
  * @Annotation
@@ -78,6 +79,18 @@ class ApiDoc
78 79
      */
79 80
     private $route;
80 81
 
  82
+    /**
  83
+     * Stores HTTP Response Codes and a description
  84
+     * @var array
  85
+     */
  86
+    private $responseCodes;
  87
+
  88
+    /**
  89
+     * An optional Markdown file to include with a long description. 
  90
+     * @var String
  91
+     */
  92
+    private $fileToInclude;
  93
+
81 94
     public function __construct(array $data)
82 95
     {
83 96
         if (isset($data['input'])) {
@@ -103,6 +116,14 @@ public function __construct(array $data)
103 116
             $this->return = $data['return'];
104 117
         }
105 118
 
  119
+        if (isset($data['responseCodes'])) {
  120
+            $this->responseCodes = $data['responseCodes'];
  121
+        }
  122
+
  123
+        if (isset($data['include'])) {
  124
+            $this->fileToInclude = $data['include'];
  125
+        }
  126
+
106 127
         $this->isResource = isset($data['resource']) && $data['resource'];
107 128
     }
108 129
 
@@ -241,6 +262,39 @@ public function getRoute()
241 262
     /**
242 263
      * @return array
243 264
      */
  265
+    public function getResponseCodes()
  266
+    {
  267
+        return $this->responseCodes;
  268
+    }
  269
+
  270
+    /**
  271
+     * @param array
  272
+     */
  273
+    public function addResponseCode($c)
  274
+    {
  275
+        $this->responseCodes = array_merge($this->responseCodes, $c);
  276
+    }
  277
+
  278
+    /**
  279
+     * @return String
  280
+     */
  281
+    public function getFileToInclude()
  282
+    {
  283
+        return $this->fileToInclude;
  284
+    }
  285
+    
  286
+    /**
  287
+     * @param String $newFileToInclude
  288
+     */
  289
+    public function setFileToInclude($newFileToInclude)
  290
+    {
  291
+        $this->fileToInclude = $newFileToInclude;
  292
+    }
  293
+
  294
+    /**
  295
+     * @return array
  296
+     * @throws \InvalidArgumentException if the file to be included is not readable 
  297
+     */
244 298
     public function toArray()
245 299
     {
246 300
         $data = array(
@@ -272,6 +326,20 @@ public function toArray()
272 326
             $data['response'] = $response;
273 327
         }
274 328
 
  329
+        if ($responseCodes = $this->responseCodes) {
  330
+            $data['responseCodes'] = $responseCodes;
  331
+        }
  332
+
  333
+        if ($fileToInclude = $this->fileToInclude) {
  334
+            if (!is_readable($fileToInclude)) {
  335
+                throw new \InvalidArgumentException("Could not open: {$fileToInclude}");
  336
+            }
  337
+
  338
+            $mdParser = new MarkdownParser();
  339
+            $fileContents = file_get_contents($fileToInclude);
  340
+            $data['fileToInclude'] = $mdParser->transform($fileContents);
  341
+        }
  342
+
275 343
         return $data;
276 344
     }
277 345
 }
6  DependencyInjection/Configuration.php
@@ -43,6 +43,12 @@ public function getConfigTreeBuilder()
43 43
                         ->end()
44 44
                     ->end()
45 45
                 ->end()
  46
+                ->arrayNode('include')
  47
+                    ->addDefaultsIfNotSet()
  48
+                    ->children()
  49
+                        ->scalarNode('location')->defaultValue('%kernel.root_dir%')->end()
  50
+                    ->end()
  51
+                ->end()
46 52
             ->end();
47 53
 
48 54
         return $treeBuilder;
1  DependencyInjection/NelmioApiDocExtension.php
@@ -31,6 +31,7 @@ public function load(array $configs, ContainerBuilder $container)
31 31
         $container->setParameter('nelmio_api_doc.api_name', $config['name']);
32 32
         $container->setParameter('nelmio_api_doc.sandbox.enabled',  $config['sandbox']['enabled']);
33 33
         $container->setParameter('nelmio_api_doc.sandbox.endpoint', $config['sandbox']['endpoint']);
  34
+        $container->setParameter('nelmio_api_doc.include.location', $config['include']['location']);
34 35
 
35 36
         $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
36 37
         $loader->load('formatters.xml');
5  Extractor/ApiDocExtractor.php
@@ -305,6 +305,11 @@ protected function extractData(ApiDoc $annotation, Route $route, \ReflectionMeth
305 305
         $annotation->setMethod($route->getRequirement('_method') ?: 'ANY');
306 306
         $annotation->setUri($route->getPattern());
307 307
 
  308
+        // Include File
  309
+        if ("" != ($fileToInclude = $annotation->getFileToInclude())) {
  310
+            $annotation->setFileToInclude($this->container->getParameter('nelmio_api_doc.include.location') . $fileToInclude);
  311
+        }
  312
+
308 313
         return $annotation;
309 314
     }
310 315
 
27  Resources/views/method.html.twig
@@ -28,6 +28,26 @@
28 28
             {% if data.documentation is defined and data.documentation is not empty %}
29 29
                 <h4>Documentation</h4>
30 30
                 <div>{{ data.documentation|extra_markdown }}</div>
  31
+                <div>{{ data.fileToInclude|raw }}</div>
  32
+            {% endif %}
  33
+
  34
+            {% if data.responseCodes is defined and data.responseCodes is not empty %}
  35
+            <h4>Response Codes</h4>
  36
+            <table class="fullwidth">
  37
+                <thead>
  38
+                    <tr>
  39
+                        <th>Response Code</th>
  40
+                        <th>Description</th>
  41
+                    </tr>
  42
+                </thead>
  43
+                <tbody>
  44
+                    {% for response_code, description in data.responseCodes %}
  45
+                    <tr>
  46
+                        <td><a href="http://en.wikipedia.org/wiki/HTTP_{{ response_code }}" target="_blank">{{ response_code }}<a/></td>
  47
+                        <td>{{ description }}</td>
  48
+                    {% endfor %}
  49
+                </tbody>
  50
+            </table>
31 51
             {% endif %}
32 52
 
33 53
             {% if data.requirements is defined  and data.requirements is not empty %}
@@ -71,8 +91,9 @@
71 91
                                 <table>
72 92
                                 {% for key, value in infos %}
73 93
                                     <tr>
74  
-                                        <td>{{ key|title }}</td>
75  
-                                        <td>{{ value|json_encode|replace({'\\\\': '\\'})|trim('"') }}</td>
  94
+                                        <td><strong>{{ key|title }}</strong></td>
  95
+                                        <td>{{ value|replace({'*': ''})|extra_markdown }}</td>
  96
+                                        {# <td>{{ value|json_encode|replace({'\\\\': '\\'})|trim('"') }}</td>#}
76 97
                                     </tr>
77 98
                                 {% endfor %}
78 99
                                 </table>
@@ -136,7 +157,7 @@
136 157
                                     <p class="tuple">
137 158
                                         <input type="text" class="key" value="{{ name }}" placeholder="Key" />
138 159
                                         <span>=</span>
139  
-                                        <input type="text" class="value" placeholder="{% if infos.description is defined %}{{ infos.description }}{% else %}Value{% endif %}" /> <span class="remove">-</span>
  160
+                                        <input type="text" class="value" placeholder="{% if infos.default is defined %}{{ infos.default }}{% elseif infos.description is defined %}{{ infos.description }}{% else %}Value{% endif %}" /> <span class="remove">-</span>
140 161
                                     </p>
141 162
                                 {% endfor %}
142 163
                             {% endif %}

0 notes on commit bcd37d5

Please sign in to comment.
Something went wrong with that request. Please try again.