Bug #16166 » mmetusalem_4-1.patch
t3lib/class.t3lib_loaddbgroup.php 2008-02-01 09:46:53.000000000 +0100 | ||
---|---|---|
require_once (PATH_t3lib.'class.t3lib_refindex.php');
|
||
... | ... | |
$this->MM_is_foreign = ($conf['MM_opposite_field']?1:0);
|
||
$this->MM_oppositeField = $conf['MM_opposite_field'];
|
||
$this->MM_table_where = $conf['MM_table_where'];
|
||
$this->MM_hasUidField = $conf['MM_hasUidField'];
|
||
$this->MM_match_fields = is_array($conf['MM_match_fields']) ? $conf['MM_match_fields'] : array();
|
||
$this->MM_insert_fields = is_array($conf['MM_insert_fields']) ? $conf['MM_insert_fields'] : $this->MM_match_fields;
|
||
|
||
... | ... | |
unset($tmp);
|
||
// only add the current table name if there is more than one allowed field
|
||
t3lib_div::loadTCA($this->MM_oppositeTable); // We must be sure this has been done at least once before accessing the "columns" part of TCA for a table.
|
||
$this->MM_oppositeFieldConf = $GLOBALS['TCA'][$this->MM_oppositeTable]['columns'][$this->MM_oppositeField]['config'];
|
||
if ($this->MM_oppositeFieldConf['allowed']) {
|
||
... | ... | |
* @param boolean If set, then table names will always be written.
|
||
* @return void
|
||
*/
|
||
function writeMM($tableName,$uid,$prependTableName=0) {
|
||
function writeMM($MM_tableName,$uid,$prependTableName=0) {
|
||
if ($this->MM_is_foreign) { // in case of a reverse relation
|
||
$uidLocal_field = 'uid_foreign';
|
||
... | ... | |
}
|
||
// Select, update or delete only those relations that match the configured fields
|
||
foreach ($this->MM_match_fields as $field => $value) {
|
||
$additionalWhere.= ' AND '.$field.'='.$GLOBALS['TYPO3_DB']->fullQuoteStr($value, $tableName);
|
||
$additionalWhere.= ' AND '.$field.'='.$GLOBALS['TYPO3_DB']->fullQuoteStr($value, $MM_tableName);
|
||
}
|
||
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($uidForeign_field.($prep?', tablenames':''), $tableName, $uidLocal_field.'='.$uid.$additionalWhere_tablenames.$additionalWhere);
|
||
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
|
||
$uidForeign_field.($prep?', tablenames':'').($this->MM_hasUidField?', uid':''),
|
||
$MM_tableName,
|
||
$uidLocal_field.'='.$uid.$additionalWhere_tablenames.$additionalWhere,
|
||
'',
|
||
$sorting_field
|
||
);
|
||
$oldMMs = array();
|
||
$oldMMs_inclUid = array(); // This array is similar to $oldMMs but also holds the uid of the MM-records, if any (configured by MM_hasUidField). If the UID is present it will be used to update sorting and delete MM-records. This is necessary if the "multiple" feature is used for the MM relations. $oldMMs is still needed for the in_array() search used to look if an item from $this->itemArray is in $oldMMs
|
||
while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
|
||
if (!$this->MM_is_foreign && $prep) {
|
||
$oldMMs[] = array($row['tablenames'], $row[$uidForeign_field]);
|
||
} else {
|
||
$oldMMs[] = $row[$uidForeign_field];
|
||
}
|
||
$oldMMs_inclUid[] = array($row['tablenames'], $row[$uidForeign_field], $row['uid']);
|
||
}
|
||
// For each item, insert it:
|
||
... | ... | |
}
|
||
if (in_array($item, $oldMMs)) {
|
||
unset($oldMMs[array_search($item, $oldMMs)]); // remove the item from the $oldMMs array so after this foreach loop only the ones that need to be deleted are in there.
|
||
$whereClause = $uidLocal_field.'='.$uid.' AND '.$uidForeign_field.'='.$val['id'];
|
||
$oldMMs_index = array_search($item, $oldMMs);
|
||
|
||
$whereClause = $uidLocal_field.'='.$uid.' AND '.$uidForeign_field.'='.$val['id'].
|
||
($this->MM_hasUidField ? ' AND uid='.intval($oldMMs_inclUid[$oldMMs_index][2]) : ''); // In principle, selecting on the UID is all we need to do if a uid field is available since that is unique! But as long as it "doesn't hurt" we just add it to the where clause. It should all match up.
|
||
if ($tablename) {
|
||
$whereClause .= ' AND tablenames="'.$tablename.'"';
|
||
}
|
||
$GLOBALS['TYPO3_DB']->exec_UPDATEquery($tableName, $whereClause.$additionalWhere, array($sorting_field => $c));
|
||
$GLOBALS['TYPO3_DB']->exec_UPDATEquery($MM_tableName, $whereClause.$additionalWhere, array($sorting_field => $c));
|
||
unset($oldMMs[$oldMMs_index]); // remove the item from the $oldMMs array so after this foreach loop only the ones that need to be deleted are in there.
|
||
unset($oldMMs_inclUid[$oldMMs_index]); // remove the item from the $oldMMs array so after this foreach loop only the ones that need to be deleted are in there.
|
||
} else {
|
||
$insertFields = $this->MM_insert_fields;
|
||
... | ... | |
$insertFields['tablenames'] = $tablename;
|
||
}
|
||
$GLOBALS['TYPO3_DB']->exec_INSERTquery($tableName, $insertFields);
|
||
$GLOBALS['TYPO3_DB']->exec_INSERTquery($MM_tableName, $insertFields);
|
||
|
||
if ($this->MM_is_foreign) {
|
||
$this->updateRefIndex($val['table'], $val['id']);
|
||
}
|
||
}
|
||
}
|
||
// Delete all not-used relations:
|
||
if(is_array($oldMMs) && count($oldMMs) > 0) {
|
||
$removeClauses = array();
|
||
foreach($oldMMs as $mmItem) {
|
||
if(is_array($mmItem)) {
|
||
$removeClauses[] = 'tablenames="'.$mmItem[0].'" AND '.$uidForeign_field.'='.$mmItem[1];
|
||
$updateRefIndex_records = array();
|
||
foreach($oldMMs as $oldMM_key => $mmItem) {
|
||
if ($this->MM_hasUidField) { // If UID field is present, of course we need only use that for deleting...:
|
||
$removeClauses[] = 'uid='.intval($oldMMs_inclUid[$oldMM_key][2]);
|
||
$elDelete = $oldMMs_inclUid[$oldMM_key];
|
||
} else {
|
||
$removeClauses[] = $uidForeign_field.'='.$mmItem;
|
||
if(is_array($mmItem)) {
|
||
$removeClauses[] = 'tablenames="'.$mmItem[0].'" AND '.$uidForeign_field.'='.$mmItem[1];
|
||
} else {
|
||
$removeClauses[] = $uidForeign_field.'='.$mmItem;
|
||
}
|
||
}
|
||
if ($this->MM_is_foreign) {
|
||
if(is_array($mmItem)) {
|
||
$updateRefIndex_records[] = array($mmItem[0],$mmItem[1]);
|
||
} else {
|
||
$updateRefIndex_records[] = array($this->firstTable,$mmItem);
|
||
}
|
||
}
|
||
}
|
||
$deleteAddWhere = ' AND ('.implode(' OR ', $removeClauses).')';
|
||
$GLOBALS['TYPO3_DB']->exec_DELETEquery($tableName, $uidLocal_field.'='.intval($uid).$deleteAddWhere.$additionalWhere_tablenames.$additionalWhere);
|
||
$GLOBALS['TYPO3_DB']->exec_DELETEquery($MM_tableName, $uidLocal_field.'='.intval($uid).$deleteAddWhere.$additionalWhere_tablenames.$additionalWhere);
|
||
|
||
// Update ref index:
|
||
foreach($updateRefIndex_records as $pair) {
|
||
$this->updateRefIndex($pair[0],$pair[1]);
|
||
}
|
||
}
|
||
|
||
// Update ref index; In tcemain it is not certain that this will happen because if only the MM field is changed the record itself is not updated and so the ref-index is not either. This could also have been fixed in updateDB in tcemain, however I decided to do it here ...
|
||
$this->updateRefIndex($this->currentTable,$uid);
|
||
}
|
||
}
|
||
/**
|
||
* Remaps MM table elements from one local uid to another
|
||
* Does NOT update the reference index for you, must be called subsequently to do that!
|
||
*
|
||
* @param string MM table name
|
||
* @param integer Local, current UID
|
||
* @param integer Local, new UID
|
||
* @param boolean If set, then table names will always be written.
|
||
* @return void
|
||
*/
|
||
function remapMM($MM_tableName,$uid,$newUid,$prependTableName=0) {
|
||
if ($this->MM_is_foreign) { // in case of a reverse relation
|
||
$uidLocal_field = 'uid_foreign';
|
||
} else { // default
|
||
$uidLocal_field = 'uid_local';
|
||
}
|
||
// If there are tables...
|
||
$tableC = count($this->tableArray);
|
||
if ($tableC) {
|
||
$prep = ($tableC>1||$prependTableName||$this->MM_isMultiTableRelationship) ? 1 : 0; // boolean: does the field "tablename" need to be filled?
|
||
$c=0;
|
||
$additionalWhere_tablenames = '';
|
||
if ($this->MM_is_foreign && $prep) {
|
||
$additionalWhere_tablenames = ' AND tablenames="'.$this->currentTable.'"';
|
||
}
|
||
$additionalWhere = '';
|
||
// add WHERE clause if configured
|
||
if ($this->MM_table_where) {
|
||
$additionalWhere.= "\n".str_replace('###THIS_UID###', intval($uid), $this->MM_table_where);
|
||
}
|
||
// Select, update or delete only those relations that match the configured fields
|
||
foreach ($this->MM_match_fields as $field => $value) {
|
||
$additionalWhere.= ' AND '.$field.'='.$GLOBALS['TYPO3_DB']->fullQuoteStr($value, $MM_tableName);
|
||
}
|
||
$GLOBALS['TYPO3_DB']->exec_UPDATEquery($MM_tableName, $uidLocal_field.'='.intval($uid).$additionalWhere_tablenames.$additionalWhere, array($uidLocal_field => $newUid));
|
||
}
|
||
}
|
||
-- t3lib/class.t3lib_tcemain.php.bkp 2008-02-01 11:41:42.000000000 +0100
|
||
++ t3lib/class.t3lib_tcemain.php 2008-02-01 09:48:16.000000000 +0100
|
||
... | ... | |
if ($status=='update') {
|
||
$dbAnalysis->writeMM($tcaFieldConf['MM'],$id,$prep);
|
||
} else {
|
||
$this->dbAnalysisStore[] = array($dbAnalysis,$tcaFieldConf['MM'],$id,$prep); // This will be traversed later to execute the actions
|
||
$this->dbAnalysisStore[] = array($dbAnalysis,$tcaFieldConf['MM'],$id,$prep,$currentTable); // This will be traversed later to execute the actions
|
||
}
|
||
$valueArray = $dbAnalysis->countItems();
|
||
} elseif ($type == 'inline') {
|
||
... | ... | |
$dsConf['TCEforms']['config'],
|
||
$dataValues[$key][$vKey],
|
||
$dataValues_current[$key][$vKey],
|
||
$uploadedFiles[$key][$vKey]
|
||
$uploadedFiles[$key][$vKey],
|
||
$structurePath.$key.'/'.$vKey.'/'
|
||
);
|
||
}
|
||
} else { // Default
|
||
... | ... | |
$curVersion['t3ver_swapmode'] = $swapVersion['t3ver_swapmode'];
|
||
}
|
||
// Registering and swapping MM relations in current and swap records:
|
||
$this->version_remapMMForVersionSwap($table,$id,$swapWith);
|
||
// Execute swapping:
|
||
$sqlErrors = array();
|
||
$GLOBALS['TYPO3_DB']->exec_UPDATEquery($table,'uid='.intval($id),$swapVersion);
|
||
... | ... | |
// If a change has been done, set the new value(s)
|
||
if ($set) {
|
||
if ($conf['MM']) {
|
||
// FIXME $theUidToUpdate is undefined
|
||
$dbAnalysis->writeMM($conf['MM'], $theUidToUpdate, $prependName);
|
||
$dbAnalysis->writeMM($conf['MM'], $MM_localUid, $prependName);
|
||
} else {
|
||
$vArray = $dbAnalysis->getValueArray($prependName);
|
||
if ($conf['type']=='select') {
|
||
... | ... | |
return $out;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Swaps MM-relations for current/swap record, see version_swap()
|
||
*
|
||
* @param string Table for the two input records
|
||
* @param integer Current record (about to go offline)
|
||
* @param integer Swap record (about to go online)
|
||
* @return void
|
||
* @see version_swap()
|
||
*/
|
||
function version_remapMMForVersionSwap($table,$id,$swapWith) {
|
||
global $TCA;
|
||
|
||
// Actually, selecting the records fully is only need if flexforms are found inside... This could be optimized ...
|
||
$currentRec = t3lib_BEfunc::getRecord($table,$id);
|
||
$swapRec = t3lib_BEfunc::getRecord($table,$swapWith);
|
||
|
||
$this->version_remapMMForVersionSwap_reg = array();
|
||
|
||
foreach($TCA[$table]['columns'] as $field => $fConf) {
|
||
$conf = $fConf['config'];
|
||
|
||
if ($this->isReferenceField($conf)) {
|
||
$allowedTables = $conf['type']=='group' ? $conf['allowed'] : $conf['foreign_table'].','.$conf['neg_foreign_table'];
|
||
$prependName = $conf['type']=='group' ? $conf['prepend_tname'] : $conf['neg_foreign_table'];
|
||
if ($conf['MM']) {
|
||
|
||
$dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
|
||
/* @var $dbAnalysis t3lib_loadDBGroup */
|
||
$dbAnalysis->start('', $allowedTables, $conf['MM'], $id, $table, $conf);
|
||
if (count($dbAnalysis->getValueArray($prependName))) {
|
||
$this->version_remapMMForVersionSwap_reg[$id][$field] = array($dbAnalysis, $conf['MM'], $prependName);
|
||
}
|
||
|
||
$dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
|
||
/* @var $dbAnalysis t3lib_loadDBGroup */
|
||
$dbAnalysis->start('', $allowedTables, $conf['MM'], $swapWith, $table, $conf);
|
||
if (count($dbAnalysis->getValueArray($prependName))) {
|
||
$this->version_remapMMForVersionSwap_reg[$swapWith][$field] = array($dbAnalysis, $conf['MM'], $prependName);
|
||
}
|
||
}
|
||
} elseif($conf['type']=='flex') {
|
||
// Current record
|
||
$dataStructArray = t3lib_BEfunc::getFlexFormDS($conf, $currentRec, $table);
|
||
$currentValueArray = t3lib_div::xml2array($currentRec[$field]);
|
||
if (is_array($currentValueArray)) {
|
||
$this->checkValue_flex_procInData(
|
||
$currentValueArray['data'],
|
||
array(), // Not used.
|
||
array(), // Not used.
|
||
$dataStructArray,
|
||
array($table,$id,$field), // Parameters.
|
||
'version_remapMMForVersionSwap_flexFormCallBack'
|
||
);
|
||
}
|
||
// Swap record
|
||
$dataStructArray = t3lib_BEfunc::getFlexFormDS($conf, $swapRec, $table);
|
||
$currentValueArray = t3lib_div::xml2array($swapRec[$field]);
|
||
if (is_array($currentValueArray)) {
|
||
$this->checkValue_flex_procInData(
|
||
$currentValueArray['data'],
|
||
array(), // Not used.
|
||
array(), // Not used.
|
||
$dataStructArray,
|
||
array($table,$swapWith,$field), // Parameters.
|
||
'version_remapMMForVersionSwap_flexFormCallBack'
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
// Execute:
|
||
$this->version_remapMMForVersionSwap_execSwap($table,$id,$swapWith);
|
||
}
|
||
/**
|
||
* Callback function for traversing the FlexForm structure in relation to ...
|
||
*
|
||
* @param array Array of parameters in num-indexes: table, uid, field
|
||
* @param array TCA field configuration (from Data Structure XML)
|
||
* @param string The value of the flexForm field
|
||
* @param string Not used.
|
||
* @param string Not used.
|
||
* @param string Path in flexforms
|
||
* @return array Result array with key "value" containing the value of the processing.
|
||
* @see version_remapMMForVersionSwap(), checkValue_flex_procInData_travDS()
|
||
*/
|
||
function version_remapMMForVersionSwap_flexFormCallBack($pParams, $dsConf, $dataValue, $dataValue_ext1, $dataValue_ext2, $path) {
|
||
// Extract parameters:
|
||
list($table, $uid, $field) = $pParams;
|
||
if ($this->isReferenceField($dsConf)) {
|
||
$allowedTables = $dsConf['type']=='group' ? $dsConf['allowed'] : $dsConf['foreign_table'].','.$dsConf['neg_foreign_table'];
|
||
$prependName = $dsConf['type']=='group' ? $dsConf['prepend_tname'] : $dsConf['neg_foreign_table'];
|
||
if ($dsConf['MM']) {
|
||
$dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
|
||
/* @var $dbAnalysis t3lib_loadDBGroup */
|
||
$dbAnalysis->start('', $allowedTables, $dsConf['MM'], $uid, $table, $dsConf);
|
||
$this->version_remapMMForVersionSwap_reg[$uid][$field.'/'.$path] = array($dbAnalysis, $dsConf['MM'], $prependName);
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Performing the remapping operations found necessary in version_remapMMForVersionSwap()
|
||
* It must be done in three steps with an intermediate "fake" uid. The UID can be something else than -$id (fx. 9999999+$id if you dare... :-)- as long as it is unique.
|
||
*
|
||
* @param string Table for the two input records
|
||
* @param integer Current record (about to go offline)
|
||
* @param integer Swap record (about to go online)
|
||
* @return void
|
||
* @see version_remapMMForVersionSwap()
|
||
*/
|
||
function version_remapMMForVersionSwap_execSwap($table,$id,$swapWith) {
|
||
|
||
if (is_array($this->version_remapMMForVersionSwap_reg[$id])) {
|
||
foreach($this->version_remapMMForVersionSwap_reg[$id] as $field => $str) {
|
||
$str[0]->remapMM($str[1],$id,-$id,$str[2]);
|
||
}
|
||
}
|
||
if (is_array($this->version_remapMMForVersionSwap_reg[$swapWith])) {
|
||
foreach($this->version_remapMMForVersionSwap_reg[$swapWith] as $field => $str) {
|
||
$str[0]->remapMM($str[1],$swapWith,$id,$str[2]);
|
||
}
|
||
}
|
||
if (is_array($this->version_remapMMForVersionSwap_reg[$id])) {
|
||
foreach($this->version_remapMMForVersionSwap_reg[$id] as $field => $str) {
|
||
$str[0]->remapMM($str[1],-$id,$swapWith,$str[2]);
|
||
}
|
||
}
|
||
}
|
||
... | ... | |
function dbAnalysisStoreExec() {
|
||
reset($this->dbAnalysisStore);
|
||
while(list($k,$v)=each($this->dbAnalysisStore)) {
|
||
$id = $this->substNEWwithIDs[$v[2]];
|
||
$id = t3lib_BEfunc::wsMapId($v[4],$this->substNEWwithIDs[$v[2]]);
|
||
if ($id) {
|
||
$v[2] = $id;
|
||
$v[0]->writeMM($v[1],$v[2],$v[3]);
|
- « Previous
- 1
- …
- 11
- 12
- 13
- Next »