[TASK] TCA tree 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 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
18 use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20
21 /**
22 * Render data as a tree.
23 *
24 * Typically rendered for config type=select, renderType=selectTree
25 */
26 class SelectTreeElement extends AbstractFormElement
27 {
28 /**
29 * Default number of tree nodes to show (determines tree height)
30 * when no ['config']['size'] is set
31 *
32 * @var int
33 */
34 protected $itemsToShow = 15;
35
36 /**
37 * Number of items to show at last
38 * e.g. when you have only 2 items in a tree
39 *
40 * @var int
41 */
42 protected $minItemsToShow = 5;
43
44 /**
45 * Pixel height of a single tree node
46 *
47 * @var int
48 */
49 protected $itemHeight = 20;
50
51 /**
52 * Render tree widget
53 *
54 * @return array As defined in initializeResultArray() of AbstractNode
55 * @see AbstractNode::initializeResultArray()
56 */
57 public function render()
58 {
59 $resultArray = $this->initializeResultArray();
60 $parameterArray = $this->data['parameterArray'];
61 $formElementId = md5($parameterArray['itemFormElName']);
62
63 // Field configuration from TCA:
64 $config = $parameterArray['fieldConf']['config'];
65 $readOnly = !empty($config['readOnly']) ? 'true' : 'false';
66 $exclusiveKeys = !empty($config['exclusiveKeys']) ? $config['exclusiveKeys'] : '';
67 $exclusiveKeys = $exclusiveKeys . ',';
68 $appearance = !empty($config['treeConfig']['appearance']) ? $config['treeConfig']['appearance'] : [];
69 $expanded = !empty($appearance['expandAll']);
70 $showHeader = !empty($appearance['showHeader']);
71 if (isset($config['size']) && (int)$config['size'] > 0) {
72 $height = max($this->minItemsToShow, (int)$config['size']);
73 } else {
74 $height = $this->itemsToShow;
75 }
76 $heightInPx = $height * $this->itemHeight;
77 $treeWrapperId = 'tree_' . $formElementId;
78
79 $fieldName = $this->data['fieldName'];
80 $flexDataStructureIdentifier = '';
81 if ($this->data['processedTca']['columns'][$fieldName]['config']['type'] === 'flex') {
82 $flexDataStructureIdentifier = $this->data['processedTca']['columns'][$fieldName]['config']['dataStructureIdentifier'];
83 }
84
85 $html = [];
86 $html[] = '<div class="typo3-tceforms-tree">';
87 $html[] = ' <input class="treeRecord" type="hidden"';
88 $html[] = ' ' . $this->getValidationDataAsDataAttribute($config);
89 $html[] = ' data-formengine-input-name="' . htmlspecialchars($parameterArray['itemFormElName']) . '"';
90 $html[] = ' data-relatedfieldname="' . htmlspecialchars($parameterArray['itemFormElName']) . '"';
91 $html[] = ' data-table="' . htmlspecialchars($this->data['tableName']) . '"';
92 $html[] = ' data-field="' . htmlspecialchars($this->data['fieldName']) . '"';
93 $html[] = ' data-flex-form-datastructure-identifier="' . htmlspecialchars($flexDataStructureIdentifier) . '"';
94 $html[] = ' data-uid="' . (int)$this->data['vanillaUid'] . '"';
95 $html[] = ' data-recordtypevalue="' . $this->data['recordTypeValue'] . '"';
96 $html[] = ' data-command="' . htmlspecialchars($this->data['command']) . '"';
97 $html[] = ' data-read-only="' . $readOnly . '"';
98 $html[] = ' data-tree-exclusive-keys="' . htmlspecialchars($exclusiveKeys) . '"';
99 $html[] = ' data-tree-expand-up-to-level="' . ($expanded ? '999' : '1') . '"';
100 $html[] = ' data-tree-show-toolbar="' . $showHeader . '"';
101 $html[] = ' name="' . htmlspecialchars($parameterArray['itemFormElName']) . '"';
102 $html[] = ' id="treeinput' . $formElementId . '"';
103 $html[] = ' value=""';
104 $html[] = ' />';
105 $html[] = '</div>';
106 $html[] = '<div id="' . $treeWrapperId . '" class="svg-tree-wrapper" style="height: ' . $heightInPx . 'px;"></div>';
107 $html[] = '<script type="text/javascript">var ' . $treeWrapperId . ' = ' . $this->getTreeOnChangeJs() . '</script>';
108
109 $resultArray['html'] = implode(LF, $html);
110
111 // add necessary labels for tree header
112 if ($showHeader) {
113 $resultArray['additionalInlineLanguageLabelFiles'][] = 'EXT:lang/Resources/Private/Language/locallang_csh_corebe.xlf';
114 }
115 $resultArray['requireJsModules']['selectTreeElement'] = [
116 'TYPO3/CMS/Backend/FormEngine/Element/SelectTreeElement' => 'function (SelectTreeElement) { SelectTreeElement.initialize(); }'
117 ];
118
119 return $resultArray;
120 }
121
122 /**
123 * Generates JS code triggered on change of the tree
124 *
125 * @return string
126 */
127 protected function getTreeOnChangeJs()
128 {
129 $table = $this->data['tableName'];
130 $field = $this->data['fieldName'];
131 $parameterArray = $this->data['parameterArray'];
132 $onChange = !empty($parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged']) ? $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] : '';
133 $onChange .= !empty($parameterArray['fieldChangeFunc']['alert']) ? $parameterArray['fieldChangeFunc']['alert'] : '';
134
135 // Create a JavaScript code line which will ask the user to save/update the form due to changing the element.
136 // This is used for eg. "type" fields and others configured with "requestUpdate"
137 if (
138 !empty($GLOBALS['TCA'][$table]['ctrl']['type'])
139 && $field === $GLOBALS['TCA'][$table]['ctrl']['type']
140 || !empty($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'])
141 && GeneralUtility::inList(str_replace(' ', '', $GLOBALS['TCA'][$table]['ctrl']['requestUpdate']), $field)
142 ) {
143 if ($this->getBackendUserAuthentication()->jsConfirmation(JsConfirmation::TYPE_CHANGE)) {
144 $onChange = 'top.TYPO3.Modal.confirm(TYPO3.lang["FormEngine.refreshRequiredTitle"], TYPO3.lang["FormEngine.refreshRequiredContent"]).on("button.clicked", function(e) { if (e.target.name == "ok" && TBE_EDITOR.checkSubmit(-1)) { TBE_EDITOR.submitForm() } top.TYPO3.Modal.dismiss(); });';
145 } else {
146 $onChange .= 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };';
147 }
148 }
149 return 'function () {' . $onChange . '}';
150 }
151
152 /**
153 * @return BackendUserAuthentication
154 */
155 protected function getBackendUserAuthentication()
156 {
157 return $GLOBALS['BE_USER'];
158 }
159 }