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