[TASK] Change to named keys in EXT:seo when using generateMetaTags hook
[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 use TYPO3\CMS\Core\Utility\GeneralUtility;
18
19 /**
20 * Render data as a tree.
21 *
22 * Typically rendered for config type=select, renderType=selectTree
23 */
24 class SelectTreeElement extends AbstractFormElement
25 {
26 /**
27 * Default field information enabled for this element.
28 *
29 * @var array
30 */
31 protected $defaultFieldInformation = [
32 'tcaDescription' => [
33 'renderType' => 'tcaDescription',
34 ],
35 ];
36
37 /**
38 * @var array Default wizards
39 */
40 protected $defaultFieldWizard = [
41 'localizationStateSelector' => [
42 'renderType' => 'localizationStateSelector',
43 ],
44 ];
45
46 /**
47 * Default number of tree nodes to show (determines tree height)
48 * when no ['config']['size'] is set
49 *
50 * @var int
51 */
52 protected $itemsToShow = 15;
53
54 /**
55 * Number of items to show at last
56 * e.g. when you have only 2 items in a tree
57 *
58 * @var int
59 */
60 protected $minItemsToShow = 5;
61
62 /**
63 * Pixel height of a single tree node
64 *
65 * @var int
66 */
67 protected $itemHeight = 20;
68
69 /**
70 * Render tree widget
71 *
72 * @return array As defined in initializeResultArray() of AbstractNode
73 * @see AbstractNode::initializeResultArray()
74 */
75 public function render()
76 {
77 $resultArray = $this->initializeResultArray();
78 $parameterArray = $this->data['parameterArray'];
79 $formElementId = md5($parameterArray['itemFormElName']);
80
81 // Field configuration from TCA:
82 $config = $parameterArray['fieldConf']['config'];
83 $readOnly = !empty($config['readOnly']) ? 1 : 0;
84 $exclusiveKeys = !empty($config['exclusiveKeys']) ? $config['exclusiveKeys'] : '';
85 $exclusiveKeys = $exclusiveKeys . ',';
86 $appearance = !empty($config['treeConfig']['appearance']) ? $config['treeConfig']['appearance'] : [];
87 $expanded = !empty($appearance['expandAll']);
88 $showHeader = !empty($appearance['showHeader']);
89 if (isset($config['size']) && (int)$config['size'] > 0) {
90 $height = max($this->minItemsToShow, (int)$config['size']);
91 } else {
92 $height = $this->itemsToShow;
93 }
94 $heightInPx = $height * $this->itemHeight;
95 $treeWrapperId = 'tree_' . $formElementId;
96 $fieldId = 'tree_record_' . $formElementId;
97
98 $fieldName = $this->data['fieldName'];
99
100 $dataStructureIdentifier = '';
101 $flexFormSheetName = '';
102 $flexFormFieldName = '';
103 $flexFormContainerName = '';
104 $flexFormContainerIdentifier = '';
105 $flexFormContainerFieldName = '';
106 $flexFormSectionContainerIsNew = false;
107 if ($this->data['processedTca']['columns'][$fieldName]['config']['type'] === 'flex') {
108 $dataStructureIdentifier = $this->data['processedTca']['columns'][$fieldName]['config']['dataStructureIdentifier'];
109 if (isset($this->data['flexFormSheetName'])) {
110 $flexFormSheetName = $this->data['flexFormSheetName'];
111 }
112 if (isset($this->data['flexFormFieldName'])) {
113 $flexFormFieldName = $this->data['flexFormFieldName'];
114 }
115 if (isset($this->data['flexFormContainerName'])) {
116 $flexFormContainerName = $this->data['flexFormContainerName'];
117 }
118 if (isset($this->data['flexFormContainerFieldName'])) {
119 $flexFormContainerFieldName = $this->data['flexFormContainerFieldName'];
120 }
121 if (isset($this->data['flexFormContainerIdentifier'])) {
122 $flexFormContainerIdentifier = $this->data['flexFormContainerIdentifier'];
123 }
124 // Add a flag this is a tree in a new flex section container element. This is needed to initialize
125 // the databaseRow with this container again so the tree data provider is able to calculate tree items.
126 if (!empty($this->data['flexSectionContainerPreparation'])) {
127 $flexFormSectionContainerIsNew = true;
128 }
129 }
130
131 $fieldInformationResult = $this->renderFieldInformation();
132 $fieldInformationHtml = $fieldInformationResult['html'];
133 $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
134
135 $fieldWizardResult = $this->renderFieldWizard();
136 $fieldWizardHtml = $fieldWizardResult['html'];
137 $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
138
139 $html = [];
140 $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
141 $html[] = $fieldInformationHtml;
142 $html[] = '<div class="form-control-wrap">';
143 $html[] = '<div class="form-wizards-wrap">';
144 $html[] = '<div class="form-wizards-element">';
145 $html[] = '<div class="typo3-tceforms-tree">';
146 $html[] = '<input class="treeRecord" type="hidden" id="' . htmlspecialchars($fieldId) . '"';
147 $html[] = ' data-formengine-validation-rules="' . htmlspecialchars($this->getValidationDataAsJsonString($config)) . '"';
148 $html[] = ' data-relatedfieldname="' . htmlspecialchars($parameterArray['itemFormElName']) . '"';
149 $html[] = ' data-tablename="' . htmlspecialchars($this->data['tableName']) . '"';
150 $html[] = ' data-fieldname="' . htmlspecialchars($this->data['fieldName']) . '"';
151 $html[] = ' data-uid="' . (int)$this->data['vanillaUid'] . '"';
152 $html[] = ' data-recordtypevalue="' . htmlspecialchars($this->data['recordTypeValue']) . '"';
153 $html[] = ' data-datastructureidentifier="' . htmlspecialchars($dataStructureIdentifier) . '"';
154 $html[] = ' data-flexformsheetname="' . htmlspecialchars($flexFormSheetName) . '"';
155 $html[] = ' data-flexformfieldname="' . htmlspecialchars($flexFormFieldName) . '"';
156 $html[] = ' data-flexformcontainername="' . htmlspecialchars($flexFormContainerName) . '"';
157 $html[] = ' data-flexformcontaineridentifier="' . htmlspecialchars($flexFormContainerIdentifier) . '"';
158 $html[] = ' data-flexformcontainerfieldname="' . htmlspecialchars($flexFormContainerFieldName) . '"';
159 $html[] = ' data-flexformsectioncontainerisnew="' . htmlspecialchars($flexFormSectionContainerIsNew) . '"';
160 $html[] = ' data-command="' . htmlspecialchars($this->data['command']) . '"';
161 $html[] = ' data-read-only="' . $readOnly . '"';
162 $html[] = ' data-tree-exclusive-keys="' . htmlspecialchars($exclusiveKeys) . '"';
163 $html[] = ' data-tree-expand-up-to-level="' . ($expanded ? '999' : '1') . '"';
164 $html[] = ' data-tree-show-toolbar="' . $showHeader . '"';
165 $html[] = ' name="' . htmlspecialchars($parameterArray['itemFormElName']) . '"';
166 $html[] = ' id="treeinput' . $formElementId . '"';
167 $html[] = ' value="' . htmlspecialchars(implode(',', $parameterArray['itemFormElValue'])) . '"';
168 $html[] = '/>';
169 $html[] = '</div>';
170 $html[] = '<div id="' . $treeWrapperId . '" class="svg-tree-wrapper" style="height: ' . $heightInPx . 'px;"></div>';
171 $html[] = '</div>';
172 if ($readOnly === 'false' && !empty($fieldWizardHtml)) {
173 $html[] = '<div class="form-wizards-items-bottom">';
174 $html[] = $fieldWizardHtml;
175 $html[] = '</div>';
176 }
177 $html[] = '</div>';
178 $html[] = '</div>';
179 $html[] = '</div>';
180
181 $resultArray['html'] = implode(LF, $html);
182
183 // add necessary labels for tree header
184 if ($showHeader) {
185 $resultArray['additionalInlineLanguageLabelFiles'][] = 'EXT:core/Resources/Private/Language/locallang_csh_corebe.xlf';
186 }
187 $resultArray['requireJsModules']['selectTreeElement'] = ['TYPO3/CMS/Backend/FormEngine/Element/SelectTreeElement' => '
188 function(SelectTreeElement) {
189 require([\'jquery\'], function($) {
190 $(function() {
191 new SelectTreeElement(' . GeneralUtility::quoteJSvalue($treeWrapperId) . ', ' . GeneralUtility::quoteJSvalue($fieldId) . ', ' . $this->getTreeOnChangeJs() . ');
192 });
193 });
194 }'
195 ];
196
197 return $resultArray;
198 }
199
200 /**
201 * Generates JS code triggered on change of the tree
202 *
203 * @return string
204 */
205 protected function getTreeOnChangeJs()
206 {
207 $parameterArray = $this->data['parameterArray'];
208 $onChange = !empty($parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged']) ? $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] : '';
209 $onChange .= !empty($parameterArray['fieldChangeFunc']['alert']) ? $parameterArray['fieldChangeFunc']['alert'] : '';
210 return 'function () {' . $onChange . '}';
211 }
212 }