Skip to content

Commit 8535f9d

Browse files
auracadveris-aadam
andauthored
fix(doctrine): read parent class properties on PUT (#6176)
* fix(doctrine): PersistProcessor on PUT operation Recursively get reflectionProperties to allow modifications on parent properties * added tests --------- Co-authored-by: Aurélien ADAM <[email protected]>
1 parent 5e4b631 commit 8535f9d

File tree

5 files changed

+116
-4
lines changed

5 files changed

+116
-4
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Feature: Update properties of a resource that are inherited with standard PUT operation
2+
3+
@!mongodb
4+
@createSchema
5+
Scenario: Update properties of a resource that are inherited with standard PUT operation
6+
Given there is a dummy entity with a mapped superclass
7+
When I add "Content-Type" header equal to "application/ld+json"
8+
And I send a "PUT" request to "/dummy_mapped_subclasses/1" with body:
9+
"""
10+
{
11+
"foo": "updated value"
12+
}
13+
"""
14+
Then the response status code should be 200
15+
And the response should be in JSON
16+
And the JSON should be equal to:
17+
"""
18+
{
19+
"@context": "/contexts/DummyMappedSubclass",
20+
"@id": "/dummy_mapped_subclasses/1",
21+
"@type": "DummyMappedSubclass",
22+
"id": 1,
23+
"foo": "updated value"
24+
}
25+
"""

src/Doctrine/Common/State/PersistProcessor.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,15 @@ private function isDeferredExplicit(DoctrineObjectManager $manager, $data): bool
128128
private function getReflectionProperties(mixed $data): array
129129
{
130130
$ret = [];
131-
$props = (new \ReflectionObject($data))->getProperties(~\ReflectionProperty::IS_STATIC);
131+
$r = new \ReflectionObject($data);
132132

133-
foreach ($props as $prop) {
134-
$ret[$prop->getName()] = $prop;
135-
}
133+
do {
134+
$props = $r->getProperties(~\ReflectionProperty::IS_STATIC);
135+
136+
foreach ($props as $prop) {
137+
$ret[$prop->getName()] = $prop;
138+
}
139+
} while ($r = $r->getParentClass());
136140

137141
return $ret;
138142
}

tests/Behat/DoctrineContext.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@
129129
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyFriend;
130130
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyGroup;
131131
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyImmutableDate;
132+
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyMappedSubclass;
132133
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyMercure;
133134
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyOffer;
134135
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPassenger;
@@ -2259,6 +2260,16 @@ public function thereAreAFewLinkHandledDummies(): void
22592260
$this->manager->flush();
22602261
}
22612262

2263+
/**
2264+
* @Given there is a dummy entity with a mapped superclass
2265+
*/
2266+
public function thereIsADummyEntityWithAMappedSuperclass(): void
2267+
{
2268+
$entity = new DummyMappedSubclass();
2269+
$this->manager->persist($entity);
2270+
$this->manager->flush();
2271+
}
2272+
22622273
private function isOrm(): bool
22632274
{
22642275
return null !== $this->schemaTool;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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\Put;
17+
use Doctrine\ORM\Mapping as ORM;
18+
19+
#[ORM\Entity]
20+
#[Put(
21+
extraProperties: [
22+
'standard_put' => true,
23+
],
24+
allowCreate: true
25+
)]
26+
class DummyMappedSubclass extends DummyMappedSuperclass
27+
{
28+
#[ORM\Id]
29+
#[ORM\GeneratedValue]
30+
#[ORM\Column]
31+
private ?int $id = null;
32+
33+
public function getId(): ?int
34+
{
35+
return $this->id;
36+
}
37+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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 Doctrine\ORM\Mapping as ORM;
17+
18+
#[ORM\MappedSuperclass]
19+
class DummyMappedSuperclass
20+
{
21+
#[ORM\Column(length: 255, nullable: true)]
22+
private ?string $foo = null;
23+
24+
public function getFoo(): ?string
25+
{
26+
return $this->foo;
27+
}
28+
29+
public function setFoo(?string $foo): static
30+
{
31+
$this->foo = $foo;
32+
33+
return $this;
34+
}
35+
}

0 commit comments

Comments
 (0)