Skip to content

Commit b9e3328

Browse files
aaa2000soyuka
authored andcommitted
Use default value of PHP properties to Swagger doc
Add default and example information to swagger context if php properties have default values so the exemple documentation section use these values. Close #2363
1 parent b72a90b commit b9e3328

File tree

5 files changed

+204
-0
lines changed

5 files changed

+204
-0
lines changed

src/Bridge/Symfony/Bundle/Resources/config/metadata/metadata.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@
7474
<argument type="service" id="api_platform.metadata.property.metadata_factory.cached.inner" />
7575
</service>
7676

77+
<service id="api_platform.metadata.property.metadata_factory.default_property" decorates="api_platform.metadata.property.metadata_factory" decoration-priority="30" class="ApiPlatform\Core\Metadata\Property\Factory\DefaultPropertyMetadataFactory" public="false">
78+
<argument type="service" id="api_platform.metadata.property.metadata_factory.default_property.inner" />
79+
</service>
80+
7781
<service id="ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface" alias="api_platform.metadata.property.metadata_factory" />
7882

7983
<!-- Cache -->
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Core\Metadata\Property\Factory;
15+
16+
use ApiPlatform\Core\Exception\PropertyNotFoundException;
17+
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
18+
19+
class DefaultPropertyMetadataFactory implements PropertyMetadataFactoryInterface
20+
{
21+
private $decorated;
22+
23+
public function __construct(PropertyMetadataFactoryInterface $decorated = null)
24+
{
25+
$this->decorated = $decorated;
26+
}
27+
28+
public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata
29+
{
30+
if (null === $this->decorated) {
31+
$propertyMetadata = new PropertyMetadata();
32+
} else {
33+
try {
34+
$propertyMetadata = $this->decorated->create($resourceClass, $property, $options);
35+
} catch (PropertyNotFoundException $propertyNotFoundException) {
36+
$propertyMetadata = new PropertyMetadata();
37+
}
38+
}
39+
40+
try {
41+
$reflectionClass = new \ReflectionClass($resourceClass);
42+
} catch (\ReflectionException $reflectionException) {
43+
return $propertyMetadata;
44+
}
45+
46+
$defaultProperties = $reflectionClass->getDefaultProperties();
47+
48+
if (array_key_exists($property, $defaultProperties) && null !== ($defaultProperty = $defaultProperties[$property])) {
49+
$attributes = $propertyMetadata->getAttributes() ?? [];
50+
$attributes['swagger_context']['default'] = $defaultProperty;
51+
if (!isset($attributes['swagger_context']['example'])) {
52+
$attributes['swagger_context']['example'] = $defaultProperty;
53+
}
54+
55+
return $propertyMetadata->withAttributes($attributes);
56+
}
57+
58+
return $propertyMetadata;
59+
}
60+
}

tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,7 @@ private function getPartialContainerBuilderProphecy($configuration = null)
936936
'api_platform.metadata.resource.metadata_factory.xml',
937937
'api_platform.metadata.resource.name_collection_factory.cached',
938938
'api_platform.metadata.resource.name_collection_factory.xml',
939+
'api_platform.metadata.property.metadata_factory.default_property',
939940
'api_platform.negotiator',
940941
'api_platform.operation_method_resolver',
941942
'api_platform.operation_path_resolver.custom',
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity;
15+
16+
use ApiPlatform\Core\Annotation\ApiResource;
17+
use Doctrine\ORM\Mapping as ORM;
18+
use Symfony\Component\Serializer\Annotation\Groups;
19+
20+
/**
21+
* DummyPropertyWithDefaultValue.
22+
*
23+
* @ORM\Entity
24+
*
25+
* @ApiResource(attributes={
26+
* "normalization_context"={"groups"={"dummy_read"}},
27+
* "denormalization_context"={"groups"={"dummy_write"}}
28+
* })
29+
*/
30+
class DummyPropertyWithDefaultValue
31+
{
32+
/**
33+
* @var int
34+
*
35+
* @ORM\Id
36+
* @ORM\Column(type="integer")
37+
* @ORM\GeneratedValue(strategy="AUTO")
38+
*
39+
* @Groups("dummy_read")
40+
*/
41+
private $id;
42+
43+
/**
44+
* @var string
45+
*
46+
* @ORM\Column(nullable=true)
47+
*
48+
* @Groups({"dummy_read", "dummy_write"})
49+
*/
50+
public $foo = 'foo';
51+
52+
/**
53+
* @return int
54+
*/
55+
public function getId()
56+
{
57+
return $this->id;
58+
}
59+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Core\Tests\Metadata\Property\Factory;
15+
16+
use ApiPlatform\Core\Exception\PropertyNotFoundException;
17+
use ApiPlatform\Core\Metadata\Property\Factory\DefaultPropertyMetadataFactory;
18+
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
19+
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
20+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyPropertyWithDefaultValue;
21+
use PHPUnit\Framework\TestCase;
22+
23+
class DefaultPropertyMetadataFactoryTest extends TestCase
24+
{
25+
public function testCreate()
26+
{
27+
$factory = new DefaultPropertyMetadataFactory();
28+
$metadata = $factory->create(DummyPropertyWithDefaultValue::class, 'foo');
29+
30+
$shouldBe = [
31+
'swagger_context' => [
32+
'default' => 'foo',
33+
'example' => 'foo',
34+
],
35+
];
36+
$this->assertEquals($metadata->getAttributes(), $shouldBe);
37+
}
38+
39+
public function testCreateShouldNotOverrideExampleIfAlreadyPresent()
40+
{
41+
$decoratedReturnProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
42+
$decoratedReturnProphecy->create(DummyPropertyWithDefaultValue::class, 'foo', [])
43+
->willReturn(new PropertyMetadata(null, 'A dummy', true, true, null, null, false, false, null, null, [
44+
'swagger_context' => [
45+
'example' => 'foo example',
46+
],
47+
]))
48+
->shouldBeCalled();
49+
50+
$factory = new DefaultPropertyMetadataFactory($decoratedReturnProphecy->reveal());
51+
$metadata = $factory->create(DummyPropertyWithDefaultValue::class, 'foo');
52+
53+
$shouldBe = [
54+
'swagger_context' => [
55+
'default' => 'foo',
56+
'example' => 'foo example',
57+
],
58+
];
59+
$this->assertEquals($metadata->getAttributes(), $shouldBe);
60+
}
61+
62+
public function testClassDoesNotExist()
63+
{
64+
$factory = new DefaultPropertyMetadataFactory();
65+
$metadata = $factory->create('\DoNotExist', 'foo');
66+
67+
$this->assertEquals(new PropertyMetadata(), $metadata);
68+
}
69+
70+
public function testPropertyDoesNotExist()
71+
{
72+
$decoratedProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
73+
$decoratedProphecy->create(DummyPropertyWithDefaultValue::class, 'doNotExist', [])->willThrow(new PropertyNotFoundException());
74+
75+
$factory = new DefaultPropertyMetadataFactory($decoratedProphecy->reveal());
76+
$metadata = $factory->create(DummyPropertyWithDefaultValue::class, 'doNotExist');
77+
78+
$this->assertEquals(new PropertyMetadata(), $metadata);
79+
}
80+
}

0 commit comments

Comments
 (0)