[!!!][FEATURE] FormEngine element level refactoring
[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 $fieldInformationResult = $this->renderFieldInformation();
109 $fieldInformationHtml = $fieldInformationResult['html'];
110 $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
111
112 $html = [];
113 $html[] = '<div class="t3js-formengine-field-item">';
114 if (!$readOnly) {
115 $html[] = $fieldInformationHtml;
116 }
117 $html[] = '<div class="form-control-wrap">';
118 $html[] = '<div class="typo3-tceforms-tree">';
119 $html[] = '<input class="treeRecord" type="hidden"';
120 $html[] = ' data-formengine-validation-rules="' . htmlspecialchars($this->getValidationDataAsJsonString($config)) . '"';
121 $html[] = ' data-relatedfieldname="' . htmlspecialchars($parameterArray['itemFormElName']) . '"';
122 $html[] = ' data-tablename="' . htmlspecialchars($this->data['tableName']) . '"';
123 $html[] = ' data-fieldname="' . htmlspecialchars($this->data['fieldName']) . '"';
124 $html[] = ' data-uid="' . (int)$this->data['vanillaUid'] . '"';
125 $html[] = ' data-recordtypevalue="' . htmlspecialchars($this->data['recordTypeValue']) . '"';
126 $html[] = ' data-datastructureidentifier="' . htmlspecialchars($dataStructureIdentifier) . '"';
127 $html[] = ' data-flexformsheetname="' . htmlspecialchars($flexFormSheetName) . '"';
128 $html[] = ' data-flexformfieldname="' . htmlspecialchars($flexFormFieldName) . '"';
129 $html[] = ' data-flexformcontainername="' . htmlspecialchars($flexFormContainerName) . '"';
130 $html[] = ' data-flexformcontaineridentifier="' . htmlspecialchars($flexFormContainerIdentifier) . '"';
131 $html[] = ' data-flexformcontainerfieldname="' . htmlspecialchars($flexFormContainerFieldName) . '"';
132 $html[] = ' data-flexformsectioncontainerisnew="' . htmlspecialchars($flexFormSectionContainerIsNew) . '"';
133 $html[] = ' data-command="' . htmlspecialchars($this->data['command']) . '"';
134 $html[] = ' data-read-only="' . $readOnly . '"';
135 $html[] = ' data-tree-exclusive-keys="' . htmlspecialchars($exclusiveKeys) . '"';
136 $html[] = ' data-tree-expand-up-to-level="' . ($expanded ? '999' : '1') . '"';
137 $html[] = ' data-tree-show-toolbar="' . $showHeader . '"';
138 $html[] = ' name="' . htmlspecialchars($parameterArray['itemFormElName']) . '"';
139 $html[] = ' id="treeinput' . $formElementId . '"';
140 $html[] = ' value=""';
141 $html[] = '/>';
142 $html[] = '</div>';
143 $html[] = '<div id="' . $treeWrapperId . '" class="svg-tree-wrapper" style="height: ' . $heightInPx . 'px;"></div>';
144 $html[] = '<script type="text/javascript">var ' . $treeWrapperId . ' = ' . $this->getTreeOnChangeJs() . '</script>';
145 $html[] = '</div>';
146 $html[] = '</div>';
147
148 $resultArray['html'] = implode(LF, $html);
149
150 // add necessary labels for tree header
151 if ($showHeader) {
152 $resultArray['additionalInlineLanguageLabelFiles'][] = 'EXT:lang/Resources/Private/Language/locallang_csh_corebe.xlf';
153 }
154 $resultArray['requireJsModules']['selectTreeElement'] = [
155 'TYPO3/CMS/Backend/FormEngine/Element/SelectTreeElement' => 'function (SelectTreeElement) { SelectTreeElement.initialize(); }'
156 ];
157
158 return $resultArray;
159 }
160
161 /**
162 * Generates JS code triggered on change of the tree
163 *
164 * @return string
165 */
166 protected function getTreeOnChangeJs()
167 {
168 $parameterArray = $this->data['parameterArray'];
169 $onChange = !empty($parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged']) ? $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] : '';
170 $onChange .= !empty($parameterArray['fieldChangeFunc']['alert']) ? $parameterArray['fieldChangeFunc']['alert'] : '';
171 return 'function () {' . $onChange . '}';
172 }
173 }