Skip to content

Commit db7da59

Browse files
mtarldsoyuka
authored andcommitted
allow no input data transformer
1 parent 56382ed commit db7da59

File tree

6 files changed

+155
-19
lines changed

6 files changed

+155
-19
lines changed

features/jsonld/input_output.feature

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,3 +354,25 @@ Feature: JSON-LD DTO input and output
354354
Then the response status code should be 400
355355
And the response should be in JSON
356356
And the JSON node "hydra:description" should be equal to "The input data is misformatted."
357+
358+
Scenario: Reset password through an input DTO without DataTransformer
359+
When I send a "POST" request to "/user-reset-password" with body:
360+
"""
361+
{
362+
"email": "[email protected]"
363+
}
364+
"""
365+
Then the response status code should be 201
366+
And the response should be in JSON
367+
And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
368+
And the JSON node "email" should be equal to "[email protected]"
369+
370+
Scenario: Reset password with an invalid payload through an input DTO without DataTransformer
371+
And I send a "POST" request to "/user-reset-password" with body:
372+
"""
373+
{
374+
"email": "this is not an email"
375+
}
376+
"""
377+
Then the response status code should be 422
378+
And the response should be in JSON

src/Serializer/AbstractItemNormalizer.php

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -226,36 +226,42 @@ public function denormalize($data, $class, $format = null, array $context = [])
226226
$normalizedData = is_scalar($data) ? [$data] : $this->prepareForDenormalization($data);
227227
$class = $this->getClassDiscriminatorResolvedClass($normalizedData, $class);
228228
}
229+
229230
$resourceClass = $this->resourceClassResolver->getResourceClass($objectToPopulate, $class);
230231
$context['api_denormalize'] = true;
231232
$context['resource_class'] = $resourceClass;
232233

233-
if (null !== ($inputClass = $this->getInputClass($resourceClass, $context)) && null !== ($dataTransformer = $this->getDataTransformer($data, $resourceClass, $context))) {
234-
$dataTransformerContext = $context;
234+
if (null !== $inputClass = $this->getInputClass($resourceClass, $context)) {
235+
if (null !== $dataTransformer = $this->getDataTransformer($data, $resourceClass, $context)) {
236+
$dataTransformerContext = $context;
235237

236-
unset($context['input']);
237-
unset($context['resource_class']);
238+
unset($context['input']);
239+
unset($context['resource_class']);
238240

239-
if (!$this->serializer instanceof DenormalizerInterface) {
240-
throw new LogicException('Cannot denormalize the input because the injected serializer is not a denormalizer');
241-
}
241+
if (!$this->serializer instanceof DenormalizerInterface) {
242+
throw new LogicException('Cannot denormalize the input because the injected serializer is not a denormalizer');
243+
}
242244

243-
if ($dataTransformer instanceof DataTransformerInitializerInterface) {
244-
$context[AbstractObjectNormalizer::OBJECT_TO_POPULATE] = $dataTransformer->initialize($inputClass, $context);
245-
$context[AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE] = true;
246-
}
245+
if ($dataTransformer instanceof DataTransformerInitializerInterface) {
246+
$context[AbstractObjectNormalizer::OBJECT_TO_POPULATE] = $dataTransformer->initialize($inputClass, $context);
247+
$context[AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE] = true;
248+
}
247249

248-
try {
249-
$denormalizedInput = $this->serializer->denormalize($data, $inputClass, $format, $context);
250-
} catch (NotNormalizableValueException $e) {
251-
throw new UnexpectedValueException('The input data is misformatted.', $e->getCode(), $e);
252-
}
250+
try {
251+
$denormalizedInput = $this->serializer->denormalize($data, $inputClass, $format, $context);
252+
} catch (NotNormalizableValueException $e) {
253+
throw new UnexpectedValueException('The input data is misformatted.', $e->getCode(), $e);
254+
}
255+
256+
if (!\is_object($denormalizedInput)) {
257+
throw new UnexpectedValueException('Expected denormalized input to be an object.');
258+
}
253259

254-
if (!\is_object($denormalizedInput)) {
255-
throw new UnexpectedValueException('Expected denormalized input to be an object.');
260+
return $dataTransformer->transform($denormalizedInput, $resourceClass, $dataTransformerContext);
256261
}
257262

258-
return $dataTransformer->transform($denormalizedInput, $resourceClass, $dataTransformerContext);
263+
$resourceClass = $inputClass;
264+
$context['resource_class'] = $inputClass;
259265
}
260266

261267
$supportsPlainIdentifiers = $this->supportsPlainIdentifiers();
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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\DataPersister;
15+
16+
use ApiPlatform\Core\DataPersister\DataPersisterInterface;
17+
use ApiPlatform\Tests\Fixtures\TestBundle\Dto\UserResetPasswordDto;
18+
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
19+
20+
final class UserResetPasswordDataPersister implements DataPersisterInterface
21+
{
22+
public function persist($data)
23+
{
24+
if ('[email protected]' === $data->email) {
25+
return $data;
26+
}
27+
28+
throw new NotFoundHttpException();
29+
}
30+
31+
public function remove($data)
32+
{
33+
throw new \LogicException(sprintf('Unexpected "%s()" call.', __METHOD__));
34+
}
35+
36+
public function supports($data): bool
37+
{
38+
return $data instanceof UserResetPasswordDto;
39+
}
40+
}
41+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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+
use Symfony\Component\Validator\Constraints as Assert;
17+
18+
final class UserResetPasswordDto
19+
{
20+
/**
21+
* @Assert\Email
22+
*/
23+
public $email;
24+
}
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\Core\Annotation\ApiResource;
17+
use ApiPlatform\Tests\Fixtures\TestBundle\Dto\UserResetPasswordDto;
18+
use Symfony\Component\Validator\Constraints as Assert;
19+
20+
/**
21+
* @ApiResource(
22+
* collectionOperations={
23+
* "user-reset-password"={
24+
* "method"="POST",
25+
* "path"="/user-reset-password",
26+
* "input"=UserResetPasswordDto::class
27+
* }
28+
* }
29+
* )
30+
*/
31+
final class UserResource
32+
{
33+
/**
34+
* @Assert\NotBlank
35+
*/
36+
public string $username;
37+
}

tests/Fixtures/app/config/config_test.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ services:
109109
tags:
110110
- { name: 'api_platform.data_persister' }
111111

112+
app.user_reset_password_data_persister:
113+
class: ApiPlatform\Tests\Fixtures\TestBundle\DataPersister\UserResetPasswordDataPersister
114+
public: false
115+
tags:
116+
- { name: 'api_platform.data_persister' }
117+
112118
app.graphql.query_resolver.dummy_custom_not_retrieved_item:
113119
class: 'ApiPlatform\Tests\Fixtures\TestBundle\GraphQl\Resolver\DummyCustomQueryNotRetrievedItemResolver'
114120
public: false

0 commit comments

Comments
 (0)