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