Task #6249 » Issue_6249_TcaGroupSupport.diff
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);
|
||
}
|
- « Previous
- 1
- 2
- 3
- Next »