From 06e3a2256bd89800c03b0478d5f26e61625a050f Mon Sep 17 00:00:00 2001 From: Evan Villemez Date: Thu, 19 Jul 2012 17:56:49 -0400 Subject: [PATCH 1/5] added a ParserInterface, refactored how Parsers are registered in the ApiDocExtractor, changed formType to inputClass in ApiDocExtractor --- Annotation/ApiDoc.php | 14 ++++--- .../RegisterExtractorClassParsersPass.php | 23 +++++++++++ Extractor/ApiDocExtractor.php | 32 +++++++++++---- NelmioApiDocBundle.php | 8 ++++ Parser/FormTypeParser.php | 24 +++++++---- Parser/ParserInterface.php | 40 +++++++++++++++++++ Resources/config/formatters.xml | 1 + Resources/config/services.xml | 1 - Tests/Annotation/ApiDocTest.php | 24 +++++------ Tests/Extractor/ApiDocExtratorTest.php | 10 ++--- Tests/Fixtures/Controller/TestController.php | 4 +- 11 files changed, 140 insertions(+), 41 deletions(-) create mode 100644 DependencyInjection/RegisterExtractorClassParsersPass.php create mode 100644 Parser/ParserInterface.php diff --git a/Annotation/ApiDoc.php b/Annotation/ApiDoc.php index 031814b..603227e 100644 --- a/Annotation/ApiDoc.php +++ b/Annotation/ApiDoc.php @@ -26,7 +26,7 @@ class ApiDoc /** * @var string */ - private $formType = null; + private $inputClass = null; /** * @var string @@ -70,8 +70,8 @@ class ApiDoc public function __construct(array $data) { - if (isset($data['formType'])) { - $this->formType = $data['formType']; + if (isset($data['inputClass'])) { + $this->inputClass = $data['inputClass']; } elseif (isset($data['filters'])) { foreach ($data['filters'] as $filter) { if (!isset($filter['name'])) { @@ -121,9 +121,9 @@ class ApiDoc /** * @return string|null */ - public function getFormType() + public function getInputClass() { - return $this->formType; + return $this->inputClass; } /** @@ -227,6 +227,10 @@ class ApiDoc if ($requirements = $this->requirements) { $data['requirements'] = $requirements; } + + if ($inputClass = $this->inputClass) { + $data['inputClass'] = $inputClass; + } return $data; } diff --git a/DependencyInjection/RegisterExtractorClassParsersPass.php b/DependencyInjection/RegisterExtractorClassParsersPass.php new file mode 100644 index 0000000..a7467fd --- /dev/null +++ b/DependencyInjection/RegisterExtractorClassParsersPass.php @@ -0,0 +1,23 @@ +hasDefinition('nelmio_api_doc.extractor.api_doc_extractor')) { + return; + } + + $definition = $container->getDefinition('nelmio_api_doc.extractor.api_doc_extractor'); + + foreach ($container->findTaggedServiceIds('nelmio_api_doc.extractor.class_parser') as $id => $attributes) { + $definition->addMethodCall('registerParser', array(new Reference($id))); + } + } +} \ No newline at end of file diff --git a/Extractor/ApiDocExtractor.php b/Extractor/ApiDocExtractor.php index a45dcf6..3678320 100644 --- a/Extractor/ApiDocExtractor.php +++ b/Extractor/ApiDocExtractor.php @@ -13,7 +13,7 @@ namespace Nelmio\ApiDocBundle\Extractor; use Doctrine\Common\Annotations\Reader; use Nelmio\ApiDocBundle\Annotation\ApiDoc; -use Nelmio\ApiDocBundle\Parser\FormTypeParser; +use Nelmio\ApiDocBundle\Parser\ParserInterface; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouterInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -41,16 +41,15 @@ class ApiDocExtractor private $reader; /** - * @var \Nelmio\ApiDocBundle\Parser\FormTypeParser + * @var array \Nelmio\ApiDocBundle\Parser\ParserInterface */ - private $parser; + private $parsers = array(); - public function __construct(ContainerInterface $container, RouterInterface $router, Reader $reader, FormTypeParser $parser) + public function __construct(ContainerInterface $container, RouterInterface $router, Reader $reader) { $this->container = $container; $this->router = $router; $this->reader = $reader; - $this->parser = $parser; } /** @@ -178,6 +177,17 @@ class ApiDocExtractor return null; } + + /** + * Registers a class parser to use for parsing input class metadata + * + * @param ParserInterface $parser + * @return void + */ + public function registerParser(ParserInterface $parser) + { + $this->parsers[] = $parser; + } /** * Returns a new ApiDoc instance with more data. @@ -215,9 +225,15 @@ class ApiDocExtractor // doc $annotation->setDocumentation($this->getDocCommentText($method)); - // formType - if (null !== $formType = $annotation->getFormType()) { - $parameters = $this->parser->parse($formType); + // inputClass + if (null !== $inputClass = $annotation->getInputClass()) { + $parameters = array(); + + foreach ($this->parsers as $parser) { + if ($parser->supportsClass($inputClass)) { + $parameters = $parser->parse($inputClass); + } + } if ('PUT' === $method) { // All parameters are optional with PUT (update) diff --git a/NelmioApiDocBundle.php b/NelmioApiDocBundle.php index b42aba2..4c3a0a5 100644 --- a/NelmioApiDocBundle.php +++ b/NelmioApiDocBundle.php @@ -3,7 +3,15 @@ namespace Nelmio\ApiDocBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Nelmio\ApiDocBundle\DependencyInjection\RegisterExtractorClassParsersPass; class NelmioApiDocBundle extends Bundle { + public function build(ContainerBuilder $container) + { + parent::build($container); + + $container->addCompilerPass(new RegisterExtractorClassParsersPass()); + } } diff --git a/Parser/FormTypeParser.php b/Parser/FormTypeParser.php index 4b0b11a..142f73d 100644 --- a/Parser/FormTypeParser.php +++ b/Parser/FormTypeParser.php @@ -14,7 +14,7 @@ namespace Nelmio\ApiDocBundle\Parser; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormFactoryInterface; -class FormTypeParser +class FormTypeParser implements ParserInterface { /** * @var \Symfony\Component\Form\FormFactoryInterface @@ -39,15 +39,22 @@ class FormTypeParser { $this->formFactory = $formFactory; } + + /** + * {@inheritdoc} + */ + public function supportsClass($class) + { + if (is_string($class) && class_exists($class)) { + $ref = new \ReflectionClass($class); + return ($ref->implementsInterface('Nelmio\ApiDocBundle\Parser\ParserInterface')); + } + + return false; + } /** - * Returns an array of data where each data is an array with the following keys: - * - dataType - * - required - * - description - * - * @param string|\Symfony\Component\Form\FormTypeInterface $type - * @return array + * {@inheritdoc} */ public function parse($type) { @@ -71,6 +78,7 @@ class FormTypeParser 'dataType' => $bestType, 'required' => $config->getRequired(), 'description' => $config->getAttribute('description'), + 'readonly' => false, ); } diff --git a/Parser/ParserInterface.php b/Parser/ParserInterface.php new file mode 100644 index 0000000..e22fb4d --- /dev/null +++ b/Parser/ParserInterface.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\Parser; + +/** + * This is the interface parsers must implement in order to be registered in the ApiDocExtractor. + */ +interface ParserInterface +{ + /** + * Return true/false whether this class supports parsing the given class. + * + * @param string $item The string name of the class to parse. + * @return boolean + */ + function supportsClass($className); + + /** + * Returns an array of class property metadata where each item is a key (the property name) and + * an array of data with the following keys: + * - dataType string + * - required boolean + * - description string + * - readonly boolean + * + * @param string $class The string name of the class to parse. + * @return array + */ + function parse($className); + +} \ No newline at end of file diff --git a/Resources/config/formatters.xml b/Resources/config/formatters.xml index d4e7984..6079c67 100644 --- a/Resources/config/formatters.xml +++ b/Resources/config/formatters.xml @@ -14,6 +14,7 @@ + - diff --git a/Tests/Annotation/ApiDocTest.php b/Tests/Annotation/ApiDocTest.php index d1904a6..993bd74 100644 --- a/Tests/Annotation/ApiDocTest.php +++ b/Tests/Annotation/ApiDocTest.php @@ -27,7 +27,7 @@ class ApiDocTest extends TestCase $this->assertFalse(isset($array['filters'])); $this->assertFalse($annot->isResource()); $this->assertFalse(isset($array['description'])); - $this->assertNull($annot->getFormType()); + $this->assertNull($annot->getInputClass()); } public function testConstructWithInvalidData() @@ -44,7 +44,7 @@ class ApiDocTest extends TestCase $this->assertFalse(isset($array['filters'])); $this->assertFalse($annot->isResource()); $this->assertFalse(isset($array['description'])); - $this->assertNull($annot->getFormType()); + $this->assertNull($annot->getInputClass()); } public function testConstruct() @@ -60,14 +60,14 @@ class ApiDocTest extends TestCase $this->assertFalse(isset($array['filters'])); $this->assertFalse($annot->isResource()); $this->assertEquals($data['description'], $array['description']); - $this->assertNull($annot->getFormType()); + $this->assertNull($annot->getInputClass()); } public function testConstructDefinesAFormType() { $data = array( 'description' => 'Heya', - 'formType' => 'My\Form\Type', + 'inputClass' => 'My\Form\Type', ); $annot = new ApiDoc($data); @@ -77,7 +77,7 @@ class ApiDocTest extends TestCase $this->assertFalse(isset($array['filters'])); $this->assertFalse($annot->isResource()); $this->assertEquals($data['description'], $array['description']); - $this->assertEquals($data['formType'], $annot->getFormType()); + $this->assertEquals($data['inputClass'], $annot->getInputClass()); } public function testConstructMethodIsResource() @@ -85,7 +85,7 @@ class ApiDocTest extends TestCase $data = array( 'resource' => true, 'description' => 'Heya', - 'formType' => 'My\Form\Type', + 'inputClass' => 'My\Form\Type', ); $annot = new ApiDoc($data); @@ -95,7 +95,7 @@ class ApiDocTest extends TestCase $this->assertFalse(isset($array['filters'])); $this->assertTrue($annot->isResource()); $this->assertEquals($data['description'], $array['description']); - $this->assertEquals($data['formType'], $annot->getFormType()); + $this->assertEquals($data['inputClass'], $annot->getInputClass()); } public function testConstructMethodResourceIsFalse() @@ -103,7 +103,7 @@ class ApiDocTest extends TestCase $data = array( 'resource' => false, 'description' => 'Heya', - 'formType' => 'My\Form\Type', + 'inputClass' => 'My\Form\Type', ); $annot = new ApiDoc($data); @@ -113,7 +113,7 @@ class ApiDocTest extends TestCase $this->assertFalse(isset($array['filters'])); $this->assertFalse($annot->isResource()); $this->assertEquals($data['description'], $array['description']); - $this->assertEquals($data['formType'], $annot->getFormType()); + $this->assertEquals($data['inputClass'], $annot->getInputClass()); } public function testConstructMethodHasFilters() @@ -135,7 +135,7 @@ class ApiDocTest extends TestCase $this->assertEquals(array('a-filter' => array()), $array['filters']); $this->assertTrue($annot->isResource()); $this->assertEquals($data['description'], $array['description']); - $this->assertNull($annot->getFormType()); + $this->assertNull($annot->getInputClass()); } /** @@ -158,7 +158,7 @@ class ApiDocTest extends TestCase $data = array( 'resource' => true, 'description' => 'Heya', - 'formType' => 'My\Form\Type', + 'inputClass' => 'My\Form\Type', 'filters' => array( array('name' => 'a-filter'), ), @@ -171,6 +171,6 @@ class ApiDocTest extends TestCase $this->assertFalse(isset($array['filters'])); $this->assertTrue($annot->isResource()); $this->assertEquals($data['description'], $array['description']); - $this->assertEquals($data['formType'], $annot->getFormType()); + $this->assertEquals($data['inputClass'], $annot->getInputClass()); } } diff --git a/Tests/Extractor/ApiDocExtratorTest.php b/Tests/Extractor/ApiDocExtratorTest.php index a71a955..b45bb92 100644 --- a/Tests/Extractor/ApiDocExtratorTest.php +++ b/Tests/Extractor/ApiDocExtratorTest.php @@ -39,28 +39,28 @@ class ApiDocExtractorTest extends WebTestCase $this->assertTrue($a1->isResource()); $this->assertEquals('index action', $a1->getDescription()); $this->assertTrue(is_array($array1['filters'])); - $this->assertNull($a1->getFormType()); + $this->assertNull($a1->getInputClass()); $a1 = $data[1]['annotation']; $array1 = $a1->toArray(); $this->assertTrue($a1->isResource()); $this->assertEquals('index action', $a1->getDescription()); $this->assertTrue(is_array($array1['filters'])); - $this->assertNull($a1->getFormType()); + $this->assertNull($a1->getInputClass()); $a2 = $data[2]['annotation']; $array2 = $a2->toArray(); $this->assertFalse($a2->isResource()); $this->assertEquals('create test', $a2->getDescription()); $this->assertFalse(isset($array2['filters'])); - $this->assertEquals('Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType', $a2->getFormType()); + $this->assertEquals('Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType', $a2->getInputClass()); $a2 = $data[3]['annotation']; $array2 = $a2->toArray(); $this->assertFalse($a2->isResource()); $this->assertEquals('create test', $a2->getDescription()); $this->assertFalse(isset($array2['filters'])); - $this->assertEquals('Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType', $a2->getFormType()); + $this->assertEquals('Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType', $a2->getInputClass()); } public function testGet() @@ -76,7 +76,7 @@ class ApiDocExtractorTest extends WebTestCase $array = $annotation->toArray(); $this->assertTrue(is_array($array['filters'])); - $this->assertNull($annotation->getFormType()); + $this->assertNull($annotation->getInputClass()); $annotation2 = $extractor->get('nemlio.test.controller:indexAction', 'test_service_route_1'); $annotation2->getRoute() diff --git a/Tests/Fixtures/Controller/TestController.php b/Tests/Fixtures/Controller/TestController.php index 1995a77..5275543 100644 --- a/Tests/Fixtures/Controller/TestController.php +++ b/Tests/Fixtures/Controller/TestController.php @@ -35,7 +35,7 @@ class TestController /** * @ApiDoc( * description="create test", - * formType="Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType" + * inputClass="Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType" * ) */ public function postTestAction() @@ -76,7 +76,7 @@ class TestController /** * @ApiDoc( * description="create another test", - * formType="dependency_type" + * inputClass="dependency_type" * ) */ public function anotherPostAction() From b2a2426f76c6c9286869285705db60970ec1fbba Mon Sep 17 00:00:00 2001 From: Evan Villemez Date: Mon, 23 Jul 2012 13:27:58 -0400 Subject: [PATCH 2/5] fixed check for wrong class in FormTypeParser, fixed CS in ParserInterface --- Parser/FormTypeParser.php | 2 +- Parser/ParserInterface.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Parser/FormTypeParser.php b/Parser/FormTypeParser.php index 142f73d..598663d 100644 --- a/Parser/FormTypeParser.php +++ b/Parser/FormTypeParser.php @@ -47,7 +47,7 @@ class FormTypeParser implements ParserInterface { if (is_string($class) && class_exists($class)) { $ref = new \ReflectionClass($class); - return ($ref->implementsInterface('Nelmio\ApiDocBundle\Parser\ParserInterface')); + return ($ref->implementsInterface('Symfony\Component\Form\FormTypeInterface')); } return false; diff --git a/Parser/ParserInterface.php b/Parser/ParserInterface.php index e22fb4d..df0ba93 100644 --- a/Parser/ParserInterface.php +++ b/Parser/ParserInterface.php @@ -22,7 +22,7 @@ interface ParserInterface * @param string $item The string name of the class to parse. * @return boolean */ - function supportsClass($className); + public function supportsClass($className); /** * Returns an array of class property metadata where each item is a key (the property name) and @@ -35,6 +35,6 @@ interface ParserInterface * @param string $class The string name of the class to parse. * @return array */ - function parse($className); + public function parse($className); } \ No newline at end of file From b9e8d61082bc080500f9b45ea1a06ed9f745a969 Mon Sep 17 00:00:00 2001 From: Evan Villemez Date: Mon, 23 Jul 2012 15:44:37 -0400 Subject: [PATCH 3/5] changed inputClass to input, refactored method and class names accordingly, fixed cs in several places --- Annotation/ApiDoc.php | 16 ++++---- .../RegisterExtractorClassParsersPass.php | 23 ------------ .../RegisterExtractorParsersPass.php | 37 +++++++++++++++++++ Extractor/ApiDocExtractor.php | 21 +++++------ Formatter/FormatterInterface.php | 2 +- NelmioApiDocBundle.php | 4 +- Parser/FormTypeParser.php | 21 +++++++---- Parser/ParserInterface.php | 14 +++---- Resources/config/formatters.xml | 2 +- Tests/Annotation/ApiDocTest.php | 24 ++++++------ Tests/Extractor/ApiDocExtratorTest.php | 10 ++--- 11 files changed, 95 insertions(+), 79 deletions(-) delete mode 100644 DependencyInjection/RegisterExtractorClassParsersPass.php create mode 100644 DependencyInjection/RegisterExtractorParsersPass.php diff --git a/Annotation/ApiDoc.php b/Annotation/ApiDoc.php index 603227e..6fdb4ac 100644 --- a/Annotation/ApiDoc.php +++ b/Annotation/ApiDoc.php @@ -26,7 +26,7 @@ class ApiDoc /** * @var string */ - private $inputClass = null; + private $input = null; /** * @var string @@ -70,8 +70,8 @@ class ApiDoc public function __construct(array $data) { - if (isset($data['inputClass'])) { - $this->inputClass = $data['inputClass']; + if (isset($data['input'])) { + $this->input = $data['input']; } elseif (isset($data['filters'])) { foreach ($data['filters'] as $filter) { if (!isset($filter['name'])) { @@ -121,9 +121,9 @@ class ApiDoc /** * @return string|null */ - public function getInputClass() + public function getInput() { - return $this->inputClass; + return $this->input; } /** @@ -227,9 +227,9 @@ class ApiDoc if ($requirements = $this->requirements) { $data['requirements'] = $requirements; } - - if ($inputClass = $this->inputClass) { - $data['inputClass'] = $inputClass; + + if ($input = $this->input) { + $data['input'] = $input; } return $data; diff --git a/DependencyInjection/RegisterExtractorClassParsersPass.php b/DependencyInjection/RegisterExtractorClassParsersPass.php deleted file mode 100644 index a7467fd..0000000 --- a/DependencyInjection/RegisterExtractorClassParsersPass.php +++ /dev/null @@ -1,23 +0,0 @@ -hasDefinition('nelmio_api_doc.extractor.api_doc_extractor')) { - return; - } - - $definition = $container->getDefinition('nelmio_api_doc.extractor.api_doc_extractor'); - - foreach ($container->findTaggedServiceIds('nelmio_api_doc.extractor.class_parser') as $id => $attributes) { - $definition->addMethodCall('registerParser', array(new Reference($id))); - } - } -} \ No newline at end of file diff --git a/DependencyInjection/RegisterExtractorParsersPass.php b/DependencyInjection/RegisterExtractorParsersPass.php new file mode 100644 index 0000000..abf8fca --- /dev/null +++ b/DependencyInjection/RegisterExtractorParsersPass.php @@ -0,0 +1,37 @@ +hasDefinition('nelmio_api_doc.extractor.api_doc_extractor')) { + return; + } + + $definition = $container->getDefinition('nelmio_api_doc.extractor.api_doc_extractor'); + + //find registered parsers and sort by priority + $sortedParsers = array(); + foreach ($container->findTaggedServiceIds('nelmio_api_doc.extractor.parser') as $id => $attributes) { + $priority = isset($attributes['priority']) ? $attributes['priority'] : 0; + $sortedParsers[$priority][] = $id; + } + + //add parsers if any + if (!empty($sortedParsers)) { + krsort($sortedParsers); + $sortedParsers = call_user_func_array('array_merge', $sortedParsers); + + //add method call for each registered parsers + foreach ($sortedParsers as $id) { + $definition->addMethodCall('addParser', array(new Reference($id))); + } + } + } +} diff --git a/Extractor/ApiDocExtractor.php b/Extractor/ApiDocExtractor.php index 3678320..dcc8af1 100644 --- a/Extractor/ApiDocExtractor.php +++ b/Extractor/ApiDocExtractor.php @@ -121,8 +121,6 @@ class ApiDocExtractor return strcmp($a['resource'], $b['resource']); }); - - return $array; } @@ -177,14 +175,13 @@ class ApiDocExtractor return null; } - + /** * Registers a class parser to use for parsing input class metadata * - * @param ParserInterface $parser - * @return void + * @param ParserInterface $parser */ - public function registerParser(ParserInterface $parser) + public function addParser(ParserInterface $parser) { $this->parsers[] = $parser; } @@ -225,13 +222,13 @@ class ApiDocExtractor // doc $annotation->setDocumentation($this->getDocCommentText($method)); - // inputClass - if (null !== $inputClass = $annotation->getInputClass()) { + // input + if (null !== $input = $annotation->getInput()) { $parameters = array(); foreach ($this->parsers as $parser) { - if ($parser->supportsClass($inputClass)) { - $parameters = $parser->parse($inputClass); + if ($parser->supports($input)) { + $parameters = $parser->parse($input); } } @@ -296,7 +293,7 @@ class ApiDocExtractor } /** - * @param Reflector $reflected + * @param Reflector $reflected * @return string */ protected function getDocComment(\Reflector $reflected) @@ -316,7 +313,7 @@ class ApiDocExtractor } /** - * @param Reflector $reflected + * @param Reflector $reflected * @return string */ protected function getDocCommentText(\Reflector $reflected) diff --git a/Formatter/FormatterInterface.php b/Formatter/FormatterInterface.php index dcbadd5..1a3302f 100644 --- a/Formatter/FormatterInterface.php +++ b/Formatter/FormatterInterface.php @@ -26,7 +26,7 @@ interface FormatterInterface /** * Format documentation data for one route. * - * @param ApiDoc $annotation + * @param ApiDoc $annotation * return string|array */ public function formatOne(ApiDoc $annotation); diff --git a/NelmioApiDocBundle.php b/NelmioApiDocBundle.php index 4c3a0a5..fbfe504 100644 --- a/NelmioApiDocBundle.php +++ b/NelmioApiDocBundle.php @@ -4,7 +4,7 @@ namespace Nelmio\ApiDocBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Nelmio\ApiDocBundle\DependencyInjection\RegisterExtractorClassParsersPass; +use Nelmio\ApiDocBundle\DependencyInjection\RegisterExtractorParsersPass; class NelmioApiDocBundle extends Bundle { @@ -12,6 +12,6 @@ class NelmioApiDocBundle extends Bundle { parent::build($container); - $container->addCompilerPass(new RegisterExtractorClassParsersPass()); + $container->addCompilerPass(new RegisterExtractorParsersPass()); } } diff --git a/Parser/FormTypeParser.php b/Parser/FormTypeParser.php index 598663d..af3bfac 100644 --- a/Parser/FormTypeParser.php +++ b/Parser/FormTypeParser.php @@ -11,8 +11,8 @@ namespace Nelmio\ApiDocBundle\Parser; -use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormFactoryInterface; +use Symfony\Component\Form\Exception\FormException; class FormTypeParser implements ParserInterface { @@ -39,18 +39,23 @@ class FormTypeParser implements ParserInterface { $this->formFactory = $formFactory; } - + /** * {@inheritdoc} */ - public function supportsClass($class) + public function supports($item) { - if (is_string($class) && class_exists($class)) { - $ref = new \ReflectionClass($class); - return ($ref->implementsInterface('Symfony\Component\Form\FormTypeInterface')); + try { + if (is_string($item) && class_exists($item)) { + $item = new $item(); + } + + $form = $this->formFactory->create($item); + } catch (FormException $e) { + return false; } - - return false; + + return true; } /** diff --git a/Parser/ParserInterface.php b/Parser/ParserInterface.php index df0ba93..8df98f5 100644 --- a/Parser/ParserInterface.php +++ b/Parser/ParserInterface.php @@ -19,11 +19,11 @@ interface ParserInterface /** * Return true/false whether this class supports parsing the given class. * - * @param string $item The string name of the class to parse. + * @param string $item The string type of input to parse. * @return boolean */ - public function supportsClass($className); - + public function supports($item); + /** * Returns an array of class property metadata where each item is a key (the property name) and * an array of data with the following keys: @@ -32,9 +32,9 @@ interface ParserInterface * - description string * - readonly boolean * - * @param string $class The string name of the class to parse. + * @param string $item The string type of input to parse. * @return array */ - public function parse($className); - -} \ No newline at end of file + public function parse($item); + +} diff --git a/Resources/config/formatters.xml b/Resources/config/formatters.xml index 6079c67..244fced 100644 --- a/Resources/config/formatters.xml +++ b/Resources/config/formatters.xml @@ -14,7 +14,7 @@ - + assertFalse(isset($array['filters'])); $this->assertFalse($annot->isResource()); $this->assertFalse(isset($array['description'])); - $this->assertNull($annot->getInputClass()); + $this->assertNull($annot->getInput()); } public function testConstructWithInvalidData() @@ -44,7 +44,7 @@ class ApiDocTest extends TestCase $this->assertFalse(isset($array['filters'])); $this->assertFalse($annot->isResource()); $this->assertFalse(isset($array['description'])); - $this->assertNull($annot->getInputClass()); + $this->assertNull($annot->getInput()); } public function testConstruct() @@ -60,14 +60,14 @@ class ApiDocTest extends TestCase $this->assertFalse(isset($array['filters'])); $this->assertFalse($annot->isResource()); $this->assertEquals($data['description'], $array['description']); - $this->assertNull($annot->getInputClass()); + $this->assertNull($annot->getInput()); } public function testConstructDefinesAFormType() { $data = array( 'description' => 'Heya', - 'inputClass' => 'My\Form\Type', + 'input' => 'My\Form\Type', ); $annot = new ApiDoc($data); @@ -77,7 +77,7 @@ class ApiDocTest extends TestCase $this->assertFalse(isset($array['filters'])); $this->assertFalse($annot->isResource()); $this->assertEquals($data['description'], $array['description']); - $this->assertEquals($data['inputClass'], $annot->getInputClass()); + $this->assertEquals($data['input'], $annot->getInput()); } public function testConstructMethodIsResource() @@ -85,7 +85,7 @@ class ApiDocTest extends TestCase $data = array( 'resource' => true, 'description' => 'Heya', - 'inputClass' => 'My\Form\Type', + 'input' => 'My\Form\Type', ); $annot = new ApiDoc($data); @@ -95,7 +95,7 @@ class ApiDocTest extends TestCase $this->assertFalse(isset($array['filters'])); $this->assertTrue($annot->isResource()); $this->assertEquals($data['description'], $array['description']); - $this->assertEquals($data['inputClass'], $annot->getInputClass()); + $this->assertEquals($data['input'], $annot->getInput()); } public function testConstructMethodResourceIsFalse() @@ -103,7 +103,7 @@ class ApiDocTest extends TestCase $data = array( 'resource' => false, 'description' => 'Heya', - 'inputClass' => 'My\Form\Type', + 'input' => 'My\Form\Type', ); $annot = new ApiDoc($data); @@ -113,7 +113,7 @@ class ApiDocTest extends TestCase $this->assertFalse(isset($array['filters'])); $this->assertFalse($annot->isResource()); $this->assertEquals($data['description'], $array['description']); - $this->assertEquals($data['inputClass'], $annot->getInputClass()); + $this->assertEquals($data['input'], $annot->getInput()); } public function testConstructMethodHasFilters() @@ -135,7 +135,7 @@ class ApiDocTest extends TestCase $this->assertEquals(array('a-filter' => array()), $array['filters']); $this->assertTrue($annot->isResource()); $this->assertEquals($data['description'], $array['description']); - $this->assertNull($annot->getInputClass()); + $this->assertNull($annot->getInput()); } /** @@ -158,7 +158,7 @@ class ApiDocTest extends TestCase $data = array( 'resource' => true, 'description' => 'Heya', - 'inputClass' => 'My\Form\Type', + 'input' => 'My\Form\Type', 'filters' => array( array('name' => 'a-filter'), ), @@ -171,6 +171,6 @@ class ApiDocTest extends TestCase $this->assertFalse(isset($array['filters'])); $this->assertTrue($annot->isResource()); $this->assertEquals($data['description'], $array['description']); - $this->assertEquals($data['inputClass'], $annot->getInputClass()); + $this->assertEquals($data['input'], $annot->getInput()); } } diff --git a/Tests/Extractor/ApiDocExtratorTest.php b/Tests/Extractor/ApiDocExtratorTest.php index b45bb92..b092643 100644 --- a/Tests/Extractor/ApiDocExtratorTest.php +++ b/Tests/Extractor/ApiDocExtratorTest.php @@ -39,28 +39,28 @@ class ApiDocExtractorTest extends WebTestCase $this->assertTrue($a1->isResource()); $this->assertEquals('index action', $a1->getDescription()); $this->assertTrue(is_array($array1['filters'])); - $this->assertNull($a1->getInputClass()); + $this->assertNull($a1->getInput()); $a1 = $data[1]['annotation']; $array1 = $a1->toArray(); $this->assertTrue($a1->isResource()); $this->assertEquals('index action', $a1->getDescription()); $this->assertTrue(is_array($array1['filters'])); - $this->assertNull($a1->getInputClass()); + $this->assertNull($a1->getInput()); $a2 = $data[2]['annotation']; $array2 = $a2->toArray(); $this->assertFalse($a2->isResource()); $this->assertEquals('create test', $a2->getDescription()); $this->assertFalse(isset($array2['filters'])); - $this->assertEquals('Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType', $a2->getInputClass()); + $this->assertEquals('Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType', $a2->getInput()); $a2 = $data[3]['annotation']; $array2 = $a2->toArray(); $this->assertFalse($a2->isResource()); $this->assertEquals('create test', $a2->getDescription()); $this->assertFalse(isset($array2['filters'])); - $this->assertEquals('Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType', $a2->getInputClass()); + $this->assertEquals('Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType', $a2->getInput()); } public function testGet() @@ -76,7 +76,7 @@ class ApiDocExtractorTest extends WebTestCase $array = $annotation->toArray(); $this->assertTrue(is_array($array['filters'])); - $this->assertNull($annotation->getInputClass()); + $this->assertNull($annotation->getInput()); $annotation2 = $extractor->get('nemlio.test.controller:indexAction', 'test_service_route_1'); $annotation2->getRoute() From 89f20445818910d565f76744484a6d8ac07c3221 Mon Sep 17 00:00:00 2001 From: Evan Villemez Date: Tue, 24 Jul 2012 14:39:43 -0400 Subject: [PATCH 4/5] fixed compiler pass, updated README --- .../RegisterExtractorParsersPass.php | 8 +++++--- Parser/FormTypeParser.php | 2 +- README.md | 18 ++++++++++++++---- Resources/config/formatters.xml | 2 +- Tests/Fixtures/Controller/TestController.php | 4 ++-- Tests/Formatter/SimpleFormatterTest.php | 7 +++++++ 6 files changed, 30 insertions(+), 11 deletions(-) diff --git a/DependencyInjection/RegisterExtractorParsersPass.php b/DependencyInjection/RegisterExtractorParsersPass.php index abf8fca..f9d4564 100644 --- a/DependencyInjection/RegisterExtractorParsersPass.php +++ b/DependencyInjection/RegisterExtractorParsersPass.php @@ -18,9 +18,11 @@ class RegisterExtractorParsersPass implements CompilerPassInterface //find registered parsers and sort by priority $sortedParsers = array(); - foreach ($container->findTaggedServiceIds('nelmio_api_doc.extractor.parser') as $id => $attributes) { - $priority = isset($attributes['priority']) ? $attributes['priority'] : 0; - $sortedParsers[$priority][] = $id; + foreach ($container->findTaggedServiceIds('nelmio_api_doc.extractor.parser') as $id => $tagAttributes) { + foreach ($tagAttributes as $attributes) { + $priority = isset($attributes['priority']) ? $attributes['priority'] : 0; + $sortedParsers[$priority][] = $id; + } } //add parsers if any diff --git a/Parser/FormTypeParser.php b/Parser/FormTypeParser.php index af3bfac..2bce09b 100644 --- a/Parser/FormTypeParser.php +++ b/Parser/FormTypeParser.php @@ -83,7 +83,7 @@ class FormTypeParser implements ParserInterface 'dataType' => $bestType, 'required' => $config->getRequired(), 'description' => $config->getAttribute('description'), - 'readonly' => false, + 'readonly' => $config->getDisabled(), ); } diff --git a/README.md b/README.md index 56772e9..ae19234 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ class YourController extends Controller /** * @ApiDoc( * description="Create a new Object", - * formType="Your\Namespace\Form\Type\YourType" + * input="Your\Namespace\Form\Type\YourType" * ) */ public function postAction() @@ -99,16 +99,16 @@ The following properties are available: * `filters`: an array of filters; -* `formType`: the Form Type associated to the method, useful for POST|PUT methods, either as FQCN or +* `input`: the input type associated to the method, currently this only supports Form Types, useful for POST|PUT methods, either as FQCN or as form type (if it is registered in the form factory in the container) Each _filter_ has to define a `name` parameter, but other parameters are free. Filters are often optional parameters, and you can document them as you want, but keep in mind to be consistent for the whole documentation. -If you set a `formType`, then the bundle automatically extracts parameters based on the given type, +If you set `input`, then the bundle automatically extracts parameters based on the given type, and determines for each parameter its data type, and if it's required or not. -You can add an extra option named `description` on each field: +For Form Types, you can add an extra option named `description` on each field: ``` php - + 'string', 'required' => true, 'description' => 'A nice description', + 'readonly' => false ), 'b' => array( 'dataType' => 'string', 'required' => false, 'description' => '', + 'readonly' => false ), 'c' => array( 'dataType' => 'boolean', 'required' => true, 'description' => '', + 'readonly' => false ), ), 'description' => 'create test', @@ -108,18 +111,21 @@ class SimpleFormatterTest extends WebTestCase 'dataType' => 'string', 'required' => true, 'description' => 'A nice description', + 'readonly' => false ), 'b' => array( 'dataType' => 'string', 'required' => false, 'description' => '', + 'readonly' => false ), 'c' => array( 'dataType' => 'boolean', 'required' => true, 'description' => '', + 'readonly' => false ), ), 'description' => 'create test', @@ -138,6 +144,7 @@ class SimpleFormatterTest extends WebTestCase 'dataType' => 'string', 'required' => true, 'description' => 'A nice description', + 'readonly' => false ), ), 'description' => 'create another test', From 11efee0f653809b95f57ac5d7d50c6bcd30eb89b Mon Sep 17 00:00:00 2001 From: Evan Villemez Date: Tue, 24 Jul 2012 16:14:11 -0400 Subject: [PATCH 5/5] tests passing --- Annotation/ApiDoc.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Annotation/ApiDoc.php b/Annotation/ApiDoc.php index 6fdb4ac..1c9c9d0 100644 --- a/Annotation/ApiDoc.php +++ b/Annotation/ApiDoc.php @@ -228,10 +228,6 @@ class ApiDoc $data['requirements'] = $requirements; } - if ($input = $this->input) { - $data['input'] = $input; - } - return $data; } }