[TASK] Remove global declarations inside methods
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_tceforms.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 TYPO3 Core Form generator - AKA "TCEforms"
29 *
30 * Revised for TYPO3 3.6 August/2003 by Kasper Skårhøj
31 * XHTML compliant
32 *
33 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
34 */
35 /**
36 * [CLASS/FUNCTION INDEX of SCRIPT]
37 *
38 *
39 *
40 * 196: class t3lib_TCEforms
41 * 302: function t3lib_TCEforms()
42 * 338: function initDefaultBEmode()
43 *
44 * SECTION: Rendering the forms, fields etc
45 * 385: function getSoloField($table,$row,$theFieldToReturn)
46 * 424: function getMainFields($table,$row,$depth=0)
47 * 618: function getListedFields($table,$row,$list)
48 * 660: function getPaletteFields($table,$row,$palette,$header='',$itemList='',$collapsedHeader='')
49 * 737: function getSingleField($table,$field,$row,$altName='',$palette=0,$extra='',$pal=0)
50 * 900: function getSingleField_SW($table,$field,$row,&$PA)
51 *
52 * SECTION: Rendering of each TCEform field type
53 * 976: function getSingleField_typeInput($table,$field,$row,&$PA)
54 * 1057: function getSingleField_typeText($table,$field,$row,&$PA)
55 * 1178: function getSingleField_typeCheck($table,$field,$row,&$PA)
56 * 1244: function getSingleField_typeRadio($table,$field,$row,&$PA)
57 * 1279: function getSingleField_typeSelect($table,$field,$row,&$PA)
58 * 1359: function getSingleField_typeSelect_single($table,$field,$row,&$PA,$config,$selItems,$nMV_label)
59 * 1490: function getSingleField_typeSelect_checkbox($table,$field,$row,&$PA,$config,$selItems,$nMV_label)
60 * 1609: function getSingleField_typeSelect_singlebox($table,$field,$row,&$PA,$config,$selItems,$nMV_label)
61 * 1719: function getSingleField_typeSelect_multiple($table,$field,$row,&$PA,$config,$selItems,$nMV_label)
62 * 1823: function getSingleField_typeGroup($table,$field,$row,&$PA)
63 * 1992: function getSingleField_typeNone($table,$field,$row,&$PA)
64 * 2008: function getSingleField_typeNone_render($config,$itemValue)
65 * 2070: function getSingleField_typeFlex($table,$field,$row,&$PA)
66 * 2205: function getSingleField_typeFlex_langMenu($languages,$elName,$selectedLanguage,$multi=1)
67 * 2224: function getSingleField_typeFlex_sheetMenu($sArr,$elName,$sheetKey)
68 * 2259: function getSingleField_typeFlex_draw($dataStruct,$editData,$cmdData,$table,$field,$row,&$PA,$formPrefix='',$level=0,$tRows=array())
69 * 2452: function getSingleField_typeUnknown($table,$field,$row,&$PA)
70 * 2467: function getSingleField_typeUser($table,$field,$row,&$PA)
71 *
72 * SECTION: Field content processing
73 * 2496: function formatValue ($config, $itemValue)
74 *
75 * SECTION: "Configuration" fetching/processing functions
76 * 2588: function getRTypeNum($table,$row)
77 * 2614: function rearrange($fields)
78 * 2640: function getExcludeElements($table,$row,$typeNum)
79 * 2688: function getFieldsToAdd($table,$row,$typeNum)
80 * 2713: function mergeFieldsWithAddedFields($fields,$fieldsToAdd)
81 * 2745: function setTSconfig($table,$row,$field='')
82 * 2767: function getSpecConfForField($table,$row,$field)
83 * 2788: function getSpecConfFromString($extraString, $defaultExtras)
84 * 3007: function loadPaletteElements($table, $row, $palette, $itemList='')
85 *
86 * SECTION: Display of localized content etc.
87 * 2816: function registerDefaultLanguageData($table,$rec)
88 * 2848: function getLanguageOverlayRawValue($table, $row, $field, $fieldConf)
89 * 2876: function renderDefaultLanguageContent($table,$field,$row,$item)
90 * 2899: function renderDefaultLanguageDiff($table,$field,$row,$item)
91 *
92 * SECTION: Form element helper functions
93 * 2955: function dbFileIcons($fName,$mode,$allowed,$itemArray,$selector='',$params=array(),$onFocus='')
94 * 3108: function getClipboardElements($allowed,$mode)
95 * 3157: function getClickMenu($str,$table,$uid='')
96 * 3178: function renderWizards($itemKinds,$wizConf,$table,$row,$field,&$PA,$itemName,$specConf,$RTE=0)
97 * 3382: function getIcon($icon)
98 * 3409: function optionTagStyle($iconString)
99 * 3425: function extractValuesOnlyFromValueLabelList($itemFormElValue)
100 * 3447: function wrapOpenPalette($header,$table,$row,$palette,$retFunc=0)
101 * 3471: function checkBoxParams($itemName,$thisValue,$c,$iCount,$addFunc='')
102 * 3485: function elName($itemName)
103 * 3496: function noTitle($str,$wrapParts=array())
104 * 3505: function blur()
105 * 3514: function thisReturnUrl()
106 * 3527: function getSingleHiddenField($table,$field,$row)
107 * 3549: function formWidth($size=48,$textarea=0)
108 * 3576: function formWidthText($size=48,$wrap='')
109 * 3592: function formElStyle($type)
110 * 3603: function formElClass($type)
111 * 3614: function formElStyleClassValue($type, $class=FALSE)
112 * 3638: function insertDefStyle($type)
113 * 3657: function getDynTabMenu($parts, $idString)
114 *
115 * SECTION: Item-array manipulation functions (check/select/radio)
116 * 3696: function initItemArray($fieldValue)
117 * 3714: function addItems($items,$iArray)
118 * 3736: function procItems($items,$iArray,$config,$table,$row,$field)
119 * 3760: function addSelectOptionsToItemArray($items,$fieldValue,$TSconfig,$field)
120 * 3980: function addSelectOptionsToItemArray_makeModuleData($value)
121 * 4002: function foreignTable($items,$fieldValue,$TSconfig,$field,$pFFlag=0)
122 *
123 * SECTION: Template functions
124 * 4083: function setNewBEDesign()
125 * 4138: function intoTemplate($inArr,$altTemplate='')
126 * 4162: function addUserTemplateMarkers($marker,$table,$field,$row,&$PA)
127 * 4173: function wrapLabels($str)
128 * 4186: function wrapTotal($c,$rec,$table)
129 * 4199: function replaceTableWrap($arr,$rec,$table)
130 * 4236: function wrapBorder(&$out_array,&$out_pointer)
131 * 4258: function rplColorScheme($inTemplate)
132 * 4278: function getDivider()
133 * 4288: function printPalette($palArr)
134 * 4339: function helpTextIcon($table,$field,$force=0)
135 * 4359: function helpText($table,$field)
136 * 4380: function setColorScheme($scheme)
137 * 4404: function resetSchemes()
138 * 4415: function storeSchemes()
139 * 4427: function restoreSchemes()
140 *
141 * SECTION: JavaScript related functions
142 * 4457: function JStop()
143 * 4508: function JSbottom($formname='forms[0]')
144 * 4835: function dbFileCon($formObj='document.forms[0]')
145 * 5053: function printNeededJSFunctions()
146 * 5080: function printNeededJSFunctions_top()
147 *
148 * SECTION: Various helper functions
149 * 5128: function getDefaultRecord($table,$pid=0)
150 * 5167: function getRecordPath($table,$rec)
151 * 5181: function readPerms()
152 * 5195: function sL($str)
153 * 5208: function getLL($str)
154 * 5229: function isPalettesCollapsed($table,$palette)
155 * 5245: function isDisplayCondition($displayCond,$row,$ffValueKey='')
156 * 5349: function getTSCpid($table,$uid,$pid)
157 * 5363: function doLoadTableDescr($table)
158 * 5375: function getAvailableLanguages($onlyIsoCoded=1,$setDefault=1)
159 *
160 *
161 * 5417: class t3lib_TCEforms_FE extends t3lib_TCEforms
162 * 5425: function wrapLabels($str)
163 * 5435: function printPalette($palArr)
164 * 5460: function setFancyDesign()
165 *
166 * TOTAL FUNCTIONS: 100
167 * (This index is automatically created/updated by the extension "extdeveval")
168 *
169 */
170
171
172 /**
173 * 'TCEforms' - Class for creating the backend editing forms.
174 *
175 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
176 * @coauthor René Fritz <r.fritz@colorcube.de>
177 * @package TYPO3
178 * @subpackage t3lib
179 */
180 class t3lib_TCEforms {
181
182 // variables not commented yet.... (do so...)
183 var $palFieldArr = array();
184 var $disableWizards = 0;
185 var $isPalettedoc = 0;
186 var $paletteMargin = 1;
187 var $defStyle = ''; // 'font-family:Verdana;font-size:10px;';
188 var $cachedTSconfig = array();
189 var $cachedTSconfig_fieldLevel = array();
190 var $cachedLanguageFlag = array();
191 var $cachedAdditionalPreviewLanguages = NULL;
192 var $transformedRow = array();
193 var $extJSCODE = '';
194 var $printNeededJS = array();
195 var $hiddenFieldAccum = array();
196 var $TBE_EDITOR_fieldChanged_func = '';
197 var $loadMD5_JS = 1;
198 var $prevBorderStyle = '[nothing here...]'; // Something unique...
199 var $allowUpload = 0; // If set direct upload fields will be shown
200 var $titleLen = 15; // @deprecated since TYPO3 4.1: $GLOBALS['BE_USER']->uc['titleLen'] but what is default??
201 var $defaultLanguageData = array(); // Array where records in the default language is stored. (processed by transferdata)
202 var $defaultLanguageData_diff = array(); // Array where records in the default language is stored (raw without any processing. used for making diff)
203 var $additionalPreviewLanguageData = array();
204
205
206 // EXTERNAL, static
207 var $backPath = ''; // Set this to the 'backPath' pointing back to the typo3 admin directory from the script where this form is displayed.
208 var $returnUrl = ''; // Alternative return URL path (default is t3lib_div::linkThisScript())
209 var $doSaveFieldName = ''; // Can be set to point to a field name in the form which will be set to '1' when the form is submitted with a *save* button. This way the recipient script can determine that the form was submitted for save and not "close" for example.
210 var $palettesCollapsed = 0; // Can be set TRUE/FALSE to whether palettes (secondary options) are in the topframe or in form. TRUE means they are NOT IN-form. So a collapsed palette is one, which is shown in the top frame, not in the page.
211 var $disableRTE = 0; // If set, the RTE is disabled (from form display, eg. by checkbox in the bottom of the page!)
212 var $globalShowHelp = 1; // If FALSE, then all CSH will be disabled, regardless of settings in $this->edit_showFieldHelp
213 var $localizationMode = ''; // If TRUE, the forms are rendering only localization relevant fields of the records.
214 var $fieldOrder = ''; // Overrule the field order set in TCA[types][showitem], eg for tt_content this value, 'bodytext,image', would make first the 'bodytext' field, then the 'image' field (if set for display)... and then the rest in the old order.
215 var $doPrintPalette = 1; // If set to FALSE, palettes will NEVER be rendered.
216
217 /**
218 * Set to initialized clipboard object; Then the element browser will offer a link to paste in records from clipboard.
219 *
220 * @var t3lib_clipboard
221 */
222 var $clipObj = FALSE;
223 var $enableClickMenu = FALSE; // Enable click menu on reference icons.
224 var $enableTabMenu = FALSE; // Enable Tab Menus.
225 var $renderReadonly = FALSE; // When enabled all fields are rendered non-editable.
226
227 var $form_rowsToStylewidth = 9.58; // Form field width compensation: Factor from NN4 form field widths to style-aware browsers (like NN6+ and MSIE, with the $GLOBALS['CLIENT']['FORMSTYLE'] value set)
228 var $form_largeComp = 1.33; // Form field width compensation: Compensation for large documents, doc-tab (editing)
229 var $charsPerRow = 40; // The number of chars expected per row when the height of a text area field is automatically calculated based on the number of characters found in the field content.
230 var $maxTextareaWidth = 48; // The maximum abstract value for textareas
231 var $maxInputWidth = 48; // The maximum abstract value for input fields
232 var $defaultMultipleSelectorStyle = 'width:250px;'; // Default style for the selector boxes used for multiple items in "select" and "group" types.
233
234
235 // INTERNAL, static
236 var $prependFormFieldNames = 'data'; // The string to prepend formfield names with.
237 var $prependCmdFieldNames = 'cmd'; // The string to prepend commands for tcemain::process_cmdmap with.
238 var $prependFormFieldNames_file = 'data_files'; // The string to prepend FILE form field names with.
239 var $formName = 'editform'; // The name attribute of the form.
240 var $allowOverrideMatrix = array(); // Whitelist that allows TCA field configuration to be overridden by TSconfig, @see overrideFieldConf()
241
242
243 // INTERNAL, dynamic
244 var $perms_clause = ''; // Set by readPerms() (caching)
245 var $perms_clause_set = 0; // Set by readPerms() (caching-flag)
246 var $edit_showFieldHelp = ''; // Used to indicate the mode of CSH (Context Sensitive Help), whether it should be icons-only ('icon'), full description ('text') or not at all (blank).
247 var $docLarge = 0; // If set, the forms will be rendered a little wider, more precisely with a factor of $this->form_largeComp.
248 var $clientInfo = array(); // Loaded with info about the browser when class is instantiated.
249 var $RTEenabled = 0; // TRUE, if RTE is possible for the current user (based on result from BE_USER->isRTE())
250 var $RTEenabled_notReasons = ''; // If $this->RTEenabled was FALSE, you can find the reasons listed in this array which is filled with reasons why the RTE could not be loaded)
251 var $RTEcounter = 0; // Counter that is incremented before an RTE is created. Can be used for unique ids etc.
252
253 var $colorScheme; // Contains current color scheme
254 var $classScheme; // Contains current class scheme
255 var $defColorScheme; // Contains the default color scheme
256 var $defClassScheme; // Contains the default class scheme
257 var $fieldStyle; // Contains field style values
258 var $borderStyle; // Contains border style values.
259
260 var $commentMessages = array(); // An accumulation of messages from the class.
261
262 // INTERNAL, templates
263 var $totalWrap = '<hr />|<hr />'; // Total wrapping for the table rows.
264 var $fieldTemplate = '<strong>###FIELD_NAME###</strong><br />###FIELD_ITEM###<hr />'; // Field template
265 var $sectionWrap = ''; // Wrapping template code for a section
266 var $palFieldTemplateHeader = ''; // Template for palette headers
267 var $palFieldTemplate = ''; // Template for palettes
268
269 // INTERNAL, working memory
270 var $excludeElements = ''; // Set to the fields NOT to display, if any.
271 var $palettesRendered = array(); // During rendering of forms this will keep track of which palettes has already been rendered (so they are not rendered twice by mistake)
272 var $hiddenFieldListArr = array(); // This array of fields will be set as hidden-fields instead of rendered normally! For instance palette fields edited in the top frame are set as hidden fields since the main form has to submit the values. The top frame actually just sets the value in the main form!
273 var $requiredFields = array(); // Used to register input-field names, which are required. (Done during rendering of the fields). This information is then used later when the JavaScript is made.
274 var $requiredAdditional = array(); // Used to register input-field names, which are required an have additional requirements (e.g. like a date/time must be positive integer). The information of this array is merged with $this->requiredFields later.
275 var $requiredElements = array(); // Used to register the min and max number of elements for selectorboxes where that apply (in the "group" type for instance)
276 var $requiredNested = array(); // Used to determine where $requiredFields or $requiredElements are nested (in Tabs or IRRE)
277 var $renderDepth = 0; // Keeps track of the rendering depth of nested records.
278 var $savedSchemes = array(); // Color scheme buffer.
279 var $dynNestedStack = array(); // holds the path an element is nested in (e.g. required for RTEhtmlarea)
280
281 // Internal, registers for user defined functions etc.
282 var $additionalCode_pre = array(); // Additional HTML code, printed before the form.
283 var $additionalJS_pre = array(); // Additional JavaScript, printed before the form
284 var $additionalJS_post = array(); // Additional JavaScript printed after the form
285 var $additionalJS_submit = array(); // Additional JavaScript executed on submit; If you set "OK" variable it will raise an error about RTEs not being loaded and offer to block further submission.
286 var $additionalJS_delete = array(); // Additional JavaScript executed when section element is deleted. This is neceessary, for example, to correctly clean up HTMLArea RTE (bug #8232)
287
288 /**
289 * Instance of t3lib_tceforms_inline
290 *
291 * @var t3lib_TCEforms_inline
292 */
293 var $inline;
294 var $hookObjectsMainFields = array(); // Array containing hook class instances called once for a form
295 var $hookObjectsSingleField = array(); // Array containing hook class instances called for each field
296 var $extraFormHeaders = array(); // Rows gettings inserted into the alt_doc headers (when called from alt_doc.php)
297
298 public $templateFile = ''; // Form templates, relative to typo3 directory
299
300
301 /**
302 * Constructor function, setting internal variables, loading the styles used.
303 *
304 * @return void
305 */
306 function __construct() {
307 $this->clientInfo = t3lib_div::clientInfo();
308
309 $this->RTEenabled = $GLOBALS['BE_USER']->isRTE();
310 if (!$this->RTEenabled) {
311 $this->RTEenabled_notReasons = implode(LF, $GLOBALS['BE_USER']->RTE_errors);
312 $this->commentMessages[] = 'RTE NOT ENABLED IN SYSTEM due to:' . LF . $this->RTEenabled_notReasons;
313 }
314
315 // Default color+class scheme
316 $this->defColorScheme = array(
317 $GLOBALS['SOBE']->doc->bgColor, // Background for the field AND palette
318 t3lib_div::modifyHTMLColorAll($GLOBALS['SOBE']->doc->bgColor, -20), // Background for the field header
319 t3lib_div::modifyHTMLColorAll($GLOBALS['SOBE']->doc->bgColor, -10), // Background for the palette field header
320 'black', // Field header font color
321 '#666666' // Palette field header font color
322 );
323 $this->defColorScheme = array();
324
325 // Override / Setting defaults from TBE_STYLES array
326 $this->resetSchemes();
327
328 // Setting the current colorScheme to default.
329 $this->defColorScheme = $this->colorScheme;
330 $this->defClassScheme = $this->classScheme;
331
332 // Define whitelist that allows TCA field configuration to be overridden by TSconfig, @see overrideFieldConf():
333 $this->allowOverrideMatrix = array(
334 'input' => array('size', 'max'),
335 'text' => array('cols', 'rows', 'wrap'),
336 'check' => array('cols', 'showIfRTE'),
337 'select' => array('size', 'autoSizeMax', 'maxitems', 'minitems'),
338 'group' => array('size', 'autoSizeMax', 'max_size', 'show_thumbs', 'maxitems', 'minitems', 'disable_controls'),
339 'inline' => array('appearance', 'behaviour', 'foreign_label', 'foreign_selector', 'foreign_unique', 'maxitems', 'minitems', 'size', 'autoSizeMax', 'symmetric_label'),
340 );
341
342 // Create instance of t3lib_TCEforms_inline only if this a non-IRRE-AJAX call:
343 if (!isset($GLOBALS['ajaxID']) || strpos($GLOBALS['ajaxID'], 't3lib_TCEforms_inline::') !== 0) {
344 $this->inline = t3lib_div::makeInstance('t3lib_TCEforms_inline');
345 }
346 // Create instance of t3lib_TCEforms_suggest only if this a non-Suggest-AJAX call:
347 if (!isset($GLOBALS['ajaxID']) || strpos($GLOBALS['ajaxID'], 't3lib_TCEforms_suggest::') !== 0) {
348 $this->suggest = t3lib_div::makeInstance('t3lib_TCEforms_suggest');
349 }
350
351 // Prepare user defined objects (if any) for hooks which extend this function:
352 $this->hookObjectsMainFields = array();
353 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getMainFieldsClass'])) {
354 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getMainFieldsClass'] as $classRef) {
355 $this->hookObjectsMainFields[] = t3lib_div::getUserObj($classRef);
356 }
357 }
358 $this->hookObjectsSingleField = array();
359 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getSingleFieldClass'])) {
360 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getSingleFieldClass'] as $classRef) {
361 $this->hookObjectsSingleField[] = t3lib_div::getUserObj($classRef);
362 }
363 }
364
365 $this->templateFile = 'templates/tceforms.html';
366
367 }
368
369 /**
370 * Initialize various internal variables.
371 *
372 * @return void
373 */
374 function initDefaultBEmode() {
375 $this->prependFormFieldNames = 'data';
376 $this->formName = 'editform';
377 $this->setNewBEDesign();
378 $this->docLarge = ($GLOBALS['BE_USER']->uc['edit_wideDocument'] ? 1 : 0);
379 $this->edit_showFieldHelp = $GLOBALS['BE_USER']->uc['edit_showFieldHelp'];
380
381 $this->edit_docModuleUpload = $GLOBALS['BE_USER']->uc['edit_docModuleUpload'];
382 $this->titleLen = $GLOBALS['BE_USER']->uc['titleLen']; // @deprecated since TYPO3 4.1
383
384 $this->inline->init($this);
385 $this->suggest->init($this);
386 }
387
388
389 /*******************************************************
390 *
391 * Rendering the forms, fields etc
392 *
393 *******************************************************/
394
395 /**
396 * Will return the TCEform element for just a single field from a record.
397 * The field must be listed in the currently displayed fields (as found in [types][showitem]) for the record.
398 * This also means that the $table/$row supplied must be complete so the list of fields to show can be found correctly
399 *
400 * @param string The table name
401 * @param array The record from the table for which to render a field.
402 * @param string The field name to return the TCEform element for.
403 * @return string HTML output
404 * @see getMainFields()
405 */
406 function getSoloField($table, $row, $theFieldToReturn) {
407 if ($GLOBALS['TCA'][$table]) {
408 t3lib_div::loadTCA($table);
409 $typeNum = $this->getRTypeNum($table, $row);
410 if ($GLOBALS['TCA'][$table]['types'][$typeNum]) {
411 $itemList = $GLOBALS['TCA'][$table]['types'][$typeNum]['showitem'];
412 if ($itemList) {
413 $fields = t3lib_div::trimExplode(',', $itemList, 1);
414 $excludeElements = $this->excludeElements = $this->getExcludeElements($table, $row, $typeNum);
415
416 foreach ($fields as $fieldInfo) {
417 $parts = explode(';', $fieldInfo);
418
419 $theField = trim($parts[0]);
420 if (!in_array($theField, $excludeElements) && !strcmp($theField, $theFieldToReturn)) {
421 if ($GLOBALS['TCA'][$table]['columns'][$theField]) {
422 $sField = $this->getSingleField($table, $theField, $row, $parts[1], 1, $parts[3], $parts[2]);
423 return $sField['ITEM'];
424 }
425 }
426 }
427 }
428 }
429 }
430 }
431
432 /**
433 * Based on the $table and $row of content, this displays the complete TCEform for the record.
434 * The input-$row is required to be preprocessed if necessary by eg. the t3lib_transferdata class. For instance the RTE content should be transformed through this class first.
435 *
436 * @param string The table name
437 * @param array The record from the table for which to render a field.
438 * @param integer Depth level
439 * @return string HTML output
440 * @see getSoloField()
441 */
442 function getMainFields($table, $row, $depth = 0) {
443 $this->renderDepth = $depth;
444
445 // Init vars:
446 $out_array = array(array());
447 $out_array_meta = array(array(
448 'title' => $this->getLL('l_generalTab')
449 ));
450
451 $out_pointer = 0;
452 $out_sheet = 0;
453 $this->palettesRendered = array();
454 $this->palettesRendered[$this->renderDepth][$table] = array();
455
456 // Hook: getMainFields_preProcess (requested by Thomas Hempel for use with the "dynaflex" extension)
457 foreach ($this->hookObjectsMainFields as $hookObj) {
458 if (method_exists($hookObj, 'getMainFields_preProcess')) {
459 $hookObj->getMainFields_preProcess($table, $row, $this);
460 }
461 }
462
463 if ($GLOBALS['TCA'][$table]) {
464
465 // Load the full TCA for the table.
466 t3lib_div::loadTCA($table);
467
468 // Get dividers2tabs setting from TCA of the current table:
469 $dividers2tabs =& $GLOBALS['TCA'][$table]['ctrl']['dividers2tabs'];
470
471 // Load the description content for the table.
472 if ($this->edit_showFieldHelp || $this->doLoadTableDescr($table)) {
473 $GLOBALS['LANG']->loadSingleTableDescription($table);
474 }
475 // Get the current "type" value for the record.
476 $typeNum = $this->getRTypeNum($table, $row);
477
478 // Find the list of fields to display:
479 if ($GLOBALS['TCA'][$table]['types'][$typeNum]) {
480 $itemList = $GLOBALS['TCA'][$table]['types'][$typeNum]['showitem'];
481 if ($itemList) { // If such a list existed...
482 // Explode the field list and possibly rearrange the order of the fields, if configured for
483 $fields = t3lib_div::trimExplode(',', $itemList, 1);
484 if ($this->fieldOrder) {
485 $fields = $this->rearrange($fields);
486 }
487
488 // Get excluded fields, added fiels and put it together:
489 $excludeElements = $this->excludeElements = $this->getExcludeElements($table, $row, $typeNum);
490 $fields = $this->mergeFieldsWithAddedFields($fields, $this->getFieldsToAdd($table, $row, $typeNum));
491
492 // If TCEforms will render a tab menu in the next step, push the name to the tab stack:
493 $tabIdentString = '';
494 $tabIdentStringMD5 = '';
495 if (strstr($itemList, '--div--') !== FALSE && $this->enableTabMenu && $dividers2tabs) {
496 $tabIdentString = 'TCEforms:' . $table . ':' . $row['uid'];
497 $tabIdentStringMD5 = $GLOBALS['TBE_TEMPLATE']->getDynTabMenuId($tabIdentString);
498 // Remember that were currently working on the general tab:
499 if (isset($fields[0]) && strpos($fields[0], '--div--') !== 0) {
500 $this->pushToDynNestedStack('tab', $tabIdentStringMD5 . '-1');
501 }
502 }
503
504 // Traverse the fields to render:
505 $cc = 0;
506 foreach ($fields as $fieldInfo) {
507 // Exploding subparts of the field configuration:
508 $parts = explode(';', $fieldInfo);
509
510 // Getting the style information out:
511 $color_style_parts = t3lib_div::trimExplode('-', $parts[4]);
512 if (strcmp($color_style_parts[0], '')) {
513 $this->setColorScheme($GLOBALS['TBE_STYLES']['colorschemes'][intval($color_style_parts[0])]);
514 }
515 if (strcmp($color_style_parts[1], '')) {
516 $this->fieldStyle = $GLOBALS['TBE_STYLES']['styleschemes'][intval($color_style_parts[1])];
517 if (!isset($this->fieldStyle)) {
518 $this->fieldStyle = $GLOBALS['TBE_STYLES']['styleschemes'][0];
519 }
520 }
521 if (strcmp($color_style_parts[2], '')) {
522 $this->wrapBorder($out_array[$out_sheet], $out_pointer);
523 $this->borderStyle = $GLOBALS['TBE_STYLES']['borderschemes'][intval($color_style_parts[2])];
524 if (!isset($this->borderStyle)) {
525 $this->borderStyle = $GLOBALS['TBE_STYLES']['borderschemes'][0];
526 }
527 }
528
529 // Render the field:
530 $theField = $parts[0];
531 if (!in_array($theField, $excludeElements)) {
532 if ($GLOBALS['TCA'][$table]['columns'][$theField]) {
533 $sFieldPal = '';
534
535 if ($parts[2] && !isset($this->palettesRendered[$this->renderDepth][$table][$parts[2]])) {
536 $sFieldPal = $this->getPaletteFields($table, $row, $parts[2]);
537 $this->palettesRendered[$this->renderDepth][$table][$parts[2]] = 1;
538 }
539 $sField = $this->getSingleField($table, $theField, $row, $parts[1], 0, $parts[3], $parts[2]);
540 if ($sField) {
541 $sField .= $sFieldPal;
542 }
543
544 $out_array[$out_sheet][$out_pointer] .= $sField;
545 } elseif ($theField == '--div--') {
546 if ($cc > 0) {
547 $out_array[$out_sheet][$out_pointer] .= $this->getDivider();
548
549 if ($this->enableTabMenu && $dividers2tabs) {
550 $this->wrapBorder($out_array[$out_sheet], $out_pointer);
551 // Remove last tab entry from the dynNestedStack:
552 $out_sheet++;
553 // Remove the previous sheet from stack (if any):
554 $this->popFromDynNestedStack('tab', $tabIdentStringMD5 . '-' . ($out_sheet));
555 // Remember on which sheet we're currently working:
556 $this->pushToDynNestedStack('tab', $tabIdentStringMD5 . '-' . ($out_sheet + 1));
557 $out_array[$out_sheet] = array();
558 $out_array_meta[$out_sheet]['title'] = $this->sL($parts[1]);
559 // Register newline for Tab
560 $out_array_meta[$out_sheet]['newline'] = ($parts[2] == "newline");
561 }
562 } else { // Setting alternative title for "General" tab if "--div--" is the very first element.
563 $out_array_meta[$out_sheet]['title'] = $this->sL($parts[1]);
564 // Only add the first tab to the dynNestedStack if there are more tabs:
565 if ($tabIdentString && strpos($itemList, '--div--', strlen($fieldInfo))) {
566 $this->pushToDynNestedStack('tab', $tabIdentStringMD5 . '-1');
567 }
568 }
569 } elseif ($theField == '--palette--') {
570 if ($parts[2] && !isset($this->palettesRendered[$this->renderDepth][$table][$parts[2]])) {
571 // render a 'header' if not collapsed
572 if ($GLOBALS['TCA'][$table]['palettes'][$parts[2]]['canNotCollapse'] && $parts[1]) {
573 $out_array[$out_sheet][$out_pointer] .= $this->getPaletteFields($table, $row, $parts[2], $this->sL($parts[1]));
574 } else {
575 $out_array[$out_sheet][$out_pointer] .= $this->getPaletteFields($table, $row, $parts[2], '', '', $this->sL($parts[1]));
576 }
577 $this->palettesRendered[$this->renderDepth][$table][$parts[2]] = 1;
578 }
579 }
580 }
581
582 $cc++;
583 }
584 }
585 }
586 }
587
588 // Hook: getMainFields_postProcess (requested by Thomas Hempel for use with the "dynaflex" extension)
589 foreach ($this->hookObjectsMainFields as $hookObj) {
590 if (method_exists($hookObj, 'getMainFields_postProcess')) {
591 $hookObj->getMainFields_postProcess($table, $row, $this);
592 }
593 }
594
595 // Wrapping a border around it all:
596 $this->wrapBorder($out_array[$out_sheet], $out_pointer);
597
598 // Resetting styles:
599 $this->resetSchemes();
600
601 // Rendering Main palettes, if any
602 $mParr = t3lib_div::trimExplode(',', $GLOBALS['TCA'][$table]['ctrl']['mainpalette']);
603 $i = 0;
604 if (count($mParr)) {
605 foreach ($mParr as $mP) {
606 if (!isset($this->palettesRendered[$this->renderDepth][$table][$mP])) {
607 $temp_palettesCollapsed = $this->palettesCollapsed;
608 $this->palettesCollapsed = 0;
609 $label = ($i == 0 ? $this->getLL('l_generalOptions') : $this->getLL('l_generalOptions_more'));
610 $out_array[$out_sheet][$out_pointer] .= $this->getPaletteFields($table, $row, $mP, $label);
611 $this->palettesCollapsed = $temp_palettesCollapsed;
612 $this->palettesRendered[$this->renderDepth][$table][$mP] = 1;
613 }
614 $this->wrapBorder($out_array[$out_sheet], $out_pointer);
615 $i++;
616 if ($this->renderDepth) {
617 $this->renderDepth--;
618 }
619 }
620 }
621
622 // Return the imploded $out_array:
623 if ($out_sheet > 0) { // There were --div-- dividers around...
624
625 // Create parts array for the tab menu:
626 $parts = array();
627 foreach ($out_array as $idx => $sheetContent) {
628 $content = implode('', $sheetContent);
629 if ($content) {
630 // Wrap content (row) with table-tag, otherwise tab/sheet will be disabled (see getdynTabMenu() )
631 $content = '<table border="0" cellspacing="0" cellpadding="0" width="100%">' . $content . '</table>';
632 }
633 $parts[$idx] = array(
634 'label' => $out_array_meta[$idx]['title'],
635 'content' => $content,
636 'newline' => $out_array_meta[$idx]['newline'], // Newline for this tab/sheet
637 );
638 }
639
640 if (count($parts) > 1) {
641 // Unset the current level of tab menus:
642 $this->popFromDynNestedStack('tab', $tabIdentStringMD5 . '-' . ($out_sheet + 1));
643 $dividersToTabsBehaviour = (isset($GLOBALS['TCA'][$table]['ctrl']['dividers2tabs'])
644 ? $GLOBALS['TCA'][$table]['ctrl']['dividers2tabs']
645 : 1);
646 $output = $this->getDynTabMenu($parts, $tabIdentString, $dividersToTabsBehaviour);
647
648 } else {
649 // If there is only one tab/part there is no need to wrap it into the dynTab code
650 $output = isset($parts[0]) ? trim($parts[0]['content']) : '';
651 }
652
653 $output = '
654 <tr>
655 <td colspan="2">
656 ' . $output . '
657 </td>
658 </tr>';
659
660 } else {
661 // Only one, so just implode:
662 $output = implode('', $out_array[$out_sheet]);
663 }
664
665 return $output;
666 }
667
668 /**
669 * Will return the TCEform elements for a pre-defined list of fields.
670 * Notice that this will STILL use the configuration found in the list [types][showitem] for those fields which are found there. So ideally the list of fields given as argument to this function should also be in the current [types][showitem] list of the record.
671 * Used for displaying forms for the frontend edit icons for instance.
672 *
673 * @param string The table name
674 * @param array The record array.
675 * @param string Commalist of fields from the table. These will be shown in the specified order in a form.
676 * @return string TCEform elements in a string.
677 */
678 function getListedFields($table, $row, $list) {
679 t3lib_div::loadTCA($table);
680 if ($this->edit_showFieldHelp || $this->doLoadTableDescr($table)) {
681 $GLOBALS['LANG']->loadSingleTableDescription($table);
682 }
683
684 $out = '';
685 $types_fieldConfig = t3lib_BEfunc::getTCAtypes($table, $row, 1);
686
687 $editFieldList = array_unique(t3lib_div::trimExplode(',', $list, 1));
688 foreach ($editFieldList as $theFieldC) {
689 list($theField, $palFields) = preg_split('/\[|\]/', $theFieldC);
690 $theField = trim($theField);
691 $palFields = trim($palFields);
692 if ($GLOBALS['TCA'][$table]['columns'][$theField]) {
693 $parts = t3lib_div::trimExplode(';', $types_fieldConfig[$theField]['origString']);
694 $sField = $this->getSingleField($table, $theField, $row, $parts[1], 0, $parts[3], 0); // Don't sent palette pointer - there are no options anyways for a field-list.
695 $out .= $sField;
696 } elseif ($theField == '--div--') {
697 $out .= $this->getDivider();
698 }
699 if ($palFields) {
700 $out .= $this->getPaletteFields($table, $row, '', '', implode(',', t3lib_div::trimExplode('|', $palFields, 1)));
701 }
702 }
703
704 return $out;
705 }
706
707 /**
708 * Creates a palette (collection of secondary options).
709 *
710 * @param string The table name
711 * @param array The row array
712 * @param string The palette number/pointer
713 * @param string Header string for the palette (used when in-form). If not set, no header item is made.
714 * @param string Optional alternative list of fields for the palette
715 * @param string Optional Link text for activating a palette (when palettes does not have another form element to belong to).
716 * @return string HTML code.
717 */
718 function getPaletteFields($table, $row, $palette, $header = '', $itemList = '', $collapsedHeader = NULL) {
719 if (!$this->doPrintPalette) {
720 return '';
721 }
722
723 $out = '';
724 $parts = $this->loadPaletteElements($table, $row, $palette, $itemList);
725
726 // Put palette together if there are fields in it:
727 if (count($parts)) {
728
729 $realFields = 0;
730
731 foreach ($parts as $part) {
732 if ($part['NAME'] !== '--linebreak--') {
733 $realFields++;
734 }
735 }
736
737 if ($realFields > 0) {
738
739 if ($header) {
740 $out .= $this->intoTemplate(
741 array('HEADER' => htmlspecialchars($header)),
742 $this->palFieldTemplateHeader
743 );
744 }
745
746 $collapsed = $this->isPalettesCollapsed($table, $palette);
747
748 $thePalIcon = '';
749 if ($collapsed && $collapsedHeader !== NULL) {
750 list($thePalIcon,) = $this->wrapOpenPalette(
751 t3lib_iconWorks::getSpriteIcon(
752 'actions-system-options-view',
753 array('title' => htmlspecialchars($this->getLL('l_moreOptions')))
754 ), $table, $row, $palette, 1);
755 $thePalIcon = '<span style="margin-left: 20px;">' . $thePalIcon . $collapsedHeader . '</span>';
756 }
757
758 $paletteHtml = $this->wrapPaletteField($this->printPalette($parts), $table, $row, $palette, $collapsed);
759
760 $out .= $this->intoTemplate(
761 array('PALETTE' => $thePalIcon . $paletteHtml),
762 $this->palFieldTemplate
763 );
764 }
765 }
766 return $out;
767 }
768
769 /**
770 * Returns the form HTML code for a database table field.
771 *
772 * @param string The table name
773 * @param string The field name
774 * @param array The record to edit from the database table.
775 * @param string Alternative field name label to show.
776 * @param boolean Set this if the field is on a palette (in top frame), otherwise not. (if set, field will render as a hidden field).
777 * @param string The "extra" options from "Part 4" of the field configurations found in the "types" "showitem" list. Typically parsed by $this->getSpecConfFromString() in order to get the options as an associative array.
778 * @param integer The palette pointer.
779 * @return mixed String (normal) or array (palettes)
780 */
781 function getSingleField($table, $field, $row, $altName = '', $palette = 0, $extra = '', $pal = 0) {
782
783 // Hook: getSingleField_preProcess
784 foreach ($this->hookObjectsSingleField as $hookObj) {
785 if (method_exists($hookObj, 'getSingleField_preProcess')) {
786 $hookObj->getSingleField_preProcess($table, $field, $row, $altName, $palette, $extra, $pal, $this);
787 }
788 }
789
790 $out = '';
791 $PA = array();
792 $PA['altName'] = $altName;
793 $PA['palette'] = $palette;
794 $PA['extra'] = $extra;
795 $PA['pal'] = $pal;
796
797 // Make sure to load full $GLOBALS['TCA'] array for the table:
798 t3lib_div::loadTCA($table);
799
800 // Get the TCA configuration for the current field:
801 $PA['fieldConf'] = $GLOBALS['TCA'][$table]['columns'][$field];
802 $PA['fieldConf']['config']['form_type'] = $PA['fieldConf']['config']['form_type'] ? $PA['fieldConf']['config']['form_type'] : $PA['fieldConf']['config']['type']; // Using "form_type" locally in this script
803
804 $skipThisField = $this->inline->skipField($table, $field, $row, $PA['fieldConf']['config']);
805
806 // Now, check if this field is configured and editable (according to excludefields + other configuration)
807 if (is_array($PA['fieldConf']) &&
808 !$skipThisField &&
809 (!$PA['fieldConf']['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields', $table . ':' . $field)) &&
810 $PA['fieldConf']['config']['form_type'] != 'passthrough' &&
811 ($this->RTEenabled || !$PA['fieldConf']['config']['showIfRTE']) &&
812 (!$PA['fieldConf']['displayCond'] || $this->isDisplayCondition($PA['fieldConf']['displayCond'], $row)) &&
813 (!$GLOBALS['TCA'][$table]['ctrl']['languageField'] || $PA['fieldConf']['l10n_display'] || strcmp($PA['fieldConf']['l10n_mode'], 'exclude') || $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] <= 0) &&
814 (!$GLOBALS['TCA'][$table]['ctrl']['languageField'] || !$this->localizationMode || $this->localizationMode === $PA['fieldConf']['l10n_cat'])
815 ) {
816
817
818 // Fetching the TSconfig for the current table/field. This includes the $row which means that
819 $PA['fieldTSConfig'] = $this->setTSconfig($table, $row, $field);
820
821 // If the field is NOT disabled from TSconfig (which it could have been) then render it
822 if (!$PA['fieldTSConfig']['disabled']) {
823 // Override fieldConf by fieldTSconfig:
824 $PA['fieldConf']['config'] = $this->overrideFieldConf($PA['fieldConf']['config'], $PA['fieldTSConfig']);
825
826 // Init variables:
827 $PA['itemFormElName'] = $this->prependFormFieldNames . '[' . $table . '][' . $row['uid'] . '][' . $field . ']'; // Form field name
828 $PA['itemFormElName_file'] = $this->prependFormFieldNames_file . '[' . $table . '][' . $row['uid'] . '][' . $field . ']'; // Form field name, in case of file uploads
829 $PA['itemFormElValue'] = $row[$field]; // The value to show in the form field.
830 $PA['itemFormElID'] = $this->prependFormFieldNames . '_' . $table . '_' . $row['uid'] . '_' . $field;
831
832 // set field to read-only if configured for translated records to show default language content as readonly
833 if ($PA['fieldConf']['l10n_display']
834 && t3lib_div::inList($PA['fieldConf']['l10n_display'], 'defaultAsReadonly')
835 && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] > 0) {
836 $PA['fieldConf']['config']['readOnly'] = TRUE;
837 $PA['itemFormElValue'] = $this->defaultLanguageData[$table . ':' . $row['uid']][$field];
838 }
839
840 // Create a JavaScript code line which will ask the user to save/update the form due to changing the element. This is used for eg. "type" fields and others configured with "requestUpdate"
841 if (
842 ($GLOBALS['TCA'][$table]['ctrl']['type'] && !strcmp($field, $GLOBALS['TCA'][$table]['ctrl']['type']))
843 || ($GLOBALS['TCA'][$table]['ctrl']['requestUpdate']
844 && t3lib_div::inList($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'], $field))) {
845 if ($GLOBALS['BE_USER']->jsConfirmation(1)) {
846 $alertMsgOnChange = 'if (confirm(TBE_EDITOR.labels.onChangeAlert) && TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };';
847 } else {
848 $alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };';
849 }
850 } else {
851 $alertMsgOnChange = '';
852 }
853
854 // Render as a hidden field?
855 if (in_array($field, $this->hiddenFieldListArr)) {
856 $this->hiddenFieldAccum[] = '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
857 } else { // Render as a normal field:
858
859 // If the field is NOT a palette field, then we might create an icon which links to a palette for the field, if one exists.
860 if (!$PA['palette']) {
861 $paletteFields = $this->loadPaletteElements($table, $row, $PA['pal']);
862 if ($PA['pal'] && $this->isPalettesCollapsed($table, $PA['pal']) && count($paletteFields)) {
863 list($thePalIcon, $palJSfunc) = $this->wrapOpenPalette(t3lib_iconWorks::getSpriteIcon('actions-system-options-view', array('title' => htmlspecialchars($this->getLL('l_moreOptions')))), $table, $row, $PA['pal'], 1);
864 } else {
865 $thePalIcon = '';
866 $palJSfunc = '';
867 }
868 }
869 // onFocus attribute to add to the field:
870 $PA['onFocus'] = (($palJSfunc && !$GLOBALS['BE_USER']->uc['dontShowPalettesOnFocusInAB'])
871 ? ' onfocus="' . htmlspecialchars($palJSfunc) . '"'
872 : '');
873
874 // Find item
875 $item = '';
876 $PA['label'] = ($PA['altName'] ? $PA['altName'] : $PA['fieldConf']['label']);
877 $PA['label'] = ($PA['fieldTSConfig']['label'] ? $PA['fieldTSConfig']['label'] : $PA['label']);
878 $PA['label'] = ($PA['fieldTSConfig']['label.'][$GLOBALS['LANG']->lang] ? $PA['fieldTSConfig']['label.'][$GLOBALS['LANG']->lang] : $PA['label']);
879 $PA['label'] = $this->sL($PA['label']);
880 // JavaScript code for event handlers:
881 $PA['fieldChangeFunc'] = array();
882 $PA['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = "TBE_EDITOR.fieldChanged('" . $table . "','" . $row['uid'] . "','" . $field . "','" . $PA['itemFormElName'] . "');";
883 $PA['fieldChangeFunc']['alert'] = $alertMsgOnChange;
884 // if this is the child of an inline type and it is the field creating the label
885 if ($this->inline->isInlineChildAndLabelField($table, $field)) {
886 $inlineObjectId = implode(
887 t3lib_TCEforms_inline::Structure_Separator,
888 array(
889 $this->inline->inlineNames['object'],
890 $table,
891 $row['uid']
892 )
893 );
894 $PA['fieldChangeFunc']['inline'] = "inline.handleChangedField('" . $PA['itemFormElName'] . "','" . $inlineObjectId . "');";
895 }
896
897 // Based on the type of the item, call a render function:
898 $item = $this->getSingleField_SW($table, $field, $row, $PA);
899
900 // Add language + diff
901 if ($PA['fieldConf']['l10n_display'] && (t3lib_div::inList($PA['fieldConf']['l10n_display'], 'hideDiff') || t3lib_div::inList($PA['fieldConf']['l10n_display'], 'defaultAsReadonly'))) {
902 $renderLanguageDiff = FALSE;
903 } else {
904 $renderLanguageDiff = TRUE;
905 }
906
907 if ($renderLanguageDiff) {
908 $item = $this->renderDefaultLanguageContent($table, $field, $row, $item);
909 $item = $this->renderDefaultLanguageDiff($table, $field, $row, $item);
910 }
911
912 // If the record has been saved and the "linkTitleToSelf" is set, we make the field name into a link, which will load ONLY this field in alt_doc.php
913 $label = t3lib_div::deHSCentities(htmlspecialchars($PA['label']));
914 if (t3lib_div::testInt($row['uid']) && $PA['fieldTSConfig']['linkTitleToSelf'] && !t3lib_div::_GP('columnsOnly')) {
915 $lTTS_url = $this->backPath . 'alt_doc.php?edit[' . $table . '][' . $row['uid'] . ']=edit&columnsOnly=' . $field . '&returnUrl=' . rawurlencode($this->thisReturnUrl());
916 $label = '<a href="' . htmlspecialchars($lTTS_url) . '">' . $label . '</a>';
917 }
918
919 // wrap the label with help text
920 $PA['label'] = $label = t3lib_BEfunc::wrapInHelp($table, $field, $label);
921
922 // Create output value:
923 if ($PA['fieldConf']['config']['form_type'] == 'user' && $PA['fieldConf']['config']['noTableWrapping']) {
924 $out = $item;
925 } elseif ($PA['palette']) {
926 // Array:
927 $out = array(
928 'NAME' => $label,
929 'ID' => $row['uid'],
930 'FIELD' => $field,
931 'TABLE' => $table,
932 'ITEM' => $item
933 );
934 $out = $this->addUserTemplateMarkers($out, $table, $field, $row, $PA);
935 } else {
936 // String:
937 $out = array(
938 'NAME' => $label,
939 'ITEM' => $item,
940 'TABLE' => $table,
941 'ID' => $row['uid'],
942 'PAL_LINK_ICON' => $thePalIcon,
943 'FIELD' => $field
944 );
945 $out = $this->addUserTemplateMarkers($out, $table, $field, $row, $PA);
946 // String:
947 $out = $this->intoTemplate($out);
948 }
949 }
950 } else {
951 $this->commentMessages[] = $this->prependFormFieldNames . '[' . $table . '][' . $row['uid'] . '][' . $field . ']: Disabled by TSconfig';
952 }
953 }
954 // Hook: getSingleField_postProcess
955 foreach ($this->hookObjectsSingleField as $hookObj) {
956 if (method_exists($hookObj, 'getSingleField_postProcess')) {
957 $hookObj->getSingleField_postProcess($table, $field, $row, $out, $PA, $this);
958 }
959 }
960 // Return value (string or array)
961 return $out;
962 }
963
964 /**
965 * Rendering a single item for the form
966 *
967 * @param string Table name of record
968 * @param string Fieldname to render
969 * @param array The record
970 * @param array parameters array containing a lot of stuff. Value by Reference!
971 * @return string Returns the item as HTML code to insert
972 * @access private
973 * @see getSingleField(), getSingleField_typeFlex_draw()
974 */
975 function getSingleField_SW($table, $field, $row, &$PA) {
976 $PA['fieldConf']['config']['form_type'] = $PA['fieldConf']['config']['form_type'] ? $PA['fieldConf']['config']['form_type'] : $PA['fieldConf']['config']['type']; // Using "form_type" locally in this script
977
978 // Hook: getSingleField_beforeRender
979 foreach ($this->hookObjectsSingleField as $hookObject) {
980 if (method_exists($hookObject, 'getSingleField_beforeRender')) {
981 $hookObject->getSingleField_beforeRender($table, $field, $row, $PA);
982 }
983 }
984
985 switch ($PA['fieldConf']['config']['form_type']) {
986 case 'input':
987 $item = $this->getSingleField_typeInput($table, $field, $row, $PA);
988 break;
989 case 'text':
990 $item = $this->getSingleField_typeText($table, $field, $row, $PA);
991 break;
992 case 'check':
993 $item = $this->getSingleField_typeCheck($table, $field, $row, $PA);
994 break;
995 case 'radio':
996 $item = $this->getSingleField_typeRadio($table, $field, $row, $PA);
997 break;
998 case 'select':
999 $item = $this->getSingleField_typeSelect($table, $field, $row, $PA);
1000 break;
1001 case 'group':
1002 $item = $this->getSingleField_typeGroup($table, $field, $row, $PA);
1003 break;
1004 case 'inline':
1005 $item = $this->inline->getSingleField_typeInline($table, $field, $row, $PA);
1006 break;
1007 case 'none':
1008 $item = $this->getSingleField_typeNone($table, $field, $row, $PA);
1009 break;
1010 case 'user':
1011 $item = $this->getSingleField_typeUser($table, $field, $row, $PA);
1012 break;
1013 case 'flex':
1014 $item = $this->getSingleField_typeFlex($table, $field, $row, $PA);
1015 break;
1016 default:
1017 $item = $this->getSingleField_typeUnknown($table, $field, $row, $PA);
1018 break;
1019 }
1020
1021 return $item;
1022 }
1023
1024
1025 /**********************************************************
1026 *
1027 * Rendering of each TCEform field type
1028 *
1029 ************************************************************/
1030
1031 /**
1032 * Generation of TCEform elements of the type "input"
1033 * This will render a single-line input form field, possibly with various control/validation features
1034 *
1035 * @param string The table name of the record
1036 * @param string The field name which this element is supposed to edit
1037 * @param array The record data array where the value(s) for the field can be found
1038 * @param array An array with additional configuration options.
1039 * @return string The HTML code for the TCEform field
1040 */
1041 function getSingleField_typeInput($table, $field, $row, &$PA) {
1042 $config = $PA['fieldConf']['config'];
1043
1044 $specConf = $this->getSpecConfFromString($PA['extra'], $PA['fieldConf']['defaultExtras']);
1045 $size = t3lib_div::intInRange($config['size'] ? $config['size'] : 30, 5, $this->maxInputWidth);
1046 $evalList = t3lib_div::trimExplode(',', $config['eval'], 1);
1047 $classAndStyleAttributes = $this->formWidthAsArray($size);
1048
1049 $fieldAppendix = '';
1050 $item = '';
1051 $cssClasses = array($classAndStyleAttributes['class']);
1052 $cssStyle = $classAndStyleAttributes['style'];
1053
1054 if (!isset($config['checkbox'])) {
1055 $config['checkbox'] = '0';
1056 $checkboxIsset = FALSE;
1057 } else {
1058 $checkboxIsset = TRUE;
1059 }
1060
1061 if (in_array('date', $evalList) || in_array('datetime', $evalList)) {
1062 if (in_array('datetime', $evalList)) {
1063 $class = 'datetime';
1064 } else {
1065 $class = 'date';
1066 }
1067 $dateRange = '';
1068 if (isset($config['range']['lower'])) {
1069 $dateRange .= ' lower-' . intval($config['range']['lower']);
1070 }
1071 if (isset($config['range']['upper'])) {
1072 $dateRange .= ' upper-' . intval($config['range']['upper']);
1073 }
1074 $inputId = uniqid('tceforms-' . $class . 'field-');
1075 $cssClasses[] = 'tceforms-textfield tceforms-' . $class . 'field' . $dateRange;
1076 $fieldAppendix = t3lib_iconWorks::getSpriteIcon(
1077 'actions-edit-pick-date',
1078 array(
1079 'style' => 'cursor:pointer;',
1080 'id' => 'picker-' . $inputId
1081 )
1082 );
1083 } elseif (in_array('timesec', $evalList)) {
1084 $inputId = uniqid('tceforms-timesecfield-');
1085 $cssClasses[] = 'tceforms-textfield tceforms-timesecfield';
1086 } elseif (in_array('year', $evalList)) {
1087 $inputId = uniqid('tceforms-yearfield-');
1088 $cssClasses[] = 'tceforms-textfield tceforms-yearfield';
1089 } elseif (in_array('time', $evalList)) {
1090 $inputId = uniqid('tceforms-timefield-');
1091 $cssClasses[] = 'tceforms-textfield tceforms-timefield';
1092 } elseif (in_array('int', $evalList)) {
1093 $inputId = uniqid('tceforms-intfield-');
1094 $cssClasses[] = 'tceforms-textfield tceforms-intfield';
1095 } elseif (in_array('double2', $evalList)) {
1096 $inputId = uniqid('tceforms-double2field-');
1097 $cssClasses[] = 'tceforms-textfield tceforms-double2field';
1098 } else {
1099 $inputId = uniqid('tceforms-textfield-');
1100 $cssClasses[] = 'tceforms-textfield';
1101 if ($checkboxIsset === FALSE) {
1102 $config['checkbox'] = '';
1103 }
1104 }
1105 if (isset($config['wizards']['link'])) {
1106 $inputId = uniqid('tceforms-linkfield-');
1107 $cssClasses[] = 'tceforms-textfield tceforms-linkfield';
1108
1109 } elseif (isset($config['wizards']['color'])) {
1110 $inputId = uniqid('tceforms-colorfield-');
1111 $cssClasses[] = 'tceforms-textfield tceforms-colorfield';
1112 }
1113
1114 if ($this->renderReadonly || $config['readOnly']) {
1115 $itemFormElValue = $PA['itemFormElValue'];
1116 if (in_array('date', $evalList)) {
1117 $config['format'] = 'date';
1118 } elseif (in_array('datetime', $evalList)) {
1119 $config['format'] = 'datetime';
1120 } elseif (in_array('time', $evalList)) {
1121 $config['format'] = 'time';
1122 }
1123 if (in_array('password', $evalList)) {
1124 $itemFormElValue = $itemFormElValue ? '*********' : '';
1125 }
1126 return $this->getSingleField_typeNone_render($config, $itemFormElValue);
1127 }
1128
1129 foreach ($evalList as $func) {
1130 switch ($func) {
1131 case 'required':
1132 $this->registerRequiredProperty('field', $table . '_' . $row['uid'] . '_' . $field, $PA['itemFormElName']);
1133 // Mark this field for date/time disposal:
1134 if (array_intersect($evalList, array('date', 'datetime', 'time'))) {
1135 $this->requiredAdditional[$PA['itemFormElName']]['isPositiveNumber'] = TRUE;
1136 }
1137 break;
1138 default:
1139 if (t3lib_div::hasValidClassPrefix($func)) {
1140 // Pair hook to the one in t3lib_TCEmain::checkValue_input_Eval()
1141 $evalObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func] . ':&' . $func);
1142 if (is_object($evalObj) && method_exists($evalObj, 'deevaluateFieldValue')) {
1143 $_params = array(
1144 'value' => $PA['itemFormElValue']
1145 );
1146 $PA['itemFormElValue'] = $evalObj->deevaluateFieldValue($_params);
1147 }
1148 }
1149 break;
1150 }
1151 }
1152
1153 $paramsList = "'" . $PA['itemFormElName'] . "','" . implode(',', $evalList) . "','" . trim($config['is_in']) . "'," . (isset($config['checkbox']) ? 1 : 0) . ",'" . $config['checkbox'] . "'";
1154 if ((in_array('date', $evalList) || in_array('datetime', $evalList))) {
1155 $item .= '<span class="t3-tceforms-input-wrapper-datetime" onmouseOver="if (document.getElementById(\'' .
1156 $inputId . '\').value) {this.className=\'t3-tceforms-input-wrapper-datetime-hover\';} else {this.className=\'t3-tceforms-input-wrapper-datetime\';};" onmouseOut="this.className=\'t3-tceforms-input-wrapper-datetime\';">';
1157
1158 // Add server timezone offset to UTC to our stored date
1159 if ($PA['itemFormElValue'] > 0) {
1160 $PA['itemFormElValue'] += date('Z', $PA['itemFormElValue']);
1161 }
1162 } else {
1163 $item .= '<span class="t3-tceforms-input-wrapper" onmouseOver="if (document.getElementById(\'' . $inputId .
1164 '\').value) {this.className=\'t3-tceforms-input-wrapper-hover\';} else {this.className=\'t3-tceforms-input-wrapper\';};" onmouseOut="this.className=\'t3-tceforms-input-wrapper\';">';
1165 }
1166
1167 $PA['fieldChangeFunc'] = array_merge(
1168 array('typo3form.fieldGet' => 'typo3form.fieldGet(' . $paramsList . ');'),
1169 $PA['fieldChangeFunc']
1170 );
1171 // old function "checkbox" now the option to set the date / remove the date
1172 if (isset($config['checkbox'])) {
1173 $item .= t3lib_iconWorks::getSpriteIcon('actions-input-clear', array('tag' => 'a', 'class' => 't3-tceforms-input-clearer', 'onclick' => 'document.getElementById(\'' . $inputId . '\').value=\'\';document.getElementById(\'' . $inputId . '\').focus();' . implode('', $PA['fieldChangeFunc'])));
1174 }
1175 $mLgd = ($config['max'] ? $config['max'] : 256);
1176 $iOnChange = implode('', $PA['fieldChangeFunc']);
1177
1178 $item .= '<input type="text" id="' . $inputId .
1179 '" class="' . implode(' ', $cssClasses) . '" name="' . $PA['itemFormElName'] .
1180 '_hr" value="" style="' . $cssStyle . '" maxlength="' . $mLgd . '" onchange="' .
1181 htmlspecialchars($iOnChange) . '"' . $PA['onFocus'] . ' />'; // This is the EDITABLE form field.
1182 $item .= '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' .
1183 htmlspecialchars($PA['itemFormElValue']) . '" />'; // This is the ACTUAL form field - values from the EDITABLE field must be transferred to this field which is the one that is written to the database.
1184 $item .= $fieldAppendix . '</span><div style="clear:both;"></div>';
1185 $this->extJSCODE .= 'typo3form.fieldSet(' . $paramsList . ');';
1186
1187 // going through all custom evaluations configured for this field
1188 foreach ($evalList as $evalData) {
1189 if (t3lib_div::hasValidClassPrefix($evalData)) {
1190 $evalObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$evalData] . ':&' . $evalData);
1191 if (is_object($evalObj) && method_exists($evalObj, 'returnFieldJS')) {
1192 $this->extJSCODE .= "\n\nfunction " . $evalData . "(value) {\n" . $evalObj->returnFieldJS() . "\n}\n";
1193 }
1194 }
1195 }
1196
1197 // Creating an alternative item without the JavaScript handlers.
1198 $altItem = '<input type="hidden" name="' . $PA['itemFormElName'] . '_hr" value="" />';
1199 $altItem .= '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
1200
1201 // Wrap a wizard around the item?
1202 $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'] . '_hr', $specConf);
1203
1204 return $item;
1205 }
1206
1207 /**
1208 * Generation of TCEform elements of the type "text"
1209 * This will render a <textarea> OR RTE area form field, possibly with various control/validation features
1210 *
1211 * @param string The table name of the record
1212 * @param string The field name which this element is supposed to edit
1213 * @param array The record data array where the value(s) for the field can be found
1214 * @param array An array with additional configuration options.
1215 * @return string The HTML code for the TCEform field
1216 */
1217 function getSingleField_typeText($table, $field, $row, &$PA) {
1218
1219 // Init config:
1220 $config = $PA['fieldConf']['config'];
1221 $evalList = t3lib_div::trimExplode(',', $config['eval'], 1);
1222
1223 if ($this->renderReadonly || $config['readOnly']) {
1224 return $this->getSingleField_typeNone_render($config, $PA['itemFormElValue']);
1225 }
1226
1227 // Setting columns number:
1228 $cols = t3lib_div::intInRange($config['cols'] ? $config['cols'] : 30, 5, $this->maxTextareaWidth);
1229
1230 // Setting number of rows:
1231 $origRows = $rows = t3lib_div::intInRange($config['rows'] ? $config['rows'] : 5, 1, 20);
1232 if (strlen($PA['itemFormElValue']) > $this->charsPerRow * 2) {
1233 $cols = $this->maxTextareaWidth;
1234 $rows = t3lib_div::intInRange(round(strlen($PA['itemFormElValue']) / $this->charsPerRow), count(explode(LF, $PA['itemFormElValue'])), 20);
1235 if ($rows < $origRows) {
1236 $rows = $origRows;
1237 }
1238 }
1239
1240 if (in_array('required', $evalList)) {
1241 $this->requiredFields[$table . '_' . $row['uid'] . '_' . $field] = $PA['itemFormElName'];
1242 }
1243
1244 // Init RTE vars:
1245 $RTEwasLoaded = 0; // Set TRUE, if the RTE is loaded; If not a normal textarea is shown.
1246 $RTEwouldHaveBeenLoaded = 0; // Set TRUE, if the RTE would have been loaded if it wasn't for the disable-RTE flag in the bottom of the page...
1247
1248 // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. Traditionally, this is where RTE configuration has been found.
1249 $specConf = $this->getSpecConfFromString($PA['extra'], $PA['fieldConf']['defaultExtras']);
1250
1251 // Setting up the altItem form field, which is a hidden field containing the value
1252 $altItem = '<input type="hidden" name="' . htmlspecialchars($PA['itemFormElName']) . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
1253
1254 // If RTE is generally enabled (TYPO3_CONF_VARS and user settings)
1255 if ($this->RTEenabled) {
1256 $p = t3lib_BEfunc::getSpecConfParametersFromArray($specConf['rte_transform']['parameters']);
1257 if (isset($specConf['richtext']) && (!$p['flag'] || !$row[$p['flag']])) { // If the field is configured for RTE and if any flag-field is not set to disable it.
1258 t3lib_BEfunc::fixVersioningPid($table, $row);
1259 list($tscPID, $thePidValue) = $this->getTSCpid($table, $row['uid'], $row['pid']);
1260
1261 // If the pid-value is not negative (that is, a pid could NOT be fetched)
1262 if ($thePidValue >= 0) {
1263 $RTEsetup = $GLOBALS['BE_USER']->getTSConfig('RTE', t3lib_BEfunc::getPagesTSconfig($tscPID));
1264 $RTEtypeVal = t3lib_BEfunc::getTCAtypeValue($table, $row);
1265 $thisConfig = t3lib_BEfunc::RTEsetup($RTEsetup['properties'], $table, $field, $RTEtypeVal);
1266
1267 if (!$thisConfig['disabled']) {
1268 if (!$this->disableRTE) {
1269 $this->RTEcounter++;
1270
1271 // Find alternative relative path for RTE images/links:
1272 $eFile = t3lib_parsehtml_proc::evalWriteFile($specConf['static_write'], $row);
1273 $RTErelPath = is_array($eFile) ? dirname($eFile['relEditFile']) : '';
1274
1275 // Get RTE object, draw form and set flag:
1276 $RTEobj = t3lib_BEfunc::RTEgetObj();
1277 $item = $RTEobj->drawRTE($this, $table, $field, $row, $PA, $specConf, $thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue);
1278
1279 // Wizard:
1280 $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'], $specConf, 1);
1281
1282 $RTEwasLoaded = 1;
1283 } else {
1284 $RTEwouldHaveBeenLoaded = 1;
1285 $this->commentMessages[] = $PA['itemFormElName'] . ': RTE is disabled by the on-page RTE-flag (probably you can enable it by the check-box in the bottom of this page!)';
1286 }
1287 } else {
1288 $this->commentMessages[] = $PA['itemFormElName'] . ': RTE is disabled by the Page TSconfig, "RTE"-key (eg. by RTE.default.disabled=0 or such)';
1289 }
1290 } else {
1291 $this->commentMessages[] = $PA['itemFormElName'] . ': PID value could NOT be fetched. Rare error, normally with new records.';
1292 }
1293 } else {
1294 if (!isset($specConf['richtext'])) {
1295 $this->commentMessages[] = $PA['itemFormElName'] . ': RTE was not configured for this field in TCA-types';
1296 }
1297 if (!(!$p['flag'] || !$row[$p['flag']])) {
1298 $this->commentMessages[] = $PA['itemFormElName'] . ': Field-flag (' . $PA['flag'] . ') has been set to disable RTE!';
1299 }
1300 }
1301 }
1302
1303 // Display ordinary field if RTE was not loaded.
1304 if (!$RTEwasLoaded) {
1305 if ($specConf['rte_only']) { // Show message, if no RTE (field can only be edited with RTE!)
1306 $item = '<p><em>' . htmlspecialchars($this->getLL('l_noRTEfound')) . '</em></p>';
1307 } else {
1308 if ($specConf['nowrap']) {
1309 $wrap = 'off';
1310 } else {
1311 $wrap = ($config['wrap'] ? $config['wrap'] : 'virtual');
1312 }
1313
1314 $classes = array();
1315 if ($specConf['fixed-font']) {
1316 $classes[] = 'fixed-font';
1317 }
1318 if ($specConf['enable-tab']) {
1319 $classes[] = 'enable-tab';
1320 }
1321
1322 $formWidthText = $this->formWidthText($cols, $wrap);
1323
1324 // Extract class attributes from $formWidthText (otherwise it would be added twice to the output)
1325 $res = array();
1326 if (preg_match('/ class="(.+?)"/', $formWidthText, $res)) {
1327 $formWidthText = str_replace(' class="' . $res[1] . '"', '', $formWidthText);
1328 $classes = array_merge($classes, explode(' ', $res[1]));
1329 }
1330
1331 if (count($classes)) {
1332 $class = ' class="tceforms-textarea ' . implode(' ', $classes) . '"';
1333 } else {
1334 $class = 'tceforms-textarea';
1335 }
1336
1337 $evalList = t3lib_div::trimExplode(',', $config['eval'], 1);
1338 foreach ($evalList as $func) {
1339 switch ($func) {
1340 case 'required':
1341 $this->registerRequiredProperty('field', $table . '_' . $row['uid'] . '_' . $field, $PA['itemFormElName']);
1342 break;
1343 default:
1344 if (t3lib_div::hasValidClassPrefix($func)) {
1345 // Pair hook to the one in t3lib_TCEmain::checkValue_input_Eval() and t3lib_TCEmain::checkValue_text_Eval()
1346 $evalObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func] . ':&' . $func);
1347 if (is_object($evalObj) && method_exists($evalObj, 'deevaluateFieldValue')) {
1348 $_params = array(
1349 'value' => $PA['itemFormElValue']
1350 );
1351 $PA['itemFormElValue'] = $evalObj->deevaluateFieldValue($_params);
1352 }
1353 }
1354 break;
1355 }
1356 }
1357
1358 $iOnChange = implode('', $PA['fieldChangeFunc']);
1359 $item .= '
1360 <textarea id="' . uniqid('tceforms-textarea-') . '" name="' . $PA['itemFormElName'] . '"' . $formWidthText . $class . ' rows="' . $rows . '" wrap="' . $wrap . '" onchange="' . htmlspecialchars($iOnChange) . '"' . $PA['onFocus'] . '>' .
1361 t3lib_div::formatForTextarea($PA['itemFormElValue']) .
1362 '</textarea>';
1363 $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'], $specConf, $RTEwouldHaveBeenLoaded);
1364 }
1365 }
1366
1367 // Return field HTML:
1368 return $item;
1369 }
1370
1371 /**
1372 * Generation of TCEform elements of the type "check"
1373 * This will render a check-box OR an array of checkboxes
1374 *
1375 * @param string The table name of the record
1376 * @param string The field name which this element is supposed to edit
1377 * @param array The record data array where the value(s) for the field can be found
1378 * @param array An array with additional configuration options.
1379 * @return string The HTML code for the TCEform field
1380 */
1381 function getSingleField_typeCheck($table, $field, $row, &$PA) {
1382 $config = $PA['fieldConf']['config'];
1383
1384 $item = '';
1385 $disabled = '';
1386 if ($this->renderReadonly || $config['readOnly']) {
1387 $disabled = ' disabled="disabled"';
1388 }
1389
1390 // Traversing the array of items:
1391 $selItems = $this->initItemArray($PA['fieldConf']);
1392 if ($config['itemsProcFunc']) {
1393 $selItems = $this->procItems($selItems, $PA['fieldTSConfig']['itemsProcFunc.'], $config, $table, $row, $field);
1394 }
1395
1396 if (!count($selItems)) {
1397 $selItems[] = array('', '');
1398 }
1399 $thisValue = intval($PA['itemFormElValue']);
1400
1401 $cols = intval($config['cols']);
1402 if ($cols > 1) {
1403 $item .= '<table border="0" cellspacing="0" cellpadding="0" class="typo3-TCEforms-checkboxArray">';
1404 for ($c = 0; $c < count($selItems); $c++) {
1405 $p = $selItems[$c];
1406 if (!($c % $cols)) {
1407 $item .= '<tr>';
1408 }
1409 $cBP = $this->checkBoxParams($PA['itemFormElName'], $thisValue, $c, count($selItems), implode('', $PA['fieldChangeFunc']));
1410 $cBName = $PA['itemFormElName'] . '_' . $c;
1411 $cBID = $PA['itemFormElID'] . '_' . $c;
1412 $item .= '<td nowrap="nowrap">' .
1413 '<input type="checkbox"' . $this->insertDefStyle('check') . ' value="1" name="' . $cBName . '"' . $cBP . $disabled . ' id="' . $cBID . '" />' .
1414 $this->wrapLabels('<label for="' . $cBID . '">' . htmlspecialchars($p[0]) . '</label>&nbsp;') .
1415 '</td>';
1416 if (($c % $cols) + 1 == $cols) {
1417 $item .= '</tr>';
1418 }
1419 }
1420 if ($c % $cols) {
1421 $rest = $cols - ($c % $cols);
1422 for ($c = 0; $c < $rest; $c++) {
1423 $item .= '<td></td>';
1424 }
1425 if ($c > 0) {
1426 $item .= '</tr>';
1427 }
1428 }
1429 $item .= '</table>';
1430 } else {
1431 for ($c = 0; $c < count($selItems); $c++) {
1432 $p = $selItems[$c];
1433 $cBP = $this->checkBoxParams($PA['itemFormElName'], $thisValue, $c, count($selItems), implode('', $PA['fieldChangeFunc']));
1434 $cBName = $PA['itemFormElName'] . '_' . $c;
1435 $cBID = $PA['itemFormElID'] . '_' . $c;
1436 $item .= ($c > 0 ? '<br />' : '') .
1437 '<input type="checkbox"' . $this->insertDefStyle('check') . ' value="1" name="' . $cBName . '"' . $cBP . $PA['onFocus'] . $disabled . ' id="' . $cBID . '" />' .
1438 $this->wrapLabels('<label for="' . $cBID . '">' . htmlspecialchars($p[0]) . '</label>');
1439 }
1440 }
1441 if (!$disabled) {
1442 $item .= '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($thisValue) . '" />';
1443 }
1444
1445 return $item;
1446 }
1447
1448 /**
1449 * Generation of TCEform elements of the type "radio"
1450 * This will render a series of radio buttons.
1451 *
1452 * @param string The table name of the record
1453 * @param string The field name which this element is supposed to edit
1454 * @param array The record data array where the value(s) for the field can be found
1455 * @param array An array with additional configuration options.
1456 * @return string The HTML code for the TCEform field
1457 */
1458 function getSingleField_typeRadio($table, $field, $row, &$PA) {
1459 $config = $PA['fieldConf']['config'];
1460
1461 $item = '';
1462 $disabled = '';
1463 if ($this->renderReadonly || $config['readOnly']) {
1464 $disabled = ' disabled="disabled"';
1465 }
1466
1467 // Get items for the array:
1468 $selItems = $this->initItemArray($PA['fieldConf']);
1469 if ($config['itemsProcFunc']) {
1470 $selItems = $this->procItems($selItems, $PA['fieldTSConfig']['itemsProcFunc.'], $config, $table, $row, $field);
1471 }
1472
1473 // Traverse the items, making the form elements:
1474 for ($c = 0; $c < count($selItems); $c++) {
1475 $p = $selItems[$c];
1476 $rID = $PA['itemFormElID'] . '_' . $c;
1477 $rOnClick = implode('', $PA['fieldChangeFunc']);
1478 $rChecked = (!strcmp($p[1], $PA['itemFormElValue']) ? ' checked="checked"' : '');
1479 $item .= '<input type="radio"' . $this->insertDefStyle('radio') . ' name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($p[1]) . '" onclick="' . htmlspecialchars($rOnClick) . '"' . $rChecked . $PA['onFocus'] . $disabled . ' id="' . $rID . '" />
1480 <label for="' . $rID . '">' . htmlspecialchars($p[0]) . '</label>
1481 <br />';
1482 }
1483
1484 return $item;
1485 }
1486
1487 /**
1488 * Generation of TCEform elements of the type "select"
1489 * This will render a selector box element, or possibly a special construction with two selector boxes. That depends on configuration.
1490 *
1491 * @param string The table name of the record
1492 * @param string The field name which this element is supposed to edit
1493 * @param array The record data array where the value(s) for the field can be found
1494 * @param array An array with additional configuration options.
1495 * @return string The HTML code for the TCEform field
1496 */
1497 function getSingleField_typeSelect($table, $field, $row, &$PA) {
1498
1499 // Field configuration from TCA:
1500 $config = $PA['fieldConf']['config'];
1501
1502 $disabled = '';
1503 if ($this->renderReadonly || $config['readOnly']) {
1504 $disabled = ' disabled="disabled"';
1505 }
1506
1507 // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. See http://typo3.org/documentation/document-library/doc_core_api/Wizards_Configuratio/.
1508 $specConf = $this->getSpecConfFromString($PA['extra'], $PA['fieldConf']['defaultExtras']);
1509
1510 // Getting the selector box items from the system
1511 $selItems = $this->addSelectOptionsToItemArray(
1512 $this->initItemArray($PA['fieldConf']),
1513 $PA['fieldConf'],
1514 $this->setTSconfig($table, $row),
1515 $field
1516 );
1517 // Possibly filter some items:
1518 $keepItemsFunc = create_function('$value', 'return $value[1];');
1519 $selItems = t3lib_div::keepItemsInArray($selItems, $PA['fieldTSConfig']['keepItems'], $keepItemsFunc);
1520 // Possibly add some items:
1521 $selItems = $this->addItems($selItems, $PA['fieldTSConfig']['addItems.']);
1522 // Process items by a user function:
1523 if (isset($config['itemsProcFunc']) && $config['itemsProcFunc']) {
1524 $selItems = $this->procItems($selItems, $PA['fieldTSConfig']['itemsProcFunc.'], $config, $table, $row, $field);
1525 }
1526
1527 // Possibly remove some items:
1528 $removeItems = t3lib_div::trimExplode(',', $PA['fieldTSConfig']['removeItems'], 1);
1529 foreach ($selItems as $tk => $p) {
1530
1531 // Checking languages and authMode:
1532 $languageDeny = $GLOBALS['TCA'][$table]['ctrl']['languageField']
1533 && !strcmp($GLOBALS['TCA'][$table]['ctrl']['languageField'], $field)
1534 && !$GLOBALS['BE_USER']->checkLanguageAccess($p[1]);
1535 $authModeDeny = $config['form_type'] == 'select' && $config['authMode'] && !$GLOBALS['BE_USER']->checkAuthMode($table, $field, $p[1], $config['authMode']);
1536 if (in_array($p[1], $removeItems) || $languageDeny || $authModeDeny) {
1537 unset($selItems[$tk]);
1538 } elseif (isset($PA['fieldTSConfig']['altLabels.'][$p[1]])) {
1539 $selItems[$tk][0] = $this->sL($PA['fieldTSConfig']['altLabels.'][$p[1]]);
1540 }
1541
1542 // Removing doktypes with no access:
1543 if (($table === 'pages' || $table === 'pages_language_overlay') && $field === 'doktype') {
1544 if (!($GLOBALS['BE_USER']->isAdmin() || t3lib_div::inList($GLOBALS['BE_USER']->groupData['pagetypes_select'], $p[1]))) {
1545 unset($selItems[$tk]);
1546 }
1547 }
1548 }
1549
1550 // Creating the label for the "No Matching Value" entry.
1551 $nMV_label = isset($PA['fieldTSConfig']['noMatchingValue_label']) ? $this->sL($PA['fieldTSConfig']['noMatchingValue_label']) : '[ ' . $this->getLL('l_noMatchingValue') . ' ]';
1552
1553 // Prepare some values:
1554 $maxitems = intval($config['maxitems']);
1555
1556 // If a SINGLE selector box...
1557 if ($maxitems <= 1 && $config['renderMode'] !== 'tree') {
1558 $item = $this->getSingleField_typeSelect_single($table, $field, $row, $PA, $config, $selItems, $nMV_label);
1559 } elseif (!strcmp($config['renderMode'], 'checkbox')) { // Checkbox renderMode
1560 $item = $this->getSingleField_typeSelect_checkbox($table, $field, $row, $PA, $config, $selItems, $nMV_label);
1561 } elseif (!strcmp($config['renderMode'], 'singlebox')) { // Single selector box renderMode
1562 $item = $this->getSingleField_typeSelect_singlebox($table, $field, $row, $PA, $config, $selItems, $nMV_label);
1563 } elseif (!strcmp($config['renderMode'], 'tree')) { // Tree renderMode
1564 $treeClass = t3lib_div::makeInstance('t3lib_TCEforms_Tree', $this);
1565 $item = $treeClass->renderField($table, $field, $row, $PA, $config, $selItems, $nMV_label);
1566 } else { // Traditional multiple selector box:
1567 $item = $this->getSingleField_typeSelect_multiple($table, $field, $row, $PA, $config, $selItems, $nMV_label);
1568 }
1569
1570 // Wizards:
1571 if (!$disabled) {
1572 $altItem = '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
1573 $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'], $specConf);
1574 }
1575
1576 return $item;
1577 }
1578
1579 /**
1580 * Creates a single-selector box
1581 * (Render function for getSingleField_typeSelect())
1582 *
1583 * @param string See getSingleField_typeSelect()
1584 * @param string See getSingleField_typeSelect()
1585 * @param array See getSingleField_typeSelect()
1586 * @param array See getSingleField_typeSelect()
1587 * @param array (Redundant) content of $PA['fieldConf']['config'] (for convenience)
1588 * @param array Items available for selection
1589 * @param string Label for no-matching-value
1590 * @return string The HTML code for the item
1591 * @see getSingleField_typeSelect()
1592 */
1593 function getSingleField_typeSelect_single($table, $field, $row, &$PA, $config, $selItems, $nMV_label) {
1594 // check against inline uniqueness
1595 $inlineParent = $this->inline->getStructureLevel(-1);
1596 if (is_array($inlineParent) && $inlineParent['uid']) {
1597 if ($inlineParent['config']['foreign_table'] == $table && $inlineParent['config']['foreign_unique'] == $field) {
1598 $uniqueIds = $this->inline->inlineData['unique'][$this->inline->inlineNames['object'] . '[' . $table . ']']['used'];
1599 $PA['fieldChangeFunc']['inlineUnique'] = "inline.updateUnique(this,'" . $this->inline->inlineNames['object'] . '[' . $table . "]','" . $this->inline->inlineNames['form'] . "','" . $row['uid'] . "');";
1600 }
1601 // hide uid of parent record for symmetric relations
1602 if ($inlineParent['config']['foreign_table'] == $table && ($inlineParent['config']['foreign_field'] == $field || $inlineParent['config']['symmetric_field'] == $field)) {
1603 $uniqueIds[] = $inlineParent['uid'];
1604 }
1605 }
1606
1607 // Initialization:
1608 $c = 0;
1609 $sI = 0;
1610 $noMatchingValue = 1;
1611 $opt = array();
1612 $selicons = array();
1613 $onlySelectedIconShown = 0;
1614 $size = intval($config['size']);
1615 $selectedStyle = ''; // Style set on <select/>
1616
1617 $item = '';
1618 $disabled = '';
1619 $onChangeIcon = ''; // TODO: icon is used but never assigned
1620
1621 if ($this->renderReadonly || $config['readOnly']) {
1622 $disabled = ' disabled="disabled"';
1623 $onlySelectedIconShown = 1;
1624 }
1625
1626 // Icon configuration:
1627 if ($config['suppress_icons'] == 'IF_VALUE_FALSE') {
1628 $suppressIcons = !$PA['itemFormElValue'] ? 1 : 0;
1629 } elseif ($config['suppress_icons'] == 'ONLY_SELECTED') {
1630 $suppressIcons = 0;
1631 $onlySelectedIconShown = 1;
1632 } elseif ($config['suppress_icons']) {
1633 $suppressIcons = 1;
1634 } else {
1635 $suppressIcons = 0;
1636 }
1637
1638 // Traverse the Array of selector box items:
1639 $optGroupStart = array();
1640 $optGroupOpen = FALSE;
1641 $classesForSelectTag = array();
1642 foreach ($selItems as $p) {
1643 $sM = (!strcmp($PA['itemFormElValue'], $p[1]) ? ' selected="selected"' : '');
1644 if ($sM) {
1645 $sI = $c;
1646 $noMatchingValue = 0;
1647 }
1648
1649 // Getting style attribute value (for icons):
1650 if ($config['iconsInOptionTags']) {
1651 $styleAttrValue = $this->optionTagStyle($p[2]);
1652 if ($sM) {
1653 list($selectIconFile, $selectIconInfo) = $this->getIcon($p[2]);
1654 if (!empty($selectIconInfo)) {
1655 $selectedStyle = ' style="background-image:url(' . $selectIconFile . ');"';
1656 $classesForSelectTag[] = 'typo3-TCEforms-select-selectedItemWithBackgroundImage';
1657 }
1658 }
1659 }
1660
1661 // Compiling the <option> tag:
1662 if (!($p[1] != $PA['itemFormElValue'] && is_array($uniqueIds) && in_array($p[1], $uniqueIds))) {
1663 if (!strcmp($p[1], '--div--')) {
1664 $optGroupStart[0] = $p[0];
1665 if ($config['iconsInOptionTags']) {
1666 $optGroupStart[1] = $this->optgroupTagStyle($p[2]);
1667 } else {
1668 $optGroupStart[1] = $styleAttrValue;
1669 }
1670
1671 } else {
1672 if (count($optGroupStart)) {
1673 if ($optGroupOpen) { // Closing last optgroup before next one starts
1674 $opt[] = '</optgroup>' . LF;
1675 }
1676 $opt[] = '<optgroup label="' . t3lib_div::deHSCentities(htmlspecialchars($optGroupStart[0])) . '"' .
1677 ($optGroupStart[1] ? ' style="' . htmlspecialchars($optGroupStart[1]) . '"' : '') .
1678 ' class="c-divider">' . LF;
1679 $optGroupOpen = TRUE;
1680 $c--;
1681 $optGroupStart = array();
1682 }
1683 $opt[] = '<option value="' . htmlspecialchars($p[1]) . '"' .
1684 $sM .
1685 ($styleAttrValue ? ' style="' . htmlspecialchars($styleAttrValue) . '"' : '') .
1686 '>' . t3lib_div::deHSCentities(($p[0])) . '</option>' . LF;
1687 }
1688 }
1689
1690 // If there is an icon for the selector box (rendered in selicon-table below)...:
1691 // if there is an icon ($p[2]), icons should be shown, and, if only selected are visible, is it selected
1692 if ($p[2] && !$suppressIcons && (!$onlySelectedIconShown || $sM)) {
1693 list($selIconFile, $selIconInfo) = $this->getIcon($p[2]);
1694 if (!empty($selIconInfo)) {
1695 $iOnClick = $this->elName($PA['itemFormElName']) . '.selectedIndex=' . $c . '; ' .
1696 $this->elName($PA['itemFormElName']) . '.style.backgroundImage=' . $this->elName($PA['itemFormElName']) . '.options[' . $c . '].style.backgroundImage; ' .
1697 implode('', $PA['fieldChangeFunc']) . $this->blur() . 'return false;';
1698 } else {
1699 $iOnClick = $this->elName($PA['itemFormElName']) . '.selectedIndex=' . $c . '; ' .
1700 $this->elName($PA['itemFormElName']) . '.className=' . $this->elName($PA['itemFormElName']) . '.options[' . $c . '].className; ' .
1701 implode('', $PA['fieldChangeFunc']) . $this->blur() . 'return false;';
1702 }
1703 $selicons[] = array(
1704 (!$onlySelectedIconShown ? '<a href="#" onclick="' . htmlspecialchars($iOnClick) . '">' : '') .
1705 $this->getIconHtml($p[2], htmlspecialchars($p[0]), htmlspecialchars($p[0])) .
1706 (!$onlySelectedIconShown ? '</a>' : ''),
1707 $c, $sM);
1708 }
1709 $c++;
1710 }
1711
1712 if ($optGroupOpen) { // Closing optgroup if open
1713 $opt[] = '</optgroup>';
1714 $optGroupOpen = FALSE;
1715 }
1716
1717 // No-matching-value:
1718 if ($PA['itemFormElValue'] && $noMatchingValue && !$PA['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
1719 $nMV_label = @sprintf($nMV_label, $PA['itemFormElValue']);
1720 $opt[] = '<option value="' . htmlspecialchars($PA['itemFormElValue']) . '" selected="selected">' . htmlspecialchars($nMV_label) . '</option>';
1721 }
1722
1723 // Create item form fields:
1724 $sOnChange = 'if (this.options[this.selectedIndex].value==\'--div--\') {this.selectedIndex=' . $sI . ';} ' . implode('', $PA['fieldChangeFunc']);
1725 if (!$disabled) {
1726 $item .= '<input type="hidden" name="' . $PA['itemFormElName'] . '_selIconVal" value="' . htmlspecialchars($sI) . '" />'; // MUST be inserted before the selector - else is the value of the hiddenfield here mysteriously submitted...
1727 }
1728 if ($config['iconsInOptionTags']) {
1729 $classesForSelectTag[] = 'icon-select';
1730 }
1731 $item .= '<select' . $selectedStyle . ' id="' . uniqid('tceforms-select-') . '" name="' . $PA['itemFormElName'] . '"' .
1732 $this->insertDefStyle('select', implode(' ', $classesForSelectTag)) .
1733 ($size ? ' size="' . $size . '"' : '') .
1734 ' onchange="' . htmlspecialchars($onChangeIcon . $sOnChange) . '"' .
1735 $PA['onFocus'] . $disabled . '>';
1736 $item .= implode('', $opt);
1737 $item .= '</select>';
1738
1739 // Create icon table:
1740 if (count($selicons) && !$config['noIconsBelowSelect']) {
1741 $item .= '<table border="0" cellpadding="0" cellspacing="0" class="typo3-TCEforms-selectIcons">';
1742 $selicon_cols = intval($config['selicon_cols']);
1743 if (!$selicon_cols) {
1744 $selicon_cols = count($selicons);
1745 }
1746 $sR = ceil(count($selicons) / $selicon_cols);
1747 $selicons = array_pad($selicons, $sR * $selicon_cols, '');
1748 for ($sa = 0; $sa < $sR; $sa++) {
1749 $item .= '<tr>';
1750 for ($sb = 0; $sb < $selicon_cols; $sb++) {
1751 $sk = ($sa * $selicon_cols + $sb);
1752 $imgN = 'selIcon_' . $table . '_' . $row['uid'] . '_' . $field . '_' . $selicons[$sk][1];
1753 $imgS = ($selicons[$sk][2] ? $this->backPath . 'gfx/content_selected.gif' : 'clear.gif');
1754 $item .= '<td><img name="' . htmlspecialchars($imgN) . '" src="' . $imgS . '" width="7" height="10" alt="" /></td>';
1755 $item .= '<td>' . $selicons[$sk][0] . '</td>';
1756 }
1757 $item .= '</tr>';
1758 }
1759 $item .= '</table>';
1760 }
1761
1762 return $item;
1763 }
1764
1765 /**
1766 * Creates a checkbox list (renderMode = "checkbox")
1767 * (Render function for getSingleField_typeSelect())
1768 *
1769 * @param string See getSingleField_typeSelect()
1770 * @param string See getSingleField_typeSelect()
1771 * @param array See getSingleField_typeSelect()
1772 * @param array See getSingleField_typeSelect()
1773 * @param array (Redundant) content of $PA['fieldConf']['config'] (for convenience)
1774 * @param array Items available for selection
1775 * @param string Label for no-matching-value
1776 * @return string The HTML code for the item
1777 * @see getSingleField_typeSelect()
1778 */
1779 function getSingleField_typeSelect_checkbox($table, $field, $row, &$PA, $config, $selItems, $nMV_label) {
1780
1781 if (empty($selItems)) {
1782 return '';
1783 }
1784
1785 // Get values in an array (and make unique, which is fine because there can be no duplicates anyway):
1786 $itemArray = array_flip($this->extractValuesOnlyFromValueLabelList($PA['itemFormElValue']));
1787
1788 $item = '';
1789 $disabled = '';
1790 if ($this->renderReadonly || $config['readOnly']) {
1791 $disabled = ' disabled="disabled"';
1792 }
1793
1794 // Traverse the Array of selector box items:
1795 $tRows = array();
1796 $c = 0;
1797 if (!$disabled) {
1798 $sOnChange = implode('', $PA['fieldChangeFunc']);
1799 $setAll = array(); // Used to accumulate the JS needed to restore the original selection.
1800 $unSetAll = array();
1801 foreach ($selItems as $p) {
1802 // Non-selectable element:
1803 if (!strcmp($p[1], '--div--')) {
1804 $tRows[] = '
1805 <tr class="c-header">
1806 <td colspan="3">' . htmlspecialchars($p[0]) . '</td>
1807 </tr>';
1808 } else {
1809 // Selected or not by default:
1810 $sM = '';
1811 if (isset($itemArray[$p[1]])) {
1812 $sM = ' checked="checked"';
1813 unset($itemArray[$p[1]]);
1814 }
1815
1816 // Icon:
1817 if ($p[2]) {
1818 $selIcon = $p[2];
1819 } else {
1820 $selIcon = t3lib_iconWorks::getSpriteIcon('empty-empty');
1821 }
1822
1823 // Compile row:
1824 $rowId = uniqid('select_checkbox_row_');
1825 $onClickCell = $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked=!' . $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked;';
1826 $onClick = 'this.attributes.getNamedItem("class").nodeValue = ' . $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked ? "c-selectedItem" : "c-unselectedItem";';
1827 $setAll[] = $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked=1;';
1828 $setAll[] .= '$(\'' . $rowId . '\').removeClassName(\'c-unselectedItem\');$(\'' . $rowId . '\').addClassName(\'c-selectedItem\');';
1829 $unSetAll[] = $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked=0;';
1830 $unSetAll[] .= '$(\'' . $rowId . '\').removeClassName(\'c-selectedItem\');$(\'' . $rowId . '\').addClassName(\'c-unselectedItem\');';
1831 $restoreCmd[] = $this->elName($PA['itemFormElName'] . '[' . $c . ']') . '.checked=' . ($sM ? 1 : 0) . ';' .
1832 '$(\'' . $rowId . '\').removeClassName(\'c-selectedItem\');$(\'' . $rowId . '\').removeClassName(\'c-unselectedItem\');' .
1833 '$(\'' . $rowId . '\').addClassName(\'c-' . ($sM ? '' : 'un') . 'selectedItem\');';
1834
1835 // Check if some help text is available
1836 // Since TYPO3 4.5 help text is expected to be an associative array
1837 // with two key, "title" and "description"
1838 // For the sake of backwards compatibility, we test if the help text
1839 // is a string and use it as a description (this could happen if items
1840 // are modified with an itemProcFunc)
1841 $hasHelp = FALSE;
1842 $help = '';
1843 $helpArray = array();
1844 if ((is_array($p[3]) && count($p[3]) > 0) || !empty($p[3])) {
1845 $hasHelp = TRUE;
1846 if (is_array($p[3])) {
1847 $helpArray = $p[3];
1848 } else {
1849 $helpArray['description'] = $p[3];
1850 }
1851 }
1852
1853 $label = t3lib_div::deHSCentities(htmlspecialchars($p[0]));
1854 if ($hasHelp) {
1855 $help = t3lib_BEfunc::wrapInHelp('', '', '', $helpArray);
1856 }
1857
1858 $tRows[] = '
1859 <tr id="' . $rowId . '" class="' . ($sM ? 'c-selectedItem' : 'c-unselectedItem') . '" onclick="' . htmlspecialchars($onClick) . '" style="cursor: pointer;">
1860 <td class="c-checkbox"><input type="checkbox"' . $this->insertDefStyle('check') . ' name="' . htmlspecialchars($PA['itemFormElName'] . '[' . $c . ']') . '" value="' . htmlspecialchars($p[1]) . '"' . $sM . ' onclick="' . htmlspecialchars($sOnChange) . '"' . $PA['onFocus'] . ' /></td>
1861 <td class="c-labelCell" onclick="' . htmlspecialchars($onClickCell) . '">' .
1862 $this->getIconHtml($selIcon) .
1863 $label .
1864 '</td>
1865 <td class="c-descr" onclick="' . htmlspecialchars($onClickCell) . '">' . ((empty($help)) ? '' : $help) . '</td>
1866 </tr>';
1867 $c++;
1868 }
1869 }
1870 }
1871
1872 // Remaining values (invalid):
1873 if (count($itemArray) && !$PA['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
1874 foreach ($itemArray as $theNoMatchValue => $temp) {
1875 // Compile <checkboxes> tag:
1876 array_unshift($tRows, '
1877 <tr class="c-invalidItem">
1878 <td class="c-checkbox"><input type="checkbox"' . $this->insertDefStyle('check') . ' name="' . htmlspecialchars($PA['itemFormElName'] . '[' . $c . ']') . '" value="' . htmlspecialchars($theNoMatchValue) . '" checked="checked" onclick="' . htmlspecialchars($sOnChange) . '"' . $PA['onFocus'] . $disabled . ' /></td>
1879 <td class="c-labelCell">' .
1880 t3lib_div::deHSCentities(htmlspecialchars(@sprintf($nMV_label, $theNoMatchValue))) .
1881 '</td><td>&nbsp;</td>
1882 </tr>');
1883 $c++;
1884 }
1885 }
1886
1887 // Add an empty hidden field which will send a blank value if all items are unselected.
1888 $item .= '<input type="hidden" name="' . htmlspecialchars($PA['itemFormElName']) . '" value="" />';
1889
1890 // Remaining checkboxes will get their set-all link:
1891 if (count($setAll)) {
1892 $tableHead = '<thead>
1893 <tr class="c-header-checkbox-controls t3-row-header">
1894 <td class="c-checkbox">
1895 <input type="checkbox" class="checkbox" onclick="if (checked) {' . htmlspecialchars(implode('', $setAll) . '} else {' . implode('', $unSetAll) . '}') . '">
1896 </td>
1897 <td colspan="2">
1898 </td>
1899 </tr></thead>';
1900 }
1901 // Implode rows in table:
1902 $item .= '
1903 <table border="0" cellpadding="0" cellspacing="0" class="typo3-TCEforms-select-checkbox">' .
1904 $tableHead .
1905 '<tbody>' . implode('', $tRows) . '</tbody>
1906 </table>
1907 ';
1908
1909 // Add revert icon
1910 if (is_array($restoreCmd)) {
1911 $item .= '<a href="#" onclick="' . implode('', $restoreCmd) . ' return false;' . '">' .
1912 t3lib_iconWorks::getSpriteIcon('actions-edit-undo', array('title' => htmlspecialchars($this->getLL('l_revertSelection')))) . '</a>';
1913 }
1914
1915 return $item;
1916 }
1917
1918 /**
1919 * Creates a selectorbox list (renderMode = "singlebox")
1920 * (Render function for getSingleField_typeSelect())
1921 *
1922 * @param string See getSingleField_typeSelect()
1923 * @param string See getSingleField_typeSelect()
1924 * @param array See getSingleField_typeSelect()
1925 * @param array See getSingleField_typeSelect()
1926 * @param array (Redundant) content of $PA['fieldConf']['config'] (for convenience)
1927 * @param array Items available for selection
1928 * @param string Label for no-matching-value
1929 * @return string The HTML code for the item
1930 * @see getSingleField_typeSelect()
1931 */
1932 function getSingleField_typeSelect_singlebox($table, $field, $row, &$PA, $config, $selItems, $nMV_label) {
1933
1934 // Get values in an array (and make unique, which is fine because there can be no duplicates anyway):
1935 $itemArray = array_flip($this->extractValuesOnlyFromValueLabelList($PA['itemFormElValue']));
1936
1937 $item = '';
1938 $disabled = '';
1939 if ($this->renderReadonly || $config['readOnly']) {
1940 $disabled = ' disabled="disabled"';
1941 }
1942
1943 // Traverse the Array of selector box items:
1944 $opt = array();
1945 $restoreCmd = array(); // Used to accumulate the JS needed to restore the original selection.
1946 $c = 0;
1947 foreach ($selItems as $p) {
1948 // Selected or not by default:
1949 $sM = '';
1950 if (isset($itemArray[$p[1]])) {
1951 $sM = ' selected="selected"';
1952 $restoreCmd[] = $this->elName($PA['itemFormElName'] . '[]') . '.options[' . $c . '].selected=1;';
1953 unset($itemArray[$p[1]]);
1954 }
1955
1956 // Non-selectable element:
1957 $nonSel = '';
1958 if (!strcmp($p[1], '--div--')) {
1959 $nonSel = ' onclick="this.selected=0;" class="c-divider"';
1960 }
1961
1962 // Icon style for option tag:
1963 if ($config['iconsInOptionTags']) {
1964 $styleAttrValue = $this->optionTagStyle($p[2]);
1965 }
1966
1967 // Compile <option> tag:
1968 $opt[] = '<option value="' . htmlspecialchars($p[1]) . '"' .
1969 $sM .
1970 $nonSel .
1971 ($styleAttrValue ? ' style="' . htmlspecialchars($styleAttrValue) . '"' : '') .
1972 '>' . t3lib_div::deHSCentities(htmlspecialchars($p[0])) . '</option>';
1973 $c++;
1974 }
1975
1976 // Remaining values:
1977 if (count($itemArray) && !$PA['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
1978 foreach ($itemArray as $theNoMatchValue => $temp) {
1979 // Compile <option> tag:
1980 array_unshift($opt, '<option value="' . htmlspecialchars($theNoMatchValue) . '" selected="selected">' . t3lib_div::deHSCentities(htmlspecialchars(@sprintf($nMV_label, $theNoMatchValue))) . '</option>');
1981 }
1982 }
1983
1984 // Compile selector box:
1985 $sOnChange = implode('', $PA['fieldChangeFunc']);
1986 $selector_itemListStyle = isset($config['itemListStyle']) ? ' style="' . htmlspecialchars($config['itemListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"';
1987 $size = intval($config['size']);
1988 $cssPrefix = ($size === 1) ? 'tceforms-select' : 'tceforms-multiselect';
1989 $size = $config['autoSizeMax'] ? t3lib_div::intInRange(count($selItems) + 1, t3lib_div::intInRange($size, 1), $config['autoSizeMax']) : $size;
1990 $selectBox = '<select id="' . uniqid($cssPrefix) . '" name="' . $PA['itemFormElName'] . '[]"' .
1991 $this->insertDefStyle('select', $cssPrefix) .
1992 ($size ? ' size="' . $size . '"' : '') .
1993 ' multiple="multiple" onchange="' . htmlspecialchars($sOnChange) . '"' .
1994 $PA['onFocus'] .
1995 $selector_itemListStyle .
1996 $disabled . '>
1997 ' .
1998 implode('
1999 ', $opt) . '
2000 </select>';
2001
2002 // Add an empty hidden field which will send a blank value if all items are unselected.
2003 if (!$disabled) {
2004 $item .= '<input type="hidden" name="' . htmlspecialchars($PA['itemFormElName']) . '" value="" />';
2005 }
2006
2007 // Put it all into a table:
2008 $item .= '
2009 <table border="0" cellspacing="0" cellpadding="0" width="1" class="typo3-TCEforms-select-singlebox">
2010 <tr>
2011 <td>
2012 ' . $selectBox . '
2013 <br/>
2014 <em>' .
2015 htmlspecialchars($this->getLL('l_holdDownCTRL')) .
2016 '</em>
2017 </td>
2018 <td valign="top">
2019 <a href="#" onclick="' . htmlspecialchars($this->elName($PA['itemFormElName'] . '[]') . '.selectedIndex=-1;' . implode('', $restoreCmd) . ' return false;') . '" title="' . htmlspecialchars($this->getLL('l_revertSelection')) . '">' .
2020 t3lib_iconWorks::getSpriteIcon('actions-edit-undo') .
2021 '</a>
2022 </td>
2023 </tr>
2024 </table>
2025 ';
2026
2027 return $item;
2028 }
2029
2030 /**
2031 * Creates a multiple-selector box (two boxes, side-by-side)
2032 * (Render function for getSingleField_typeSelect())
2033 *
2034 * @param string See getSingleField_typeSelect()
2035 * @param string See getSingleField_typeSelect()
2036 * @param array See getSingleField_typeSelect()
2037 * @param array See getSingleField_typeSelect()
2038 * @param array (Redundant) content of $PA['fieldConf']['config'] (for convenience)
2039 * @param array Items available for selection
2040 * @param string Label for no-matching-value
2041 * @return string The HTML code for the item
2042 * @see getSingleField_typeSelect()
2043 */
2044 function getSingleField_typeSelect_multiple($table, $field, $row, &$PA, $config, $selItems, $nMV_label) {
2045
2046 $item = '';
2047 $disabled = '';
2048 if ($this->renderReadonly || $config['readOnly']) {
2049 $disabled = ' disabled="disabled"';
2050 }
2051
2052 // Setting this hidden field (as a flag that JavaScript can read out)
2053 if (!$disabled) {
2054 $item .= '<input type="hidden" name="' . $PA['itemFormElName'] . '_mul" value="' . ($config['multiple'] ? 1 : 0) . '" />';
2055 }
2056
2057 // Set max and min items:
2058 $maxitems = t3lib_div::intInRange($config['maxitems'], 0);
2059 if (!$maxitems) {
2060 $maxitems = 100000;
2061 }
2062 $minitems = t3lib_div::intInRange($config['minitems'], 0);
2063
2064 // Register the required number of elements:
2065 $this->registerRequiredProperty('range', $PA['itemFormElName'], array($minitems, $maxitems, 'imgName' => $table . '_' . $row['uid'] . '_' . $field));
2066
2067 // Get "removeItems":
2068 $removeItems = t3lib_div::trimExplode(',', $PA['fieldTSConfig']['removeItems'], 1);
2069
2070 // Get the array with selected items:
2071 $itemArray = t3lib_div::trimExplode(',', $PA['itemFormElValue'], 1);
2072
2073 // Possibly filter some items:
2074 $keepItemsFunc = create_function('$value', '$parts=explode(\'|\',$value,2); return rawurldecode($parts[0]);');
2075 $itemArray = t3lib_div::keepItemsInArray($itemArray, $PA['fieldTSConfig']['keepItems'], $keepItemsFunc);
2076
2077 // Perform modification of the selected items array:
2078 foreach ($itemArray as $tk => $tv) {
2079 $tvP = explode('|', $tv, 2);
2080 $evalValue = $tvP[0];
2081 $isRemoved = in_array($evalValue, $removeItems) || ($config['form_type'] == 'select' && $config['authMode'] && !$GLOBALS['BE_USER']->checkAuthMode($table, $field, $evalValue, $config['authMode']));
2082 if ($isRemoved && !$PA['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
2083 $tvP[1] = rawurlencode(@sprintf($nMV_label, $evalValue));
2084 } elseif (isset($PA['fieldTSConfig']['altLabels.'][$evalValue])) {
2085 $tvP[1] = rawurlencode($this->sL($PA['fieldTSConfig']['altLabels.'][$evalValue]));
2086 }
2087 if ($tvP[1] == '') {
2088 // Case: flexform, default values supplied, no label provided (bug #9795)
2089 foreach ($selItems as $selItem) {
2090 if ($selItem[1] == $tvP[0]) {
2091 $tvP[1] = html_entity_decode($selItem[0]);
2092 break;
2093 }
2094 }
2095 }
2096 $itemArray[$tk] = implode('|', $tvP);
2097 }
2098 $itemsToSelect = '';
2099
2100 if (!$disabled) {
2101 // Create option tags:
2102 $opt = array();
2103 $styleAttrValue = '';
2104 foreach ($selItems as $p) {
2105 if ($config['iconsInOptionTags']) {
2106 $styleAttrValue = $this->optionTagStyle($p[2]);
2107 }
2108 $opt[] = '<option value="' . htmlspecialchars($p[1]) . '"' .
2109 ($styleAttrValue ? ' style="' . htmlspecialchars($styleAttrValue) . '"' : '') .
2110 '>' . $p[0] . '</option>';
2111 }
2112
2113 // Put together the selector box:
2114 $selector_itemListStyle = isset($config['itemListStyle']) ? ' style="' . htmlspecialchars($config['itemListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"';
2115 $size = intval($config['size']);
2116 $size = $config['autoSizeMax'] ? t3lib_div::intInRange(count($itemArray) + 1, t3lib_div::intInRange($size, 1), $config['autoSizeMax']) : $size;
2117 if ($config['exclusiveKeys']) {
2118 $sOnChange = 'setFormValueFromBrowseWin(\'' . $PA['itemFormElName'] . '\',this.options[this.selectedIndex].value,this.options[this.selectedIndex].text,\'' . $config['exclusiveKeys'] . '\'); ';
2119 } else {
2120 $sOnChange = 'setFormValueFromBrowseWin(\'' . $PA['itemFormElName'] . '\',this.options[this.selectedIndex].value,this.options[this.selectedIndex].text); ';
2121 }
2122 $sOnChange .= implode('', $PA['fieldChangeFunc']);
2123 $itemsToSelect = '
2124 <select id="' . uniqid('tceforms-multiselect-') . '" name="' . $PA['itemFormElName'] . '_sel"' .
2125 $this->insertDefStyle('select', 'tceforms-multiselect tceforms-itemstoselect') .
2126 ($size ? ' size="' . $size . '"' : '') .
2127 ' onchange="' . htmlspecialchars($sOnChange) . '"' .
2128 $PA['onFocus'] .
2129 $selector_itemListStyle . '>
2130 ' . implode('
2131 ', $opt) . '
2132 </select>';
2133 }
2134
2135 // Pass to "dbFileIcons" function:
2136 $params = array(
2137 'size' => $size,
2138 'autoSizeMax' => t3lib_div::intInRange($config['autoSizeMax'], 0),
2139 'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"',
2140 'dontShowMoveIcons' => ($maxitems <= 1),
2141 'maxitems' => $maxitems,
2142 'info' => '',
2143 'headers' => array(
2144 'selector' => $this->getLL('l_selected') . ':<br />',
2145 'items' => $this->getLL('l_items') . ':<br />'
2146 ),
2147 'noBrowser' => 1,
2148 'thumbnails' => $itemsToSelect,
2149 'readOnly' => $disabled
2150 );
2151 $item .= $this->dbFileIcons($PA['itemFormElName'], '', '', $itemArray, '', $params, $PA['onFocus']);
2152
2153 return $item;
2154 }
2155
2156 /**
2157 * Generation of TCEform elements of the type "group"
2158 * This will render a selectorbox into which elements from either the file system or database can be inserted. Relations.
2159 *
2160 * @param string The table name of the record
2161 * @param string The field name which this element is supposed to edit
2162 * @param array The record data array where the value(s) for the field can be found
2163 * @param array An array with additional configuration options.
2164 * @return string The HTML code for the TCEform field
2165 */
2166 function getSingleField_typeGroup($table, $field, $row, &$PA) {
2167 // Init:
2168 $config = $PA['fieldConf']['config'];
2169 $internal_type = $config['internal_type'];
2170 $show_thumbs = $config['show_thumbs'];
2171 $size = intval($config['size']);
2172 $maxitems = t3lib_div::intInRange($config['maxitems'], 0);
2173 if (!$maxitems) {
2174 $maxitems = 100000;
2175 }
2176 $minitems = t3lib_div::intInRange($config['minitems'], 0);
2177 $allowed = trim($config['allowed']);
2178 $disallowed = trim($config['disallowed']);
2179
2180 $item = '';
2181 $disabled = '';
2182 if ($this->renderReadonly || $config['readOnly']) {
2183 $disabled = ' disabled="disabled"';
2184 }
2185
2186 $item .= '<input type="hidden" name="' . $PA['itemFormElName'] . '_mul" value="' . ($config['multiple'] ? 1 : 0) . '"' . $disabled . ' />';
2187 $this->registerRequiredProperty('range', $PA['itemFormElName'], array($minitems, $maxitems, 'imgName' => $table . '_' . $row['uid'] . '_' . $field));
2188 $info = '';
2189
2190 // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. See http://typo3.org/documentation/document-library/doc_core_api/Wizards_Configuratio/.
2191 $specConf = $this->getSpecConfFromString($PA['extra'], $PA['fieldConf']['defaultExtras']);
2192
2193 $PA['itemFormElID_file'] = $PA['itemFormElID'] . '_files';
2194
2195 // whether the list controls should be disabled
2196 $noList = isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'list');
2197
2198 // if maxitems==1 then automatically replace the current item (in list and file selector)
2199 if ($maxitems === 1) {
2200 $this->additionalJS_post[] = "TBE_EDITOR.clearBeforeSettingFormValueFromBrowseWin['" . $PA['itemFormElName'] . "'] = {
2201 itemFormElID_file: '" . $PA['itemFormElID_file'] . "'
2202 }";
2203 $PA['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = "setFormValueManipulate('" . $PA['itemFormElName'] . "', 'Remove'); " . $PA['fieldChangeFunc']['TBE_EDITOR_fieldChanged'];
2204 } elseif ($noList) {
2205 // if the list controls have been removed and the maximum number is reached, remove the first entry to avoid "write once" field
2206 $PA['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = "setFormValueManipulate('" . $PA['itemFormElName'] . "', 'RemoveFirstIfFull', '" . $maxitems . "'); " . $PA['fieldChangeFunc']['TBE_EDITOR_fieldChanged'];
2207 }
2208
2209 // Acting according to either "file" or "db" type:
2210 switch ((string) $config['internal_type']) {
2211 case 'file_reference':
2212 $config['uploadfolder'] = '';
2213 // Fall through
2214 case 'file': // If the element is of the internal type "file":
2215
2216 // Creating string showing allowed types:
2217 $tempFT = t3lib_div::trimExplode(',', $allowed, TRUE);
2218 if (!count($tempFT)) {
2219 $info .= '*';
2220 }
2221 foreach ($tempFT as $ext) {
2222 if ($ext) {
2223 $info .= strtoupper($ext) . ' ';
2224 }
2225 }
2226 // Creating string, showing disallowed types:
2227 $tempFT_dis = t3lib_div::trimExplode(',', $disallowed, TRUE);
2228 if (count($tempFT_dis)) {
2229 $info .= '<br />';
2230 }
2231 foreach ($tempFT_dis as $ext) {
2232 if ($ext) {
2233 $info .= '-' . strtoupper($ext) . ' ';
2234 }
2235 }
2236
2237 // Making the array of file items:
2238 $itemArray = t3lib_div::trimExplode(',', $PA['itemFormElValue'], TRUE);
2239
2240 // Showing thumbnails:
2241 $thumbsnail = '';
2242 if ($show_thumbs) {
2243 $imgs = array();
2244 foreach ($itemArray as $imgRead) {
2245 $imgP = explode('|', $imgRead);
2246 $imgPath = rawurldecode($imgP[0]);
2247
2248 $rowCopy = array();
2249 $rowCopy[$field] = $imgPath;
2250
2251 $imgs[] = '<span class="nobr">' . t3lib_BEfunc::thumbCode($rowCopy, $table, $field, $this->backPath, 'thumbs.php', $config['uploadfolder'], 0, ' align="middle"') .
2252 $imgPath .
2253 '</span>';
2254 }
2255 $thumbsnail = implode('<br />', $imgs);
2256 }
2257
2258 // Creating the element:
2259 $params = array(
2260 'size' => $size,
2261 'dontShowMoveIcons' => ($maxitems <= 1),
2262 'autoSizeMax' => t3lib_div::intInRange($config['autoSizeMax'], 0),
2263 'maxitems' => $maxitems,
2264 'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"',
2265 'info' => $info,
2266 'thumbnails' => $thumbsnail,
2267 'readOnly' => $disabled,
2268 'noBrowser' => $noList || (isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'browser')),
2269 'noList' => $noList,
2270 );
2271 $item .= $this->dbFileIcons($PA['itemFormElName'], 'file', implode(',', $tempFT), $itemArray, '', $params, $PA['onFocus']);
2272
2273 if (!$disabled && !(isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'upload'))) {
2274 // Adding the upload field:
2275 if ($this->edit_docModuleUpload && $config['uploadfolder']) {
2276 $item .= '<div id="' . $PA['itemFormElID_file'] . '"><input type="file" name="' . $PA['itemFormElName_file'] . '" size="35" onchange="' . implode('', $PA['fieldChangeFunc']) . '" /></div>';
2277 }
2278 }
2279 break;
2280 case 'folder': // If the element is of the internal type "folder":
2281
2282 // array of folder items:
2283 $itemArray = t3lib_div::trimExplode(',', $PA['itemFormElValue'], 1);
2284
2285 // Creating the element:
2286 $params = array(
2287 'size' => $size,
2288 'dontShowMoveIcons' => ($maxitems <= 1),
2289 'autoSizeMax' => t3lib_div::intInRange($config['autoSizeMax'], 0),
2290 'maxitems' => $maxitems,
2291 'style' => isset($config['selectedListStyle']) ?
2292 ' style="' . htmlspecialchars($config['selectedListStyle']) . '"'
2293 : ' style="' . $this->defaultMultipleSelectorStyle . '"',
2294 'info' => $info,
2295 'readOnly' => $disabled,
2296 'noBrowser' => $noList || (isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'browser')),
2297 'noList' => $noList,
2298 );
2299
2300 $item .= $this->dbFileIcons(
2301 $PA['itemFormElName'],
2302 'folder',
2303 '',
2304 $itemArray,
2305 '',
2306 $params,
2307 $PA['onFocus']
2308 );
2309 break;
2310 case 'db': // If the element is of the internal type "db":
2311
2312 // Creating string showing allowed types:
2313 $tempFT = t3lib_div::trimExplode(',', $allowed, TRUE);
2314 if (!strcmp(trim($tempFT[0]), '*')) {
2315 $onlySingleTableAllowed = FALSE;
2316 $info .= '<span class="nobr">' .
2317 htmlspecialchars($this->getLL('l_allTables')) .
2318 '</span><br />';
2319 } elseif ($tempFT) {
2320 $onlySingleTableAllowed = (count($tempFT) == 1);
2321 foreach ($tempFT as $theT) {
2322 $info .= '<span class="nobr">' .
2323 t3lib_iconWorks::getSpriteIconForRecord($theT, array()) .
2324 htmlspecialchars($this->sL($GLOBALS['TCA'][$theT]['ctrl']['title'])) .
2325 '</span><br />';
2326 }
2327 }
2328
2329 $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
2330 $itemArray = array();
2331 $imgs = array();
2332
2333 // Thumbnails:
2334 $temp_itemArray = t3lib_div::trimExplode(',', $PA['itemFormElValue'], 1);
2335 foreach ($temp_itemArray as $dbRead) {
2336 $recordParts = explode('|', $dbRead);
2337 list($this_table, $this_uid) = t3lib_BEfunc::splitTable_Uid($recordParts[0]);
2338 // For the case that no table was found and only a single table is defined to be allowed, use that one:
2339 if (!$this_table && $onlySingleTableAllowed) {
2340 $this_table = $allowed;
2341 }
2342 $itemArray[] = array('table' => $this_table, 'id' => $this_uid);
2343 if (!$disabled && $show_thumbs) {
2344 $rr = t3lib_BEfunc::getRecordWSOL($this_table, $this_uid);
2345 $imgs[] = '<span class="nobr">' .
2346 $this->getClickMenu(
2347 t3lib_iconWorks::getSpriteIconForRecord(
2348 $this_table,
2349 $rr,
2350 array(
2351 'style' => 'vertical-align:top',
2352 'title' => htmlspecialchars(t3lib_BEfunc::getRecordPath($rr['pid'], $perms_clause, 15) . ' [UID: ' . $rr['uid'] . ']')
2353 )
2354 ),
2355 $this_table,
2356 $this_uid
2357 ) .
2358 '&nbsp;' .
2359 t3lib_BEfunc::getRecordTitle($this_table, $rr, TRUE) . ' <span class="typo3-dimmed"><em>[' . $rr['uid'] . ']</em></span>' .
2360 '</span>';
2361 }
2362 }
2363 $thumbsnail = '';
2364 if (!$disabled && $show_thumbs) {
2365 $thumbsnail = implode('<br />', $imgs);
2366 }
2367
2368 // Creating the element:
2369 $params = array(
2370 'size' => $size,
2371 'dontShowMoveIcons' => ($maxitems <= 1),
2372 'autoSizeMax' => t3lib_div::intInRange($config['autoSizeMax'], 0),
2373 'maxitems' => $maxitems,
2374 'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : ' style="' . $this->defaultMultipleSelectorStyle . '"',
2375 'info' => $info,
2376 'thumbnails' => $thumbsnail,
2377 'readOnly' => $disabled,
2378 'noBrowser' => $noList || (isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'browser')),
2379 'noList' => $noList,
2380 );
2381 $item .= $this->dbFileIcons($PA['itemFormElName'], 'db', implode(',', $tempFT), $itemArray, '', $params, $PA['onFocus'], $table, $field, $row['uid']);
2382
2383 break;
2384 }
2385
2386 // Wizards:
2387 $altItem = '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
2388 if (!$disabled) {
2389 $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'], $specConf);
2390 }
2391
2392 return $item;
2393 }
2394
2395 /**
2396 * Generation of TCEform elements of the type "none"
2397 * This will render a non-editable display of the content of the field.
2398 *
2399 * @param string The table name of the record
2400 * @param string The field name which this element is supposed to edit
2401 * @param array The record data array where the value(s) for the field can be found
2402 * @param array An array with additional configuration options.
2403 * @return string The HTML code for the TCEform field
2404 */
2405 function getSingleField_typeNone($table, $field, $row, &$PA) {
2406 // Init:
2407 $config = $PA['fieldConf']['config'];
2408 $itemValue = $PA['itemFormElValue'];
2409
2410 return $this->getSingleField_typeNone_render($config, $itemValue);
2411 }
2412
2413 /**
2414 * HTML rendering of a value which is not editable.
2415 *
2416 * @param array Configuration for the display
2417 * @param string The value to display
2418 * @return string The HTML code for the display
2419 * @see getSingleField_typeNone();
2420 */
2421 function getSingleField_typeNone_render($config, $itemValue) {
2422
2423 // is colorScheme[0] the right value?
2424 $divStyle = 'border:solid 1px ' . t3lib_div::modifyHTMLColorAll($this->colorScheme[0], -30) . ';' . $this->defStyle . $this->formElStyle('none') . ' background-color: ' . $this->colorScheme[0] . '; padding-left:1px;color:#555;';
2425
2426 if ($config['format']) {
2427 $itemValue = $this->formatValue($config, $itemValue);
2428 }
2429
2430 $rows = intval($config['rows']);
2431 if ($rows > 1) {
2432 if (!$config['pass_content']) {
2433 $itemValue = nl2br(htmlspecialchars($itemValue));
2434 }
2435 // like textarea
2436 $cols = t3lib_div::intInRange($config['cols'] ? $config['cols'] : 30, 5, $this->maxTextareaWidth);
2437 if (!$config['fixedRows']) {
2438 $origRows = $rows = t3lib_div::intInRange($rows, 1, 20);
2439 if (strlen($itemValue) > $this->charsPerRow * 2) {
2440 $cols = $this->maxTextareaWidth;
2441 $rows = t3lib_div::intInRange(round(strlen($itemValue) / $this->charsPerRow), count(explode(LF, $itemValue)), 20);
2442 if ($rows < $origRows) {
2443 $rows = $origRows;
2444 }
2445 }
2446 }
2447
2448 if ($this->docLarge) {
2449 $cols = round($cols * $this->form_largeComp);
2450 }
2451 $width = ceil($cols * $this->form_rowsToStylewidth);
2452 // hardcoded: 12 is the height of the font
2453 $height = $rows * 12;
2454
2455 $item = '
2456 <div style="' . htmlspecialchars($divStyle . ' overflow:auto; height:' . $height . 'px; width:' . $width . 'px;') . '" class="' . htmlspecialchars($this->formElClass('none')) . '">' .
2457 $itemValue .
2458 '</div>';
2459 } else {
2460 if (!$config['pass_content']) {
2461 $itemValue = htmlspecialchars($itemValue);
2462 }
2463
2464 $cols = $config['cols'] ? $config['cols'] : ($config['size'] ? $config['size'] : $this->maxInputWidth);
2465 if ($this->docLarge) {
2466 $cols = round($cols * $this->form_largeComp);
2467 }
2468 $width = ceil($cols * $this->form_rowsToStylewidth);
2469
2470 // overflow:auto crashes mozilla here. Title tag is usefull when text is longer than the div box (overflow:hidden).
2471 $item = '
2472 <div style="' . htmlspecialchars($divStyle . ' overflow:hidden; width:' . $width . 'px;') . '" class="' . htmlspecialchars($this->formElClass('none')) . '" title="' . $itemValue . '">' .
2473 '<span class="nobr">' . (strcmp($itemValue, '') ? $itemValue : '&nbsp;') . '</span>' .
2474 '</div>';
2475 }
2476
2477 return $item;
2478 }
2479
2480 /**
2481 * Handler for Flex Forms
2482 *
2483 * @param string The table name of the record
2484 * @param string The field name which this element is supposed to edit
2485 * @param array The record data array where the value(s) for the field can be found
2486 * @param array An array with additional configuration options.
2487 * @return string The HTML code for the TCEform field
2488 */
2489 function getSingleField_typeFlex($table, $field, $row, &$PA) {
2490
2491 // Data Structure:
2492 $dataStructArray = t3lib_BEfunc::getFlexFormDS($PA['fieldConf']['config'], $row, $table);
2493 $item = '';
2494
2495 // Manipulate Flexform DS via TSConfig and group access lists
2496 if (is_array($dataStructArray)) {
2497 $flexFormHelper = t3lib_div::makeInstance('t3lib_TCEforms_Flexforms');
2498 $dataStructArray = $flexFormHelper->modifyFlexFormDS($dataStructArray, $table, $field, $row, $PA['fieldConf']['config']);
2499 unset($flexFormHelper);
2500 }
2501
2502 // Get data structure:
2503 if (is_array($dataStructArray)) {
2504
2505 // Get data:
2506 $xmlData = $PA['itemFormElValue'];
2507 $xmlHeaderAttributes = t3lib_div::xmlGetHeaderAttribs($xmlData);
2508 $storeInCharset = strtolower($xmlHeaderAttributes['encoding']);
2509 if ($storeInCharset) {
2510 $currentCharset = $GLOBALS['LANG']->charSet;
2511 $xmlData = $GLOBALS['LANG']->csConvObj->conv($xmlData, $storeInCharset, $currentCharset, 1);
2512 }
2513 $editData = t3lib_div::xml2array($xmlData);
2514 if (!is_array($editData)) { // Must be XML parsing error...
2515 $editData = array();
2516 } elseif (!isset($editData['meta']) || !is_array($editData['meta'])) {
2517 $editData['meta'] = array();
2518 }
2519
2520 // Find the data structure if sheets are found:
2521 $sheet = $editData['meta']['currentSheetId'] ? $editData['meta']['currentSheetId'] : 'sDEF'; // Sheet to display
2522
2523 // Create sheet menu:
2524 //TODO; Why is this commented out?
2525 // if (is_array($dataStructArray['sheets'])) {
2526 // #$item.=$this->getSingleField_typeFlex_sheetMenu($dataStructArray['sheets'], $PA['itemFormElName'].'[meta][currentSheetId]', $sheet).'<br />';
2527 // }
2528
2529 // Create language menu:
2530 $langChildren = $dataStructArray['meta']['langChildren'] ? 1 : 0;
2531 $langDisabled = $dataStructArray['meta']['langDisable'] ? 1 : 0;
2532
2533 $editData['meta']['currentLangId'] = array();
2534
2535 // Look up page overlays:
2536 $checkPageLanguageOverlay = $GLOBALS['BE_USER']->getTSConfigVal('options.checkPageLanguageOverlay') ? TRUE : FALSE;
2537 if ($checkPageLanguageOverlay) {
2538 $pageOverlays = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
2539 '*',
2540 'pages_language_overlay',
2541 'pid=' . intval($row['pid']) .
2542 t3lib_BEfunc::deleteClause('pages_language_overlay') .
2543 t3lib_BEfunc::versioningPlaceholderClause('pages_language_overlay'),
2544 '',
2545 '',
2546 '',
2547 'sys_language_uid'
2548 );
2549 }
2550 $languages = $this->getAvailableLanguages();
2551
2552 foreach ($languages as $lInfo) {
2553 if ($GLOBALS['BE_USER']->checkLanguageAccess($lInfo['uid']) && (!$checkPageLanguageOverlay || $lInfo['uid'] <= 0 || is_array($pageOverlays[$lInfo['uid']]))) {
2554 $editData['meta']['currentLangId'][] = $lInfo['ISOcode'];
2555 }
2556 }
2557 if (!is_array($editData['meta']['currentLangId']) || !count($editData['meta']['currentLangId'])) {
2558 $editData['meta']['currentLangId'] = array('DEF');
2559 }
2560
2561 $editData['meta']['currentLangId'] = array_unique($editData['meta']['currentLangId']);
2562
2563 //TODO: Why is this commented out?
2564 // if (!$langDisabled && count($languages) > 1) {
2565 // $item.=$this->getSingleField_typeFlex_langMenu($languages, $PA['itemFormElName'].'[meta][currentLangId]', $editData['meta']['currentLangId']).'<br />';
2566 // }
2567
2568 $PA['_noEditDEF'] = FALSE;
2569 if ($langChildren || $langDisabled) {
2570 $rotateLang = array('DEF');
2571 } else {
2572 if (!in_array('DEF', $editData['meta']['currentLangId'])) {
2573 array_unshift($editData['meta']['currentLangId'], 'DEF');
2574 $PA['_noEditDEF'] = TRUE;
2575 }
2576 $rotateLang = $editData['meta']['currentLangId'];
2577 }
2578
2579 // Tabs sheets
2580 if (is_array($dataStructArray['sheets'])) {
2581 $tabsToTraverse = array_keys($dataStructArray['sheets']);
2582 } else {
2583 $tabsToTraverse = array($sheet);
2584 }
2585
2586 foreach ($rotateLang as $lKey) {
2587 if (!$langChildren && !$langDisabled) {
2588 $item .= '<strong>' . $this->getLanguageIcon($table, $row, 'v' . $lKey) . $lKey . ':</strong>';
2589 }
2590
2591 $tabParts = array();
2592 foreach ($tabsToTraverse as $sheet) {
2593 list ($dataStruct, $sheet) = t3lib_div::resolveSheetDefInDS($dataStructArray, $sheet);
2594
2595 // Render sheet:
2596 if (is_array($dataStruct['ROOT']) && is_array($dataStruct['ROOT']['el'])) {
2597 $lang = 'l' . $lKey; // Default language, other options are "lUK" or whatever country code (independant of system!!!)
2598 $PA['_valLang'] = $langChildren && !$langDisabled ? $editData['meta']['currentLangId'] : 'DEF'; // Default language, other options are "lUK" or whatever country code (independant of system!!!)
2599 $PA['_lang'] = $lang;
2600 // Assemble key for loading the correct CSH file
2601 $dsPointerFields = t3lib_div::trimExplode(',', $GLOBALS['TCA'][$table]['columns'][$field]['config']['ds_pointerField'], TRUE);
2602 $PA['_cshKey'] = $table . '.' . $field;
2603 foreach ($dsPointerFields as $key) {
2604 $PA['_cshKey'] .= '.' . $row[$key];
2605 }
2606
2607 // Push the sheet level tab to DynNestedStack
2608 if (is_array($dataStructArray['sheets'])) {
2609 $tabIdentString = $GLOBALS['TBE_TEMPLATE']->getDynTabMenuId('TCEFORMS:flexform:' . $PA['itemFormElName'] . $PA['_lang']);
2610 $this->pushToDynNestedStack('tab', $tabIdentString . '-' . (count($tabParts) + 1));
2611 }
2612 // Render flexform:
2613 $tRows = $this->getSingleField_typeFlex_draw(
2614 $dataStruct['ROOT']['el'],
2615 $editData['data'][$sheet][$lang],
2616 $table,
2617 $field,
2618 $row,
2619 $PA,
2620 '[data][' . $sheet . '][' . $lang . ']'
2621 );
2622 $sheetContent = '<div class="typo3-TCEforms-flexForm">' . $tRows . '</div>';
2623
2624
2625 // Pop the sheet level tab from DynNestedStack
2626 if (is_array($dataStructArray['sheets'])) {
2627 $this->popFromDynNestedStack('tab', $tabIdentString . '-' . (count($tabParts) + 1));
2628 }
2629 } else {
2630 $sheetContent = 'Data Structure ERROR: No ROOT element found for sheet "' . $sheet . '".';
2631 }
2632
2633 // Add to tab:
2634 $tabParts[] = array(
2635 'label' => ($dataStruct['ROOT']['TCEforms']['sheetTitle'] ? $this->sL($dataStruct['ROOT']['TCEforms']['sheetTitle']) : $sheet),
2636 'description' => ($dataStruct['ROOT']['TCEforms']['sheetDescription'] ? $this->sL($dataStruct['ROOT']['TCEforms']['sheetDescription']) : ''),
2637 'linkTitle' => ($dataStruct['ROOT']['TCEforms']['sheetShortDescr'] ? $this->sL($dataStruct['ROOT']['TCEforms']['sheetShortDescr']) : ''),
2638 'content' => $sheetContent
2639 );
2640 }
2641
2642 if (is_array($dataStructArray['sheets'])) {
2643 $dividersToTabsBehaviour = (isset($GLOBALS['TCA'][$table]['ctrl']['dividers2tabs']) ? $GLOBALS['TCA'][$table]['ctrl']['dividers2tabs'] : 1);
2644 $item .= $this->getDynTabMenu($tabParts, 'TCEFORMS:flexform:' . $PA['itemFormElName'] . $PA['_lang'], $dividersToTabsBehaviour);
2645 } else {
2646 $item .= $sheetContent;
2647 }
2648 }
2649 } else {
2650 $item = 'Data Structure ERROR: ' . $dataStructArray;
2651 }
2652
2653 return $item;
2654 }
2655
2656 /**
2657 * Creates the language menu for FlexForms:
2658 *
2659 * @param [type] $languages: ...
2660 * @param [type] $elName: ...
2661 * @param [type] $selectedLanguage: ...
2662 * @param [type] $multi: ...
2663 * @return string HTML for menu
2664 */
2665 function getSingleField_typeFlex_langMenu($languages, $elName, $selectedLanguage, $multi = 1) {
2666 $opt = array();
2667 foreach ($languages as $lArr) {
2668 $opt[] = '<option value="' . htmlspecialchars($lArr['ISOcode']) . '"' . (in_array($lArr['ISOcode'], $selectedLanguage) ? ' selected="selected"' : '') . '>' . htmlspecialchars($lArr['title']) . '</option>';
2669 }
2670
2671 $output = '<select id="' . uniqid('tceforms-multiselect-') . ' class="tceforms-select tceforms-multiselect tceforms-flexlangmenu" name="' . $elName . '[]"' . ($multi ? ' multiple="multiple" size="' . count($languages) . '"' : '') . '>' . implode('', $opt) . '</select>';
2672
2673 return $output;
2674 }
2675
2676 /**
2677 * Creates the menu for selection of the sheets:
2678 *
2679 * @param array Sheet array for which to render the menu
2680 * @param string Form element name of the field containing the sheet pointer
2681 * @param string Current sheet key
2682 * @return string HTML for menu
2683 */
2684 function getSingleField_typeFlex_sheetMenu($sArr, $elName, $sheetKey) {
2685
2686 $tCells = array();
2687 $pct = round(100 / count($sArr));
2688 foreach ($sArr as $sKey => $sheetCfg) {
2689 if ($GLOBALS['BE_USER']->jsConfirmation(1)) {
2690 $onClick = 'if (confirm(TBE_EDITOR.labels.onChangeAlert) && TBE_EDITOR.checkSubmit(-1)){' . $this->elName($elName) . ".value='"