Skip to content

Commit 7d311da

Browse files
authored
Merge pull request #1914 from bendavies/json-hal-name-converter
use name converter for relations in hal item normalizer
2 parents c711237 + f0c490f commit 7d311da

File tree

2 files changed

+69
-20
lines changed

2 files changed

+69
-20
lines changed

src/Hal/Serializer/ItemNormalizer.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,24 +174,29 @@ private function populateRelation(array $data, $object, string $format = null, a
174174
continue;
175175
}
176176

177+
$relationName = $relation['name'];
178+
if ($this->nameConverter) {
179+
$relationName = $this->nameConverter->normalize($relationName);
180+
}
181+
177182
if ('one' === $relation['cardinality']) {
178183
if ('links' === $type) {
179-
$data[$key][$relation['name']]['href'] = $this->getRelationIri($attributeValue);
184+
$data[$key][$relationName]['href'] = $this->getRelationIri($attributeValue);
180185
continue;
181186
}
182187

183-
$data[$key][$relation['name']] = $attributeValue;
188+
$data[$key][$relationName] = $attributeValue;
184189
continue;
185190
}
186191

187192
// many
188-
$data[$key][$relation['name']] = [];
193+
$data[$key][$relationName] = [];
189194
foreach ($attributeValue as $rel) {
190195
if ('links' === $type) {
191196
$rel = ['href' => $this->getRelationIri($rel)];
192197
}
193198

194-
$data[$key][$relation['name']][] = $rel;
199+
$data[$key][$relationName][] = $rel;
195200
}
196201
}
197202

tests/Hal/Serializer/ItemNormalizerTest.php

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@
2121
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
2222
use ApiPlatform\Core\Metadata\Property\PropertyNameCollection;
2323
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy;
24+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy;
2425
use PHPUnit\Framework\TestCase;
2526
use Prophecy\Argument;
27+
use Symfony\Component\PropertyInfo\Type;
28+
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
2629
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
2730
use Symfony\Component\Serializer\SerializerInterface;
2831

@@ -34,25 +37,28 @@ class ItemNormalizerTest extends TestCase
3437
/**
3538
* @expectedException \ApiPlatform\Core\Exception\RuntimeException
3639
*/
37-
public function testDonTSupportDenormalization()
40+
public function testDoesNotSupportDenormalization()
3841
{
3942
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
4043
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
4144
$iriConverterProphecy = $this->prophesize(IriConverterInterface::class);
4245
$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
46+
$nameConverter = $this->prophesize(NameConverterInterface::class);
4347

4448
$normalizer = new ItemNormalizer(
4549
$propertyNameCollectionFactoryProphecy->reveal(),
4650
$propertyMetadataFactoryProphecy->reveal(),
4751
$iriConverterProphecy->reveal(),
48-
$resourceClassResolverProphecy->reveal()
52+
$resourceClassResolverProphecy->reveal(),
53+
null,
54+
$nameConverter->reveal()
4955
);
5056

5157
$this->assertFalse($normalizer->supportsDenormalization('foo', ItemNormalizer::FORMAT));
5258
$normalizer->denormalize(['foo'], 'Foo');
5359
}
5460

55-
public function testSupportNormalization()
61+
public function testSupportsNormalization()
5662
{
5763
$std = new \stdClass();
5864
$dummy = new Dummy();
@@ -66,11 +72,15 @@ public function testSupportNormalization()
6672
$resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true)->shouldBeCalled();
6773
$resourceClassResolverProphecy->isResourceClass(\stdClass::class)->willReturn(false)->shouldBeCalled();
6874

75+
$nameConverter = $this->prophesize(NameConverterInterface::class);
76+
6977
$normalizer = new ItemNormalizer(
7078
$propertyNameCollectionFactoryProphecy->reveal(),
7179
$propertyMetadataFactoryProphecy->reveal(),
7280
$iriConverterProphecy->reveal(),
73-
$resourceClassResolverProphecy->reveal()
81+
$resourceClassResolverProphecy->reveal(),
82+
null,
83+
$nameConverter->reveal()
7484
);
7585

7686
$this->assertTrue($normalizer->supportsNormalization($dummy, 'jsonhal'));
@@ -80,40 +90,57 @@ public function testSupportNormalization()
8090

8191
public function testNormalize()
8292
{
93+
$relatedDummy = new RelatedDummy();
8394
$dummy = new Dummy();
8495
$dummy->setName('hello');
96+
$dummy->setRelatedDummy($relatedDummy);
8597

86-
$propertyNameCollection = new PropertyNameCollection(['name']);
98+
$propertyNameCollection = new PropertyNameCollection(['name', 'relatedDummy']);
8799
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
88100
$propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn($propertyNameCollection)->shouldBeCalled();
89101

90-
$propertyMetadataFactory = new PropertyMetadata(null, null, true);
91102
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
92-
$propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn($propertyMetadataFactory)->shouldBeCalled();
103+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn(
104+
new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), '', true)
105+
)->shouldBeCalled();
106+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', [])->willReturn(
107+
new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class), '', true, false, false)
108+
)->shouldBeCalled();
93109

94110
$iriConverterProphecy = $this->prophesize(IriConverterInterface::class);
95-
$iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1988')->shouldBeCalled();
111+
$iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1')->shouldBeCalled();
112+
$iriConverterProphecy->getIriFromItem($relatedDummy)->willReturn('/related-dummies/2')->shouldBeCalled();
96113

97114
$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
98115
$resourceClassResolverProphecy->getResourceClass($dummy, null, true)->willReturn(Dummy::class)->shouldBeCalled();
99116
$resourceClassResolverProphecy->getResourceClass($dummy, Dummy::class, true)->willReturn(Dummy::class)->shouldBeCalled();
117+
$resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true)->shouldBeCalled();
100118

101119
$serializerProphecy = $this->prophesize(SerializerInterface::class);
102120
$serializerProphecy->willImplement(NormalizerInterface::class);
103121
$serializerProphecy->normalize('hello', null, Argument::type('array'))->willReturn('hello')->shouldBeCalled();
104122

123+
$nameConverter = $this->prophesize(NameConverterInterface::class);
124+
$nameConverter->normalize('name')->shouldBeCalled()->willReturn('name');
125+
$nameConverter->normalize('relatedDummy')->shouldBeCalled()->willReturn('related_dummy');
126+
105127
$normalizer = new ItemNormalizer(
106128
$propertyNameCollectionFactoryProphecy->reveal(),
107129
$propertyMetadataFactoryProphecy->reveal(),
108130
$iriConverterProphecy->reveal(),
109-
$resourceClassResolverProphecy->reveal()
131+
$resourceClassResolverProphecy->reveal(),
132+
null,
133+
$nameConverter->reveal()
110134
);
111135
$normalizer->setSerializer($serializerProphecy->reveal());
112136

113137
$expected = [
114138
'_links' => [
115139
'self' => [
116-
'href' => '/dummies/1988',
140+
'href' => '/dummies/1',
141+
],
142+
'related_dummy' => [
143+
'href' => '/related-dummies/2',
117144
],
118145
],
119146
'name' => 'hello',
@@ -123,40 +150,57 @@ public function testNormalize()
123150

124151
public function testNormalizeWithoutCache()
125152
{
153+
$relatedDummy = new RelatedDummy();
126154
$dummy = new Dummy();
127155
$dummy->setName('hello');
156+
$dummy->setRelatedDummy($relatedDummy);
128157

129-
$propertyNameCollection = new PropertyNameCollection(['name']);
158+
$propertyNameCollection = new PropertyNameCollection(['name', 'relatedDummy']);
130159
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
131160
$propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn($propertyNameCollection)->shouldBeCalled();
132161

133-
$propertyMetadataFactory = new PropertyMetadata(null, null, true);
134162
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
135-
$propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn($propertyMetadataFactory)->shouldBeCalled();
163+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn(
164+
new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), '', true)
165+
)->shouldBeCalled();
166+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', [])->willReturn(
167+
new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class), '', true, false, false)
168+
)->shouldBeCalled();
136169

137170
$iriConverterProphecy = $this->prophesize(IriConverterInterface::class);
138-
$iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1988')->shouldBeCalled();
171+
$iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1')->shouldBeCalled();
172+
$iriConverterProphecy->getIriFromItem($relatedDummy)->willReturn('/related-dummies/2')->shouldBeCalled();
139173

140174
$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
141175
$resourceClassResolverProphecy->getResourceClass($dummy, null, true)->willReturn(Dummy::class)->shouldBeCalled();
142176
$resourceClassResolverProphecy->getResourceClass($dummy, Dummy::class, true)->willReturn(Dummy::class)->shouldBeCalled();
177+
$resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true)->shouldBeCalled();
143178

144179
$serializerProphecy = $this->prophesize(SerializerInterface::class);
145180
$serializerProphecy->willImplement(NormalizerInterface::class);
146181
$serializerProphecy->normalize('hello', null, Argument::type('array'))->willReturn('hello')->shouldBeCalled();
147182

183+
$nameConverter = $this->prophesize(NameConverterInterface::class);
184+
$nameConverter->normalize('name')->shouldBeCalled()->willReturn('name');
185+
$nameConverter->normalize('relatedDummy')->shouldBeCalled()->willReturn('related_dummy');
186+
148187
$normalizer = new ItemNormalizer(
149188
$propertyNameCollectionFactoryProphecy->reveal(),
150189
$propertyMetadataFactoryProphecy->reveal(),
151190
$iriConverterProphecy->reveal(),
152-
$resourceClassResolverProphecy->reveal()
191+
$resourceClassResolverProphecy->reveal(),
192+
null,
193+
$nameConverter->reveal()
153194
);
154195
$normalizer->setSerializer($serializerProphecy->reveal());
155196

156197
$expected = [
157198
'_links' => [
158199
'self' => [
159-
'href' => '/dummies/1988',
200+
'href' => '/dummies/1',
201+
],
202+
'related_dummy' => [
203+
'href' => '/related-dummies/2',
160204
],
161205
],
162206
'name' => 'hello',

0 commit comments

Comments
 (0)