Skip to content

Commit e51024c

Browse files
lyrixxdunglas
authored andcommitted
Do not try do retrieve object in ItemNormalizer $context['resource_class'] is not defined (#2326)
* Do not try do retrieve object in ItemNormalizer $context['resource_class'] is not defined We store some document in Elasticsearch and we hydrate them with the Serializer. But the `ItemNormalizer` raise an error because the `resource_class` is not defined. * Added some log when the $context['resource_class'] is missing in ItemNormalizer
1 parent 6884830 commit e51024c

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

src/Serializer/ItemNormalizer.php

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,17 @@
1313

1414
namespace ApiPlatform\Core\Serializer;
1515

16+
use ApiPlatform\Core\Api\IriConverterInterface;
17+
use ApiPlatform\Core\Api\ResourceClassResolverInterface;
18+
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
1619
use ApiPlatform\Core\Exception\InvalidArgumentException;
20+
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
21+
use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
22+
use Psr\Log\LoggerInterface;
23+
use Psr\Log\NullLogger;
24+
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
25+
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
26+
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
1727

1828
/**
1929
* Generic item normalizer.
@@ -24,6 +34,15 @@
2434
*/
2535
class ItemNormalizer extends AbstractItemNormalizer
2636
{
37+
private $logger;
38+
39+
public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, ResourceClassResolverInterface $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, ItemDataProviderInterface $itemDataProvider = null, bool $allowPlainIdentifiers = false, LoggerInterface $logger = null)
40+
{
41+
parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, $itemDataProvider, $allowPlainIdentifiers);
42+
43+
$this->logger = $logger ?: new NullLogger();
44+
}
45+
2746
/**
2847
* {@inheritdoc}
2948
*
@@ -37,7 +56,14 @@ public function denormalize($data, $class, $format = null, array $context = [])
3756
throw new InvalidArgumentException('Update is not allowed for this operation.');
3857
}
3958

40-
$this->updateObjectToPopulate($data, $context);
59+
if (isset($context['resource_class'])) {
60+
$this->updateObjectToPopulate($data, $context);
61+
} else {
62+
// See https://github.com/api-platform/core/pull/2326 to understand this message.
63+
$this->logger->warning('The "resource_class" key is missing from the context.', [
64+
'context' => $context,
65+
]);
66+
}
4167
}
4268

4369
return parent::denormalize($data, $class, $format, $context);

tests/Serializer/ItemNormalizerTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,4 +186,38 @@ public function testDenormalizeWithIdAndUpdateNotAllowed()
186186
$normalizer->setSerializer($serializerProphecy->reveal());
187187
$normalizer->denormalize(['id' => '12', 'name' => 'hello'], Dummy::class, null, $context);
188188
}
189+
190+
public function testDenormalizeWithIdAndNoResourceClass()
191+
{
192+
$context = [];
193+
194+
$propertyNameCollection = new PropertyNameCollection(['id', 'name']);
195+
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
196+
$propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn($propertyNameCollection)->shouldBeCalled();
197+
198+
$propertyMetadataFactory = new PropertyMetadata(null, null, true, true);
199+
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
200+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'id', [])->willReturn($propertyMetadataFactory)->shouldBeCalled();
201+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn($propertyMetadataFactory)->shouldBeCalled();
202+
203+
$iriConverterProphecy = $this->prophesize(IriConverterInterface::class);
204+
205+
$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
206+
207+
$serializerProphecy = $this->prophesize(SerializerInterface::class);
208+
$serializerProphecy->willImplement(DenormalizerInterface::class);
209+
210+
$normalizer = new ItemNormalizer(
211+
$propertyNameCollectionFactoryProphecy->reveal(),
212+
$propertyMetadataFactoryProphecy->reveal(),
213+
$iriConverterProphecy->reveal(),
214+
$resourceClassResolverProphecy->reveal()
215+
);
216+
$normalizer->setSerializer($serializerProphecy->reveal());
217+
218+
$object = $normalizer->denormalize(['id' => '42', 'name' => 'hello'], Dummy::class, null, $context);
219+
$this->assertInstanceOf(Dummy::class, $object);
220+
$this->assertSame('42', $object->getId());
221+
$this->assertSame('hello', $object->getName());
222+
}
189223
}

0 commit comments

Comments
 (0)