Skip to content

Commit 0b82379

Browse files
authored
fix(state): object mapper with input different (#7435)
1 parent d979f95 commit 0b82379

File tree

4 files changed

+104
-6
lines changed

4 files changed

+104
-6
lines changed

src/State/Processor/ObjectMapperProcessor.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,12 @@ public function __construct(
3535

3636
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): object|array|null
3737
{
38-
if (!$this->objectMapper || !$operation->canWrite()) {
39-
return $this->decorated->process($data, $operation, $uriVariables, $context);
40-
}
41-
42-
if (!(new \ReflectionClass($operation->getClass()))->getAttributes(Map::class)) {
38+
if (
39+
!$this->objectMapper
40+
|| !$operation->canWrite()
41+
|| !is_a($data, $operation->getClass(), true)
42+
|| !(new \ReflectionClass($operation->getClass()))->getAttributes(Map::class)
43+
) {
4344
return $this->decorated->process($data, $operation, $uriVariables, $context);
4445
}
4546

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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\ApiResource;
15+
16+
use ApiPlatform\Doctrine\Orm\State\Options;
17+
use ApiPlatform\JsonLd\ContextBuilder;
18+
use ApiPlatform\Metadata\Operation;
19+
use ApiPlatform\Metadata\Post;
20+
use ApiPlatform\Tests\Fixtures\TestBundle\Dto\MappedResouceInput;
21+
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\MappedEntity;
22+
use Symfony\Component\ObjectMapper\Attribute\Map;
23+
24+
#[Post(
25+
uriTemplate: '/mapped_resource_with_input',
26+
input: MappedResouceInput::class,
27+
stateOptions: new Options(entityClass: MappedEntity::class),
28+
normalizationContext: [ContextBuilder::HYDRA_CONTEXT_HAS_PREFIX => false],
29+
processor: [self::class, 'process']
30+
)]
31+
#[Map(target: MappedEntity::class)]
32+
final class MappedResourceWithInput
33+
{
34+
#[Map(if: false)]
35+
public ?string $id = null;
36+
public string $username;
37+
38+
public static function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = [])
39+
{
40+
$s = new self();
41+
$s->id = $data->id;
42+
$s->username = $data->name;
43+
44+
return $s;
45+
}
46+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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\Dto;
15+
16+
class MappedResouceInput
17+
{
18+
public string $id;
19+
public string $name;
20+
}

tests/Functional/MappingTest.php

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\FirstResource;
1818
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\MappedResource;
1919
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\MappedResourceOdm;
20+
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\MappedResourceWithInput;
2021
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\MappedResourceWithRelation;
2122
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\MappedResourceWithRelationRelated;
2223
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\SecondResource;
@@ -40,7 +41,15 @@ final class MappingTest extends ApiTestCase
4041
*/
4142
public static function getResources(): array
4243
{
43-
return [MappedResource::class, MappedResourceOdm::class, FirstResource::class, SecondResource::class, MappedResourceWithRelation::class, MappedResourceWithRelationRelated::class];
44+
return [
45+
MappedResource::class,
46+
MappedResourceOdm::class,
47+
FirstResource::class,
48+
SecondResource::class,
49+
MappedResourceWithRelation::class,
50+
MappedResourceWithRelationRelated::class,
51+
MappedResourceWithInput::class,
52+
];
4453
}
4554

4655
public function testShouldMapBetweenResourceAndEntity(): void
@@ -136,6 +145,28 @@ public function testMapPutAllowCreate(): void
136145
]);
137146
}
138147

148+
public function testShouldNotMapWhenInput(): void
149+
{
150+
if (!$this->getContainer()->has('api_platform.object_mapper')) {
151+
$this->markTestSkipped('ObjectMapper not installed');
152+
}
153+
154+
if ($this->isMongoDB()) {
155+
$this->markTestSkipped('MongoDB not tested');
156+
}
157+
158+
$this->recreateSchema([MappedEntity::class]);
159+
$this->loadFixtures();
160+
$r = self::createClient()->request('POST', 'mapped_resource_with_input', [
161+
'headers' => [
162+
'content-type' => 'application/ld+json',
163+
],
164+
'json' => ['name' => 'test', 'id' => '1'],
165+
]);
166+
167+
$this->assertJsonContains(['username' => 'test']);
168+
}
169+
139170
private function loadFixtures(): void
140171
{
141172
$manager = $this->getManager();

0 commit comments

Comments
 (0)