[!!!][FEATURE] FormEngine element level refactoring
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / Element / TextTableElement.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\Utility\GeneralUtility;
19 use TYPO3\CMS\Core\Utility\MathUtility;
20 use TYPO3\CMS\Core\Utility\StringUtility;
21
22 /**
23 * Generation of TCEform elements of the type "text"
24 */
25 class TextTableElement extends AbstractFormElement
26 {
27 /**
28 * Default field wizards enabled for this element.
29 *
30 * @var array
31 */
32 protected $defaultFieldWizard = [
33 'otherLanguageContent' => [
34 'renderType' => 'otherLanguageContent',
35 ],
36 'defaultLanguageDifferences' => [
37 'renderType' => 'defaultLanguageDifferences',
38 'after' => [
39 'otherLanguageContent',
40 ],
41 ],
42 ];
43
44 /**
45 * This renderType adds the "table wizard icon" by default (on not new records)
46 *
47 * @var array
48 */
49 protected $defaultFieldControl = [
50 'tableWizard' => [
51 'renderType' => 'tableWizard',
52 ],
53 ];
54
55 /**
56 * The number of chars expected per row when the height of a text area field is
57 * automatically calculated based on the number of characters found in the field content.
58 *
59 * @var int
60 */
61 protected $charactersPerRow = 40;
62
63 /**
64 * This will render a <textarea> with table wizard
65 *
66 * @return array As defined in initializeResultArray() of AbstractNode
67 */
68 public function render()
69 {
70 $backendUser = $this->getBackendUserAuthentication();
71
72 $parameterArray = $this->data['parameterArray'];
73 $resultArray = $this->initializeResultArray();
74
75 $itemValue = $parameterArray['itemFormElValue'];
76 $config = $parameterArray['fieldConf']['config'];
77 $evalList = GeneralUtility::trimExplode(',', $config['eval'], true);
78 $cols = MathUtility::forceIntegerInRange($config['cols'] ?: $this->defaultInputWidth, $this->minimumInputWidth, $this->maxInputWidth);
79 $width = $this->formMaxWidth($cols);
80
81 // Setting number of rows
82 $rows = MathUtility::forceIntegerInRange($config['rows'] ?: 5, 1, 20);
83 $originalRows = $rows;
84 $itemFormElementValueLength = strlen($itemValue);
85 if ($itemFormElementValueLength > $this->charactersPerRow * 2) {
86 $rows = MathUtility::forceIntegerInRange(
87 round($itemFormElementValueLength / $this->charactersPerRow),
88 count(explode(LF, $itemValue)),
89 20
90 );
91 if ($rows < $originalRows) {
92 $rows = $originalRows;
93 }
94 }
95
96 if ($config['readOnly']) {
97 $html = [];
98 $html[] = '<div class="t3js-formengine-field-item">';
99 $html[] = '<div class="form-wizards-wrap">';
100 $html[] = '<div class="form-wizards-element">';
101 $html[] = '<div class="form-control-wrap" style="max-width: ' . $width . 'px">';
102 $html[] = '<textarea class="form-control" rows="' . $rows . '" disabled>';
103 $html[] = htmlspecialchars($itemValue);
104 $html[] = '</textarea>';
105 $html[] = '</div>';
106 $html[] = '</div>';
107 $html[] = '</div>';
108 $html[] = '</div>';
109 $resultArray['html'] = implode(LF, $html);
110 return $resultArray;
111 }
112
113 // @todo: The whole eval handling is a mess and needs refactoring
114 foreach ($evalList as $func) {
115 // @todo: This is ugly: The code should find out on it's own whether a eval definition is a
116 // @todo: keyword like "date", or a class reference. The global registration could be dropped then
117 // Pair hook to the one in \TYPO3\CMS\Core\DataHandling\DataHandler::checkValue_input_Eval()
118 // There is a similar hook for "evaluateFieldValue" in DataHandler and InputTextElement
119 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func])) {
120 if (class_exists($func)) {
121 $evalObj = GeneralUtility::makeInstance($func);
122 if (method_exists($evalObj, 'deevaluateFieldValue')) {
123 $_params = [
124 'value' => $itemValue
125 ];
126 $itemValue = $evalObj->deevaluateFieldValue($_params);
127 }
128 }
129 }
130 }
131
132 $attributes = [
133 'id' => StringUtility::getUniqueId('formengine-textarea-'),
134 'name' => htmlspecialchars($parameterArray['itemFormElName']),
135 'data-formengine-validation-rules' => $this->getValidationDataAsJsonString($config),
136 'data-formengine-input-name' => htmlspecialchars($parameterArray['itemFormElName']),
137 'rows' => $rows,
138 'wrap' => $config['wrap'] ?: 'virtual',
139 'onChange' => implode('', $parameterArray['fieldChangeFunc']),
140 ];
141 $classes = [
142 'form-control',
143 't3js-formengine-textarea',
144 'formengine-textarea',
145 ];
146 if ($config['fixedFont']) {
147 $classes[] = 'text-monospace';
148 }
149 if ($config['enableTabulator']) {
150 $classes[] = 't3js-enable-tab';
151 }
152 $attributes['class'] = implode(' ', $classes);
153 $maximumHeight = (int)$backendUser->uc['resizeTextareas_MaxHeight'];
154 if ($maximumHeight > 0) {
155 // add the max-height from the users' preference to it
156 $attributes['style'] = 'max-height: ' . $maximumHeight . 'px';
157 }
158 if (isset($config['max']) && (int)$config['max'] > 0) {
159 $attributes['maxlength'] = (int)$config['max'];
160 }
161 if (!empty($config['placeholder'])) {
162 $attributes['placeholder'] = htmlspecialchars(trim($config['placeholder']));
163 }
164
165 $legacyWizards = $this->renderWizards();
166 $legacyFieldControlHtml = implode(LF, $legacyWizards['fieldControl']);
167 $legacyFieldWizardHtml = implode(LF, $legacyWizards['fieldWizard']);
168
169 $fieldInformationResult = $this->renderFieldInformation();
170 $fieldInformationHtml = $fieldInformationResult['html'];
171 $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
172
173 $fieldControlResult = $this->renderFieldControl();
174 $fieldControlHtml = $legacyFieldControlHtml . $fieldControlResult['html'];
175 $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldControlResult, false);
176
177 $fieldWizardResult = $this->renderFieldWizard();
178 $fieldWizardHtml = $legacyFieldWizardHtml . $fieldWizardResult['html'];
179 $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
180
181 $html = [];
182 $html[] = '<div class="t3js-formengine-field-item">';
183 $html[] = $fieldInformationHtml;
184 $html[] = '<div class="form-control-wrap" style="max-width: ' . $width . 'px">';
185 $html[] = '<div class="form-wizards-wrap">';
186 $html[] = '<div class="form-wizards-element">';
187 $html[] = '<textarea ' . GeneralUtility::implodeAttributes($attributes, true) . '>';
188 $html[] = htmlspecialchars($itemValue);
189 $html[] = '</textarea>';
190 $html[] = '</div>';
191 $html[] = '<div class="form-wizards-items-aside">';
192 $html[] = '<div class="btn-group">';
193 $html[] = $fieldControlHtml;
194 $html[] = '</div>';
195 $html[] = '</div>';
196 $html[] = '<div class="form-wizards-items-bottom">';
197 $html[] = $fieldWizardHtml;
198 $html[] = '</div>';
199 $html[] = '</div>';
200 $html[] = '</div>';
201 $html[] = '</div>';
202
203 $resultArray['html'] = implode(LF, $html);
204 return $resultArray;
205 }
206
207 /**
208 * @return BackendUserAuthentication
209 */
210 protected function getBackendUserAuthentication()
211 {
212 return $GLOBALS['BE_USER'];
213 }
214 }