[TASK] Use makeInstance in some hooks
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / Element / InputElement.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\Backend\Utility\IconUtility;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20 use TYPO3\CMS\Core\Utility\MathUtility;
21 use TYPO3\CMS\Backend\Form\NodeFactory;
22
23 /**
24 * Generation of TCEform elements of the type "input"
25 */
26 class InputElement extends AbstractFormElement {
27
28 /**
29 * This will render a single-line input form field, possibly with various control/validation features
30 *
31 * @return array As defined in initializeResultArray() of AbstractNode
32 */
33 public function render() {
34 $languageService = $this->getLanguageService();
35
36 $table = $this->globalOptions['table'];
37 $fieldName = $this->globalOptions['fieldName'];
38 $row = $this->globalOptions['databaseRow'];
39 $parameterArray = $this->globalOptions['parameterArray'];
40 $resultArray = $this->initializeResultArray();
41 $isDateField = FALSE;
42
43 $config = $parameterArray['fieldConf']['config'];
44 $specConf = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
45 $size = MathUtility::forceIntegerInRange($config['size'] ?: $this->defaultInputWidth, $this->minimumInputWidth, $this->maxInputWidth);
46 $evalList = GeneralUtility::trimExplode(',', $config['eval'], TRUE);
47 $classes = array();
48 $attributes = array();
49
50 if (!isset($config['checkbox'])) {
51 $config['checkbox'] = '0';
52 $checkboxIsset = FALSE;
53 } else {
54 $checkboxIsset = TRUE;
55 }
56
57 // set all date times available
58 $dateFormats = array(
59 'date' => '%d-%m-%Y',
60 'year' => '%Y',
61 'time' => '%H:%M',
62 'timesec' => '%H:%M:%S'
63 );
64 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat']) {
65 $dateFormats['date'] = '%m-%d-%Y';
66 }
67 $dateFormats['datetime'] = $dateFormats['time'] . ' ' . $dateFormats['date'];
68 $dateFormats['datetimesec'] = $dateFormats['timesec'] . ' ' . $dateFormats['date'];
69
70 // readonly
71 if ($this->isGlobalReadonly() || $config['readOnly']) {
72 $itemFormElValue = $parameterArray['itemFormElValue'];
73 if (in_array('date', $evalList)) {
74 $config['format'] = 'date';
75 } elseif (in_array('datetime', $evalList)) {
76 $config['format'] = 'datetime';
77 } elseif (in_array('time', $evalList)) {
78 $config['format'] = 'time';
79 }
80 if (in_array('password', $evalList)) {
81 $itemFormElValue = $itemFormElValue ? '*********' : '';
82 }
83 $options = $this->globalOptions;
84 $options['parameterArray'] = array(
85 'fieldConf' => array(
86 'config' => $config,
87 ),
88 'itemFormElValue' => $itemFormElValue,
89 );
90 $options['renderType'] = 'none';
91 /** @var NodeFactory $nodeFactory */
92 $nodeFactory = $this->globalOptions['nodeFactory'];
93 return $nodeFactory->create($options)->render();
94 }
95
96 if (in_array('datetime', $evalList, TRUE)
97 || in_array('date', $evalList)) {
98
99 $classes[] = 't3js-datetimepicker';
100 $isDateField = TRUE;
101 if (in_array('datetime', $evalList)) {
102 $attributes['data-date-type'] = 'datetime';
103 $dateFormat = $dateFormats['datetime'];
104 } elseif (in_array('date', $evalList)) {
105 $attributes['data-date-type'] = 'date';
106 $dateFormat = $dateFormats['date'];
107 }
108 if ($parameterArray['itemFormElValue'] > 0) {
109 $parameterArray['itemFormElValue'] += date('Z', $parameterArray['itemFormElValue']);
110 }
111 if (isset($config['range']['lower'])) {
112 $attributes['data-date-minDate'] = (int)$config['range']['lower'];
113 }
114 if (isset($config['range']['upper'])) {
115 $attributes['data-date-maxDate'] = (int)$config['range']['upper'];
116 }
117 } elseif (in_array('time', $evalList)) {
118 $dateFormat = $dateFormats['time'];
119 $isDateField = TRUE;
120 $classes[] = 't3js-datetimepicker';
121 $attributes['data-date-type'] = 'time';
122 } elseif (in_array('timesec', $evalList)) {
123 $dateFormat = $dateFormats['timesec'];
124 $isDateField = TRUE;
125 $classes[] = 't3js-datetimepicker';
126 $attributes['data-date-type'] = 'timesec';
127 } else {
128 if ($checkboxIsset === FALSE) {
129 $config['checkbox'] = '';
130 }
131 }
132
133 // @todo: The whole eval handling is a mess and needs refactoring
134 foreach ($evalList as $func) {
135 switch ($func) {
136 case 'required':
137 $resultArray['requiredFields'][$table . '_' . $row['uid'] . '_' . $fieldName] = $parameterArray['itemFormElName'];
138 $tabAndInlineStack = $this->globalOptions['tabAndInlineStack'];
139 if (!empty($tabAndInlineStack) && preg_match('/^(.+\\])\\[(\\w+)\\]$/', $parameterArray['itemFormElName'], $match)) {
140 array_shift($match);
141 $resultArray['requiredNested'][$parameterArray['itemFormElName']] = array(
142 'parts' => $match,
143 'level' => $tabAndInlineStack,
144 );
145 }
146 // Mark this field for date/time disposal:
147 if (array_intersect($evalList, array('date', 'datetime', 'time', 'timesec'))) {
148 $resultArray['requiredAdditional'][$parameterArray['itemFormElName']] = array(
149 'isPositiveNumber' => TRUE,
150 );
151 }
152 break;
153 default:
154 // @todo: This is ugly: The code should find out on it's own whether a eval definition is a
155 // @todo: keyword like "date", or a class reference. The global registration could be dropped then
156 // Pair hook to the one in \TYPO3\CMS\Core\DataHandling\DataHandler::checkValue_input_Eval()
157 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func])) {
158 if (class_exists($func)) {
159 $evalObj = GeneralUtility::makeInstance($func);
160 if (method_exists($evalObj, 'deevaluateFieldValue')) {
161 $_params = array(
162 'value' => $parameterArray['itemFormElValue']
163 );
164 $parameterArray['itemFormElValue'] = $evalObj->deevaluateFieldValue($_params);
165 }
166 }
167 }
168 }
169 }
170 $paramsList = GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . ',' . GeneralUtility::quoteJSvalue(implode(',', $evalList)) . ',' . GeneralUtility::quoteJSvalue(trim($config['is_in'])) . ',' . ($config['checkbox'] ? 1 : 0) . ',' . GeneralUtility::quoteJSvalue($config['checkbox']);
171 $parameterArray['fieldChangeFunc'] = array_merge(array('typo3form.fieldGet' => 'typo3form.fieldGet(' . $paramsList . ');'), $parameterArray['fieldChangeFunc']);
172
173 // set classes
174 $classes[] = 'form-control';
175 $classes[] = 't3js-clearable';
176 $classes[] = 'hasDefaultValue';
177
178 // calculate attributes
179 $attributes['id'] = str_replace('.', '', uniqid('formengine-input-', TRUE));
180 $attributes['name'] = $parameterArray['itemFormElName'] . '_hr';
181 $attributes['value'] = '';
182 $attributes['maxlength'] = $config['max'] ?: 256;
183 $attributes['onchange'] = implode('', $parameterArray['fieldChangeFunc']);
184
185 if (!empty($styles)) {
186 $attributes['style'] = implode(' ', $styles);
187 }
188 if (!empty($classes)) {
189 $attributes['class'] = implode(' ', $classes);
190 }
191 if (isset($config['max']) && (int)$config['max'] > 0) {
192 $attributes['maxlength'] = (int)$config['max'];
193 }
194
195 // Build the attribute string
196 $attributeString = '';
197 foreach ($attributes as $attributeName => $attributeValue) {
198 $attributeString .= ' ' . $attributeName . '="' . htmlspecialchars($attributeValue) . '"';
199 }
200
201 // This is the EDITABLE form field.
202 $placeholderValue = $this->getPlaceholderValue($table, $config, $row);
203 $placeholderAttribute = '';
204 if (!empty($placeholderValue)) {
205 $placeholderAttribute = ' placeholder="' . htmlspecialchars(trim($languageService->sL($placeholderValue))) . '" ';
206 }
207
208 $html = '
209 <input type="text"'
210 . $attributeString
211 . $placeholderAttribute
212 . $parameterArray['onFocus'] . ' />';
213
214 // This is the ACTUAL form field - values from the EDITABLE field must be transferred to this field which is the one that is written to the database.
215 $html .= '<input type="hidden" name="' . $parameterArray['itemFormElName'] . '" value="' . htmlspecialchars($parameterArray['itemFormElValue']) . '" />';
216
217 $resultArray['extJSCODE'] = 'typo3form.fieldSet(' . $paramsList . ');';
218
219 // Going through all custom evaluations configured for this field
220 // @todo: Similar to above code!
221 foreach ($evalList as $evalData) {
222 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$evalData])) {
223 if (class_exists($evalData)) {
224 $evalObj = GeneralUtility::makeInstance($evalData);
225 if (method_exists($evalObj, 'returnFieldJS')) {
226 $resultArray['extJSCODE'] .= LF . 'TBE_EDITOR.customEvalFunctions[' . GeneralUtility::quoteJSvalue($evalData) . '] = function(value) {' . $evalObj->returnFieldJS() . '}';
227 }
228 }
229 }
230 }
231
232 // add HTML wrapper
233 if ($isDateField) {
234 $html = '
235 <div class="input-group">
236 ' . $html . '
237 <span class="input-group-btn">
238 <label class="btn btn-default" for="' . $attributes['id'] . '">
239 ' . IconUtility::getSpriteIcon('actions-edit-pick-date') . '
240 </label>
241 </span>
242 </div>';
243 }
244
245 // Creating an alternative item without the JavaScript handlers.
246 $altItem = '
247 <input type="hidden" name="' . htmlspecialchars($parameterArray['itemFormElName']) . '_hr" value="" />
248 <input type="hidden" name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" value="' . htmlspecialchars($parameterArray['itemFormElValue']) . '" />';
249
250 // Wrap a wizard around the item?
251 $html = $this->renderWizards(
252 array($html, $altItem),
253 $config['wizards'],
254 $table,
255 $row,
256 $fieldName,
257 $parameterArray,
258 $parameterArray['itemFormElName'] . '_hr', $specConf
259 );
260
261 // Add a wrapper to remain maximum width
262 $width = (int)$this->formMaxWidth($size);
263 $html = '<div class="form-control-wrap"' . ($width ? ' style="max-width: ' . $width . 'px"' : '') . '>' . $html . '</div>';
264 $resultArray['html'] = $html;
265 return $resultArray;
266 }
267
268 }