Skip to content

Commit e7563bd

Browse files
author
Tassilo Groeper
authored
Merge b630e14 into 9781658
2 parents 9781658 + b630e14 commit e7563bd

File tree

4 files changed

+14
-16
lines changed

4 files changed

+14
-16
lines changed

src/OpenApi/Model/Components.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ final class Components
2929

3030
public function __construct(\ArrayObject $schemas = null, \ArrayObject $responses = null, \ArrayObject $parameters = null, \ArrayObject $examples = null, \ArrayObject $requestBodies = null, \ArrayObject $headers = null, \ArrayObject $securitySchemes = null, \ArrayObject $links = null, \ArrayObject $callbacks = null)
3131
{
32+
!$schemas ?: $schemas->ksort();
33+
3234
$this->schemas = $schemas;
3335
$this->responses = $responses;
3436
$this->parameters = $parameters;

src/OpenApi/Model/Paths.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ final class Paths
2020
public function addPath(string $path, PathItem $pathItem)
2121
{
2222
$this->paths[$path] = $pathItem;
23+
24+
ksort($this->paths);
2325
}
2426

2527
public function getPath(string $path): ?PathItem

src/OpenApi/Serializer/OpenApiNormalizer.php

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace ApiPlatform\Core\OpenApi\Serializer;
1515

16+
use ApiPlatform\Core\OpenApi\Model\Paths;
1617
use ApiPlatform\Core\OpenApi\OpenApi;
1718
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
1819
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
@@ -38,8 +39,14 @@ public function __construct(NormalizerInterface $decorated)
3839
*/
3940
public function normalize($object, $format = null, array $context = []): array
4041
{
42+
$pathsCallback = function ($innerObject) {
43+
return $innerObject instanceof Paths ? $innerObject->getPaths() : [];
44+
};
4145
$context[AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS] = true;
4246
$context[AbstractObjectNormalizer::SKIP_NULL_VALUES] = true;
47+
$context[AbstractObjectNormalizer::CALLBACKS] = [
48+
'paths' => $pathsCallback,
49+
];
4350

4451
return $this->recursiveClean($this->decorated->normalize($object, $format, $context));
4552
}
@@ -54,23 +61,8 @@ private function recursiveClean($data): array
5461
continue;
5562
}
5663

57-
if ('schemas' === $key && \is_array($value)) {
58-
ksort($value);
59-
}
60-
61-
// Side effect of using getPaths(): Paths which itself contains the array
62-
if ('paths' === $key) {
63-
$value = $data['paths'] = $data['paths']['paths'];
64-
if ($value) {
65-
ksort($value);
66-
}
67-
unset($data['paths']['paths']);
68-
}
69-
7064
if (\is_array($value)) {
7165
$data[$key] = $this->recursiveClean($value);
72-
// arrays must stay even if empty
73-
continue;
7466
}
7567
}
7668

tests/OpenApi/Serializer/OpenApiNormalizerTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public function testNormalize()
6060
$resourceNameCollectionFactoryProphecy->create()->shouldBeCalled()->willReturn(new ResourceNameCollection([Dummy::class, 'Zorro']));
6161
$defaultContext = ['base_url' => '/app_dev.php/'];
6262
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
63-
$propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['id', 'name', 'description', 'dummyDate']));
63+
$propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['id', 'name', 'description', 'dummyDate', 'paths']));
6464
$propertyNameCollectionFactoryProphecy->create('Zorro', Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['id']));
6565

6666
$dummyMetadata = new ResourceMetadata(
@@ -104,6 +104,8 @@ public function testNormalize()
104104
$propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [], null, null, null, null, ['minLength' => 3, 'maxLength' => 20, 'pattern' => '^dummyPattern$']));
105105
$propertyMetadataFactoryProphecy->create(Dummy::class, 'description', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is an initializable but not writable property.', true, false, true, true, false, false, null, null, [], null, true));
106106
$propertyMetadataFactoryProphecy->create(Dummy::class, 'dummyDate', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTime::class), 'This is a \DateTimeInterface object.', true, true, true, true, false, false, null, null, []));
107+
// Check reserved word "paths": when normalize->recursiveClean in OpenApi Component Schema.
108+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'paths', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_ARRAY), 'This is a array.', true, true, true, true, false, false, null, null, []));
107109

108110
$propertyMetadataFactoryProphecy->create('Zorro', 'id', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false, null, null, null, true));
109111

0 commit comments

Comments
 (0)