Skip to content

Commit b8e918d

Browse files
bug #49832 [Serializer] Fix MissingConstructorArgumentsException returning missing argument one by one (ktherage)
This PR was squashed before being merged into the 6.3 branch. Discussion ---------- [Serializer] Fix MissingConstructorArgumentsException returning missing argument one by one | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | - | License | MIT | Doc PR | - This PR is an improvment of #49013 and fix #42712. She aims to fix the problem reported in #49013 indicating that the method `getMissingConstructorArguments()` of `\Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException` class introduced in #42712 is returning only one missing arguments when there's more than one missing. Commits ------- 43d028d [Serializer] Fix MissingConstructorArgumentsException returning missing argument one by one
2 parents f2b7403 + 43d028d commit b8e918d

File tree

7 files changed

+49
-88
lines changed

7 files changed

+49
-88
lines changed

UPGRADE-6.3.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ Validator
133133
Serializer
134134
----------
135135

136-
* Deprecate `MissingConstructorArgumentsException` in favor of `MissingConstructorArgumentException`
137136
* Deprecate `CacheableSupportsMethodInterface` in favor of the new `getSupportedTypes(?string $format)` methods
138137
* The following Normalizer classes will become final in 7.0:
139138
* `ConstraintViolationListNormalizer`

src/Symfony/Component/Serializer/CHANGELOG.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ CHANGELOG
99
* Add `UnsupportedFormatException` which is thrown when there is no decoder for a given format
1010
* Add method `getSupportedTypes(?string $format)` to `NormalizerInterface` and `DenormalizerInterface`
1111
* Make `ProblemNormalizer` give details about `ValidationFailedException` and `PartialDenormalizationException`
12-
* Deprecate `MissingConstructorArgumentsException` in favor of `MissingConstructorArgumentException`
1312
* Deprecate `CacheableSupportsMethodInterface` in favor of the new `getSupportedTypes(?string $format)` methods
1413
* The following Normalizer classes will become final in 7.0:
1514
* `ConstraintViolationListNormalizer`

src/Symfony/Component/Serializer/Exception/MissingConstructorArgumentException.php

Lines changed: 0 additions & 41 deletions
This file was deleted.

src/Symfony/Component/Serializer/Exception/MissingConstructorArgumentsException.php

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,37 @@
1212
namespace Symfony\Component\Serializer\Exception;
1313

1414
/**
15-
* @deprecated since Symfony 6.3, use {@see MissingConstructorArgumentException} instead
16-
*
1715
* @author Maxime VEBER <maxime.veber@nekland.fr>
1816
*/
1917
class MissingConstructorArgumentsException extends RuntimeException
2018
{
2119
/**
22-
* @var string[]
20+
* @param string[] $missingArguments
21+
* @param class-string|null $class
2322
*/
24-
private $missingArguments;
25-
26-
public function __construct(string $message, int $code = 0, \Throwable $previous = null, array $missingArguments = [])
27-
{
28-
if (!$this instanceof MissingConstructorArgumentException) {
29-
trigger_deprecation('symfony/serializer', '6.3', 'The "%s" class is deprecated, use "%s" instead.', __CLASS__, MissingConstructorArgumentException::class);
30-
}
31-
32-
$this->missingArguments = $missingArguments;
33-
23+
public function __construct(
24+
string $message,
25+
int $code = 0,
26+
\Throwable $previous = null,
27+
private array $missingArguments = [],
28+
private ?string $class = null,
29+
) {
3430
parent::__construct($message, $code, $previous);
3531
}
3632

3733
/**
38-
* @deprecated since Symfony 6.3, use {@see MissingConstructorArgumentException::getMissingArgument()} instead
39-
*
4034
* @return string[]
4135
*/
4236
public function getMissingConstructorArguments(): array
4337
{
44-
trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, use "%s::getMissingArgument()" instead.', __METHOD__, MissingConstructorArgumentException::class);
45-
4638
return $this->missingArguments;
4739
}
40+
41+
/**
42+
* @return class-string|null
43+
*/
44+
public function getClass(): ?string
45+
{
46+
return $this->class;
47+
}
4848
}

src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
use Symfony\Component\Serializer\Exception\CircularReferenceException;
1515
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
1616
use Symfony\Component\Serializer\Exception\LogicException;
17-
use Symfony\Component\Serializer\Exception\MissingConstructorArgumentException;
17+
use Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException;
1818
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
1919
use Symfony\Component\Serializer\Exception\RuntimeException;
2020
use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface;
@@ -313,7 +313,7 @@ protected function getConstructor(array &$data, string $class, array &$context,
313313
* @return object
314314
*
315315
* @throws RuntimeException
316-
* @throws MissingConstructorArgumentException
316+
* @throws MissingConstructorArgumentsException
317317
*/
318318
protected function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, array|bool $allowedAttributes, string $format = null)
319319
{
@@ -332,7 +332,7 @@ protected function instantiateObject(array &$data, string $class, array &$contex
332332
}
333333

334334
$constructorParameters = $constructor->getParameters();
335-
335+
$missingConstructorArguments = [];
336336
$params = [];
337337
foreach ($constructorParameters as $constructorParameter) {
338338
$paramName = $constructorParameter->name;
@@ -386,7 +386,8 @@ protected function instantiateObject(array &$data, string $class, array &$contex
386386
$params[] = null;
387387
} else {
388388
if (!isset($context['not_normalizable_value_exceptions'])) {
389-
throw new MissingConstructorArgumentException($class, $constructorParameter->name);
389+
$missingConstructorArguments[] = $constructorParameter->name;
390+
continue;
390391
}
391392

392393
$exception = NotNormalizableValueException::createForUnexpectedDataType(
@@ -402,19 +403,23 @@ protected function instantiateObject(array &$data, string $class, array &$contex
402403
}
403404
}
404405

405-
if ($constructor->isConstructor()) {
406-
try {
407-
return $reflectionClass->newInstanceArgs($params);
408-
} catch (\TypeError $e) {
409-
if (!isset($context['not_normalizable_value_exceptions'])) {
410-
throw $e;
411-
}
406+
if ($missingConstructorArguments) {
407+
throw new MissingConstructorArgumentsException(sprintf('Cannot create an instance of "%s" from serialized data because its constructor requires the following parameters to be present : "$%s".', $class, implode('", "$', $missingConstructorArguments)), 0, null, $missingConstructorArguments, $class);
408+
}
412409

413-
return $reflectionClass->newInstanceWithoutConstructor();
414-
}
415-
} else {
410+
if (!$constructor->isConstructor()) {
416411
return $constructor->invokeArgs(null, $params);
417412
}
413+
414+
try {
415+
return $reflectionClass->newInstanceArgs($params);
416+
} catch (\TypeError $e) {
417+
if (!isset($context['not_normalizable_value_exceptions'])) {
418+
throw $e;
419+
}
420+
421+
return $reflectionClass->newInstanceWithoutConstructor();
422+
}
418423
}
419424

420425
return new $class();
@@ -438,7 +443,7 @@ protected function denormalizeParameter(\ReflectionClass $class, \ReflectionPara
438443
}
439444
} catch (\ReflectionException $e) {
440445
throw new RuntimeException(sprintf('Could not determine the class of the parameter "%s".', $parameterName), 0, $e);
441-
} catch (MissingConstructorArgumentException $e) {
446+
} catch (MissingConstructorArgumentsException $e) {
442447
if (!$parameter->getType()->allowsNull()) {
443448
throw $e;
444449
}

src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
use Symfony\Component\Serializer\Encoder\XmlEncoder;
2323
use Symfony\Component\Serializer\Exception\ExtraAttributesException;
2424
use Symfony\Component\Serializer\Exception\LogicException;
25-
use Symfony\Component\Serializer\Exception\MissingConstructorArgumentException;
25+
use Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException;
2626
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
2727
use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface;
2828
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
@@ -419,15 +419,15 @@ abstract protected function setAttributeValue(object $object, string $attribute,
419419
*
420420
* @throws NotNormalizableValueException
421421
* @throws ExtraAttributesException
422-
* @throws MissingConstructorArgumentException
422+
* @throws MissingConstructorArgumentsException
423423
* @throws LogicException
424424
*/
425425
private function validateAndDenormalize(array $types, string $currentClass, string $attribute, mixed $data, ?string $format, array $context): mixed
426426
{
427427
$expectedTypes = [];
428428
$isUnionType = \count($types) > 1;
429429
$extraAttributesException = null;
430-
$missingConstructorArgumentException = null;
430+
$missingConstructorArgumentsException = null;
431431
foreach ($types as $type) {
432432
if (null === $data && $type->isNullable()) {
433433
return null;
@@ -567,21 +567,21 @@ private function validateAndDenormalize(array $types, string $currentClass, stri
567567
}
568568

569569
$extraAttributesException ??= $e;
570-
} catch (MissingConstructorArgumentException $e) {
570+
} catch (MissingConstructorArgumentsException $e) {
571571
if (!$isUnionType) {
572572
throw $e;
573573
}
574574

575-
$missingConstructorArgumentException ??= $e;
575+
$missingConstructorArgumentsException ??= $e;
576576
}
577577
}
578578

579579
if ($extraAttributesException) {
580580
throw $extraAttributesException;
581581
}
582582

583-
if ($missingConstructorArgumentException) {
584-
throw $missingConstructorArgumentException;
583+
if ($missingConstructorArgumentsException) {
584+
throw $missingConstructorArgumentsException;
585585
}
586586

587587
if ($context[self::DISABLE_TYPE_ENFORCEMENT] ?? $this->defaultContext[self::DISABLE_TYPE_ENFORCEMENT] ?? false) {

src/Symfony/Component/Serializer/Tests/Normalizer/Features/ConstructorArgumentsTestTrait.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
namespace Symfony\Component\Serializer\Tests\Normalizer\Features;
1313

14-
use Symfony\Component\Serializer\Exception\MissingConstructorArgumentException;
14+
use Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException;
1515
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
1616
use Symfony\Component\Serializer\Tests\Fixtures\NotSerializedConstructorArgumentDummy;
1717

@@ -62,14 +62,13 @@ public function testConstructorWithMissingData()
6262
];
6363

6464
$normalizer = $this->getDenormalizerForConstructArguments();
65-
6665
try {
6766
$normalizer->denormalize($data, ConstructorArgumentsObject::class);
68-
self::fail(sprintf('Failed asserting that exception of type "%s" is thrown.', MissingConstructorArgumentException::class));
69-
} catch (MissingConstructorArgumentException $e) {
70-
self::assertSame(sprintf('Cannot create an instance of "%s" from serialized data because its constructor requires parameter "bar" to be present.', ConstructorArgumentsObject::class), $e->getMessage());
67+
self::fail(sprintf('Failed asserting that exception of type "%s" is thrown.', MissingConstructorArgumentsException::class));
68+
} catch (MissingConstructorArgumentsException $e) {
69+
self::assertSame(sprintf('Cannot create an instance of "%s" from serialized data because its constructor requires the following parameters to be present : "$bar", "$baz".', ConstructorArgumentsObject::class), $e->getMessage());
7170
self::assertSame(ConstructorArgumentsObject::class, $e->getClass());
72-
self::assertSame('bar', $e->getMissingArgument());
71+
self::assertSame(['bar', 'baz'], $e->getMissingConstructorArguments());
7372
}
7473
}
7574
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy