Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

added support for JMS Serializer GroupsExclusionStrategy #156

Merged
merged 2 commits into from

9 participants

Jeroen Fiege William Durand Jordi Boggiano Peter Kruithof Pierre-Yves Lebecq Christophe Coevoet MaksSlesarenko Benjamin Laugueux remyLemeunier
Jeroen Fiege

A proposal to support the GroupsExclusionStrategy of the JMS Serializer.

From the updated readme in this PR:

When using a class with JMS Serializer metadata, you can use exclude groups by using this syntax: input="Acme\YourBundle\Entity\User@update,public". In this case the groups 'update' and 'public' are used.

William Durand
Collaborator

looks good to me

Jordi Boggiano
Owner

To me too, except that the annotation syntax is a bit strange and not very future proof. I don't have a better idea though.

README.md
@@ -101,7 +101,9 @@ The following properties are available:
* `filters`: an array of filters;
* `input`: the input type associated to the method, currently this supports 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)
+ metadata, useful for POST|PUT methods, either as FQCN or as form type (if it is registered in the form factory in the container).
+ When using a class with JMS Serializer metadata, you can use exclude groups by using this syntax:

The term "exclude" implicates that these groups are not used. I understand the relation to the ExclusionStrategy from the Serializer, but I think that term is ambiguous also. It would be more clear if it said: "you can use specific groups by using this syntax".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Peter Kruithof

@Seldaek an alternative would be to use an additional annotation, something like inputgroup=blah. But I think it makes more sense to suffix the input line.

Maybe a # or :: would make more sense as a separator? I don't know what the most commonly used notation for class/property definitions is, but it seems to me that would be useful here too.

Jeroen Fiege

The notation is indeed arguable. Another suggestion might be:

input={
    "class"="Acme\Bundle\Entity\User", 
    "groups"="update, public"
}

This makes it also extendable in the future.

Peter Kruithof

:+1: for that notation

Parser/JmsMetadataParser.php
@@ -80,6 +86,9 @@ protected function doParse($className, $visited = array())
throw new \InvalidArgumentException(sprintf("No metadata found for class %s", $className));
}
+ $context = new NavigatorContext(GraphNavigator::DIRECTION_SERIALIZATION, 'json'); //TODO: the exclusionStrategy has a hard dependency on this, despite it isn't even used :(
+ $exclusionStrategy = new GroupsExclusionStrategy($groups);
Christophe Coevoet
stof added a note

What about the VersionExclusionStrategy ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Pierre-Yves Lebecq

This would be a great feature. And as @stof said, VersionExclusionStrategy would be really nice too.
For the annotation, another proposal, which is a little tweak of @fieg last proposal :

// Supporting the old syntax
input="Acme\Bundle\Entity\User"
// Which would be equals to
input={
    "class"="Acme\Bundle\Entity\User",
    "groups"={"Default"}
}
// And of course could be customized by typing
input={
    "class"="Acme\Bundle\Entity\User",
    "groups"={"Update", "Public"}
}

The only difference here would be to declare groups as an array instead of a string with separators. What dou you think ?

Jeroen Fiege

Good suggestions @stof and @pylebecq. Will look into it.

Jeroen Fiege

Ok, I tackled the input/output notation.

Does anyone want to help with the VersionExclusionStrategy support? Let me know so I can add you as a contributor to the feature branch. I'm running a little short on time here...

Parser/JmsMetadataParser.php
@@ -80,6 +87,9 @@ protected function doParse($className, $visited = array())
throw new \InvalidArgumentException(sprintf("No metadata found for class %s", $className));
}
+ $context = new NavigatorContext(GraphNavigator::DIRECTION_SERIALIZATION, 'json'); //TODO: the exclusionStrategy has a hard dependency on this, despite it isn't even used :(

NavigatorContext won't exist anymore in Serializer 0.12.
It was renamed to Context in schmittjoh/serializer@ffb2d5d and split into two classes in schmittjoh/serializer@0207222

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Pierre-Yves Lebecq

@fieg If I have time this weekend, I will try to do something about the version exclusion strategy.

Pierre-Yves Lebecq

Ok, finally I took some time tonight to add the support of the VersionExclusionStrategy. It will show up here as soon as @fieg merges the PR.

My last concern is related to my previous comment about the removal of NavigationContext in Serializer 0.12.
I don't know how to handle this. Should we update the composer.json file to forbid usage of Serializer >= 0.12 or should we update the code to use the new classes of Serializer 0.12 and make this bundle only compatible with Serializer 0.12 ? Or anything else ?

Christophe Coevoet

As 0.12 is stable as of yesterday, forbidding it is not an option IMO

MaksSlesarenko

Is this relative to FosRestBundle SerializerGroups option #119 ?

Jeroen Fiege

Does anyone have some thoughts about how to proceed with this PR?

Jeroen Fiege

Hi, I rebased, fixed the unit tests and refactored the NavigatorContext to support the new Serializer version. Hopefully this can get merged now.

Extractor/ApiDocExtractor.php
((12 lines not shown))
+ // normalize strings
+ if (is_string($input)) {
+ $input = array('class' => $input);
+ }
+
+ // normalize groups
+ if (isset($input['groups']) && is_string($input['groups'])) {
+ $input['groups'] = array_map('trim', explode(',', $input['groups']));
+ }
+
+ // normalize version
+ if (!array_key_exists('version', $input)) {
+ $input['version'] = null;
+ }
+
+ return $input += $defaults;
Jordi Boggiano Owner
Seldaek added a note

The = is kinda superfluous here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Extractor/ApiDocExtractor.php
((10 lines not shown))
+ );
+
+ // normalize strings
+ if (is_string($input)) {
+ $input = array('class' => $input);
+ }
+
+ // normalize groups
+ if (isset($input['groups']) && is_string($input['groups'])) {
+ $input['groups'] = array_map('trim', explode(',', $input['groups']));
+ }
+
+ // normalize version
+ if (!array_key_exists('version', $input)) {
+ $input['version'] = null;
+ }
Jordi Boggiano Owner
Seldaek added a note

This block seems useless, if the key is not defined, then it'll be added from the defaults already as far as I can see.

Pierre-Yves Lebecq
pylebecq added a note

Yep, you're right. Sorry, my mistake.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Jordi Boggiano
Owner

@fieg the README change is out of date I think, and I have one more question: it now only supports the latest Serializer version right? Is it possible to support older ones too without too much hassle? It'd be great, but if not that's fine, but then please change the composer.json to reflect this (I think the conflict should be conflicting with <0.12 now?).

Besides this stuff and the other couple comments I wrote, I think it's good to merge.

Jeroen Fiege

Good comments, I will try to look into it later today.

William Durand
Collaborator

ping @fieg

Pierre-Yves Lebecq

I'm not completely satisfied by the implementation of the version exclusion strategy, because every time you introduce a new version you have to update all your ApiDoc annotations. Also, by doing this, there is no possibility to get the documentation for a specific version.
Don't you think a new column like the "required" column would be more appropriate ? Instead of excluding the property, we could show the version that applies to the properties. For example : >=1.0,<2.0

Jeroen Fiege

Thanks for the ping @willdurand.

I updated according to your comments @Seldaek and did a rebase.

Jeroen Fiege

Hmm, some whitespace got messed up. Will fix.

Jeroen Fiege

@Seldaek do you see change to review and merge this?

Jordi Boggiano
Owner

I'd rather have @willdurand review/merge it because it's quite involved and I don't know this code in depth.

That said, I think @pylebecq had a point.. This should be carefully considered.

Jeroen Fiege

My suggestion is that we merge this PR as is and then @pylebecq (and others) could improve the Version-part of this feature in some other PR? It would be a shame if this would stall the GroupExclusion feature unnecessarily.

Pierre-Yves Lebecq

I agree with @fieg, let's not block the group exclusion strategy feature but before merging I think we should remove the work on the version exclusion strategy because the feature seems wrong to me and don't deserve to land in the code base the way it is implemented for now.

Jeroen Fiege

@pylebecq reworked the version support :+1: . @willdurand could you please review it?

Extractor/ApiDocExtractor.php
@@ -266,9 +266,11 @@ protected function extractData(ApiDoc $annotation, Route $route, \ReflectionMeth
if (null !== $input = $annotation->getInput()) {
$parameters = array();
+ $normalizedInput = $this->normalizeInputOutputParameter($input);
William Durand Collaborator

normalizeParameters()?

Jeroen Fiege
fieg added a note

I think normalizeParameters would be to generic; it only normalizes the type of parameter that is used with the input and output option. How about normalizeClassParameter as the type of parameter is best described as a class?

William Durand Collaborator

I think normalizeParameters() is fine. Do we have other parameters?

Jeroen Fiege
fieg added a note

Yes, description for example. Also the method only normalizes a single parameter.

William Durand Collaborator

ok for normalizeClassParameter then

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Extractor/ApiDocExtractor.php
((6 lines not shown))
+ $defaults = array(
+ 'class' => '',
+ 'groups' => array(),
+ );
+
+ // normalize strings
+ if (is_string($input)) {
+ $input = array('class' => $input);
+ }
+
+ // normalize groups
+ if (isset($input['groups']) && is_string($input['groups'])) {
+ $input['groups'] = array_map('trim', explode(',', $input['groups']));
+ }
+
+ return $input + $defaults;
William Durand Collaborator

please, don't do that

Jeroen Fiege
fieg added a note

Can you be more specific?

William Durand Collaborator

don't merge arrays using the + sign.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Benjamin Laugueux

ping @fieg please :)

William Durand
Collaborator

ping @fieg

Formatter/AbstractFormatter.php
@@ -113,7 +113,13 @@ protected function processAnnotation($annotation)
}
if (isset($annotation['response'])) {
- $annotation['response'] = $this->compressNestedParameters($annotation['response']);
+ $response = $this->compressNestedParameters($annotation['response']);
+ foreach ($response as $name => &$info) {
+ $info['sinceVersion'] = array_key_exists('sinceVersion', $annotation['response'][$name]) ? $annotation['response'][$name]['sinceVersion'] : null;
Jeroen Fiege
fieg added a note

@pylebecq I'm running into an issue here with nested parameters:

Notice: Undefined index: credit[amount] in vendor/nelmio/api-doc-bundle/Nelmio/ApiDocBundle/Formatter/AbstractFormatter.php line 118
Pierre-Yves Lebecq
pylebecq added a note

I'll fix it tonight and send you a PR as usual. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Benjamin Laugueux

@fieg can you rebase and squash your commits to have a better readability of your PR please

Jeroen Fiege

I rebased (and resolve some conflicts), but now run into some failing tests which I'm not certain how to fix. @pylebecq I think you might have a better insight in how to fix these tests. You can check the result of the rebase here: https://github.com/fieg/NelmioApiDocBundle/commits/jms-groups-support-rebased

@blaugueux I've never squashed commits before, should all commits be squashed in a single commit? How would this improve the readability?

Benjamin Laugueux

@fieg This will group your 16 commits into 1. It will be more easy to rebase for you and better for us to read :) Here is a small tuto: http://ariejan.net/2011/07/05/git-squash-your-latests-commits-into-one/

Jeroen Fiege

@blaugueux Would author information for the commits of @pylebecq be maintained?

@willdurand what do you think about this squashing of commits?

Pierre-Yves Lebecq

@fieg I fixed the tests, this was no big deal, probably a mistake when resolving conflics.

I pushed in your rebased branch : https://github.com/fieg/NelmioApiDocBundle/commits/jms-groups-support-rebased .
I also squashed our commits resulting in two commits : the first commit is yours and is about the implementation of the group exclusion strategy. The other commit is mine and is about the version support. I pushed the squashed commits in an other branch : https://github.com/fieg/NelmioApiDocBundle/commits/jms-groups-support-rebased-squashed .

The only difference between the two branches is two use statements not used anymore I removed in the squashed branch :

audrey:ApiDocBundle pierreyves$ git diff origin/jms-groups-support-rebased..origin/jms-groups-support-rebased-squashed
diff --git a/Parser/JmsMetadataParser.php b/Parser/JmsMetadataParser.php
index add1e3d..2edc28e 100644
--- a/Parser/JmsMetadataParser.php
+++ b/Parser/JmsMetadataParser.php
@@ -12,8 +12,6 @@
 namespace Nelmio\ApiDocBundle\Parser;

 use JMS\Serializer\Exclusion\GroupsExclusionStrategy;
-use JMS\Serializer\GraphNavigator;
-use JMS\Serializer\NavigatorContext;
 use JMS\Serializer\SerializationContext;
 use Metadata\MetadataFactoryInterface;
 use Nelmio\ApiDocBundle\Util\DocCommentExtractor;

I did my best to squash like @blaugueux asked and to keep the author information for the both of us. You can view the two commits to see if the split seems fair (it should) and if everything is ok for everyone the last thing to do will be to push the jms-groups-support-rebased-squashed on jms-groups-support (you will need to use --force).

Don't hesitate to contact me via private messages if you have any question.

William Durand
Collaborator

Ok so, can we have a clean PR now? A rebase is still needed, I don't really care about the squashing commits.
You should update the doc though.

Jeroen Fiege

@pylebecq you're the best :) I pushed jms-groups-support-rebased-squashed onto jms-group-support.

I believe @willdurand is pointing at the documentation about the version feature of this PR. @pylebecq if you could only fix this last thing, then we are all set and this can get merged.

William Durand
Collaborator

This needs to be rebased btw

Pierre-Yves Lebecq

I updated the docs and rebased / fixed tests / squashed / killed some kittens again. :)

William Durand willdurand merged commit ce1b40e into from
William Durand
Collaborator

thanks!

Benjamin Laugueux

@willdurand @Seldaek can you create a tag with this new feature?

Jeroen Fiege fieg deleted the branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
32 Extractor/ApiDocExtractor.php
View
@@ -266,9 +266,11 @@ protected function extractData(ApiDoc $annotation, Route $route, \ReflectionMeth
if (null !== $input = $annotation->getInput()) {
$parameters = array();
+ $normalizedInput = $this->normalizeClassParameter($input);
+
foreach ($this->parsers as $parser) {
- if ($parser->supports($input)) {
- $parameters = $parser->parse($input);
+ if ($parser->supports($normalizedInput)) {
+ $parameters = $parser->parse($normalizedInput);
break;
}
}
@@ -287,9 +289,11 @@ protected function extractData(ApiDoc $annotation, Route $route, \ReflectionMeth
if (null !== $output = $annotation->getOutput()) {
$response = array();
+ $normalizedOutput = $this->normalizeClassParameter($output);
+
foreach ($this->parsers as $parser) {
- if ($parser->supports($output)) {
- $response = $parser->parse($output);
+ if ($parser->supports($normalizedOutput)) {
+ $response = $parser->parse($normalizedOutput);
break;
}
}
@@ -350,6 +354,26 @@ protected function extractData(ApiDoc $annotation, Route $route, \ReflectionMeth
return $annotation;
}
+ protected function normalizeClassParameter($input)
+ {
+ $defaults = array(
+ 'class' => '',
+ 'groups' => array(),
+ );
+
+ // normalize strings
+ if (is_string($input)) {
+ $input = array('class' => $input);
+ }
+
+ // normalize groups
+ if (isset($input['groups']) && is_string($input['groups'])) {
+ $input['groups'] = array_map('trim', explode(',', $input['groups']));
+ }
+
+ return array_merge($defaults, $input);
+ }
+
/**
* Parses annotations for a given method, and adds new information to the given ApiDoc
* annotation. Useful to extract information from the FOSRestBundle annotations.
2  Formatter/AbstractFormatter.php
View
@@ -73,6 +73,8 @@ protected function compressNestedParameters(array $data, $parentName = null, $ig
'dataType' => $info['dataType'],
'readonly' => $info['readonly'],
'required' => $info['required'],
+ 'sinceVersion' => array_key_exists('sinceVersion', $info) ? $info['sinceVersion'] : null,
+ 'untilVersion' => array_key_exists('untilVersion', $info) ? $info['untilVersion'] : null,
);
if (isset($info['children']) && (!$info['readonly'] || !$ignoreNestedReadOnly)) {
14 Formatter/MarkdownFormatter.php
View
@@ -103,6 +103,20 @@ protected function renderOne(array $data)
$markdown .= sprintf(" * description: %s\n", $parameter['description']);
}
+ if (null !== $parameter['sinceVersion'] || null !== $parameter['untilVersion']) {
+ $markdown .= " * versions: ";
+ if ($parameter['sinceVersion']) {
+ $markdown .= '>='.$parameter['sinceVersion'];
+ }
+ if ($parameter['untilVersion']) {
+ if ($parameter['sinceVersion']) {
+ $markdown .= ',';
+ }
+ $markdown .= '<='.$parameter['untilVersion'];
+ }
+ $markdown .= "\n";
+ }
+
$markdown .= "\n";
}
}
10 Parser/FormTypeParser.php
View
@@ -47,10 +47,12 @@ public function __construct(FormFactoryInterface $formFactory, FormRegistry $for
/**
* {@inheritdoc}
*/
- public function supports($item)
+ public function supports(array $item)
{
+ $className = $item['class'];
+
try {
- if ($this->createForm($item)) {
+ if ($this->createForm($className)) {
return true;
}
} catch (FormException $e) {
@@ -65,8 +67,10 @@ public function supports($item)
/**
* {@inheritdoc}
*/
- public function parse($type)
+ public function parse(array $item)
{
+ $type = $item['class'];
+
if ($this->implementsType($type)) {
$type = $this->getTypeInstance($type);
}
45 Parser/JmsMetadataParser.php
View
@@ -11,6 +11,8 @@
namespace Nelmio\ApiDocBundle\Parser;
+use JMS\Serializer\Exclusion\GroupsExclusionStrategy;
+use JMS\Serializer\SerializationContext;
use Metadata\MetadataFactoryInterface;
use Nelmio\ApiDocBundle\Util\DocCommentExtractor;
use JMS\Serializer\Metadata\PropertyMetadata;
@@ -22,7 +24,6 @@
*/
class JmsMetadataParser implements ParserInterface
{
-
/**
* @var \Metadata\MetadataFactoryInterface
*/
@@ -54,10 +55,12 @@ public function __construct(
/**
* {@inheritdoc}
*/
- public function supports($input)
+ public function supports(array $input)
{
+ $className = $input['class'];
+
try {
- if ($meta = $this->factory->getMetadataForClass($input)) {
+ if ($meta = $this->factory->getMetadataForClass($className)) {
return true;
}
} catch (\ReflectionException $e) {
@@ -69,9 +72,12 @@ public function supports($input)
/**
* {@inheritdoc}
*/
- public function parse($input)
+ public function parse(array $input)
{
- return $this->doParse($input);
+ $className = $input['class'];
+ $groups = $input['groups'];
+
+ return $this->doParse($className, array(), $groups);
}
/**
@@ -79,10 +85,11 @@ public function parse($input)
*
* @param string $className Class to get all metadata for
* @param array $visited Classes we've already visited to prevent infinite recursion.
+ * @param array $groups Serialization groups to include.
* @return array metadata for given class
* @throws \InvalidArgumentException
*/
- protected function doParse($className, $visited = array())
+ protected function doParse($className, $visited = array(), array $groups = array())
{
$meta = $this->factory->getMetadataForClass($className);
@@ -90,6 +97,9 @@ protected function doParse($className, $visited = array())
throw new \InvalidArgumentException(sprintf("No metadata found for class %s", $className));
}
+ $exclusionStrategies = array();
+ $exclusionStrategies[] = new GroupsExclusionStrategy($groups);
+
$params = array();
// iterate over property metadata
@@ -99,11 +109,21 @@ protected function doParse($className, $visited = array())
$dataType = $this->processDataType($item);
+ // apply exclusion strategies
+ foreach ($exclusionStrategies as $strategy) {
+ if (true === $strategy->shouldSkipProperty($item, SerializationContext::create())) {
+ continue 2;
+ }
+ }
+
$params[$name] = array(
- 'dataType' => $dataType['normalized'],
- 'required' => false, //TODO: can't think of a good way to specify this one, JMS doesn't have a setting for this
- 'description' => $this->getDescription($className, $item),
- 'readonly' => $item->readOnly
+ 'dataType' => $dataType['normalized'],
+ 'required' => false,
+ //TODO: can't think of a good way to specify this one, JMS doesn't have a setting for this
+ 'description' => $this->getDescription($className, $item),
+ 'readonly' => $item->readOnly,
+ 'sinceVersion' => $item->sinceVersion,
+ 'untilVersion' => $item->untilVersion,
);
// if class already parsed, continue, to avoid infinite recursion
@@ -113,8 +133,8 @@ protected function doParse($className, $visited = array())
// check for nested classes with JMS metadata
if ($dataType['class'] && null !== $this->factory->getMetadataForClass($dataType['class'])) {
- $visited[] = $dataType['class'];
- $params[$name]['children'] = $this->doParse($dataType['class'], $visited);
+ $visited[] = $dataType['class'];
+ $params[$name]['children'] = $this->doParse($dataType['class'], $visited, $groups);
}
}
}
@@ -206,5 +226,4 @@ protected function getDescription($className, PropertyMetadata $item)
return $extracted;
}
-
}
7 Parser/ParserInterface.php
View
@@ -19,10 +19,10 @@
/**
* Return true/false whether this class supports parsing the given class.
*
- * @param string $item The string type of input to parse.
+ * @param array $item containing the following fields: class, groups. Of which groups is optional
* @return boolean
*/
- public function supports($item);
+ public function supports(array $item);
/**
* Returns an array of class property metadata where each item is a key (the property name) and
@@ -37,6 +37,5 @@ public function supports($item);
* @param string $item The string type of input to parse.
* @return array
*/
- public function parse($item);
-
+ public function parse(array $item);
}
27 README.md
View
@@ -105,7 +105,7 @@ The following properties are available:
* `filters`: an array of filters;
* `input`: the input type associated to the method, currently this supports 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)
+ metadata, useful for POST|PUT methods, either as FQCN or as form type (if it is registered in the form factory in the container).
* `output`: the output type associated with the response. Specified and parsed the same way as `input`.
@@ -183,6 +183,31 @@ Also bundle will get information from the other annotations:
Route functions marked as @deprecated will be set method as deprecation in documentation.
+#### JMS Serializer features ####
+
+The bundle has support for some of the JMS Serializer features and use these extra information in the generated documentation.
+
+##### Group Exclusion Strategy #####
+
+If your classes use [JMS Group Exclusion Strategy](http://jmsyst.com/libs/serializer/master/cookbook/exclusion_strategies#creating-different-views-of-your-objects),
+you can specify which groups to use when generating the documentation by using this syntax :
+
+ ```
+ input={
+ "class"="Acme\Bundle\Entity\User",
+ "groups"={"update", "public"}
+ }
+ ```
+
+ In this case the groups 'update' and 'public' are used.
+
+ This feature also works for the `output` property.
+
+##### Versioning Objects #####
+
+If your `output` classes use [versioning capabilities of JMS Serializer](http://jmsyst.com/libs/serializer/master/cookbook/exclusion_strategies#versioning-objects),
+the versioning information will be automatically used when generating the documentation.
+
### Documentation on-the-fly ###
By calling an URL with the parameter `?_doc=1`, you will get the corresponding documentation if available.
8 Resources/views/Components/version.html.twig
View
@@ -0,0 +1,8 @@
+{% if sinceVersion is empty and untilVersion is empty %}
+*
+{% else %}
+ {% if sinceVersion is not empty %}&gt;={{ sinceVersion }}{% endif %}
+ {% if untilVersion is not empty %}
+ {% if sinceVersion is not empty %},{% endif %}&lt;={{ untilVersion }}
+ {% endif %}
+{% endif %}
2  Resources/views/method.html.twig
View
@@ -134,6 +134,7 @@
<tr>
<th>Parameter</th>
<th>Type</th>
+ <th>Versions</th>
<th>Description</th>
</tr>
</thead>
@@ -142,6 +143,7 @@
<tr>
<td>{{ name }}</td>
<td>{{ infos.dataType }}</td>
+ <td>{% include 'NelmioApiDocBundle:Components:version.html.twig' with {'sinceVersion': infos.sinceVersion, 'untilVersion': infos.untilVersion} only %}</td>
<td>{{ infos.description }}</td>
</tr>
{% endfor %}
6 Tests/Extractor/ApiDocExtractorTest.php
View
@@ -15,7 +15,7 @@
class ApiDocExtractorTest extends WebTestCase
{
- const ROUTES_QUANTITY = 19;
+ const ROUTES_QUANTITY = 20;
public function testAll()
{
@@ -66,7 +66,7 @@ public function testAll()
$this->assertFalse(isset($array2['filters']));
$this->assertEquals('Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType', $a2->getInput());
- $a3 = $data['12']['annotation'];
+ $a3 = $data['13']['annotation'];
$this->assertTrue($a3->getHttps());
}
@@ -155,7 +155,7 @@ public function testGetWithDocComment()
"This method is useful to test if the getDocComment works.",
$annotation->getDescription()
);
-
+
$data = $annotation->toArray();
$this->assertEquals(
4,
11 Tests/Fixtures/Controller/TestController.php
View
@@ -172,7 +172,7 @@ public function authenticatedAction()
public function cachedAction()
{
}
-
+
/**
* @ApiDoc()
* @deprecated
@@ -180,4 +180,13 @@ public function cachedAction()
public function deprecatedAction()
{
}
+
+ /**
+ * @ApiDoc(
+ * output="Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest"
+ * )
+ */
+ public function jmsReturnNestedOutputAction()
+ {
+ }
}
18 Tests/Fixtures/Model/JmsNested.php
View
@@ -36,4 +36,22 @@ class JmsNested
*/
public $parent;
+ /**
+ * @Jms\Type("string")
+ * @Jms\Since("0.2")
+ */
+ public $since;
+
+ /**
+ * @Jms\Type("string")
+ * @Jms\Until("0.3")
+ */
+ public $until;
+
+ /**
+ * @Jms\Type("string")
+ * @Jms\Since("0.4")
+ * @Jms\Until("0.5")
+ */
+ public $sinceAndUntil;
}
18 Tests/Fixtures/app/AppKernel.php
View
@@ -12,23 +12,7 @@
namespace Nelmio\ApiDocBundle\Tests\Functional;
// get the autoload file
-$dir = __DIR__;
-$lastDir = null;
-while ($dir !== $lastDir) {
- $lastDir = $dir;
-
- if (is_file($dir.'/autoload.php')) {
- require_once $dir.'/autoload.php';
- break;
- }
-
- if (is_file($dir.'/autoload.php.dist')) {
- require_once $dir.'/autoload.php.dist';
- break;
- }
-
- $dir = dirname($dir);
-}
+require_once __DIR__.'/../../../vendor/autoload.php';
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\HttpKernel\Kernel;
4 Tests/Fixtures/app/config/routing.yml
View
@@ -117,3 +117,7 @@ test_route_17:
defaults: { _controller: NelmioApiDocTestBundle:Test:deprecated }
requirements:
_method: GET
+
+test_return_nested_output:
+ pattern: /return-nested-output
+ defaults: { _controller: NelmioApiDocTestBundle:Test:jmsReturnNestedOutput, _format: json }
107 Tests/Formatter/MarkdownFormatterTest.php
View
@@ -244,6 +244,21 @@ public function testFormat()
* type: array of objects (JmsNested)
* required: false
+nested[since]:
+
+ * type: string
+ * required: false
+
+nested[until]:
+
+ * type: string
+ * required: false
+
+nested[since_and_until]:
+
+ * type: string
+ * required: false
+
nested_array[]:
* type: array of objects (JmsNested)
@@ -285,6 +300,98 @@ public function testFormat()
- Description: The param id
+### `ANY` /return-nested-output ###
+
+
+#### Response ####
+
+foo:
+
+ * type: string
+
+bar:
+
+ * type: DateTime
+
+number:
+
+ * type: double
+
+arr:
+
+ * type: array
+
+nested:
+
+ * type: object (JmsNested)
+
+nested[foo]:
+
+ * type: DateTime
+
+nested[bar]:
+
+ * type: string
+
+nested[baz][]:
+
+ * type: array of integers
+ * description: Epic description.
+
+With multiple lines.
+
+nested[circular]:
+
+ * type: object (JmsNested)
+
+nested[parent]:
+
+ * type: object (JmsTest)
+
+nested[parent][foo]:
+
+ * type: string
+
+nested[parent][bar]:
+
+ * type: DateTime
+
+nested[parent][number]:
+
+ * type: double
+
+nested[parent][arr]:
+
+ * type: array
+
+nested[parent][nested]:
+
+ * type: object (JmsNested)
+
+nested[parent][nested_array][]:
+
+ * type: array of objects (JmsNested)
+
+nested[since]:
+
+ * type: string
+ * versions: >=0.2
+
+nested[until]:
+
+ * type: string
+ * versions: <=0.3
+
+nested[since_and_until]:
+
+ * type: string
+ * versions: >=0.4,<=0.5
+
+nested_array[]:
+
+ * type: array of objects (JmsNested)
+
+
### `ANY` /secure-route ###
272 Tests/Formatter/SimpleFormatterTest.php
View
@@ -252,6 +252,8 @@ public function testFormat()
'required' => false,
'description' => '',
'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
),
'bar' =>
array(
@@ -259,6 +261,8 @@ public function testFormat()
'required' => false,
'description' => '',
'readonly' => true,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
),
'number' =>
array(
@@ -266,6 +270,8 @@ public function testFormat()
'required' => false,
'description' => '',
'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
),
'arr' =>
array(
@@ -273,6 +279,8 @@ public function testFormat()
'required' => false,
'description' => '',
'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
),
'nested' =>
array(
@@ -280,6 +288,8 @@ public function testFormat()
'required' => false,
'description' => '',
'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
'children' =>
array(
'foo' =>
@@ -288,6 +298,8 @@ public function testFormat()
'required' => false,
'description' => '',
'readonly' => true,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
),
'bar' =>
array(
@@ -295,6 +307,8 @@ public function testFormat()
'required' => false,
'description' => '',
'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
),
'baz' =>
array(
@@ -304,6 +318,8 @@ public function testFormat()
With multiple lines.',
'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
),
'circular' =>
array(
@@ -311,6 +327,8 @@ public function testFormat()
'required' => false,
'description' => '',
'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
),
'parent' =>
array(
@@ -318,6 +336,8 @@ public function testFormat()
'required' => false,
'description' => '',
'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
'children' =>
array(
'foo' =>
@@ -326,6 +346,8 @@ public function testFormat()
'required' => false,
'description' => '',
'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
),
'bar' =>
array(
@@ -333,6 +355,8 @@ public function testFormat()
'required' => false,
'description' => '',
'readonly' => true,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
),
'number' =>
array(
@@ -340,6 +364,8 @@ public function testFormat()
'required' => false,
'description' => '',
'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
),
'arr' =>
array(
@@ -347,6 +373,8 @@ public function testFormat()
'required' => false,
'description' => '',
'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
),
'nested' =>
array(
@@ -354,6 +382,8 @@ public function testFormat()
'required' => false,
'description' => '',
'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
),
'nested_array' =>
array(
@@ -361,9 +391,38 @@ public function testFormat()
'required' => false,
'description' => '',
'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
),
),
),
+ 'since' =>
+ array (
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => '0.2',
+ 'untilVersion' => null,
+ ),
+ 'until' =>
+ array (
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => '0.3',
+ ),
+ 'since_and_until' =>
+ array (
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => '0.4',
+ 'untilVersion' => '0.5',
+ ),
),
),
'nested_array' =>
@@ -372,6 +431,8 @@ public function testFormat()
'required' => false,
'description' => '',
'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
),
),
'https' => false,
@@ -440,6 +501,205 @@ public function testFormat()
7 =>
array(
'method' => 'ANY',
+ 'uri' => '/return-nested-output',
+ 'https' => false,
+ 'authentication' => false,
+ 'deprecated' => false,
+ 'response' =>
+ array (
+ 'foo' =>
+ array (
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'bar' =>
+ array (
+ 'dataType' => 'DateTime',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => true,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'number' =>
+ array (
+ 'dataType' => 'double',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'arr' =>
+ array (
+ 'dataType' => 'array',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'nested' =>
+ array (
+ 'dataType' => 'object (JmsNested)',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ 'children' =>
+ array (
+ 'foo' =>
+ array (
+ 'dataType' => 'DateTime',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => true,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'bar' =>
+ array (
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'baz' =>
+ array (
+ 'dataType' => 'array of integers',
+ 'required' => false,
+ 'description' => 'Epic description.
+
+With multiple lines.',
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'circular' =>
+ array (
+ 'dataType' => 'object (JmsNested)',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'parent' =>
+ array (
+ 'dataType' => 'object (JmsTest)',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ 'children' =>
+ array (
+ 'foo' =>
+ array (
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'bar' =>
+ array (
+ 'dataType' => 'DateTime',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => true,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'number' =>
+ array (
+ 'dataType' => 'double',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'arr' =>
+ array (
+ 'dataType' => 'array',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'nested' =>
+ array (
+ 'dataType' => 'object (JmsNested)',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'nested_array' =>
+ array (
+ 'dataType' => 'array of objects (JmsNested)',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ ),
+ ),
+ 'since' =>
+ array (
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => '0.2',
+ 'untilVersion' => null,
+ ),
+ 'until' =>
+ array (
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => '0.3',
+ ),
+ 'since_and_until' =>
+ array (
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => '0.4',
+ 'untilVersion' => '0.5',
+ ),
+ ),
+ ),
+ 'nested_array' =>
+ array (
+ 'dataType' => 'array of objects (JmsNested)',
+ 'required' => false,
+ 'description' => '',
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ ),
+ ),
+ 8 =>
+ array(
+ 'method' => 'ANY',
'uri' => '/secure-route',
'requirements' =>
array(
@@ -454,7 +714,7 @@ public function testFormat()
'authentication' => false,
'deprecated' => false,
),
- 8 =>
+ 9 =>
array(
'method' => 'ANY',
'uri' => '/yet-another/{id}',
@@ -471,7 +731,7 @@ public function testFormat()
'authentication' => false,
'deprecated' => false,
),
- 9 =>
+ 10 =>
array(
'method' => 'GET',
'uri' => '/z-action-with-deprecated-indicator',
@@ -479,7 +739,7 @@ public function testFormat()
'authentication' => false,
'deprecated' => true,
),
- 10 =>
+ 11 =>
array(
'method' => 'GET',
'uri' => '/z-action-with-query-param',
@@ -496,7 +756,7 @@ public function testFormat()
'authentication' => false,
'deprecated' => false,
),
- 11 =>
+ 12 =>
array(
'method' => 'GET',
'uri' => '/z-action-with-query-param-no-default',
@@ -512,7 +772,7 @@ public function testFormat()
'authentication' => false,
'deprecated' => false,
),
- 12 =>
+ 13 =>
array(
'method' => 'GET',
'uri' => '/z-action-with-query-param-strict',
@@ -529,7 +789,7 @@ public function testFormat()
'authentication' => false,
'deprecated' => false,
),
- 13 =>
+ 14 =>
array(
'method' => 'POST',
'uri' => '/z-action-with-request-param',
289 Tests/Parser/JmsMetadataParserTest.php
View
@@ -5,6 +5,7 @@
use Nelmio\ApiDocBundle\Parser\JmsMetadataParser;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
+use JMS\Serializer\Naming\CamelCaseNamingStrategy;
class JmsMetadataParserTest extends \PHPUnit_Framework_TestCase
{
@@ -61,7 +62,7 @@ public function testParserWithNestedType($type)
->method('translateName')
->will($this->returnValue('baz'));
- $input = new JmsNested();
+ $input = 'Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsNested';
$metadataFactory->expects($this->once())
->method('getMetadataForClass')
@@ -70,28 +71,278 @@ public function testParserWithNestedType($type)
$jmsMetadataParser = new JmsMetadataParser($metadataFactory, $propertyNamingStrategy, $docCommentExtractor);
- $output = $jmsMetadataParser->parse($input);
+ $output = $jmsMetadataParser->parse(
+ array(
+ 'class' => $input,
+ 'groups' => array(),
+ )
+ );
+
+ $this->assertEquals(
+ array(
+ 'foo' => array(
+ 'dataType' => 'DateTime',
+ 'required' => false,
+ 'description' => null,
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'bar' => array(
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => null,
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'baz' => array(
+ 'dataType' => 'array of integers',
+ 'required' => false,
+ 'description' => null,
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ )
+ ),
+ $output
+ );
+ }
+
+ public function testParserWithGroups()
+ {
+ $metadataFactory = $this->getMock('Metadata\MetadataFactoryInterface');
+ $docCommentExtractor = $this->getMockBuilder('Nelmio\ApiDocBundle\Util\DocCommentExtractor')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyMetadataFoo = new PropertyMetadata('Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsNested', 'foo');
+ $propertyMetadataFoo->type = array('name' => 'string');
+
+ $propertyMetadataBar = new PropertyMetadata('Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsNested', 'bar');
+ $propertyMetadataBar->type = array('name' => 'string');
+ $propertyMetadataBar->groups = array('Default', 'Special');
+
+ $propertyMetadataBaz = new PropertyMetadata('Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsNested', 'baz');
+ $propertyMetadataBaz->type = array('name' => 'string');
+ $propertyMetadataBaz->groups = array('Special');
+
+ $input = 'Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsNested';
+
+ $metadata = new ClassMetadata($input);
+ $metadata->addPropertyMetadata($propertyMetadataFoo);
+ $metadata->addPropertyMetadata($propertyMetadataBar);
+ $metadata->addPropertyMetadata($propertyMetadataBaz);
+
+ $metadataFactory->expects($this->any())
+ ->method('getMetadataForClass')
+ ->with($input)
+ ->will($this->returnValue($metadata));
+
+ $propertyNamingStrategy = new CamelCaseNamingStrategy();
+
+ $jmsMetadataParser = new JmsMetadataParser($metadataFactory, $propertyNamingStrategy, $docCommentExtractor);
+
+ // No group specified.
+ $output = $jmsMetadataParser->parse(
+ array(
+ 'class' => $input,
+ 'groups' => array(),
+ )
+ );
+
+ $this->assertEquals(
+ array(
+ 'foo' => array(
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => null,
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'bar' => array(
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => null,
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ ),
+ $output
+ );
+
+ // Default group.
+ $output = $jmsMetadataParser->parse(
+ array(
+ 'class' => $input,
+ 'groups' => array('Default'),
+ )
+ );
+
+ $this->assertEquals(
+ array(
+ 'foo' => array(
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => null,
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'bar' => array(
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => null,
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ ),
+ $output
+ );
- $this->assertEquals(array(
- 'foo' => array(
- 'dataType' => 'DateTime',
- 'required' => false,
- 'description' => '',
- 'readonly' => false
+ // Special group.
+ $output = $jmsMetadataParser->parse(
+ array(
+ 'class' => $input,
+ 'groups' => array('Special'),
+ )
+ );
+
+ $this->assertEquals(
+ array(
+ 'bar' => array(
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => null,
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'baz' => array(
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => null,
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
),
- 'bar' => array(
- 'dataType' => 'string',
- 'required' => false,
- 'description' => '',
- 'readonly' => false
+ $output
+ );
+
+ // Default + Special groups.
+ $output = $jmsMetadataParser->parse(
+ array(
+ 'class' => $input,
+ 'groups' => array('Default', 'Special'),
+ )
+ );
+
+ $this->assertEquals(
+ array(
+ 'foo' => array(
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => null,
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'bar' => array(
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => null,
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'baz' => array(
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => null,
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ )
),
- 'baz' => array(
- 'dataType' => 'array of integers',
- 'required' => false,
- 'description' => '',
- 'readonly' => false
+ $output
+ );
+ }
+
+ public function testParserWithVersion()
+ {
+ $metadataFactory = $this->getMock('Metadata\MetadataFactoryInterface');
+ $docCommentExtractor = $this->getMockBuilder('Nelmio\ApiDocBundle\Util\DocCommentExtractor')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyMetadataFoo = new PropertyMetadata('Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsNested', 'foo');
+ $propertyMetadataFoo->type = array('name' => 'string');
+
+ $propertyMetadataBar = new PropertyMetadata('Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsNested', 'bar');
+ $propertyMetadataBar->type = array('name' => 'string');
+ $propertyMetadataBar->sinceVersion = '2.0';
+
+ $propertyMetadataBaz = new PropertyMetadata('Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsNested', 'baz');
+ $propertyMetadataBaz->type = array('name' => 'string');
+ $propertyMetadataBaz->untilVersion = '3.0';
+
+ $input = 'Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsNested';
+
+ $metadata = new ClassMetadata($input);
+ $metadata->addPropertyMetadata($propertyMetadataFoo);
+ $metadata->addPropertyMetadata($propertyMetadataBar);
+ $metadata->addPropertyMetadata($propertyMetadataBaz);
+
+ $metadataFactory->expects($this->any())
+ ->method('getMetadataForClass')
+ ->with($input)
+ ->will($this->returnValue($metadata));
+
+ $propertyNamingStrategy = new CamelCaseNamingStrategy();
+
+ $jmsMetadataParser = new JmsMetadataParser($metadataFactory, $propertyNamingStrategy, $docCommentExtractor);
+
+ // No group specified.
+ $output = $jmsMetadataParser->parse(
+ array(
+ 'class' => $input,
+ 'groups' => array(),
)
- ), $output);
+ );
+
+ $this->assertEquals(
+ array(
+ 'foo' => array(
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => null,
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => null,
+ ),
+ 'bar' => array(
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => null,
+ 'readonly' => false,
+ 'sinceVersion' => '2.0',
+ 'untilVersion' => null,
+ ),
+ 'baz' => array(
+ 'dataType' => 'string',
+ 'required' => false,
+ 'description' => null,
+ 'readonly' => false,
+ 'sinceVersion' => null,
+ 'untilVersion' => '3.0',
+ )
+ ),
+ $output
+ );
}
public function dataTestParserWithNestedType()
1  composer.json
View
@@ -21,6 +21,7 @@
"dflydev/markdown": "1.0.*"
},
"conflict": {
+ "jms/serializer": "<0.12",
"jms/serializer-bundle": "<0.11"
},
"require-dev": {
Something went wrong with that request. Please try again.