mirror of
https://github.com/retailcrm/NelmioApiDocBundle.git
synced 2025-02-02 15:51:48 +03:00
started on implementing JmsMetadataParser and tests
This commit is contained in:
parent
4b69e1149a
commit
b71bc8bf3f
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -229,6 +229,7 @@ class ApiDocExtractor
|
||||
foreach ($this->parsers as $parser) {
|
||||
if ($parser->supports($input)) {
|
||||
$parameters = $parser->parse($input);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
93
Parser/JmsMetadataParser.php
Normal file
93
Parser/JmsMetadataParser.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
|
||||
|
16
Resources/config/services.jms.xml
Normal file
16
Resources/config/services.jms.xml
Normal 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
5
TODO.md
Normal file
@ -0,0 +1,5 @@
|
||||
# TODO #
|
||||
|
||||
* Fix JMS registration by moving logic into a CompilerPass
|
||||
* Finish `JmsMetadataParser`
|
||||
* Implement new tests
|
@ -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));
|
||||
|
@ -90,4 +90,14 @@ class TestController
|
||||
public function zActionWithQueryParamAction()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @ApiDoc(
|
||||
* description="Testing JMS",
|
||||
* input="Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest"
|
||||
* )
|
||||
*/
|
||||
public function jmsInputTestAction()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
33
Tests/Fixtures/Model/JmsTest.php
Normal file
33
Tests/Fixtures/Model/JmsTest.php
Normal 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;
|
||||
|
||||
}
|
@ -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(),
|
||||
);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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: /
|
||||
|
@ -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._
|
||||
|
@ -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',
|
||||
|
@ -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": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user