From b71bc8bf3f94007559d4184357e4d4967ddca13d Mon Sep 17 00:00:00 2001 From: Evan Villemez Date: Tue, 7 Aug 2012 17:50:58 -0400 Subject: [PATCH] started on implementing JmsMetadataParser and tests --- DependencyInjection/NelmioApiDocExtension.php | 10 ++ Extractor/ApiDocExtractor.php | 1 + Parser/JmsMetadataParser.php | 93 +++++++++++++++++++ README.md | 4 +- Resources/config/services.jms.xml | 16 ++++ TODO.md | 5 + Tests/Extractor/ApiDocExtratorTest.php | 2 +- Tests/Fixtures/Controller/TestController.php | 10 ++ Tests/Fixtures/Model/JmsTest.php | 33 +++++++ Tests/Fixtures/app/AppKernel.php | 1 + Tests/Fixtures/app/config/default.yml | 30 ++++++ Tests/Fixtures/app/config/routing.yml | 7 ++ Tests/Formatter/MarkdownFormatterTest.php | 5 + Tests/Formatter/SimpleFormatterTest.php | 41 +++++++- composer.json | 2 +- 15 files changed, 255 insertions(+), 5 deletions(-) create mode 100644 Parser/JmsMetadataParser.php create mode 100644 Resources/config/services.jms.xml create mode 100644 TODO.md create mode 100644 Tests/Fixtures/Model/JmsTest.php diff --git a/DependencyInjection/NelmioApiDocExtension.php b/DependencyInjection/NelmioApiDocExtension.php index 1ecae53..5aedd86 100644 --- a/DependencyInjection/NelmioApiDocExtension.php +++ b/DependencyInjection/NelmioApiDocExtension.php @@ -36,5 +36,15 @@ class NelmioApiDocExtension extends Extension $loader->load('formatters.xml'); $loader->load('request_listener.xml'); $loader->load('services.xml'); + + //JMS may or may not be installed, if it is, load that config as well + try { + if ($serializer = $container->findDefinition('serializer')) { + die(__METHOD__); + $loader->load('services.jms.xml'); + } + } catch (\Exception $e) { + + } } } diff --git a/Extractor/ApiDocExtractor.php b/Extractor/ApiDocExtractor.php index dcc8af1..2e0dae6 100644 --- a/Extractor/ApiDocExtractor.php +++ b/Extractor/ApiDocExtractor.php @@ -229,6 +229,7 @@ class ApiDocExtractor foreach ($this->parsers as $parser) { if ($parser->supports($input)) { $parameters = $parser->parse($input); + break; } } diff --git a/Parser/JmsMetadataParser.php b/Parser/JmsMetadataParser.php new file mode 100644 index 0000000..8978de2 --- /dev/null +++ b/Parser/JmsMetadataParser.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Nelmio\ApiDocBundle\Parser; + +use Metadata\MetadataFactoryInterface; + +/** + * Uses the JMS metadata factory to extract input/output model information + */ +class JmsMetadataParser implements ParserInterface +{ + + /** + * Constructor, requires JMS Metadata factory + */ + public function __construct(MetadataFactoryInterface $factory) + { + $this->factory = $factory; + } + + /** + * {@inheritdoc} + */ + public function supports($input) + { + if($meta = $this->factory->getMetadataForClass($input)) { + return true; + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function parse($input) + { + die(__METHOD__); + + $meta = $this->factory->getMetadataForClass($input); + + if(is_null($meta)) { + throw new \InvalidArgumentException(sprintf("No metadata found for class %s", $input)); + } + + $params = array(); + $refClass = new \ReflectionClass($input); + + //iterate over property metadata + foreach ($meta->propertyMetadata as $item) { + $name = isset($item->serializedName) ? $item->serializedName : $item->name; + + $type = $this->getType($item->type); + + if (true) { + //TODO: check for nested type + } + + $params[$name] = array( + 'dataType' => $item->type, + 'required' => false, //can't think of a good way to specify this one, JMS doesn't have a setting for this + 'description' => $this->getDescription($refClass, $item->name), + 'readonly' => $item->readonly + ); + } + + return $params; + } + + protected function getDescription($ref, $nativePropertyName) + { + $description = "No description."; + + if (!$doc = $ref->getProperty($nativePropertyName)->getDocComment()) { + return $description; + } + + //TODO: regex comment to get description - or move doc comment parsing functionality from `ApiDocExtractor` to a new location + //in order to reuse it here + + return $description; + } + +} diff --git a/README.md b/README.md index ae19234..d011f4b 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ The following properties are available: * `filters`: an array of filters; -* `input`: the input type associated to the method, currently this only supports Form Types, useful for POST|PUT methods, either as FQCN or +* `input`: the input type associated to the method, currently this 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) Each _filter_ has to define a `name` parameter, but other parameters are free. Filters are often optional @@ -110,6 +110,8 @@ and determines for each parameter its data type, and if it's required or not. For Form Types, you can add an extra option named `description` on each field: +For classes parsed with JMS metadata, description will be taken from the properties doc comment, if available. + ``` php + + + + Nelmio\ApiDocBundle\Parser\JmsMetadataParser + + + + + + diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..f4d3408 --- /dev/null +++ b/TODO.md @@ -0,0 +1,5 @@ +# TODO # + +* Fix JMS registration by moving logic into a CompilerPass +* Finish `JmsMetadataParser` +* Implement new tests \ No newline at end of file diff --git a/Tests/Extractor/ApiDocExtratorTest.php b/Tests/Extractor/ApiDocExtratorTest.php index b092643..a15de3a 100644 --- a/Tests/Extractor/ApiDocExtratorTest.php +++ b/Tests/Extractor/ApiDocExtratorTest.php @@ -22,7 +22,7 @@ class ApiDocExtractorTest extends WebTestCase $data = $extractor->all(); $this->assertTrue(is_array($data)); - $this->assertCount(10, $data); + $this->assertCount(11, $data); foreach ($data as $d) { $this->assertTrue(is_array($d)); diff --git a/Tests/Fixtures/Controller/TestController.php b/Tests/Fixtures/Controller/TestController.php index d39a02a..e01189d 100644 --- a/Tests/Fixtures/Controller/TestController.php +++ b/Tests/Fixtures/Controller/TestController.php @@ -90,4 +90,14 @@ class TestController public function zActionWithQueryParamAction() { } + + /** + * @ApiDoc( + * description="Testing JMS", + * input="Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest" + * ) + */ + public function jmsInputTestAction() + { + } } diff --git a/Tests/Fixtures/Model/JmsTest.php b/Tests/Fixtures/Model/JmsTest.php new file mode 100644 index 0000000..343d936 --- /dev/null +++ b/Tests/Fixtures/Model/JmsTest.php @@ -0,0 +1,33 @@ + 'Action without HTTP verb', ), 3 => + array( + 'method' => 'POST', + 'uri' => '/jms-input-test', + 'parameters' => + array( + 'foo' => + array( + 'dataType' => 'string', + 'required' => false, + 'description' => 'No description.', + 'readonly' => false + ), + 'bar' => + array( + 'dataType' => 'DateTime', + 'required' => false, + 'description' => 'No description.', + 'readonly' => true + ), + 'number' => + array( + 'dataType' => 'double', + 'required' => false, + 'description' => 'No description.', + 'readonly' => false + ), + 'arr' => + array( + 'dataType' => 'array', + 'required' => false, + 'description' => 'No description.', + 'readonly' => false + ) + ), + 'description' => 'Testing JMS' + ), + 4 => array( 'method' => 'ANY', 'uri' => '/my-commented/{id}/{page}', @@ -177,7 +214,7 @@ class SimpleFormatterTest extends WebTestCase 'description' => 'This method is useful to test if the getDocComment works.', 'documentation' => "This method is useful to test if the getDocComment works.\nAnd, it supports multilines until the first '@' char." ), - 4 => + 5 => array( 'method' => 'ANY', 'uri' => '/yet-another/{id}', @@ -186,7 +223,7 @@ class SimpleFormatterTest extends WebTestCase 'id' => array('type' => '', 'description' => '', 'requirement' => '\d+') ), ), - 5 => + 6 => array( 'method' => 'GET', 'uri' => '/z-action-with-query-param', diff --git a/composer.json b/composer.json index 2f8d743..80ed4d6 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "symfony/browser-kit": "2.1.*", "symfony/validator": "2.1.*", "symfony/yaml": "2.1.*", - "friendsofsymfony/rest-bundle": "dev-master" + "jms/serializer-bundle": "0.9.*" }, "minimum-stability": "dev", "autoload": {