[!!!][TASK] Improve flex and TCA handling in FormEngine
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / Element / SelectTreeElement.php
1 <?php
2 namespace TYPO3\CMS\Backend\Form\Element;
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 /**
18 * Render data as a tree.
19 *
20 * Typically rendered for config type=select, renderType=selectTree
21 */
22 class SelectTreeElement extends AbstractFormElement
23 {
24 /**
25 * Default number of tree nodes to show (determines tree height)
26 * when no ['config']['size'] is set
27 *
28 * @var int
29 */
30 protected $itemsToShow = 15;
31
32 /**
33 * Number of items to show at last
34 * e.g. when you have only 2 items in a tree
35 *
36 * @var int
37 */
38 protected $minItemsToShow = 5;
39
40 /**
41 * Pixel height of a single tree node
42 *
43 * @var int
44 */
45 protected $itemHeight = 20;
46
47 /**
48 * Render tree widget
49 *
50 * @return array As defined in initializeResultArray() of AbstractNode
51 * @see AbstractNode::initializeResultArray()
52 */
53 public function render()
54 {
55 $resultArray = $this->initializeResultArray();
56 $parameterArray = $this->data['parameterArray'];
57 $formElementId = md5($parameterArray['itemFormElName']);
58
59 // Field configuration from TCA:
60 $config = $parameterArray['fieldConf']['config'];
61 $readOnly = !empty($config['readOnly']) ? 'true' : 'false';
62 $exclusiveKeys = !empty($config['exclusiveKeys']) ? $config['exclusiveKeys'] : '';
63 $exclusiveKeys = $exclusiveKeys . ',';
64 $appearance = !empty($config['treeConfig']['appearance']) ? $config['treeConfig']['appearance'] : [];
65 $expanded = !empty($appearance['expandAll']);
66 $showHeader = !empty($appearance['showHeader']);
67 if (isset($config['size']) && (int)$config['size'] > 0) {
68 $height = max($this->minItemsToShow, (int)$config['size']);
69 } else {
70 $height = $this->itemsToShow;
71 }
72 $heightInPx = $height * $this->itemHeight;
73 $treeWrapperId = 'tree_' . $formElementId;
74
75 $fieldName = $this->data['fieldName'];
76
77 $dataStructureIdentifier = '';
78 $flexFormSheetName = '';
79 $flexFormFieldName = '';
80 $flexFormContainerName = '';
81 $flexFormContainerIdentifier = '';
82 $flexFormContainerFieldName = '';
83 $flexFormSectionContainerIsNew = false;
84 if ($this->data['processedTca']['columns'][$fieldName]['config']['type'] === 'flex') {
85 $dataStructureIdentifier = $this->data['processedTca']['columns'][$fieldName]['config']['dataStructureIdentifier'];
86 if (isset($this->data['flexFormSheetName'])) {
87 $flexFormSheetName = $this->data['flexFormSheetName'];
88 }
89 if (isset($this->data['flexFormFieldName'])) {
90 $flexFormFieldName = $this->data['flexFormFieldName'];
91 }
92 if (isset($this->data['flexFormContainerName'])) {
93 $flexFormContainerName = $this->data['flexFormContainerName'];
94 }
95 if (isset($this->data['flexFormContainerFieldName'])) {
96 $flexFormContainerFieldName = $this->data['flexFormContainerFieldName'];
97 }
98 if (isset($this->data['flexFormContainerIdentifier'])) {
99 $flexFormContainerIdentifier = $this->data['flexFormContainerIdentifier'];
100 }
101 // Add a flag this is a tree in a new flex section container element. This is needed to initialize
102 // the databaseRow with this container again so the tree data provider is able to calculate tree items.
103 if (!empty($this->data['flexSectionContainerPreparation'])) {
104 $flexFormSectionContainerIsNew = true;
105 }
106 }
107
108 $html = [];
109 $html[] = '<div class="typo3-tceforms-tree">';
110 $html[] = ' <input class="treeRecord" type="hidden"';
111 $html[] = ' ' . $this->getValidationDataAsDataAttribute($config);
112 $html[] = ' data-relatedfieldname="' . htmlspecialchars($parameterArray['itemFormElName']) . '"';
113 $html[] = ' data-tablename="' . htmlspecialchars($this->data['tableName']) . '"';
114 $html[] = ' data-fieldname="' . htmlspecialchars($this->data['fieldName']) . '"';
115 $html[] = ' data-uid="' . (int)$this->data['vanillaUid'] . '"';
116 $html[] = ' data-recordtypevalue="' . htmlspecialchars($this->data['recordTypeValue']) . '"';
117 $html[] = ' data-datastructureidentifier="' . htmlspecialchars($dataStructureIdentifier) . '"';
118 $html[] = ' data-flexformsheetname="' . htmlspecialchars($flexFormSheetName) . '"';
119 $html[] = ' data-flexformfieldname="' . htmlspecialchars($flexFormFieldName) . '"';
120 $html[] = ' data-flexformcontainername="' . htmlspecialchars($flexFormContainerName) . '"';
121 $html[] = ' data-flexformcontaineridentifier="' . htmlspecialchars($flexFormContainerIdentifier) . '"';
122 $html[] = ' data-flexformcontainerfieldname="' . htmlspecialchars($flexFormContainerFieldName) . '"';
123 $html[] = ' data-flexformsectioncontainerisnew="' . htmlspecialchars($flexFormSectionContainerIsNew) . '"';
124 $html[] = ' data-command="' . htmlspecialchars($this->data['command']) . '"';
125 $html[] = ' data-read-only="' . $readOnly . '"';
126 $html[] = ' data-tree-exclusive-keys="' . htmlspecialchars($exclusiveKeys) . '"';
127 $html[] = ' data-tree-expand-up-to-level="' . ($expanded ? '999' : '1') . '"';
128 $html[] = ' data-tree-show-toolbar="' . $showHeader . '"';
129 $html[] = ' name="' . htmlspecialchars($parameterArray['itemFormElName']) . '"';
130 $html[] = ' id="treeinput' . $formElementId . '"';
131 $html[] = ' value=""';
132 $html[] = ' />';
133 $html[] = '</div>';
134 $html[] = '<div id="' . $treeWrapperId . '" class="svg-tree-wrapper" style="height: ' . $heightInPx . 'px;"></div>';
135 $html[] = '<script type="text/javascript">var ' . $treeWrapperId . ' = ' . $this->getTreeOnChangeJs() . '</script>';
136
137 $resultArray['html'] = implode(LF, $html);
138
139 // add necessary labels for tree header
140 if ($showHeader) {
141 $resultArray['additionalInlineLanguageLabelFiles'][] = 'EXT:lang/Resources/Private/Language/locallang_csh_corebe.xlf';
142 }
143 $resultArray['requireJsModules']['selectTreeElement'] = [
144 'TYPO3/CMS/Backend/FormEngine/Element/SelectTreeElement' => 'function (SelectTreeElement) { SelectTreeElement.initialize(); }'
145 ];
146
147 return $resultArray;
148 }
149
150 /**
151 * Generates JS code triggered on change of the tree
152 *
153 * @return string
154 */
155 protected function getTreeOnChangeJs()
156 {
157 $parameterArray = $this->data['parameterArray'];
158 $onChange = !empty($parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged']) ? $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] : '';
159 $onChange .= !empty($parameterArray['fieldChangeFunc']['alert']) ? $parameterArray['fieldChangeFunc']['alert'] : '';
160 return 'function () {' . $onChange . '}';
161 }
162 }