[+BUGFIX] Extbase (Persistence): Fixed processing of one-to-one relations with interm...
authorJochen Rau <j.rau@web.de>
Sun, 20 Jun 2010 07:18:10 +0000 (07:18 +0000)
committerJochen Rau <j.rau@web.de>
Sun, 20 Jun 2010 07:18:10 +0000 (07:18 +0000)
typo3/sysext/extbase/Classes/Persistence/Mapper/DataMapFactory.php
typo3/sysext/extbase/Classes/Persistence/Mapper/DataMapper.php
typo3/sysext/extbase/Classes/Persistence/Storage/Typo3DbBackend.php
typo3/sysext/extbase/Tests/Persistence/Mapper/DataMapFactory_testcase.php

index ca13337..48c9164 100644 (file)
@@ -177,18 +177,14 @@ class Tx_Extbase_Persistence_Mapper_DataMapFactory {
         */
        protected function setRelations(Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap, $columnConfiguration, $propertyMetaData) {
                if (isset($columnConfiguration)) {
-                       if (isset($propertyMetaData['elementType'])) {
-                               if (isset($columnConfiguration['MM']) || isset($columnConfiguration['foreign_selector'])) {
-                                       $columnMap = $this->setManyToManyRelation($columnMap, $columnConfiguration);
-                               } else {
-                                       $columnMap = $this->setOneToManyRelation($columnMap, $columnConfiguration);
-                               }
+                       if (isset($columnConfiguration['MM']) || isset($columnConfiguration['foreign_selector'])) {
+                               $columnMap = $this->setManyToManyRelation($columnMap, $columnConfiguration);
+                       } elseif (isset($propertyMetaData['elementType'])) {
+                               $columnMap = $this->setOneToManyRelation($columnMap, $columnConfiguration);
+                       } elseif (isset($propertyMetaData['type']) && strpos($propertyMetaData['type'], '_') !== FALSE) {
+                               $columnMap = $this->setOneToOneRelation($columnMap, $columnConfiguration);
                        } else {
-                               if (isset($propertyMetaData['type']) && strpos($propertyMetaData['type'], '_') !== FALSE) {
-                                       $columnMap = $this->setOneToOneRelation($columnMap, $columnConfiguration);
-                               } else {
                                        $columnMap->setTypeOfRelation(Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_NONE);
-                               }
                        }
                } else {
                        $columnMap->setTypeOfRelation(Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_NONE);
index 0f8aab1..2c2721d 100644 (file)
@@ -344,16 +344,17 @@ class Tx_Extbase_Persistence_Mapper_DataMapper implements t3lib_Singleton {
        protected function getPreparedQuery(Tx_Extbase_DomainObject_DomainObjectInterface $parentObject, $propertyName, $fieldValue = '') {
                $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
                $queryFactory = t3lib_div::makeInstance('Tx_Extbase_Persistence_QueryFactory');
+               $type = $this->getType(get_class($parentObject), $propertyName);
                if ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_ONE) {
-                       $query = $queryFactory->create($this->getType(get_class($parentObject), $propertyName));
+                       $query = $queryFactory->create($type);
                } elseif ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) {
-                       $query = $queryFactory->create($this->getElementType(get_class($parentObject), $propertyName));
+                       $query = $queryFactory->create($type);
                        $query->getQuerySettings()->setRespectStoragePage(FALSE);
                        if ($columnMap->getChildSortByFieldName() !== NULL) {
                                $query->setOrderings(array($columnMap->getChildSortByFieldName() => Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING));
                        }
                } elseif ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
-                       $query = $queryFactory->create($this->getElementType(get_class($parentObject), $propertyName));
+                       $query = $queryFactory->create($type);
                        $query->getQuerySettings()->setRespectStoragePage(FALSE);
                        $query->setSource($this->getSource($parentObject, $propertyName));
                        if ($columnMap->getChildSortByFieldName() !== NULL) {
@@ -407,7 +408,7 @@ class Tx_Extbase_Persistence_Mapper_DataMapper implements t3lib_Singleton {
        protected function getSource(Tx_Extbase_DomainObject_DomainObjectInterface $parentObject, $propertyName) {
                $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
                $left = $this->qomFactory->selector(NULL, $columnMap->getRelationTableName());
-               $childClassName = $this->getElementType(get_class($parentObject), $propertyName);
+               $childClassName = $this->getType(get_class($parentObject), $propertyName);
                $right = $this->qomFactory->selector($childClassName, $columnMap->getChildTableName());
                $joinCondition = $this->qomFactory->equiJoinCondition($columnMap->getRelationTableName(), $columnMap->getChildKeyFieldName(), $columnMap->getChildTableName(), 'uid');
                $source = $this->qomFactory->join(
@@ -434,7 +435,7 @@ class Tx_Extbase_Persistence_Mapper_DataMapper implements t3lib_Singleton {
                        $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
                        $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
                        if (in_array($propertyMetaData['type'], array('array', 'ArrayObject', 'SplObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'))) {
-                               $elementType = $this->getElementType(get_class($parentObject), $propertyName);
+                               $elementType = $this->getType(get_class($parentObject), $propertyName);
                                $objects = array();
                                foreach ($result as $value) {
                                        $objects[] = $value;
@@ -544,7 +545,9 @@ class Tx_Extbase_Persistence_Mapper_DataMapper implements t3lib_Singleton {
         */
        public function getType($parentClassName, $propertyName) {
                $propertyMetaData = $this->reflectionService->getClassSchema($parentClassName)->getProperty($propertyName);
-               if (!empty($propertyMetaData['type'])) {
+               if (!empty($propertyMetaData['elementType'])) {
+                       $type = $propertyMetaData['elementType'];
+               } elseif (!empty($propertyMetaData['type'])) {
                        $type = $propertyMetaData['type'];
                } else {
                        throw new Tx_Extbase_Persistence_Exception_UnexpectedTypeException('Could not determine the child object type.', 1251315967);
@@ -552,22 +555,5 @@ class Tx_Extbase_Persistence_Mapper_DataMapper implements t3lib_Singleton {
                return $type;
        }
 
-       /**
-        * Returns the type of the elements inside an ObjectStorage or array.
-        *
-        * @param string $parentClassName The class name of the object this proxy is part of
-        * @param string $propertyName The name of the proxied property in it's parent
-        * @return string The class name of the elements inside an ObjectStorage
-        */
-       public function getElementType($parentClassName, $propertyName) {
-               $propertyMetaData = $this->reflectionService->getClassSchema($parentClassName)->getProperty($propertyName);
-               if (!empty($propertyMetaData['elementType'])) {
-                       $elementType = $propertyMetaData['elementType'];
-               } else {
-                       throw new Tx_Extbase_Persistence_Exception_UnexpectedTypeException('Could not determine the type of the contained objects.', 1251315966);
-               }
-               return $elementType;            
-       }
-
 }
 ?>
\ No newline at end of file
index 0f642e3..c73e25f 100644 (file)
@@ -648,12 +648,12 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
                                $onStatement .= ' OR ' . $tableName . '.' . $columnName . ' LIKE CONCAT(' . $childTableName . '.uid,\',%\'))';
                                $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $onStatement;
                        }
-                       $className = $this->dataMapper->getElementType($className, $propertyName);
+                       $className = $this->dataMapper->getType($className, $propertyName);
                } elseif ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
                        $relationTableName = $columnMap->getRelationTableName();
                        $sql['unions'][$relationTableName] = 'LEFT JOIN ' . $relationTableName . ' ON ' . $tableName . '.uid=' . $relationTableName . '.uid_local';
                        $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $relationTableName . '.uid_foreign=' . $childTableName . '.uid';
-                       $className = $this->dataMapper->getElementType($className, $propertyName);
+                       $className = $this->dataMapper->getType($className, $propertyName);
                } else {
                        throw new Tx_Extbase_Persistence_Exception('Could not determine type of relation.', 1252502725);
                }
index a3442c3..1308ff9 100644 (file)
@@ -53,6 +53,27 @@ class Tx_Extbase_Persistence_Mapper_DataMapFactory_testcase extends Tx_Extbase_B
        /**
         * @test
         */
+       public function setRelationsDetectsOneToOneRelationWithIntermediateTable() {
+               $mockColumnMap = $this->getMock('Tx_Extbase_Persistence_Mapper_ColumnMap', array(), array(), '', FALSE);
+           $columnConfiguration = array(
+                       'type' => 'select',
+                       'foreign_table' => 'tx_myextension_bar',
+                       'MM' => 'tx_myextension_mm'
+                       );
+               $propertyMetaData = array(
+                       'type' => 'Tx_Myext_Domain_Model_Foo',
+                       'elementType' => NULL
+                       );
+               $mockDataMapFactory = $this->getMock($this->buildAccessibleProxy('Tx_Extbase_Persistence_Mapper_DataMapFactory'), array('setOneToOneRelation', 'setOneToManyRelation', 'setManyToManyRelation'), array(), '', FALSE);
+               $mockDataMapFactory->expects($this->never())->method('setOneToOneRelation');
+               $mockDataMapFactory->expects($this->never())->method('setOneToManyRelation');
+               $mockDataMapFactory->expects($this->once())->method('setManyToManyRelation');
+               $mockDataMapFactory->_callRef('setRelations', $mockColumnMap, $columnConfiguration, $propertyMetaData);
+       }
+       
+       /**
+        * @test
+        */
        public function setRelationsDetectsOneToManyRelation() {
                $mockColumnMap = $this->getMock('Tx_Extbase_Persistence_Mapper_ColumnMap', array(), array(), '', FALSE);
            $columnConfiguration = array(