Project

General

Profile

Task #6249 » Issue_6249_TcaGroupSupport.diff

Franz Koch, 2011-01-21 17:09

View differences:

Classes/Persistence/Backend.php (working copy)
$columnMap->getParentKeyFieldName() => (int)$parentObject->getUid(),
$columnMap->getChildKeyFieldName() => (int)$object->getUid(),
$columnMap->getChildSortByFieldName() => !is_null($sortingPosition) ? (int)$sortingPosition : 0
);
$relationTableName = $columnMap->getRelationTableName();
// FIXME Reenable support for tablenames
// $childTableName = $columnMap->getChildTableName();
// if (isset($childTableName)) {
// $row['tablenames'] = $childTableName;
// }
);
// support for "tablenames" column
if ($columnMap->getRelationTableRelatedTableColumnName() !== NULL) {
if ($columnMap->isMultiColumnRelation() === TRUE) {
$tableName = $this->dataMapper->getDataMap(get_class($object))->getTableName();
} else {
$tableName = $dataMap->getTableName();
}
$row[$columnMap->getRelationTableRelatedTableColumnName()] = $tableName;
}
if ($columnMap->getRelationTablePageIdColumnName() !== NULL) {
$row[$columnMap->getRelationTablePageIdColumnName()] = $this->determineStoragePageIdForNewRecord();
}
......
}
}
$relationTableName = $columnMap->getRelationTableName();
$res = $this->storageBackend->addRow(
$relationTableName,
$row,
......
$columnMap->getParentKeyFieldName() => (int)$parentObject->getUid()
);
$relationTableMatchFields = $columnMap->getRelationTableMatchFields();
if (is_array($relationTableMatchFields) && count($relationTableMatchFields) > 0) {
$relationMatchFields = array_merge($relationTableMatchFields,$relationMatchFields);
}
$this->addDefaultMatchFieldsToRelationMatchFields($columnMap, $relationMatchFields);
$res = $this->storageBackend->removeRow(
$relationTableName,
......
$dataMap = $this->dataMapper->getDataMap(get_class($parentObject));
$columnMap = $dataMap->getColumnMap($parentPropertyName);
$relationTableName = $columnMap->getRelationTableName();
$relationMatchFields = array(
$columnMap->getParentKeyFieldName() => (int)$parentObject->getUid(),
$columnMap->getChildKeyFieldName() => (int)$relatedObject->getUid(),
);
$this->addDefaultMatchFieldsToRelationMatchFields($columnMap, $relationMatchFields);
$res = $this->storageBackend->removeRow(
$relationTableName,
array(
$columnMap->getParentKeyFieldName() => (int)$parentObject->getUid(),
$columnMap->getChildKeyFieldName() => (int)$relatedObject->getUid(),
),
$relationMatchFields,
FALSE);
return $res;
}
......
}
/**
* Returns a table row to be inserted or updated in the database
* Adds common DB fields like creationDate, storagePids etc. to a database row
*
* @param Tx_Extbase_Persistence_Mapper_DataMap $dataMap The appropriate data map representing a database table
* @param array $properties The properties of the object
* @return array A single row to be inserted in the database
* @param Tx_Extbase_DomainObject_DomainObjectInterface $object The related domain object the fields should be added for
* @param array $row The database row the fields should get added to
* @return void
*/
protected function addCommonFieldsToRow(Tx_Extbase_DomainObject_DomainObjectInterface $object, array &$row) {
$className = get_class($object);
......
}
/**
* Adds default matchFields to the passed relationRow array which will be used in queries
*
* @param Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap The column map representing the related database column
* @param array $relationRow The relation row the fields should get added to
* @return void
*/
protected function addDefaultMatchFieldsToRelationMatchFields(Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap, array &$relationMatchFields) {
$relationTableMatchFields = $columnMap->getRelationTableMatchFields();
if (is_array($relationTableMatchFields)
&& count($relationTableMatchFields) > 0) {
$relationMatchFields = array_merge($relationTableMatchFields, $relationMatchFields);
}
// support for "tablenames" column
if ($columnMap->getRelationTableRelatedTableColumnName() !== NULL) {
$relationMatchFields[$columnMap->getRelationTableRelatedTableColumnName()] = $dataMap->getTableName();
}
}
/**
* Iterate over deleted aggregate root objects and process them
*
* @return void
Classes/Persistence/Mapper/ColumnMap.php (working copy)
protected $relationTablePageIdColumnName;
/**
* Flag if the current relation is a multiColumn relation
*
* @var boolean
**/
protected $isMultiColumnRelation;
/**
* The name of the column of the relation table holding the name of the related table
*
* @var string
**/
protected $relationTableRelatedTableColumnName;
/**
* An array of field => value pairs to both insert and match against when writing/reading MM relations
*
* @var array
......
return $this->relationTablePageIdColumnName;
}
public function setRelationTableRelatedTableColumnName($relationTableRelatedTableColumnName) {
$this->relationTableRelatedTableColumnName = $relationTableRelatedTableColumnName;
}
public function getRelationTableRelatedTableColumnName() {
return $this->relationTableRelatedTableColumnName;
}
public function setIsMultiColumnRelation($isMultiColumnRelation) {
$this->isMultiColumnRelation = (boolean) $isMultiColumnRelation;
}
public function getIsMultiColumnRelation() {
return $this->isMultiColumnRelation;
}
public function isMultiColumnRelation() {
return self::getIsMultiColumnRelation();
}
public function setRelationTableMatchFields(array $relationTableMatchFields) {
$this->relationTableMatchFields = $relationTableMatchFields;
}
Classes/Persistence/Mapper/DataMapFactory.php (working copy)
* @return void
*/
protected function setRelations(Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap, $columnConfiguration, $propertyMetaData) {
if (isset($columnConfiguration)) {
if (isset($columnConfiguration) && $this->isSupportedRelationConfiguration($columnConfiguration, $propertyMetaData)) {
if (isset($columnConfiguration['MM']) || isset($columnConfiguration['foreign_selector'])) {
$columnMap = $this->setManyToManyRelation($columnMap, $columnConfiguration);
} elseif (isset($propertyMetaData['elementType'])) {
......
*/
protected function setOneToOneRelation(Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap, $columnConfiguration) {
$columnMap->setTypeOfRelation(Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_ONE);
$columnMap->setChildTableName($columnConfiguration['foreign_table']);
$columnMap->setChildTableName($this->resolveDefaultChildTableName($columnConfiguration));
$columnMap->setChildTableWhereStatement($columnConfiguration['foreign_table_where']);
$columnMap->setChildSortbyFieldName($columnConfiguration['foreign_sortby']);
$columnMap->setParentKeyFieldName($columnConfiguration['foreign_field']);
$columnMap->setParentTableFieldName($columnConfiguration['foreign_table_field']);
if($columnConfiguration['type'] != 'group') {
$columnMap->setChildKeyFieldName($columnConfiguration['foreign_key_field']);
$columnMap->setChildSortbyFieldName($columnConfiguration['foreign_sortby']);
$columnMap->setParentKeyFieldName($columnConfiguration['foreign_field']);
$columnMap->setParentTableFieldName($columnConfiguration['foreign_table_field']);
}
return $columnMap;
}
......
*/
protected function setOneToManyRelation(Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap, $columnConfiguration) {
$columnMap->setTypeOfRelation(Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY);
$columnMap->setChildTableName($columnConfiguration['foreign_table']);
$columnMap->setChildTableName($this->resolveDefaultChildTableName($columnConfiguration));
$columnMap->setChildTableWhereStatement($columnConfiguration['foreign_table_where']);
$columnMap->setChildSortbyFieldName($columnConfiguration['foreign_sortby']);
$columnMap->setParentKeyFieldName($columnConfiguration['foreign_field']);
$columnMap->setParentTableFieldName($columnConfiguration['foreign_table_field']);
if($columnConfiguration['type'] != 'group') {
$columnMap->setChildKeyFieldName($columnConfiguration['foreign_key_field']);
$columnMap->setChildSortbyFieldName($columnConfiguration['foreign_sortby']);
$columnMap->setParentKeyFieldName($columnConfiguration['foreign_field']);
$columnMap->setParentTableFieldName($columnConfiguration['foreign_table_field']);
}
return $columnMap;
}
......
protected function setManyToManyRelation(Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap, $columnConfiguration) {
$columnMap->setTypeOfRelation(Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY);
if (isset($columnConfiguration['MM'])) {
$columnMap->setChildTableName($columnConfiguration['foreign_table']);
$foreignTable = $this->resolveDefaultChildTableName($columnConfiguration);
$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']);
$matchFields = is_array($columnConfiguration['MM_match_fields']) ? $columnConfiguration['MM_match_fields'] : array();
$insertFields = is_array($columnConfiguration['MM_insert_fields']) ? array_merge($matchFields, $columnConfiguration['MM_insert_fields']) : $matchFields;
if (count($matchFields)) {
$columnMap->setRelationTableMatchFields($matchFields);
}
if (is_array($columnConfiguration['MM_insert_fields'])) {
$columnMap->setRelationTableInsertFields($columnConfiguration['MM_insert_fields']);
if (count($insertFields)) {
$columnMap->setRelationTableInsertFields($insertFields);
}
$columnMap->setRelationTableWhereStatement($columnConfiguration['MM_table_where']);
$useRelationTableRelatedTableName = FALSE;
if (!empty($columnConfiguration['MM_opposite_field'])) {
$columnMap->setParentKeyFieldName('uid_foreign');
$columnMap->setChildKeyFieldName('uid_local');
$columnMap->setChildSortByFieldName('sorting_foreign');
$foreignTable = $this->resolveDefaultChildTableName($columnConfiguration);
$foreignTableDefinitions = $this->getColumnsDefinition($foreignTable);
$oppositeFieldConfiguration = $foreignTableDefinitions[$columnConfiguration['MM_opposite_field']];
// don't set the columnMap to multiColumnRelation here, because the relation itself is not treated as such
// all we need is to define the relationTableRelatedTableColumnName here in order to build the correct MM relations
if ($this->isMultiColumnRelation($oppositeFieldConfiguration)) {
$useRelationTableRelatedTableName = TRUE;
}
} else {
$columnMap->setParentKeyFieldName('uid_local');
$columnMap->setChildKeyFieldName('uid_foreign');
$columnMap->setChildSortByFieldName('sorting');
$columnMap->setIsMultiColumnRelation( $this->isMultiColumnRelation($columnConfiguration) );
}
// automatically set required 'tablenames' fields on the relation table, just like TYPO3 core does on certain MM relations
// @see function writeMM of class class.t3lib_loaddbgroup.php
if (($columnConfiguration['type'] === 'group' && $columnConfiguration['prepend_tname'])
|| $columnConfiguration['neg_foreign_table']) {
if (!isset($matchFields['tablenames'])) {
$useRelationTableRelatedTableName = TRUE;
}
}
if ($useRelationTableRelatedTableName === TRUE
|| $columnMap->isMultiColumnRelation() === TRUE) {
$columnMap->setRelationTableRelatedTableColumnName('tablenames');
}
} elseif (isset($columnConfiguration['foreign_selector'])) {
$columns = $this->getColumnsDefinition($columnConfiguration['foreign_table']);
$childKeyFieldName = $columnConfiguration['foreign_selector'];
......
return $columnMap;
}
/**
* Checks if the given columnConfiguration belongs to a multiTable relation
*
* @param array $columnConfiguration The column configuration from $GLOBALS['TCA']
* @return boolean
* @see class.t3lib_loaddbgroup.php function readMM and writeMM
*/
private function isMultiColumnRelation($columnConfiguration) {
if ( is_array($columnConfiguration)
&& isset($columnConfiguration['allowed']) ) {
$allowedTables = t3lib_div::trimExplode(',', $columnConfiguration['allowed']);
if (count($allowedTables) > 1) {
throw new Tx_Extbase_Persistence_Exception_UnsupportedRelation('Extbase currently doesn\'t support multiTable relations. You current TCA configuration tries to create a multiTable relation to these tables: ' . implode(', ', $tableNameArray), 1295571070);
#return TRUE;
}
}
return FALSE;
}
/**
* Is resolving the correct childTableName from the given columnConfiguration.
* The main purpose of this method is to return the default table name that should be used
* to build the database relations in case it's a multitable relation like it's possible
* with TCA type "group".
*
* @param array $columnConfiguration The column configuration from $GLOBALS['TCA']
* @return string The name of the child table
*/
private function resolveDefaultChildTableName($columnConfiguration) {
$tableName = $columnConfiguration['allowed'] ? $columnConfiguration['allowed'] : $columnConfiguration['foreign_table'];
$tableNameArray = t3lib_div::trimExplode(',', $tableName);
if (count($tableNameArray) > 1) {
$tableName = current($tableNameArray);
}
return $tableName;
}
/**
* Check is the given configuration matches supported relation configurations
*
* @param array $columnConfiguration The column configuration from $GLOBALS['TCA']
* @param array $propertyMetaData The property metadata as delivered by the reflection service
* @return boolean
*/
private function isSupportedRelationConfiguration($columnConfiguration, $propertyMetaData) {
if (isset($columnConfiguration['foreign_table'])) {
return TRUE;
}
if ($columnConfiguration['type'] == 'group'
&& $columnConfiguration['internal_type'] == 'db'
&& isset($columnConfiguration['allowed'])) {
return TRUE;
}
return FALSE;
}
}
Classes/Persistence/Mapper/DataMapper.php (working copy)
* @return Tx_Extbase_Persistence_QOM_ConstraintInterface $constraint
*/
protected function getConstraint(Tx_Extbase_Persistence_QueryInterface $query, Tx_Extbase_DomainObject_DomainObjectInterface $parentObject, $propertyName, $fieldValue = '', $relationTableMatchFields = array()) {
$columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
$dataMap = $this->getDataMap(get_class($parentObject));
$columnMap = $dataMap->getColumnMap($propertyName);
if ($columnMap->getParentKeyFieldName() !== NULL) {
$constraint = $query->equals($columnMap->getParentKeyFieldName(), $parentObject);
if($columnMap->getParentTableFieldName() !== NULL) {
$constraint = $query->logicalAnd(
$constraint,
$query->equals($columnMap->getParentTableFieldName(), $this->getDataMap(get_class($parentObject))->getTableName())
$query->equals($columnMap->getParentTableFieldName(), $dataMap->getTableName())
);
}
} else {
......
$constraint = $query->logicalAnd($constraint, $query->equals($relationTableMatchFieldName, $relationTableMatchFieldValue));
}
}
// support for "tablenames" column
if ($columnMap->getRelationTableRelatedTableColumnName() !== NULL) {
$constraint = $query->logicalAnd($constraint, $query->equals($columnMap->getRelationTableRelatedTableColumnName(), $dataMap->getTableName()));
}
return $constraint;
}
Classes/Persistence/Storage/Typo3DbBackend.php (working copy)
$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->getType($className, $propertyName);
$relationTableMatchFields = $columnMap->getRelationTableMatchFields();
if (is_array($relationTableMatchFields) && count($relationTableMatchFields)) {
foreach ($relationTableMatchFields as $matchFieldName => $matchFieldValue) {
$sql['unions'][$relationTableName] .= ' AND ' . $relationTableName . '.' . $matchFieldName . '=' . $this->databaseHandle->fullQuoteStr($matchFieldValue, 'foo');
}
}
// support for "tablenames" column
if ($columnMap->getRelationTableRelatedTableColumnName() !== NULL) {
$sql['unions'][$relationTableName] .= ' AND ' . $columnMap->getRelationTableRelatedTableColumnName() . '=' . $this->databaseHandle->fullQuoteStr($tableName, 'foo');
}
} else {
throw new Tx_Extbase_Persistence_Exception('Could not determine type of relation.', 1252502725);
}
(3-3/3)