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