started on implementing JmsMetadataParser and tests

This commit is contained in:
Evan Villemez 2012-08-07 17:50:58 -04:00
parent 4b69e1149a
commit b71bc8bf3f
15 changed files with 255 additions and 5 deletions

View File

@ -36,5 +36,15 @@ class NelmioApiDocExtension extends Extension
$loader->load('formatters.xml'); $loader->load('formatters.xml');
$loader->load('request_listener.xml'); $loader->load('request_listener.xml');
$loader->load('services.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) {
}
} }
} }

View File

@ -229,6 +229,7 @@ class ApiDocExtractor
foreach ($this->parsers as $parser) { foreach ($this->parsers as $parser) {
if ($parser->supports($input)) { if ($parser->supports($input)) {
$parameters = $parser->parse($input); $parameters = $parser->parse($input);
break;
} }
} }

View File

@ -0,0 +1,93 @@
<?php
/*
* This file is part of the NelmioApiDocBundle.
*
* (c) Nelmio <hello@nelm.io>
*
* 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;
}
}

View File

@ -99,7 +99,7 @@ The following properties are available:
* `filters`: an array of filters; * `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) 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 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 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 ``` php
<?php <?php

View File

@ -0,0 +1,16 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="nelmio_api_doc.parser.jms_metadata_parser.class">Nelmio\ApiDocBundle\Parser\JmsMetadataParser</parameter>
</parameters>
<services>
<service id="nelmio_api_doc.parser.jms_metadata_parser" class="%nelmio_api_doc.parser.jms_metadata_parser.class%">
<argument type="service" id="jms_serializer.metadata_factory" />
<tag name="nelmio_api_doc.extractor.parser" />
</service>
</services>
</container>

5
TODO.md Normal file
View File

@ -0,0 +1,5 @@
# TODO #
* Fix JMS registration by moving logic into a CompilerPass
* Finish `JmsMetadataParser`
* Implement new tests

View File

@ -22,7 +22,7 @@ class ApiDocExtractorTest extends WebTestCase
$data = $extractor->all(); $data = $extractor->all();
$this->assertTrue(is_array($data)); $this->assertTrue(is_array($data));
$this->assertCount(10, $data); $this->assertCount(11, $data);
foreach ($data as $d) { foreach ($data as $d) {
$this->assertTrue(is_array($d)); $this->assertTrue(is_array($d));

View File

@ -90,4 +90,14 @@ class TestController
public function zActionWithQueryParamAction() public function zActionWithQueryParamAction()
{ {
} }
/**
* @ApiDoc(
* description="Testing JMS",
* input="Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest"
* )
*/
public function jmsInputTestAction()
{
}
} }

View File

@ -0,0 +1,33 @@
<?php
namespace Nelmio\ApiDocBundle\Tests\Fixtures\Model;
use JMS\SerializerBundle\Annotation as JMS;
class JmsTest
{
public $nothing;
/**
* @JMS\Type("string");
*/
public $foo;
/**
* @JMS\Type("DateTime");
* @JMS\ReadOnly
*/
public $bar;
/**
* @JMS\Type("double");
* @JMS\SerializedName("number");
*/
public $baz;
/**
* @JMS\Type("array");
*/
public $arr;
}

View File

@ -48,6 +48,7 @@ class AppKernel extends Kernel
return array( return array(
new \Symfony\Bundle\FrameworkBundle\FrameworkBundle(), new \Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new \Symfony\Bundle\TwigBundle\TwigBundle(), new \Symfony\Bundle\TwigBundle\TwigBundle(),
new \JMS\SerializerBundle\JMSSerializerBundle($this),
new \Nelmio\ApiDocBundle\NelmioApiDocBundle(), new \Nelmio\ApiDocBundle\NelmioApiDocBundle(),
new \Nelmio\ApiDocBundle\Tests\Fixtures\NelmioApiDocTestBundle(), new \Nelmio\ApiDocBundle\Tests\Fixtures\NelmioApiDocTestBundle(),
); );

View File

@ -26,3 +26,33 @@ services:
- [foo, bar] - [foo, bar]
tags: tags:
- { name: form.type, alias: dependency_type } - { name: form.type, alias: dependency_type }
#JMS Serializer config for testing JmsMetadataParser
jms_serializer:
handlers:
object_based: false
datetime:
format: "Y-m-dTH:i:s" # ISO8601
default_timezone: "UTC" # defaults to whatever timezone set in php.ini or via date_default_timezone_set
array_collection: true
form_error: true
constraint_violation: true
property_naming:
separator: _
lower_case: true
metadata:
cache: file
debug: "%kernel.debug%"
file_cache:
dir: "%kernel.cache_dir%/serializer"
# Using auto-detection, the mapping files for each bundle will be
# expected in the Resources/config/serializer directory.
#
# Example:
# class: My\FooBundle\Entity\User
# expected path: @MyFooBundle/Resources/config/serializer/Entity.User.(yml|xml|php)
auto_detection: true

View File

@ -40,6 +40,12 @@ test_route_8:
requirements: requirements:
_method: GET _method: GET
test_route_9:
pattern: /jms-input-test
defaults: { _controller: NelmioApiDocTestBundle:Test:jmsInputTest }
requirements:
_method: POST
test_service_route_1: test_service_route_1:
pattern: /tests pattern: /tests
defaults: { _controller: nemlio.test.controller:indexAction, _format: json } defaults: { _controller: nemlio.test.controller:indexAction, _format: json }
@ -63,3 +69,4 @@ test_service_route_4:
NelmioApiDocBundle: NelmioApiDocBundle:
resource: "@NelmioApiDocBundle/Resources/config/routing.yml" resource: "@NelmioApiDocBundle/Resources/config/routing.yml"
prefix: / prefix: /

View File

@ -135,6 +135,11 @@ _Action without HTTP verb_
### `POST` /jms-input-test ###
_Testing JMS_
### `ANY` /my-commented/{id}/{page} ### ### `ANY` /my-commented/{id}/{page} ###
_This method is useful to test if the getDocComment works._ _This method is useful to test if the getDocComment works._

View File

@ -166,6 +166,43 @@ class SimpleFormatterTest extends WebTestCase
'description' => 'Action without HTTP verb', 'description' => 'Action without HTTP verb',
), ),
3 => 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( array(
'method' => 'ANY', 'method' => 'ANY',
'uri' => '/my-commented/{id}/{page}', 'uri' => '/my-commented/{id}/{page}',
@ -177,7 +214,7 @@ class SimpleFormatterTest extends WebTestCase
'description' => 'This method is useful to test if the getDocComment works.', '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." 'documentation' => "This method is useful to test if the getDocComment works.\nAnd, it supports multilines until the first '@' char."
), ),
4 => 5 =>
array( array(
'method' => 'ANY', 'method' => 'ANY',
'uri' => '/yet-another/{id}', 'uri' => '/yet-another/{id}',
@ -186,7 +223,7 @@ class SimpleFormatterTest extends WebTestCase
'id' => array('type' => '', 'description' => '', 'requirement' => '\d+') 'id' => array('type' => '', 'description' => '', 'requirement' => '\d+')
), ),
), ),
5 => 6 =>
array( array(
'method' => 'GET', 'method' => 'GET',
'uri' => '/z-action-with-query-param', 'uri' => '/z-action-with-query-param',

View File

@ -25,7 +25,7 @@
"symfony/browser-kit": "2.1.*", "symfony/browser-kit": "2.1.*",
"symfony/validator": "2.1.*", "symfony/validator": "2.1.*",
"symfony/yaml": "2.1.*", "symfony/yaml": "2.1.*",
"friendsofsymfony/rest-bundle": "dev-master" "jms/serializer-bundle": "0.9.*"
}, },
"minimum-stability": "dev", "minimum-stability": "dev",
"autoload": { "autoload": {