Project

General

Profile

Bug #16518 ยป mmtables_v2.patch

Administrator Admin, 2006-09-03 20:29

View differences:

C:/apache/typo3/typo3_src-trunk/t3lib/class.t3lib_admin.php (working copy)
if ($fieldConf['internal_type']=='db') {
// dbs - group
$dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
$dbAnalysis->start($row[$field],$fieldConf['allowed'],$fieldConf['MM'],$row['uid']);
$dbAnalysis->start($row[$field],$fieldConf['allowed'],$fieldConf['MM'],$row['uid'], $table, $fieldConf);
reset($dbAnalysis->itemArray);
while (list(,$tempArr)=each($dbAnalysis->itemArray)) {
$this->checkGroupDBRefs[$tempArr['table']][$tempArr['id']]+=1;
......
if ($fieldConf['type']=='select' && $fieldConf['foreign_table']) {
// dbs - select
$dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
$dbAnalysis->start($row[$field],$fieldConf['foreign_table'],$fieldConf['MM'],$row['uid']);
$dbAnalysis->start($row[$field],$fieldConf['foreign_table'],$fieldConf['MM'],$row['uid'], $table, $fieldConf);
reset($dbAnalysis->itemArray);
while (list(,$tempArr)=each($dbAnalysis->itemArray)) {
if ($tempArr['id']>0) {
......
$allowedTables = ($fieldConf['type']=='group') ? $fieldConf['allowed'] : $fieldConf['foreign_table'];
$dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
$dbAnalysis->start($row[$field],$allowedTables,$fieldConf['MM'],$row['uid']);
$dbAnalysis->start($row[$field],$allowedTables,$fieldConf['MM'],$row['uid'], $table, $fieldConf);
reset($dbAnalysis->itemArray);
while (list(,$tempArr)=each($dbAnalysis->itemArray)) {
if ($tempArr['table']==$searchTable && $tempArr['id']==$id) {
C:/apache/typo3/typo3_src-trunk/t3lib/class.t3lib_befunc.php (working copy)
*
*/
require_once (PATH_t3lib.'class.t3lib_loaddbgroup.php');
/**
* Standard functions available for the TYPO3 backend.
* Don't instantiate - call functions with "t3lib_BEfunc::" prefixed the function name.
......
}
$MMfield = join(',',$MMfields);
}
$MMres = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query(
$MMfield,
($table!=$theColConf['foreign_table']?$table:''),
$theColConf['MM'],
$theColConf['foreign_table'],
'AND '.$theColConf['MM'].'.uid_local ='.intval($uid).t3lib_BEfunc::deleteClause($theColConf['foreign_table'])
);
if ($MMres) {
$dbGroup = t3lib_div::makeInstance('t3lib_loadDBGroup');
$dbGroup->start($value, $theColConf['foreign_table'], $theColConf['MM'], $uid, $table, $theColConf);
$selectUids = $dbGroup->tableArray[$theColConf['foreign_table']];
if (is_array($selectUids) && count($selectUids)>0) {
$MMres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
'uid, '.$MMfield,
$theColConf['foreign_table'],
'uid IN ('.implode(',', $selectUids).')'
);
while($MMrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($MMres)) {
$mmlA[] = ($noRecordLookup?$MMrow['uid']:t3lib_BEfunc::getRecordTitle($theColConf['foreign_table'], $MMrow));
}
C:/apache/typo3/typo3_src-trunk/t3lib/class.t3lib_loaddbgroup.php (working copy)
var $dbPaths=Array();
var $firstTable = ''; // Will contain the first table name in the $tablelist (for positive ids)
var $secondTable = ''; // Will contain the second table name in the $tablelist (for negative ids)
// private
var $MM_is_foreign = 0; // boolean - if 1, uid_local and uid_foreign are switched, and the current table is inserted as tablename - this means you display a foreign relation "from the opposite side"
var $MM_oppositeField = ''; // field name at the "local" side of the MM relation
var $MM_oppositeTable = ''; // only set if MM_is_foreign is set
var $MM_oppositeFieldConf = ''; // only set if MM_is_foreign is set
var $MM_isMultiTableRelationship = 0; // is empty by default; if MM_is_foreign is set and there is more than one table allowed (on the "local" side), then it contains the first table (as a fallback)
var $currentTable; // current table => Only needed for reverse relations
/**
* Initialization of the class.
*
......
* @param string Comma list of tables, first table takes priority if no table is set for an entry in the list.
* @param string Name of a MM table.
* @param integer Local UID for MM lookup
* @param string current table name
* @param integer TCA configuration for current field
* @return void
*/
function start($itemlist,$tablelist, $MMtable='',$MMuid=0) {
function start($itemlist, $tablelist, $MMtable='', $MMuid=0, $currentTable='', $conf=array()) {
// SECTION: MM reverse relations
$this->MM_is_foreign = ($conf['MM_opposite_field']?1:0);
$this->MM_oppositeField = $conf['MM_opposite_field'];
$this->currentTable = $currentTable;
if ($this->MM_is_foreign) {
$tmp = ($conf['type']==='group'?$conf['allowed']:$conf['foreign_table']);
// normally, $conf['allowed'] can contain a list of tables, but as we are looking at a MM relation from the foreign side, it only makes sense to allow one one table in $conf['allowed']
$tmp = t3lib_div::trimExplode(',', $tmp);
$this->MM_oppositeTable = $tmp[0];
unset($tmp);
// only add the current table name if there is more than one allowed field
$this->MM_oppositeFieldConf = $GLOBALS['TCA'][$this->MM_oppositeTable]['columns'][$this->MM_oppositeField]['config'];
if ($this->MM_oppositeFieldConf['allowed']) {
$oppositeFieldConf_allowed = explode(',', $this->MM_oppositeFieldConf['allowed']);
if (count($oppositeFieldConf_allowed) > 1) {
$this->MM_isMultiTableRelationship = $oppositeFieldConf_allowed[0];
}
}
}
// SECTION: normal MM relations
// If the table list is "*" then all tables are used in the list:
if (!strcmp(trim($tablelist),'*')) {
$tablelist = implode(',',array_keys($GLOBALS['TCA']));
......
*/
function readMM($tableName,$uid) {
$key=0;
if ($this->MM_is_foreign) { // in case of a reverse relation
$uidLocal_field = 'uid_foreign';
$uidForeign_field = 'uid_local';
$sorting_field = 'sorting_foreign';
if ($this->MM_isMultiTableRelationship) {
$additionalWhere = ' AND ( tablenames="'.$this->currentTable.'"';
if ($this->currentTable == $this->MM_isMultiTableRelationship) { // be backwards compatible! When allowing more than one table after having previously allowed only one table, this case applies.
$additionalWhere .= ' OR tablenames=""';
}
$additionalWhere .= ' ) ';
}
$theTable = $this->MM_oppositeTable;
} else { // default
$uidLocal_field = 'uid_local';
$uidForeign_field = 'uid_foreign';
$additionalWhere = '';
$sorting_field = 'sorting';
}
// Select all MM relations:
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $tableName, 'uid_local='.intval($uid), '', 'sorting');
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $tableName, $uidLocal_field.'='.intval($uid).$additionalWhere, '', $sorting_field);
while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
$theTable = $row['tablenames'] ? $row['tablenames'] : $this->firstTable; // If tablesnames columns exists and contain a name, then this value is the table, else it's the firstTable...
if (($row['uid_foreign'] || $theTable=='pages') && $theTable && isset($this->tableArray[$theTable])) {
$this->itemArray[$key]['id'] = $row['uid_foreign'];
if (!$this->MM_is_foreign) { // default
$theTable = $row['tablenames'] ? $row['tablenames'] : $this->firstTable; // If tablesnames columns exists and contain a name, then this value is the table, else it's the firstTable...
}
if (($row[$uidForeign_field] || $theTable=='pages') && $theTable && isset($this->tableArray[$theTable])) {
$this->itemArray[$key]['id'] = $row[$uidForeign_field];
$this->itemArray[$key]['table'] = $theTable;
$this->tableArray[$theTable][]= $row['uid_foreign'];
$this->tableArray[$theTable][]= $row[$uidForeign_field];
} elseif ($this->registerNonTableValues) {
$this->itemArray[$key]['id'] = $row['uid_foreign'];
$this->itemArray[$key]['id'] = $row[$uidForeign_field];
$this->itemArray[$key]['table'] = '_NO_TABLE';
$this->nonTableArray[] = $row['uid_foreign'];
$this->nonTableArray[] = $row[$uidForeign_field];
}
$key++;
}
......
*/
function writeMM($tableName,$uid,$prependTableName=0) {
// Delete all relations:
$GLOBALS['TYPO3_DB']->exec_DELETEquery($tableName, 'uid_local='.intval($uid));
if ($this->MM_is_foreign) { // in case of a reverse relation
$uidLocal_field = 'uid_foreign';
$uidForeign_field = 'uid_local';
$sorting_field = 'sorting_foreign';
} else { // default
$uidLocal_field = 'uid_local';
$uidForeign_field = 'uid_foreign';
$sorting_field = 'sorting';
} // TODO: SORTING!
// If there are tables...
$tableC = count($this->tableArray);
if ($tableC) {
$prep = ($tableC>1||$prependTableName) ? 1 : 0;
$prep = ($tableC>1||$prependTableName||$this->MM_isMultiTableRelationship) ? 1 : 0; // boolean: does the field "tablename" need to be filled?
$c=0;
$tName=array();
$additionalWhere_tablenames = '';
if ($this->MM_is_foreign && $prep) {
$additionalWhere_tablenames = ' AND tablenames="'.$this->currentTable.'"';
}
$existingMMs = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows($uidForeign_field, $tableName, $uidLocal_field.'='.$uid.$additionalWhere_tablenames, '', '', '', $uidForeign_field);
// For each item, insert it:
$uidList = array();
foreach($this->itemArray as $val) {
$c++;
$insertFields = array(
'uid_local' => $uid,
'uid_foreign' => $val['id'],
'sorting' => $c
);
$uidList[] = $val['id'];
if ($prep || $val['table']=='_NO_TABLE') {
$insertFields['tablenames'] = $val['table'];
if ($this->MM_is_foreign) { // insert current table if needed
$tablename = $this->currentTable;
} else {
$tablename = $val['table'];
}
} else {
$tablename = '';
}
$GLOBALS['TYPO3_DB']->exec_INSERTquery($tableName, $insertFields);
if (isset($existingMMs[$val['id']])) {
$whereClause = $uidLocal_field.'='.$uid.' AND '.$uidForeign_field.'='.$val['id'];
if ($tablename)
$whereClause .= ' AND tablenames="'.$tablename.'"';
$GLOBALS['TYPO3_DB']->exec_UPDATEquery($tableName, $whereClause, array($sorting_field => $c));
} else {
$GLOBALS['TYPO3_DB']->exec_INSERTquery($tableName, array(
$uidLocal_field => $uid,
$uidForeign_field => $val['id'],
$sorting_field => $c,
'tablenames' => $tablename
));
}
}
// Delete all not-used relations:
$additionalWhere = '';
if (count($uidList)) {
$additionalWhere = ' AND '.$uidForeign_field.' NOT IN ( '.implode(',', $uidList).' ) ';
}
$GLOBALS['TYPO3_DB']->exec_DELETEquery($tableName, $uidLocal_field.'='.intval($uid).$additionalWhere.$additionalWhere_tablenames);
}
}
C:/apache/typo3/typo3_src-trunk/t3lib/class.t3lib_refindex.php (working copy)
$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_opposite_field']) {
return array();
}
$dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
$dbAnalysis->start($value,$allowedTables,$conf['MM'],$uid);
C:/apache/typo3/typo3_src-trunk/t3lib/class.t3lib_tcemain.php (working copy)
$fieldArray = $this->newFieldArray($table); // Get a fieldArray with default values
if (isset($incomingFieldArray['pid'])) { // A pid must be set for new records.
// $value = the pid
$pid_value = $incomingFieldArray['pid'];
$pid_value = $incomingFieldArray['pid'];
// Checking and finding numerical pid, it may be a string-reference to another value
$OK = 1;
......
);
break;
case 'db':
$valueArray = $this->checkValue_group_select_processDBdata($valueArray,$tcaFieldConf,$id,$status,'group');
$valueArray = $this->checkValue_group_select_processDBdata($valueArray,$tcaFieldConf,$id,$status,'group', $table);
break;
}
}
// For select types which has a foreign table attached:
if ($tcaFieldConf['type']=='select' && $tcaFieldConf['foreign_table']) {
$valueArray = $this->checkValue_group_select_processDBdata($valueArray,$tcaFieldConf,$id,$status,'select');
$valueArray = $this->checkValue_group_select_processDBdata($valueArray,$tcaFieldConf,$id,$status,'select', $table);
}
// BTW, checking for min and max items here does NOT make any sense when MM is used because the above function calls will just return an array with a single item (the count) if MM is used... Why didn't I perform the check before? Probably because we could not evaluate the validity of record uids etc... Hmm...
......
* @param integer Record id, used for look-up of MM relations (local_uid)
* @param string Status string ('update' or 'new')
* @param string The type, either 'select' or 'group'
* @param string Table name, needs to be passed to t3lib_loadDBGroup
* @return array Modified value array
*/
function checkValue_group_select_processDBdata($valueArray,$tcaFieldConf,$id,$status,$type) {
function checkValue_group_select_processDBdata($valueArray,$tcaFieldConf,$id,$status,$type,$currentTable) {
$tables = $type=='group'?$tcaFieldConf['allowed']:$tcaFieldConf['foreign_table'].','.$tcaFieldConf['neg_foreign_table'];
$prep = $type=='group'?$tcaFieldConf['prepend_tname']:$tcaFieldConf['neg_foreign_table'];
$dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
$dbAnalysis->registerNonTableValues=$tcaFieldConf['allowNonIdValues'] ? 1 : 0;
$dbAnalysis->start(implode(',',$valueArray),$tables);
$dbAnalysis->start(implode(',',$valueArray),$tables, '', 0, $currentTable, $tcaFieldConf);
if ($tcaFieldConf['MM']) {
if ($status=='update') {
......
$prependName = $conf['type']=='group' ? $conf['prepend_tname'] : $conf['neg_foreign_table'];
if ($conf['MM']) {
$dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
$dbAnalysis->start('',$allowedTables,$conf['MM'],$uid);
$dbAnalysis->start('', $allowedTables, $conf['MM'], $uid, $table, $conf);
$value = implode(',',$dbAnalysis->getValueArray($prependName));
}
if ($value) { // Setting the value in this array will notify the remapListedDBRecords() function that this field MAY need references to be corrected
......
/*
Version ID swapping principles:
- Version from archive (future/past, called "swap version") will get the uid of the "t3ver_oid", the official element with uid = "t3ver_oid" will get the new versions old uid. PIDs are swapped also
- Version from archive (future/past, called "swap version") will get the uid of the "t3ver_oid", the official element with uid = "t3ver_oid" will get the new versions old uid. PIDs are swapped also
uid pid uid t3ver_oid pid
1: 13 123 --> -13 247 123 (Original has negated UID, and sets t3ver_oid to the final UID (which is nice to know for recovery). PID is unchanged at this point)
......
switch($conf['type']) {
case 'group':
case 'select':
$vArray = $this->remapListedDBRecords_procDBRefs($conf, $value, $theUidToUpdate);
$vArray = $this->remapListedDBRecords_procDBRefs($conf, $value, $theUidToUpdate, $table);
if (is_array($vArray)) {
$newData[$fieldName] = implode(',',$vArray);
}
......
// If references are set for this field, set flag so they can be corrected later:
if ($this->isReferenceField($dsConf) && strlen($dataValue)) {
$vArray = $this->remapListedDBRecords_procDBRefs($dsConf, $dataValue, $uid);
$vArray = $this->remapListedDBRecords_procDBRefs($dsConf, $dataValue, $uid, $table);
if (is_array($vArray)) {
$dataValue = implode(',',$vArray);
}
......
* @param array TCA field config
* @param string Field value
* @param integer UID of local record (for MM relations - might need to change if support for FlexForms should be done!)
* @param string Table name
* @return array Returns array of items ready to implode for field content.
* @see remapListedDBRecords()
*/
function remapListedDBRecords_procDBRefs($conf, $value, $MM_localUid) {
function remapListedDBRecords_procDBRefs($conf, $value, $MM_localUid, $table) {
// Initialize variables
$set = FALSE; // Will be set true if an upgrade should be done...
......
// Convert value to list of references:
$dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
$dbAnalysis->registerNonTableValues = ($conf['type']=='select' && $conf['allowNonIdValues']) ? 1 : 0;
$dbAnalysis->start($value, $allowedTables, $conf['MM'], $MM_localUid);
$dbAnalysis->start($value, $allowedTables, $conf['MM'], $MM_localUid, $table, $conf);
// Traverse those references and map IDs:
foreach($dbAnalysis->itemArray as $k => $v) {
......
function int_pageTreeInfo($CPtable,$pid,$counter, $rootID) {
if ($counter) {
$addW = !$this->admin ? ' AND '.$this->BE_USER->getPagePermsClause($this->pMap['show']) : '';
$mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'pages', 'pid='.intval($pid).$this->deleteClause('pages').$addW, '', 'sorting DESC');
while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) {
$mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'pages', 'pid='.intval($pid).$this->deleteClause('pages').$addW, '', 'sorting DESC');
while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) {
if ($row['uid']!=$rootID) {
$CPtable[$row['uid']] = $pid;
if ($counter-1) { // If the uid is NOT the rootID of the copyaction and if we are supposed to walk further down
$CPtable = $this->int_pageTreeInfo($CPtable,$row['uid'],$counter-1, $rootID);
}
$CPtable[$row['uid']] = $pid;
if ($counter-1) { // If the uid is NOT the rootID of the copyaction and if we are supposed to walk further down
$CPtable = $this->int_pageTreeInfo($CPtable,$row['uid'],$counter-1, $rootID);
}
}
}
}
}
return $CPtable;
return $CPtable;
}
/**
......
case 0:
$emails = $this->notifyStageChange_getEmails($workspaceRec['members']);
break;
default:
default:
$emails = $this->notifyStageChange_getEmails($workspaceRec['adminusers'], TRUE);
break;
}
C:/apache/typo3/typo3_src-trunk/t3lib/class.t3lib_transferdata.php (working copy)
break;
case 'db':
$loadDB = t3lib_div::makeInstance('t3lib_loadDBGroup');
$loadDB->start($data, $fieldConfig['config']['allowed'], $fieldConfig['config']['MM'], $row['uid']);
$loadDB->start($data, $fieldConfig['config']['allowed'], $fieldConfig['config']['MM'], $row['uid'], $table, $fieldConfig['config']);
$loadDB->getFromDB();
$data = $loadDB->readyForInterface();
break;
......
// Add "foreign table" stuff:
if ($TCA[$fieldConfig['config']['foreign_table']]) {
$dataAcc = $this->selectAddForeign($dataAcc, $elements, $fieldConfig, $field, $TSconfig, $row);
$dataAcc = $this->selectAddForeign($dataAcc, $elements, $fieldConfig, $field, $TSconfig, $row, $table);
}
// Always keep the native order for display in interface:
......
} else { // Normal, <= 1 -> value without title on it
if ($TCA[$fieldConfig['config']['foreign_table']]) {
// Getting the data
$dataIds = $this->getDataIdList($elements, $fieldConfig, $row);
$dataIds = $this->getDataIdList($elements, $fieldConfig, $row, $table);
if (!count($dataIds)) $dataIds = array(0);
$dataAcc[]=$dataIds[0];
......
* @param string The field name
* @param array TSconfig for the record
* @param array The record
* @param array The current table
* @return array Modified $dataAcc array
* @access private
* @see renderRecord_selectProc()
*/
function selectAddForeign($dataAcc, $elements, $fieldConfig, $field, $TSconfig, $row) {
function selectAddForeign($dataAcc, $elements, $fieldConfig, $field, $TSconfig, $row, $table) {
global $TCA;
// Init:
......
// At this point all records that CAN be selected is found in $recordList
// Now, get the data from loadDBgroup based on the input list of values.
$dataIds = $this->getDataIdList($elements, $fieldConfig, $row);
$dataIds = $this->getDataIdList($elements, $fieldConfig, $row, $table);
if ($fieldConfig['config']['MM']) $dataAcc=array(); // Reset, if MM (which cannot bear anything but real relations!)
// After this we can traverse the loadDBgroup values and match values with the list of possible values in $recordList:
......
* @param array The array of original elements - basically the field value exploded by ","
* @param array Field configuration from TCA
* @param array The data array, currently. Used to set the "local_uid" for selecting MM relation records.
* @param string Current table name. passed on to t3lib_loadDBGroup
* @return array An array with ids of the records from the input elements array.
* @access private
*/
function getDataIdList($elements, $fieldConfig, $row) {
function getDataIdList($elements, $fieldConfig, $row, $table) {
$loadDB = t3lib_div::makeInstance('t3lib_loadDBGroup');
$loadDB->registerNonTableValues=$fieldConfig['config']['allowNonIdValues'] ? 1 : 0;
$loadDB->start(implode(',',$elements), $fieldConfig['config']['foreign_table'].','.$fieldConfig['config']['neg_foreign_table'], $fieldConfig['config']['MM'], $row['uid']);
$loadDB->start(implode(',',$elements),
$fieldConfig['config']['foreign_table'].','.$fieldConfig['config']['neg_foreign_table'],
$fieldConfig['config']['MM'],
$row['uid'],
$table,
$fieldConfig['config']
);
$idList = $loadDB->convertPosNeg($loadDB->getValueArray(),$fieldConfig['config']['foreign_table'],$fieldConfig['config']['neg_foreign_table']);
C:/apache/typo3/typo3_src-trunk/typo3/mod/user/ws/workspaceforms.php (working copy)
$config = &$GLOBALS['TCA']['sys_workspace']['columns']['adminusers']['config'];
// Notice: $config['MM'] is not set in the current version of $TCA but
// we still pass it to ensure compatibility with feature versions!
$loadDB->start($GLOBALS['BE_USER']->user['uid'], $config['allowed'], $config['MM'], $uid);
$loadDB->start($GLOBALS['BE_USER']->user['uid'], $config['allowed'], $config['MM'], $uid, 'sys_workspace', $config);
$loadDB->getFromDB();
return $loadDB->readyForInterface();
}
    (1-1/1)