Skip to content

Commit 2ac0d66

Browse files
aaa2000soyuka
authored andcommitted
Add default and example properties to ApiProperty
1 parent b9e3328 commit 2ac0d66

File tree

7 files changed

+147
-43
lines changed

7 files changed

+147
-43
lines changed

src/Annotation/ApiProperty.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ final class ApiProperty
7676
*/
7777
public $identifier;
7878

79+
/**
80+
* @var string
81+
*/
82+
public $default;
83+
84+
/**
85+
* @var string
86+
*/
87+
public $example;
88+
7989
/**
8090
* @see https://github.com/Haehnchen/idea-php-annotation-plugin/issues/112
8191
*

src/Metadata/Property/Factory/AnnotationPropertyMetadataFactory.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,16 @@ private function createMetadata(ApiProperty $annotation, PropertyMetadata $paren
112112
$annotation->identifier,
113113
$annotation->iri,
114114
null,
115-
$annotation->attributes
115+
$annotation->attributes,
116+
null,
117+
null,
118+
$annotation->default,
119+
$annotation->example
116120
);
117121
}
118122

119123
$propertyMetadata = $parentPropertyMetadata;
120-
foreach ([['get', 'description'], ['is', 'readable'], ['is', 'writable'], ['is', 'readableLink'], ['is', 'writableLink'], ['is', 'required'], ['get', 'iri'], ['is', 'identifier'], ['get', 'attributes']] as $property) {
124+
foreach ([['get', 'description'], ['is', 'readable'], ['is', 'writable'], ['is', 'readableLink'], ['is', 'writableLink'], ['is', 'required'], ['get', 'iri'], ['is', 'identifier'], ['get', 'attributes'], ['get', 'default'], ['get', 'example']] as $property) {
121125
if (null !== $value = $annotation->{$property[1]}) {
122126
$propertyMetadata = $this->createWith($propertyMetadata, $property, $value);
123127
}

src/Metadata/Property/Factory/DefaultPropertyMetadataFactory.php

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
use ApiPlatform\Core\Exception\PropertyNotFoundException;
1717
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
1818

19-
class DefaultPropertyMetadataFactory implements PropertyMetadataFactoryInterface
19+
/**
20+
* Populates defaults values of the ressource properties using the default PHP values of properties.
21+
*/
22+
final class DefaultPropertyMetadataFactory implements PropertyMetadataFactoryInterface
2023
{
2124
private $decorated;
2225

@@ -45,16 +48,10 @@ public function create(string $resourceClass, string $property, array $options =
4548

4649
$defaultProperties = $reflectionClass->getDefaultProperties();
4750

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);
51+
if (!array_key_exists($property, $defaultProperties) || null === ($defaultProperty = $defaultProperties[$property])) {
52+
return $propertyMetadata;
5653
}
5754

58-
return $propertyMetadata;
55+
return $propertyMetadata->withDefault($defaultProperty);
5956
}
6057
}

src/Metadata/Property/PropertyMetadata.php

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,16 @@ final class PropertyMetadata
3838
private $attributes;
3939
private $subresource;
4040
private $initializable;
41+
/**
42+
* @var null
43+
*/
44+
private $default;
45+
/**
46+
* @var null
47+
*/
48+
private $example;
4149

42-
public function __construct(Type $type = null, string $description = null, bool $readable = null, bool $writable = null, bool $readableLink = null, bool $writableLink = null, bool $required = null, bool $identifier = null, string $iri = null, $childInherited = null, array $attributes = null, SubresourceMetadata $subresource = null, bool $initializable = null)
50+
public function __construct(Type $type = null, string $description = null, bool $readable = null, bool $writable = null, bool $readableLink = null, bool $writableLink = null, bool $required = null, bool $identifier = null, string $iri = null, $childInherited = null, array $attributes = null, SubresourceMetadata $subresource = null, bool $initializable = null, $default = null, $example = null)
4351
{
4452
$this->type = $type;
4553
$this->description = $description;
@@ -57,6 +65,8 @@ public function __construct(Type $type = null, string $description = null, bool
5765
$this->attributes = $attributes;
5866
$this->subresource = $subresource;
5967
$this->initializable = $initializable;
68+
$this->default = $default;
69+
$this->example = $example;
6070
}
6171

6272
/**
@@ -349,4 +359,42 @@ public function withInitializable(bool $initializable): self
349359

350360
return $metadata;
351361
}
362+
363+
/**
364+
* Returns the default value of the property or NULL if the property doesn't have a default value.
365+
*/
366+
public function getDefault()
367+
{
368+
return $this->default;
369+
}
370+
371+
/**
372+
* Returns a new instance with the given default value for the property.
373+
*/
374+
public function withDefault($default): self
375+
{
376+
$metadata = clone $this;
377+
$metadata->default = $default;
378+
379+
return $metadata;
380+
}
381+
382+
/**
383+
* Returns an example of the value of the property.
384+
*/
385+
public function getExample()
386+
{
387+
return $this->example;
388+
}
389+
390+
/**
391+
* Returns a new instance with the given example.
392+
*/
393+
public function withExample($example): self
394+
{
395+
$metadata = clone $this;
396+
$metadata->example = $example;
397+
398+
return $metadata;
399+
}
352400
}

tests/Metadata/Property/Factory/DefaultPropertyMetadataFactoryTest.php

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -27,36 +27,7 @@ public function testCreate()
2727
$factory = new DefaultPropertyMetadataFactory();
2828
$metadata = $factory->create(DummyPropertyWithDefaultValue::class, 'foo');
2929

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);
30+
$this->assertEquals($metadata->getDefault(), 'foo');
6031
}
6132

6233
public function testClassDoesNotExist()

tests/Metadata/Property/PropertyMetadataTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ public function testValueObject()
8282
$newMetadata = $metadata->withInitializable(true);
8383
$this->assertNotSame($metadata, $newMetadata);
8484
$this->assertTrue($newMetadata->isInitializable());
85+
86+
$newMetadata = $metadata->withDefault('foobar');
87+
$this->assertNotSame($metadata, $newMetadata);
88+
$this->assertEquals('foobar', $newMetadata->getDefault());
89+
90+
$newMetadata = $metadata->withExample('foobarexample');
91+
$this->assertNotSame($metadata, $newMetadata);
92+
$this->assertEquals('foobarexample', $newMetadata->getExample());
8593
}
8694

8795
public function testShouldReturnRequiredFalseWhenRequiredTrueIsSetButMaskedByWritableFalse()

tests/Swagger/Serializer/DocumentationNormalizerV2Test.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Dto\OutputDto;
4646
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Answer;
4747
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy;
48+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyPropertyWithDefaultValue;
4849
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Question;
4950
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy;
5051
use PHPUnit\Framework\TestCase;
@@ -2934,4 +2935,69 @@ private function doTestNormalizeWithInputAndOutputClass(): void
29342935

29352936
$this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/']));
29362937
}
2938+
2939+
/**
2940+
* @dataProvider propertyWithDefaultProvider
2941+
*/
2942+
public function testNormalizeWithDefaultProperty($expectedDefault, $expectedExample, PropertyMetadata $propertyMetadata)
2943+
{
2944+
$documentation = new Documentation(new ResourceNameCollection([DummyPropertyWithDefaultValue::class]));
2945+
2946+
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
2947+
$propertyNameCollectionFactoryProphecy->create(DummyPropertyWithDefaultValue::class, [])->shouldBeCalled()->willReturn(new PropertyNameCollection(['foo']));
2948+
2949+
$dummyMetadata = new ResourceMetadata('DummyPropertyWithDefaultValue', null, null, ['get' => ['method' => 'GET']]);
2950+
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
2951+
$resourceMetadataFactoryProphecy->create(DummyPropertyWithDefaultValue::class)->shouldBeCalled()->willReturn($dummyMetadata);
2952+
2953+
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
2954+
$propertyMetadataFactoryProphecy->create(DummyPropertyWithDefaultValue::class, 'foo')->shouldBeCalled()->willReturn($propertyMetadata);
2955+
$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
2956+
$resourceClassResolverProphecy->isResourceClass(DummyPropertyWithDefaultValue::class)->willReturn(true);
2957+
2958+
$operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class);
2959+
$operationMethodResolverProphecy->getItemOperationMethod(DummyPropertyWithDefaultValue::class, 'get')->shouldBeCalled()->willReturn('GET');
2960+
2961+
$operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()));
2962+
2963+
$normalizer = new DocumentationNormalizer(
2964+
$resourceMetadataFactoryProphecy->reveal(),
2965+
$propertyNameCollectionFactoryProphecy->reveal(),
2966+
$propertyMetadataFactoryProphecy->reveal(),
2967+
$resourceClassResolverProphecy->reveal(),
2968+
$operationMethodResolverProphecy->reveal(),
2969+
$operationPathResolver
2970+
);
2971+
2972+
$result = $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT);
2973+
2974+
$this->assertEquals($expectedDefault, $result['definitions']['DummyPropertyWithDefaultValue']['properties']['foo']['default']);
2975+
$this->assertEquals($expectedExample, $result['definitions']['DummyPropertyWithDefaultValue']['properties']['foo']['example']);
2976+
}
2977+
2978+
public function propertyWithDefaultProvider()
2979+
{
2980+
yield 'default should be use for the example if it is not defined' => [
2981+
'default name',
2982+
'default name',
2983+
$this->createStringPropertyMetada('default name'),
2984+
];
2985+
2986+
yield 'should use default and example if they are defined' => [
2987+
'default name',
2988+
'example name',
2989+
$this->createStringPropertyMetada('default name', 'example name'),
2990+
];
2991+
2992+
yield 'should use default and example from swagger context if they are defined' => [
2993+
'swagger default',
2994+
'swagger example',
2995+
$this->createStringPropertyMetada('default name', 'example name', ['swagger_context' => ['default' => 'swagger default', 'example' => 'swagger example']]),
2996+
];
2997+
}
2998+
2999+
protected function createStringPropertyMetada($default = null, $example = null, $attributes = []): PropertyMetadata
3000+
{
3001+
return new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), null, true, true, true, true, false, false, null, null, $attributes, null, null, $default, $example);
3002+
}
29373003
}

0 commit comments

Comments
 (0)