Initial revision
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_loaddbgroup.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2003 Kasper Skårhøj (kasper@typo3.com)
6 * All rights reserved
7 *
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.
13 *
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.
18 *
19 *
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.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Contains class for loading database groups
29 *
30 * Revised for TYPO3 3.6 September/2003 by Kasper Skårhøj
31 */
32 /**
33 * [CLASS/FUNCTION INDEX of SCRIPT]
34 *
35 *
36 *
37 * 69: class t3lib_loadDBGroup
38 * 96: function start ($itemlist,$tablelist, $MMtable='',$MMuid=0)
39 * 137: function readList($itemlist)
40 * 183: function readMM($tableName,$uid)
41 * 213: function writeMM($tableName,$uid,$prependTableName=0)
42 * 242: function getValueArray($prependTableName='')
43 * 270: function convertPosNeg($valueArray,$fTable,$nfTable)
44 * 292: function getFromDB()
45 * 325: function readyForInterface()
46 *
47 * TOTAL FUNCTIONS: 8
48 * (This index is automatically created/updated by the extension "extdeveval")
49 *
50 */
51
52
53
54
55
56
57
58
59
60
61 /**
62 * Load database groups (relations)
63 * Used to process the relations created by the TCA element types "group" and "select" for database records. Manages MM-relations as well.
64 *
65 * @author Kasper Skårhøj <kasper@typo3.com>
66 * @package TYPO3
67 * @subpackage t3lib
68 */
69 class t3lib_loadDBGroup {
70 // External, static:
71 var $fromTC = 1; // Means that only uid and the label-field is returned
72 var $registerNonTableValues=0; // If set, values that are not ids in tables are normally discarded. By this options they will be preserved.
73
74 // Internal, dynamic:
75 var $tableArray=Array(); // Contains the table names as keys. The values are the id-values for each table. Should ONLY contain proper table names.
76 var $itemArray=Array(); // Contains items in an numeric array (table/id for each). Tablenames here might be "_NO_TABLE"
77 var $nonTableArray=array(); // Array for NON-table elements
78 var $additionalWhere=array();
79 var $checkIfDeleted = 1; // deleted-column is added to additionalWhere... if this is set...
80 var $dbPaths=Array();
81 var $firstTable = ''; // Will contain the first table name in the $tablelist (for positive ids)
82 var $secondTable = ''; // Will contain the second table name in the $tablelist (for negative ids)
83
84
85
86
87 /**
88 * Initialization of the class.
89 *
90 * @param string List of group/select items
91 * @param string Comma list of tables, first table takes priority if no table is set for an entry in the list.
92 * @param string Name of a MM table.
93 * @param integer Local UID for MM lookup
94 * @return void
95 */
96 function start ($itemlist,$tablelist, $MMtable='',$MMuid=0) {
97 // If the table list is "*" then all tables are used in the list:
98 if (!strcmp(trim($tablelist),'*')) {
99 $tablelist = implode(',',array_keys($GLOBALS['TCA']));
100 }
101
102 // The tables are traversed and internal arrays are initialized:
103 $tempTableArray = t3lib_div::trimExplode(',',$tablelist,1);
104 foreach($tempTableArray as $key => $val) {
105 $tName = trim($val);
106 $this->tableArray[$tName] = Array();
107 if ($this->checkIfDeleted && $GLOBALS['TCA'][$tName]['ctrl']['delete']) {
108 $fieldN = $tName.'.'.$GLOBALS['TCA'][$tName]['ctrl']['delete'];
109 $this->additionalWhere[$tName].=' AND NOT '.$fieldN;
110 }
111 }
112
113 if (is_array($this->tableArray)) {
114 reset($this->tableArray);
115 } else {return 'No tables!';}
116
117 // Set first and second tables:
118 $this->firstTable = key($this->tableArray); // Is the first table
119 next($this->tableArray);
120 $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...
121
122 // Now, populate the internal itemArray and tableArray arrays:
123 if ($MMtable) { // If MM, then call this function to do that:
124 $this->readMM($MMtable,$MMuid);
125 } else {
126 // If not MM, then explode the itemlist by "," and traverse the list:
127 $this->readList($itemlist);
128 }
129 }
130
131 /**
132 * Explodes the item list and stores the parts in the internal arrays itemArray and tableArray from MM records.
133 *
134 * @param string Item list
135 * @return void
136 */
137 function readList($itemlist) {
138 if ((string)trim($itemlist)!='') {
139 $tempItemArray = explode(',',$itemlist);
140 while(list($key,$val)=each($tempItemArray)) {
141 $isSet = 0; // Will be set to "1" if the entry was a real table/id:
142
143 // Extract table name and id. This is un the formular [tablename]_[id] where table name MIGHT contain "_", hence the reversion of the string!
144 $val = strrev($val);
145 $parts = explode('_',$val,2);
146 $theID = strrev($parts[0]);
147
148 // Check that the id IS an integer:
149 if (t3lib_div::testInt($theID)) {
150 // 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
151 $theTable = trim($parts[1]) ? strrev(trim($parts[1])) : ($this->secondTable && $theID<0 ? $this->secondTable : $this->firstTable);
152 // If the ID is not blank and the table name is among the names in the inputted tableList, then proceed:
153 if ((string)$theID!='' && $theID && $theTable && isset($this->tableArray[$theTable])) {
154 // Get ID as the right value:
155 $theID = $this->secondTable ? abs(intval($theID)) : intval($theID);
156 // Register ID/table name in internal arrays:
157 $this->itemArray[$key]['id'] = $theID;
158 $this->itemArray[$key]['table'] = $theTable;
159 $this->tableArray[$theTable][]=$theID;
160 // Set update-flag:
161 $isSet=1;
162 }
163 }
164
165 // 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:
166 if (!$isSet && $this->registerNonTableValues) {
167 $this->itemArray[$key]['id'] = $tempItemArray[$key];
168 $this->itemArray[$key]['table'] = '_NO_TABLE';
169 $this->nonTableArray[] = $tempItemArray[$key];
170 }
171 }
172 }
173 }
174
175 /**
176 * Reads the record tablename/id into the internal arrays itemArray and tableArray from MM records.
177 * You can call this function after start if you supply no list to start()
178 *
179 * @param string MM Tablename
180 * @param integer Local UID
181 * @return void
182 */
183 function readMM($tableName,$uid) {
184 // Select all MM relations:
185 $query='SELECT * FROM '.$tableName.' WHERE uid_local='.intval($uid).' ORDER BY sorting';
186 $res=mysql(TYPO3_db,$query);
187 echo mysql_error();
188
189 $key=0;
190 while($row=mysql_fetch_assoc($res)) {
191 $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 the firstTable...
192 if (($row['uid_foreign'] || $theTable=='pages') && $theTable && isset($this->tableArray[$theTable])) {
193 $this->itemArray[$key]['id'] = $row['uid_foreign'];
194 $this->itemArray[$key]['table'] = $theTable;
195 $this->tableArray[$theTable][]= $row['uid_foreign'];
196 } elseif ($this->registerNonTableValues) {
197 $this->itemArray[$key]['id'] = $row['uid_foreign'];
198 $this->itemArray[$key]['table'] = '_NO_TABLE';
199 $this->nonTableArray[] = $row['uid_foreign'];
200 }
201 $key++;
202 }
203 }
204
205 /**
206 * Writes the internal itemArray to MM table:
207 *
208 * @param string MM table name
209 * @param integer Local UID
210 * @param boolean If set, then table names will always be written.
211 * @return void
212 */
213 function writeMM($tableName,$uid,$prependTableName=0) {
214 // Delete all relations:
215 $query='DELETE FROM '.$tableName.' WHERE uid_local='.intval($uid);
216 $res=mysql(TYPO3_db,$query);
217
218 // If there are tables...
219 $tableC = count($this->tableArray);
220 if ($tableC) {
221 $prep = ($tableC>1||$prependTableName) ? 1 : 0;
222 $c=0;
223 $tName=array();
224 // For each item, insert it:
225 foreach($this->itemArray as $val) {
226 $c++;
227 if ($prep || $val['table']=='_NO_TABLE') {
228 $tName=array(',tablenames', ',"'.addslashes($val['table']).'"');
229 }
230 $query='INSERT INTO '.$tableName.' (uid_local,uid_foreign,sorting'.$tName[0].') VALUES ("'.$uid.'","'.addslashes($val['id']).'",'.$c.$tName[1].')';
231 $res=mysql(TYPO3_db,$query);
232 }
233 }
234 }
235
236 /**
237 * After initialization you can extract an array of the elements from the object. Use this function for that.
238 *
239 * @param boolean If set, then table names will ALWAYS be prepended (unless its a _NO_TABLE value)
240 * @return array A numeric array.
241 */
242 function getValueArray($prependTableName='') {
243 // INIT:
244 $valueArray=Array();
245 $tableC = count($this->tableArray);
246
247 // If there are tables in the table array:
248 if ($tableC) {
249 // If there are more than ONE table in the table array, then always prepend table names:
250 $prep = ($tableC>1||$prependTableName) ? 1 : 0;
251
252 // Traverse the array of items:
253 foreach($this->itemArray as $val) {
254 $valueArray[]=(($prep && $val['table']!='_NO_TABLE') ? $val['table'].'_' : '').
255 $val['id'];
256 }
257 }
258 // Return the array
259 return $valueArray;
260 }
261
262 /**
263 * Converts id numbers from negative to positive.
264 *
265 * @param array Array of [table]_[id] pairs.
266 * @param string Foreign table (the one used for positive numbers)
267 * @param string NEGative foreign table
268 * @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.
269 */
270 function convertPosNeg($valueArray,$fTable,$nfTable) {
271 if (is_array($valueArray) && $fTable) {
272 foreach($valueArray as $key => $val) {
273 $val = strrev($val);
274 $parts = explode('_',$val,2);
275 $theID = strrev($parts[0]);
276 $theTable = strrev($parts[1]);
277
278 if ( t3lib_div::testInt($theID) && (!$theTable || !strcmp($theTable,$fTable) || !strcmp($theTable,$nfTable)) ) {
279 $valueArray[$key]= $theTable && strcmp($theTable,$fTable) ? $theID*-1 : $theID;
280 }
281 }
282 }
283 return $valueArray;
284 }
285
286 /**
287 * 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.
288 * If $this->fromTC is set you can save a little memory since only uid,pid and a few other fields are selected.
289 *
290 * @return void
291 */
292 function getFromDB() {
293 // Traverses the tables listed:
294 foreach($this->tableArray as $key => $val) {
295 if (is_array($val)) {
296 $itemList = implode($val,',');
297 if ($itemList) {
298 $from = '*';
299 if ($this->fromTC) {
300 $from = 'uid,pid';
301 if ($GLOBALS['TCA'][$key]['ctrl']['label']) {
302 $from.= ','.$GLOBALS['TCA'][$key]['ctrl']['label']; // Titel
303 }
304 if ($GLOBALS['TCA'][$key]['ctrl']['thumbnail']) {
305 $from.= ','.$GLOBALS['TCA'][$key]['ctrl']['thumbnail']; // Thumbnail
306 }
307 }
308 $query='SELECT '.$from.' FROM '.$key.' WHERE uid IN ('.$itemList.')'.$this->additionalWhere[$key];
309 $res=mysql(TYPO3_db,$query);
310 while($row = mysql_fetch_assoc($res)) {
311 $this->results[$key][$row['uid']]=$row;
312 }
313 }
314 }
315 }
316 return $this->results;
317 }
318
319 /**
320 * Prepare items from itemArray to be transferred to the TCEforms interface (as a comma list)
321 *
322 * @return string
323 * @see t3lib_transferdata::renderRecord()
324 */
325 function readyForInterface() {
326 global $TCA;
327
328 if (!is_array($this->itemArray)) {return false;}
329
330 $output=array();
331 $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1); // For use when getting the paths....
332 $titleLen=intval($GLOBALS['BE_USER']->uc['titleLen']);
333
334 foreach($this->itemArray as $key => $val) {
335 $theRow = $this->results[$val['table']][$val['id']];
336 if ($theRow && is_array($TCA[$val['table']])) {
337 $label = t3lib_div::fixed_lgd(strip_tags($theRow[$TCA[$val['table']]['ctrl']['label']]),$titleLen);
338 $label = ($label)?$label:'[...]';
339 $output[]=str_replace(',','',$val['table'].'_'.$val['id'].'|'.rawurlencode($label));
340 }
341 }
342 return implode(',',$output);
343 }
344 }
345
346
347 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_loaddbgroup.php']) {
348 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_loaddbgroup.php']);
349 }
350 ?>