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