Fixed bug #17133: Pagetree - qtip can be used to execute custom javascript (XSS)...
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_transferdata.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@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 getting and transforming data for display in backend forms (TCEforms)
29 *
30 * $Id$
31 * Revised for TYPO3 3.6 September/2003 by Kasper Skårhøj
32 *
33 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
34 */
35 /**
36 * [CLASS/FUNCTION INDEX of SCRIPT]
37 *
38 *
39 *
40 * 99: class t3lib_transferData
41 *
42 * SECTION: Getting record content, ready for display in TCEforms
43 * 138: function fetchRecord($table,$idList,$operation)
44 * 225: function renderRecord($table, $id, $pid, $row)
45 * 269: function renderRecordRaw($table, $id, $pid, $row, $TSconfig='', $tscPID=0)
46 * 327: function renderRecord_SW($data,$fieldConfig,$TSconfig,$table,$row,$field)
47 * 359: function renderRecord_groupProc($data,$fieldConfig,$TSconfig,$table,$row,$field)
48 * 410: function renderRecord_selectProc($data,$fieldConfig,$TSconfig,$table,$row,$field)
49 * 473: function renderRecord_flexProc($data,$fieldConfig,$TSconfig,$table,$row,$field)
50 * 504: function renderRecord_typesProc($totalRecordContent,$types_fieldConfig,$tscPID,$table,$pid)
51 * 545: function renderRecord_inlineProc($data,$fieldConfig,$TSconfig,$table,$row,$field)
52 *
53 * SECTION: FlexForm processing functions
54 * 632: function renderRecord_flexProc_procInData($dataPart,$dataStructArray,$pParams)
55 * 661: function renderRecord_flexProc_procInData_travDS(&$dataValues,$DSelements,$pParams)
56 *
57 * SECTION: Selector box processing functions
58 * 738: function selectAddSpecial($dataAcc, $elements, $specialKey)
59 * 863: function selectAddForeign($dataAcc, $elements, $fieldConfig, $field, $TSconfig, $row, $table)
60 * 917: function getDataIdList($elements, $fieldConfig, $row, $table)
61 * 946: function procesItemArray($selItems,$config,$fieldTSConfig,$table,$row,$field)
62 * 961: function addItems($items,$iArray)
63 * 983: function procItems($items,$itemsProcFuncTSconfig,$config,$table,$row,$field)
64 *
65 * SECTION: Helper functions
66 * 1018: function lockRecord($table, $id, $pid=0)
67 * 1035: function regItem($table, $id, $field, $content)
68 * 1045: function sL($in)
69 *
70 * TOTAL FUNCTIONS: 20
71 * (This index is automatically created/updated by the extension "extdeveval")
72 *
73 */
74
75
76 /**
77 * Class for getting and transforming data for display in backend forms (TCEforms)
78 *
79 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
80 * @package TYPO3
81 * @subpackage t3lib
82 */
83 class t3lib_transferData {
84 // External, static:
85 var $lockRecords = 0; // If set, the records requested are locked.
86 var $disableRTE = 0; // Is set externally if RTE is disabled.
87 var $prevPageID = ''; // If the pid in the command is 'prev' then $prevPageID is used as pid for the record. This is used to attach new records to other previous records eg. new pages.
88 var $defVals = array(); // Can be set with an array of default values for tables. First key is table name, second level keys are field names. Originally this was a GLOBAL array used internally.
89 var $addRawData = FALSE; // If set, the processed data is overlaid the raw record.
90
91 // Internal, dynamic
92 var $regTableItems = array(); // Used to register, which items are already loaded!!
93 var $regTableItems_data = array(); // This stores the record data of the loaded records
94 var $loadModules = ''; // Contains loadModules object, if used. (for reuse internally)
95
96
97 /***********************************************
98 *
99 * Getting record content, ready for display in TCEforms
100 *
101 ***********************************************/
102
103 /**
104 * A function which can be used for load a batch of records from $table into internal memory of this object.
105 * The function is also used to produce proper default data for new records
106 * Ultimately the function will call renderRecord()
107 *
108 * @param string Table name, must be found in $TCA
109 * @param string Comma list of id values. If $idList is "prev" then the value from $this->prevPageID is used. NOTICE: If $operation is "new", then negative ids are meant to point to a "previous" record and positive ids are PID values for new records. Otherwise (for existing records that is) it is straight forward table/id pairs.
110 * @param string If "new", then a record with default data is returned. Further, the $id values are meant to be PID values (or if negative, pointing to a previous record). If NOT new, then the table/ids are just pointing to an existing record!
111 * @return void
112 * @see renderRecord()
113 */
114 function fetchRecord($table, $idList, $operation) {
115 global $TCA;
116
117 if ((string) $idList == 'prev') {
118 $idList = $this->prevPageID;
119 }
120
121 if ($TCA[$table]) {
122 t3lib_div::loadTCA($table);
123
124 // For each ID value (integer) we
125 $ids = t3lib_div::trimExplode(',', $idList, 1);
126 foreach ($ids as $id) {
127 if (strcmp($id, '')) { // If ID is not blank:
128
129 // For new records to be created, find default values:
130 if ($operation == 'new') {
131
132 // Default values:
133 $newRow = array(); // Used to store default values as found here:
134
135 // Default values as set in userTS:
136 $TCAdefaultOverride = $GLOBALS['BE_USER']->getTSConfigProp('TCAdefaults');
137 if (is_array($TCAdefaultOverride[$table . '.'])) {
138 foreach ($TCAdefaultOverride[$table . '.'] as $theF => $theV) {
139 if (isset($TCA[$table]['columns'][$theF])) {
140 $newRow[$theF] = $theV;
141 }
142 }
143 }
144
145 if ($id < 0) {
146 $record = t3lib_beFunc::getRecord($table, abs($id), 'pid');
147 $pid = $record['pid'];
148 unset($record);
149 } else {
150 $pid = intval($id);
151 }
152
153 $pageTS = t3lib_beFunc::getPagesTSconfig($pid);
154
155 if (isset($pageTS['TCAdefaults.'])) {
156 $TCAPageTSOverride = $pageTS['TCAdefaults.'];
157 if (is_array($TCAPageTSOverride[$table . '.'])) {
158 foreach ($TCAPageTSOverride[$table . '.'] as $theF => $theV) {
159 if (isset($TCA[$table]['columns'][$theF])) {
160 $newRow[$theF] = $theV;
161 }
162 }
163 }
164 }
165
166 // Default values as submitted:
167 if (is_array($this->defVals[$table])) {
168 foreach ($this->defVals[$table] as $theF => $theV) {
169 if (isset($TCA[$table]['columns'][$theF])) {
170 $newRow[$theF] = $theV;
171 }
172 }
173 }
174
175 // Fetch default values if a previous record exists
176 if ($id < 0 && $TCA[$table]['ctrl']['useColumnsForDefaultValues']) {
177 // Fetches the previous record:
178 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, 'uid=' . abs($id) . t3lib_BEfunc::deleteClause($table));
179 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
180 // Gets the list of fields to copy from the previous record.
181 $fArr = t3lib_div::trimExplode(',', $TCA[$table]['ctrl']['useColumnsForDefaultValues'], 1);
182 foreach ($fArr as $theF) {
183 if (isset($TCA[$table]['columns'][$theF])) {
184 $newRow[$theF] = $row[$theF];
185 }
186 }
187 }
188 $GLOBALS['TYPO3_DB']->sql_free_result($res);
189 }
190
191 // Finally, call renderRecord:
192 $this->renderRecord($table, uniqid('NEW'), $id, $newRow);
193 } else {
194 $id = intval($id);
195
196 // Fetch database values
197 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, 'uid=' . intval($id) . t3lib_BEfunc::deleteClause($table));
198 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
199 t3lib_BEfunc::fixVersioningPid($table, $row);
200 $this->renderRecord($table, $id, $row['pid'], $row);
201 $contentTable = $GLOBALS['TYPO3_CONF_VARS']['SYS']['contentTable'];
202 $this->lockRecord($table, $id, $contentTable == $table ? $row['pid'] : 0); // Locking the pid if the table edited is the content table.
203 }
204 $GLOBALS['TYPO3_DB']->sql_free_result($res);
205 }
206 }
207 }
208 }
209 }
210
211 /**
212 * This function performs processing on the input $row array and stores internally a corresponding array which contains processed values, ready to pass on to the TCEforms rendering in the frontend!
213 * The objective with this function is to prepare the content for handling in TCEforms.
214 * Default values from outside/TSconfig is added by fetchRecord(). In this function default values from TCA is used if a field is NOT defined in $row.
215 * The resulting, processed row is stored in $this->regTableItems_data[$uniqueItemRef], where $uniqueItemRef is "[tablename]_[id-value]"
216 *
217 * @param string The table name
218 * @param string The uid value of the record (integer). Can also be a string (NEW-something) if the record is a NEW record.
219 * @param integer The pid integer. For existing records this is of course the row's "pid" field. For new records it can be either a page id (positive) or a pointer to another record from the SAME table (negative) after which the record should be inserted (or on same page)
220 * @param array The row of the current record. If NEW record, then it may be loaded with default values (by eg. fetchRecord()).
221 * @return void
222 * @see fetchRecord()
223 */
224 function renderRecord($table, $id, $pid, $row) {
225 global $TCA;
226
227 // Init:
228 $uniqueItemRef = $table . '_' . $id;
229 t3lib_div::loadTCA($table);
230
231 // Fetches the true PAGE TSconfig pid to use later, if needed. (Until now, only for the RTE, but later..., who knows?)
232 list($tscPID) = t3lib_BEfunc::getTSCpid($table, $id, $pid);
233 $TSconfig = t3lib_BEfunc::getTCEFORM_TSconfig($table, array_merge($row, array('uid' => $id, 'pid' => $pid)));
234
235 // If the record has not already been loaded (in which case we DON'T do it again)...
236 if (!$this->regTableItems[$uniqueItemRef]) {
237 $this->regTableItems[$uniqueItemRef] = 1; // set "loaded" flag.
238
239 // If the table is pages, set the previous page id internally.
240 if ($table == 'pages') {
241 $this->prevPageID = $id;
242 }
243
244 $this->regTableItems_data[$uniqueItemRef] = $this->renderRecordRaw($table, $id, $pid, $row, $TSconfig, $tscPID);
245
246 // Merges the processed array on-top of the raw one - this is done because some things in TCEforms may need access to other fields than those in the columns configuration!
247 if ($this->addRawData && is_array($row) && is_array($this->regTableItems_data[$uniqueItemRef])) {
248 $this->regTableItems_data[$uniqueItemRef] = array_merge($row, $this->regTableItems_data[$uniqueItemRef]);
249 }
250 }
251 }
252
253
254 /**
255 * This function performs processing on the input $row array and stores internally a corresponding array which contains processed values, ready to pass on to the TCEforms rendering in the frontend!
256 * The objective with this function is to prepare the content for handling in TCEforms.
257 * In opposite to renderRecord() this function do not prepare things like fetching TSconfig and others.
258 * The resulting, processed row will be returned.
259 *
260 * @param string The table name
261 * @param string The uid value of the record (integer). Can also be a string (NEW-something) if the record is a NEW record.
262 * @param integer The pid integer. For existing records this is of course the row's "pid" field. For new records it can be either a page id (positive) or a pointer to another record from the SAME table (negative) after which the record should be inserted (or on same page)
263 * @param array The row of the current record. If NEW record, then it may be loaded with default values (by eg. fetchRecord()).
264 * @param array Tsconfig array
265 * @param integer PAGE TSconfig pid
266 * @return array Processed record data
267 * @see renderRecord()
268 */
269 function renderRecordRaw($table, $id, $pid, $row, $TSconfig = '', $tscPID = 0) {
270 global $TCA;
271
272 if (!is_array($TSconfig)) {
273 $TSconfig = array();
274 }
275
276 // Create blank accumulation array:
277 $totalRecordContent = array();
278
279 // Traverse the configured columns for the table (TCA):
280 // For each column configured, we will perform processing if needed based on the type (eg. for "group" and "select" types this is needed)
281 t3lib_div::loadTCA($table);
282 $copyOfColumns = $TCA[$table]['columns'];
283 foreach ($copyOfColumns as $field => $fieldConfig) {
284 // Set $data variable for the field, either inputted value from $row - or if not found, the default value as defined in the "config" array
285 if (isset($row[$field])) {
286 $data = $row[$field];
287 } else {
288 $data = $fieldConfig['config']['default'];
289 }
290
291 $data = $this->renderRecord_SW($data, $fieldConfig, $TSconfig, $table, $row, $field);
292
293 // Set the field in the accumulation array IF the $data variabel is set:
294 $totalRecordContent[$field] = isset($data) ? $data : '';
295 }
296
297 // Further processing may apply for each field in the record depending on the settings in the "types" configuration (the list of fields to currently display for a record in TCEforms).
298 // For instance this could be processing instructions for the Rich Text Editor.
299 $types_fieldConfig = t3lib_BEfunc::getTCAtypes($table, $totalRecordContent);
300 if (is_array($types_fieldConfig)) {
301 $totalRecordContent = $this->renderRecord_typesProc($totalRecordContent, $types_fieldConfig, $tscPID, $table, $pid);
302 }
303
304 // Register items, mostly for external use (overriding the regItem() function)
305 foreach ($totalRecordContent as $field => $data) {
306 $this->regItem($table, $id, $field, $data);
307 }
308
309 // Finally, store the result:
310 reset($totalRecordContent);
311
312 return $totalRecordContent;
313
314 }
315
316 /**
317 * Function with the switch() construct which triggers functions for processing of the data value depending on the TCA-config field type.
318 *
319 * @param string Value to process
320 * @param array TCA/columns array for field (independant of TCA for flexforms - coming from XML then)
321 * @param array TSconfig (blank for flexforms for now)
322 * @param string Table name
323 * @param array The row array, always of the real record (also for flexforms)
324 * @param string The field (empty for flexforms!)
325 * @return string Modified $value
326 */
327 function renderRecord_SW($data, $fieldConfig, $TSconfig, $table, $row, $field) {
328 switch ((string) $fieldConfig['config']['type']) {
329 case 'group':
330 $data = $this->renderRecord_groupProc($data, $fieldConfig, $TSconfig, $table, $row, $field);
331 break;
332 case 'select':
333 $data = $this->renderRecord_selectProc($data, $fieldConfig, $TSconfig, $table, $row, $field);
334 break;
335 case 'flex':
336 $data = $this->renderRecord_flexProc($data, $fieldConfig, $TSconfig, $table, $row, $field);
337 break;
338 case 'inline':
339 $data = $this->renderRecord_inlineProc($data, $fieldConfig, $TSconfig, $table, $row, $field);
340 break;
341 }
342
343 return $data;
344 }
345
346 /**
347 * Processing of the data value in case the field type is "group"
348 *
349 * @param string The field value
350 * @param array TCA field config
351 * @param array TCEform TSconfig for the record
352 * @param string Table name
353 * @param array The row
354 * @param string Field name
355 * @return string The processed input field value ($data)
356 * @access private
357 * @see renderRecord()
358 */
359 function renderRecord_groupProc($data, $fieldConfig, $TSconfig, $table, $row, $field) {
360 switch ($fieldConfig['config']['internal_type']) {
361 case 'file':
362 // Init array used to accumulate the files:
363 $dataAcc = array();
364
365 // Now, load the files into the $dataAcc array, whether stored by MM or as a list of filenames:
366 if ($fieldConfig['config']['MM']) {
367 $loadDB = t3lib_div::makeInstance('t3lib_loadDBGroup');
368 $loadDB->start('', 'files', $fieldConfig['config']['MM'], $row['uid']); // Setting dummy startup
369
370 foreach ($loadDB->itemArray as $value) {
371 if ($value['id']) {
372 $dataAcc[] = rawurlencode($value['id']) . '|' . rawurlencode($value['id']);
373 }
374 }
375 } else {
376 $fileList = t3lib_div::trimExplode(',', $data, 1);
377 foreach ($fileList as $value) {
378 if ($value) {
379 $dataAcc[] = rawurlencode($value) . '|' . rawurlencode($value);
380 }
381 }
382 }
383 // Implode the accumulation array to a comma separated string:
384 $data = implode(',', $dataAcc);
385 break;
386 case 'db':
387 $loadDB = t3lib_div::makeInstance('t3lib_loadDBGroup');
388 /* @var $loadDB t3lib_loadDBGroup */
389 $loadDB->start($data, $fieldConfig['config']['allowed'], $fieldConfig['config']['MM'], $row['uid'], $table, $fieldConfig['config']);
390 $loadDB->getFromDB();
391 $data = $loadDB->readyForInterface();
392 break;
393 }
394
395 return $data;
396 }
397
398 /**
399 * Processing of the data value in case the field type is "select"
400 *
401 * @param string The field value
402 * @param array TCA field config
403 * @param array TCEform TSconfig for the record
404 * @param string Table name
405 * @param array The row
406 * @param string Field name
407 * @return string The processed input field value ($data)
408 * @access private
409 * @see renderRecord()
410 */
411 function renderRecord_selectProc($data, $fieldConfig, $TSconfig, $table, $row, $field) {
412 global $TCA;
413
414 // Initialize:
415 $elements = t3lib_div::trimExplode(',', $data, 1); // Current data set.
416 $dataAcc = array(); // New data set, ready for interface (list of values, rawurlencoded)
417
418 // For list selectors (multi-value):
419 if (intval($fieldConfig['config']['maxitems']) > 1) {
420
421 // Add regular elements:
422 if (!is_array($fieldConfig['config']['items'])) {
423 $fieldConfig['config']['items'] = array();
424 }
425 $fieldConfig['config']['items'] = $this->procesItemArray($fieldConfig['config']['items'], $fieldConfig['config'], $TSconfig[$field], $table, $row, $field);
426 foreach ($fieldConfig['config']['items'] as $pvpv) {
427 foreach ($elements as $eKey => $value) {
428 if (!strcmp($value, $pvpv[1])) {
429 $dataAcc[$eKey] = rawurlencode($pvpv[1]) . '|' . rawurlencode($this->sL($pvpv[0]));
430 }
431 }
432 }
433
434 // Add "special"
435 if ($fieldConfig['config']['special']) {
436 $dataAcc = $this->selectAddSpecial($dataAcc, $elements, $fieldConfig['config']['special']);
437 }
438
439 // Add "foreign table" stuff:
440 if ($TCA[$fieldConfig['config']['foreign_table']]) {
441 $dataAcc = $this->selectAddForeign($dataAcc, $elements, $fieldConfig, $field, $TSconfig, $row, $table);
442 }
443
444 // Always keep the native order for display in interface:
445 ksort($dataAcc);
446 } else { // Normal, <= 1 -> value without title on it
447 if ($TCA[$fieldConfig['config']['foreign_table']]) {
448 // Getting the data
449 $dataIds = $this->getDataIdList($elements, $fieldConfig, $row, $table);
450
451 if (!count($dataIds)) {
452 $dataIds = array(0);
453 }
454 $dataAcc[] = $dataIds[0];
455 } else {
456 $dataAcc[] = $elements[0];
457 }
458 }
459
460 return implode(',', $dataAcc);
461 }
462
463 /**
464 * Processing of the data value in case the field type is "flex"
465 * MUST NOT be called in case of already INSIDE a flexform!
466 *
467 * @param string The field value
468 * @param array TCA field config
469 * @param array TCEform TSconfig for the record
470 * @param string Table name
471 * @param array The row
472 * @param string Field name
473 * @return string The processed input field value ($data)
474 * @access private
475 * @see renderRecord()
476 */
477 function renderRecord_flexProc($data, $fieldConfig, $TSconfig, $table, $row, $field) {
478 global $TCA;
479
480 // Convert the XML data to PHP array:
481 $currentValueArray = t3lib_div::xml2array($data);
482 if (is_array($currentValueArray)) {
483
484 // Get current value array:
485 $dataStructArray = t3lib_BEfunc::getFlexFormDS($fieldConfig['config'], $row, $table);
486
487 // Manipulate Flexform DS via TSConfig and group access lists
488 if (is_array($dataStructArray)) {
489 $flexFormHelper = t3lib_div::makeInstance('t3lib_TCEforms_Flexforms');
490 $dataStructArray = $flexFormHelper->modifyFlexFormDS($dataStructArray, $table, $field, $row, $fieldConfig);
491 unset($flexFormHelper);
492 }
493
494 if (is_array($dataStructArray)) {
495 $currentValueArray['data'] = $this->renderRecord_flexProc_procInData($currentValueArray['data'], $dataStructArray, array($data, $fieldConfig, $TSconfig, $table, $row, $field));
496
497 $flexObj = t3lib_div::makeInstance('t3lib_flexformtools');
498 $data = $flexObj->flexArray2Xml($currentValueArray, TRUE);
499 }
500 }
501
502 return $data;
503 }
504
505 /**
506 * Processing of the content in $totalRecordcontent based on settings in the types-configuration
507 *
508 * @param array The array of values which has been processed according to their type (eg. "group" or "select")
509 * @param array The "types" configuration for the current display of fields.
510 * @param integer PAGE TSconfig PID
511 * @param string Table name
512 * @param integer PID value
513 * @return array The processed version of $totalRecordContent
514 * @access private
515 */
516 function renderRecord_typesProc($totalRecordContent, $types_fieldConfig, $tscPID, $table, $pid) {
517 foreach ($types_fieldConfig as $vconf) {
518
519 // Find file to write to, if configured:
520 $eFile = t3lib_parsehtml_proc::evalWriteFile($vconf['spec']['static_write'], $totalRecordContent);
521
522 // Write file configuration:
523 if (is_array($eFile)) {
524 if ($eFile['loadFromFileField'] && $totalRecordContent[$eFile['loadFromFileField']]) {
525 // Read the external file, and insert the content between the ###TYPO3_STATICFILE_EDIT### markers:
526 $SW_fileContent = t3lib_div::getUrl($eFile['editFile']);
527 $parseHTML = t3lib_div::makeInstance('t3lib_parsehtml_proc');
528 $parseHTML->init('', '');
529
530 $totalRecordContent[$vconf['field']] = $parseHTML->getSubpart(
531 $SW_fileContent,
532 $eFile['markerField'] && trim($totalRecordContent[$eFile['markerField']])
533 ? trim($totalRecordContent[$eFile['markerField']])
534 : '###TYPO3_STATICFILE_EDIT###'
535 );
536 }
537 }
538 }
539
540 return $totalRecordContent;
541 }
542
543 /**
544 * Processing of the data value in case the field type is "inline"
545 * In some parts nearly the same as type "select"
546 *
547 * @param string The field value
548 * @param array TCA field config
549 * @param array TCEform TSconfig for the record
550 * @param string Table name
551 * @param array The row
552 * @param string Field name
553 * @return string The processed input field value ($data)
554 * @access private
555 * @see renderRecord()
556 */
557 function renderRecord_inlineProc($data, $fieldConfig, $TSconfig, $table, $row, $field) {
558 global $TCA;
559
560 // Initialize:
561 $elements = t3lib_div::trimExplode(',', $data); // Current data set.
562 $dataAcc = array(); // New data set, ready for interface (list of values, rawurlencoded)
563
564 // At this point all records that CAN be selected is found in $recordList
565 // Now, get the data from loadDBgroup based on the input list of values.
566 $dataIds = $this->getDataIdList($elements, $fieldConfig, $row, $table);
567
568 // After this we can traverse the loadDBgroup values and match values with the list of possible values in $recordList:
569 foreach ($dataIds as $theId) {
570 if ($fieldConfig['config']['MM'] || $fieldConfig['config']['foreign_field']) {
571 $dataAcc[] = $theId;
572 } else {
573 foreach ($elements as $eKey => $value) {
574 if (!strcmp($theId, $value)) {
575 $dataAcc[$eKey] = $theId;
576 }
577 }
578 }
579 }
580
581 return implode(',', $dataAcc);
582 }
583
584
585 /***********************************************
586 *
587 * FlexForm processing functions
588 *
589 ***********************************************/
590
591 /**
592 * Function traversing sheets/languages for flex form data structures
593 *
594 * @param array Data array
595 * @param array Data Structure array
596 * @param array Various parameters to pass-through
597 * @return array Modified $dataPart array.
598 * @access private
599 * @see t3lib_TCEmain::checkValue_flex_procInData(), renderRecord_flexProc_procInData_travDS()
600 */
601 function renderRecord_flexProc_procInData($dataPart, $dataStructArray, $pParams) {
602 if (is_array($dataPart)) {
603 foreach ($dataPart as $sKey => $sheetDef) {
604 list ($dataStruct, $actualSheet) = t3lib_div::resolveSheetDefInDS($dataStructArray, $sKey);
605
606 if (is_array($dataStruct) && $actualSheet == $sKey && is_array($sheetDef)) {
607 foreach ($sheetDef as $lKey => $lData) {
608 $this->renderRecord_flexProc_procInData_travDS(
609 $dataPart[$sKey][$lKey],
610 $dataStruct['ROOT']['el'],
611 $pParams
612 );
613 }
614 }
615 }
616 }
617
618 return $dataPart;
619 }
620
621 /**
622 * Traverse data array / structure
623 *
624 * @param array Data array passed by reference.
625 * @param array Data structure
626 * @param array Various parameters pass-through.
627 * @return void
628 * @see renderRecord_flexProc_procInData(), t3lib_TCEmain::checkValue_flex_procInData_travDS()
629 */
630 function renderRecord_flexProc_procInData_travDS(&$dataValues, $DSelements, $pParams) {
631 if (is_array($DSelements)) {
632
633 // For each DS element:
634 foreach ($DSelements as $key => $dsConf) {
635
636 // Array/Section:
637 if ($DSelements[$key]['type'] == 'array') {
638 if (is_array($dataValues[$key]['el'])) {
639 if ($DSelements[$key]['section']) {
640 foreach ($dataValues[$key]['el'] as $ik => $el) {
641 if (is_array($el)) {
642 $theKey = key($el);
643 if (is_array($dataValues[$key]['el'][$ik][$theKey]['el'])) {
644 $this->renderRecord_flexProc_procInData_travDS(
645 $dataValues[$key]['el'][$ik][$theKey]['el'],
646 $DSelements[$key]['el'][$theKey]['el'],
647 $pParams
648 );
649 }
650 }
651 }
652 } else {
653 if (!isset($dataValues[$key]['el'])) {
654 $dataValues[$key]['el'] = array();
655 }
656 $this->renderRecord_flexProc_procInData_travDS(
657 $dataValues[$key]['el'],
658 $DSelements[$key]['el'],
659 $pParams
660 );
661 }
662 }
663 } else {
664 if (is_array($dsConf['TCEforms']['config']) && is_array($dataValues[$key])) {
665 foreach ($dataValues[$key] as $vKey => $data) {
666
667 // $data,$fieldConfig,$TSconfig,$table,$row,$field
668 list(, , $CVTSconfig, $CVtable, $CVrow, $CVfield) = $pParams;
669
670 // Set default value:
671 if (!isset($dataValues[$key][$vKey])) {
672 $dataValues[$key][$vKey] = $dsConf['TCEforms']['config']['default'];
673 }
674
675 // Process value:
676 $dataValues[$key][$vKey] = $this->renderRecord_SW($dataValues[$key][$vKey], $dsConf['TCEforms'], $CVTSconfig, $CVtable, $CVrow, '');
677 }
678 }
679 }
680 }
681 }
682 }
683
684
685 /***********************************************
686 *
687 * Selector box processing functions
688 *
689 ***********************************************/
690
691 /**
692 * Adding "special" types to the $dataAcc array of selector items
693 *
694 * @param array Array with numeric keys, containing values for the selector box, prepared for interface. We are going to add elements to this array as needed.
695 * @param array The array of original elements - basically the field value exploded by ","
696 * @param string The "special" key from the TCA config of the field. Determines the type of processing in here.
697 * @return array Modified $dataAcc array
698 * @access private
699 * @see renderRecord_selectProc()
700 */
701 function selectAddSpecial($dataAcc, $elements, $specialKey) {
702 global $TCA;
703
704 // Special select types:
705 switch ((string) $specialKey) {
706 case 'tables': // Listing all tables from $TCA:
707 $tNames = array_keys($TCA);
708 foreach ($tNames as $tableName) {
709 foreach ($elements as $eKey => $value) {
710 if (!strcmp($tableName, $value)) {
711 $dataAcc[$eKey] = rawurlencode($value) . '|' . rawurlencode($this->sL($TCA[$value]['ctrl']['title']));
712 }
713 }
714 }
715 break;
716 case 'pagetypes': // Listing all page types (doktype)
717 $theTypes = $TCA['pages']['columns']['doktype']['config']['items'];
718 if (is_array($theTypes)) {
719 foreach ($theTypes as $theTypesArrays) {
720 foreach ($elements as $eKey => $value) {
721 if (!strcmp($theTypesArrays[1], $value)) {
722 $dataAcc[$eKey] = rawurlencode($value) . '|' . rawurlencode($this->sL($theTypesArrays[0]));
723 }
724 }
725 }
726 }
727 break;
728 case 'exclude': // Listing exclude fields.
729 $theExcludeFields = t3lib_BEfunc::getExcludeFields();
730
731 if (is_array($theExcludeFields)) {
732 foreach ($theExcludeFields as $theExcludeFieldsArrays) {
733 foreach ($elements as $eKey => $value) {
734 if (!strcmp($theExcludeFieldsArrays[1], $value)) {
735 $dataAcc[$eKey] = rawurlencode($value) . '|' . rawurlencode(rtrim($theExcludeFieldsArrays[0], ':'));
736 }
737 }
738 }
739 }
740 break;
741 case 'explicitValues':
742 $theTypes = t3lib_BEfunc::getExplicitAuthFieldValues();
743
744 foreach ($theTypes as $tableFieldKey => $theTypeArrays) {
745 if (is_array($theTypeArrays['items'])) {
746 foreach ($theTypeArrays['items'] as $itemValue => $itemContent) {
747 foreach ($elements as $eKey => $value) {
748 if (!strcmp($tableFieldKey . ':' . $itemValue . ':' . $itemContent[0], $value)) {
749 $dataAcc[$eKey] = rawurlencode($value) . '|' . rawurlencode('[' . $itemContent[2] . '] ' . $itemContent[1]);
750 }
751 }
752 }
753 }
754 }
755 break;
756 case 'languages':
757 $theLangs = t3lib_BEfunc::getSystemLanguages();
758 foreach ($theLangs as $lCfg) {
759 foreach ($elements as $eKey => $value) {
760 if (!strcmp($lCfg[1], $value)) {
761 $dataAcc[$eKey] = rawurlencode($value) . '|' . rawurlencode($lCfg[0]);
762 }
763 }
764 }
765 break;
766 case 'custom':
767 $customOptions = $GLOBALS['TYPO3_CONF_VARS']['BE']['customPermOptions'];
768
769 if (is_array($customOptions)) {
770 foreach ($customOptions as $coKey => $coValue) {
771 if (is_array($coValue['items'])) {
772 // Traverse items:
773 foreach ($coValue['items'] as $itemKey => $itemCfg) {
774 foreach ($elements as $eKey => $value) {
775 if (!strcmp($coKey . ':' . $itemKey, $value)) {
776 $dataAcc[$eKey] = rawurlencode($value) . '|' . rawurlencode($this->sL($itemCfg[0]));
777 }
778 }
779 }
780 }
781 }
782 }
783 break;
784 case 'modListGroup': // Listing modules for GROUPS
785 case 'modListUser': // Listing modules for USERS:
786 if (!$this->loadModules) {
787 $this->loadModules = t3lib_div::makeInstance('t3lib_loadModules');
788 $this->loadModules->load($GLOBALS['TBE_MODULES']);
789 }
790 $modList = ($specialKey == 'modListUser') ? $this->loadModules->modListUser : $this->loadModules->modListGroup;
791
792 foreach ($modList as $theModName) {
793 foreach ($elements as $eKey => $value) {
794 $label = '';
795 // Add label for main module:
796 $pp = explode('_', $value);
797 if (count($pp) > 1) {
798 $label .= $GLOBALS['LANG']->moduleLabels['tabs'][$pp[0] . '_tab'] . '>';
799 }
800 // Add modules own label now:
801 $label .= $GLOBALS['LANG']->moduleLabels['tabs'][$value . '_tab'];
802
803 if (!strcmp($theModName, $value)) {
804 $dataAcc[$eKey] = rawurlencode($value) . '|' . rawurlencode($label);
805 }
806 }
807 }
808 break;
809 }
810
811 return $dataAcc;
812 }
813
814 /**
815 * Adds the foreign record elements to $dataAcc, if any
816 *
817 * @param array Array with numeric keys, containing values for the selector box, prepared for interface. We are going to add elements to this array as needed.
818 * @param array The array of original elements - basically the field value exploded by ","
819 * @param array Field configuration from TCA
820 * @param string The field name
821 * @param array TSconfig for the record
822 * @param array The record
823 * @param array The current table
824 * @return array Modified $dataAcc array
825 * @access private
826 * @see renderRecord_selectProc()
827 */
828 function selectAddForeign($dataAcc, $elements, $fieldConfig, $field, $TSconfig, $row, $table) {
829 global $TCA;
830
831 // Init:
832 $recordList = array();
833
834 // foreign_table
835 $subres = t3lib_BEfunc::exec_foreign_table_where_query($fieldConfig, $field, $TSconfig);
836 while ($subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($subres)) {
837 $recordList[$subrow['uid']] = t3lib_BEfunc::getRecordTitle($fieldConfig['config']['foreign_table'], $subrow);
838 }
839
840 // neg_foreign_table
841 if (is_array($TCA[$fieldConfig['config']['neg_foreign_table']])) {
842 $subres = t3lib_BEfunc::exec_foreign_table_where_query($fieldConfig, $field, $TSconfig, 'neg_');
843 while ($subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($subres)) {
844 $recordList[-$subrow['uid']] = t3lib_BEfunc::getRecordTitle($fieldConfig['config']['neg_foreign_table'], $subrow);
845 }
846 }
847
848 // At this point all records that CAN be selected is found in $recordList
849 // Now, get the data from loadDBgroup based on the input list of values.
850 $dataIds = $this->getDataIdList($elements, $fieldConfig, $row, $table);
851 if ($fieldConfig['config']['MM']) {
852 $dataAcc = array();
853 } // Reset, if MM (which cannot bear anything but real relations!)
854
855 // After this we can traverse the loadDBgroup values and match values with the list of possible values in $recordList:
856 foreach ($dataIds as $theId) {
857 if (isset($recordList[$theId])) {
858 $lPrefix = $this->sL($fieldConfig['config'][($theId > 0 ? '' : 'neg_') . 'foreign_table_prefix']);
859 if ($fieldConfig['config']['MM'] || $fieldConfig['config']['foreign_field']) {
860 $dataAcc[] = rawurlencode($theId) . '|' . rawurlencode(t3lib_div::fixed_lgd_cs($lPrefix . strip_tags($recordList[$theId]), $GLOBALS['BE_USER']->uc['titleLen']));
861 } else {
862 foreach ($elements as $eKey => $value) {
863 if (!strcmp($theId, $value)) {
864 $dataAcc[$eKey] = rawurlencode($theId) . '|' . rawurlencode(t3lib_div::fixed_lgd_cs($lPrefix . strip_tags($recordList[$theId]), $GLOBALS['BE_USER']->uc['titleLen']));
865 }
866 }
867 }
868 }
869 }
870
871 return $dataAcc;
872 }
873
874 /**
875 * Returning the id-list processed by loadDBgroup for the foreign tables.
876 *
877 * @param array The array of original elements - basically the field value exploded by ","
878 * @param array Field configuration from TCA
879 * @param array The data array, currently. Used to set the "local_uid" for selecting MM relation records.
880 * @param string Current table name. passed on to t3lib_loadDBGroup
881 * @return array An array with ids of the records from the input elements array.
882 * @access private
883 */
884 function getDataIdList($elements, $fieldConfig, $row, $table) {
885 $loadDB = t3lib_div::makeInstance('t3lib_loadDBGroup');
886 $loadDB->registerNonTableValues = $fieldConfig['config']['allowNonIdValues'] ? 1 : 0;
887 $loadDB->start(implode(',', $elements),
888 $fieldConfig['config']['foreign_table'] . ',' . $fieldConfig['config']['neg_foreign_table'],
889 $fieldConfig['config']['MM'],
890 $row['uid'],
891 $table,
892 $fieldConfig['config']
893 );
894
895 $idList = $loadDB->convertPosNeg($loadDB->getValueArray(), $fieldConfig['config']['foreign_table'], $fieldConfig['config']['neg_foreign_table']);
896
897 return $idList;
898 }
899
900 /**
901 * Processing of selector box items. This includes the automated adding of elements plus user-function processing.
902 *
903 * @param array The elements to process
904 * @param array TCA/columns configuration
905 * @param array TSconfig for the field
906 * @param string The table name
907 * @param array The current row
908 * @param string The field name
909 * @return array The modified input $selItems array
910 * @access private
911 * @see renderRecord_selectProc()
912 */
913 function procesItemArray($selItems, $config, $fieldTSConfig, $table, $row, $field) {
914 $selItems = $this->addItems($selItems, $fieldTSConfig['addItems.']);
915 if ($config['itemsProcFunc']) {
916 $selItems = $this->procItems($selItems, $fieldTSConfig['itemsProcFunc.'], $config, $table, $row, $field);
917 }
918 return $selItems;
919 }
920
921 /**
922 * Adding items from $iArray to $items array
923 *
924 * @param array The array of selector box items to which key(value) / value(label) pairs from $iArray will be added.
925 * @param array The array of elements to add. The keys will become values. The value will become the label.
926 * @return array The modified input $items array
927 * @access private
928 * @see procesItemArray()
929 */
930 function addItems($items, $iArray) {
931 if (is_array($iArray)) {
932 foreach ($iArray as $value => $label) {
933 $items[] = array($label, $value);
934 }
935 }
936 return $items;
937 }
938
939 /**
940 * User processing of a selector box array of values.
941 *
942 * @param array The array of selector box items
943 * @param array TSconfig for the fields itemProcFunc
944 * @param array TCA/columns configuration
945 * @param string The table name
946 * @param array The current row
947 * @param string The field name
948 * @return array The modified input $items array
949 * @access private
950 * @see procesItemArray()
951 */
952 function procItems($items, $itemsProcFuncTSconfig, $config, $table, $row, $field) {
953 $params = array();
954 $params['items'] = &$items;
955 $params['config'] = $config;
956 $params['TSconfig'] = $itemsProcFuncTSconfig;
957 $params['table'] = $table;
958 $params['row'] = $row;
959 $params['field'] = $field;
960
961 t3lib_div::callUserFunction($config['itemsProcFunc'], $params, $this);
962 return $items;
963 }
964
965
966 /***********************************************
967 *
968 * Helper functions
969 *
970 ***********************************************/
971
972 /**
973 * Sets the lock for a record from table/id, IF $this->lockRecords is set!
974 *
975 * @param string The table name
976 * @param integer The id of the record
977 * @param integer The pid of the record
978 * @return void
979 */
980 function lockRecord($table, $id, $pid = 0) {
981 if ($this->lockRecords) {
982 t3lib_BEfunc::lockRecords($table, $id, $pid);
983 }
984 }
985
986 /**
987 * Dummy function, can be used to "register" records. Used by eg. the "show_item" script.
988 *
989 * @param string Table name
990 * @param integer Record id
991 * @param string Field name
992 * @param string Field content.
993 * @return void
994 * @access private
995 * @see renderRecord()
996 */
997 function regItem($table, $id, $field, $content) {
998 }
999
1000 /**
1001 * Local wrapper function for LANG->sL (returning language labels)
1002 *
1003 * @param string Language label key
1004 * @return string Localized label value.
1005 * @access private
1006 */
1007 function sL($in) {
1008 return $GLOBALS['LANG']->sL($in);
1009 }
1010 }
1011
1012
1013 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_transferdata.php'])) {
1014 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_transferdata.php']);
1015 }
1016
1017 ?>