Index: Classes/Persistence/Mapper/DataMap.php =================================================================== --- Classes/Persistence/Mapper/DataMap.php (revision 1805) +++ Classes/Persistence/Mapper/DataMap.php (working copy) @@ -114,7 +114,8 @@ protected function initialize(array $mapping) { $this->addCommonColumns(); $columnConfigurations = array(); - foreach ($this->getColumnsDefinitions() as $columnName => $columnDefinition) { + $columnDefinitions = $this->getColumnsDefinitions(); + foreach ($columnDefinitions as $columnName => $columnDefinition) { $columnConfigurations[$columnName] = $columnDefinition['config']; $columnConfigurations[$columnName]['mapOnProperty'] = Tx_Extbase_Utility_Extension::convertUnderscoredToLowerCamelCase($columnName); } @@ -190,7 +191,7 @@ } elseif (in_array('double2', $evalConfiguration)) { $columnMap->setPropertyType(Tx_Extbase_Persistence_PropertyType::DOUBLE); } else { - if (isset($columnConfiguration['foreign_table'])) { + if (isset($columnConfiguration['foreign_table']) || $this->isValidRelationOfTypeGroup($columnConfiguration)) { if (isset($columnConfiguration['loadingStrategy'])) { $columnMap->setLoadingStrategy($columnConfiguration['loadingStrategy']); } else { @@ -213,13 +214,14 @@ */ protected function setRelations(Tx_Extbase_Persistence_Mapper_ColumnMap &$columnMap, $columnConfiguration) { if (isset($columnConfiguration) && $columnConfiguration['type'] !== 'passthrough') { - if (isset($columnConfiguration['foreign_table']) && !isset($columnConfiguration['MM']) && !isset($columnConfiguration['foreign_label'])) { + $isDatabaseRelationOfTypeGroup = $this->isValidRelationOfTypeGroup($columnConfiguration); + if ( (isset($columnConfiguration['foreign_table']) || $isDatabaseRelationOfTypeGroup ) && !isset($columnConfiguration['MM'])) { if ($columnConfiguration['maxitems'] == 1) { $this->setOneToOneRelation($columnMap, $columnConfiguration); } else { $this->setOneToManyRelation($columnMap, $columnConfiguration); } - } elseif (isset($columnConfiguration['foreign_label']) || isset($columnConfiguration['MM'])) { + } else if ($isDatabaseRelationOfTypeGroup || isset($columnConfiguration['MM'])) { $this->setManyToManyRelation($columnMap, $columnConfiguration); } else { $columnMap->setTypeOfRelation(Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_NONE); @@ -238,11 +240,17 @@ protected function setOneToOneRelation(Tx_Extbase_Persistence_Mapper_ColumnMap &$columnMap, $columnConfiguration) { $columnMap->setTypeOfRelation(Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_ONE); $columnMap->setChildClassName($this->determineChildClassName($columnConfiguration)); - $columnMap->setChildTableName($columnConfiguration['foreign_table']); - $columnMap->setChildTableWhereStatement($columnConfiguration['foreign_table_where']); - $columnMap->setChildSortbyFieldName($columnConfiguration['foreign_sortby']); - $columnMap->setParentKeyFieldName($columnConfiguration['foreign_field']); - $columnMap->setParentTableFieldName($columnConfiguration['foreign_table_field']); + if($this->isValidRelationOfTypeGroup($columnConfiguration)) { + // for now only support one table relation until singleTableInheritance is implemented + //@todo implement methods that allow relations to multiple tables + $columnMap->setChildTableName( current( t3lib_div::trimExplode(',', $columnConfiguration['allowed']) ) ); + } else { + $columnMap->setChildTableName($columnConfiguration['foreign_table']); + $columnMap->setChildTableWhereStatement($columnConfiguration['foreign_table_where']); + $columnMap->setChildSortbyFieldName($columnConfiguration['foreign_sortby']); + $columnMap->setParentKeyFieldName($columnConfiguration['foreign_field']); + $columnMap->setParentTableFieldName($columnConfiguration['foreign_table_field']); + } } /** @@ -256,11 +264,17 @@ protected function setOneToManyRelation(Tx_Extbase_Persistence_Mapper_ColumnMap &$columnMap, $columnConfiguration) { $columnMap->setTypeOfRelation(Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY); $columnMap->setChildClassName($this->determineChildClassName($columnConfiguration)); - $columnMap->setChildTableName($columnConfiguration['foreign_table']); - $columnMap->setChildTableWhereStatement($columnConfiguration['foreign_table_where']); - $columnMap->setChildSortbyFieldName($columnConfiguration['foreign_sortby']); - $columnMap->setParentKeyFieldName($columnConfiguration['foreign_field']); - $columnMap->setParentTableFieldName($columnConfiguration['foreign_table_field']); + if($this->isValidRelationOfTypeGroup($columnConfiguration)) { + // for now only support one table relation until singleTableInheritance is implemented + //@todo implement methods that allow relations to multiple tables + $columnMap->setChildTableName( current( t3lib_div::trimExplode(',', $columnConfiguration['allowed']) ) ); + } else { + $columnMap->setChildTableName($columnConfiguration['foreign_table']); + $columnMap->setChildTableWhereStatement($columnConfiguration['foreign_table_where']); + $columnMap->setChildSortbyFieldName($columnConfiguration['foreign_sortby']); + $columnMap->setParentKeyFieldName($columnConfiguration['foreign_field']); + $columnMap->setParentTableFieldName($columnConfiguration['foreign_table_field']); + } } /** @@ -276,33 +290,63 @@ $columnMap->setTypeOfRelation(Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY); if ($columnConfiguration['type'] === 'inline') { $columns = $this->getColumnsDefinitions($columnConfiguration['foreign_table']); $columnMap->setChildClassName($this->determineChildClassName($columns[$columnConfiguration['foreign_label']])); $columnMap->setChildTableName($columns[$columnConfiguration['foreign_label']]['foreign_table']); $columnMap->setRelationTableName($columnConfiguration['foreign_table']); $columnMap->setParentKeyFieldName($columnConfiguration['foreign_field']); $columnMap->setChildKeyFieldName($columnConfiguration['foreign_label']); $columnMap->setChildSortByFieldName($columnConfiguration['foreign_sortby']); } else { $columnMap->setChildClassName($this->determineChildClassName($columnConfiguration)); - $columnMap->setChildTableName($columnConfiguration['foreign_table']); + $columnMap->setRelationTableWhereStatement($columnConfiguration['MM_table_where']); + + $foreignTable = $columnConfiguration['allowed'] ? $columnConfiguration['allowed'] : $columnConfiguration['foreign_table']; + // for now only support one table relation until singleTableInheritance is implemented + // @todo implement methods that allow relations to multiple tables, like for the RECORDS content type of TYPO3 + $foreignTable = current( t3lib_div::trimExplode(',', $foreignTable) ); + + $columnMap->setChildTableName($foreignTable); $columnMap->setChildTableWhereStatement($columnConfiguration['foreign_table_where']); - $columnMap->setRelationTableName($columnConfiguration['MM']); - if (is_array($columnConfiguration['MM_match_fields'])) { - $columnMap->setRelationTableMatchFields($columnConfiguration['MM_match_fields']); - } - if (is_array($columnConfiguration['MM_insert_fields'])) { - $columnMap->setRelationTableInsertFields($columnConfiguration['MM_insert_fields']); - } - $columnMap->setRelationTableWhereStatement($columnConfiguration['MM_table_where']); + if (!empty($columnConfiguration['MM_opposite_field'])) { $columnMap->setParentKeyFieldName('uid_foreign'); $columnMap->setChildKeyFieldName('uid_local'); $columnMap->setChildSortByFieldName('sorting_foreign'); + + // check if we're in a multitable relation so that we also have to use tablenames for relations in queries + $foreignTableDefinitions = $this->getColumnsDefinitions($foreignTable); + $oppositeFieldConfiguration = $foreignTableDefinitions[$columnConfiguration['MM_opposite_field']]; + + if ( is_array($oppositeFieldConfiguration) && isset($oppositeFieldConfiguration['allowed']) ) { + $oppositeAllowedTables = t3lib_div::trimExplode(',', $oppositeFieldConfiguration['allowed']); + if (count($oppositeAllowedTables) > 1) { + $isMultiTableRelation = $oppositeAllowedTables[0]; + } + } } else { $columnMap->setParentKeyFieldName('uid_local'); $columnMap->setChildKeyFieldName('uid_foreign'); $columnMap->setChildSortByFieldName('sorting'); + $isMultiTableRelation = false; } + + $columnMap->setRelationTableName($columnConfiguration['MM']); + + $matchFields = $columnConfiguration['MM_match_fields']; + $insertFields = $columnConfiguration['MM_insert_fields'] ? $columnConfiguration['MM_insert_fields'] : $matchFields; + + // automatically add 'tablenames' fields to matchfields, just like TYPO3 core does on certain MM relations + // @see function writeMM of class class.t3lib_loaddbgroup.php + if (($columnConfiguration['prepend_tname'] && !isset($matchFields['tablenames'])) || $isMultiTableRelation) { + $matchFields['tablenames'] = $insertFields['tablenames'] = $this->getTableName(); + } + + if (is_array($matchFields)) { + $columnMap->setRelationTableMatchFields($matchFields); + } + if (is_array($insertFields)) { + $columnMap->setRelationTableInsertFields($insertFields); + } } } @@ -320,10 +364,16 @@ } if (empty($foreignClassName)){ $extbaseSettings = Tx_Extbase_Dispatcher::getExtbaseFrameworkConfiguration(); + if ($this->isValidRelationOfTypeGroup($columnConfiguration)) { + // for now only one relation table for TCA fields of type "group" is supported - so only return the first defined one + $tableName = current( t3lib_div::trimExplode(',',$columnConfiguration['allowed']) ); + } else { + $tableName = $columnConfiguration['foreign_table']; + } // TODO Apply a cache to increase performance (profile first) if (is_array($extbaseSettings['persistence']['classes'])) { foreach ($extbaseSettings['persistence']['classes'] as $className => $classConfiguration) { - if ($classConfiguration['mapping']['tableName'] === $columnConfiguration['foreign_table']) { + if ($classConfiguration['mapping']['tableName'] === $tableName) { $foreignClassName = $className; break; } @@ -415,6 +465,15 @@ } /** + * Check if the given configuration is a valid TCA group field configuration that we can handle + * + * @return boolean + */ + public function isValidRelationOfTypeGroup($columnConfiguration) { + return ( $columnConfiguration['type'] == 'group' && $columnConfiguration['internal_type'] == 'db' && isset($columnConfiguration['allowed']) ); + } + + /** * Returns TRUE if the table has a pid column holding the id of the page the record is virtually stored on. * Currently we don't support tables without a pid column. *