Skip to content

Commit 30e6f10

Browse files
committed
-refactoring
1 parent f43bc57 commit 30e6f10

File tree

3 files changed

+101
-14
lines changed

3 files changed

+101
-14
lines changed

behat.yml.dist

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ default:
1919
tags: '~@postgres&&~@mongodb&&~@elasticsearch&&~@controller&&~@mercure&&~@query_parameter_validator'
2020
extensions:
2121
'FriendsOfBehat\SymfonyExtension':
22-
bootstrap: 'tests/Fixtures/app/bootstrap.php'
22+
bootstrap: '/Users/alex/PhpstormProjects/api-platform-core/tests/Fixtures/app/bootstrap.php'
2323
kernel:
2424
environment: 'test'
2525
debug: true
2626
class: AppKernel
27-
path: 'tests/Fixtures/app/AppKernel.php'
27+
path: '/Users/alex/PhpstormProjects/api-platform-core/tests/Fixtures/app/AppKernel.php'
2828
'Behat\MinkExtension':
2929
base_url: 'http://example.com/'
3030
files_path: 'features/files'
@@ -206,12 +206,12 @@ legacy:
206206
tags: '~@postgres&&~@mongodb&&~@elasticsearch&&~@link_security&&~@use_listener&&~@query_parameter_validator'
207207
extensions:
208208
'FriendsOfBehat\SymfonyExtension':
209-
bootstrap: 'tests/Fixtures/app/bootstrap.php'
209+
bootstrap: '/Users/alex/PhpstormProjects/api-platform-core/tests/Fixtures/app/bootstrap.php'
210210
kernel:
211211
environment: 'test'
212212
debug: true
213213
class: AppKernel
214-
path: 'tests/Fixtures/app/AppKernel.php'
214+
path: '/Users/alex/PhpstormProjects/api-platform-core/tests/Fixtures/app/AppKernel.php'
215215
'Behat\MinkExtension':
216216
base_url: 'http://example.com/'
217217
files_path: 'features/files'
@@ -241,12 +241,12 @@ symfony_listeners:
241241
tags: '~@postgres&&~@mongodb&&~@elasticsearch&&~@mercure&&~@query_parameter_validator'
242242
extensions:
243243
'FriendsOfBehat\SymfonyExtension':
244-
bootstrap: 'tests/Fixtures/app/bootstrap.php'
244+
bootstrap: '/Users/alex/PhpstormProjects/api-platform-core/tests/Fixtures/app/bootstrap.php'
245245
kernel:
246246
environment: 'test'
247247
debug: true
248248
class: AppKernel
249-
path: 'tests/Fixtures/app/AppKernel.php'
249+
path: '/Users/alex/PhpstormProjects/api-platform-core/tests/Fixtures/app/AppKernel.php'
250250
'Behat\MinkExtension':
251251
base_url: 'http://example.com/'
252252
files_path: 'features/files'

features/main/validation.feature

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,19 +114,14 @@ Feature: Using validations groups
114114
"@context": "/contexts/ConstraintViolationList",
115115
"@type": "ConstraintViolationList",
116116
"hydra:title": "An error occurred",
117-
"hydra:description": "This value should be of type unknown.\nqux: This value should be of type string.\nfoo: This value should be of type bool.\nbar: This value should be of type int.\nuuid: This value should be of type uuid.\nrelatedDummy: This value should be of type array|string.\nrelatedDummies: This value should be of type array.",
117+
"hydra:description": "baz: This value should be of type string.\nfoo: This value should be of type bool.\nbar: This value should be of type int.\nqux: This value should be of type string.\nuuid: This value should be of type uuid.\nrelatedDummy: This value should be of type array|string.\nrelatedDummies: This value should be of type array.",
118118
"violations": [
119119
{
120-
"propertyPath": "",
121-
"message": "This value should be of type unknown.",
120+
"propertyPath": "baz",
121+
"message": "This value should be of type string.",
122122
"code": "ba785a8c-82cb-4283-967c-3cf342181b40",
123123
"hint": "Failed to create object because the class misses the \"baz\" property."
124124
},
125-
{
126-
"propertyPath": "qux",
127-
"message": "This value should be of type string.",
128-
"code": "ba785a8c-82cb-4283-967c-3cf342181b40"
129-
},
130125
{
131126
"propertyPath": "foo",
132127
"message": "This value should be of type bool.",
@@ -137,6 +132,11 @@ Feature: Using validations groups
137132
"message": "This value should be of type int.",
138133
"code": "ba785a8c-82cb-4283-967c-3cf342181b40"
139134
},
135+
{
136+
"propertyPath": "qux",
137+
"message": "This value should be of type string.",
138+
"code": "ba785a8c-82cb-4283-967c-3cf342181b40"
139+
},
140140
{
141141
"propertyPath": "uuid",
142142
"message": "This value should be of type uuid.",

src/Serializer/AbstractItemNormalizer.php

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@
3535
use Symfony\Component\Serializer\Encoder\CsvEncoder;
3636
use Symfony\Component\Serializer\Encoder\XmlEncoder;
3737
use Symfony\Component\Serializer\Exception\LogicException;
38+
use Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException;
3839
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
40+
use Symfony\Component\Serializer\Exception\RuntimeException;
3941
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
4042
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
4143
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
@@ -287,6 +289,91 @@ public function denormalize(mixed $data, string $class, ?string $format = null,
287289
return $object;
288290
}
289291

292+
/**
293+
* Method copy-pasted from symfony/serializer.
294+
* Remove it after symfony/serializer version update @see https://github.com/symfony/symfony/pull/28263.
295+
*
296+
* {@inheritdoc}
297+
*
298+
* @internal
299+
*/
300+
protected function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, array|bool $allowedAttributes, ?string $format = null): object
301+
{
302+
if (null !== $object = $this->extractObjectToPopulate($class, $context, static::OBJECT_TO_POPULATE)) {
303+
unset($context[static::OBJECT_TO_POPULATE]);
304+
305+
return $object;
306+
}
307+
308+
$class = $this->getClassDiscriminatorResolvedClass($data, $class, $context);
309+
$reflectionClass = new \ReflectionClass($class);
310+
311+
$constructor = $this->getConstructor($data, $class, $context, $reflectionClass, $allowedAttributes);
312+
if ($constructor) {
313+
$constructorParameters = $constructor->getParameters();
314+
315+
$params = [];
316+
$missingConstructorArguments = [];
317+
foreach ($constructorParameters as $constructorParameter) {
318+
$paramName = $constructorParameter->name;
319+
$key = $this->nameConverter ? $this->nameConverter->normalize($paramName, $class, $format, $context) : $paramName;
320+
321+
$allowed = false === $allowedAttributes || (\is_array($allowedAttributes) && \in_array($paramName, $allowedAttributes, true));
322+
$ignored = !$this->isAllowedAttribute($class, $paramName, $format, $context);
323+
if ($constructorParameter->isVariadic()) {
324+
if ($allowed && !$ignored && (isset($data[$key]) || \array_key_exists($key, $data))) {
325+
if (!\is_array($data[$paramName])) {
326+
throw new RuntimeException(\sprintf('Cannot create an instance of %s from serialized data because the variadic parameter %s can only accept an array.', $class, $constructorParameter->name));
327+
}
328+
329+
$params[] = $data[$paramName];
330+
}
331+
} elseif ($allowed && !$ignored && (isset($data[$key]) || \array_key_exists($key, $data))) {
332+
$constructorContext = $context;
333+
$constructorContext['deserialization_path'] = $context['deserialization_path'] ?? $key;
334+
try {
335+
$params[] = $this->createConstructorArgument($data[$key], $key, $constructorParameter, $constructorContext, $format);
336+
} catch (NotNormalizableValueException $exception) {
337+
if (!isset($context['not_normalizable_value_exceptions'])) {
338+
throw $exception;
339+
}
340+
$context['not_normalizable_value_exceptions'][] = $exception;
341+
}
342+
343+
// Don't run set for a parameter passed to the constructor
344+
unset($data[$key]);
345+
} elseif (isset($context[static::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key])) {
346+
$params[] = $context[static::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key];
347+
} elseif ($constructorParameter->isDefaultValueAvailable()) {
348+
$params[] = $constructorParameter->getDefaultValue();
349+
} else {
350+
if (!isset($context['not_normalizable_value_exceptions'])) {
351+
$missingConstructorArguments[] = $constructorParameter->name;
352+
}
353+
354+
$exception = NotNormalizableValueException::createForUnexpectedDataType(\sprintf('Failed to create object because the class misses the "%s" property.', $constructorParameter->name), $data, ['unknown'], $context['deserialization_path'] ?? null, true);
355+
$context['not_normalizable_value_exceptions'][] = $exception;
356+
}
357+
}
358+
359+
if ($missingConstructorArguments) {
360+
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);
361+
}
362+
363+
if (\count($context['not_normalizable_value_exceptions'] ?? []) > 0) {
364+
return $reflectionClass->newInstanceWithoutConstructor();
365+
}
366+
367+
if ($constructor->isConstructor()) {
368+
return $reflectionClass->newInstanceArgs($params);
369+
}
370+
371+
return $constructor->invokeArgs(null, $params);
372+
}
373+
374+
return new $class();
375+
}
376+
290377
protected function getClassDiscriminatorResolvedClass(array $data, string $class, array $context = []): string
291378
{
292379
if (null === $this->classDiscriminatorResolver || (null === $mapping = $this->classDiscriminatorResolver->getMappingForClass($class))) {

0 commit comments

Comments
 (0)