protected function doMapping($source, $targetType, PropertyMappingConfigurationInterface $configuration, &$currentPropertyPath)
    {
        $targetTypeWithoutNull = TypeHandling::stripNullableType($targetType);
        $isNullableType = $targetType !== $targetTypeWithoutNull;
        if ($source === null && $isNullableType) {
            return null;
        }
        $targetType = $targetTypeWithoutNull;

        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);
            if ($targetPropertyType === null) {
                continue;
            }

            $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;
    }
protected function doMapping($source, $targetType, PropertyMappingConfigurationInterface $configuration, &$currentPropertyPath)
    {
        $targetTypeWithoutNull = TypeHandling::stripNullableType($targetType);
        $isNullableType = $targetType !== $targetTypeWithoutNull;
        if ($source === null && $isNullableType) {
            return null;
        }
        $targetType = $targetTypeWithoutNull;

        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);
            if ($targetPropertyType === null) {
                continue;
            }

            $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;
    }
protected function doMapping ( $ source , $ targetType , PropertyMappingConfigurationInterface $ configuration , & $ currentPropertyPath ) { $ targetTypeWithoutNull = TypeHandling :: stripNullableType ( $ targetType ) ; $ isNullableType = $ targetType !== $ targetTypeWithoutNull ; if ( $ source === null && $ isNullableType ) { return null ; } $ targetType = $ targetTypeWithoutNull ; 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 ) ; if ( $ targetPropertyType === null ) { continue ; } $ 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 ; }
Internal function which actually does the property mapping.

@param mixed $source the source data to map. MUST be a simple type, NO object allowed!
@param string $targetType The type of the target; can be either a class name or a simple type.
@param PropertyMappingConfigurationInterface $configuration Configuration for the property mapping.
@param array $currentPropertyPath The property path currently being mapped; used for knowing the context in case an exception is thrown.
@return mixed an instance of $targetType
@throws Exception\TypeConverterException
@throws Exception\InvalidPropertyMappingConfigurationException
Internal function which actually does the property mapping .