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