2 namespace TYPO3\CMS\Extbase\Property;
23 use TYPO3\CMS\Extbase\Property\Exception\TargetNotFoundException;
90 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'EXTCONF'][
'extbase'][
'typeConverters'] as $typeConverterClassName) {
91 $typeConverter = $this->objectManager->get($typeConverterClassName);
92 foreach ($typeConverter->getSupportedSourceTypes() as $supportedSourceType) {
93 if (isset($this->typeConverters[$supportedSourceType][$typeConverter->getSupportedTargetType()][$typeConverter->getPriority()])) {
94 throw new Exception\DuplicateTypeConverterException(
'There exist at least two converters which handle the conversion from "' . $supportedSourceType .
'" to "' . $typeConverter->getSupportedTargetType() .
'" with priority "' . $typeConverter->getPriority() .
'": ' . get_class($this->typeConverters[$supportedSourceType][$typeConverter->getSupportedTargetType()][$typeConverter->getPriority()]) .
' and ' . get_class($typeConverter), 1297951378);
96 $this->typeConverters[$supportedSourceType][$typeConverter->getSupportedTargetType()][$typeConverter->getPriority()] = $typeConverter;
113 if ($configuration === null) {
114 $configuration = $this->configurationBuilder->build();
116 $currentPropertyPath = array();
117 $this->messages = new \TYPO3\CMS\Extbase\Error\Result();
119 $result = $this->
doMapping($source, $targetType, $configuration, $currentPropertyPath);
120 if ($result instanceof \TYPO3\CMS\Extbase\Error\Error) {
128 throw new Exception(
'Exception while property mapping at property path "' . implode(
'.', $currentPropertyPath) .
'":' . $e->getMessage(), 1297759968, $e);
156 if (is_object($source)) {
158 if ($source instanceof $targetType) {
163 if ($source === null) {
168 $targetType = $typeConverter->getTargetTypeForSource($source, $targetType, $configuration);
170 if (!is_object($typeConverter) || !$typeConverter instanceof \TYPO3\CMS\Extbase\Property\
TypeConverterInterface) {
171 throw new Exception\TypeConverterException(
'Type converter for "' . $source .
'" -> "' . $targetType .
'" not found.');
174 $convertedChildProperties = array();
175 foreach ($typeConverter->getSourceChildPropertiesToBeConverted($source) as $sourcePropertyName => $sourcePropertyValue) {
177 if ($configuration->
shouldSkip($targetPropertyName)) {
181 if (!$configuration->shouldMap($targetPropertyName)) {
185 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.
', 1355155913);
188 $targetPropertyType = $typeConverter->getTypeOfChildProperty($targetType, $targetPropertyName, $configuration);
190 $subConfiguration = $configuration->getConfigurationFor($targetPropertyName);
192 $currentPropertyPath[] = $targetPropertyName;
193 $targetPropertyValue = $this->doMapping($sourcePropertyValue, $targetPropertyType, $subConfiguration, $currentPropertyPath);
194 array_pop($currentPropertyPath);
195 if (!($targetPropertyValue instanceof \TYPO3\CMS\Extbase\Error\Error)) {
196 $convertedChildProperties[$targetPropertyName] = $targetPropertyValue;
199 $result = $typeConverter->convertFrom($source, $targetType, $convertedChildProperties, $configuration);
201 if ($result instanceof \TYPO3\CMS\Extbase\Error\Error) {
202 $this->messages->forProperty(implode('.
', $currentPropertyPath))->addError($result);
218 protected function findTypeConverter($source, $targetType, PropertyMappingConfigurationInterface $configuration)
220 if ($configuration->getTypeConverter() !== null) {
221 return $configuration->getTypeConverter();
224 $sourceType = $this->determineSourceType($source);
226 if (!is_string($targetType)) {
227 throw new Exception\InvalidTargetException('The target type was no string, but of type
"' . gettype($targetType) . '"', 1297941727);
230 $targetType = $this->parseCompositeType($targetType);
231 // This is needed to correctly convert old class names to new ones
232 // This compatibility layer will be removed with 7.0
233 $targetType = \TYPO3\CMS\Core\Core\ClassLoadingInformation::getClassNameForAlias($targetType);
235 $targetType = TypeHandlingUtility::normalizeType($targetType);
239 if (TypeHandlingUtility::isSimpleType($targetType)) {
240 if (isset($this->typeConverters[$sourceType][$targetType])) {
241 $converter = $this->findEligibleConverterWithHighestPriority($this->typeConverters[$sourceType][$targetType], $source, $targetType);
244 $converter = $this->findFirstEligibleTypeConverterInObjectHierarchy($source, $sourceType, $targetType);
247 if ($converter === null) {
248 throw new Exception\TypeConverterException('No converter found which can be used to
convert from
"' . $sourceType . '" to
"' . $targetType . '".
');
263 protected function findFirstEligibleTypeConverterInObjectHierarchy($source, $sourceType, $targetClass)
265 if (!class_exists($targetClass) && !interface_exists($targetClass)) {
266 throw new Exception\InvalidTargetException('Could not find a suitable type converter
for "' . $targetClass . '" because no such
class or interface exists.', 1297948764);
269 if (!isset($this->typeConverters[$sourceType])) {
273 $convertersForSource = $this->typeConverters[$sourceType];
274 if (isset($convertersForSource[$targetClass])) {
275 $converter = $this->findEligibleConverterWithHighestPriority($convertersForSource[$targetClass], $source, $targetClass);
276 if ($converter !== null) {
281 foreach (class_parents($targetClass) as $parentClass) {
282 if (!isset($convertersForSource[$parentClass])) {
286 $converter = $this->findEligibleConverterWithHighestPriority($convertersForSource[$parentClass], $source, $targetClass);
287 if ($converter !== null) {
293 $converter = $this->findEligibleConverterWithHighestPriority($converters, $source, $targetClass);
295 if ($converter !== null) {
298 if (isset($convertersForSource[
'object'])) {
299 return $this->findEligibleConverterWithHighestPriority($convertersForSource[
'object'], $source, $targetClass);
311 protected function findEligibleConverterWithHighestPriority($converters, $source, $targetType)
313 if (!is_array($converters)) {
319 foreach ($converters as $converter) {
320 if ($converter->canConvertFrom($source, $targetType)) {
335 $convertersForInterface = array();
336 foreach ($interfaceNames as $implementedInterface) {
337 if (isset($convertersForSource[$implementedInterface])) {
338 foreach ($convertersForSource[$implementedInterface] as $priority => $converter) {
339 if (isset($convertersForInterface[$priority])) {
340 throw new Exception\DuplicateTypeConverterException(
'There exist at least two converters which handle the conversion to an interface with priority "' . $priority .
'". ' . get_class($convertersForInterface[$priority]) .
' and ' . get_class($converter), 1297951338);
342 $convertersForInterface[$priority] = $converter;
346 return $convertersForInterface;
358 if (is_string($source)) {
360 }
elseif (is_array($source)) {
362 }
elseif (is_float($source)) {
364 }
elseif (is_integer($source)) {
366 }
elseif (is_bool($source)) {
369 throw new Exception\InvalidSourceException(
'The source is not of type string, array, float, integer or boolean, but of type "' . gettype($source) .
'"', 1297773150);
382 if (strpos($compositeType,
'<') !==
false) {
383 $compositeType = substr($compositeType, 0, strpos($compositeType,
'<'));
385 return $compositeType;