[CLEANUP] Replace strlen() with === for zero length check
[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 ($value !== '') {
374 if (GeneralUtility::inList($confData['fieldname'], 'auto_respond_msg')) {
375 $hmacChecksum = GeneralUtility::hmac($value, 'content_form');
376 $hiddenfields .= sprintf('<input type="hidden" name="auto_respond_checksum" id="%sauto_respond_checksum" value="%s" />', $prefix, $hmacChecksum);
377 }
378 if (GeneralUtility::inList('recipient_copy,recipient', $confData['fieldname']) && $GLOBALS['TYPO3_CONF_VARS']['FE']['secureFormmail']) {
379 break;
380 }
381 if (GeneralUtility::inList('recipient_copy,recipient', $confData['fieldname'])) {
382 $value = $GLOBALS['TSFE']->codeString($value);
383 }
384 }
385 $hiddenfields .= sprintf('<input type="hidden" name="%s"%s value="%s" />', $confData['fieldname'], $elementIdAttribute, htmlspecialchars($value));
386 break;
387 case 'property':
388 if (GeneralUtility::inList('type,locationData,goodMess,badMess,emailMess', $confData['fieldname'])) {
389 $value = trim($parts[2]);
390 $propertyOverride[$confData['fieldname']] = $value;
391 $conf[$confData['fieldname']] = $value;
392 }
393 break;
394 case 'submit':
395 $value = trim($parts[2]);
396 if ($conf['image.']) {
397 $this->cObj->data[$this->cObj->currentValKey] = $value;
398 $image = $this->cObj->IMG_RESOURCE($conf['image.']);
399 $params = $conf['image.']['params'] ? ' ' . $conf['image.']['params'] : '';
400 $params .= $this->cObj->getAltParam($conf['image.'], FALSE);
401 $params .= $addParams;
402 } else {
403 $image = '';
404 }
405 if ($image) {
406 $fieldCode = sprintf('<input type="image" name="%s"%s src="%s"%s />', $confData['fieldname'], $elementIdAttribute, $image, $params);
407 } else {
408 $fieldCode = sprintf('<input type="submit" name="%s"%s value="%s"%s />', $confData['fieldname'], $elementIdAttribute, htmlspecialchars($value, ENT_COMPAT, 'UTF-8', FALSE), $addParams);
409 }
410 break;
411 case 'reset':
412 $value = trim($parts[2]);
413 $fieldCode = sprintf('<input type="reset" name="%s"%s value="%s"%s />', $confData['fieldname'], $elementIdAttribute, htmlspecialchars($value, ENT_COMPAT, 'UTF-8', FALSE), $addParams);
414 break;
415 case 'label':
416 $fieldCode = nl2br(htmlspecialchars(trim($parts[2])));
417 break;
418 default:
419 $confData['type'] = 'comment';
420 $fieldCode = trim($parts[2]) . '&nbsp;';
421 }
422 if ($fieldCode) {
423 // Checking for special evaluation modes:
424 if (trim($parts[3]) !== '' && GeneralUtility::inList('textarea,input,password', $confData['type'])) {
425 $modeParameters = GeneralUtility::trimExplode(':', $parts[3]);
426 } else {
427 $modeParameters = array();
428 }
429 // Adding evaluation based on settings:
430 switch ((string)$modeParameters[0]) {
431 case 'EREG':
432 $fieldlist[] = '_EREG';
433 $fieldlist[] = $modeParameters[1];
434 $fieldlist[] = $modeParameters[2];
435 $fieldlist[] = $confData['fieldname'];
436 $fieldlist[] = $confData['label'];
437 // Setting this so "required" layout is used.
438 $confData['required'] = 1;
439 break;
440 case 'EMAIL':
441 $fieldlist[] = '_EMAIL';
442 $fieldlist[] = $confData['fieldname'];
443 $fieldlist[] = $confData['label'];
444 // Setting this so "required" layout is used.
445 $confData['required'] = 1;
446 break;
447 default:
448 if ($confData['required']) {
449 $fieldlist[] = $confData['fieldname'];
450 $fieldlist[] = $confData['label'];
451 }
452 }
453 // Field:
454 $fieldLabel = $confData['label'];
455 if ($accessibility && trim($fieldLabel) && !preg_match('/^(label|hidden|comment)$/', $confData['type'])) {
456 $fieldLabel = '<label for="' . $prefix . $fName . '">' . $fieldLabel . '</label>';
457 }
458 // Getting template code:
459 if (isset($conf['fieldWrap.'])) {
460 $fieldCode = $this->cObj->stdWrap($fieldCode, $conf['fieldWrap.']);
461 }
462 $labelCode = isset($conf['labelWrap.']) ? $this->cObj->stdWrap($fieldLabel, $conf['labelWrap.']) : $fieldLabel;
463 $commentCode = isset($conf['commentWrap.']) ? $this->cObj->stdWrap($confData['label'], $conf['commentWrap.']) : $confData['label'];
464 $result = $conf['layout'];
465 $req = isset($conf['REQ.']) ? $this->cObj->stdWrap($conf['REQ'], $conf['REQ.']) : $conf['REQ'];
466 if ($req && $confData['required']) {
467 if (isset($conf['REQ.']['fieldWrap.'])) {
468 $fieldCode = $this->cObj->stdWrap($fieldCode, $conf['REQ.']['fieldWrap.']);
469 }
470 if (isset($conf['REQ.']['labelWrap.'])) {
471 $labelCode = $this->cObj->stdWrap($fieldLabel, $conf['REQ.']['labelWrap.']);
472 }
473 $reqLayout = isset($conf['REQ.']['layout.']) ? $this->cObj->stdWrap($conf['REQ.']['layout'], $conf['REQ.']['layout.']) : $conf['REQ.']['layout'];
474 if ($reqLayout) {
475 $result = $reqLayout;
476 }
477 }
478 if ($confData['type'] == 'comment') {
479 $commentLayout = isset($conf['COMMENT.']['layout.']) ? $this->cObj->stdWrap($conf['COMMENT.']['layout'], $conf['COMMENT.']['layout.']) : $conf['COMMENT.']['layout'];
480 if ($commentLayout) {
481 $result = $commentLayout;
482 }
483 }
484 if ($confData['type'] == 'check') {
485 $checkLayout = isset($conf['CHECK.']['layout.']) ? $this->cObj->stdWrap($conf['CHECK.']['layout'], $conf['CHECK.']['layout.']) : $conf['CHECK.']['layout'];
486 if ($checkLayout) {
487 $result = $checkLayout;
488 }
489 }
490 if ($confData['type'] == 'radio') {
491 $radioLayout = isset($conf['RADIO.']['layout.']) ? $this->cObj->stdWrap($conf['RADIO.']['layout'], $conf['RADIO.']['layout.']) : $conf['RADIO.']['layout'];
492 if ($radioLayout) {
493 $result = $radioLayout;
494 }
495 }
496 if ($confData['type'] == 'label') {
497 $labelLayout = isset($conf['LABEL.']['layout.']) ? $this->cObj->stdWrap($conf['LABEL.']['layout'], $conf['LABEL.']['layout.']) : $conf['LABEL.']['layout'];
498 if ($labelLayout) {
499 $result = $labelLayout;
500 }
501 }
502 //RTF
503 $content .= str_replace(
504 array(
505 '###FIELD###',
506 '###LABEL###',
507 '###COMMENT###'
508 ),
509 array(
510 $fieldCode,
511 $labelCode,
512 $commentCode
513 ),
514 $result
515 );
516 }
517 }
518 }
519 if (isset($conf['stdWrap.'])) {
520 $content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
521 }
522 // Redirect (external: where to go afterwards. internal: where to submit to)
523 $theRedirect = isset($conf['redirect.']) ? $this->cObj->stdWrap($conf['redirect'], $conf['redirect.']) : $conf['redirect'];
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 $target = isset($conf['target.']) ? $this->cObj->stdWrap($conf['target'], $conf['target.']) : $conf['target'];
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 $noCache = isset($conf['no_cache.']) ? $this->cObj->stdWrap($conf['no_cache'], $conf['no_cache.']) : $conf['no_cache'];
528 // 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)
529 $page = $GLOBALS['TSFE']->page;
530 // Internal: Just submit to current page
531 if (!$theRedirect) {
532 $LD = $GLOBALS['TSFE']->tmpl->linkData($page, $target, $noCache, 'index.php', '', $this->cObj->getClosestMPvalueForPage($page['uid']));
533 } elseif (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($theRedirect)) {
534 // Internal: Submit to page with ID $theRedirect
535 $page = $GLOBALS['TSFE']->sys_page->getPage_noCheck($theRedirect);
536 $LD = $GLOBALS['TSFE']->tmpl->linkData($page, $target, $noCache, 'index.php', '', $this->cObj->getClosestMPvalueForPage($page['uid']));
537 } else {
538 // External URL, redirect-hidden field is rendered!
539 $LD = $GLOBALS['TSFE']->tmpl->linkData($page, $target, $noCache, '', '', $this->cObj->getClosestMPvalueForPage($page['uid']));
540 $LD['totalURL'] = $theRedirect;
541 $hiddenfields .= '<input type="hidden" name="redirect" value="' . htmlspecialchars($LD['totalURL']) . '" />';
542 }
543 // Formtype (where to submit to!):
544 if ($propertyOverride['type']) {
545 $formtype = $propertyOverride['type'];
546 } else {
547 $formtype = isset($conf['type.']) ? $this->cObj->stdWrap($conf['type'], $conf['type.']) : $conf['type'];
548 }
549 // Submit to a specific page
550 if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($formtype)) {
551 $page = $GLOBALS['TSFE']->sys_page->getPage_noCheck($formtype);
552 $LD_A = $GLOBALS['TSFE']->tmpl->linkData($page, $target, $noCache, '', '', $this->cObj->getClosestMPvalueForPage($page['uid']));
553 $action = $LD_A['totalURL'];
554 } elseif ($formtype) {
555 // Submit to external script
556 $LD_A = $LD;
557 $action = $formtype;
558 } elseif (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($theRedirect)) {
559 $LD_A = $LD;
560 $action = $LD_A['totalURL'];
561 } else {
562 // Submit to "nothing" - which is current page
563 $LD_A = $GLOBALS['TSFE']->tmpl->linkData($GLOBALS['TSFE']->page, $target, $noCache, '', '', $this->cObj->getClosestMPvalueForPage($page['uid']));
564 $action = $LD_A['totalURL'];
565 }
566 // Recipient:
567 $theEmail = isset($conf['recipient.']) ? $this->cObj->stdWrap($conf['recipient'], $conf['recipient.']) : $conf['recipient'];
568 if ($theEmail && !$GLOBALS['TYPO3_CONF_VARS']['FE']['secureFormmail']) {
569 $theEmail = $GLOBALS['TSFE']->codeString($theEmail);
570 $hiddenfields .= '<input type="hidden" name="recipient" value="' . htmlspecialchars($theEmail) . '" />';
571 }
572 // location data:
573 $location = isset($conf['locationData.']) ? $this->cObj->stdWrap($conf['locationData'], $conf['locationData.']) : $conf['locationData'];
574 if ($location) {
575 if ($location == 'HTTP_POST_VARS' && isset($_POST['locationData'])) {
576 $locationData = GeneralUtility::_POST('locationData');
577 } else {
578 // 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.
579 if (isset($this->data['_LOCALIZED_UID'])) {
580 $locationData = $GLOBALS['TSFE']->id . ':' . str_replace($this->data['uid'], $this->data['_LOCALIZED_UID'], $this->cObj->currentRecord);
581 } else {
582 $locationData = $GLOBALS['TSFE']->id . ':' . $this->cObj->currentRecord;
583 }
584 }
585 $hiddenfields .= '<input type="hidden" name="locationData" value="' . htmlspecialchars($locationData) . '" />';
586 }
587 // Hidden fields:
588 if (is_array($conf['hiddenFields.'])) {
589 foreach ($conf['hiddenFields.'] as $hF_key => $hF_conf) {
590 if (substr($hF_key, -1) != '.') {
591 $hF_value = $this->cObj->cObjGetSingle($hF_conf, $conf['hiddenFields.'][$hF_key . '.'], 'hiddenfields');
592 if ((string)$hF_value !== '' && GeneralUtility::inList('recipient_copy,recipient', $hF_key)) {
593 if ($GLOBALS['TYPO3_CONF_VARS']['FE']['secureFormmail']) {
594 continue;
595 }
596 $hF_value = $GLOBALS['TSFE']->codeString($hF_value);
597 }
598 $hiddenfields .= '<input type="hidden" name="' . $hF_key . '" value="' . htmlspecialchars($hF_value) . '" />';
599 }
600 }
601 }
602 // Wrap all hidden fields in a div tag (see http://forge.typo3.org/issues/14491)
603 $hiddenfields = isset($conf['hiddenFields.']['stdWrap.']) ? $this->cObj->stdWrap($hiddenfields, $conf['hiddenFields.']['stdWrap.']) : '<div style="display:none;">' . $hiddenfields . '</div>';
604 if ($conf['REQ']) {
605 $goodMess = isset($conf['goodMess.']) ? $this->cObj->stdWrap($conf['goodMess'], $conf['goodMess.']) : $conf['goodMess'];
606 $badMess = isset($conf['badMess.']) ? $this->cObj->stdWrap($conf['badMess'], $conf['badMess.']) : $conf['badMess'];
607 $emailMess = isset($conf['emailMess.']) ? $this->cObj->stdWrap($conf['emailMess'], $conf['emailMess.']) : $conf['emailMess'];
608 $validateForm = ' onsubmit="return validateForm(' . GeneralUtility::quoteJSvalue($formName) . ',' . GeneralUtility::quoteJSvalue(implode(',', $fieldlist)) . ',' . GeneralUtility::quoteJSvalue($goodMess) . ',' . GeneralUtility::quoteJSvalue($badMess) . ',' . GeneralUtility::quoteJSvalue($emailMess) . ')"';
609 $GLOBALS['TSFE']->additionalHeaderData['JSFormValidate'] = '<script type="text/javascript" src="' . GeneralUtility::createVersionNumberedFilename(($GLOBALS['TSFE']->absRefPrefix . 'typo3/sysext/frontend/Resources/Public/JavaScript/jsfunc.validateform.js')) . '"></script>';
610 } else {
611 $validateForm = '';
612 }
613 // Create form tag:
614 $theTarget = $theRedirect ? $LD['target'] : $LD_A['target'];
615 $method = isset($conf['method.']) ? $this->cObj->stdWrap($conf['method'], $conf['method.']) : $conf['method'];
616 $content = array(
617 '<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 . '>',
618 $hiddenfields . $content,
619 '</form>'
620 );
621 $arrayReturnMode = isset($conf['arrayReturnMode.']) ? $this->cObj->stdWrap($conf['arrayReturnMode'], $conf['arrayReturnMode.']) : $conf['arrayReturnMode'];
622 if ($arrayReturnMode) {
623 $content['validateForm'] = $validateForm;
624 $content['formname'] = $formName;
625 return $content;
626 } else {
627 return implode('', $content);
628 }
629 }
630
631 }