Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 43d028d

Browse files
ktheragenicolas-grekas
authored andcommitted
[Serializer] Fix MissingConstructorArgumentsException returning missing argument one by one
1 parent f2b7403 commit 43d028d

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 <[email protected]>
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)