Skip to content

Commit f0c490f

Browse files
committed
use name converter for relations in hal item normalizer
1 parent dcdea86 commit f0c490f

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
@@ -22,8 +22,11 @@
2222
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
2323
use ApiPlatform\Core\Metadata\Property\PropertyNameCollection;
2424
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy;
25+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy;
2526
use PHPUnit\Framework\TestCase;
2627
use Prophecy\Argument;
28+
use Symfony\Component\PropertyInfo\Type;
29+
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
2730
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
2831
use Symfony\Component\Serializer\SerializerInterface;
2932

@@ -35,25 +38,28 @@ class ItemNormalizerTest extends TestCase
3538
/**
3639
* @expectedException \ApiPlatform\Core\Exception\RuntimeException
3740
*/
38-
public function testDonTSupportDenormalization()
41+
public function testDoesNotSupportDenormalization()
3942
{
4043
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
4144
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
4245
$iriConverterProphecy = $this->prophesize(IriConverterInterface::class);
4346
$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
47+
$nameConverter = $this->prophesize(NameConverterInterface::class);
4448

4549
$normalizer = new ItemNormalizer(
4650
$propertyNameCollectionFactoryProphecy->reveal(),
4751
$propertyMetadataFactoryProphecy->reveal(),
4852
$iriConverterProphecy->reveal(),
49-
$resourceClassResolverProphecy->reveal()
53+
$resourceClassResolverProphecy->reveal(),
54+
null,
55+
$nameConverter->reveal()
5056
);
5157

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

56-
public function testSupportNormalization()
62+
public function testSupportsNormalization()
5763
{
5864
$std = new \stdClass();
5965
$dummy = new Dummy();
@@ -67,11 +73,15 @@ public function testSupportNormalization()
6773
$resourceClassResolverProphecy->getResourceClass($dummy)->willReturn(Dummy::class)->shouldBeCalled();
6874
$resourceClassResolverProphecy->getResourceClass($std)->willThrow(new InvalidArgumentException())->shouldBeCalled();
6975

76+
$nameConverter = $this->prophesize(NameConverterInterface::class);
77+
7078
$normalizer = new ItemNormalizer(
7179
$propertyNameCollectionFactoryProphecy->reveal(),
7280
$propertyMetadataFactoryProphecy->reveal(),
7381
$iriConverterProphecy->reveal(),
74-
$resourceClassResolverProphecy->reveal()
82+
$resourceClassResolverProphecy->reveal(),
83+
null,
84+
$nameConverter->reveal()
7585
);
7686

7787
$this->assertTrue($normalizer->supportsNormalization($dummy, 'jsonhal'));
@@ -81,40 +91,57 @@ public function testSupportNormalization()
8191

8292
public function testNormalize()
8393
{
94+
$relatedDummy = new RelatedDummy();
8495
$dummy = new Dummy();
8596
$dummy->setName('hello');
97+
$dummy->setRelatedDummy($relatedDummy);
8698

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

91-
$propertyMetadataFactory = new PropertyMetadata(null, null, true);
92103
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
93-
$propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn($propertyMetadataFactory)->shouldBeCalled();
104+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn(
105+
new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), '', true)
106+
)->shouldBeCalled();
107+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', [])->willReturn(
108+
new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class), '', true, false, false)
109+
)->shouldBeCalled();
94110

95111
$iriConverterProphecy = $this->prophesize(IriConverterInterface::class);
96-
$iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1988')->shouldBeCalled();
112+
$iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1')->shouldBeCalled();
113+
$iriConverterProphecy->getIriFromItem($relatedDummy)->willReturn('/related-dummies/2')->shouldBeCalled();
97114

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

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

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

114138
$expected = [
115139
'_links' => [
116140
'self' => [
117-
'href' => '/dummies/1988',
141+
'href' => '/dummies/1',
142+
],
143+
'related_dummy' => [
144+
'href' => '/related-dummies/2',
118145
],
119146
],
120147
'name' => 'hello',
@@ -124,40 +151,57 @@ public function testNormalize()
124151

125152
public function testNormalizeWithoutCache()
126153
{
154+
$relatedDummy = new RelatedDummy();
127155
$dummy = new Dummy();
128156
$dummy->setName('hello');
157+
$dummy->setRelatedDummy($relatedDummy);
129158

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

134-
$propertyMetadataFactory = new PropertyMetadata(null, null, true);
135163
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
136-
$propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn($propertyMetadataFactory)->shouldBeCalled();
164+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn(
165+
new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), '', true)
166+
)->shouldBeCalled();
167+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', [])->willReturn(
168+
new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class), '', true, false, false)
169+
)->shouldBeCalled();
137170

138171
$iriConverterProphecy = $this->prophesize(IriConverterInterface::class);
139-
$iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1988')->shouldBeCalled();
172+
$iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1')->shouldBeCalled();
173+
$iriConverterProphecy->getIriFromItem($relatedDummy)->willReturn('/related-dummies/2')->shouldBeCalled();
140174

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

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

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

157198
$expected = [
158199
'_links' => [
159200
'self' => [
160-
'href' => '/dummies/1988',
201+
'href' => '/dummies/1',
202+
],
203+
'related_dummy' => [
204+
'href' => '/related-dummies/2',
161205
],
162206
],
163207
'name' => 'hello',

0 commit comments

Comments
 (0)