Skip to content

Commit 364538b

Browse files
authored
Fix #4024 identifiers with multiple classes (#4029)
1 parent 5df77ad commit 364538b

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed

src/DataProvider/OperationDataProviderTrait.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use ApiPlatform\Core\Exception\InvalidIdentifierException;
1717
use ApiPlatform\Core\Exception\RuntimeException;
1818
use ApiPlatform\Core\Identifier\CompositeIdentifierParser;
19+
use ApiPlatform\Core\Identifier\ContextAwareIdentifierConverterInterface;
1920
use ApiPlatform\Core\Identifier\IdentifierConverterInterface;
2021

2122
/**
@@ -106,7 +107,7 @@ private function extractIdentifiers(array $parameters, array $attributes)
106107
throw new InvalidIdentifierException(sprintf('Expected %d identifiers, got %d', $identifiersNumber, $currentIdentifiersNumber));
107108
}
108109

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

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

124+
if ($this->identifierConverter instanceof ContextAwareIdentifierConverterInterface) {
125+
return $this->identifierConverter->convert($identifiers, $attributes['resource_class'], ['identifiers' => $identifiersKeys]);
126+
}
127+
123128
return $this->identifierConverter->convert($identifiers, $attributes['resource_class']);
124129
}
125130
}

src/Identifier/IdentifierConverter.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,9 @@ public function convert($data, string $class, array $context = []): array
5656
}
5757

5858
$identifiers = $data;
59-
foreach ($data as $identifier => $value) {
60-
if (null === $type = $this->getIdentifierType($class, $identifier)) {
59+
60+
foreach ($data as $parameter => $value) {
61+
if (null === $type = $this->getIdentifierType($context['identifiers'][$parameter][0] ?? $class, $context['identifiers'][$parameter][1] ?? $parameter)) {
6162
continue;
6263
}
6364

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

7071
try {
71-
$identifiers[$identifier] = $identifierTransformer->denormalize($value, $type);
72+
$identifiers[$parameter] = $identifierTransformer->denormalize($value, $type);
7273
break;
7374
} catch (InvalidIdentifierException $e) {
74-
throw new InvalidIdentifierException(sprintf('Identifier "%s" could not be denormalized.', $identifier), $e->getCode(), $e);
75+
throw new InvalidIdentifierException(sprintf('Identifier "%s" could not be denormalized.', $parameter), $e->getCode(), $e);
7576
}
7677
}
7778
}

tests/Identifier/IdentifierConverterTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,27 @@ public function testShouldBreakAfterTransforming()
121121

122122
$this->assertSame(['id' => 42], $identifierDenormalizer->convert($identifier, $class));
123123
}
124+
125+
public function testWithContextAndMultipleIdentifiers()
126+
{
127+
$identifier = ['id' => '42', 'book' => '21'];
128+
129+
$integerIdentifierPropertyMetadata = (new PropertyMetadata())->withIdentifier(true)->withType(new Type(Type::BUILTIN_TYPE_INT));
130+
131+
$propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class);
132+
$propertyMetadataFactory->create('Author', 'id')->shouldBeCalled()->willReturn($integerIdentifierPropertyMetadata);
133+
$propertyMetadataFactory->create('Book', 'id')->shouldBeCalled()->willReturn($integerIdentifierPropertyMetadata);
134+
135+
$identifiersExtractor = $this->prophesize(IdentifiersExtractorInterface::class);
136+
$identifiersExtractor->getIdentifiersFromResourceClass('Book')->willReturn(['id']);
137+
$identifiersExtractor->getIdentifiersFromResourceClass('Author')->willReturn(['id']);
138+
139+
$shouldNotBeCalled = $this->prophesize(DenormalizerInterface::class);
140+
$shouldNotBeCalled->supportsDenormalization()->shouldNotBeCalled();
141+
142+
$identifierDenormalizers = [new IntegerDenormalizer(), $shouldNotBeCalled->reveal()];
143+
$identifierDenormalizer = new IdentifierConverter($identifiersExtractor->reveal(), $propertyMetadataFactory->reveal(), $identifierDenormalizers);
144+
145+
$this->assertSame(['id' => 42, 'book' => 21], $identifierDenormalizer->convert($identifier, 'Book', ['identifiers' => ['id' => ['Author', 'id'], 'book' => ['Book', 'id']]]));
146+
}
124147
}

0 commit comments

Comments
 (0)