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('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) {
}
}
}

View File

@ -229,6 +229,7 @@ class ApiDocExtractor
foreach ($this->parsers as $parser) {
if ($parser->supports($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;
* `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
<?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();
$this->assertTrue(is_array($data));
$this->assertCount(10, $data);
$this->assertCount(11, $data);
foreach ($data as $d) {
$this->assertTrue(is_array($d));

View File

@ -90,4 +90,14 @@ class TestController
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(
new \Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new \Symfony\Bundle\TwigBundle\TwigBundle(),
new \JMS\SerializerBundle\JMSSerializerBundle($this),
new \Nelmio\ApiDocBundle\NelmioApiDocBundle(),
new \Nelmio\ApiDocBundle\Tests\Fixtures\NelmioApiDocTestBundle(),
);

View File

@ -26,3 +26,33 @@ services:
- [foo, bar]
tags:
- { 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:
_method: GET
test_route_9:
pattern: /jms-input-test
defaults: { _controller: NelmioApiDocTestBundle:Test:jmsInputTest }
requirements:
_method: POST
test_service_route_1:
pattern: /tests
defaults: { _controller: nemlio.test.controller:indexAction, _format: json }
@ -63,3 +69,4 @@ test_service_route_4:
NelmioApiDocBundle:
resource: "@NelmioApiDocBundle/Resources/config/routing.yml"
prefix: /

View File

@ -135,6 +135,11 @@ _Action without HTTP verb_
### `POST` /jms-input-test ###
_Testing JMS_
### `ANY` /my-commented/{id}/{page} ###
_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',
),
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',

View File

@ -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": {