From 23f64b84f61c553de18b33ecb6eae58f3f00ca58 Mon Sep 17 00:00:00 2001
From: Josh Hall-Bachner <jhallbachner@gmail.com>
Date: Sun, 30 Jun 2013 21:28:40 -0700
Subject: [PATCH] Fixed multi-level validation nesting.

Removed "class" parameters from results after processed.

Updated README.
---
 Extractor/ApiDocExtractor.php                  | 16 +++++++++++++++-
 Parser/ValidationParser.php                    |  7 ++++++-
 README.md                                      |  5 +++--
 ...andlerTest.php => ValidationParserTest.php} | 18 ++++++++++--------
 4 files changed, 34 insertions(+), 12 deletions(-)
 rename Tests/Parser/{SymfonyValidationHandlerTest.php => ValidationParserTest.php} (86%)

diff --git a/Extractor/ApiDocExtractor.php b/Extractor/ApiDocExtractor.php
index 4ba5a37..da7cead 100644
--- a/Extractor/ApiDocExtractor.php
+++ b/Extractor/ApiDocExtractor.php
@@ -282,6 +282,8 @@ class ApiDocExtractor
                 }
             }
 
+            $parameters = $this->clearClasses($parameters);
+
             if ('PUT' === $method) {
                 // All parameters are optional with PUT (update)
                 array_walk($parameters, function($val, $key) use (&$data) {
@@ -303,6 +305,7 @@ class ApiDocExtractor
                     $response = $parser->parse($normalizedOutput);
                 }
             }
+            $response = $this->clearClasses($response);
 
             $annotation->setResponse($response);
         }
@@ -382,7 +385,7 @@ class ApiDocExtractor
 
     protected function mergeParameters($p1, $p2)
     {
-        $params = array();
+        $params = $p1;
 
         foreach($p2 as $propname => $propvalue) {
             if(!isset($p1[$propname])) {
@@ -434,4 +437,15 @@ class ApiDocExtractor
             $handler->handle($annotation, $annots, $route, $method);
         }
     }
+
+    protected function clearClasses($array)
+    {
+        if(is_array($array)) {
+            unset($array['class']);
+            foreach($array as $name => $item) {
+                $array[$name] = $this->clearClasses($item);
+            }
+        }
+        return $array;
+    }
 }
diff --git a/Parser/ValidationParser.php b/Parser/ValidationParser.php
index 1385cd4..0cb4399 100644
--- a/Parser/ValidationParser.php
+++ b/Parser/ValidationParser.php
@@ -71,7 +71,12 @@ class ValidationParser implements ParserInterface
         foreach($parameters as $param => $data) {
             if(isset($data['class']) && isset($data['children'])) {
                 $input = array('class' => $data['class']);
-                $parameters[$param]['children'] = $this->parse($input, $parameters[$param]['children']);
+                $parameters[$param]['children'] = array_merge(
+                    $parameters[$param]['children'], $this->postParse($input, $parameters[$param]['children'])
+                );
+                $parameters[$param]['children'] = array_merge(
+                    $parameters[$param]['children'], $this->parse($input, $parameters[$param]['children'])
+                );
             }
         }
 
diff --git a/README.md b/README.md
index ed38e28..b31a0e8 100644
--- a/README.md
+++ b/README.md
@@ -104,8 +104,9 @@ The following properties are available:
 
 * `filters`: an array of filters;
 
-* `input`: the input type associated to the method, currently this supports Form Types, and classes with JMS Serializer
- metadata, useful for POST|PUT methods, either as FQCN or as form type (if it is registered in the form factory in the container).
+* `input`: the input type associated to the method (currently this supports Form Types, classes with JMS Serializer
+ metadata, and classes with Validation component metadata) useful for POST|PUT methods, either as FQCN or as form type
+ (if it is registered in the form factory in the container).
 
 * `output`: the output type associated with the response.  Specified and parsed the same way as `input`.
 
diff --git a/Tests/Parser/SymfonyValidationHandlerTest.php b/Tests/Parser/ValidationParserTest.php
similarity index 86%
rename from Tests/Parser/SymfonyValidationHandlerTest.php
rename to Tests/Parser/ValidationParserTest.php
index 4deb76b..4e5c256 100644
--- a/Tests/Parser/SymfonyValidationHandlerTest.php
+++ b/Tests/Parser/ValidationParserTest.php
@@ -2,10 +2,10 @@
 namespace NelmioApiDocBundle\Tests\Parser;
 
 use Nelmio\ApiDocBundle\Tests\WebTestCase;
-use Nelmio\ApiDocBundle\Parser\Handler\SymfonyValidationHandler;
+use Nelmio\ApiDocBundle\Parser\ValidationParser;
 
 
-class SymfonyValidationHandlerTest extends WebTestCase
+class ValidationParserTest extends WebTestCase
 {
     protected $handler;
 
@@ -14,21 +14,23 @@ class SymfonyValidationHandlerTest extends WebTestCase
         $container  = $this->getContainer();
         $factory = $container->get('validator.mapping.class_metadata_factory');
 
-        $this->handler = new SymfonyValidationHandler($factory);
+        $this->parser = new ValidationParser($factory);
     }
 
     /**
-     * @dataProvider dataTestHandler
+     * @dataProvider dataTestParser
      */
-    public function testHandler($property, $expected)
+    public function testParser($property, $expected)
     {
-        $result = $this->handler->handle('Nelmio\ApiDocBundle\Tests\Fixtures\Model\ValidatorTest', $property, array());
+        $result = $this->parser->parse(array('class' => 'Nelmio\ApiDocBundle\Tests\Fixtures\Model\ValidatorTest'));
 
-        $this->assertEquals($expected, $result);
+        foreach($expected as $name => $value) {
+            $this->assertEquals($value, $expected[$name]);
+        }
     }
 
 
-    public function dataTestHandler()
+    public function dataTestParser()
     {
         return array(
             array(