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