Skip to content

Commit e9333c5

Browse files
committed
fix(jsonld): read identifier with itemUriTemplate
1 parent 0edbc37 commit e9333c5

File tree

2 files changed

+57
-4
lines changed

2 files changed

+57
-4
lines changed

src/Metadata/IdentifiersExtractor.php

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ public function getIdentifiersFromItem(object $item, ?Operation $operation = nul
6262
return $this->getIdentifiersFromOperation($item, $operation, $context);
6363
}
6464

65+
/**
66+
* @param array<string, mixed> $context
67+
*/
6568
private function getIdentifiersFromOperation(object $item, Operation $operation, array $context = []): array
6669
{
6770
if ($operation instanceof HttpOperation) {
@@ -75,24 +78,26 @@ private function getIdentifiersFromOperation(object $item, Operation $operation,
7578
if (1 < (is_countable($link->getIdentifiers()) ? \count($link->getIdentifiers()) : 0)) {
7679
$compositeIdentifiers = [];
7780
foreach ($link->getIdentifiers() as $identifier) {
78-
$compositeIdentifiers[$identifier] = $this->getIdentifierValue($item, $link->getFromClass() ?? $operation->getClass(), $identifier, $link->getParameterName());
81+
$compositeIdentifiers[$identifier] = $this->getIdentifierValue($item, $link->getFromClass() ?? $operation->getClass(), $identifier, $link->getParameterName(), null, $context, $operation);
7982
}
8083

8184
$identifiers[$link->getParameterName()] = CompositeIdentifierParser::stringify($compositeIdentifiers);
8285
continue;
8386
}
8487

8588
$parameterName = $link->getParameterName();
86-
$identifiers[$parameterName] = $this->getIdentifierValue($item, $link->getFromClass() ?? $operation->getClass(), $link->getIdentifiers()[0] ?? $k, $parameterName, $link->getToProperty());
89+
$identifiers[$parameterName] = $this->getIdentifierValue($item, $link->getFromClass() ?? $operation->getClass(), $link->getIdentifiers()[0] ?? $k, $parameterName, $link->getToProperty(), $context, $operation);
8790
}
8891

8992
return $identifiers;
9093
}
9194

9295
/**
9396
* Gets the value of the given class property.
97+
*
98+
* @param array<string, mixed> $context
9499
*/
95-
private function getIdentifierValue(object $item, string $class, string $property, string $parameterName, ?string $toProperty = null): float|bool|int|string
100+
private function getIdentifierValue(object $item, string $class, string $property, string $parameterName, ?string $toProperty, array $context, Operation $operation): float|bool|int|string
96101
{
97102
if ($item instanceof $class) {
98103
try {
@@ -102,6 +107,15 @@ private function getIdentifierValue(object $item, string $class, string $propert
102107
}
103108
}
104109

110+
// ItemUriTemplate is defined on a collection and we read the identifier alghough the PHP class may be different
111+
if (isset($context['item_uri_template']) && $operation->getClass() === $class) {
112+
try {
113+
return $this->resolveIdentifierValue($this->propertyAccessor->getValue($item, $property), $parameterName);
114+
} catch (NoSuchPropertyException $e) {
115+
throw new RuntimeException(\sprintf('Could not retrieve identifier "%s" for class "%s" using itemUriTemplate "%s". Check that the property exists and is accessible.', $property, $class, $context['item_uri_template']), $e->getCode(), $e);
116+
}
117+
}
118+
105119
if ($toProperty) {
106120
return $this->resolveIdentifierValue($this->propertyAccessor->getValue($item, "$toProperty.$property"), $parameterName);
107121
}

tests/Functional/JsonLdTest.php

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7298\ImageModuleResource;
2323
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7298\PageResource;
2424
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7298\TitleModuleResource;
25+
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\ItemUriTemplateWithCollection\Recipe;
26+
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\ItemUriTemplateWithCollection\RecipeCollection;
2527
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue6465\Bar;
2628
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue6465\Foo;
2729
use ApiPlatform\Tests\SetupClassResourcesTrait;
@@ -39,7 +41,20 @@ class JsonLdTest extends ApiTestCase
3941
*/
4042
public static function getResources(): array
4143
{
42-
return [Foo::class, Bar::class, JsonLdContextOutput::class, GenIdFalse::class, AggregateRating::class, LevelFirst::class, LevelThird::class, PageResource::class, TitleModuleResource::class, ImageModuleResource::class];
44+
return [
45+
Foo::class,
46+
Bar::class,
47+
JsonLdContextOutput::class,
48+
GenIdFalse::class,
49+
AggregateRating::class,
50+
LevelFirst::class,
51+
LevelThird::class,
52+
PageResource::class,
53+
TitleModuleResource::class,
54+
ImageModuleResource::class,
55+
Recipe::class,
56+
RecipeCollection::class,
57+
];
4358
}
4459

4560
/**
@@ -129,6 +144,30 @@ public function testIssue7298(): void
129144
]);
130145
}
131146

147+
public function testItemUriTemplate(): void
148+
{
149+
self::createClient()->request(
150+
'GET',
151+
'/item_uri_template_recipes',
152+
);
153+
$this->assertResponseIsSuccessful();
154+
155+
$this->assertJsonContains([
156+
'member' => [
157+
[
158+
'@type' => 'RecipeCollection',
159+
'@id' => '/item_uri_template_recipes/1',
160+
'name' => 'Dummy Recipe',
161+
],
162+
[
163+
'@type' => 'RecipeCollection',
164+
'@id' => '/item_uri_template_recipes/2',
165+
'name' => 'Dummy Recipe 2',
166+
],
167+
],
168+
]);
169+
}
170+
132171
protected function setUp(): void
133172
{
134173
self::bootKernel();

0 commit comments

Comments
 (0)