Skip to content

Commit a59fbee

Browse files
authored
fix(serializer): uriTemplate wrong cache usage in hal format (#6313)
* add failing test * prevent components caching between different subresources * fix tests for MongoDB
1 parent 195ff52 commit a59fbee

8 files changed

+232
-6
lines changed

features/hal/collection_uri_template.feature

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,33 @@ Feature: Exposing a property being a collection of resources
3636
"_links": {
3737
"self": {
3838
"href": "/property_collection_iri_only_relations/1"
39+
},
40+
"children": {
41+
"href": "/property_collection_iri_only_relations/1/children"
3942
}
4043
},
41-
"name": "asb"
44+
"name": "asb1"
45+
},
46+
{
47+
"_links": {
48+
"self": {
49+
"href": "/property_collection_iri_only_relations/2"
50+
},
51+
"children": {
52+
"href": "/property_collection_iri_only_relations/2/children"
53+
}
54+
},
55+
"name": "asb2"
4256
}
4357
],
4458
"iterableIri": [
4559
{
4660
"_links": {
4761
"self": {
4862
"href": "/property_collection_iri_only_relations/9999"
63+
},
64+
"children": {
65+
"href": "/property_collection_iri_only_relations/9999/children"
4966
}
5067
},
5168
"name": "Michel"

features/jsonapi/collection_uri_template.feature

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ Feature: Exposing a property being a collection of resources
3333
{
3434
"type": "PropertyCollectionIriOnlyRelation",
3535
"id": "/property_collection_iri_only_relations/1"
36+
},
37+
{
38+
"type": "PropertyCollectionIriOnlyRelation",
39+
"id": "/property_collection_iri_only_relations/2"
3640
}
3741
]
3842
},

src/Hal/Serializer/ItemNormalizer.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ private function getComponents(object $object, ?string $format, array $context):
184184

185185
$relation['iri'] = $this->iriConverter->getIriFromResource($object, UrlGeneratorInterface::ABS_PATH, $operation, $childContext);
186186
$relation['operation'] = $operation;
187+
$cacheKey = null;
187188
}
188189

189190
if ($propertyMetadata->isReadableLink()) {
@@ -200,7 +201,7 @@ private function getComponents(object $object, ?string $format, array $context):
200201
}
201202
}
202203

203-
if (false !== $context['cache_key']) {
204+
if ($cacheKey && false !== $context['cache_key']) {
204205
$this->componentsCache[$cacheKey] = $components;
205206
}
206207

tests/Behat/DoctrineContext.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1993,18 +1993,23 @@ public function thereAreIriOnlyDummies(int $nb): void
19931993
*/
19941994
public function thereAreResourcesWithPropertyUriTemplates(): void
19951995
{
1996-
$propertyCollectionIriOnlyRelation = $this->isOrm() ? new PropertyCollectionIriOnlyRelation() : new PropertyCollectionIriOnlyRelationDocument();
1997-
$propertyCollectionIriOnlyRelation->name = 'asb';
1996+
$propertyCollectionIriOnlyRelation1 = $this->isOrm() ? new PropertyCollectionIriOnlyRelation() : new PropertyCollectionIriOnlyRelationDocument();
1997+
$propertyCollectionIriOnlyRelation1->name = 'asb1';
1998+
1999+
$propertyCollectionIriOnlyRelation2 = $this->isOrm() ? new PropertyCollectionIriOnlyRelation() : new PropertyCollectionIriOnlyRelationDocument();
2000+
$propertyCollectionIriOnlyRelation2->name = 'asb2';
19982001

19992002
$propertyToOneRelation = $this->isOrm() ? new PropertyUriTemplateOneToOneRelation() : new PropertyUriTemplateOneToOneRelationDocument();
20002003
$propertyToOneRelation->name = 'xarguš';
20012004

20022005
$propertyCollectionIriOnly = $this->isOrm() ? new PropertyCollectionIriOnly() : new PropertyCollectionIriOnlyDocument();
2003-
$propertyCollectionIriOnly->addPropertyCollectionIriOnlyRelation($propertyCollectionIriOnlyRelation);
2006+
$propertyCollectionIriOnly->addPropertyCollectionIriOnlyRelation($propertyCollectionIriOnlyRelation1);
2007+
$propertyCollectionIriOnly->addPropertyCollectionIriOnlyRelation($propertyCollectionIriOnlyRelation2);
20042008
$propertyCollectionIriOnly->setToOneRelation($propertyToOneRelation);
20052009

20062010
$this->manager->persist($propertyCollectionIriOnly);
2007-
$this->manager->persist($propertyCollectionIriOnlyRelation);
2011+
$this->manager->persist($propertyCollectionIriOnlyRelation1);
2012+
$this->manager->persist($propertyCollectionIriOnlyRelation2);
20082013
$this->manager->persist($propertyToOneRelation);
20092014
$this->manager->flush();
20102015
}

tests/Fixtures/TestBundle/Document/PropertyCollectionIriOnlyRelation.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@
1313

1414
namespace ApiPlatform\Tests\Fixtures\TestBundle\Document;
1515

16+
use ApiPlatform\Metadata\ApiProperty;
1617
use ApiPlatform\Metadata\GetCollection;
1718
use ApiPlatform\Metadata\Link;
1819
use ApiPlatform\Metadata\Post;
20+
use Doctrine\Common\Collections\ArrayCollection;
21+
use Doctrine\Common\Collections\Collection;
1922
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
2023
use Symfony\Component\Serializer\Annotation\Groups;
2124

@@ -42,6 +45,16 @@ class PropertyCollectionIriOnlyRelation
4245
#[ODM\ReferenceOne(targetDocument: PropertyCollectionIriOnly::class)]
4346
private ?PropertyCollectionIriOnly $propertyCollectionIriOnly = null;
4447

48+
#[ODM\ReferenceMany(targetDocument: PropertyCollectionIriOnlyRelationSecondLevel::class)]
49+
#[ApiProperty(uriTemplate: '/property_collection_iri_only_relations/{parentId}/children')]
50+
#[Groups('read')]
51+
private Collection $children;
52+
53+
public function __construct()
54+
{
55+
$this->children = new ArrayCollection();
56+
}
57+
4558
public function getId(): ?int
4659
{
4760
return $this->id ?? 9999;
@@ -56,4 +69,34 @@ public function setPropertyCollectionIriOnly(?PropertyCollectionIriOnly $propert
5669
{
5770
$this->propertyCollectionIriOnly = $propertyCollectionIriOnly;
5871
}
72+
73+
/**
74+
* @return Collection<int, PropertyCollectionIriOnlyRelationSecondLevel>
75+
*/
76+
public function getChildren(): Collection
77+
{
78+
return $this->children;
79+
}
80+
81+
public function addChild(PropertyCollectionIriOnlyRelationSecondLevel $child): self
82+
{
83+
if (!$this->children->contains($child)) {
84+
$this->children->add($child);
85+
$child->setParent($this);
86+
}
87+
88+
return $this;
89+
}
90+
91+
public function removeChild(PropertyCollectionIriOnlyRelationSecondLevel $child): self
92+
{
93+
if ($this->children->removeElement($child)) {
94+
// set the owning side to null (unless already changed)
95+
if ($child->getParent() === $this) {
96+
$child->setParent(null);
97+
}
98+
}
99+
100+
return $this;
101+
}
59102
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\Document;
15+
16+
use ApiPlatform\Metadata\GetCollection;
17+
use ApiPlatform\Metadata\Link;
18+
use ApiPlatform\Metadata\Post;
19+
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
20+
21+
#[
22+
Post,
23+
GetCollection(uriTemplate: '/property-collection-relation-second-levels'),
24+
GetCollection(
25+
uriTemplate: '/property_collection_iri_only_relations/{parentId}/children',
26+
uriVariables: [
27+
'parentId' => new Link(toProperty: 'parent', fromClass: PropertyCollectionIriOnlyRelation::class),
28+
]
29+
)
30+
]
31+
#[ODM\Document]
32+
class PropertyCollectionIriOnlyRelationSecondLevel
33+
{
34+
#[ODM\Id(strategy: 'INCREMENT', type: 'int')]
35+
private ?int $id = null;
36+
37+
#[ODM\ReferenceOne(targetDocument: PropertyCollectionIriOnlyRelation::class)]
38+
private ?PropertyCollectionIriOnlyRelation $parent = null;
39+
40+
public function getId(): ?int
41+
{
42+
return $this->id ?? 9999;
43+
}
44+
45+
public function getParent(): ?PropertyCollectionIriOnlyRelation
46+
{
47+
return $this->parent;
48+
}
49+
50+
public function setParent(?PropertyCollectionIriOnlyRelation $parent): void
51+
{
52+
$this->parent = $parent;
53+
}
54+
}

tests/Fixtures/TestBundle/Entity/PropertyCollectionIriOnlyRelation.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@
1313

1414
namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity;
1515

16+
use ApiPlatform\Metadata\ApiProperty;
1617
use ApiPlatform\Metadata\GetCollection;
1718
use ApiPlatform\Metadata\Link;
1819
use ApiPlatform\Metadata\Post;
20+
use Doctrine\Common\Collections\ArrayCollection;
21+
use Doctrine\Common\Collections\Collection;
1922
use Doctrine\ORM\Mapping as ORM;
2023
use Symfony\Component\Serializer\Annotation\Groups;
2124
use Symfony\Component\Validator\Constraints\NotBlank;
@@ -49,6 +52,16 @@ class PropertyCollectionIriOnlyRelation
4952
#[ORM\ManyToOne(inversedBy: 'propertyCollectionIriOnlyRelation')]
5053
private ?PropertyCollectionIriOnly $propertyCollectionIriOnly = null;
5154

55+
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: PropertyCollectionIriOnlyRelationSecondLevel::class)]
56+
#[ApiProperty(uriTemplate: '/property_collection_iri_only_relations/{parentId}/children')]
57+
#[Groups('read')]
58+
private Collection $children;
59+
60+
public function __construct()
61+
{
62+
$this->children = new ArrayCollection();
63+
}
64+
5265
public function getId(): ?int
5366
{
5467
return $this->id ?? 9999;
@@ -63,4 +76,34 @@ public function setPropertyCollectionIriOnly(?PropertyCollectionIriOnly $propert
6376
{
6477
$this->propertyCollectionIriOnly = $propertyCollectionIriOnly;
6578
}
79+
80+
/**
81+
* @return Collection<int, PropertyCollectionIriOnlyRelationSecondLevel>
82+
*/
83+
public function getChildren(): Collection
84+
{
85+
return $this->children;
86+
}
87+
88+
public function addChild(PropertyCollectionIriOnlyRelationSecondLevel $child): self
89+
{
90+
if (!$this->children->contains($child)) {
91+
$this->children->add($child);
92+
$child->setParent($this);
93+
}
94+
95+
return $this;
96+
}
97+
98+
public function removeChild(PropertyCollectionIriOnlyRelationSecondLevel $child): self
99+
{
100+
if ($this->children->removeElement($child)) {
101+
// set the owning side to null (unless already changed)
102+
if ($child->getParent() === $this) {
103+
$child->setParent(null);
104+
}
105+
}
106+
107+
return $this;
108+
}
66109
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity;
15+
16+
use ApiPlatform\Metadata\GetCollection;
17+
use ApiPlatform\Metadata\Link;
18+
use ApiPlatform\Metadata\Post;
19+
use Doctrine\ORM\Mapping as ORM;
20+
21+
#[
22+
Post,
23+
GetCollection(uriTemplate: '/property-collection-relation-second-levels'),
24+
GetCollection(
25+
uriTemplate: '/property_collection_iri_only_relations/{parentId}/children',
26+
uriVariables: [
27+
'parentId' => new Link(toProperty: 'parent', fromClass: PropertyCollectionIriOnlyRelation::class),
28+
]
29+
)
30+
]
31+
#[ORM\Entity]
32+
class PropertyCollectionIriOnlyRelationSecondLevel
33+
{
34+
/**
35+
* The entity ID.
36+
*/
37+
#[ORM\Id]
38+
#[ORM\Column(type: 'integer')]
39+
#[ORM\GeneratedValue]
40+
private ?int $id = null;
41+
42+
#[ORM\ManyToOne(inversedBy: 'children')]
43+
private ?PropertyCollectionIriOnlyRelation $parent = null;
44+
45+
public function getId(): ?int
46+
{
47+
return $this->id ?? 9999;
48+
}
49+
50+
public function getParent(): ?PropertyCollectionIriOnlyRelation
51+
{
52+
return $this->parent;
53+
}
54+
55+
public function setParent(?PropertyCollectionIriOnlyRelation $parent): void
56+
{
57+
$this->parent = $parent;
58+
}
59+
}

0 commit comments

Comments
 (0)