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