[!!!][TASK] Remove static file edit magic
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / Element / TextElement.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\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Core\Html\RteHtmlParser;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20 use TYPO3\CMS\Core\Utility\MathUtility;
21
22 /**
23 * Generation of TCEform elements of the type "text"
24 */
25 class TextElement extends AbstractFormElement {
26
27 /**
28 * This will render a <textarea> OR RTE area form field,
29 * possibly with various control/validation features
30 *
31 * @param string $table The table name of the record
32 * @param string $field The field name which this element is supposed to edit
33 * @param array $row The record data array where the value(s) for the field can be found
34 * @param array $additionalInformation An array with additional configuration options.
35 * @return string The HTML code for the TCEform field
36 */
37 public function render($table, $field, $row, &$additionalInformation) {
38 $config = $additionalInformation['fieldConf']['config'];
39 if ($this->formEngine->renderReadonly || $config['readOnly']) {
40 return $this->formEngine->getSingleField_typeNone_render($config, $additionalInformation['itemFormElValue']);
41 }
42
43 // Setting columns number
44 $cols = MathUtility::forceIntegerInRange($config['cols'] ?: 30, 5, $this->formEngine->maxTextareaWidth);
45
46 // Setting number of rows
47 $rows = MathUtility::forceIntegerInRange($config['rows'] ?: 5, 1, 20);
48 $originalRows = $rows;
49
50 $itemFormElementValueLength = strlen($additionalInformation['itemFormElValue']);
51 if ($itemFormElementValueLength > $this->formEngine->charsPerRow * 2) {
52 $cols = $this->formEngine->maxTextareaWidth;
53 $rows = MathUtility::forceIntegerInRange(
54 round($itemFormElementValueLength / $this->formEngine->charsPerRow),
55 count(explode(LF, $additionalInformation['itemFormElValue'])),
56 20
57 );
58 if ($rows < $originalRows) {
59 $rows = $originalRows;
60 }
61 }
62
63 $evalList = GeneralUtility::trimExplode(',', $config['eval'], TRUE);
64 if (in_array('required', $evalList, TRUE)) {
65 $this->formEngine->requiredFields[$table . '_' . $row['uid'] . '_' . $field] = $additionalInformation['itemFormElName'];
66 }
67 // Init RTE vars
68 // Set TRUE, if the RTE is loaded; If not a normal textarea is shown.
69 $rteWasLoaded = FALSE;
70 // Set TRUE, if the RTE would have been loaded if it wasn't for the disable-RTE flag in the bottom of the page...
71 $rteWouldHaveBeenLoaded = FALSE;
72 // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. Traditionally, this is where RTE configuration has been found.
73 $specialConfiguration = $this->formEngine->getSpecConfFromString($additionalInformation['extra'], $additionalInformation['fieldConf']['defaultExtras']);
74 // Setting up the altItem form field, which is a hidden field containing the value
75 $altItem = '<input type="hidden" name="' . htmlspecialchars($additionalInformation['itemFormElName']) . '" value="' . htmlspecialchars($additionalInformation['itemFormElValue']) . '" />';
76 $item = '';
77 // If RTE is generally enabled (TYPO3_CONF_VARS and user settings)
78 if ($this->formEngine->RTEenabled) {
79 $parameters = BackendUtility::getSpecConfParametersFromArray($specialConfiguration['rte_transform']['parameters']);
80 // If the field is configured for RTE and if any flag-field is not set to disable it.
81 if (isset($specialConfiguration['richtext']) && (!$parameters['flag'] || !$row[$parameters['flag']])) {
82 BackendUtility::fixVersioningPid($table, $row);
83 list($recordPid, $tsConfigPid) = $this->formEngine->getTSCpid($table, $row['uid'], $row['pid']);
84 // If the pid-value is not negative (that is, a pid could NOT be fetched)
85 if ($tsConfigPid >= 0) {
86 $rteSetup = $this->getBackendUserAuthentication()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($recordPid));
87 $rteTcaTypeValue = BackendUtility::getTCAtypeValue($table, $row);
88 $rteSetupConfiguration = BackendUtility::RTEsetup($rteSetup['properties'], $table, $field, $rteTcaTypeValue);
89 if (!$rteSetupConfiguration['disabled']) {
90 if (!$this->formEngine->disableRTE) {
91 $this->formEngine->RTEcounter++;
92 // Get RTE object, draw form and set flag:
93 $rteObject = BackendUtility::RTEgetObj();
94 $item = $rteObject->drawRTE(
95 $this->formEngine,
96 $table,
97 $field,
98 $row,
99 $additionalInformation,
100 $specialConfiguration,
101 $rteSetupConfiguration,
102 $rteTcaTypeValue,
103 '',
104 $tsConfigPid
105 );
106
107 // Wizard
108 $item = $this->formEngine->renderWizards(
109 array($item, $altItem),
110 $config['wizards'],
111 $table,
112 $row,
113 $field,
114 $additionalInformation,
115 $additionalInformation['itemFormElName'],
116 $specialConfiguration,
117 TRUE
118 );
119 $rteWasLoaded = TRUE;
120 } else {
121 $rteWouldHaveBeenLoaded = TRUE;
122 $this->formEngine->commentMessages[] = $additionalInformation['itemFormElName'] . ': RTE is disabled by the on-page RTE-flag (probably you can enable it by the check-box in the bottom of this page!)';
123 }
124 } else {
125 $this->formEngine->commentMessages[] = $additionalInformation['itemFormElName'] . ': RTE is disabled by the Page TSconfig, "RTE"-key (eg. by RTE.default.disabled=0 or such)';
126 }
127 } else {
128 $this->formEngine->commentMessages[] = $additionalInformation['itemFormElName'] . ': PID value could NOT be fetched. Rare error, normally with new records.';
129 }
130 } else {
131 if (!isset($specialConfiguration['richtext'])) {
132 $this->formEngine->commentMessages[] = $additionalInformation['itemFormElName'] . ': RTE was not configured for this field in TCA-types';
133 }
134 if (!(!$parameters['flag'] || !$row[$parameters['flag']])) {
135 $this->formEngine->commentMessages[] = $additionalInformation['itemFormElName'] . ': Field-flag (' . $additionalInformation['flag'] . ') has been set to disable RTE!';
136 }
137 }
138 }
139 // Display ordinary field if RTE was not loaded.
140 if (!$rteWasLoaded) {
141 // Show message, if no RTE (field can only be edited with RTE!)
142 if ($specialConfiguration['rte_only']) {
143 $item = '<p><em>' . htmlspecialchars($this->formEngine->getLL('l_noRTEfound')) . '</em></p>';
144 } else {
145 if ($specialConfiguration['nowrap']) {
146 $wrap = 'off';
147 } else {
148 $wrap = $config['wrap'] ?: 'virtual';
149 }
150 $classes = array();
151 if ($specialConfiguration['fixed-font']) {
152 $classes[] = 'fixed-font';
153 }
154 if ($specialConfiguration['enable-tab']) {
155 $classes[] = 'enable-tab';
156 }
157 $formWidthText = $this->formWidthText($cols, $wrap);
158 // Extract class attributes from $formWidthText (otherwise it would be added twice to the output)
159 $res = array();
160 if (preg_match('/ class="(.+?)"/', $formWidthText, $res)) {
161 $formWidthText = str_replace(' class="' . $res[1] . '"', '', $formWidthText);
162 $classes = array_merge($classes, explode(' ', $res[1]));
163 }
164
165 if (!empty($classes)) {
166 $class = ' class="tceforms-textarea ' . implode(' ', $classes) . '"';
167 } else {
168 $class = ' class="tceforms-textarea"';
169 }
170
171 foreach ($evalList as $func) {
172 if ($func === 'required') {
173 $this->formEngine->registerRequiredProperty('field', $table . '_' . $row['uid'] . '_' . $field, $additionalInformation['itemFormElName']);
174 } else {
175 // Pair hook to the one in \TYPO3\CMS\Core\DataHandling\DataHandler::checkValue_input_Eval()
176 // and \TYPO3\CMS\Core\DataHandling\DataHandler::checkValue_text_Eval()
177 $evalObj = GeneralUtility::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func] . ':&' . $func);
178 if (is_object($evalObj) && method_exists($evalObj, 'deevaluateFieldValue')) {
179 $_params = array(
180 'value' => $additionalInformation['itemFormElValue']
181 );
182 $additionalInformation['itemFormElValue'] = $evalObj->deevaluateFieldValue($_params);
183 }
184 }
185 }
186 $textOnChange = implode('', $additionalInformation['fieldChangeFunc']);
187 $item .= '
188 <textarea ' . 'id="' . str_replace('.', '', uniqid('tceforms-textarea-', TRUE)) . '" ' . 'name="' . $additionalInformation['itemFormElName']
189 . '"' . $formWidthText . $class . ' ' . 'rows="' . $rows . '" ' . 'wrap="' . $wrap . '" ' . 'onchange="'
190 . htmlspecialchars($textOnChange) . '"' . $this->formEngine->getPlaceholderAttribute($table, $field, $config, $row)
191 . $additionalInformation['onFocus'] . '>' . GeneralUtility::formatForTextarea($additionalInformation['itemFormElValue']) . '</textarea>';
192 $item = $this->formEngine->renderWizards(
193 array($item, $altItem),
194 $config['wizards'],
195 $table,
196 $row,
197 $field,
198 $additionalInformation,
199 $additionalInformation['itemFormElName'],
200 $specialConfiguration,
201 $rteWouldHaveBeenLoaded
202 );
203 }
204 }
205 return $item;
206 }
207
208 /**
209 * Returns parameters to set with for a textarea field
210 *
211 * @param int $size The abstract width (1-48)
212 * @param string $wrap Empty or "off" (text wrapping in the field or not)
213 * @return string The "cols" attribute string (or style from formWidth())
214 * @see formWidth()
215 */
216 protected function formWidthText($size = 48, $wrap = '') {
217 $wTags = $this->formEngine->formWidth($size, TRUE);
218 // Netscape 6+ seems to have this ODD problem where there WILL ALWAYS be wrapping
219 // with the cols-attribute set and NEVER without the col-attribute...
220 if (strtolower(trim($wrap)) != 'off' && $GLOBALS['CLIENT']['BROWSER'] == 'net' && $GLOBALS['CLIENT']['VERSION'] >= 5) {
221 $wTags .= ' cols="' . $size . '"';
222 }
223 return $wTags;
224 }
225 }