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