[BUGFIX] Property Mapper chokes on already-converted objects
authorMarc Neuhaus <apocalip@gmail.com>
Sat, 9 Feb 2013 23:21:49 +0000 (00:21 +0100)
committerMarkus Günther <mail@markus-guenther.de>
Tue, 2 Apr 2013 20:22:58 +0000 (22:22 +0200)
Fixes also PropertyMappers chokes on already converted Objects if the
targetType is a compositeType like Collection<Entity>.
Backport from Flow issues #39445, #40661 and #36988

Change-Id: I8622dd9ef15a5e8e4aa98adc4e5b0def4a913ce1
Fixes: #44214
Fixes: #44215
Releases: 6.1, 6.0
Reviewed-on: https://review.typo3.org/18172
Reviewed-by: Anja Leichsenring
Tested-by: Anja Leichsenring
Reviewed-by: Wouter Wolters
Tested-by: Wouter Wolters
Reviewed-by: Stefan Neufeind
Reviewed-by: Marc Neuhaus
Reviewed-by: Markus Günther
Tested-by: Markus Günther
typo3/sysext/extbase/Classes/Property/PropertyMapper.php
typo3/sysext/extbase/Tests/Unit/Property/PropertyMapperTest.php

index 1d2ac1b..9c17525 100644 (file)
@@ -156,6 +156,12 @@ class PropertyMapper implements \TYPO3\CMS\Core\SingletonInterface {
                // This is needed to correctly convert old class names to new ones
                // This compatibility layer will be removed with 7.0
                $targetType = \TYPO3\CMS\Core\Core\ClassLoader::getClassNameForAlias($targetType);
+               if (is_object($source)) {
+                       $targetType = $this->parseCompositeType($targetType);
+                       if ($source instanceof $targetType) {
+                               return $source;
+                       }
+               }
                $typeConverter = $this->findTypeConverter($source, $targetType, $configuration);
                if (!is_object($typeConverter) || !$typeConverter instanceof \TYPO3\CMS\Extbase\Property\TypeConverterInterface) {
                        throw new \TYPO3\CMS\Extbase\Property\Exception\TypeConverterException('Type converter for "' . $source . '" -> "' . $targetType . '" not found.');
@@ -201,9 +207,7 @@ class PropertyMapper implements \TYPO3\CMS\Core\SingletonInterface {
                if (!is_string($targetType)) {
                        throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException('The target type was no string, but of type "' . gettype($targetType) . '"', 1297941727);
                }
-               if (strpos($targetType, '<') !== FALSE) {
-                       $targetType = substr($targetType, 0, strpos($targetType, '<'));
-               }
+               $targetType = $this->parseCompositeType($targetType);
                $converter = NULL;
                if ($this->typeHandlingService->isSimpleType($targetType)) {
                        if (isset($this->typeConverters[$sourceType][$targetType])) {
@@ -325,6 +329,21 @@ class PropertyMapper implements \TYPO3\CMS\Core\SingletonInterface {
                        throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidSourceException('The source is not of type string, array, float, integer or boolean, but of type "' . gettype($source) . '"', 1297773150);
                }
        }
+
+       /**
+        * Parse a composite type like \Foo\Collection<\Bar\Entity> into
+        * \Foo\Collection
+        *
+        * @param string $compositeType
+        * @return string
+        */
+       public function parseCompositeType($compositeType) {
+               if (strpos($compositeType, '<') !== FALSE) {
+                       $compositeType = substr($compositeType, 0, strpos($compositeType, '<'));
+               }
+               return $compositeType;
+       }
+
 }
 
 ?>
\ No newline at end of file
index 020223d..0a524ea 100644 (file)
@@ -339,6 +339,29 @@ class PropertyMapperTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
                $propertyMapper = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Property\\PropertyMapper', array('dummy'));
                $this->assertNull($propertyMapper->_call('findFirstEligibleTypeConverterInObjectHierarchy', 'source', 'unknownSourceType', 'TYPO3\\CMS\\Extbase\\Core\\Bootstrap'));
        }
+
+       /**
+        * @test
+        */
+       public function convertReturnsSourceUnchangedIfAlreadyConverted() {
+               $source = new \ArrayObject();
+               $targetType = 'ArrayObject';
+               $propertyPath = '';
+               $propertyMapper = new \TYPO3\CMS\Extbase\Property\PropertyMapper();
+               $this->assertSame($source, $propertyMapper->convert($source, $targetType, $this->mockConfiguration, $propertyPath));
+       }
+
+       /**
+        * @test
+        */
+       public function convertReturnsSourceUnchangedIfAlreadyConvertedToCompositeType() {
+               $source = new \ArrayObject();
+               $targetType = 'ArrayObject<SomeEntity>';
+               $propertyPath = '';
+               $propertyMapper = new \TYPO3\CMS\Extbase\Property\PropertyMapper();
+               $this->assertSame($source, $propertyMapper->convert($source, $targetType, $this->mockConfiguration, $propertyPath));
+       }
+
 }
 
 ?>
\ No newline at end of file