[!!!][TASK] Drop TYPO3_CONF_VARS['SYS]['form_enctype']
[Packages/TYPO3.CMS.git] / typo3 / sysext / compatibility6 / Classes / ContentObject / FormContentObject.php
1 <?php
2 namespace TYPO3\CMS\Compatibility6\ContentObject;
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 * Contains FORM class object.
21 */
22 class FormContentObject extends \TYPO3\CMS\Frontend\ContentObject\AbstractContentObject {
23
24 /**
25 * Rendering the cObject, FORM
26 *
27 * Note on $formData:
28 * In the optional $formData array each entry represents a line in the ordinary setup.
29 * In those entries each entry (0,1,2...) represents a space normally divided by the '|' line.
30 *
31 * $formData [] = array('Name:', 'name=input, 25 ', 'Default value....');
32 * $formData [] = array('Email:', 'email=input, 25 ', 'Default value for email....');
33 *
34 * - corresponds to the $conf['data'] value being :
35 * Name:|name=input, 25 |Default value....||Email:|email=input, 25 |Default value for email....
36 *
37 * If $formData is an array the value of $conf['data'] is ignored.
38 *
39 * @param array $conf Array of TypoScript properties
40 * @param array $formData Alternative formdata overriding whatever comes from TypoScript
41 * @return string Output
42 */
43 public function render($conf = array(), $formData = '') {
44 $content = '';
45 if (is_array($formData)) {
46 $dataArray = $formData;
47 } else {
48 $data = isset($conf['data.']) ? $this->cObj->stdWrap($conf['data'], $conf['data.']) : $conf['data'];
49 // Clearing dataArr
50 $dataArray = array();
51 // Getting the original config
52 if (trim($data)) {
53 $data = str_replace(LF, '||', $data);
54 $dataArray = explode('||', $data);
55 }
56 // Adding the new dataArray config form:
57 if (is_array($conf['dataArray.'])) {
58 // dataArray is supplied
59 $sortedKeyArray = \TYPO3\CMS\Core\TypoScript\TemplateService::sortedKeyList($conf['dataArray.'], TRUE);
60 foreach ($sortedKeyArray as $theKey) {
61 $singleKeyArray = $conf['dataArray.'][$theKey . '.'];
62 if (is_array($singleKeyArray)) {
63 $temp = array();
64 $label = isset($singleKeyArray['label.']) ? $this->cObj->stdWrap($singleKeyArray['label'], $singleKeyArray['label.']) : $singleKeyArray['label'];
65 list($temp[0]) = explode('|', $label);
66 $type = isset($singleKeyArray['type.']) ? $this->cObj->stdWrap($singleKeyArray['type'], $singleKeyArray['type.']) : $singleKeyArray['type'];
67 list($temp[1]) = explode('|', $type);
68 $required = isset($singleKeyArray['required.']) ? $this->cObj->stdWrap($singleKeyArray['required'], $singleKeyArray['required.']) : $singleKeyArray['required'];
69 if ($required) {
70 $temp[1] = '*' . $temp[1];
71 }
72 $singleValue = isset($singleKeyArray['value.']) ? $this->cObj->stdWrap($singleKeyArray['value'], $singleKeyArray['value.']) : $singleKeyArray['value'];
73 list($temp[2]) = explode('|', $singleValue);
74 // If value array is set, then implode those values.
75 if (is_array($singleKeyArray['valueArray.'])) {
76 $temp_accumulated = array();
77 foreach ($singleKeyArray['valueArray.'] as $singleKey => $singleKey_valueArray) {
78 if (is_array($singleKey_valueArray) && (int)$singleKey . '.' === (string)$singleKey) {
79 $temp_valueArray = array();
80 $valueArrayLabel = isset($singleKey_valueArray['label.']) ? $this->cObj->stdWrap($singleKey_valueArray['label'], $singleKey_valueArray['label.']) : $singleKey_valueArray['label'];
81 list($temp_valueArray[0]) = explode('=', $valueArrayLabel);
82 $selected = isset($singleKey_valueArray['selected.']) ? $this->cObj->stdWrap($singleKey_valueArray['selected'], $singleKey_valueArray['selected.']) : $singleKey_valueArray['selected'];
83 if ($selected) {
84 $temp_valueArray[0] = '*' . $temp_valueArray[0];
85 }
86 $singleKeyValue = isset($singleKey_valueArray['value.']) ? $this->cObj->stdWrap($singleKey_valueArray['value'], $singleKey_valueArray['value.']) : $singleKey_valueArray['value'];
87 list($temp_valueArray[1]) = explode(',', $singleKeyValue);
88 }
89 $temp_accumulated[] = implode('=', $temp_valueArray);
90 }
91 $temp[2] = implode(',', $temp_accumulated);
92 }
93 $specialEval = isset($singleKeyArray['specialEval.']) ? $this->cObj->stdWrap($singleKeyArray['specialEval'], $singleKeyArray['specialEval.']) : $singleKeyArray['specialEval'];
94 list($temp[3]) = explode('|', $specialEval);
95 // Adding the form entry to the dataArray
96 $dataArray[] = implode('|', $temp);
97 }
98 }
99 }
100 }
101 $attachmentCounter = '';
102 $hiddenfields = '';
103 $fieldlist = array();
104 $propertyOverride = array();
105 $fieldname_hashArray = array();
106 $counter = 0;
107 $xhtmlStrict = GeneralUtility::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype);
108 // Formname
109 $formName = isset($conf['formName.']) ? $this->cObj->stdWrap($conf['formName'], $conf['formName.']) : $conf['formName'];
110 $formName = $this->cleanFormName($formName);
111 $formName = $GLOBALS['TSFE']->getUniqueId($formName);
112
113 $fieldPrefix = isset($conf['fieldPrefix.']) ? $this->cObj->stdWrap($conf['fieldPrefix'], $conf['fieldPrefix.']) : $conf['fieldPrefix'];
114 if (isset($conf['fieldPrefix']) || isset($conf['fieldPrefix.'])) {
115 if ($fieldPrefix) {
116 $prefix = $this->cleanFormName($fieldPrefix);
117 } else {
118 $prefix = '';
119 }
120 } else {
121 $prefix = $formName;
122 }
123 foreach ($dataArray as $dataValue) {
124 $counter++;
125 $confData = array();
126 if (is_array($formData)) {
127 $parts = $dataValue;
128 // TRUE...
129 $dataValue = 1;
130 } else {
131 $dataValue = trim($dataValue);
132 $parts = explode('|', $dataValue);
133 }
134 if ($dataValue && strcspn($dataValue, '#/')) {
135 // label:
136 $confData['label'] = GeneralUtility::removeXSS(trim($parts[0]));
137 // field:
138 $fParts = explode(',', $parts[1]);
139 $fParts[0] = trim($fParts[0]);
140 if ($fParts[0][0] === '*') {
141 $confData['required'] = 1;
142 $fParts[0] = substr($fParts[0], 1);
143 }
144 $typeParts = explode('=', $fParts[0]);
145 $confData['type'] = trim(strtolower(end($typeParts)));
146 if (count($typeParts) === 1) {
147 $confData['fieldname'] = $this->cleanFormName($parts[0]);
148 if (strtolower(preg_replace('/[^[:alnum:]]/', '', $confData['fieldname'])) == 'email') {
149 $confData['fieldname'] = 'email';
150 }
151 // Duplicate fieldnames resolved
152 if (isset($fieldname_hashArray[md5($confData['fieldname'])])) {
153 $confData['fieldname'] .= '_' . $counter;
154 }
155 $fieldname_hashArray[md5($confData['fieldname'])] = $confData['fieldname'];
156 // Attachment names...
157 if ($confData['type'] == 'file') {
158 $confData['fieldname'] = 'attachment' . $attachmentCounter;
159 $attachmentCounter = (int)$attachmentCounter + 1;
160 }
161 } else {
162 $confData['fieldname'] = str_replace(' ', '_', trim($typeParts[0]));
163 }
164 $confData['fieldname'] = htmlspecialchars($confData['fieldname']);
165 $fieldCode = '';
166 $wrapFieldName = isset($conf['wrapFieldName']) ? $this->cObj->stdWrap($conf['wrapFieldName'], $conf['wrapFieldName.']) : $conf['wrapFieldName'];
167 if ($wrapFieldName) {
168 $confData['fieldname'] = $this->cObj->wrap($confData['fieldname'], $wrapFieldName);
169 }
170 // Set field name as current:
171 $this->cObj->setCurrentVal($confData['fieldname']);
172 // Additional parameters
173 if (trim($confData['type'])) {
174 if (isset($conf['params.'][$confData['type']])) {
175 $addParams = isset($conf['params.'][$confData['type'] . '.']) ? trim($this->cObj->stdWrap($conf['params.'][$confData['type']], $conf['params.'][$confData['type'] . '.'])) : trim($conf['params.'][$confData['type']]);
176 } else {
177 $addParams = isset($conf['params.']) ? trim($this->cObj->stdWrap($conf['params'], $conf['params.'])) : trim($conf['params']);
178 }
179 if ((string)$addParams !== '') {
180 $addParams = ' ' . $addParams;
181 }
182 } else {
183 $addParams = '';
184 }
185 $dontMd5FieldNames = isset($conf['dontMd5FieldNames.']) ? $this->cObj->stdWrap($conf['dontMd5FieldNames'], $conf['dontMd5FieldNames.']) : $conf['dontMd5FieldNames'];
186 if ($dontMd5FieldNames) {
187 $fName = $confData['fieldname'];
188 } else {
189 $fName = md5($confData['fieldname']);
190 }
191 // Accessibility: Set id = fieldname attribute:
192 $accessibility = isset($conf['accessibility.']) ? $this->cObj->stdWrap($conf['accessibility'], $conf['accessibility.']) : $conf['accessibility'];
193 if ($accessibility || $xhtmlStrict) {
194 $elementIdAttribute = ' id="' . $prefix . $fName . '"';
195 } else {
196 $elementIdAttribute = '';
197 }
198 // Create form field based on configuration/type:
199 switch ($confData['type']) {
200 case 'textarea':
201 $cols = trim($fParts[1]) ? (int)$fParts[1] : 20;
202 $compensateFieldWidth = isset($conf['compensateFieldWidth.']) ? $this->cObj->stdWrap($conf['compensateFieldWidth'], $conf['compensateFieldWidth.']) : $conf['compensateFieldWidth'];
203 $compWidth = doubleval($compensateFieldWidth ? $compensateFieldWidth : $GLOBALS['TSFE']->compensateFieldWidth);
204 $compWidth = $compWidth ? $compWidth : 1;
205 $cols = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($cols * $compWidth, 1, 120);
206 $rows = trim($fParts[2]) ? \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($fParts[2], 1, 30) : 5;
207 $wrap = trim($fParts[3]);
208 $noWrapAttr = isset($conf['noWrapAttr.']) ? $this->cObj->stdWrap($conf['noWrapAttr'], $conf['noWrapAttr.']) : $conf['noWrapAttr'];
209 if ($noWrapAttr || $wrap === 'disabled') {
210 $wrap = '';
211 } else {
212 $wrap = $wrap ? ' wrap="' . $wrap . '"' : ' wrap="virtual"';
213 }
214 $noValueInsert = isset($conf['noValueInsert.']) ? $this->cObj->stdWrap($conf['noValueInsert'], $conf['noValueInsert.']) : $conf['noValueInsert'];
215 $default = $this->getFieldDefaultValue($noValueInsert, $confData['fieldname'], str_replace('\\n', LF, trim($parts[2])));
216 $fieldCode = sprintf('<textarea name="%s"%s cols="%s" rows="%s"%s%s>%s</textarea>', $confData['fieldname'], $elementIdAttribute, $cols, $rows, $wrap, $addParams, htmlspecialchars($default));
217 break;
218 case 'input':
219
220 case 'password':
221 $size = trim($fParts[1]) ? (int)$fParts[1] : 20;
222 $compensateFieldWidth = isset($conf['compensateFieldWidth.']) ? $this->cObj->stdWrap($conf['compensateFieldWidth'], $conf['compensateFieldWidth.']) : $conf['compensateFieldWidth'];
223 $compWidth = doubleval($compensateFieldWidth ? $compensateFieldWidth : $GLOBALS['TSFE']->compensateFieldWidth);
224 $compWidth = $compWidth ? $compWidth : 1;
225 $size = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($size * $compWidth, 1, 120);
226 $noValueInsert = isset($conf['noValueInsert.']) ? $this->cObj->stdWrap($conf['noValueInsert'], $conf['noValueInsert.']) : $conf['noValueInsert'];
227 $default = $this->getFieldDefaultValue($noValueInsert, $confData['fieldname'], trim($parts[2]));
228 if ($confData['type'] == 'password') {
229 $default = '';
230 }
231 $max = trim($fParts[2]) ? ' maxlength="' . \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($fParts[2], 1, 1000) . '"' : '';
232 $theType = $confData['type'] == 'input' ? 'text' : 'password';
233 $fieldCode = sprintf('<input type="%s" name="%s"%s size="%s"%s value="%s"%s />', $theType, $confData['fieldname'], $elementIdAttribute, $size, $max, htmlspecialchars($default), $addParams);
234 break;
235 case 'file':
236 $size = trim($fParts[1]) ? \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($fParts[1], 1, 60) : 20;
237 $fieldCode = sprintf('<input type="file" name="%s"%s size="%s"%s />', $confData['fieldname'], $elementIdAttribute, $size, $addParams);
238 break;
239 case 'check':
240 // alternative default value:
241 $noValueInsert = isset($conf['noValueInsert.']) ? $this->cObj->stdWrap($conf['noValueInsert'], $conf['noValueInsert.']) : $conf['noValueInsert'];
242 $default = $this->getFieldDefaultValue($noValueInsert, $confData['fieldname'], trim($parts[2]));
243 $checked = $default ? ' checked="checked"' : '';
244 $fieldCode = sprintf('<input type="checkbox" value="%s" name="%s"%s%s%s />', 1, $confData['fieldname'], $elementIdAttribute, $checked, $addParams);
245 break;
246 case 'select':
247 $option = '';
248 $valueParts = explode(',', $parts[2]);
249 // size
250 if (strtolower(trim($fParts[1])) == 'auto') {
251 $fParts[1] = count($valueParts);
252 }
253 // Auto size set here. Max 20
254 $size = trim($fParts[1]) ? \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($fParts[1], 1, 20) : 1;
255 // multiple
256 $multiple = strtolower(trim($fParts[2])) == 'm' ? ' multiple="multiple"' : '';
257 // Where the items will be
258 $items = array();
259 //RTF
260 $defaults = array();
261 $pCount = count($valueParts);
262 for ($a = 0; $a < $pCount; $a++) {
263 $valueParts[$a] = trim($valueParts[$a]);
264 // Finding default value
265 if ($valueParts[$a][0] === '*') {
266 $sel = 'selected';
267 $valueParts[$a] = substr($valueParts[$a], 1);
268 } else {
269 $sel = '';
270 }
271 // Get value/label
272 $subParts = explode('=', $valueParts[$a]);
273 // Sets the value
274 $subParts[1] = isset($subParts[1]) ? trim($subParts[1]) : trim($subParts[0]);
275 // Adds the value/label pair to the items-array
276 $items[] = $subParts;
277 if ($sel) {
278 $defaults[] = $subParts[1];
279 }
280 }
281 // alternative default value:
282 $noValueInsert = isset($conf['noValueInsert.']) ? $this->cObj->stdWrap($conf['noValueInsert'], $conf['noValueInsert.']) : $conf['noValueInsert'];
283 $default = $this->getFieldDefaultValue($noValueInsert, $confData['fieldname'], $defaults);
284 if (!is_array($default)) {
285 $defaults = array();
286 $defaults[] = $default;
287 } else {
288 $defaults = $default;
289 }
290 // Create the select-box:
291 $iCount = count($items);
292 for ($a = 0; $a < $iCount; $a++) {
293 $option .= '<option value="' . $items[$a][1] . '"' . (in_array($items[$a][1], $defaults) ? ' selected="selected"' : '') . '>' . trim($items[$a][0]) . '</option>';
294 }
295 if ($multiple) {
296 // The fieldname must be prepended '[]' if multiple select. And the reason why it's prepended is, because the required-field list later must also have [] prepended.
297 $confData['fieldname'] .= '[]';
298 }
299 $fieldCode = sprintf('<select name="%s"%s size="%s"%s%s>%s</select>', $confData['fieldname'], $elementIdAttribute, $size, $multiple, $addParams, $option);
300 //RTF
301 break;
302 case 'radio':
303 $option = '';
304 $valueParts = explode(',', $parts[2]);
305 // Where the items will be
306 $items = array();
307 $default = '';
308 $pCount = count($valueParts);
309 for ($a = 0; $a < $pCount; $a++) {
310 $valueParts[$a] = trim($valueParts[$a]);
311 if ($valueParts[$a][0] === '*') {
312 $sel = 'checked';
313 $valueParts[$a] = substr($valueParts[$a], 1);
314 } else {
315 $sel = '';
316 }
317 // Get value/label
318 $subParts = explode('=', $valueParts[$a]);
319 // Sets the value
320 $subParts[1] = isset($subParts[1]) ? trim($subParts[1]) : trim($subParts[0]);
321 // Adds the value/label pair to the items-array
322 $items[] = $subParts;
323 if ($sel) {
324 $default = $subParts[1];
325 }
326 }
327 // alternative default value:
328 $noValueInsert = isset($conf['noValueInsert.']) ? $this->cObj->stdWrap($conf['noValueInsert'], $conf['noValueInsert.']) : $conf['noValueInsert'];
329 $default = $this->getFieldDefaultValue($noValueInsert, $confData['fieldname'], $default);
330 // Create the select-box:
331 $iCount = count($items);
332 for ($a = 0; $a < $iCount; $a++) {
333 $optionParts = '';
334 $radioId = $prefix . $fName . $this->cleanFormName($items[$a][0]);
335 if ($accessibility) {
336 $radioLabelIdAttribute = ' id="' . $radioId . '"';
337 } else {
338 $radioLabelIdAttribute = '';
339 }
340 $optionParts .= '<input type="radio" name="' . $confData['fieldname'] . '"' . $radioLabelIdAttribute . ' value="' . $items[$a][1] . '"' . ((string)$items[$a][1] === (string)$default ? ' checked="checked"' : '') . $addParams . ' />';
341 if ($accessibility) {
342 $label = isset($conf['radioWrap.']) ? $this->cObj->stdWrap(trim($items[$a][0]), $conf['radioWrap.']) : trim($items[$a][0]);
343 $optionParts .= '<label for="' . $radioId . '">' . $label . '</label>';
344 } else {
345 $optionParts .= isset($conf['radioWrap.']) ? $this->cObj->stdWrap(trim($items[$a][0]), $conf['radioWrap.']) : trim($items[$a][0]);
346 }
347 $option .= isset($conf['radioInputWrap.']) ? $this->cObj->stdWrap($optionParts, $conf['radioInputWrap.']) : $optionParts;
348 }
349 if ($accessibility) {
350 $accessibilityWrap = isset($conf['radioWrap.']['accessibilityWrap.']) ? $this->cObj->stdWrap($conf['radioWrap.']['accessibilityWrap'], $conf['radioWrap.']['accessibilityWrap.']) : $conf['radioWrap.']['accessibilityWrap'];
351 if ($accessibilityWrap) {
352 $search = array(
353 '###RADIO_FIELD_ID###',
354 '###RADIO_GROUP_LABEL###'
355 );
356 $replace = array(
357 $elementIdAttribute,
358 $confData['label']
359 );
360 $accessibilityWrap = str_replace($search, $replace, $accessibilityWrap);
361 $option = $this->cObj->wrap($option, $accessibilityWrap);
362 }
363 }
364 $fieldCode = $option;
365 break;
366 case 'hidden':
367 $value = trim($parts[2]);
368 // If this form includes an auto responder message, include a HMAC checksum field
369 // in order to verify potential abuse of this feature.
370 if ($value !== '') {
371 if (GeneralUtility::inList($confData['fieldname'], 'auto_respond_msg')) {
372 $hmacChecksum = GeneralUtility::hmac($value, 'content_form');
373 $hiddenfields .= sprintf('<input type="hidden" name="auto_respond_checksum" id="%sauto_respond_checksum" value="%s" />', $prefix, $hmacChecksum);
374 }
375 if (GeneralUtility::inList('recipient_copy,recipient', $confData['fieldname']) && $GLOBALS['TYPO3_CONF_VARS']['FE']['secureFormmail']) {
376 break;
377 }
378 if (GeneralUtility::inList('recipient_copy,recipient', $confData['fieldname'])) {
379 $value = \TYPO3\CMS\Compatibility6\Utility\FormUtility::codeString($value);
380 }
381 }
382 $hiddenfields .= sprintf('<input type="hidden" name="%s"%s value="%s" />', $confData['fieldname'], $elementIdAttribute, htmlspecialchars($value));
383 break;
384 case 'property':
385 if (GeneralUtility::inList('type,locationData,goodMess,badMess,emailMess', $confData['fieldname'])) {
386 $value = trim($parts[2]);
387 $propertyOverride[$confData['fieldname']] = $value;
388 $conf[$confData['fieldname']] = $value;
389 }
390 break;
391 case 'submit':
392 $value = trim($parts[2]);
393 if ($conf['image.']) {
394 $this->cObj->data[$this->cObj->currentValKey] = $value;
395 $image = $this->cObj->cObjGetSingle('IMG_RESOURCE', $conf['image.']);
396 $params = $conf['image.']['params'] ? ' ' . $conf['image.']['params'] : '';
397 $params .= $this->cObj->getAltParam($conf['image.'], FALSE);
398 $params .= $addParams;
399 } else {
400 $image = '';
401 }
402 if ($image) {
403 $fieldCode = sprintf('<input type="image" name="%s"%s src="%s"%s />', $confData['fieldname'], $elementIdAttribute, $image, $params);
404 } else {
405 $fieldCode = sprintf('<input type="submit" name="%s"%s value="%s"%s />', $confData['fieldname'], $elementIdAttribute, htmlspecialchars($value, ENT_COMPAT, 'UTF-8', FALSE), $addParams);
406 }
407 break;
408 case 'reset':
409 $value = trim($parts[2]);
410 $fieldCode = sprintf('<input type="reset" name="%s"%s value="%s"%s />', $confData['fieldname'], $elementIdAttribute, htmlspecialchars($value, ENT_COMPAT, 'UTF-8', FALSE), $addParams);
411 break;
412 case 'label':
413 $fieldCode = nl2br(htmlspecialchars(trim($parts[2])));
414 break;
415 default:
416 $confData['type'] = 'comment';
417 $fieldCode = trim($parts[2]) . '&nbsp;';
418 }
419 if ($fieldCode) {
420 // Checking for special evaluation modes:
421 if (trim($parts[3]) !== '' && GeneralUtility::inList('textarea,input,password', $confData['type'])) {
422 $modeParameters = GeneralUtility::trimExplode(':', $parts[3]);
423 } else {
424 $modeParameters = array();
425 }
426 // Adding evaluation based on settings:
427 switch ((string)$modeParameters[0]) {
428 case 'EREG':
429 $fieldlist[] = '_EREG';
430 $fieldlist[] = $modeParameters[1];
431 $fieldlist[] = $modeParameters[2];
432 $fieldlist[] = $confData['fieldname'];
433 $fieldlist[] = $confData['label'];
434 // Setting this so "required" layout is used.
435 $confData['required'] = 1;
436 break;
437 case 'EMAIL':
438 $fieldlist[] = '_EMAIL';
439 $fieldlist[] = $confData['fieldname'];
440 $fieldlist[] = $confData['label'];
441 // Setting this so "required" layout is used.
442 $confData['required'] = 1;
443 break;
444 default:
445 if ($confData['required']) {
446 $fieldlist[] = $confData['fieldname'];
447 $fieldlist[] = $confData['label'];
448 }
449 }
450 // Field:
451 $fieldLabel = $confData['label'];
452 if ($accessibility && trim($fieldLabel) && !preg_match('/^(label|hidden|comment)$/', $confData['type'])) {
453 $fieldLabel = '<label for="' . $prefix . $fName . '">' . $fieldLabel . '</label>';
454 }
455 // Getting template code:
456 if (isset($conf['fieldWrap.'])) {
457 $fieldCode = $this->cObj->stdWrap($fieldCode, $conf['fieldWrap.']);
458 }
459 $labelCode = isset($conf['labelWrap.']) ? $this->cObj->stdWrap($fieldLabel, $conf['labelWrap.']) : $fieldLabel;
460 $commentCode = isset($conf['commentWrap.']) ? $this->cObj->stdWrap($confData['label'], $conf['commentWrap.']) : $confData['label'];
461 $result = $conf['layout'];
462 $req = isset($conf['REQ.']) ? $this->cObj->stdWrap($conf['REQ'], $conf['REQ.']) : $conf['REQ'];
463 if ($req && $confData['required']) {
464 if (isset($conf['REQ.']['fieldWrap.'])) {
465 $fieldCode = $this->cObj->stdWrap($fieldCode, $conf['REQ.']['fieldWrap.']);
466 }
467 if (isset($conf['REQ.']['labelWrap.'])) {
468 $labelCode = $this->cObj->stdWrap($fieldLabel, $conf['REQ.']['labelWrap.']);
469 }
470 $reqLayout = isset($conf['REQ.']['layout.']) ? $this->cObj->stdWrap($conf['REQ.']['layout'], $conf['REQ.']['layout.']) : $conf['REQ.']['layout'];
471 if ($reqLayout) {
472 $result = $reqLayout;
473 }
474 }
475 if ($confData['type'] == 'comment') {
476 $commentLayout = isset($conf['COMMENT.']['layout.']) ? $this->cObj->stdWrap($conf['COMMENT.']['layout'], $conf['COMMENT.']['layout.']) : $conf['COMMENT.']['layout'];
477 if ($commentLayout) {
478 $result = $commentLayout;
479 }
480 }
481 if ($confData['type'] == 'check') {
482 $checkLayout = isset($conf['CHECK.']['layout.']) ? $this->cObj->stdWrap($conf['CHECK.']['layout'], $conf['CHECK.']['layout.']) : $conf['CHECK.']['layout'];
483 if ($checkLayout) {
484 $result = $checkLayout;
485 }
486 }
487 if ($confData['type'] == 'radio') {
488 $radioLayout = isset($conf['RADIO.']['layout.']) ? $this->cObj->stdWrap($conf['RADIO.']['layout'], $conf['RADIO.']['layout.']) : $conf['RADIO.']['layout'];
489 if ($radioLayout) {
490 $result = $radioLayout;
491 }
492 }
493 if ($confData['type'] == 'label') {
494 $labelLayout = isset($conf['LABEL.']['layout.']) ? $this->cObj->stdWrap($conf['LABEL.']['layout'], $conf['LABEL.']['layout.']) : $conf['LABEL.']['layout'];
495 if ($labelLayout) {
496 $result = $labelLayout;
497 }
498 }
499 //RTF
500 $content .= str_replace(
501 array(
502 '###FIELD###',
503 '###LABEL###',
504 '###COMMENT###'
505 ),
506 array(
507 $fieldCode,
508 $labelCode,
509 $commentCode
510 ),
511 $result
512 );
513 }
514 }
515 }
516 if (isset($conf['stdWrap.'])) {
517 $content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
518 }
519 // Redirect (external: where to go afterwards. internal: where to submit to)
520 $theRedirect = isset($conf['redirect.']) ? $this->cObj->stdWrap($conf['redirect'], $conf['redirect.']) : $conf['redirect'];
521 // redirect should be set to the page to redirect to after an external script has been used. If internal scripts is used, and if no 'type' is set that dictates otherwise, redirect is used as the url to jump to as long as it's an integer (page)
522 $target = isset($conf['target.']) ? $this->cObj->stdWrap($conf['target'], $conf['target.']) : $conf['target'];
523 // redirect should be set to the page to redirect to after an external script has been used. If internal scripts is used, and if no 'type' is set that dictates otherwise, redirect is used as the url to jump to as long as it's an integer (page)
524 $noCache = isset($conf['no_cache.']) ? $this->cObj->stdWrap($conf['no_cache'], $conf['no_cache.']) : $conf['no_cache'];
525 // redirect should be set to the page to redirect to after an external script has been used. If internal scripts is used, and if no 'type' is set that dictates otherwise, redirect is used as the url to jump to as long as it's an integer (page)
526 $page = $GLOBALS['TSFE']->page;
527 // Internal: Just submit to current page
528 if (!$theRedirect) {
529 $LD = $GLOBALS['TSFE']->tmpl->linkData($page, $target, $noCache, 'index.php', '', $this->cObj->getClosestMPvalueForPage($page['uid']));
530 } elseif (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($theRedirect)) {
531 // Internal: Submit to page with ID $theRedirect
532 $page = $GLOBALS['TSFE']->sys_page->getPage_noCheck($theRedirect);
533 $LD = $GLOBALS['TSFE']->tmpl->linkData($page, $target, $noCache, 'index.php', '', $this->cObj->getClosestMPvalueForPage($page['uid']));
534 } else {
535 // External URL, redirect-hidden field is rendered!
536 $LD = $GLOBALS['TSFE']->tmpl->linkData($page, $target, $noCache, '', '', $this->cObj->getClosestMPvalueForPage($page['uid']));
537 $LD['totalURL'] = $theRedirect;
538 $hiddenfields .= '<input type="hidden" name="redirect" value="' . htmlspecialchars($LD['totalURL']) . '" />';
539 }
540 // Formtype (where to submit to!):
541 if ($propertyOverride['type']) {
542 $formtype = $propertyOverride['type'];
543 } else {
544 $formtype = isset($conf['type.']) ? $this->cObj->stdWrap($conf['type'], $conf['type.']) : $conf['type'];
545 }
546 // Submit to a specific page
547 if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($formtype)) {
548 $page = $GLOBALS['TSFE']->sys_page->getPage_noCheck($formtype);
549 $LD_A = $GLOBALS['TSFE']->tmpl->linkData($page, $target, $noCache, '', '', $this->cObj->getClosestMPvalueForPage($page['uid']));
550 $action = $LD_A['totalURL'];
551 } elseif ($formtype) {
552 // Submit to external script
553 $LD_A = $LD;
554 $action = $formtype;
555 } elseif (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($theRedirect)) {
556 $LD_A = $LD;
557 $action = $LD_A['totalURL'];
558 } else {
559 // Submit to "nothing" - which is current page
560 $LD_A = $GLOBALS['TSFE']->tmpl->linkData($GLOBALS['TSFE']->page, $target, $noCache, '', '', $this->cObj->getClosestMPvalueForPage($page['uid']));
561 $action = $LD_A['totalURL'];
562 }
563 // Recipient:
564 $theEmail = isset($conf['recipient.']) ? $this->cObj->stdWrap($conf['recipient'], $conf['recipient.']) : $conf['recipient'];
565 if ($theEmail && !$GLOBALS['TYPO3_CONF_VARS']['FE']['secureFormmail']) {
566 $theEmail = \TYPO3\CMS\Compatibility6\Utility\FormUtility::codeString($theEmail);
567 $hiddenfields .= '<input type="hidden" name="recipient" value="' . htmlspecialchars($theEmail) . '" />';
568 }
569 // location data:
570 $location = isset($conf['locationData.']) ? $this->cObj->stdWrap($conf['locationData'], $conf['locationData.']) : $conf['locationData'];
571 if ($location) {
572 if ($location == 'HTTP_POST_VARS' && isset($_POST['locationData'])) {
573 $locationData = GeneralUtility::_POST('locationData');
574 } else {
575 // locationData is [the page id]:[tablename]:[uid of record]. Indicates on which page the record (from tablename with uid) is shown. Used to check access.
576 if (isset($this->data['_LOCALIZED_UID'])) {
577 $locationData = $GLOBALS['TSFE']->id . ':' . str_replace($this->data['uid'], $this->data['_LOCALIZED_UID'], $this->cObj->currentRecord);
578 } else {
579 $locationData = $GLOBALS['TSFE']->id . ':' . $this->cObj->currentRecord;
580 }
581 }
582 $hiddenfields .= '<input type="hidden" name="locationData" value="' . htmlspecialchars($locationData) . '" />';
583 }
584 // Hidden fields:
585 if (is_array($conf['hiddenFields.'])) {
586 foreach ($conf['hiddenFields.'] as $hF_key => $hF_conf) {
587 if (substr($hF_key, -1) != '.') {
588 $hF_value = $this->cObj->cObjGetSingle($hF_conf, $conf['hiddenFields.'][$hF_key . '.'], 'hiddenfields');
589 if ((string)$hF_value !== '' && GeneralUtility::inList('recipient_copy,recipient', $hF_key)) {
590 if ($GLOBALS['TYPO3_CONF_VARS']['FE']['secureFormmail']) {
591 continue;
592 }
593 $hF_value = \TYPO3\CMS\Compatibility6\Utility\FormUtility::codeString($hF_value);
594 }
595 $hiddenfields .= '<input type="hidden" name="' . $hF_key . '" value="' . htmlspecialchars($hF_value) . '" />';
596 }
597 }
598 }
599 // Wrap all hidden fields in a div tag (see http://forge.typo3.org/issues/14491)
600 $hiddenfields = isset($conf['hiddenFields.']['stdWrap.']) ? $this->cObj->stdWrap($hiddenfields, $conf['hiddenFields.']['stdWrap.']) : '<div style="display:none;">' . $hiddenfields . '</div>';
601 if ($conf['REQ']) {
602 $goodMess = isset($conf['goodMess.']) ? $this->cObj->stdWrap($conf['goodMess'], $conf['goodMess.']) : $conf['goodMess'];
603 $badMess = isset($conf['badMess.']) ? $this->cObj->stdWrap($conf['badMess'], $conf['badMess.']) : $conf['badMess'];
604 $emailMess = isset($conf['emailMess.']) ? $this->cObj->stdWrap($conf['emailMess'], $conf['emailMess.']) : $conf['emailMess'];
605 $validateForm = ' onsubmit="return validateForm(' . GeneralUtility::quoteJSvalue($formName) . ',' . GeneralUtility::quoteJSvalue(implode(',', $fieldlist)) . ',' . GeneralUtility::quoteJSvalue($goodMess) . ',' . GeneralUtility::quoteJSvalue($badMess) . ',' . GeneralUtility::quoteJSvalue($emailMess) . ')"';
606 $GLOBALS['TSFE']->additionalHeaderData['JSFormValidate'] = '<script type="text/javascript" src="' . GeneralUtility::createVersionNumberedFilename(($GLOBALS['TSFE']->absRefPrefix . 'typo3/sysext/compatibility6/Resources/Public/JavaScript/jsfunc.validateform.js')) . '"></script>';
607 } else {
608 $validateForm = '';
609 }
610 // Create form tag:
611 $theTarget = $theRedirect ? $LD['target'] : $LD_A['target'];
612 $method = isset($conf['method.']) ? $this->cObj->stdWrap($conf['method'], $conf['method.']) : $conf['method'];
613 $content = array(
614 '<form' . ' action="' . htmlspecialchars($action) . '"' . ' id="' . $formName . '"' . ($xhtmlStrict ? '' : ' name="' . $formName . '"') . ' enctype="multipart/form-data"' . ' method="' . ($method ? $method : 'post') . '"' . ($theTarget ? ' target="' . $theTarget . '"' : '') . $validateForm . '>',
615 $hiddenfields . $content,
616 '</form>'
617 );
618 $arrayReturnMode = isset($conf['arrayReturnMode.']) ? $this->cObj->stdWrap($conf['arrayReturnMode'], $conf['arrayReturnMode.']) : $conf['arrayReturnMode'];
619 if ($arrayReturnMode) {
620 $content['validateForm'] = $validateForm;
621 $content['formname'] = $formName;
622 return $content;
623 } else {
624 return implode('', $content);
625 }
626 }
627
628
629 /**
630 * Returns a default value for a form field in the FORM cObject.
631 * Page CANNOT be cached because that would include the inserted value for the current user.
632 *
633 * @param bool $noValueInsert If noValueInsert OR if the no_cache flag for this page is NOT set, the original default value is returned.
634 * @param string $fieldName The POST var name to get default value for
635 * @param string $defaultVal The current default value
636 * @return string The default value, either from INPUT var or the current default, based on whether caching is enabled or not.
637 */
638 protected function getFieldDefaultValue($noValueInsert, $fieldName, $defaultVal) {
639 if (!$GLOBALS['TSFE']->no_cache || !isset($_POST[$fieldName]) && !isset($_GET[$fieldName]) || $noValueInsert) {
640 return $defaultVal;
641 } else {
642 return GeneralUtility::_GP($fieldName);
643 }
644 }
645
646 /**
647 * Removes forbidden characters and spaces from name/id attributes in the form tag and formfields
648 *
649 * @param string $name Input string
650 * @return string the cleaned string
651 */
652 protected function cleanFormName($name) {
653 // Turn data[x][y] into data:x:y:
654 $name = preg_replace('/\\[|\\]\\[?/', ':', trim($name));
655 // Remove illegal chars like _
656 return preg_replace('#[^:a-zA-Z0-9]#', '', $name);
657 }
658 }