|
<?php
|
|
/***************************************************************
|
|
* Copyright notice
|
|
*
|
|
* (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
|
|
* All rights reserved
|
|
*
|
|
* This script is part of the TYPO3 project. The TYPO3 project is
|
|
* free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* The GNU General Public License can be found at
|
|
* http://www.gnu.org/copyleft/gpl.html.
|
|
* A copy is found in the textfile GPL.txt and important notices to the license
|
|
* from the author is found in LICENSE.txt distributed with these scripts.
|
|
*
|
|
*
|
|
* This script is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* This copyright notice MUST APPEAR in all copies of the script!
|
|
***************************************************************/
|
|
/**
|
|
* Contains class for loading database groups
|
|
*
|
|
* $Id: class.t3lib_loaddbgroup.php,v 1.12.6.3 2006/03/16 11:12:12 rfritz Exp $
|
|
* Revised for TYPO3 3.6 September/2003 by Kasper Skaarhoj
|
|
*
|
|
* @author Kasper Skaarhoj <kasperYYYY@typo3.com>
|
|
*/
|
|
/**
|
|
* [CLASS/FUNCTION INDEX of SCRIPT]
|
|
*
|
|
*
|
|
*
|
|
* 72: class t3lib_loadDBGroup
|
|
* 99: function start($itemlist,$tablelist, $MMtable='',$MMuid=0)
|
|
* 140: function readList($itemlist)
|
|
* 186: function readMM($tableName,$uid)
|
|
* 215: function writeMM($tableName,$uid,$prependTableName=0)
|
|
* 251: function getValueArray($prependTableName='')
|
|
* 279: function convertPosNeg($valueArray,$fTable,$nfTable)
|
|
* 301: function getFromDB()
|
|
* 333: function readyForInterface()
|
|
*
|
|
* TOTAL FUNCTIONS: 8
|
|
* (This index is automatically created/updated by the extension "extdeveval")
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Load database groups (relations)
|
|
* Used to process the relations created by the TCA element types "group" and "select" for database records. Manages MM-relations as well.
|
|
*
|
|
* @author Kasper Skaarhoj <kasperYYYY@typo3.com>
|
|
* @package TYPO3
|
|
* @subpackage t3lib
|
|
*/
|
|
class t3lib_loadDBGroup {
|
|
|
|
/**
|
|
* Means that only uid and the label-field is returned
|
|
*/
|
|
var $fromTC = true;
|
|
|
|
/**
|
|
* Will exclude deleted records.
|
|
* deleted-column is added to $additionalWhere...
|
|
*/
|
|
var $checkIfDeleted = true;
|
|
|
|
/**
|
|
* If set, values that are not ids in tables are normally discarded.
|
|
* By this options they will be preserved and stored in $itemArray.
|
|
*/
|
|
var $registerNonTableValues = false;
|
|
|
|
/**
|
|
* Usded to collect NON-table elements if registerNonTableValues = true
|
|
*/
|
|
var $nonTableArray = array();
|
|
|
|
|
|
|
|
/**
|
|
* Contains the table names htat are allowed for the relation as keys.
|
|
* The values are the id-values for each table. Should ONLY contain proper table names.
|
|
*/
|
|
var $tableArray = array();
|
|
|
|
/**
|
|
* Contains items in an numeric array (table/id for each). Tablenames here might be "_NO_TABLE"
|
|
*/
|
|
var $itemArray = array();
|
|
|
|
|
|
|
|
var $additionalWhere = array(); // used for additional where clause like "AND table.delete=0"
|
|
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)
|
|
|
|
|
|
|
|
// MM stuff for foreign select
|
|
|
|
/**
|
|
* field value pairs that should match while select and to be set while insert
|
|
*/
|
|
var $MMmatchFields = array();
|
|
|
|
/**
|
|
* Extra field value pairs that should be set while insert
|
|
*/
|
|
var $MMinsertFields = array();
|
|
|
|
/**
|
|
* The name of the local table. Needed for foreign select
|
|
*/
|
|
var $MMlocalTable = '';
|
|
|
|
/**
|
|
* The tablenames field should match this list
|
|
*/
|
|
var $MMmatchTablenames = '';
|
|
|
|
/**
|
|
* Extra table where clause
|
|
*/
|
|
var $MMtableWhere = '';
|
|
|
|
/**
|
|
* If true this is a foregin select and uid's needs to be swapped
|
|
*/
|
|
var $MMswapLocalForeign = false;
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Initialization of the class.
|
|
*
|
|
* Known parameter from TCA:
|
|
*
|
|
* MM_foreign_select
|
|
* MM_table_where
|
|
* MM_insert_fields
|
|
* prepend_tname
|
|
* allowed
|
|
*
|
|
* @param string Name of the local table
|
|
* @param array Configuration array coming from TCA.
|
|
* @return void
|
|
*/
|
|
function init($thisTable, $MMconf) {
|
|
|
|
// the local table name, needed for foreign select
|
|
$this->MMlocalTable = $thisTable;
|
|
|
|
// If set, uid_local and uid_foreign field names will be swapped
|
|
$this->MMswapLocalForeign = $MMconf['MM_foreign_select'];
|
|
|
|
// extra MM table where
|
|
$this->MMtableWhere = $MMconf['MM_table_where'];
|
|
|
|
// array of fields value pairs that should match while SELECT and will be written into MM table
|
|
$this->MMmatchFields = is_array($MMconf['MM_match_fields']) ? $MMconf['MM_match_fields'] : array();
|
|
|
|
// array of fields and value pairs used for insert in MM table
|
|
$this->MMinsertFields = is_array($MMconf['MM_insert_fields']) ? $MMconf['MM_insert_fields'] : $this->MMmatchFields;
|
|
|
|
// the "tablenames" field will be queried with this table name list if needed.
|
|
$this->MMmatchTablenames = '';
|
|
if ($MMconf['prepend_tname'] && $MMconf['MM_foreign_select']) {
|
|
$this->MMmatchTablenames = $this->MMlocalTable;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Start of the MM handling. Reads relations.
|
|
*
|
|
* @param string List of group/select items. Possible format: tablename_uid,tablename2_uid
|
|
* @param string Comma list of allowed tables, first table takes priority if no table is set for an entry in the item list.
|
|
* @param string Name of a MM table.
|
|
* @param integer Local UID for MM lookup
|
|
* @return void
|
|
*/
|
|
function start($itemlist, $tablelist, $MMtable='', $MMuid=0) {
|
|
|
|
// If the table list is "*" then all tables are used in the list:
|
|
if (!strcmp(trim($tablelist),'*')) {
|
|
$tablelist = implode(',',array_keys($GLOBALS['TCA']));
|
|
} else {
|
|
// add MMmatchTablenames which might be the local table for foreign access
|
|
$tablelist = $tablelist.','.$this->MMmatchTablenames;
|
|
$tablelist = implode(',', array_unique(t3lib_div::trimExplode(',',$tablelist,1)));
|
|
}
|
|
|
|
// The tables are traversed and internal arrays are initialized:
|
|
$tempTableArray = t3lib_div::trimExplode(',',$tablelist,1);
|
|
foreach($tempTableArray as $key => $val) {
|
|
$tName = trim($val);
|
|
$this->tableArray[$tName] = array();
|
|
if ($this->checkIfDeleted && $GLOBALS['TCA'][$tName]['ctrl']['delete']) {
|
|
$fieldN = $tName.'.'.$GLOBALS['TCA'][$tName]['ctrl']['delete'];
|
|
$this->additionalWhere[$tName].=' AND NOT '.$fieldN;
|
|
}
|
|
}
|
|
|
|
if (is_array($this->tableArray)) {
|
|
reset($this->tableArray);
|
|
} else {return 'No tables!';}
|
|
|
|
// Set first and second tables:
|
|
$this->firstTable = key($this->tableArray); // Is the first table
|
|
next($this->tableArray);
|
|
$this->secondTable = key($this->tableArray); // If the second table is set and the ID number is less than zero (later) then the record is regarded to come from the second table...
|
|
|
|
$this->itemArray = array();
|
|
|
|
// Now, populate the internal itemArray and tableArray arrays:
|
|
if ($MMtable) { // If MM, then call this function to do that:
|
|
|
|
// used here to get defVals when set - [tablename]_[id]
|
|
if(strpos($itemlist, '_')) {
|
|
$this->readList($itemlist);
|
|
|
|
// remap submitted defVals from form to local table if in foreign mode
|
|
if ($this->MMswapLocalForeign && $this->MMlocalTable) {
|
|
foreach ($this->itemArray as $key => $val) {
|
|
$this->itemArray[$key]['table_relation'] = $this->MMlocalTable; // is the current table
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->readMM($MMtable, $MMuid, $this->MMmatchTablenames);
|
|
|
|
} else {
|
|
// If not MM, then explode the itemlist by "," and traverse the list:
|
|
$this->readList($itemlist);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Explodes the item list and stores the parts in the internal arrays itemArray and tableArray from MM records.
|
|
*
|
|
* @param string Item list
|
|
* @return void
|
|
*/
|
|
function readList($itemlist) {
|
|
if ((string)trim($itemlist)!='') {
|
|
$tempItemArray = t3lib_div::trimExplode(',', $itemlist); // Changed to trimExplode 31/3 04; HMENU special type "list" didn't work if there were spaces in the list... I suppose this is better overall...
|
|
foreach($tempItemArray as $key => $val) {
|
|
$isSet = 0; // Will be set to "1" if the entry was a real table/id:
|
|
|
|
// Extract table name and id. This is un the formular [tablename]_[id] where table name MIGHT contain "_", hence the reversion of the string!
|
|
$val = strrev($val);
|
|
$parts = explode('_',$val,2);
|
|
$theID = strrev($parts[0]);
|
|
|
|
// Check that the id IS an integer:
|
|
if (t3lib_div::testInt($theID)) {
|
|
// Get the table name: If a part of the exploded string, use that. Otherwise if the id number is LESS than zero, use the second table, otherwise the first table
|
|
$theTable = trim($parts[1]) ? strrev(trim($parts[1])) : ($this->secondTable && $theID<0 ? $this->secondTable : $this->firstTable);
|
|
// If the ID is not blank and the table name is among the names in the inputted tableList, then proceed:
|
|
if ((string)$theID!='' && $theID && $theTable && isset($this->tableArray[$theTable])) {
|
|
// Get ID as the right value:
|
|
$theID = $this->secondTable ? abs(intval($theID)) : intval($theID);
|
|
// Register ID/table name in internal arrays:
|
|
$this->itemArray[$key]['id'] = $theID;
|
|
$this->itemArray[$key]['table'] = $theTable;
|
|
$this->tableArray[$theTable][] = $theID;
|
|
// Set update-flag:
|
|
$isSet=1;
|
|
}
|
|
}
|
|
|
|
// If it turns out that the value from the list was NOT a valid reference to a table-record, then we might still set it as a NO_TABLE value:
|
|
if (!$isSet && $this->registerNonTableValues) {
|
|
$this->itemArray[$key]['id'] = $tempItemArray[$key];
|
|
$this->itemArray[$key]['table'] = '_NO_TABLE';
|
|
$this->nonTableArray[] = $tempItemArray[$key];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads the record tablename/id into the internal arrays itemArray and tableArray from MM records.
|
|
* You can call this function after start if you supply no list to start()
|
|
*
|
|
* @param string MM Tablename
|
|
* @param integer Local UID
|
|
* @param string The "tablenames" field will be queried with this table name list
|
|
* @return void
|
|
*/
|
|
function readMM($tableName, $uid, $tableList='') {
|
|
$key=count($this->itemArray);
|
|
|
|
if ($this->MMswapLocalForeign) {
|
|
$uid_foreign = 'uid_local';
|
|
$uid_local = 'uid_foreign';
|
|
} else {
|
|
$uid_local = 'uid_local';
|
|
$uid_foreign = 'uid_foreign';
|
|
}
|
|
|
|
$where = $uid_local.'='.intval($uid);
|
|
if ($this->MMtableWhere) {
|
|
$where.= "\n".str_replace('###THIS_UID###', intval($uid), $this->MMtableWhere);
|
|
}
|
|
foreach ($this->MMmatchFields as $field => $value) {
|
|
$where.= ' AND '.$field.'='.$GLOBALS['TYPO3_DB']->fullQuoteStr($value, $tableName);
|
|
}
|
|
if ($tableList) {
|
|
$tableArr = t3lib_div::trimExplode(',', $tableList, 1);
|
|
$whereArr = array();
|
|
foreach($tableArr as $foreignTable) {
|
|
$whereArr[] = 'tablenames='.$GLOBALS['TYPO3_DB']->fullQuoteStr($foreignTable, $tableName);
|
|
}
|
|
$where.= ' AND ( '.implode(' OR ', $whereArr).' ) ';
|
|
}
|
|
|
|
// Select all MM relations:
|
|
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $tableName, $where, '', 'sorting');
|
|
while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
|
|
|
|
// in foreign_select mode firstTable is the right table - tablenames should then be the current table
|
|
$theTable = ($row['tablenames'] AND !$this->MMswapLocalForeign) ? $row['tablenames'] : $this->firstTable;
|
|
|
|
if (($row[$uid_foreign] || $theTable=='pages') && $theTable && isset($this->tableArray[$theTable])) {
|
|
$this->itemArray[$key]['id'] = $row[$uid_foreign];
|
|
$this->itemArray[$key]['table'] = $theTable;
|
|
$this->itemArray[$key]['table_relation'] = $row['tablenames'];
|
|
$this->tableArray[$theTable][]= $row[$uid_foreign];
|
|
} elseif ($this->registerNonTableValues) {
|
|
$this->itemArray[$key]['id'] = $row[$uid_foreign];
|
|
$this->itemArray[$key]['table'] = '_NO_TABLE';
|
|
$this->itemArray[$key]['table_relation'] = '_NO_TABLE';
|
|
$this->nonTableArray[] = $row[$uid_foreign];
|
|
}
|
|
$this->itemArray[$key]['foreign_select'] = $this->MMswapLocalForeign;
|
|
$key++;
|
|
}
|
|
|
|
$GLOBALS['TYPO3_DB']->sql_free_result($res);
|
|
}
|
|
|
|
/**
|
|
* Writes the internal itemArray to MM table:
|
|
*
|
|
* @param string MM table name
|
|
* @param integer Local UID
|
|
* @param boolean If set, then table names will always be written.
|
|
* @return void
|
|
*/
|
|
function writeMM($tableName, $uid, $prependTableName=0) {
|
|
|
|
if ($this->MMswapLocalForeign) {
|
|
$uid_foreign = 'uid_local';
|
|
$uid_local = 'uid_foreign';
|
|
} else {
|
|
$uid_local = 'uid_local';
|
|
$uid_foreign = 'uid_foreign';
|
|
}
|
|
|
|
// If there are tables...
|
|
$tableC = count($this->tableArray);
|
|
if ($tableC) {
|
|
$prep = ($tableC>1||$prependTableName) ? 1 : 0;
|
|
}
|
|
|
|
// delete all relations with local uid
|
|
$where = $uid_local.'='.intval($uid);
|
|
|
|
// add WHERE clause if configured
|
|
if ($this->MMtableWhere) {
|
|
$where.= "\n".str_replace('###THIS_UID###', intval($uid), $this->MMtableWhere);
|
|
}
|
|
// delete those relations that match the configured fields
|
|
foreach ($this->MMmatchFields as $field => $value) {
|
|
$where.= ' AND '.$field.'='.$GLOBALS['TYPO3_DB']->fullQuoteStr($value, $tableName);
|
|
}
|
|
|
|
// if prepend table name is configured the 'tablenames' have to match those
|
|
if ($prep) {
|
|
$whereArr = array();
|
|
foreach($this->tableArray as $matchTable => $dummy) {
|
|
$whereArr[] = 'tablenames='.$GLOBALS['TYPO3_DB']->fullQuoteStr($matchTable, $tableName);
|
|
}
|
|
$where.= ' AND ( '.implode(' OR ', $whereArr).' ) ';
|
|
}
|
|
|
|
|
|
// Delete all relations:
|
|
$GLOBALS['TYPO3_DB']->exec_DELETEquery($tableName, $where);
|
|
|
|
|
|
|
|
if ($tableC) {
|
|
// For each item, insert it:
|
|
$c=0;
|
|
foreach($this->itemArray as $val) {
|
|
$c++;
|
|
|
|
$insertFields = $this->MMinsertFields;
|
|
$insertFields[$uid_local] = $uid;
|
|
$insertFields[$uid_foreign] = $val['id'];
|
|
$insertFields['sorting'] = $c;
|
|
|
|
if ($prep || $val['table']=='_NO_TABLE') {
|
|
$insertFields['tablenames'] = $val['table_relation'] ? $val['table_relation'] : $val['table'];
|
|
}
|
|
|
|
$GLOBALS['TYPO3_DB']->exec_INSERTquery($tableName, $insertFields);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* After initialization you can extract an array of the elements from the object. Use this function for that.
|
|
*
|
|
* @param boolean If set, then table names will ALWAYS be prepended (unless its a _NO_TABLE value)
|
|
* @return array A numeric array.
|
|
*/
|
|
function getValueArray($prependTableName=false) {
|
|
// INIT:
|
|
$valueArray=array();
|
|
$tableC = count($this->tableArray);
|
|
|
|
// If there are tables in the table array:
|
|
if ($tableC) {
|
|
// If there are more than ONE table in the table array, then always prepend table names:
|
|
$prep = ($tableC>1||$prependTableName) ? 1 : 0;
|
|
|
|
// Traverse the array of items:
|
|
foreach($this->itemArray as $val) {
|
|
$valueArray[]=(($prep && $val['table']!='_NO_TABLE') ? $val['table'].'_' : '').
|
|
$val['id'];
|
|
}
|
|
}
|
|
// Return the array
|
|
return $valueArray;
|
|
}
|
|
|
|
/**
|
|
* Converts id numbers from negative to positive.
|
|
*
|
|
* @param array Array of [table]_[id] pairs.
|
|
* @param string Foreign table (the one used for positive numbers)
|
|
* @param string NEGative foreign table
|
|
* @return array The array with ID integer values, converted to positive for those where the table name was set but did NOT match the positive foreign table.
|
|
*/
|
|
function convertPosNeg($valueArray,$fTable,$nfTable) {
|
|
if (is_array($valueArray) && $fTable) {
|
|
foreach($valueArray as $key => $val) {
|
|
$val = strrev($val);
|
|
$parts = explode('_',$val,2);
|
|
$theID = strrev($parts[0]);
|
|
$theTable = strrev($parts[1]);
|
|
|
|
if ( t3lib_div::testInt($theID) && (!$theTable || !strcmp($theTable,$fTable) || !strcmp($theTable,$nfTable)) ) {
|
|
$valueArray[$key]= $theTable && strcmp($theTable,$fTable) ? $theID*-1 : $theID;
|
|
}
|
|
}
|
|
}
|
|
return $valueArray;
|
|
}
|
|
|
|
/**
|
|
* Reads all records from internal tableArray into the internal ->results array where keys are table names and for each table, records are stored with uids as their keys.
|
|
* If $this->fromTC is set you can save a little memory since only uid,pid and a few other fields are selected.
|
|
*
|
|
* @return void
|
|
*/
|
|
function getFromDB() {
|
|
// Traverses the tables listed:
|
|
foreach($this->tableArray as $table => $val) {
|
|
if (is_array($val)) {
|
|
$itemList = implode(',',$val);
|
|
if ($itemList) {
|
|
$from = '*';
|
|
if ($this->fromTC) {
|
|
$from = 'uid,pid';
|
|
if ($GLOBALS['TCA'][$table]['ctrl']['label']) {
|
|
$from.= ','.$GLOBALS['TCA'][$table]['ctrl']['label']; // Title
|
|
}
|
|
if ($GLOBALS['TCA'][$table]['ctrl']['thumbnail']) {
|
|
$from.= ','.$GLOBALS['TCA'][$table]['ctrl']['thumbnail']; // Thumbnail
|
|
}
|
|
}
|
|
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($from, $table, 'uid IN ('.$itemList.')'.$this->additionalWhere[$table]);
|
|
while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
|
|
$this->results[$table][$row['uid']]=$row;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return $this->results;
|
|
}
|
|
|
|
/**
|
|
* Prepare items from itemArray to be transferred to the TCEforms interface (as a comma list)
|
|
*
|
|
* @return string
|
|
* @see t3lib_transferdata::renderRecord()
|
|
*/
|
|
function readyForInterface() {
|
|
global $TCA;
|
|
|
|
if (!is_array($this->itemArray)) {return false;}
|
|
|
|
$output=array();
|
|
$perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1); // For use when getting the paths....
|
|
$titleLen=intval($GLOBALS['BE_USER']->uc['titleLen']);
|
|
|
|
foreach($this->itemArray as $key => $val) {
|
|
$theRow = $this->results[$val['table']][$val['id']];
|
|
if ($theRow && is_array($TCA[$val['table']])) {
|
|
$label = t3lib_div::fixed_lgd_cs(strip_tags($theRow[$TCA[$val['table']]['ctrl']['label']]),$titleLen);
|
|
$label = ($label)?$label:'[...]';
|
|
$output[]=str_replace(',','',$val['table'].'_'.$val['id'].'|'.rawurlencode($label));
|
|
}
|
|
}
|
|
return implode(',',$output);
|
|
}
|
|
}
|
|
|
|
|
|
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_loaddbgroup.php']) {
|
|
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_loaddbgroup.php']);
|
|
}
|
|
?>
|