Skip to content

Commit

Permalink
Merge 9512d40 into 8a00d6e
Browse files Browse the repository at this point in the history
  • Loading branch information
soyuka committed Feb 6, 2021
2 parents 8a00d6e + 9512d40 commit 230be36
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 17 deletions.
4 changes: 2 additions & 2 deletions src/DataProvider/OperationDataProviderTrait.php
Expand Up @@ -106,7 +106,7 @@ private function extractIdentifiers(array $parameters, array $attributes)
throw new InvalidIdentifierException(sprintf('Expected %d identifiers, got %d', $identifiersNumber, $currentIdentifiersNumber));
}

return $this->identifierConverter->convert($identifiers, $attributes['resource_class']);
return $this->identifierConverter->convert($identifiers, $identifiedBy[0]);
}

// TODO: Subresources tuple may have a third item representing if it is a "collection", this behavior will be removed in 3.0
Expand All @@ -120,6 +120,6 @@ private function extractIdentifiers(array $parameters, array $attributes)
$identifiers[$parameterName] = $parameters[$parameterName];
}

return $this->identifierConverter->convert($identifiers, $attributes['resource_class']);
return $this->identifierConverter->convert($identifiers, $attributes['resource_class'], ['identifiers' => $identifiersKeys]);
}
}
9 changes: 5 additions & 4 deletions src/Identifier/IdentifierConverter.php
Expand Up @@ -56,8 +56,9 @@ public function convert($data, string $class, array $context = []): array
}

$identifiers = $data;
foreach ($data as $identifier => $value) {
if (null === $type = $this->getIdentifierType($class, $identifier)) {

foreach ($data as $parameter => $value) {
if (null === $type = $this->getIdentifierType($context['identifiers'][$parameter][0] ?? $class, $context['identifiers'][$parameter][1] ?? $parameter)) {
continue;
}

Expand All @@ -68,10 +69,10 @@ public function convert($data, string $class, array $context = []): array
}

try {
$identifiers[$identifier] = $identifierTransformer->denormalize($value, $type);
$identifiers[$parameter] = $identifierTransformer->denormalize($value, $type);
break;
} catch (InvalidIdentifierException $e) {
throw new InvalidIdentifierException(sprintf('Identifier "%s" could not be denormalized.', $identifier), $e->getCode(), $e);
throw new InvalidIdentifierException(sprintf('Identifier "%s" could not be denormalized.', $parameter), $e->getCode(), $e);
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions tests/Bridge/Symfony/Routing/IriConverterTest.php
Expand Up @@ -267,7 +267,7 @@ public function testGetItemFromIriWithIdentifierConverter()
$itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class);
$itemDataProviderProphecy->getItem(Dummy::class, ['id' => 3], 'get', ['fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true])->shouldBeCalled()->willReturn($item);
$identifierConverterProphecy = $this->prophesize(IdentifierConverterInterface::class);
$identifierConverterProphecy->convert(['id' => '3'], Dummy::class)->shouldBeCalled()->willReturn(['id' => 3]);
$identifierConverterProphecy->convert(['id' => '3'], Dummy::class, ['identifiers' => ['id' => [Dummy::class, 'id']]])->shouldBeCalled()->willReturn(['id' => 3]);
$routerProphecy = $this->prophesize(RouterInterface::class);
$routerProphecy->match('/users/3')->willReturn([
'_api_resource_class' => Dummy::class,
Expand Down Expand Up @@ -315,7 +315,7 @@ public function testGetItemFromIriWithSubresourceDataProviderNotFound()
'id' => 3,
])->shouldBeCalledTimes(1);
$identifierConverterProphecy = $this->prophesize(IdentifierConverterInterface::class);
$identifierConverterProphecy->convert(['id' => '3'], Dummy::class)->shouldBeCalled()->willReturn(['id' => 3]);
$identifierConverterProphecy->convert(['id' => '3'], Dummy::class, ['identifiers' => $subresourceContext['identifiers']])->shouldBeCalled()->willReturn(['id' => 3]);
$subresourceDataProviderProphecy = $this->prophesize(SubresourceDataProviderInterface::class);
$subresourceDataProviderProphecy->getSubresource(Dummy::class, ['id' => ['id' => 3]], $subresourceContext + ['fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true], 'get_subresource')->shouldBeCalled()->willReturn(null);
$converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, $subresourceDataProviderProphecy, $identifierConverterProphecy);
Expand All @@ -337,7 +337,7 @@ public function testGetItemFromIriBadIdentifierException()
'id' => 3,
])->shouldBeCalledTimes(1);
$identifierConverterProphecy = $this->prophesize(IdentifierConverterInterface::class);
$identifierConverterProphecy->convert(['id' => '3'], Dummy::class)->shouldBeCalled()->willThrow(new InvalidIdentifierException('Item not found for "/users/3".'));
$identifierConverterProphecy->convert(['id' => '3'], Dummy::class, Argument::type('array'))->shouldBeCalled()->willThrow(new InvalidIdentifierException('Item not found for "/users/3".'));
$converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, null, $identifierConverterProphecy);
$this->assertEquals($converter->getItemFromIri('/users/3', ['fetch_data' => true]), $item);
}
Expand Down Expand Up @@ -411,7 +411,7 @@ private function getIriConverter($routerProphecy = null, $routeNameResolverProph

if (null === $identifierConverterProphecy) {
$identifierConverterProphecy = $this->prophesize(IdentifierConverterInterface::class);
$identifierConverterProphecy->convert(Argument::type('array'), Argument::type('string'))->will(function ($args) {
$identifierConverterProphecy->convert(Argument::type('array'), Argument::type('string'), Argument::type('array'))->will(function ($args) {
return $args[0];
});
}
Expand Down
14 changes: 7 additions & 7 deletions tests/EventListener/ReadListenerTest.php
Expand Up @@ -188,7 +188,7 @@ public function testRetrieveCollectionGet()
public function testRetrieveItem()
{
$identifierConverter = $this->prophesize(IdentifierConverterInterface::class);
$identifierConverter->convert(['id' => '1'], 'Foo')->shouldBeCalled()->willReturn(['id' => '1']);
$identifierConverter->convert(['id' => '1'], 'Foo', Argument::type('array'))->shouldBeCalled()->willReturn(['id' => '1']);

$collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class);
$collectionDataProvider->getCollection()->shouldNotBeCalled();
Expand Down Expand Up @@ -241,7 +241,7 @@ public function testRetrieveItemNoIdentifier()
public function testRetrieveSubresource()
{
$identifierConverter = $this->prophesize(IdentifierConverterInterface::class);
$identifierConverter->convert(['id' => '1'], 'Foo')->shouldBeCalled()->willReturn(['id' => '1']);
$identifierConverter->convert(['id' => '1'], 'Foo', Argument::type('array'))->shouldBeCalled()->willReturn(['id' => '1']);

$collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class);
$collectionDataProvider->getCollection()->shouldNotBeCalled();
Expand Down Expand Up @@ -271,7 +271,7 @@ public function testRetrieveSubresourceNoDataProvider()
$this->expectException(RuntimeException::class);

$identifierConverter = $this->prophesize(IdentifierConverterInterface::class);
$identifierConverter->convert(['id' => '1'], 'Foo')->shouldBeCalled()->willReturn(['id' => '1']);
$identifierConverter->convert(['id' => '1'], 'Foo', Argument::type('array'))->shouldBeCalled()->willReturn(['id' => '1']);

$collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class);
$collectionDataProvider->getCollection()->shouldNotBeCalled();
Expand All @@ -294,7 +294,7 @@ public function testRetrieveSubresourceNoDataProvider()
public function testRetrieveSubresourceNotFound()
{
$identifierConverter = $this->prophesize(IdentifierConverterInterface::class);
$identifierConverter->convert(['id' => '1'], 'Foo')->willThrow(new InvalidIdentifierException())->shouldBeCalled();
$identifierConverter->convert(['id' => '1'], 'Foo', Argument::type('array'))->willThrow(new InvalidIdentifierException())->shouldBeCalled();
$this->expectException(NotFoundHttpException::class);

$collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class);
Expand All @@ -316,7 +316,7 @@ public function testRetrieveSubresourceNotFound()
public function testRetrieveItemNotFound()
{
$identifierConverter = $this->prophesize(IdentifierConverterInterface::class);
$identifierConverter->convert(['id' => '22'], 'Foo')->shouldBeCalled()->willReturn(['id' => 22]);
$identifierConverter->convert(['id' => '22'], 'Foo', Argument::type('array'))->shouldBeCalled()->willReturn(['id' => 22]);
$this->expectException(NotFoundHttpException::class);

$collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class);
Expand All @@ -341,7 +341,7 @@ public function testRetrieveBadItemNormalizedIdentifiers()
$this->expectException(NotFoundHttpException::class);

$identifierConverter = $this->prophesize(IdentifierConverterInterface::class);
$identifierConverter->convert(['id' => '1'], 'Foo')->shouldBeCalled()->willThrow(new InvalidIdentifierException());
$identifierConverter->convert(['id' => '1'], 'Foo', Argument::type('array'))->shouldBeCalled()->willThrow(new InvalidIdentifierException());

$collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class);
$itemDataProvider = $this->prophesize(ItemDataProviderInterface::class);
Expand All @@ -362,7 +362,7 @@ public function testRetrieveBadSubresourceNormalizedIdentifiers()
$this->expectException(NotFoundHttpException::class);

$identifierConverter = $this->prophesize(IdentifierConverterInterface::class);
$identifierConverter->convert(Argument::type('array'), Argument::type('string'))->shouldBeCalled()->willThrow(new InvalidIdentifierException());
$identifierConverter->convert(Argument::type('array'), Argument::type('string'), Argument::type('array'))->shouldBeCalled()->willThrow(new InvalidIdentifierException());

$collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class);
$collectionDataProvider->getCollection()->shouldNotBeCalled();
Expand Down
23 changes: 23 additions & 0 deletions tests/Identifier/IdentifierConverterTest.php
Expand Up @@ -121,4 +121,27 @@ public function testShouldBreakAfterTransforming()

$this->assertSame(['id' => 42], $identifierDenormalizer->convert($identifier, $class));
}

public function testWithContextAndMultipleIdentifiers()
{
$identifier = ['id' => '42', 'book' => '21'];

$integerIdentifierPropertyMetadata = (new PropertyMetadata())->withIdentifier(true)->withType(new Type(Type::BUILTIN_TYPE_INT));

$propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class);
$propertyMetadataFactory->create('Author', 'id')->shouldBeCalled()->willReturn($integerIdentifierPropertyMetadata);
$propertyMetadataFactory->create('Book', 'id')->shouldBeCalled()->willReturn($integerIdentifierPropertyMetadata);

$identifiersExtractor = $this->prophesize(IdentifiersExtractorInterface::class);
$identifiersExtractor->getIdentifiersFromResourceClass('Book')->willReturn(['id']);
$identifiersExtractor->getIdentifiersFromResourceClass('Author')->willReturn(['id']);

$shouldNotBeCalled = $this->prophesize(DenormalizerInterface::class);
$shouldNotBeCalled->supportsDenormalization()->shouldNotBeCalled();

$identifierDenormalizers = [new IntegerDenormalizer(), $shouldNotBeCalled->reveal()];
$identifierDenormalizer = new IdentifierConverter($identifiersExtractor->reveal(), $propertyMetadataFactory->reveal(), $identifierDenormalizers);

$this->assertSame(['id' => 42, 'book' => 21], $identifierDenormalizer->convert($identifier, 'Book', ['identifiers' => ['id' => ['Author', 'id'], 'book' => ['Book', 'id']]]));
}
}

0 comments on commit 230be36

Please sign in to comment.