2 /***************************************************************
5 * (c) 1999-2006 Kasper Skaarhoj (kasperYYYY@typo3.com)
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
28 * Contains class for loading database groups
31 * Revised for TYPO3 3.6 September/2003 by Kasper Skaarhoj
33 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
36 * [CLASS/FUNCTION INDEX of SCRIPT]
40 * 72: class t3lib_loadDBGroup
41 * 99: function start($itemlist,$tablelist, $MMtable='',$MMuid=0)
42 * 140: function readList($itemlist)
43 * 186: function readMM($tableName,$uid)
44 * 215: function writeMM($tableName,$uid,$prependTableName=0)
45 * 251: function getValueArray($prependTableName='')
46 * 279: function convertPosNeg($valueArray,$fTable,$nfTable)
47 * 301: function getFromDB()
48 * 333: function readyForInterface()
51 * (This index is automatically created/updated by the extension "extdeveval")
65 * Load database groups (relations)
66 * Used to process the relations created by the TCA element types "group" and "select" for database records. Manages MM-relations as well.
68 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
72 class t3lib_loadDBGroup
{
74 var $fromTC = 1; // Means that only uid and the label-field is returned
75 var $registerNonTableValues=0; // If set, values that are not ids in tables are normally discarded. By this options they will be preserved.
78 var $tableArray=Array(); // Contains the table names as keys. The values are the id-values for each table. Should ONLY contain proper table names.
79 var $itemArray=Array(); // Contains items in an numeric array (table/id for each). Tablenames here might be "_NO_TABLE"
80 var $nonTableArray=array(); // Array for NON-table elements
81 var $additionalWhere=array();
82 var $checkIfDeleted = 1; // deleted-column is added to additionalWhere... if this is set...
84 var $firstTable = ''; // Will contain the first table name in the $tablelist (for positive ids)
85 var $secondTable = ''; // Will contain the second table name in the $tablelist (for negative ids)
91 * Initialization of the class.
93 * @param string List of group/select items
94 * @param string Comma list of tables, first table takes priority if no table is set for an entry in the list.
95 * @param string Name of a MM table.
96 * @param integer Local UID for MM lookup
99 function start($itemlist,$tablelist, $MMtable='',$MMuid=0) {
100 // If the table list is "*" then all tables are used in the list:
101 if (!strcmp(trim($tablelist),'*')) {
102 $tablelist = implode(',',array_keys($GLOBALS['TCA']));
105 // The tables are traversed and internal arrays are initialized:
106 $tempTableArray = t3lib_div
::trimExplode(',',$tablelist,1);
107 foreach($tempTableArray as $key => $val) {
109 $this->tableArray
[$tName] = Array();
110 if ($this->checkIfDeleted
&& $GLOBALS['TCA'][$tName]['ctrl']['delete']) {
111 $fieldN = $tName.'.'.$GLOBALS['TCA'][$tName]['ctrl']['delete'];
112 $this->additionalWhere
[$tName].=' AND '.$fieldN.'=0';
116 if (is_array($this->tableArray
)) {
117 reset($this->tableArray
);
118 } else {return 'No tables!';}
120 // Set first and second tables:
121 $this->firstTable
= key($this->tableArray
); // Is the first table
122 next($this->tableArray
);
123 $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...
125 // Now, populate the internal itemArray and tableArray arrays:
126 if ($MMtable) { // If MM, then call this function to do that:
127 $this->readMM($MMtable,$MMuid);
129 // If not MM, then explode the itemlist by "," and traverse the list:
130 $this->readList($itemlist);
135 * Explodes the item list and stores the parts in the internal arrays itemArray and tableArray from MM records.
137 * @param string Item list
140 function readList($itemlist) {
141 if ((string)trim($itemlist)!='') {
142 $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...
143 foreach($tempItemArray as $key => $val) {
144 $isSet = 0; // Will be set to "1" if the entry was a real table/id:
146 // Extract table name and id. This is un the formular [tablename]_[id] where table name MIGHT contain "_", hence the reversion of the string!
148 $parts = explode('_',$val,2);
149 $theID = strrev($parts[0]);
151 // Check that the id IS an integer:
152 if (t3lib_div
::testInt($theID)) {
153 // 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
154 $theTable = trim($parts[1]) ?
strrev(trim($parts[1])) : ($this->secondTable
&& $theID<0 ?
$this->secondTable
: $this->firstTable
);
155 // If the ID is not blank and the table name is among the names in the inputted tableList, then proceed:
156 if ((string)$theID!='' && $theID && $theTable && isset($this->tableArray
[$theTable])) {
157 // Get ID as the right value:
158 $theID = $this->secondTable ?
abs(intval($theID)) : intval($theID);
159 // Register ID/table name in internal arrays:
160 $this->itemArray
[$key]['id'] = $theID;
161 $this->itemArray
[$key]['table'] = $theTable;
162 $this->tableArray
[$theTable][] = $theID;
168 // 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:
169 if (!$isSet && $this->registerNonTableValues
) {
170 $this->itemArray
[$key]['id'] = $tempItemArray[$key];
171 $this->itemArray
[$key]['table'] = '_NO_TABLE';
172 $this->nonTableArray
[] = $tempItemArray[$key];
179 * Reads the record tablename/id into the internal arrays itemArray and tableArray from MM records.
180 * You can call this function after start if you supply no list to start()
182 * @param string MM Tablename
183 * @param integer Local UID
186 function readMM($tableName,$uid) {
189 // Select all MM relations:
190 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $tableName, 'uid_local='.intval($uid), '', 'sorting');
191 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
192 $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...
193 if (($row['uid_foreign'] ||
$theTable=='pages') && $theTable && isset($this->tableArray
[$theTable])) {
194 $this->itemArray
[$key]['id'] = $row['uid_foreign'];
195 $this->itemArray
[$key]['table'] = $theTable;
196 $this->tableArray
[$theTable][]= $row['uid_foreign'];
197 } elseif ($this->registerNonTableValues
) {
198 $this->itemArray
[$key]['id'] = $row['uid_foreign'];
199 $this->itemArray
[$key]['table'] = '_NO_TABLE';
200 $this->nonTableArray
[] = $row['uid_foreign'];
204 $GLOBALS['TYPO3_DB']->sql_free_result($res);
208 * Writes the internal itemArray to MM table:
210 * @param string MM table name
211 * @param integer Local UID
212 * @param boolean If set, then table names will always be written.
215 function writeMM($tableName,$uid,$prependTableName=0) {
217 // Delete all relations:
218 $GLOBALS['TYPO3_DB']->exec_DELETEquery($tableName, 'uid_local='.intval($uid));
220 // If there are tables...
221 $tableC = count($this->tableArray
);
223 $prep = ($tableC>1||
$prependTableName) ?
1 : 0;
227 // For each item, insert it:
228 foreach($this->itemArray
as $val) {
231 $insertFields = array(
233 'uid_foreign' => $val['id'],
236 if ($prep ||
$val['table']=='_NO_TABLE') {
237 $insertFields['tablenames'] = $val['table'];
240 $GLOBALS['TYPO3_DB']->exec_INSERTquery($tableName, $insertFields);
246 * After initialization you can extract an array of the elements from the object. Use this function for that.
248 * @param boolean If set, then table names will ALWAYS be prepended (unless its a _NO_TABLE value)
249 * @return array A numeric array.
251 function getValueArray($prependTableName='') {
254 $tableC = count($this->tableArray
);
256 // If there are tables in the table array:
258 // If there are more than ONE table in the table array, then always prepend table names:
259 $prep = ($tableC>1||
$prependTableName) ?
1 : 0;
261 // Traverse the array of items:
262 foreach($this->itemArray
as $val) {
263 $valueArray[]=(($prep && $val['table']!='_NO_TABLE') ?
$val['table'].'_' : '').
272 * Converts id numbers from negative to positive.
274 * @param array Array of [table]_[id] pairs.
275 * @param string Foreign table (the one used for positive numbers)
276 * @param string NEGative foreign table
277 * @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.
279 function convertPosNeg($valueArray,$fTable,$nfTable) {
280 if (is_array($valueArray) && $fTable) {
281 foreach($valueArray as $key => $val) {
283 $parts = explode('_',$val,2);
284 $theID = strrev($parts[0]);
285 $theTable = strrev($parts[1]);
287 if ( t3lib_div
::testInt($theID) && (!$theTable ||
!strcmp($theTable,$fTable) ||
!strcmp($theTable,$nfTable)) ) {
288 $valueArray[$key]= $theTable && strcmp($theTable,$fTable) ?
$theID*-1 : $theID;
296 * 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.
297 * If $this->fromTC is set you can save a little memory since only uid,pid and a few other fields are selected.
301 function getFromDB() {
302 // Traverses the tables listed:
303 foreach($this->tableArray
as $key => $val) {
304 if (is_array($val)) {
305 $itemList = implode(',',$val);
310 if ($GLOBALS['TCA'][$key]['ctrl']['label']) {
311 $from.= ','.$GLOBALS['TCA'][$key]['ctrl']['label']; // Titel
313 if ($GLOBALS['TCA'][$key]['ctrl']['label_alt']) {
314 $from.= ','.$GLOBALS['TCA'][$key]['ctrl']['label_alt']; // Alternative Title-Fields
316 if ($GLOBALS['TCA'][$key]['ctrl']['thumbnail']) {
317 $from.= ','.$GLOBALS['TCA'][$key]['ctrl']['thumbnail']; // Thumbnail
320 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($from, $key, 'uid IN ('.$itemList.')'.$this->additionalWhere
[$key]);
321 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
322 $this->results
[$key][$row['uid']]=$row;
327 return $this->results
;
331 * Prepare items from itemArray to be transferred to the TCEforms interface (as a comma list)
334 * @see t3lib_transferdata::renderRecord()
336 function readyForInterface() {
339 if (!is_array($this->itemArray
)) {return false;}
342 $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1); // For use when getting the paths....
343 $titleLen=intval($GLOBALS['BE_USER']->uc
['titleLen']);
345 foreach($this->itemArray
as $key => $val) {
346 $theRow = $this->results
[$val['table']][$val['id']];
347 if ($theRow && is_array($TCA[$val['table']])) {
348 $label = t3lib_div
::fixed_lgd_cs(strip_tags(t3lib_BEfunc
::getRecordTitle($val['table'], $theRow)),$titleLen);
349 $label = ($label)?
$label:'[...]';
350 $output[]=str_replace(',','',$val['table'].'_'.$val['id'].'|'.rawurlencode($label));
353 return implode(',',$output);
358 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE
]['XCLASS']['t3lib/class.t3lib_loaddbgroup.php']) {
359 include_once($TYPO3_CONF_VARS[TYPO3_MODE
]['XCLASS']['t3lib/class.t3lib_loaddbgroup.php']);