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