958a1eb1edc7618ec29c101cbc9f220c663eb2af
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / FormEngine.php
1 <?php
2 namespace TYPO3\CMS\Backend\Form;
3
4 /**
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Backend\Form\Element\InlineElement;
18 use TYPO3\CMS\Backend\Template\DocumentTemplate;
19 use TYPO3\CMS\Backend\Utility\BackendUtility;
20 use TYPO3\CMS\Backend\Utility\IconUtility;
21 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
22 use TYPO3\CMS\Core\Database\DatabaseConnection;
23 use TYPO3\CMS\Core\Html\HtmlParser;
24 use TYPO3\CMS\Core\Messaging\FlashMessage;
25 use TYPO3\CMS\Core\Messaging\FlashMessageQueue;
26 use TYPO3\CMS\Core\Messaging\FlashMessageService;
27 use TYPO3\CMS\Core\Utility\ArrayUtility;
28 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
29 use TYPO3\CMS\Core\Utility\GeneralUtility;
30 use TYPO3\CMS\Core\Utility\MathUtility;
31 use TYPO3\CMS\Core\Utility\PathUtility;
32 use TYPO3\CMS\Lang\LanguageService;
33
34 /**
35 * 'TCEforms' - Class for creating the backend editing forms.
36 *
37 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
38 * @coauthor René Fritz <r.fritz@colorcube.de>
39 */
40 class FormEngine {
41
42 /**
43 * @var array
44 */
45 public $palFieldArr = array();
46
47 /**
48 * @var bool
49 */
50 public $disableWizards = FALSE;
51
52 /**
53 * @var bool
54 */
55 public $isPalettedoc = FALSE;
56
57 /**
58 * @var int
59 */
60 public $paletteMargin = 1;
61
62 /**
63 * @var string
64 * @deprecated since TYPO3 CMS 7, will be removed in CMS 8
65 */
66 public $defStyle = '';
67
68 /**
69 * @var array
70 */
71 public $cachedTSconfig = array();
72
73 /**
74 * @var array
75 */
76 public $cachedTSconfig_fieldLevel = array();
77
78 /**
79 * @var array
80 */
81 public $cachedLanguageFlag = array();
82
83 /**
84 * @var array|NULL
85 */
86 public $cachedAdditionalPreviewLanguages = NULL;
87
88 /**
89 * Cache for the real PID of a record. The array key consists for a combined string "<table>:<uid>:<pid>".
90 * The value is an array with two values: first is the real PID of a record, second is the PID value for TSconfig.
91 *
92 * @var array
93 */
94 protected $cache_getTSCpid = array();
95
96 /**
97 * @var array
98 */
99 public $transformedRow = array();
100
101 /**
102 * @var string
103 */
104 public $extJSCODE = '';
105
106 /**
107 * @var array
108 */
109 public $printNeededJS = array();
110
111 /**
112 * @var array
113 */
114 public $hiddenFieldAccum = array();
115
116 /**
117 * @var string
118 */
119 public $TBE_EDITOR_fieldChanged_func = '';
120
121 /**
122 * @var bool
123 */
124 public $loadMD5_JS = TRUE;
125
126 /**
127 * Array where records in the default language is stored. (processed by transferdata)
128 *
129 * @var array
130 */
131 public $defaultLanguageData = array();
132
133 /**
134 * Array where records in the default language is stored (raw without any processing. used for making diff)
135 *
136 * @var array
137 */
138 public $defaultLanguageData_diff = array();
139
140 /**
141 * @var array
142 */
143 public $additionalPreviewLanguageData = array();
144
145 // EXTERNAL, static
146 /**
147 * Set this to the 'backPath' pointing back to the typo3 admin directory
148 * from the script where this form is displayed.
149 *
150 * @var string
151 */
152 public $backPath = '';
153
154 /**
155 * Alternative return URL path (default is \TYPO3\CMS\Core\Utility\GeneralUtility::linkThisScript())
156 *
157 * @var string
158 */
159 public $returnUrl = '';
160
161 /**
162 * Can be set to point to a field name in the form which will be set to '1' when the form
163 * is submitted with a *save* button. This way the recipient script can determine that
164 * the form was submitted for save and not "close" for example.
165 *
166 * @var string
167 */
168 public $doSaveFieldName = '';
169
170 /**
171 * Can be set TRUE/FALSE to whether palettes (secondary options) are in the topframe or in form.
172 * 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 * @var bool
175 */
176 public $palettesCollapsed = FALSE;
177
178 /**
179 * If set, the RTE is disabled (from form display, eg. by checkbox in the bottom of the page!)
180 *
181 * @var bool
182 */
183 public $disableRTE = FALSE;
184
185 /**
186 * If FALSE, then all CSH will be disabled, regardless of settings in $this->edit_showFieldHelp
187 *
188 * @var bool
189 */
190 public $globalShowHelp = TRUE;
191
192 /**
193 * If this evaluates to TRUE, the forms are rendering only localization relevant fields of the records.
194 *
195 * @var string
196 */
197 public $localizationMode = '';
198
199 /**
200 * Overrule the field order set in TCA[types][showitem], eg for tt_content this value,
201 * 'bodytext,image', would make first the 'bodytext' field, then the 'image' field (if set for display)...
202 * and then the rest in the old order.
203 *
204 * @var string
205 */
206 public $fieldOrder = '';
207
208 /**
209 * If set to FALSE, palettes will NEVER be rendered.
210 *
211 * @var bool
212 */
213 public $doPrintPalette = TRUE;
214
215 /**
216 * Set to initialized clipboard object;
217 * Then the element browser will offer a link to paste in records from clipboard.
218 *
219 * @var \TYPO3\CMS\Backend\Clipboard\Clipboard|NULL
220 */
221 public $clipObj = NULL;
222
223 /**
224 * Enable click menu on reference icons.
225 *
226 * @var bool
227 */
228 public $enableClickMenu = FALSE;
229
230 /**
231 * @var bool
232 */
233 public $enableTabMenu = FALSE;
234
235 /**
236 * When enabled all fields are rendered non-editable
237 *
238 * @var bool
239 */
240 public $renderReadonly = FALSE;
241
242 /**
243 * Form field width compensation: Factor of "size=12" to "style="width: 12*9.58px"
244 * for form field widths of style-aware browsers
245 *
246 * @var float
247 */
248 public $form_rowsToStylewidth = 9.58;
249
250 /**
251 * Value that gets added for style="width: ...px" for textareas compared to input fields.
252 *
253 * @var integer
254 */
255 protected $form_additionalTextareaStyleWidth = 23;
256
257 /**
258 * Form field width compensation: Compensation for large documents, doc-tab (editing)
259 *
260 * @var float
261 */
262 public $form_largeComp = 1.33;
263
264 /**
265 * The number of chars expected per row when the height of a text area field is
266 * automatically calculated based on the number of characters found in the field content.
267 *
268 * @var int
269 */
270 public $charsPerRow = 40;
271
272 /**
273 * The maximum abstract value for textareas
274 *
275 * @var int
276 */
277 public $maxTextareaWidth = 48;
278
279 /**
280 * The maximum abstract value for input fields
281 *
282 * @var int
283 */
284 public $maxInputWidth = 48;
285
286 /**
287 * Default style for the selector boxes used for multiple items in "select" and "group" types.
288 *
289 * @var string
290 */
291 public $defaultMultipleSelectorStyle = 'width:310px;';
292
293 // INTERNAL, static
294 /**
295 * The string to prepend formfield names with.
296 *
297 * @var string
298 */
299 public $prependFormFieldNames = 'data';
300
301 /**
302 * The string to prepend commands for tcemain::process_cmdmap with
303 *
304 * @var string
305 */
306 public $prependCmdFieldNames = 'cmd';
307
308 /**
309 * The string to prepend FILE form field names with
310 *
311 * @var string
312 */
313 public $prependFormFieldNames_file = 'data_files';
314
315 /**
316 * The string to prepend form field names that are active (not NULL)
317 *
318 * @var string
319 */
320 protected $prependFormFieldNamesActive = 'control[active]';
321
322 /**
323 * The name attribute of the form
324 *
325 * @var string
326 */
327 public $formName = 'editform';
328
329 /**
330 * Whitelist that allows TCA field configuration to be overridden by TSconfig
331 *
332 * @see overrideFieldConf()
333 * @var array
334 */
335 public $allowOverrideMatrix = array();
336
337 // INTERNAL, dynamic
338 /**
339 * Set by readPerms() (caching)
340 *
341 * @var string
342 */
343 public $perms_clause = '';
344
345 /**
346 * Set by readPerms() (caching-flag)
347 *
348 * @var bool
349 */
350 public $perms_clause_set = FALSE;
351
352 /**
353 * Used to indicate the mode of CSH (Context Sensitive Help),
354 * whether it should be icons-only ('icon') or not at all (blank).
355 *
356 * @var bool
357 */
358 public $edit_showFieldHelp = FALSE;
359
360 /**
361 * @var bool
362 */
363 public $edit_docModuleUpload = FALSE;
364
365 /**
366 * Loaded with info about the browser when class is instantiated
367 *
368 * @var array
369 */
370 public $clientInfo = array();
371
372 /**
373 * TRUE, if RTE is possible for the current user (based on result from BE_USER->isRTE())
374 *
375 * @var bool
376 */
377 public $RTEenabled = FALSE;
378
379 /**
380 * If $this->RTEenabled was FALSE, you can find the reasons listed in this array
381 * which is filled with reasons why the RTE could not be loaded)
382 *
383 * @var string
384 */
385 public $RTEenabled_notReasons = '';
386
387 /**
388 * Counter that is incremented before an RTE is created. Can be used for unique ids etc.
389 *
390 * @var int
391 */
392 public $RTEcounter = 0;
393
394 /**
395 * Contains current color scheme
396 *
397 * @var array
398 * @deprecated since TYPO3 CMS 7, will be removed in CMS 8
399 */
400 public $colorScheme = array();
401
402 /**
403 * Contains current class scheme
404 *
405 * @var array
406 * @deprecated since TYPO3 CMS 7, will be removed in CMS 8
407 */
408 public $classScheme = array();
409
410 /**
411 * Contains the default color scheme
412 *
413 * @var array
414 * @deprecated since TYPO3 CMS 7, will be removed in CMS 8
415 */
416 public $defColorScheme = array();
417
418 /**
419 * Contains the default class scheme
420 *
421 * @var array
422 * @deprecated since TYPO3 CMS 7, will be removed in CMS 8
423 */
424 public $defClassScheme = array();
425
426 /**
427 * Contains field style values
428 *
429 * @var array|NULL
430 * @deprecated since TYPO3 CMS 7, will be removed in CMS 8
431 */
432 public $fieldStyle = NULL;
433
434 /**
435 * Contains border style values
436 *
437 * @var array|NULL
438 * @deprecated since TYPO3 CMS 7, will be removed in CMS 8
439 */
440 public $borderStyle = NULL;
441
442 /**
443 * An accumulation of messages from the class
444 *
445 * @var array
446 */
447 public $commentMessages = array();
448
449 // INTERNAL, templates
450 /**
451 * Total wrapping for the table rows
452 *
453 * @var string
454 */
455 public $totalWrap = '<hr />|<hr />';
456
457 /**
458 * Field template
459 *
460 * @var string
461 */
462 public $fieldTemplate = '<strong>###FIELD_NAME###</strong><br />###FIELD_ITEM###<hr />';
463
464 /**
465 * Template subpart for palette fields
466 *
467 * @var string
468 */
469 protected $paletteFieldTemplate = '';
470
471 /**
472 * Wrapping template code for a section
473 *
474 * @var string
475 */
476 public $sectionWrap = '';
477
478 /**
479 * Template for palette headers
480 *
481 * @var string
482 */
483 public $palFieldTemplateHeader = '';
484
485 /**
486 * Template for palettes
487 *
488 * @var string
489 */
490 public $palFieldTemplate = '';
491
492 // INTERNAL, working memory
493 /**
494 * Set to the fields NOT to display, if any
495 *
496 * @var array|NULL
497 */
498 public $excludeElements = NULL;
499
500 /**
501 * During rendering of forms this will keep track of which palettes
502 * has already been rendered (so they are not rendered twice by mistake)
503 *
504 * @var array
505 */
506 public $palettesRendered = array();
507
508 /**
509 * This array of fields will be set as hidden-fields instead of rendered normally!
510 * For instance palette fields edited in the top frame are set as hidden fields
511 * since the main form has to submit the values.
512 * The top frame actually just sets the value in the main form!
513 *
514 * @var array
515 */
516 public $hiddenFieldListArr = array();
517
518 /**
519 * Used to register input-field names, which are required. (Done during rendering of the fields).
520 * This information is then used later when the JavaScript is made.
521 *
522 * @var array
523 */
524 public $requiredFields = array();
525
526 /**
527 * Used to register input-field names, which are required an have additional requirements.
528 * (e.g. like a date/time must be positive integer)
529 * The information of this array is merged with $this->requiredFields later.
530 *
531 * @var array
532 */
533 public $requiredAdditional = array();
534
535 /**
536 * Used to register the min and max number of elements
537 * for selector boxes where that apply (in the "group" type for instance)
538 *
539 * @var array
540 */
541 public $requiredElements = array();
542
543 /**
544 * Used to determine where $requiredFields or $requiredElements are nested (in Tabs or IRRE)
545 *
546 * @var array
547 */
548 public $requiredNested = array();
549
550 /**
551 * Keeps track of the rendering depth of nested records
552 *
553 * @var int
554 */
555 public $renderDepth = 0;
556
557 /**
558 * Color scheme buffer
559 *
560 * @var array
561 */
562 public $savedSchemes = array();
563
564 /**
565 * holds the path an element is nested in (e.g. required for RTEhtmlarea)
566 *
567 * @var array
568 */
569 public $dynNestedStack = array();
570
571 // Internal, registers for user defined functions etc.
572 /**
573 * Additional HTML code, printed before the form
574 *
575 * @var array
576 */
577 public $additionalCode_pre = array();
578
579 /**
580 * Additional JavaScript, printed before the form
581 *
582 * @var array
583 */
584 public $additionalJS_pre = array();
585
586 /**
587 * Additional JavaScript printed after the form
588 *
589 * @var array
590 */
591 public $additionalJS_post = array();
592
593 /**
594 * Additional JavaScript executed on submit; If you set "OK" variable it will raise an error
595 * about RTEs not being loaded and offer to block further submission.
596 *
597 * @var array
598 */
599 public $additionalJS_submit = array();
600
601 /**
602 * Additional JavaScript executed when section element is deleted.
603 * This is necessary, for example, to correctly clean up HTMLArea RTE (bug #8232)
604 *
605 * @var array
606 */
607 public $additionalJS_delete = array();
608
609 /**
610 * @var \TYPO3\CMS\Backend\Form\Element\InlineElement
611 */
612 public $inline;
613
614 /**
615 * Array containing hook class instances called once for a form
616 *
617 * @var array
618 */
619 public $hookObjectsMainFields = array();
620
621 /**
622 * Array containing hook class instances called for each field
623 *
624 * @var array
625 */
626 public $hookObjectsSingleField = array();
627
628 /**
629 * Rows getting inserted into the alt_doc headers (when called from alt_doc.php)
630 *
631 * @var array
632 */
633 public $extraFormHeaders = array();
634
635 /**
636 * Form template, relative to typo3 directory
637 *
638 * @var string
639 */
640 public $templateFile = '';
641
642 /**
643 * @var integer
644 * @var internal
645 */
646 public $multiSelectFilterCount = 0;
647
648 /**
649 * @var \TYPO3\CMS\Backend\Form\Element\SuggestElement
650 */
651 protected $suggest;
652
653 /**
654 * Constructor function, setting internal variables, loading the styles used.
655 *
656 */
657 public function __construct() {
658 $this->clientInfo = GeneralUtility::clientInfo();
659 $this->RTEenabled = $this->getBackendUserAuthentication()->isRTE();
660 if (!$this->RTEenabled) {
661 $this->RTEenabled_notReasons = implode(LF, $this->getBackendUserAuthentication()->RTE_errors);
662 $this->commentMessages[] = 'RTE NOT ENABLED IN SYSTEM due to:' . LF . $this->RTEenabled_notReasons;
663 }
664 // Define whitelist that allows TCA field configuration to be overridden by TSconfig, @see overrideFieldConf():
665 $this->allowOverrideMatrix = array(
666 'input' => array('size', 'max', 'readOnly'),
667 'text' => array('cols', 'rows', 'wrap', 'readOnly'),
668 'check' => array('cols', 'showIfRTE', 'readOnly'),
669 'select' => array('size', 'autoSizeMax', 'maxitems', 'minitems', 'readOnly', 'treeConfig'),
670 'group' => array('size', 'autoSizeMax', 'max_size', 'show_thumbs', 'maxitems', 'minitems', 'disable_controls', 'readOnly'),
671 'inline' => array('appearance', 'behaviour', 'foreign_label', 'foreign_selector', 'foreign_unique', 'maxitems', 'minitems', 'size', 'autoSizeMax', 'symmetric_label', 'readOnly')
672 );
673 // Create instance of InlineElement only if this a non-IRRE-AJAX call:
674 if (!isset($GLOBALS['ajaxID']) || strpos($GLOBALS['ajaxID'], 'TYPO3\\CMS\\Backend\\Form\\Element\\InlineElement::') !== 0) {
675 $this->inline = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\Element\\InlineElement');
676 }
677 // Create instance of \TYPO3\CMS\Backend\Form\Element\SuggestElement only if this a non-Suggest-AJAX call:
678 if (!isset($GLOBALS['ajaxID']) || strpos($GLOBALS['ajaxID'], 'TYPO3\\CMS\\Backend\\Form\\Element\\SuggestElement::') !== 0) {
679 $this->suggest = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\Element\\SuggestElement');
680 }
681 // Prepare user defined objects (if any) for hooks which extend this function:
682 $this->hookObjectsMainFields = array();
683 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getMainFieldsClass'])) {
684 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getMainFieldsClass'] as $classRef) {
685 $this->hookObjectsMainFields[] = GeneralUtility::getUserObj($classRef);
686 }
687 }
688 $this->hookObjectsSingleField = array();
689 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getSingleFieldClass'])) {
690 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getSingleFieldClass'] as $classRef) {
691 $this->hookObjectsSingleField[] = GeneralUtility::getUserObj($classRef);
692 }
693 }
694 $this->templateFile = 'sysext/backend/Resources/Private/Templates/FormEngine.html';
695 }
696
697 /**
698 * Initialize various internal variables.
699 *
700 * @return void
701 */
702 public function initDefaultBEmode() {
703 $this->prependFormFieldNames = 'data';
704 $this->formName = 'editform';
705 $this->setNewBEDesign();
706 $this->edit_showFieldHelp = (bool)$this->getBackendUserAuthentication()->uc['edit_showFieldHelp'];
707 $this->edit_docModuleUpload = (bool)$this->getBackendUserAuthentication()->uc['edit_docModuleUpload'];
708 $this->inline->init($this);
709 $this->suggest->init($this);
710 }
711
712 /*******************************************************
713 *
714 * Rendering the forms, fields etc
715 *
716 *******************************************************/
717 /**
718 * Will return the TCEform element for just a single field from a record.
719 * The field must be listed in the currently displayed fields (as found in [types][showitem]) for the record.
720 * This also means that the $table/$row supplied must be complete so the list of fields to show can be found correctly
721 *
722 * @param string $table The table name
723 * @param array $row The record from the table for which to render a field.
724 * @param string $theFieldToReturn The field name to return the TCEform element for.
725 * @return string HTML output
726 * @see getMainFields()
727 */
728 public function getSoloField($table, $row, $theFieldToReturn) {
729 if (!isset($GLOBALS['TCA'][$table])) {
730 return '';
731 }
732 $typeNum = $this->getRTypeNum($table, $row);
733 if (isset($GLOBALS['TCA'][$table]['types'][$typeNum])) {
734 $itemList = $GLOBALS['TCA'][$table]['types'][$typeNum]['showitem'];
735 if ($itemList) {
736 $fields = GeneralUtility::trimExplode(',', $itemList, TRUE);
737 $excludeElements = ($this->excludeElements = $this->getExcludeElements($table, $row, $typeNum));
738 foreach ($fields as $fieldInfo) {
739 $parts = explode(';', $fieldInfo);
740 $theField = trim($parts[0]);
741 if (!in_array($theField, $excludeElements) && (string)$theField === (string)$theFieldToReturn) {
742 if ($GLOBALS['TCA'][$table]['columns'][$theField]) {
743 $sField = $this->getSingleField($table, $theField, $row, $parts[1], 1, $parts[3], $parts[2]);
744 return $sField['ITEM'];
745 }
746 }
747 }
748 }
749 }
750 return '';
751 }
752
753 /**
754 * Based on the $table and $row of content, this displays the complete TCEform for the record.
755 * The input-$row is required to be preprocessed if necessary by eg.
756 * the \TYPO3\CMS\Backend\Form\DataPreprocessor class. For instance the RTE content
757 * should be transformed through this class first.
758 *
759 * @param string $table The table name
760 * @param array $row The record from the table for which to render a field.
761 * @param int $depth Depth level
762 * @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'].
763 * @return string HTML output
764 * @see getSoloField()
765 */
766 public function getMainFields($table, array $row, $depth = 0, array $overruleTypesArray = array()) {
767 $this->renderDepth = $depth;
768 // Init vars:
769 $out_array = array(array());
770 $out_array_meta = array(
771 array(
772 'title' => $this->getLL('l_generalTab')
773 )
774 );
775 $out_pointer = 0;
776 $out_sheet = 0;
777 $this->palettesRendered = array();
778 $this->palettesRendered[$this->renderDepth][$table] = array();
779 // Hook: getMainFields_preProcess (requested by Thomas Hempel for use with the "dynaflex" extension)
780 foreach ($this->hookObjectsMainFields as $hookObj) {
781 if (method_exists($hookObj, 'getMainFields_preProcess')) {
782 $hookObj->getMainFields_preProcess($table, $row, $this);
783 }
784 }
785 $tabIdentString = '';
786 $tabIdentStringMD5 = '';
787 if ($GLOBALS['TCA'][$table]) {
788 // Get dividers2tabs setting from TCA of the current table:
789 $dividers2tabs = &$GLOBALS['TCA'][$table]['ctrl']['dividers2tabs'];
790 // Load the description content for the table.
791 if ($this->edit_showFieldHelp || $this->doLoadTableDescr($table)) {
792 $this->getLanguageService()->loadSingleTableDescription($table);
793 }
794 // Get the current "type" value for the record.
795 $typeNum = $this->getRTypeNum($table, $row);
796 // Find the list of fields to display:
797 if ($GLOBALS['TCA'][$table]['types'][$typeNum]) {
798 $itemList = $GLOBALS['TCA'][$table]['types'][$typeNum]['showitem'];
799 if (is_array($overruleTypesArray) && isset($overruleTypesArray[$typeNum]['showitem'])) {
800 $itemList = $overruleTypesArray[$typeNum]['showitem'];
801 }
802 // If such a list existed...
803 if ($itemList) {
804 // Explode the field list and possibly rearrange the order of the fields, if configured for
805 $fields = GeneralUtility::trimExplode(',', $itemList, TRUE);
806 if ($this->fieldOrder) {
807 $fields = $this->rearrange($fields);
808 }
809 // Get excluded fields, added fiels and put it together:
810 $excludeElements = ($this->excludeElements = $this->getExcludeElements($table, $row, $typeNum));
811 $fields = $this->mergeFieldsWithAddedFields($fields, $this->getFieldsToAdd($table, $row, $typeNum), $table);
812 // If TCEforms will render a tab menu in the next step, push the name to the tab stack:
813 if (strstr($itemList, '--div--') !== FALSE && $this->enableTabMenu && $dividers2tabs) {
814 $tabIdentString = 'TCEforms:' . $table . ':' . $row['uid'];
815 $tabIdentStringMD5 = $this->getDocumentTemplate()->getDynTabMenuId($tabIdentString);
816 // Remember that were currently working on the general tab:
817 if (isset($fields[0]) && strpos($fields[0], '--div--') !== 0) {
818 $this->pushToDynNestedStack('tab', $tabIdentStringMD5 . '-1');
819 }
820 }
821 // Traverse the fields to render:
822 $cc = 0;
823 foreach ($fields as $fieldInfo) {
824 // Exploding subparts of the field configuration:
825 // this is documented as this:
826 // fieldname;fieldlabel;paletteidorlinebreaktodisplay;extradata;colorscheme
827 // fieldname can also be "--div--" or "--palette--"
828 // the last option colorscheme was dropped with TYPO3 CMS 7
829
830 list($theField, $fieldLabel, $additionalPalette, $extraFieldProcessingData) = explode(';', $fieldInfo);
831
832 // Render the field:
833 if (!in_array($theField, $excludeElements)) {
834 if ($GLOBALS['TCA'][$table]['columns'][$theField]) {
835 $sFieldPal = '';
836 if ($additionalPalette && !isset($this->palettesRendered[$this->renderDepth][$table][$additionalPalette])) {
837 $sFieldPal = $this->getPaletteFields($table, $row, $additionalPalette);
838 $this->palettesRendered[$this->renderDepth][$table][$additionalPalette] = 1;
839 }
840 $sField = $this->getSingleField($table, $theField, $row, $fieldLabel, 0, $extraFieldProcessingData, $additionalPalette);
841 if ($sField) {
842 $sField .= $sFieldPal;
843 }
844 $out_array[$out_sheet][$out_pointer] .= $sField;
845 } elseif ($theField == '--div--') {
846 if ($cc > 0) {
847 $out_array[$out_sheet][$out_pointer] .= $this->getDivider();
848 if ($this->enableTabMenu && $dividers2tabs) {
849 $this->wrapBorder($out_array[$out_sheet], $out_pointer);
850 // Remove last tab entry from the dynNestedStack:
851 $out_sheet++;
852 // Remove the previous sheet from stack (if any):
853 $this->popFromDynNestedStack('tab', $tabIdentStringMD5 . '-' . $out_sheet);
854 // Remember on which sheet we're currently working:
855 $this->pushToDynNestedStack('tab', $tabIdentStringMD5 . '-' . ($out_sheet + 1));
856 $out_array[$out_sheet] = array();
857 $out_array_meta[$out_sheet]['title'] = $this->sL($fieldLabel);
858 // Register newline for Tab
859 $out_array_meta[$out_sheet]['newline'] = $additionalPalette == 'newline';
860 }
861 } else {
862 // Setting alternative title for "General" tab if "--div--" is the very first element.
863 $out_array_meta[$out_sheet]['title'] = $this->sL($fieldLabel);
864 // Only add the first tab to the dynNestedStack if there are more tabs:
865 if ($tabIdentString && strpos($itemList, '--div--', strlen($fieldInfo))) {
866 $this->pushToDynNestedStack('tab', $tabIdentStringMD5 . '-1');
867 }
868 }
869 } elseif ($theField == '--palette--') {
870 if ($additionalPalette && !isset($this->palettesRendered[$this->renderDepth][$table][$additionalPalette])) {
871 // Render a 'header' if not collapsed
872 if ($GLOBALS['TCA'][$table]['palettes'][$additionalPalette]['canNotCollapse'] && $fieldLabel) {
873 $out_array[$out_sheet][$out_pointer] .= $this->getPaletteFields($table, $row, $additionalPalette, $this->sL($fieldLabel));
874 } else {
875 $out_array[$out_sheet][$out_pointer] .= $this->getPaletteFields($table, $row, $additionalPalette, '', '', $this->sL($fieldLabel));
876 }
877 $this->palettesRendered[$this->renderDepth][$table][$additionalPalette] = 1;
878 }
879 }
880 }
881 $cc++;
882 }
883 }
884 }
885 }
886 // Hook: getMainFields_postProcess (requested by Thomas Hempel for use with the "dynaflex" extension)
887 foreach ($this->hookObjectsMainFields as $hookObj) {
888 if (method_exists($hookObj, 'getMainFields_postProcess')) {
889 $hookObj->getMainFields_postProcess($table, $row, $this);
890 }
891 }
892 // Wrapping a border around it all:
893 $this->wrapBorder($out_array[$out_sheet], $out_pointer);
894 // Rendering Main palettes, if any
895 $mParr = GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$table]['ctrl']['mainpalette']);
896 $i = 0;
897 if (count($mParr)) {
898 foreach ($mParr as $mP) {
899 if (!isset($this->palettesRendered[$this->renderDepth][$table][$mP])) {
900 $temp_palettesCollapsed = $this->palettesCollapsed;
901 $this->palettesCollapsed = FALSE;
902 $label = $i == 0 ? $this->getLL('l_generalOptions') : $this->getLL('l_generalOptions_more');
903 $out_array[$out_sheet][$out_pointer] .= $this->getPaletteFields($table, $row, $mP, $label);
904 $this->palettesCollapsed = $temp_palettesCollapsed;
905 $this->palettesRendered[$this->renderDepth][$table][$mP] = 1;
906 }
907 $this->wrapBorder($out_array[$out_sheet], $out_pointer);
908 $i++;
909 if ($this->renderDepth) {
910 $this->renderDepth--;
911 }
912 }
913 }
914 // Return the imploded $out_array:
915 // There were --div-- dividers around...
916 if ($out_sheet > 0) {
917 // Create parts array for the tab menu:
918 $parts = array();
919 foreach ($out_array as $idx => $sheetContent) {
920 $content = implode('', $sheetContent);
921 if ($content) {
922 // Wrap content (row) with table-tag, otherwise tab/sheet will be disabled (see getdynTabMenu() )
923 $content = '<table border="0" cellspacing="0" cellpadding="0" width="100%">' . $content . '</table>';
924 }
925 $parts[$idx] = array(
926 'label' => $out_array_meta[$idx]['title'],
927 'content' => $content,
928 'newline' => $out_array_meta[$idx]['newline']
929 );
930 }
931 if (count($parts) > 1) {
932 // Unset the current level of tab menus:
933 $this->popFromDynNestedStack('tab', $tabIdentStringMD5 . '-' . ($out_sheet + 1));
934 $dividersToTabsBehaviour = isset($GLOBALS['TCA'][$table]['ctrl']['dividers2tabs']) ? $GLOBALS['TCA'][$table]['ctrl']['dividers2tabs'] : 1;
935 $output = $this->getDynTabMenu($parts, $tabIdentString, $dividersToTabsBehaviour);
936 } else {
937 // If there is only one tab/part there is no need to wrap it into the dynTab code
938 $output = isset($parts[0]) ? trim($parts[0]['content']) : '';
939 }
940 $output = '
941 <tr>
942 <td colspan="2">
943 ' . $output . '
944 </td>
945 </tr>';
946 } else {
947 // Only one tab, so just implode and wrap the background image (= tab container) around:
948 $output = implode('', $out_array[$out_sheet]);
949 $output = '<div class="typo3-dyntabmenu-divs">' . $output . '</div>';
950 }
951
952 return $output;
953 }
954
955 /**
956 * Will return the TCEform elements for a pre-defined list of fields.
957 * 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.
958 * Used for displaying forms for the frontend edit icons for instance.
959 *
960 * @param string $table The table name
961 * @param array $row The record array.
962 * @param string $list Commalist of fields from the table. These will be shown in the specified order in a form.
963 * @return string TCEform elements in a string.
964 */
965 public function getListedFields($table, $row, $list) {
966 if ($this->edit_showFieldHelp || $this->doLoadTableDescr($table)) {
967 $this->getLanguageService()->loadSingleTableDescription($table);
968 }
969 $out = '';
970 $types_fieldConfig = BackendUtility::getTCAtypes($table, $row, 1);
971 $editFieldList = array_unique(GeneralUtility::trimExplode(',', $list, TRUE));
972 foreach ($editFieldList as $theFieldC) {
973 list($theField, $palFields) = preg_split('/\\[|\\]/', $theFieldC);
974 $theField = trim($theField);
975 $palFields = trim($palFields);
976 if ($GLOBALS['TCA'][$table]['columns'][$theField]) {
977 $parts = GeneralUtility::trimExplode(';', $types_fieldConfig[$theField]['origString']);
978 // Don't sent palette pointer - there are no options anyways for a field-list.
979 $sField = $this->getSingleField($table, $theField, $row, $parts[1], 0, $parts[3], 0);
980 $out .= $sField;
981 } elseif ($theField == '--div--') {
982 $out .= $this->getDivider();
983 }
984 if ($palFields) {
985 $out .= $this->getPaletteFields($table, $row, '', '', implode(',', GeneralUtility::trimExplode('|', $palFields, TRUE)));
986 }
987 }
988 return $out;
989 }
990
991 /**
992 * Creates a palette (collection of secondary options).
993 *
994 * @param string $table The table name
995 * @param array $row The row array
996 * @param string $palette The palette number/pointer
997 * @param string $header Header string for the palette (used when in-form). If not set, no header item is made.
998 * @param string $itemList Optional alternative list of fields for the palette
999 * @param string $collapsedHeader Optional Link text for activating a palette (when palettes does not have another form element to belong to).
1000 * @return string HTML code.
1001 */
1002 public function getPaletteFields($table, $row, $palette, $header = '', $itemList = '', $collapsedHeader = NULL) {
1003 if (!$this->doPrintPalette) {
1004 return '';
1005 }
1006 $out = '';
1007 $parts = $this->loadPaletteElements($table, $row, $palette, $itemList);
1008 // Put palette together if there are fields in it:
1009 if (count($parts)) {
1010 $realFields = 0;
1011 foreach ($parts as $part) {
1012 if ($part['NAME'] !== '--linebreak--') {
1013 $realFields++;
1014 }
1015 }
1016 if ($realFields > 0) {
1017 if ($header) {
1018 $out .= $this->intoTemplate(array('HEADER' => htmlspecialchars($header)), $this->palFieldTemplateHeader);
1019 }
1020 $collapsed = $this->isPalettesCollapsed($table, $palette);
1021 // Check if the palette is a hidden palette
1022 $isHiddenPalette = !empty($GLOBALS['TCA'][$table]['palettes'][$palette]['isHiddenPalette']);
1023 $thePalIcon = '';
1024 if ($collapsed && $collapsedHeader !== NULL && !$isHiddenPalette) {
1025 list($thePalIcon, ) = $this->wrapOpenPalette(IconUtility::getSpriteIcon('actions-system-options-view', array('title' => htmlspecialchars($this->getLL('l_moreOptions')))), $table, $row, $palette, 1);
1026 $thePalIcon = '<span style="margin-left: 20px;">' . $thePalIcon . $collapsedHeader . '</span>';
1027 }
1028 $paletteHtml = $this->wrapPaletteField($this->printPalette($parts), $table, $row, $palette, $collapsed);
1029 $out .= $this->intoTemplate(array('PALETTE' => $thePalIcon . $paletteHtml), $this->palFieldTemplate);
1030 }
1031 }
1032 return $out;
1033 }
1034
1035 /**
1036 * Returns the form HTML code for a database table field.
1037 *
1038 * @param string $table The table name
1039 * @param string $field The field name
1040 * @param array $row The record to edit from the database table.
1041 * @param string $altName Alternative field name label to show.
1042 * @param bool $palette Set this if the field is on a palette (in top frame), otherwise not. (if set, field will render as a hidden field).
1043 * @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.
1044 * @param int $pal The palette pointer.
1045 * @return mixed String (normal) or array (palettes)
1046 */
1047 public function getSingleField($table, $field, $row, $altName = '', $palette = FALSE, $extra = '', $pal = 0) {
1048 // Hook: getSingleField_preProcess
1049 foreach ($this->hookObjectsSingleField as $hookObj) {
1050 if (method_exists($hookObj, 'getSingleField_preProcess')) {
1051 $hookObj->getSingleField_preProcess($table, $field, $row, $altName, $palette, $extra, $pal, $this);
1052 }
1053 }
1054 $out = '';
1055 $PA = array();
1056 $PA['altName'] = $altName;
1057 $PA['palette'] = $palette;
1058 $PA['extra'] = $extra;
1059 $PA['pal'] = $pal;
1060 // Get the TCA configuration for the current field:
1061 $PA['fieldConf'] = $GLOBALS['TCA'][$table]['columns'][$field];
1062 $PA['fieldConf']['config']['form_type'] = $PA['fieldConf']['config']['form_type'] ?: $PA['fieldConf']['config']['type'];
1063
1064 // Using "form_type" locally in this script
1065 $skipThisField = $this->inline->skipField($table, $field, $row, $PA['fieldConf']['config']);
1066
1067 // Evaluate display condition
1068 $displayConditionResult = TRUE;
1069 if (is_array($PA['fieldConf']) && $PA['fieldConf']['displayCond'] && is_array($row)) {
1070 /** @var $elementConditionMatcher \TYPO3\CMS\Backend\Form\ElementConditionMatcher */
1071 $elementConditionMatcher = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\ElementConditionMatcher');
1072 $displayConditionResult = $elementConditionMatcher->match($PA['fieldConf']['displayCond'], $row);
1073 }
1074 // Check if this field is configured and editable (according to excludefields + other configuration)
1075 if (
1076 is_array($PA['fieldConf'])
1077 && !$skipThisField
1078 && (!$PA['fieldConf']['exclude'] || $this->getBackendUserAuthentication()->check('non_exclude_fields', $table . ':' . $field))
1079 && $PA['fieldConf']['config']['form_type'] != 'passthrough'
1080 && ($this->RTEenabled || !$PA['fieldConf']['config']['showIfRTE'])
1081 && $displayConditionResult
1082 && (!$GLOBALS['TCA'][$table]['ctrl']['languageField'] || $PA['fieldConf']['l10n_display'] || ($PA['fieldConf']['l10n_mode'] !== 'exclude') || $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] <= 0)
1083 && (!$GLOBALS['TCA'][$table]['ctrl']['languageField'] || !$this->localizationMode || $this->localizationMode === $PA['fieldConf']['l10n_cat'])
1084 ) {
1085 // Fetching the TSconfig for the current table/field. This includes the $row which means that
1086 $PA['fieldTSConfig'] = $this->setTSconfig($table, $row, $field);
1087 // If the field is NOT disabled from TSconfig (which it could have been) then render it
1088 if (!$PA['fieldTSConfig']['disabled']) {
1089 // Override fieldConf by fieldTSconfig:
1090 $PA['fieldConf']['config'] = $this->overrideFieldConf($PA['fieldConf']['config'], $PA['fieldTSConfig']);
1091 // Init variables:
1092 $PA['itemFormElName'] = $this->prependFormFieldNames . '[' . $table . '][' . $row['uid'] . '][' . $field . ']';
1093 // Form field name, in case of file uploads
1094 $PA['itemFormElName_file'] = $this->prependFormFieldNames_file . '[' . $table . '][' . $row['uid'] . '][' . $field . ']';
1095 // Form field name, to activate elements
1096 // If the "eval" list contains "null", elements can be deactivated which results in storing NULL to database
1097 $PA['itemFormElNameActive'] = $this->prependFormFieldNamesActive . '[' . $table . '][' . $row['uid'] . '][' . $field . ']';
1098 // The value to show in the form field.
1099 $PA['itemFormElValue'] = $row[$field];
1100 $PA['itemFormElID'] = $this->prependFormFieldNames . '_' . $table . '_' . $row['uid'] . '_' . $field;
1101 // Set field to read-only if configured for translated records to show default language content as readonly
1102 if ($PA['fieldConf']['l10n_display'] && GeneralUtility::inList($PA['fieldConf']['l10n_display'], 'defaultAsReadonly') && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] > 0) {
1103 $PA['fieldConf']['config']['readOnly'] = TRUE;
1104 $PA['itemFormElValue'] = $this->defaultLanguageData[$table . ':' . $row['uid']][$field];
1105 }
1106 if (strpos($GLOBALS['TCA'][$table]['ctrl']['type'], ':') === FALSE) {
1107 $typeField = $GLOBALS['TCA'][$table]['ctrl']['type'];
1108 } else {
1109 $typeField = substr($GLOBALS['TCA'][$table]['ctrl']['type'], 0, strpos($GLOBALS['TCA'][$table]['ctrl']['type'], ':'));
1110 }
1111 // 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"
1112 if (
1113 !empty($GLOBALS['TCA'][$table]['ctrl']['type'])
1114 && $field === $typeField
1115 || !empty($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'])
1116 && GeneralUtility::inList(str_replace(' ', '', $GLOBALS['TCA'][$table]['ctrl']['requestUpdate']), $field)
1117 ) {
1118 if ($this->getBackendUserAuthentication()->jsConfirmation(1)) {
1119 $alertMsgOnChange = 'if (confirm(TBE_EDITOR.labels.onChangeAlert) && TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };';
1120 } else {
1121 $alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };';
1122 }
1123 } else {
1124 $alertMsgOnChange = '';
1125 }
1126 // Render as a hidden field?
1127 if (in_array($field, $this->hiddenFieldListArr)) {
1128 $this->hiddenFieldAccum[] = '<input type="hidden" name="' . $PA['itemFormElName'] . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
1129 } else {
1130 // Render as a normal field:
1131 // 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.
1132 $palJSfunc = '';
1133 $thePalIcon = '';
1134 if (!$PA['palette']) {
1135 $paletteFields = $this->loadPaletteElements($table, $row, $PA['pal']);
1136 if ($PA['pal'] && $this->isPalettesCollapsed($table, $PA['pal']) && count($paletteFields)) {
1137 list($thePalIcon, $palJSfunc) = $this->wrapOpenPalette(IconUtility::getSpriteIcon('actions-system-options-view', array('title' => htmlspecialchars($this->getLL('l_moreOptions')))), $table, $row, $PA['pal'], 1);
1138 }
1139 }
1140 // onFocus attribute to add to the field:
1141 $PA['onFocus'] = $palJSfunc && !$this->getBackendUserAuthentication()->uc['dontShowPalettesOnFocusInAB'] ? ' onfocus="' . htmlspecialchars($palJSfunc) . '"' : '';
1142 $PA['label'] = $PA['altName'] ?: $PA['fieldConf']['label'];
1143 $PA['label'] = $PA['fieldTSConfig']['label'] ?: $PA['label'];
1144 $PA['label'] = $PA['fieldTSConfig']['label.'][$this->getLanguageService()->lang] ?: $PA['label'];
1145 $PA['label'] = $this->sL($PA['label']);
1146 // JavaScript code for event handlers:
1147 $PA['fieldChangeFunc'] = array();
1148 $PA['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'TBE_EDITOR.fieldChanged(\'' . $table . '\',\'' . $row['uid'] . '\',\'' . $field . '\',\'' . $PA['itemFormElName'] . '\');';
1149 $PA['fieldChangeFunc']['alert'] = $alertMsgOnChange;
1150 // If this is the child of an inline type and it is the field creating the label
1151 if ($this->inline->isInlineChildAndLabelField($table, $field)) {
1152 $inlineObjectId = implode(InlineElement::Structure_Separator, array(
1153 $this->inline->inlineNames['object'],
1154 $table,
1155 $row['uid']
1156 ));
1157 $PA['fieldChangeFunc']['inline'] = 'inline.handleChangedField(\'' . $PA['itemFormElName'] . '\',\'' . $inlineObjectId . '\');';
1158 }
1159 // Based on the type of the item, call a render function:
1160 $item = $this->getSingleField_SW($table, $field, $row, $PA);
1161 // Add language + diff
1162 if ($PA['fieldConf']['l10n_display'] && (GeneralUtility::inList($PA['fieldConf']['l10n_display'], 'hideDiff') || GeneralUtility::inList($PA['fieldConf']['l10n_display'], 'defaultAsReadonly'))) {
1163 $renderLanguageDiff = FALSE;
1164 } else {
1165 $renderLanguageDiff = TRUE;
1166 }
1167 if ($renderLanguageDiff) {
1168 $item = $this->renderDefaultLanguageContent($table, $field, $row, $item);
1169 $item = $this->renderDefaultLanguageDiff($table, $field, $row, $item);
1170 }
1171 // 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
1172 $label = htmlspecialchars($PA['label'], ENT_COMPAT, 'UTF-8', FALSE);
1173 if (MathUtility::canBeInterpretedAsInteger($row['uid']) && $PA['fieldTSConfig']['linkTitleToSelf'] && !GeneralUtility::_GP('columnsOnly')) {
1174 $lTTS_url = $this->backPath . 'alt_doc.php?edit[' . $table . '][' . $row['uid'] . ']=edit&columnsOnly=' . $field . '&returnUrl=' . rawurlencode($this->thisReturnUrl());
1175 $label = '<a href="' . htmlspecialchars($lTTS_url) . '">' . $label . '</a>';
1176 }
1177
1178 if (isset($PA['fieldConf']['config']['mode']) && $PA['fieldConf']['config']['mode'] == 'useOrOverridePlaceholder') {
1179 $placeholder = $this->getPlaceholderValue($table, $field, $PA['fieldConf']['config'], $row);
1180 $onChange = 'typo3form.fieldTogglePlaceholder(' . GeneralUtility::quoteJSvalue($PA['itemFormElName']) . ', !this.checked)';
1181 $checked = $PA['itemFormElValue'] === NULL ? '' : ' checked="checked"';
1182
1183 $this->additionalJS_post[] = 'typo3form.fieldTogglePlaceholder('
1184 . GeneralUtility::quoteJSvalue($PA['itemFormElName']) . ', ' . ($checked ? 'false' : 'true') . ');';
1185
1186 $item = '<div class="t3-form-field-placeholder-override">'
1187 . '<span class="t3-tceforms-placeholder-override-checkbox">' .
1188 '<input type="hidden" name="' . htmlspecialchars($PA['itemFormElNameActive']) . '" value="0" />' .
1189 '<input type="checkbox" name="' . htmlspecialchars($PA['itemFormElNameActive']) . '" value="1" id="tce-forms-textfield-use-override-' . $field . '-' . $row['uid'] . '" onchange="' . htmlspecialchars($onChange) . '"' . $checked . ' />' .
1190 '<label for="tce-forms-textfield-use-override-' . $field . '-' . $row['uid'] . '">' .
1191 sprintf($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.placeholder.override'),
1192 BackendUtility::getRecordTitlePrep($placeholder, 20)) . '</label>' .
1193 '</span>'
1194 . '<div class="t3-form-placeholder-placeholder">' . $this->getSingleField_typeNone_render(
1195 $PA['fieldConf']['config'], GeneralUtility::fixed_lgd_cs($placeholder, 30)
1196 ) . '</div>'
1197 . '<div class="t3-form-placeholder-formfield">' . $item . '</div>'
1198 . '</div>';
1199 }
1200
1201 // Wrap the label with help text
1202 $PA['label'] = ($label = BackendUtility::wrapInHelp($table, $field, $label));
1203 // Create output value:
1204 if ($PA['fieldConf']['config']['form_type'] == 'user' && $PA['fieldConf']['config']['noTableWrapping']) {
1205 $out = $item;
1206 } elseif ($PA['palette']) {
1207 // Array:
1208 $out = array(
1209 'NAME' => $label,
1210 'ID' => $row['uid'],
1211 'FIELD' => $field,
1212 'TABLE' => $table,
1213 'ITEM' => $item,
1214 'ITEM_DISABLED' => ($this->isDisabledNullValueField($table, $field, $row, $PA) ? ' disabled' : ''),
1215 'ITEM_NULLVALUE' => $this->renderNullValueWidget($table, $field, $row, $PA),
1216 );
1217 $out = $this->addUserTemplateMarkers($out, $table, $field, $row, $PA);
1218 } else {
1219 // String:
1220 $out = array(
1221 'NAME' => $label,
1222 'ITEM' => $item,
1223 'TABLE' => $table,
1224 'ID' => $row['uid'],
1225 'PAL_LINK_ICON' => $thePalIcon,
1226 'FIELD' => $field,
1227 'ITEM_DISABLED' => ($this->isDisabledNullValueField($table, $field, $row, $PA) ? ' disabled' : ''),
1228 'ITEM_NULLVALUE' => $this->renderNullValueWidget($table, $field, $row, $PA),
1229 );
1230 $out = $this->addUserTemplateMarkers($out, $table, $field, $row, $PA);
1231 // String:
1232 $out = $this->intoTemplate($out);
1233 }
1234 }
1235 } else {
1236 $this->commentMessages[] = $this->prependFormFieldNames . '[' . $table . '][' . $row['uid'] . '][' . $field . ']: Disabled by TSconfig';
1237 }
1238 }
1239 // Hook: getSingleField_postProcess
1240 foreach ($this->hookObjectsSingleField as $hookObj) {
1241 if (method_exists($hookObj, 'getSingleField_postProcess')) {
1242 $hookObj->getSingleField_postProcess($table, $field, $row, $out, $PA, $this);
1243 }
1244 }
1245 // Return value (string or array)
1246 return $out;
1247 }
1248
1249 /**
1250 * Rendering a single item for the form
1251 *
1252 * @param string $table Table name of record
1253 * @param string $field Fieldname to render
1254 * @param array $row The record
1255 * @param array $PA Parameters array containing a lot of stuff. Value by Reference!
1256 * @return string Returns the item as HTML code to insert
1257 * @access private
1258 * @see getSingleField(), getSingleField_typeFlex_draw()
1259 */
1260 public function getSingleField_SW($table, $field, $row, &$PA) {
1261 $PA['fieldConf']['config']['form_type'] = $PA['fieldConf']['config']['form_type'] ?: $PA['fieldConf']['config']['type'];
1262 // Using "form_type" locally in this script
1263 // Hook: getSingleField_beforeRender
1264 foreach ($this->hookObjectsSingleField as $hookObject) {
1265 if (method_exists($hookObject, 'getSingleField_beforeRender')) {
1266 $hookObject->getSingleField_beforeRender($table, $field, $row, $PA);
1267 }
1268 }
1269 $type = $PA['fieldConf']['config']['form_type'];
1270 if ($type === 'inline') {
1271 $item = $this->inline->getSingleField_typeInline($table, $field, $row, $PA);
1272 } else {
1273 $typeClassNameMapping = array(
1274 'input' => 'InputElement',
1275 'text' => 'TextElement',
1276 'check' => 'CheckboxElement',
1277 'radio' => 'RadioElement',
1278 'select' => 'SelectElement',
1279 'group' => 'GroupElement',
1280 'none' => 'NoneElement',
1281 'user' => 'UserElement',
1282 'flex' => 'FlexElement',
1283 'unknown' => 'UnknownElement',
1284 );
1285 if (!isset($typeClassNameMapping[$type])) {
1286 $type = 'unknown';
1287 }
1288 $item = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\Element\\' . $typeClassNameMapping[$type], $this)
1289 ->render($table, $field, $row, $PA);
1290 }
1291 return $item;
1292 }
1293
1294 /**********************************************************
1295 *
1296 * Rendering of each TCEform field type
1297 *
1298 ************************************************************/
1299 /**
1300 * Generation of TCEform elements of the type "input"
1301 * This will render a single-line input form field, possibly with various control/validation features
1302 *
1303 * @param string $table The table name of the record
1304 * @param string $field The field name which this element is supposed to edit
1305 * @param array $row The record data array where the value(s) for the field can be found
1306 * @param array $PA An array with additional configuration options.
1307 * @return string The HTML code for the TCEform field
1308 * @deprecated since 7.0 - will be removed two versions later; Use \TYPO3\CMS\Backend\Form\Element\InputElement
1309 */
1310 public function getSingleField_typeInput($table, $field, $row, &$PA) {
1311 GeneralUtility::logDeprecatedFunction();
1312 return $item = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\Element\\InputElement', $this)
1313 ->render($table, $field, $row, $PA);
1314 }
1315
1316 /**
1317 * Renders a view widget to handle and activate NULL values.
1318 * The widget is enabled by using 'null' in the 'eval' TCA definition.
1319 *
1320 * @param string $table Name of the table
1321 * @param string $field Name of the field
1322 * @param array $row Accordant data of the record row
1323 * @param array $PA Parameters array with rendering instructions
1324 * @return string Widget (if any).
1325 */
1326 protected function renderNullValueWidget($table, $field, array $row, array $PA) {
1327 $widget = '';
1328
1329 $config = $PA['fieldConf']['config'];
1330 if (
1331 !empty($config['eval']) && GeneralUtility::inList($config['eval'], 'null')
1332 && (empty($config['mode']) || $config['mode'] !== 'useOrOverridePlaceholder')
1333 ) {
1334 $checked = $PA['itemFormElValue'] === NULL ? '' : ' checked="checked"';
1335 $onChange = htmlspecialchars(
1336 'typo3form.fieldSetNull(\'' . $PA['itemFormElName'] . '\', !this.checked)'
1337 );
1338
1339 $widget = '<span class="t3-tceforms-widget-null-wrapper">' .
1340 '<input type="hidden" name="' . $PA['itemFormElNameActive'] . '" value="0" />' .
1341 '<input type="checkbox" name="' . $PA['itemFormElNameActive'] . '" value="1" onchange="' . $onChange . '"' . $checked . ' />' .
1342 '</span>';
1343 }
1344
1345 return $widget;
1346 }
1347
1348 /**
1349 * Determines whether the current field value is considered as NULL value.
1350 * Using NULL values is enabled by using 'null' in the 'eval' TCA definition.
1351 *
1352 * @param string $table Name of the table
1353 * @param string $field Name of the field
1354 * @param array $row Accordant data
1355 * @param array $PA Parameters array with rendering instructions
1356 * @return bool
1357 */
1358 protected function isDisabledNullValueField($table, $field, array $row, array $PA) {
1359 $result = FALSE;
1360
1361 $config = $PA['fieldConf']['config'];
1362 if ($PA['itemFormElValue'] === NULL && !empty($config['eval'])
1363 && GeneralUtility::inList($config['eval'], 'null')
1364 && (empty($config['mode']) || $config['mode'] !== 'useOrOverridePlaceholder')) {
1365
1366 $result = TRUE;
1367 }
1368
1369 return $result;
1370 }
1371
1372 /**
1373 * Generation of TCEform elements of the type "text"
1374 * This will render a <textarea> OR RTE area form field, possibly with various control/validation features
1375 *
1376 * @param string $table The table name of the record
1377 * @param string $field The field name which this element is supposed to edit
1378 * @param array $row The record data array where the value(s) for the field can be found
1379 * @param array $PA An array with additional configuration options.
1380 * @return string The HTML code for the TCEform field
1381 * @deprecated since 7.0 - will be removed two versions later; Use \TYPO3\CMS\Backend\Form\Element\TextElement
1382 */
1383 public function getSingleField_typeText($table, $field, $row, &$PA) {
1384 GeneralUtility::logDeprecatedFunction();
1385 return $item = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\Element\\TextElement', $this)
1386 ->render($table, $field, $row, $PA);
1387 }
1388
1389 /**
1390 * Generation of TCEform elements of the type "check"
1391 * This will render a check-box OR an array of checkboxes
1392 *
1393 * @param string $table The table name of the record
1394 * @param string $field The field name which this element is supposed to edit
1395 * @param array $row The record data array where the value(s) for the field can be found
1396 * @param array $PA An array with additional configuration options.
1397 * @return string The HTML code for the TCEform field
1398 * @deprecated since 7.0 - will be removed two versions later; Use \TYPO3\CMS\Backend\Form\Element\CheckboxElement
1399 */
1400 public function getSingleField_typeCheck($table, $field, $row, &$PA) {
1401 GeneralUtility::logDeprecatedFunction();
1402 return $item = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\Element\\CheckboxElement', $this)
1403 ->render($table, $field, $row, $PA);
1404 }
1405
1406 /**
1407 * Generation of TCEform elements of the type "radio"
1408 * This will render a series of radio buttons.
1409 *
1410 * @param string $table The table name of the record
1411 * @param string $field The field name which this element is supposed to edit
1412 * @param array $row The record data array where the value(s) for the field can be found
1413 * @param array $PA An array with additional configuration options.
1414 * @return string The HTML code for the TCEform field
1415 * @deprecated since 7.0 - will be removed two versions later; Use \TYPO3\CMS\Backend\Form\Element\RadioElement
1416 */
1417 public function getSingleField_typeRadio($table, $field, $row, &$PA) {
1418 GeneralUtility::logDeprecatedFunction();
1419 return $item = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\Element\\RadioElement', $this)
1420 ->render($table, $field, $row, $PA);
1421 }
1422
1423 /**
1424 * Generation of TCEform elements of the type "select"
1425 * This will render a selector box element, or possibly a special construction with two selector boxes.
1426 * That depends on configuration.
1427 *
1428 * @param string $table The table name of the record
1429 * @param string $field The field name which this element is supposed to edit
1430 * @param array $row The record data array where the value(s) for the field can be found
1431 * @param array $PA An array with additional configuration options.
1432 * @return string The HTML code for the TCEform field
1433 * @deprecated since 7.0 - will be removed two versions later; Use \TYPO3\CMS\Backend\Form\Element\SelectElement
1434 */
1435 public function getSingleField_typeSelect($table, $field, $row, &$PA) {
1436 GeneralUtility::logDeprecatedFunction();
1437 return $item = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\Element\\SelectElement', $this)
1438 ->render($table, $field, $row, $PA);
1439 }
1440
1441 /**
1442 * Generation of TCEform elements of the type "group"
1443 * This will render a selectorbox into which elements from either the file system or database can be inserted. Relations.
1444 *
1445 * @param string $table The table name of the record
1446 * @param string $field The field name which this element is supposed to edit
1447 * @param array $row The record data array where the value(s) for the field can be found
1448 * @param array $PA An array with additional configuration options.
1449 * @return string The HTML code for the TCEform field
1450 * @deprecated since 7.0 - will be removed two versions later; Use \TYPO3\CMS\Backend\Form\Element\GroupElement
1451 */
1452 public function getSingleField_typeGroup($table, $field, $row, &$PA) {
1453 GeneralUtility::logDeprecatedFunction();
1454 return $item = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\Element\\GroupElement', $this)
1455 ->render($table, $field, $row, $PA);
1456 }
1457
1458 /**
1459 * Generation of TCEform elements of the type "none"
1460 * This will render a non-editable display of the content of the field.
1461 *
1462 * @param string $table The table name of the record
1463 * @param string $field The field name which this element is supposed to edit
1464 * @param array $row The record data array where the value(s) for the field can be found
1465 * @param array $PA An array with additional configuration options.
1466 * @return string The HTML code for the TCEform field
1467 * @deprecated since 7.0 - will be removed two versions later; Use \TYPO3\CMS\Backend\Form\Element\NoneElement
1468 */
1469 public function getSingleField_typeNone($table, $field, $row, &$PA) {
1470 GeneralUtility::logDeprecatedFunction();
1471 return $item = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\Element\\NoneElement', $this)
1472 ->render($table, $field, $row, $PA);
1473 }
1474
1475 /**
1476 * HTML rendering of a value which is not editable.
1477 *
1478 * @param array $config Configuration for the display
1479 * @param string $itemValue The value to display
1480 * @return string The HTML code for the display
1481 * @see getSingleField_typeNone();
1482 */
1483 public function getSingleField_typeNone_render($config, $itemValue) {
1484 if ($config['format']) {
1485 $itemValue = $this->formatValue($config, $itemValue);
1486 }
1487 $rows = (int)$config['rows'];
1488 if ($rows > 1) {
1489 if (!$config['pass_content']) {
1490 $itemValue = nl2br(htmlspecialchars($itemValue));
1491 }
1492 // Like textarea
1493 $cols = MathUtility::forceIntegerInRange($config['cols'] ? $config['cols'] : 30, 5, $this->maxTextareaWidth);
1494 if (!$config['fixedRows']) {
1495 $origRows = ($rows = MathUtility::forceIntegerInRange($rows, 1, 20));
1496 if (strlen($itemValue) > $this->charsPerRow * 2) {
1497 $cols = $this->maxTextareaWidth;
1498 $rows = MathUtility::forceIntegerInRange(round(strlen($itemValue) / $this->charsPerRow), count(explode(LF, $itemValue)), 20);
1499 if ($rows < $origRows) {
1500 $rows = $origRows;
1501 }
1502 }
1503 }
1504
1505 $cols = round($cols * $this->form_largeComp);
1506 $width = ceil($cols * $this->form_rowsToStylewidth);
1507 // Hardcoded: 12 is the height of the font
1508 $height = $rows * 12;
1509 $item = '
1510 <div style="overflow:auto; height:' . $height . 'px; width:' . $width . 'px;" class="t3-tceforms-fieldReadOnly">'
1511 . $itemValue . IconUtility::getSpriteIcon('status-status-readonly') . '</div>';
1512 } else {
1513 if (!$config['pass_content']) {
1514 $itemValue = htmlspecialchars($itemValue);
1515 }
1516 $cols = $config['cols'] ? $config['cols'] : ($config['size'] ? $config['size'] : $this->maxInputWidth);
1517 $cols = round($cols * $this->form_largeComp);
1518 $width = ceil($cols * $this->form_rowsToStylewidth);
1519 // Overflow:auto crashes mozilla here. Title tag is useful when text is longer than the div box (overflow:hidden).
1520 $item = '
1521 <div style="overflow:hidden; width:' . $width . 'px;" class="t3-tceforms-fieldReadOnly" title="' . $itemValue . '">'
1522 . '<span class="nobr">' . ((string)$itemValue !== '' ? $itemValue : '&nbsp;') . '</span>'
1523 . IconUtility::getSpriteIcon('status-status-readonly') . '</div>';
1524 }
1525 return $item;
1526 }
1527
1528 /**
1529 * Handler for Flex Forms
1530 *
1531 * @param string $table The table name of the record
1532 * @param string $field The field name which this element is supposed to edit
1533 * @param array $row The record data array where the value(s) for the field can be found
1534 * @param array $PA An array with additional configuration options.
1535 * @return string The HTML code for the TCEform field
1536 * @deprecated since 7.0 - will be removed two versions later; Use \TYPO3\CMS\Backend\Form\Element\FlexElement
1537 */
1538 public function getSingleField_typeFlex($table, $field, $row, &$PA) {
1539 GeneralUtility::logDeprecatedFunction();
1540 return $item = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\Element\\FlexElement', $this)
1541 ->render($table, $field, $row, $PA);
1542 }
1543
1544 /**
1545 * Creates the language menu for FlexForms:
1546 *
1547 * @param array $languages
1548 * @param string $elName
1549 * @param array $selectedLanguage
1550 * @param bool $multi
1551 * @return string HTML for menu
1552 */
1553 public function getSingleField_typeFlex_langMenu($languages, $elName, $selectedLanguage, $multi = TRUE) {
1554 $opt = array();
1555 foreach ($languages as $lArr) {
1556 $opt[] = '<option value="' . htmlspecialchars($lArr['ISOcode']) . '"'
1557 . (in_array($lArr['ISOcode'], $selectedLanguage) ? ' selected="selected"' : '') . '>'
1558 . htmlspecialchars($lArr['title']) . '</option>';
1559 }
1560 $output = '<select id="' . str_replace('.', '', uniqid('tceforms-multiselect-', TRUE))
1561 . ' class="tceforms-select tceforms-multiselect tceforms-flexlangmenu" name="' . $elName . '[]"'
1562 . ($multi ? ' multiple="multiple" size="' . count($languages) . '"' : '') . '>' . implode('', $opt)
1563 . '</select>';
1564 return $output;
1565 }
1566
1567 /**
1568 * Creates the menu for selection of the sheets:
1569 *
1570 * @param array $sArr Sheet array for which to render the menu
1571 * @param string $elName Form element name of the field containing the sheet pointer
1572 * @param string $sheetKey Current sheet key
1573 * @return string HTML for menu
1574 */
1575 public function getSingleField_typeFlex_sheetMenu($sArr, $elName, $sheetKey) {
1576 $tCells = array();
1577 $pct = round(100 / count($sArr));
1578 foreach ($sArr as $sKey => $sheetCfg) {
1579 if ($this->getBackendUserAuthentication()->jsConfirmation(1)) {
1580 $onClick = 'if (confirm(TBE_EDITOR.labels.onChangeAlert) && TBE_EDITOR.checkSubmit(-1)){'
1581 . $this->elName($elName) . '.value=\'' . $sKey . '\'; TBE_EDITOR.submitForm()};';
1582 } else {
1583 $onClick = 'if(TBE_EDITOR.checkSubmit(-1)){ ' . $this->elName($elName) . '.value=\'' . $sKey . '\'; TBE_EDITOR.submitForm();}';
1584 }
1585 $tCells[] = '<td width="' . $pct . '%" style="'
1586 . ($sKey == $sheetKey ? 'background-color: #9999cc; font-weight: bold;' : 'background-color: #aaaaaa;')
1587 . ' cursor: hand;" onclick="' . htmlspecialchars($onClick) . '" align="center">'
1588 . ($sheetCfg['ROOT']['TCEforms']['sheetTitle'] ? $this->sL($sheetCfg['ROOT']['TCEforms']['sheetTitle']) : $sKey)
1589 . '</td>';
1590 }
1591 return '<table border="0" cellpadding="0" cellspacing="2" class="typo3-TCEforms-flexForm-sheetMenu"><tr>' . implode('', $tCells) . '</tr></table>';
1592 }
1593
1594 /**
1595 * Handler for unknown types.
1596 *
1597 * @param string $table The table name of the record
1598 * @param string $field The field name which this element is supposed to edit
1599 * @param array $row The record data array where the value(s) for the field can be found
1600 * @param array $PA An array with additional configuration options.
1601 * @return string The HTML code for the TCEform field
1602 * @deprecated since 7.0 - will be removed two versions later; Use \TYPO3\CMS\Backend\Form\Element\UnknownElement
1603 */
1604 public function getSingleField_typeUnknown($table, $field, $row, &$PA) {
1605 GeneralUtility::logDeprecatedFunction();
1606 return $item = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\Element\\UnknownElement', $this)
1607 ->render($table, $field, $row, $PA);
1608 }
1609
1610 /**
1611 * User defined field type
1612 *
1613 * @param string $table The table name of the record
1614 * @param string $field The field name which this element is supposed to edit
1615 * @param array $row The record data array where the value(s) for the field can be found
1616 * @param array $PA An array with additional configuration options.
1617 * @return string The HTML code for the TCEform field
1618 * @deprecated since 7.0 - will be removed two versions later; Use \TYPO3\CMS\Backend\Form\Element\UserElement
1619 */
1620 public function getSingleField_typeUser($table, $field, $row, &$PA) {
1621 GeneralUtility::logDeprecatedFunction();
1622 return $item = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\Element\\UserElement', $this)
1623 ->render($table, $field, $row, $PA);
1624 }
1625
1626 /************************************************************
1627 *
1628 * Field content processing
1629 *
1630 ************************************************************/
1631 /**
1632 * Format field content of various types if $config['format'] is set to date, filesize, ..., user
1633 * This is primarily for the field type none but can be used for user field types for example
1634 *
1635 * @param array $config Configuration for the display
1636 * @param string $itemValue The value to display
1637 * @return string Formatted Field content
1638 */
1639 public function formatValue($config, $itemValue) {
1640 $format = trim($config['format']);
1641 switch ($format) {
1642 case 'date':
1643 if ($itemValue) {
1644 $option = trim($config['format.']['option']);
1645 if ($option) {
1646 if ($config['format.']['strftime']) {
1647 $value = strftime($option, $itemValue);
1648 } else {
1649 $value = date($option, $itemValue);
1650 }
1651 } else {
1652 $value = date('d-m-Y', $itemValue);
1653 }
1654 } else {
1655 $value = '';
1656 }
1657 if ($config['format.']['appendAge']) {
1658 $age = BackendUtility::calcAge(
1659 $GLOBALS['EXEC_TIME'] - $itemValue,
1660 $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysYears')
1661 );
1662 $value .= ' (' . $age . ')';
1663 }
1664 $itemValue = $value;
1665 break;
1666 case 'datetime':
1667 // compatibility with "eval" (type "input")
1668 $itemValue = date('H:i d-m-Y', $itemValue);
1669 break;
1670 case 'time':
1671 // compatibility with "eval" (type "input")
1672 $itemValue = date('H:i', $itemValue);
1673 break;
1674 case 'timesec':
1675 // compatibility with "eval" (type "input")
1676 $itemValue = date('H:i:s', $itemValue);
1677 break;
1678 case 'year':
1679 // compatibility with "eval" (type "input")
1680 $itemValue = date('Y', $itemValue);
1681 break;
1682 case 'int':
1683 $baseArr = array('dec' => 'd', 'hex' => 'x', 'HEX' => 'X', 'oct' => 'o', 'bin' => 'b');
1684 $base = trim($config['format.']['base']);
1685 $format = $baseArr[$base] ? $baseArr[$base] : 'd';
1686 $itemValue = sprintf('%' . $format, $itemValue);
1687 break;
1688 case 'float':
1689 $precision = MathUtility::forceIntegerInRange($config['format.']['precision'], 1, 10, 2);
1690 $itemValue = sprintf('%.' . $precision . 'f', $itemValue);
1691 break;
1692 case 'number':
1693 $format = trim($config['format.']['option']);
1694 $itemValue = sprintf('%' . $format, $itemValue);
1695 break;
1696 case 'md5':
1697 $itemValue = md5($itemValue);
1698 break;
1699 case 'filesize':
1700 $value = GeneralUtility::formatSize((int)$itemValue);
1701 if ($config['format.']['appendByteSize']) {
1702 $value .= ' (' . $itemValue . ')';
1703 }
1704 $itemValue = $value;
1705 break;
1706 case 'user':
1707 $func = trim($config['format.']['userFunc']);
1708 if ($func) {
1709 $params = array(
1710 'value' => $itemValue,
1711 'args' => $config['format.']['userFunc'],
1712 'config' => $config,
1713 'pObj' => &$this
1714 );
1715 $itemValue = GeneralUtility::callUserFunction($func, $params, $this);
1716 }
1717 break;
1718 default:
1719 // Do nothing
1720 }
1721 return $itemValue;
1722 }
1723
1724 /************************************************************
1725 *
1726 * "Configuration" fetching/processing functions
1727 *
1728 ************************************************************/
1729 /**
1730 * Calculate and return the current "types" pointer value for a record
1731 *
1732 * @param string $table The table name. MUST be in $GLOBALS['TCA']
1733 * @param array $row The row from the table, should contain at least the "type" field, if applicable.
1734 * @return string Return the "type" value for this record, ready to pick a "types" configuration from the $GLOBALS['TCA'] array.
1735 * @throws \RuntimeException
1736 */
1737 public function getRTypeNum($table, $row) {
1738 $typeNum = 0;
1739 $field = $GLOBALS['TCA'][$table]['ctrl']['type'];
1740 if ($field) {
1741 if (strpos($field, ':') !== FALSE) {
1742 list($pointerField, $foreignTypeField) = explode(':', $field);
1743 $fieldConfig = $GLOBALS['TCA'][$table]['columns'][$pointerField]['config'];
1744 $relationType = $fieldConfig['type'];
1745 if ($relationType === 'select') {
1746 $foreignUid = $row[$pointerField];
1747 $foreignTable = $fieldConfig['foreign_table'];
1748 } elseif ($relationType === 'group') {
1749 $values = $this->extractValuesOnlyFromValueLabelList($row[$pointerField]);
1750 list(, $foreignUid) = GeneralUtility::revExplode('_', $values[0], 2);
1751 $allowedTables = explode(',', $fieldConfig['allowed']);
1752 // Always take the first configured table.
1753 $foreignTable = $allowedTables[0];
1754 } else {
1755 throw new \RuntimeException('TCA Foreign field pointer fields are only allowed to be used with group or select field types.', 1325861239);
1756 }
1757 if ($foreignUid) {
1758 $foreignRow = BackendUtility::getRecord($foreignTable, $foreignUid, $foreignTypeField);
1759 $this->registerDefaultLanguageData($foreignTable, $foreignRow);
1760 if ($foreignRow[$foreignTypeField]) {
1761 $foreignTypeFieldConfig = $GLOBALS['TCA'][$table]['columns'][$field];
1762 $typeNum = $this->getLanguageOverlayRawValue($foreignTable, $foreignRow, $foreignTypeField, $foreignTypeFieldConfig);
1763 }
1764 }
1765 } else {
1766 $typeFieldConfig = $GLOBALS['TCA'][$table]['columns'][$field];
1767 $typeNum = $this->getLanguageOverlayRawValue($table, $row, $field, $typeFieldConfig);
1768 }
1769 }
1770 if (empty($typeNum)) {
1771 // If that value is an empty string, set it to "0" (zero)
1772 $typeNum = 0;
1773 }
1774 // If current typeNum doesn't exist, set it to 0 (or to 1 for historical reasons, if 0 doesn't exist)
1775 if (!$GLOBALS['TCA'][$table]['types'][$typeNum]) {
1776 $typeNum = $GLOBALS['TCA'][$table]['types']['0'] ? 0 : 1;
1777 }
1778 // Force to string. Necessary for eg '-1' to be recognized as a type value.
1779 $typeNum = (string) $typeNum;
1780 return $typeNum;
1781 }
1782
1783 /**
1784 * Used to adhoc-rearrange the field order normally set in the [types][showitem] list
1785 *
1786 * @param array $fields A [types][showitem] list of fields, exploded by ",
1787 * @return array Returns rearranged version (keys are changed around as well.)
1788 * @see getMainFields()
1789 */
1790 public function rearrange($fields) {
1791 $fO = array_flip(GeneralUtility::trimExplode(',', $this->fieldOrder, TRUE));
1792 $newFields = array();
1793 foreach ($fields as $cc => $content) {
1794 $cP = GeneralUtility::trimExplode(';', $content);
1795 if (isset($fO[$cP[0]])) {
1796 $newFields[$fO[$cP[0]]] = $content;
1797 unset($fields[$cc]);
1798 }
1799 }
1800 ksort($newFields);
1801 // Candidate for GeneralUtility::array_merge() if integer-keys will some day make trouble...
1802 $fields = array_merge($newFields, $fields);
1803 return $fields;
1804 }
1805
1806 /**
1807 * Producing an array of field names NOT to display in the form,
1808 * based on settings from subtype_value_field, bitmask_excludelist_bits etc.
1809 * Notice, this list is in NO way related to the "excludeField" flag
1810 *
1811 * @param string $table Table name, MUST be in $GLOBALS['TCA']
1812 * @param array $row A record from table.
1813 * @param string $typeNum A "type" pointer value, probably the one calculated based on the record array.
1814 * @return array Array with fieldnames as values. The fieldnames are those which should NOT be displayed "anyways
1815 * @see getMainFields()
1816 */
1817 public function getExcludeElements($table, $row, $typeNum) {
1818 // Init:
1819 $excludeElements = array();
1820 // If a subtype field is defined for the type
1821 if ($GLOBALS['TCA'][$table]['types'][$typeNum]['subtype_value_field']) {
1822 $sTfield = $GLOBALS['TCA'][$table]['types'][$typeNum]['subtype_value_field'];
1823 if (trim($GLOBALS['TCA'][$table]['types'][$typeNum]['subtypes_excludelist'][$row[$sTfield]])) {
1824 $excludeElements = GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$table]['types'][$typeNum]['subtypes_excludelist'][$row[$sTfield]], TRUE);
1825 }
1826 }
1827 // If a bitmask-value field has been configured, then find possible fields to exclude based on that:
1828 if ($GLOBALS['TCA'][$table]['types'][$typeNum]['bitmask_value_field']) {
1829 $sTfield = $GLOBALS['TCA'][$table]['types'][$typeNum]['bitmask_value_field'];
1830 $sTValue = MathUtility::forceIntegerInRange($row[$sTfield], 0);
1831 if (is_array($GLOBALS['TCA'][$table]['types'][$typeNum]['bitmask_excludelist_bits'])) {
1832 foreach ($GLOBALS['TCA'][$table]['types'][$typeNum]['bitmask_excludelist_bits'] as $bitKey => $eList) {
1833 $bit = substr($bitKey, 1);
1834 if (MathUtility::canBeInterpretedAsInteger($bit)) {
1835 $bit = MathUtility::forceIntegerInRange($bit, 0, 30);
1836 if ($bitKey[0] === '-' && !($sTValue & pow(2, $bit)) || $bitKey[0] === '+' && $sTValue & pow(2, $bit)) {
1837 $excludeElements = array_merge($excludeElements, GeneralUtility::trimExplode(',', $eList, TRUE));
1838 }
1839 }
1840 }
1841 }
1842 }
1843 // Return the array of elements:
1844 return $excludeElements;
1845 }
1846
1847 /**
1848 * Finds possible field to add to the form, based on subtype fields.
1849 *
1850 * @param string $table Table name, MUST be in $GLOBALS['TCA']
1851 * @param array $row A record from table.
1852 * @param string $typeNum A "type" pointer value, probably the one calculated based on the record array.
1853 * @return array An array containing two values: 1) Another array containing field names to add and 2) the subtype value field.
1854 * @see getMainFields()
1855 */
1856 public function getFieldsToAdd($table, $row, $typeNum) {
1857 // Init:
1858 $addElements = array();
1859 // If a subtype field is defined for the type
1860 $sTfield = '';
1861 if ($GLOBALS['TCA'][$table]['types'][$typeNum]['subtype_value_field']) {
1862 $sTfield = $GLOBALS['TCA'][$table]['types'][$typeNum]['subtype_value_field'];
1863 if (trim($GLOBALS['TCA'][$table]['types'][$typeNum]['subtypes_addlist'][$row[$sTfield]])) {
1864 $addElements = GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$table]['types'][$typeNum]['subtypes_addlist'][$row[$sTfield]], TRUE);
1865 }
1866 }
1867 // Return the return
1868 return array($addElements, $sTfield);
1869 }
1870
1871 /**
1872 * Merges the current [types][showitem] array with the array of fields to add for the current subtype field of the "type" value.
1873 *
1874 * @param array $fields A [types][showitem] list of fields, exploded by ",
1875 * @param array $fieldsToAdd The output from getFieldsToAdd()
1876 * @param string $table The table name, if we want to consider it's palettes when positioning the new elements
1877 * @return array Return the modified $fields array.
1878 * @see getMainFields(),getFieldsToAdd()
1879 */
1880 public function mergeFieldsWithAddedFields($fields, $fieldsToAdd, $table = '') {
1881 if (count($fieldsToAdd[0])) {
1882 $c = 0;
1883 $found = FALSE;
1884 foreach ($fields as $fieldInfo) {
1885 list($fieldName, $label, $paletteName) = GeneralUtility::trimExplode(';', $fieldInfo);
1886 if ($fieldName === $fieldsToAdd[1]) {
1887 $found = TRUE;
1888 } elseif ($fieldName === '--palette--' && $paletteName && $table !== '') {
1889 // Look inside the palette
1890 if (is_array($GLOBALS['TCA'][$table]['palettes'][$paletteName])) {
1891 $itemList = $GLOBALS['TCA'][$table]['palettes'][$paletteName]['showitem'];
1892 if ($itemList) {
1893 $paletteFields = GeneralUtility::trimExplode(',', $itemList, TRUE);
1894 foreach ($paletteFields as $info) {
1895 $fieldParts = GeneralUtility::trimExplode(';', $info);
1896 $theField = $fieldParts[0];
1897 if ($theField === $fieldsToAdd[1]) {
1898 $found = TRUE;
1899 break 1;
1900 }
1901 }
1902 }
1903 }
1904 }
1905 if ($found) {
1906 array_splice($fields, $c + 1, 0, $fieldsToAdd[0]);
1907 break;
1908 }
1909 $c++;
1910 }
1911 }
1912 return $fields;
1913 }
1914
1915 /**
1916 * Returns TSconfig for table/row
1917 * Multiple requests to this function will return cached content so there is no performance loss in calling
1918 * this many times since the information is looked up only once.
1919 *
1920 * @param string $table The table name
1921 * @param array $row The table row (Should at least contain the "uid" value, even if "NEW..." string. The "pid" field is important as well, and negative values will be intepreted as pointing to a record from the same table.)
1922 * @param string $field Optionally you can specify the field name as well. In that case the TSconfig for the field is returned.
1923 * @return mixed The TSconfig values (probably in an array)
1924 * @see BackendUtility::getTCEFORM_TSconfig()
1925 */
1926 public function setTSconfig($table, $row, $field = '') {
1927 $mainKey = $table . ':' . $row['uid'];
1928 if (!isset($this->cachedTSconfig[$mainKey])) {
1929 $this->cachedTSconfig[$mainKey] = BackendUtility::getTCEFORM_TSconfig($table, $row);
1930 }
1931 if ($field) {
1932 return $this->cachedTSconfig[$mainKey][$field];
1933 } else {
1934 return $this->cachedTSconfig[$mainKey];
1935 }
1936 }
1937
1938 /**
1939 * Overrides the TCA field configuration by TSconfig settings.
1940 *
1941 * Example TSconfig: TCEform.<table>.<field>.config.appearance.useSortable = 1
1942 * This overrides the setting in $GLOBALS['TCA'][<table>]['columns'][<field>]['config']['appearance']['useSortable'].
1943 *
1944 * @param array $fieldConfig $GLOBALS['TCA'] field configuration
1945 * @param array $TSconfig TSconfig
1946 * @return array Changed TCA field configuration
1947 */
1948 public function overrideFieldConf($fieldConfig, $TSconfig) {
1949 if (is_array($TSconfig)) {
1950 $TSconfig = GeneralUtility::removeDotsFromTS($TSconfig);
1951 $type = $fieldConfig['type'];
1952 if (is_array($TSconfig['config']) && is_array($this->allowOverrideMatrix[$type])) {
1953 // Check if the keys in TSconfig['config'] are allowed to override TCA field config:
1954 foreach (array_keys($TSconfig['config']) as $key) {
1955 if (!in_array($key, $this->allowOverrideMatrix[$type], TRUE)) {
1956 unset($TSconfig['config'][$key]);
1957 }
1958 }
1959 // Override $GLOBALS['TCA'] field config by remaining TSconfig['config']:
1960 if (count($TSconfig['config'])) {
1961 ArrayUtility::mergeRecursiveWithOverrule($fieldConfig, $TSconfig['config']);
1962 }
1963 }
1964 }
1965 return $fieldConfig;
1966 }
1967
1968 /**
1969 * Returns the "special" configuration (from the "types" "showitem" list) for a fieldname based on input table/record
1970 * (Not used anywhere...?)
1971 *
1972 * @param string $table The table name
1973 * @param array $row The table row (Should at least contain the "uid" value, even if "NEW..." string. The "pid" field is important as well, and negative values will be intepreted as pointing to a record from the same table.)
1974 * @param string $field Specify the field name.
1975 * @return array|NULL
1976 * @see getSpecConfFromString(), BackendUtility::getTCAtypes()
1977 * @deprecated since 6.3 - will be removed two versions later; unused in Core
1978 */
1979 public function getSpecConfForField($table, $row, $field) {
1980 GeneralUtility::logDeprecatedFunction();
1981 // Finds the current "types" configuration for the table/row:
1982 $types_fieldConfig = BackendUtility::getTCAtypes($table, $row);
1983 // If this is an array, then traverse it:
1984 if (is_array($types_fieldConfig)) {
1985 foreach ($types_fieldConfig as $vconf) {
1986 // If the input field name matches one found in the 'types' list, then return the 'special' configuration.
1987 if ($vconf['field'] == $field) {
1988 return $vconf['spec'];
1989 }
1990 }
1991 }
1992 return NULL;
1993 }
1994
1995 /**
1996 * Returns the "special" configuration of an "extra" string (non-parsed)
1997 *
1998 * @param string $extraString The "Part 4" of the fields configuration in "types" "showitem" lists.
1999 * @param string $defaultExtras The ['defaultExtras'] value from field configuration
2000 * @return array An array with the special options in.
2001 * @see getSpecConfForField(), BackendUtility::getSpecConfParts()
2002 */
2003 public function getSpecConfFromString($extraString, $defaultExtras) {
2004 return BackendUtility::getSpecConfParts($extraString, $defaultExtras);
2005 }
2006
2007 /**
2008 * Loads the elements of a palette (collection of secondary options) in an array.
2009 *
2010 * @param string $table The table name
2011 * @param array $row The row array
2012 * @param string $palette The palette number/pointer
2013 * @param string $itemList Optional alternative list of fields for the palette
2014 * @return array The palette elements
2015 */
2016 public function loadPaletteElements($table, $row, $palette, $itemList = '') {
2017 $parts = array();
2018 // Getting excludeElements, if any.
2019 if (!is_array($this->excludeElements)) {
2020 $this->excludeElements = $this->getExcludeElements($table, $row, $this->getRTypeNum($table, $row));
2021 }
2022 // Load the palette TCEform elements
2023 if ($GLOBALS['TCA'][$table] && (is_array($GLOBALS['TCA'][$table]['palettes'][$palette]) || $itemList)) {
2024 $itemList = $itemList ? $itemList : $GLOBALS['TCA'][$table]['palettes'][$palette]['showitem'];
2025 if ($itemList) {
2026 $fields = GeneralUtility::trimExplode(',', $itemList, TRUE);
2027 foreach ($fields as $info) {
2028 $fieldParts = GeneralUtility::trimExplode(';', $info);
2029 $theField = $fieldParts[0];
2030 if ($theField === '--linebreak--') {
2031 $parts[]['NAME'] = '--linebreak--';
2032 } elseif (!in_array($theField, $this->excludeElements) && $GLOBALS['TCA'][$table]['columns'][$theField]) {
2033 $this->palFieldArr[$palette][] = $theField;
2034 $elem = $this->getSingleField($table, $theField, $row, $fieldParts[1], 1, '', $fieldParts[2]);
2035 if (is_array($elem)) {
2036 $parts[] = $elem;
2037 }
2038 }
2039 }
2040 }
2041 }
2042 return $parts;
2043 }
2044
2045 /************************************************************
2046 *
2047 * Display of localized content etc.
2048 *
2049 ************************************************************/
2050 /**
2051 * Will register data from original language records if the current record is a translation of another.
2052 * The original data is shown with the edited record in the form.
2053 * The information also includes possibly diff-views of what changed in the original record.
2054 * Function called from outside (see alt_doc.php + quick edit) before rendering a form for a record
2055 *
2056 * @param string $table Table name of the record being edited
2057 * @param array $rec Record array of the record being edited
2058 * @return void
2059 */
2060 public function registerDefaultLanguageData($table, $rec) {
2061 // Add default language:
2062 if (
2063 $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $rec[$GLOBALS['TCA'][$table]['ctrl']['languageField']] > 0
2064 && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']
2065 && (int)$rec[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] > 0
2066 ) {
2067 $lookUpTable = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable']
2068 ? $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable']
2069 : $table;
2070 // Get data formatted:
2071 $this->defaultLanguageData[$table . ':' . $rec['uid']] = BackendUtility::getRecordWSOL(
2072 $lookUpTable,
2073 (int)$rec[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']]
2074 );
2075 // Get data for diff:
2076 if ($GLOBALS['TCA'][$table]['ctrl']['transOrigDiffSourceField']) {
2077 $this->defaultLanguageData_diff[$table . ':' . $rec['uid']] = unserialize($rec[$GLOBALS['TCA'][$table]['ctrl']['transOrigDiffSourceField']]);
2078 }
2079 // If there are additional preview languages, load information for them also:
2080 $prLang = $this->getAdditionalPreviewLanguages();
2081 foreach ($prLang as $prL) {
2082 /** @var $t8Tools \TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider */
2083 $t8Tools = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Configuration\\TranslationConfigurationProvider');
2084 $tInfo = $t8Tools->translationInfo($lookUpTable, (int)$rec[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']], $prL['uid']);
2085 if (is_array($tInfo['translations']) && is_array($tInfo['translations'][$prL['uid']])) {
2086 $this->additionalPreviewLanguageData[$table . ':' . $rec['uid']][$prL['uid']] = BackendUtility::getRecordWSOL($table, (int)$tInfo['translations'][$prL['uid']]['uid']);
2087 }
2088 }
2089 }
2090 }
2091
2092 /**
2093 * Creates language-overlay for a field value
2094 * This means the requested field value will be overridden with the data from the default language.
2095 * Can be used to render read only fields for example.
2096 *
2097 * @param string $table Table name of the record being edited
2098 * @param array $row Record array of the record being edited in current language
2099 * @param string $field Field name represented by $item
2100 * @param array $fieldConf Content of $PA['fieldConf']
2101 * @return string Unprocessed field value merged with default language data if needed
2102 */
2103 public function getLanguageOverlayRawValue($table, $row, $field, $fieldConf) {
2104 $value = $row[$field];
2105 if (is_array($this->defaultLanguageData[$table . ':' . $row['uid']])) {
2106 if (
2107 $fieldConf['l10n_mode'] == 'exclude'
2108 || $fieldConf['l10n_mode'] == 'mergeIfNotBlank' && trim($this->defaultLanguageData[$table . ':' . $row['uid']][$field]) !== ''
2109 ) {
2110 $value = $this->defaultLanguageData[$table . ':' . $row['uid']][$field];
2111 }
2112 }
2113 return $value;
2114 }
2115
2116 /**
2117 * Renders the display of default language record content around current field.
2118 * Will render content if any is found in the internal array, $this->defaultLanguageData,
2119 * depending on registerDefaultLanguageData() being called prior to this.
2120 *
2121 * @param string $table Table name of the record being edited
2122 * @param string $field Field name represented by $item
2123 * @param array $row Record array of the record being edited
2124 * @param string $item HTML of the form field. This is what we add the content to.
2125 * @return string Item string returned again, possibly with the original value added to.
2126 * @see getSingleField(), registerDefaultLanguageData()
2127 */
2128 public function renderDefaultLanguageContent($table, $field, $row, $item) {
2129 if (is_array($this->defaultLanguageData[$table . ':' . $row['uid']])) {
2130 $defaultLanguageValue = BackendUtility::getProcessedValue($table, $field, $this->defaultLanguageData[$table . ':' . $row['uid']][$field], 0, 1);
2131 $fieldConfig = $GLOBALS['TCA'][$table]['columns'][$field];
2132 // Don't show content if it's for IRRE child records:
2133 if ($fieldConfig['config']['type'] != 'inline') {
2134 if ($defaultLanguageValue !== '') {
2135 $item .= '<div class="typo3-TCEforms-originalLanguageValue">' . $this->getLanguageIcon($table, $row, 0)
2136 . $this->getMergeBehaviourIcon($fieldConfig['l10n_mode'])
2137 . $this->previewFieldValue($defaultLanguageValue, $fieldConfig, $field) . '&nbsp;</div>';
2138 }
2139 $previewLanguages = $this->getAdditionalPreviewLanguages();
2140 foreach ($previewLanguages as $previewLanguage) {
2141 $defaultLanguageValue = BackendUtility::getProcessedValue($table, $field, $this->additionalPreviewLanguageData[$table . ':' . $row['uid']][$previewLanguage['uid']][$field], 0, 1);
2142 if ($defaultLanguageValue !== '') {
2143 $item .= '<div class="typo3-TCEforms-originalLanguageValue">'
2144 . $this->getLanguageIcon($table, $row, ('v' . $previewLanguage['ISOcode']))
2145 . $this->getMergeBehaviourIcon($fieldConfig['l10n_mode'])
2146 . $this->previewFieldValue($defaultLanguageValue, $fieldConfig, $field) . '&nbsp;</div>';
2147 }
2148 }
2149 }
2150 }
2151 return $item;
2152 }
2153
2154 /**
2155 * Renders the diff-view of default language record content compared with what the record was originally translated from.
2156 * Will render content if any is found in the internal array, $this->defaultLanguageData,
2157 * depending on registerDefaultLanguageData() being called prior to this.
2158 *
2159 * @param string $table Table name of the record being edited
2160 * @param string $field Field name represented by $item
2161 * @param array $row Record array of the record being edited
2162 * @param string $item HTML of the form field. This is what we add the content to.
2163 * @return string Item string returned again, possibly with the original value added to.
2164 * @see getSingleField(), registerDefaultLanguageData()
2165 */
2166 public function renderDefaultLanguageDiff($table, $field, $row, $item) {
2167 if (is_array($this->defaultLanguageData_diff[$table . ':' . $row['uid']])) {
2168 // Initialize:
2169 $dLVal = array(
2170 'old' => $this->defaultLanguageData_diff[$table . ':' . $row['uid']],
2171 'new' => $this->defaultLanguageData[$table . ':' . $row['uid']]
2172 );
2173 // There must be diff-data:
2174 if (isset($dLVal['old'][$field])) {
2175 if ((string)$dLVal['old'][$field] !== (string)$dLVal['new'][$field]) {
2176 // Create diff-result:
2177 $t3lib_diff_Obj = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Utility\\DiffUtility');
2178 $diffres = $t3lib_diff_Obj->makeDiffDisplay(
2179 BackendUtility::getProcessedValue($table, $field, $dLVal['old'][$field], 0, 1),
2180 BackendUtility::getProcessedValue($table, $field, $dLVal['new'][$field], 0, 1)
2181 );
2182 $item .= '<div class="typo3-TCEforms-diffBox">' . '<div class="typo3-TCEforms-diffBox-header">'
2183 . htmlspecialchars($this->getLL('l_changeInOrig')) . ':</div>' . $diffres . '</div>';
2184 }
2185 }
2186 }
2187 return $item;
2188 }
2189
2190 /**
2191 * Renders the diff-view of vDEF fields in flexforms
2192 *
2193 * @param array $vArray Record array of the record being edited
2194 * @param string $vDEFkey HTML of the form field. This is what we add the content to.
2195 * @return string Item string returned again, possibly with the original value added to.
2196 * @see getSingleField(), registerDefaultLanguageData()
2197 */
2198 public function renderVDEFDiff($vArray, $vDEFkey) {
2199 $item = NULL;
2200 if (
2201 $GLOBALS['TYPO3_CONF_VARS']['BE']['flexFormXMLincludeDiffBase'] && isset($vArray[$vDEFkey . '.vDEFbase'])
2202 && (string)$vArray[$vDEFkey . '.vDEFbase'] !== (string)$vArray['vDEF']
2203 ) {
2204 // Create diff-result:
2205 $t3lib_diff_Obj = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Utility\\DiffUtility');
2206 $diffres = $t3lib_diff_Obj->makeDiffDisplay($vArray[$vDEFkey . '.vDEFbase'], $vArray['vDEF']);
2207 $item = '<div class="typo3-TCEforms-diffBox">' . '<div class="typo3-TCEforms-diffBox-header">'
2208 . htmlspecialchars($this->getLL('l_changeInOrig')) . ':</div>' . $diffres . '</div>';
2209 }
2210 return $item;
2211 }
2212
2213 /************************************************************
2214 *
2215 * Form element helper functions
2216 *
2217 ************************************************************/
2218 /**
2219 * Prints the selector box form-field for the db/file/select elements (multiple)
2220 *
2221 * @param string $fName Form element name
2222 * @param string $mode Mode "db", "file" (internal_type for the "group" type) OR blank (then for the "select" type)
2223 * @param string $allowed Commalist of "allowed
2224 * @param array $itemArray The array of items. For "select" and "group"/"file" this is just a set of value. For "db" its an array of arrays with table/uid pairs.
2225 * @param string $selector Alternative selector box.
2226 * @param array $params An array of additional parameters, eg: "size", "info", "headers" (array with "selector" and "items"), "noBrowser", "thumbnails
2227 * @param string $onFocus On focus attribute string
2228 * @param string $table (optional) Table name processing for
2229 * @param string $field (optional) Field of table name processing for
2230 * @param string $uid (optional) uid of table record processing for
2231 * @param array $config (optional) The TCA field config
2232 * @return string The form fields for the selection.
2233 * @throws \UnexpectedValueException
2234 */
2235 public function dbFileIcons($fName, $mode, $allowed, $itemArray, $selector = '', $params = array(), $onFocus = '', $table = '', $field = '', $uid = '', $config = array()) {
2236 $disabled = '';
2237 if ($this->renderReadonly || $params['readOnly']) {
2238 $disabled = ' disabled="disabled"';
2239 }
2240 // Sets a flag which means some JavaScript is included on the page to support this element.
2241 $this->printNeededJS['dbFileIcons'] = 1;
2242 // INIT
2243 $uidList = array();
2244 $opt = array();
2245 $itemArrayC = 0;
2246 // Creating <option> elements:
2247 if (is_array($itemArray)) {
2248 $itemArrayC = count($itemArray);
2249 switch ($mode) {
2250 case 'db':
2251 foreach ($itemArray as $pp) {
2252 $pRec = BackendUtility::getRecordWSOL($pp['table'], $pp['id']);
2253 if (is_array($pRec)) {
2254 $pTitle = BackendUtility::getRecordTitle($pp['table'], $pRec, FALSE, TRUE);
2255 $pUid = $pp['table'] . '_' . $pp['id'];
2256 $uidList[] = $pUid;
2257 $title = htmlspecialchars($pTitle);
2258 $opt[] = '<option value="' . htmlspecialchars($pUid) . '" title="' . $title . '">' . $title . '</option>';
2259 }
2260 }
2261 break;
2262 case 'file_reference':
2263
2264 case 'file':
2265 foreach ($itemArray as $item) {
2266 $itemParts = explode('|', $item);
2267 $uidList[] = ($pUid = ($pTitle = $itemParts[0]));
2268 $title = htmlspecialchars(rawurldecode($itemParts[1]));
2269 $opt[] = '<option value="' . htmlspecialchars(rawurldecode($itemParts[0])) . '" title="' . $title . '">' . $title . '</option>';
2270 }
2271 break;
2272 case 'folder':
2273 foreach ($itemArray as $pp) {
2274 $pParts = explode('|', $pp);
2275 $uidList[] = ($pUid = ($pTitle = $pParts[0]));
2276 $title = htmlspecialchars(rawurldecode($pParts[0]));
2277 $opt[] = '<option value="' . htmlspecialchars(rawurldecode($pParts[0])) . '" title="' . $title . '">' . $title . '</option>';
2278 }
2279 break;
2280 default:
2281 foreach ($itemArray as $pp) {
2282 $pParts = explode('|', $pp, 2);
2283 $uidList[] = ($pUid = $pParts[0]);
2284 $pTitle = $pParts[1];
2285 $title = htmlspecialchars(rawurldecode($pTitle));
2286 $opt[] = '<option value="' . htmlspecialchars(rawurldecode($pUid)) . '" title="' . $title . '">' . $title . '</option>';
2287 }
2288 }
2289 }
2290 // Create selector box of the options
2291 $sSize = $params['autoSizeMax']
2292 ? MathUtility::forceIntegerInRange($itemArrayC + 1, MathUtility::forceIntegerInRange($params['size'], 1), $params['autoSizeMax'])
2293 : $params['size'];
2294 if (!$selector) {
2295 $isMultiple = $params['maxitems'] != 1 && $params['size'] != 1;
2296 $selector = '<select id="' . str_replace('.', '', uniqid('tceforms-multiselect-', TRUE)) . '" '
2297 . ($params['noList'] ? 'style="display: none"' : 'size="' . $sSize . '"' . $this->insertDefStyle('group', 'tceforms-multiselect'))
2298 . ($isMultiple ? ' multiple="multiple"' : '')
2299 . ' name="' . $fName . '_list" ' . $onFocus . $params['style'] . $disabled . '>' . implode('', $opt)
2300 . '</select>';
2301 }
2302 $icons = array(
2303 'L' => array(),
2304 'R' => array()
2305 );
2306 $rOnClickInline = '';
2307 if (!$params['readOnly'] && !$params['noList']) {
2308 if (!$params['noBrowser']) {
2309 // Check against inline uniqueness
2310 $inlineParent = $this->inline->getStructureLevel(-1);
2311 $aOnClickInline = '';
2312 if (is_array($inlineParent) && $inlineParent['uid']) {
2313 if ($inlineParent['config']['foreign_table'] == $table && $inlineParent['config']['foreign_unique'] == $field) {
2314 $objectPrefix = $this->inline->inlineNames['object'] . InlineElement::Structure_Separator . $table;
2315 $aOnClickInline = $objectPrefix . '|inline.checkUniqueElement|inline.setUniqueElement';
2316 $rOnClickInline = 'inline.revertUnique(\'' . $objectPrefix . '\',null,\'' . $uid . '\');';
2317 }
2318 }
2319 if (is_array($config['appearance']) && isset($config['appearance']['elementBrowserType'])) {
2320 $elementBrowserType = $config['appearance']['elementBrowserType'];
2321 } else {
2322 $elementBrowserType = $mode;
2323 }
2324 if (is_array($config['appearance']) && isset($config['appearance']['elementBrowserAllowed'])) {
2325 $elementBrowserAllowed = $config['appearance']['elementBrowserAllowed'];
2326 } else {
2327 $elementBrowserAllowed = $allowed;
2328 }
2329 $aOnClick = 'setFormValueOpenBrowser(\'' . $elementBrowserType . '\',\''
2330 . ($fName . '|||' . $elementBrowserAllowed . '|' . $aOnClickInline) . '\'); return false;';
2331 $spriteIcon = IconUtility::getSpriteIcon('actions-insert-record', array(
2332 'title' => htmlspecialchars($this->getLL('l_browse_' . ($mode == 'db' ? 'db' : 'file')))
2333 ));
2334 $icons['R'][] = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '" class="btn btn-default">' . $spriteIcon . '</a>';
2335 }
2336 if (!$params['dontShowMoveIcons']) {
2337 if ($sSize >= 5) {
2338 $icons['L'][] = IconUtility::getSpriteIcon('actions-move-to-top', array(
2339 'data-fieldname' => $fName,
2340 'class' => 't3-btn t3-btn-moveoption-top',
2341 'title' => htmlspecialchars($this->getLL('l_move_to_top'))
2342 ));
2343 }
2344 $icons['L'][] = IconUtility::getSpriteIcon('actions-move-up', array(
2345 'data-fieldname' => $fName,
2346 'class' => 't3-btn t3-btn-moveoption-up',
2347 'title' => htmlspecialchars($this->getLL('l_move_up'))
2348 ));
2349 $icons['L'][] = IconUtility::getSpriteIcon('actions-move-down', array(
2350 'data-fieldname' => $fName,
2351 'class' => 't3-btn t3-btn-moveoption-down',
2352 'title' => htmlspecialchars($this->getLL('l_move_down'))
2353 ));
2354 if ($sSize >= 5) {
2355 $icons['L'][] = IconUtility::getSpriteIcon('actions-move-to-bottom', array(
2356 'data-fieldname' => $fName,
2357 'class' => 't3-btn t3-btn-moveoption-bottom',
2358 'title' => htmlspecialchars($this->getLL('l_move_to_bottom'))
2359 ));
2360 }
2361 }
2362 $clipElements = $this->getClipboardElements($allowed, $mode);
2363 if (count($clipElements)) {
2364 $aOnClick = '';
2365 foreach ($clipElements as $elValue) {
2366 if ($mode == 'db') {
2367 list($itemTable, $itemUid) = explode('|', $elValue);
2368 $recordTitle = BackendUtility::getRecordTitle($itemTable, BackendUtility::getRecordWSOL($itemTable, $itemUid));
2369 $itemTitle = GeneralUtility::quoteJSvalue($recordTitle);
2370 $elValue = $itemTable . '_' . $itemUid;
2371 } else {
2372 // 'file', 'file_reference' and 'folder' mode
2373 $itemTitle = 'unescape(\'' . rawurlencode(basename($elValue)) . '\')';
2374 }
2375 $aOnClick .= 'setFormValueFromBrowseWin(\'' . $fName . '\',unescape(\''
2376 . rawurlencode(str_replace('%20', ' ', $elValue)) . '\'),' . $itemTitle . ',' . $itemTitle . ');';
2377 }
2378 $aOnClick .= 'return false;';
2379 $spriteIcon1 = IconUtility::getSpriteIcon('actions-document-paste-into', array(
2380 'title' => htmlspecialchars(sprintf($this->getLL('l_clipInsert_' . ($mode == 'db' ? 'db' : 'file')), count($clipElements)))
2381 ));
2382 $icons['R'][] = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">' . $spriteIcon1 . '</a>';
2383 }
2384 }
2385 if (!$params['readOnly'] && !$params['noDelete']) {
2386 $icons['L'][] = IconUtility::getSpriteIcon('actions-selection-delete', array(
2387 'onclick' => $rOnClickInline,
2388 'data-fieldname' => $fName,
2389 'class' => 't3-btn t3-btn-removeoption',
2390 'title' => htmlspecialchars($this->getLL('l_remove_selected'))
2391
2392 ));
2393 }
2394 $imagesOnly = FALSE;
2395 if ($params['thumbnails'] && $params['info']) {
2396 // In case we have thumbnails, check if only images are allowed.
2397 // In this case, render them below the field, instead of to the right
2398 $allowedExtensionList = GeneralUtility::trimExplode(' ', strtolower($params['info']), TRUE);
2399 $imageExtensionList = GeneralUtility::trimExplode(',', strtolower($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']), TRUE);
2400 $imagesOnly = TRUE;
2401 foreach ($allowedExtensionList as $allowedExtension) {
2402 if (!GeneralUtility::inArray($imageExtensionList, $allowedExtension)) {
2403 $imagesOnly = FALSE;
2404 break;
2405 }
2406 }
2407 }
2408 if ($imagesOnly) {
2409 $rightbox = '';
2410 $thumbnails = '<div class="imagethumbs">' . $params['thumbnails'] . '</div>';
2411 } else {
2412 $rightbox = $params['thumbnails'];
2413 $thumbnails = '';
2414 }
2415 // Hook: dbFileIcons_postProcess (requested by FAL-team for use with the "fal" extension)
2416 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['dbFileIcons'])) {
2417 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['dbFileIcons'] as $classRef) {
2418 $hookObject = GeneralUtility::getUserObj($classRef);
2419 if (!$hookObject instanceof DatabaseFileIconsHookInterface) {
2420 throw new \UnexpectedValueException('$hookObject must implement interface TYPO3\\CMS\\Backend\\Form\\DatabaseFileIconsHookInterface', 1290167704);
2421 }
2422 $additionalParams = array(
2423 'mode' => $mode,
2424 'allowed' => $allowed,
2425 'itemArray' => $itemArray,
2426 'onFocus' => $onFocus,
2427 'table' => $table,
2428 'field' => $field,
2429 'uid' => $uid,
2430 'config' => $GLOBALS['TCA'][$table]['columns'][$field]
2431 );
2432 $hookObject->dbFileIcons_postProcess($params, $selector, $thumbnails, $icons, $rightbox, $fName, $uidList, $additionalParams, $this);
2433 }
2434 }
2435 $str = '<table border="0" cellpadding="0" cellspacing="0" width="1" class="t3-form-field-group-file">
2436 ' . ($params['headers'] ? '
2437 <tr>
2438 <td>' . $params['headers']['selector'] . '</td>
2439 <td></td>
2440 <td></td>
2441 <td>' . ($params['thumbnails'] ? $params['headers']['items'] : '') . '</td>
2442 </tr>' : '') . '
2443 <tr>
2444 <td>' . $selector . $thumbnails;
2445 if (!$params['noList'] && $params['info'] !== '') {
2446 $str .= '<span class="filetypes">' . $params['info'] . '</span>';
2447 }
2448 $str .= '</td>
2449 <td class="icons">' . implode('<br />', $icons['L']) . '</td>
2450 <td class="icons">' . implode('<br />', $icons['R']) . '</td>
2451 <td>' . $rightbox . '</td>
2452 </tr>
2453 </table>';
2454 // Creating the hidden field which contains the actual value as a comma list.
2455 $str .= '<input type="hidden" name="' . $fName . '" value="' . htmlspecialchars(implode(',', $uidList)) . '" />';
2456 return $str;
2457 }
2458
2459 /**
2460 * Returns array of elements from clipboard to insert into GROUP element box.
2461 *
2462 * @param string $allowed Allowed elements, Eg "pages,tt_content", "gif,jpg,jpeg,png
2463 * @param string $mode Mode of relations: "db" or "file
2464 * @return array Array of elements in values (keys are insignificant), if none found, empty array.
2465 */
2466 public function getClipboardElements($allowed, $mode) {
2467 $output = array();
2468 if (is_object($this->clipObj)) {
2469 switch ($mode) {
2470 case 'file_reference':
2471
2472 case 'file':
2473 $elFromTable = $this->clipObj->elFromTable('_FILE');
2474 $allowedExts = GeneralUtility::trimExplode(',', $allowed, TRUE);
2475 // If there are a set of allowed extensions, filter the content:
2476 if ($allowedExts) {
2477 foreach ($elFromTable as $elValue) {
2478 $pI = pathinfo($elValue);
2479 $ext = strtolower($pI['extension']);
2480 if (in_array($ext, $allowedExts)) {
2481 $output[] = $elValue;
2482 }
2483 }
2484 } else {
2485 // If all is allowed, insert all: (This does NOT respect any disallowed extensions,
2486 // but those will be filtered away by the backend TCEmain)
2487 $output = $elFromTable;
2488 }
2489 break;
2490 case 'db':
2491 $allowedTables = GeneralUtility::trimExplode(',', $allowed, TRUE);
2492 // All tables allowed for relation:
2493 if (trim($allowedTables[0]) === '*') {
2494 $output = $this->clipObj->elFromTable('');
2495 } else {
2496 // Only some tables, filter them:
2497 foreach ($allowedTables as $tablename) {
2498 $elFromTable = $this->clipObj->elFromTable($tablename);
2499 $output = array_merge($output, $elFromTable);
2500 }
2501 }
2502 $output = array_keys($output);
2503 break;
2504 }
2505 }
2506 return $output;
2507 }
2508
2509 /**
2510 * Wraps the icon of a relation item (database record or file) in a link opening the context menu for the item.
2511 * Icons will be wrapped only if $this->enableClickMenu is set. This must be done only if a global SOBE object
2512 * exists and if the necessary JavaScript for displaying the context menus has been added to the page properties.
2513 *
2514 * @param string $str The icon HTML to wrap
2515 * @param string $table Table name (eg. "pages" or "tt_content") OR the absolute path to the file
2516 * @param int $uid The uid of the record OR if file, just blank value.
2517 * @return string HTML
2518 */
2519 public function getClickMenu($str, $table, $uid = 0) {
2520 if ($this->enableClickMenu) {
2521 $onClick = $this->getControllerDocumentTemplate()->wrapClickMenuOnIcon($str, $table, $uid, 1, '', '+copy,info,edit,view', TRUE);
2522 return '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $str . '</a>';
2523 }
2524 return '';
2525 }
2526
2527 /**
2528 * Rendering wizards for form fields.
2529 *
2530 * @param array $itemKinds Array with the real item in the first value, and an alternative item in the second value.
2531 * @param array $wizConf The "wizard" key from the config array for the field (from TCA)
2532 * @param string $table Table name
2533 * @param array $row The record array
2534 * @param string $field The field name
2535 * @param array $PA Additional configuration array. (passed by reference!)
2536 * @param string $itemName The field name
2537 * @param array $specConf Special configuration if available.
2538 * @param bool $RTE Whether the RTE could have been loaded.
2539 * @return string The new item value.
2540 */
2541 public function renderWizards($itemKinds, $wizConf, $table, $row, $field, &$PA, $itemName, $specConf, $RTE = FALSE) {
2542 // Init:
2543 $fieldChangeFunc = $PA['fieldChangeFunc'];
2544 $item = $itemKinds[0];
2545 $outArr = array();
2546 $colorBoxLinks = array();
2547 $fName = '[' . $table . '][' . $row['uid'] . '][' . $field . ']';
2548 $md5ID = 'ID' . GeneralUtility::shortmd5($itemName);
2549 $listFlag = '_list';
2550 $fieldConfig = $PA['fieldConf']['config'];
2551 $prefixOfFormElName = 'data[' . $table . '][' . $row['uid'] . '][' . $field . ']';
2552 $flexFormPath = '';
2553 if (GeneralUtility::isFirstPartOfStr($PA['itemFormElName'], $prefixOfFormElName)) {
2554 $flexFormPath = str_replace('][', '/', substr($PA['itemFormElName'], strlen($prefixOfFormElName) + 1, -1));
2555 }
2556 // Manipulate the field name (to be the TRUE form field name) and remove
2557 // a suffix-value if the item is a selector box with renderMode "singlebox":
2558 if ($PA['fieldConf']['config']['form_type'] == 'select') {
2559 // Single select situation:
2560 if ($PA['fieldConf']['config']['maxitems'] <= 1) {
2561 $listFlag = '';
2562 } elseif ($PA['fieldConf']['config']['renderMode'] == 'singlebox') {
2563 $itemName .= '[]';
2564 $listFlag = '';
2565 }
2566 }
2567 // Traverse wizards:
2568 if (is_array($wizConf) && !$this->disableWizards) {
2569 $parametersOfWizards = &$specConf['wizards']['parameters'];
2570 foreach ($wizConf as $wid => $wConf) {
2571 if (
2572 $wid[0] !== '_' && (!$wConf['enableByTypeConfig']
2573 || is_array($parametersOfWizards) && in_array($wid, $parametersOfWizards)) && ($RTE || !$wConf['RTEonly'])
2574 ) {
2575 // Title / icon:
2576 $iTitle = htmlspecialchars($this->sL($wConf['title']));
2577 if ($wConf['icon']) {
2578 $icon = $this->getIconHtml($wConf['icon'], $iTitle, $iTitle);
2579 } else {
2580 $icon = $iTitle;
2581 }
2582 switch ((string) $wConf['type']) {
2583 case 'userFunc':
2584
2585 case 'script':
2586
2587 case 'popup':
2588
2589 case 'colorbox':
2590
2591 case 'slider':
2592 if (!$wConf['notNewRecords'] || MathUtility::canBeInterpretedAsInteger($row['uid'])) {
2593 // Setting &P array contents:
2594 $params = array();
2595 // Including the full fieldConfig from TCA may produce too long an URL
2596 if ($wid != 'RTE') {
2597 $params['fieldConfig'] = $fieldConfig;
2598 }
2599 $params['params'] = $wConf['params'];
2600 $params['exampleImg'] = $wConf['exampleImg'];
2601 $params['table'] = $table;
2602 $params['uid'] = $row['uid'];
2603 $params['pid'] = $row['pid'];
2604 $params['field'] = $field;
2605 $params['flexFormPath'] = $flexFormPath;
2606 $params['md5ID'] = $md5ID;
2607 $params['returnUrl'] = $this->thisReturnUrl();
2608
2609 $wScript = '';
2610 // Resolving script filename and setting URL.
2611 if (isset($wConf['module']['name'])) {
2612 $urlParameters = array();
2613 if (isset($wConf['module']['urlParameters']) && is_array($wConf['module']['urlParameters'])) {
2614 $urlParameters = $wConf['module']['urlParameters'];
2615 }
2616 $wScript = BackendUtility::getModuleUrl($wConf['module']['name'], $urlParameters);
2617 } elseif (isset($wConf['script'])) {
2618 GeneralUtility::deprecationLog(
2619 'The way registering a wizard in TCA has changed in 6.2. '
2620 . 'Please set module[name]=module_name instead of using script=path/to/sctipt.php in your TCA. '
2621 . 'The possibility to register wizards this way will be removed in 2 versions.'
2622 );
2623 if (substr($wConf['script'], 0, 4) === 'EXT:') {
2624 $wScript = GeneralUtility::getFileAbsFileName($wConf['script']);
2625 if ($wScript) {
2626 $wScript = '../' . PathUtility::stripPathSitePrefix($wScript);
2627 } else {
2628 // Illeagal configuration, fail silently
2629 break;
2630 }
2631 } else {
2632 // Compatibility layer
2633 // @deprecated since 6.2, will be removed 2 versions later
2634 $parsedWizardUrl = parse_url($wConf['script']);
2635 if (in_array($parsedWizardUrl['path'], array(
2636 'wizard_add.php',
2637 'wizard_colorpicker.php',
2638 'wizard_edit.php',
2639 'wizard_forms.php',
2640 'wizard_list.php',
2641 'wizard_rte.php',
2642 'wizard_table.php',
2643 'browse_links.php',
2644 'sysext/cms/layout/wizard_backend_layout.php'
2645 ))
2646 ) {
2647 $urlParameters = array();
2648 if (isset($parsedWizardUrl['query'])) {
2649 parse_str($parsedWizardUrl['query'], $urlParameters);
2650 }
2651 $moduleName = str_replace(
2652 array('.php', 'browse_links', 'sysext/cms/layout/wizard_backend_layout'),
2653 array('', 'wizard_element_browser', 'wizard_backend_layout'),
2654 $parsedWizardUrl['path']
2655 );
2656 $wScript = BackendUtility::getModuleUrl($moduleName, $urlParameters);
2657 unset($moduleName, $urlParameters, $parsedWizardUrl);
2658 } else {
2659 $wScript = $wConf['script'];
2660 }
2661 }
2662 } elseif (in_array($wConf['type'], array('script', 'colorbox', 'popup'), TRUE)) {
2663 // Illegal configuration, fail silently
2664 break;
2665 }
2666
2667 $url = $this->backPath . $wScript . (strstr($wScript, '?') ? '' : '?');
2668 // If "script" type, create the links around the icon:
2669 if ((string) $wConf['type'] === 'script') {
2670 $aUrl = $url . GeneralUtility::implodeArrayForUrl('', array('P' => $params));
2671 $outArr[] = '<a href="' . htmlspecialchars($aUrl) . '" onclick="this.blur(); return !TBE_EDITOR.isFormChanged();">' . $icon . '</a>';
2672 } else {
2673 // ... else types "popup", "colorbox" and "userFunc" will need additional parameters:
2674 $params['formName'] = $this->formName;
2675 $params['itemName'] = $itemName;
2676 $params['hmac'] = GeneralUtility::hmac($params['formName'] . $params['itemName'], 'wizard_js');
2677 $params['fieldChangeFunc'] = $fieldChangeFunc;
2678 $params['fieldChangeFuncHash'] = GeneralUtility::hmac(serialize($fieldChangeFunc));
2679 switch ((string) $wConf['type']) {
2680 case 'popup':
2681 case 'colorbox':
2682 // Current form value is passed as P[currentValue]!
2683 $addJS = $wConf['popup_onlyOpenIfSelected']
2684 ? 'if (!TBE_EDITOR.curSelected(\'' . $itemName . $listFlag . '\')){alert('
2685 . GeneralUtility::quoteJSvalue($this->getLL('m_noSelItemForEdit'))
2686 . '); return false;}'
2687 : '';
2688 $curSelectedValues = '+\'&P[currentSelectedValues]=\'+TBE_EDITOR.curSelected(\'' . $itemName . $listFlag . '\')';
2689 $aOnClick = 'this.blur();' . $addJS . 'vHWin=window.open(\'' . $url
2690 . GeneralUtility::implodeArrayForUrl('', array('P' => $params))
2691 . '\'+\'&P[currentValue]=\'+TBE_EDITOR.rawurlencode('
2692 . $this->elName($itemName) . '.value,200)' . $curSelectedValues
2693 . ',\'popUp' . $md5ID . '\',\'' . $wConf['JSopenParams'] . '\');'
2694 . 'vHWin.focus();return false;';
2695 // Setting "colorBoxLinks" - user LATER to wrap around the color box as well:
2696 $colorBoxLinks = array('<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">', '</a>');
2697 if ((string) $wConf['type'] == 'popup') {
2698 $outArr[] = $colorBoxLinks[0] . $icon . $colorBoxLinks[1];
2699 }
2700 break;
2701 case 'userFunc':
2702 // Reference set!
2703 $params['item'] = &$item;
2704 $params['icon'] = $icon;
2705 $params['iTitle'] = $iTitle;
2706 $params['wConf'] = $wConf;
2707 $params['row'] = $row;
2708 $outArr[] = GeneralUtility::callUserFunction($wConf['userFunc'], $params, $this);
2709 break;
2710 case 'slider':
2711 // Reference set!
2712 $params['item'] = &$item;
2713 $params['icon'] = $icon;
2714 $params['iTitle'] = $iTitle;
2715 $params['wConf'] = $wConf;
2716 $params['row'] = $row;
2717 $wizard = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\Element\\ValueSlider');
2718 $outArr[] = call_user_func_array(array(&$wizard, 'renderWizard'), array(&$params, &$this));
2719 break;
2720 }
2721 }
2722 // Hide the real form element?
2723 if (is_array($wConf['hideParent']) || $wConf['hideParent']) {
2724 // Setting the item to a hidden-field.
2725 $item = $itemKinds[1];
2726 if (is_array($wConf['hideParent'])) {
2727 $item .= $this->getSingleField_typeNone_render($wConf['hideParent'], $PA['itemFormElValue']);
2728 }
2729 }
2730 }
2731 break;
2732 case 'select':
2733 $fieldValue = array('config' => $wConf);
2734 $TSconfig = $this->setTSconfig($table, $row);
2735 $TSconfig[$field] = $TSconfig[$field]['wizards.'][$wid . '.'];
2736 $selItems = $this->addSelectOptionsToItemArray($this->initItemArray($fieldValue), $fieldValue, $TSconfig, $field);
2737 // Process items by a user function:
2738 if (!empty($wConf['itemsProcFunc'])) {
2739 $funcConfig = !empty($wConf['itemsProcFunc.']) ? $wConf['itemsProcFunc.'] : array();
2740 $selItems = $this->procItems($selItems, $funcConfig, $wConf, $table, $row, $field);
2741 }
2742 $opt = array();
2743 $opt[] = '<option>' . $iTitle . '</option>';
2744 foreach ($selItems as $p) {
2745 $opt[] = '<option value="' . htmlspecialchars($p[1]) . '">' . htmlspecialchars($p[0]) . '</option>';
2746 }
2747 if ($wConf['mode'] == 'append') {
2748 $assignValue = $this->elName($itemName) . '.value=\'\'+this.options[this.selectedIndex].value+' . $this->elName($itemName) . '.value';
2749 } elseif ($wConf['mode'] == 'prepend') {
2750 $assignValue = $this->elName($itemName) . '.value+=\'\'+this.opti