Skip to content

Commit 63716ce

Browse files
authored
Merge pull request #2536 from bendavies/demormalize-plain-identifier-relations-correctly
fix error case when denormalizing relations with plain identifiers.
2 parents 8909336 + 89947c9 commit 63716ce

File tree

2 files changed

+64
-7
lines changed

2 files changed

+64
-7
lines changed

src/Serializer/AbstractItemNormalizer.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -436,13 +436,12 @@ protected function denormalizeRelation(string $attributeName, PropertyMetadata $
436436
if (!\is_array($value)) {
437437
// repeat the code so that IRIs keep working with the json format
438438
if (true === $this->allowPlainIdentifiers && $this->itemDataProvider) {
439-
try {
440-
return $this->itemDataProvider->getItem($className, $value, null, $context + ['fetch_data' => true]);
441-
} catch (ItemNotFoundException $e) {
442-
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
443-
} catch (InvalidArgumentException $e) {
444-
// Give a chance to other normalizers (e.g.: DateTimeNormalizer)
439+
$item = $this->itemDataProvider->getItem($className, $value, null, $context + ['fetch_data' => true]);
440+
if (null === $item) {
441+
throw new ItemNotFoundException(sprintf('Item not found for "%s".', $value));
445442
}
443+
444+
return $item;
446445
}
447446

448447
throw new InvalidArgumentException(sprintf(

tests/Serializer/AbstractItemNormalizerTest.php

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
1919
use ApiPlatform\Core\DataTransformer\DataTransformerInterface;
2020
use ApiPlatform\Core\Exception\InvalidArgumentException;
21+
use ApiPlatform\Core\Exception\ItemNotFoundException;
2122
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
2223
use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
2324
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
@@ -822,6 +823,63 @@ public function testChildInheritedProperty()
822823

823824
public function testDenormalizeRelationWithPlainId()
824825
{
826+
$relatedDummy = new RelatedDummy();
827+
828+
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
829+
$propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn(
830+
new PropertyNameCollection(['relatedDummy'])
831+
)->shouldBeCalled();
832+
833+
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
834+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', [])->willReturn(
835+
new PropertyMetadata(
836+
new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class),
837+
'',
838+
false,
839+
true,
840+
false,
841+
false
842+
)
843+
)->shouldBeCalled();
844+
845+
$iriConverterProphecy = $this->prophesize(IriConverterInterface::class);
846+
$propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class);
847+
$propertyAccessorProphecy->setValue(Argument::type(Dummy::class), 'relatedDummy', $relatedDummy)->shouldBeCalled();
848+
849+
$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
850+
$resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true)->shouldBeCalled();
851+
852+
$serializerProphecy = $this->prophesize(SerializerInterface::class);
853+
$serializerProphecy->willImplement(DenormalizerInterface::class);
854+
855+
$itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class);
856+
$itemDataProviderProphecy->getItem(RelatedDummy::class, 1, null, Argument::type('array'))->willReturn($relatedDummy)->shouldBeCalled();
857+
858+
$normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [
859+
$propertyNameCollectionFactoryProphecy->reveal(),
860+
$propertyMetadataFactoryProphecy->reveal(),
861+
$iriConverterProphecy->reveal(),
862+
$resourceClassResolverProphecy->reveal(),
863+
$propertyAccessorProphecy->reveal(),
864+
null,
865+
null,
866+
$itemDataProviderProphecy->reveal(),
867+
true,
868+
[],
869+
null,
870+
null,
871+
true,
872+
]);
873+
$normalizer->setSerializer($serializerProphecy->reveal());
874+
875+
$normalizer->denormalize(['relatedDummy' => 1], Dummy::class, 'jsonld');
876+
}
877+
878+
public function testDenormalizeRelationWithPlainIdNotFound()
879+
{
880+
$this->expectException(ItemNotFoundException::class);
881+
$this->expectExceptionMessage('Item not found for "1".');
882+
825883
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
826884
$propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn(
827885
new PropertyNameCollection(['relatedDummy'])
@@ -849,7 +907,7 @@ public function testDenormalizeRelationWithPlainId()
849907
$serializerProphecy->willImplement(DenormalizerInterface::class);
850908

851909
$itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class);
852-
$itemDataProviderProphecy->getItem(RelatedDummy::class, 1, null, Argument::type('array'))->shouldBeCalled();
910+
$itemDataProviderProphecy->getItem(RelatedDummy::class, 1, null, Argument::type('array'))->willReturn(null)->shouldBeCalled();
853911

854912
$normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [
855913
$propertyNameCollectionFactoryProphecy->reveal(),

0 commit comments

Comments
 (0)