protected function doMapping($source, $targetType, PropertyMappingConfigurationInterface $configuration, &$currentPropertyPath)
{
if (is_object($source)) {
$targetClass = TypeHandling::truncateElementType($targetType);
if ($source instanceof $targetClass) {
return $source;
}
}
if ($source === null) {
$source = '';
}
$typeConverter = $this->findTypeConverter($source, $targetType, $configuration);
$targetType = $typeConverter->getTargetTypeForSource($source, $targetType, $configuration);
if (!is_object($typeConverter) || !$typeConverter instanceof TypeConverterInterface) {
throw new Exception\TypeConverterException('Type converter for "' . $source . '" -> "' . $targetType . '" not found.');
}
$convertedChildProperties = [];
foreach ($typeConverter->getSourceChildPropertiesToBeConverted($source) as $sourcePropertyName => $sourcePropertyValue) {
$targetPropertyName = $configuration->getTargetPropertyName($sourcePropertyName);
if ($configuration->shouldSkip($targetPropertyName)) {
continue;
}
if (!$configuration->shouldMap($targetPropertyName)) {
if ($configuration->shouldSkipUnknownProperties()) {
continue;
}
throw new Exception\InvalidPropertyMappingConfigurationException('It is not allowed to map property "' . $targetPropertyName . '". You need to use $propertyMappingConfiguration->allowProperties(\'' . $targetPropertyName . '\') to enable mapping of this property.', 1335969887);
}
$targetPropertyType = $typeConverter->getTypeOfChildProperty($targetType, $targetPropertyName, $configuration);
$subConfiguration = $configuration->getConfigurationFor($targetPropertyName);
$currentPropertyPath[] = $targetPropertyName;
$targetPropertyValue = $this->doMapping($sourcePropertyValue, $targetPropertyType, $subConfiguration, $currentPropertyPath);
array_pop($currentPropertyPath);
if (!$targetPropertyValue instanceof Error) {
$convertedChildProperties[$targetPropertyName] = $targetPropertyValue;
}
}
$result = $typeConverter->convertFrom($source, $targetType, $convertedChildProperties, $configuration);
if ($result instanceof Error) {
$this->messages->forProperty(implode('.', $currentPropertyPath))->addError($result);
}
return $result;
}