Skip to content

Commit

Permalink
-refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
alexndlm committed Oct 29, 2024
1 parent 30e6f10 commit 68a7d3e
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 19 deletions.
12 changes: 6 additions & 6 deletions features/main/validation.feature
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,19 @@ Feature: Using validations groups
"@context": "/contexts/ConstraintViolationList",
"@type": "ConstraintViolationList",
"hydra:title": "An error occurred",
"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.",
"hydra:description": "baz: This value should be of type string.\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.",
"violations": [
{
"propertyPath": "baz",
"message": "This value should be of type string.",
"code": "ba785a8c-82cb-4283-967c-3cf342181b40",
"hint": "Failed to create object because the class misses the \"baz\" property."
},
{
"propertyPath": "qux",
"message": "This value should be of type string.",
"code": "ba785a8c-82cb-4283-967c-3cf342181b40"
},
{
"propertyPath": "foo",
"message": "This value should be of type bool.",
Expand All @@ -132,11 +137,6 @@ Feature: Using validations groups
"message": "This value should be of type int.",
"code": "ba785a8c-82cb-4283-967c-3cf342181b40"
},
{
"propertyPath": "qux",
"message": "This value should be of type string.",
"code": "ba785a8c-82cb-4283-967c-3cf342181b40"
},
{
"propertyPath": "uuid",
"message": "This value should be of type uuid.",
Expand Down
91 changes: 78 additions & 13 deletions src/Serializer/AbstractItemNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -304,18 +304,27 @@ protected function instantiateObject(array &$data, string $class, array &$contex

return $object;
}
// clean up even if no match
unset($context[static::OBJECT_TO_POPULATE]);

$class = $this->getClassDiscriminatorResolvedClass($data, $class, $context);
$reflectionClass = new \ReflectionClass($class);

$constructor = $this->getConstructor($data, $class, $context, $reflectionClass, $allowedAttributes);
if ($constructor) {
$constructorParameters = $constructor->getParameters();
$context['has_constructor'] = true;
if (true !== $constructor->isPublic()) {
return $reflectionClass->newInstanceWithoutConstructor();
}

$params = [];
$constructorParameters = $constructor->getParameters();
$missingConstructorArguments = [];
$params = [];
$unsetKeys = [];

foreach ($constructorParameters as $constructorParameter) {
$paramName = $constructorParameter->name;
$attributeContext = $this->getAttributeDenormalizationContext($class, $paramName, $context);
$key = $this->nameConverter ? $this->nameConverter->normalize($paramName, $class, $format, $context) : $paramName;

$allowed = false === $allowedAttributes || (\is_array($allowedAttributes) && \in_array($paramName, $allowedAttributes, true));
Expand All @@ -326,7 +335,22 @@ protected function instantiateObject(array &$data, string $class, array &$contex
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));
}

$params[] = $data[$paramName];
$variadicParameters = [];
foreach ($data[$key] as $parameterKey => $parameterData) {
try {
$variadicParameters[$parameterKey] = $this->denormalizeParameter($reflectionClass, $constructorParameter, $paramName, $parameterData, $attributeContext, $format);
} catch (NotNormalizableValueException $exception) {
if (!isset($context['not_normalizable_value_exceptions'])) {
throw $exception;
}

$context['not_normalizable_value_exceptions'][] = $exception;
$params[$paramName] = $parameterData;
}
}

$params = array_merge(array_values($params), $variadicParameters);
$unsetKeys[] = $key;
}
} elseif ($allowed && !$ignored && (isset($data[$key]) || \array_key_exists($key, $data))) {
$constructorContext = $context;
Expand All @@ -341,17 +365,34 @@ protected function instantiateObject(array &$data, string $class, array &$contex
}

// Don't run set for a parameter passed to the constructor
unset($data[$key]);
} elseif (isset($context[static::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key])) {
$params[] = $context[static::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key];
$unsetKeys[] = $key;
} elseif (\array_key_exists($key, $context[static::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class] ?? [])) {
$params[$paramName] = $context[static::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key];
} elseif (\array_key_exists($key, $this->defaultContext[self::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class] ?? [])) {
$params[$paramName] = $this->defaultContext[self::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key];
} elseif ($constructorParameter->isDefaultValueAvailable()) {
$params[] = $constructorParameter->getDefaultValue();
$params[$paramName] = $constructorParameter->getDefaultValue();
} elseif (!($context[self::REQUIRE_ALL_PROPERTIES] ?? $this->defaultContext[self::REQUIRE_ALL_PROPERTIES] ?? false) && $constructorParameter->hasType() && $constructorParameter->getType()->allowsNull()) {
$params[$paramName] = null;
} else {
if (!isset($context['not_normalizable_value_exceptions'])) {
$missingConstructorArguments[] = $constructorParameter->name;
continue;
}

$exception = NotNormalizableValueException::createForUnexpectedDataType(\sprintf('Failed to create object because the class misses the "%s" property.', $constructorParameter->name), $data, ['unknown'], $context['deserialization_path'] ?? null, true);
$constructorParameterType = 'unknown';
$reflectionType = $constructorParameter->getType();
if ($reflectionType instanceof \ReflectionNamedType) {
$constructorParameterType = $reflectionType->getName();
}

$exception = NotNormalizableValueException::createForUnexpectedDataType(
sprintf('Failed to create object because the class misses the "%s" property.', $constructorParameter->name),
null,
[$constructorParameterType],
$attributeContext['deserialization_path'] ?? null,
true
);
$context['not_normalizable_value_exceptions'][] = $exception;
}
}
Expand All @@ -360,15 +401,39 @@ protected function instantiateObject(array &$data, string $class, array &$contex
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);
}

if (\count($context['not_normalizable_value_exceptions'] ?? []) > 0) {
return $reflectionClass->newInstanceWithoutConstructor();
if (!$constructor->isConstructor()) {
$instance = $constructor->invokeArgs(null, $params);

// do not set a parameter that has been set in the constructor
foreach ($unsetKeys as $key) {
unset($data[$key]);
}

return $instance;
}

if ($constructor->isConstructor()) {
return $reflectionClass->newInstanceArgs($params);
try {
$instance = $reflectionClass->newInstanceArgs($params);

// do not set a parameter that has been set in the constructor
foreach ($unsetKeys as $key) {
unset($data[$key]);
}

return $instance;
} catch (\TypeError $e) {
if (!isset($context['not_normalizable_value_exceptions'])) {
throw $e;
}

return $reflectionClass->newInstanceWithoutConstructor();
}
}

unset($context['has_constructor']);

return $constructor->invokeArgs(null, $params);
if (!$reflectionClass->isInstantiable()) {
throw NotNormalizableValueException::createForUnexpectedDataType(sprintf('Failed to create object because the class "%s" is not instantiable.', $class), $data, ['unknown'], $context['deserialization_path'] ?? null);
}

return new $class();
Expand Down

0 comments on commit 68a7d3e

Please sign in to comment.