[TASK] Fix CGL violations against SuperfluousWhitespace
[Packages/TYPO3.CMS.git] / typo3 / wizard_forms.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27
28 /**
29 * Wizard to help make forms (fx. for tt_content elements) of type 'form'.
30 *
31 * Revised for TYPO3 3.6 November/2003 by Kasper Skårhøj
32 * XHTML compliant
33 *
34 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
35 */
36
37 $BACK_PATH = '';
38 require('init.php');
39 $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_wizards.xml');
40
41 /**
42 * API comments:
43 *
44 * The form wizard can help you to create forms - it allows you to create almost any kind of HTML form elements and in any order and amount.
45 *
46 * The format for the resulting configuration code can be either a line-based configuration. That can look like this:
47 *
48 * Your name: | *name=input | (input your name here!)
49 * Your Email: | *email=input
50 * Your address: | address=textarea,40,10
51 * Your Haircolor: | hair=radio |
52 * upload | attachment=file
53 * | quoted_printable=hidden | 0
54 * | formtype_mail=submit | Send form
55 * | html_enabled=hidden
56 * | subject=hidden | This is the subject
57 *
58 *
59 * Alternatively it can be XML. The same configuration from above looks like this in XML:
60 *
61 * <T3FormWizard>
62 * <n2>
63 * <type>input</type>
64 * <label>Your name:</label>
65 * <required>1</required>
66 * <fieldname>name</fieldname>
67 * <size></size>
68 * <max></max>
69 * <default>(input your name here!)</default>
70 * </n2>
71 * <n4>
72 * <type>input</type>
73 * <label>Your Email:</label>
74 * <required>1</required>
75 * <fieldname>email</fieldname>
76 * <size></size>
77 * <max></max>
78 * <default></default>
79 * </n4>
80 * <n6>
81 * <type>textarea</type>
82 * <label>Your address:</label>
83 * <fieldname>address</fieldname>
84 * <cols>40</cols>
85 * <rows>10</rows>
86 * <default></default>
87 * </n6>
88 * <n8>
89 * <type>radio</type>
90 * <label>Your Haircolor:</label>
91 * <fieldname>hair</fieldname>
92 * <options></options>
93 * </n8>
94 * <n10>
95 * <type>file</type>
96 * <label>upload</label>
97 * <fieldname>attachment</fieldname>
98 * <size></size>
99 * </n10>
100 * <n12>
101 * <type>hidden</type>
102 * <label></label>
103 * <fieldname>quoted_printable</fieldname>
104 * <default>0</default>
105 * </n12>
106 * <n2000>
107 * <fieldname>formtype_mail</fieldname>
108 * <type>submit</type>
109 * <default>Send form</default>
110 * </n2000>
111 * <n2002>
112 * <fieldname>html_enabled</fieldname>
113 * <type>hidden</type>
114 * </n2002>
115 * <n2004>
116 * <fieldname>subject</fieldname>
117 * <type>hidden</type>
118 * <default>This is the subject</default>
119 * </n2004>
120 * <n20>
121 * <content></content>
122 * </n20>
123 * </T3FormWizard>
124 *
125 *
126 * The XML/phpArray structure is the internal format of the wizard.
127 */
128
129
130 /**
131 * Script Class for rendering the Form Wizard
132 *
133 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
134 * @package TYPO3
135 * @subpackage core
136 */
137 class SC_wizard_forms {
138
139 // Internal, dynamic:
140 /**
141 * document template object
142 *
143 * @var mediumDoc
144 */
145 var $doc;
146 // Content accumulation for the module.
147 var $content;
148 // List of files to include.
149 var $include_once = array();
150 // Used to numerate attachments automatically.
151 var $attachmentCounter = 0;
152
153 // Internal, static:
154 // If set, the string version of the content is interpreted/written as XML instead of
155 // the original linebased kind. This variable still needs binding to the wizard parameters
156 // - but support is ready!
157 var $xmlStorage = 0;
158
159 // Internal, static: GPvars
160 // Wizard parameters, coming from TCEforms linking to the wizard.
161 var $P;
162 // The array which is constantly submitted by the multidimensional form of this wizard.
163 var $FORMCFG;
164 // Indicates if the form is of a dedicated type, like "formtype_mail" (for tt_content element "Form")
165 var $special;
166
167 /**
168 * Initialization the class
169 *
170 * @return void
171 */
172 function init() {
173 // GPvars:
174 $this->P = t3lib_div::_GP('P');
175 $this->special = t3lib_div::_GP('special');
176 $this->FORMCFG = t3lib_div::_GP('FORMCFG');
177
178 // Setting options:
179 $this->xmlStorage = $this->P['params']['xmlOutput'];
180
181 // Document template object:
182 $this->doc = t3lib_div::makeInstance('template');
183 $this->doc->backPath = $GLOBALS['BACK_PATH'];
184 $this->doc->setModuleTemplate('templates/wizard_forms.html');
185 $this->doc->JScode=$this->doc->wrapScriptTags('
186 function jumpToUrl(URL,formEl) { //
187 window.location.href = URL;
188 }
189 ');
190
191 // Setting form tag:
192 list($rUri) = explode('#', t3lib_div::getIndpEnv('REQUEST_URI'));
193 $this->doc->form ='<form action="'.htmlspecialchars($rUri).'" method="post" name="wizardForm">';
194 }
195
196 /**
197 * Main function for rendering the form wizard HTML
198 *
199 * @return void
200 */
201 function main() {
202 if ($this->P['table'] && $this->P['field'] && $this->P['uid']) {
203 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('forms_title'), $this->formsWizard(), 0, 1);
204 } else {
205 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('forms_title'), '<span class="typo3-red">' . $GLOBALS['LANG']->getLL('table_noData', 1) . '</span>', 0, 1);
206 }
207
208 // Setting up the buttons and markers for docheader
209 $docHeaderButtons = $this->getButtons();
210 $markers['CSH'] = $docHeaderButtons['csh'];
211 $markers['CONTENT'] = $this->content;
212
213 // Build the <body> for the module
214 $this->content = $this->doc->startPage('Form Wizard');
215 $this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
216 $this->content .= $this->doc->endPage();
217 $this->content = $this->doc->insertStylesAndJS($this->content);
218 }
219
220 /**
221 * Outputting the accumulated content to screen
222 *
223 * @return void
224 */
225 function printContent() {
226 echo $this->content;
227 }
228
229 /**
230 * Create the panel of buttons for submitting the form or otherwise perform operations.
231 *
232 * @return array All available buttons as an assoc. array
233 */
234 protected function getButtons() {
235 $buttons = array(
236 'csh' => '',
237 'csh_buttons' => '',
238 'close' => '',
239 'save' => '',
240 'save_close' => '',
241 'reload' => '',
242 );
243
244 if ($this->P['table'] && $this->P['field'] && $this->P['uid']) {
245 // CSH
246 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'wizard_forms_wiz', $GLOBALS['BACK_PATH'], '');
247
248 // CSH Buttons
249 $buttons['csh_buttons'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'wizard_forms_wiz_buttons', $GLOBALS['BACK_PATH'], '');
250
251 // Close
252 $buttons['close'] = '<a href="#" onclick="' . htmlspecialchars('jumpToUrl(unescape(\'' . rawurlencode(t3lib_div::sanitizeLocalUrl($this->P['returnUrl'])) . '\')); return false;') . '">' .
253 t3lib_iconWorks::getSpriteIcon('actions-document-close', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:rm.closeDoc', TRUE))) .
254 '</a>';
255
256 // Save
257 $buttons['save'] = '<input type="image" class="c-inputButton" name="savedok"' . t3lib_iconWorks::skinImg($this->doc->backPath, 'gfx/savedok.gif') . ' title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:rm.saveDoc', 1) . '" />';
258
259 // Save & Close
260 $buttons['save_close'] = '<input type="image" class="c-inputButton" name="saveandclosedok"' . t3lib_iconWorks::skinImg($this->doc->backPath, 'gfx/saveandclosedok.gif') . ' title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:rm.saveCloseDoc', 1) . '" />';
261
262 // Reload
263 $buttons['reload'] = '<input type="image" class="c-inputButton" name="_refresh"' . t3lib_iconWorks::skinImg('', 'gfx/refresh_n.gif') . ' title="' . $GLOBALS['LANG']->getLL('forms_refresh', 1) . '" />';
264 }
265
266 return $buttons;
267 }
268
269 /**
270 * Draws the form wizard content
271 *
272 * @return string HTML content for the form.
273 */
274 function formsWizard() {
275
276 // First, check the references by selecting the record:
277 $row = t3lib_BEfunc::getRecord($this->P['table'], $this->P['uid']);
278 if (!is_array($row)) {
279 throw new RuntimeException('Wizard Error: No reference to record', 1294587124);
280 }
281
282 // This will get the content of the form configuration code field to us - possibly
283 // cleaned up, saved to database etc. if the form has been submitted in the meantime.
284 $formCfgArray = $this->getConfigCode($row);
285
286 // Generation of the Form Wizards HTML code:
287 $content = $this->getFormHTML($formCfgArray, $row);
288
289 // Return content:
290 return $content;
291 }
292
293 /****************************
294 *
295 * Helper functions
296 *
297 ***************************/
298
299 /**
300 * Will get and return the configuration code string
301 * Will also save (and possibly redirect/exit) the content if a save button has been pressed
302 *
303 * @param array $row Current parent record row (passed by value!)
304 * @return array Configuration Array
305 * @access private
306 */
307 function getConfigCode(&$row) {
308
309 // If some data has been submitted, then construct
310 if (isset($this->FORMCFG['c'])) {
311
312 // Process incoming:
313 $this->changeFunc();
314
315 // Convert to string (either line based or XML):
316 if ($this->xmlStorage) {
317 // Convert the input array to XML:
318 $bodyText = t3lib_div::array2xml_cs($this->FORMCFG['c'], 'T3FormWizard');
319
320 // Setting cfgArr directly from the input:
321 $cfgArr = $this->FORMCFG['c'];
322 } else {
323 // Convert the input array to a string of configuration code:
324 $bodyText = $this->cfgArray2CfgString($this->FORMCFG['c']);
325
326 // Create cfgArr from the string based configuration - that way it is cleaned
327 // up and any incompatibilities will be removed!
328 $cfgArr = $this->cfgString2CfgArray($bodyText);
329 }
330
331 // If a save button has been pressed, then save the new field content:
332 if ($_POST['savedok_x'] || $_POST['saveandclosedok_x']) {
333
334 // Make TCEmain object:
335 $tce = t3lib_div::makeInstance('t3lib_TCEmain');
336 $tce->stripslashes_values = 0;
337
338 // Put content into the data array:
339 $data = array();
340 $data[$this->P['table']][$this->P['uid']][$this->P['field']] = $bodyText;
341 if ($this->special == 'formtype_mail') {
342 $data[$this->P['table']][$this->P['uid']]['subheader'] = $this->FORMCFG['recipient'];
343 }
344
345 // Perform the update:
346 $tce->start($data, array());
347 $tce->process_datamap();
348
349 // Re-load the record content:
350 $row = t3lib_BEfunc::getRecord($this->P['table'], $this->P['uid']);
351
352 // If the save/close button was pressed, then redirect the screen:
353 if ($_POST['saveandclosedok_x']) {
354 t3lib_utility_Http::redirect(t3lib_div::sanitizeLocalUrl($this->P['returnUrl']));
355 }
356 }
357 } else { // If nothing has been submitted, load the $bodyText variable from the selected database row:
358 if ($this->xmlStorage) {
359 $cfgArr = t3lib_div::xml2array($row[$this->P['field']]);
360 } else { // Regular linebased form configuration:
361 $cfgArr = $this->cfgString2CfgArray($row[$this->P['field']]);
362 }
363 $cfgArr = is_array($cfgArr) ? $cfgArr : array();
364 }
365
366 // Return configuration code:
367 return $cfgArr;
368 }
369
370 /**
371 * Creates the HTML for the Form Wizard:
372 *
373 * @param string $formCfgArray Form config array
374 * @param array $row Current parent record array
375 * @return string HTML for the form wizard
376 * @access private
377 */
378 function getFormHTML($formCfgArray, $row) {
379 // Initialize variables:
380 $specParts = array();
381 $hiddenFields = array();
382 $tRows = array();
383
384 // Set header row:
385 $cells = array($GLOBALS['LANG']->getLL('forms_preview', 1).':',
386 $GLOBALS['LANG']->getLL('forms_element', 1).':',
387 $GLOBALS['LANG']->getLL('forms_config', 1).':',
388 );
389 $tRows[] = '
390 <tr class="bgColor2" id="typo3-formWizardHeader">
391 <td>&nbsp;</td>
392 <td>' . implode('</td>
393 <td>', $cells) . '</td>
394 </tr>';
395
396 // Traverse the number of form elements:
397 $k = 0;
398 foreach ($formCfgArray as $confData) {
399
400 // Initialize:
401 $cells = array();
402
403 // If there is a configuration line which is active, then render it:
404 if (!isset($confData['comment'])) {
405
406 // Special parts:
407 if ($this->special == 'formtype_mail' && t3lib_div::inList('formtype_mail,subject,html_enabled', $confData['fieldname'])) {
408 $specParts[$confData['fieldname']] = $confData['default'];
409 } else {
410
411 // Render title/field preview COLUMN
412 $cells[] = $confData['type'] != 'hidden' ? '<strong>'.htmlspecialchars($confData['label']).'</strong>' : '';
413
414 // Render general type/title COLUMN:
415 $temp_cells = array();
416
417 // Field type selector:
418 $opt = array();
419 $opt[] = '<option value=""></option>';
420 $types = explode(',', 'input,textarea,select,check,radio,password,file,hidden,submit,property,label');
421 foreach ($types as $t) {
422 $opt[] = '
423 <option value="'.$t.'"'.($confData['type']==$t?' selected="selected"':'').'>'.$GLOBALS['LANG']->getLL('forms_type_'.$t, 1).'</option>';
424 }
425 $temp_cells[$GLOBALS['LANG']->getLL('forms_type')]='
426 <select name="FORMCFG[c]['.(($k+1)*2).'][type]">
427 ' . implode('
428 ', $opt) . '
429 </select>';
430
431 // Title field:
432 if (!t3lib_div::inList('hidden,submit', $confData['type'])) {
433 $temp_cells[$GLOBALS['LANG']->getLL('forms_label')]='<input type="text"'.$this->doc->formWidth(15).' name="FORMCFG[c]['.(($k+1)*2).'][label]" value="'.htmlspecialchars($confData['label']).'" />';
434 }
435
436 // Required checkbox:
437 if (!t3lib_div::inList('check,hidden,submit,label', $confData['type'])) {
438 $temp_cells[$GLOBALS['LANG']->getLL('forms_required')]='<input type="checkbox" name="FORMCFG[c]['.(($k+1)*2).'][required]" value="1"'.($confData['required']?' checked="checked"':'').' title="'.$GLOBALS['LANG']->getLL('forms_required', 1).'" />';
439 }
440
441 // Put sub-items together into table cell:
442 $cells[] = $this->formatCells($temp_cells);
443
444 // Render specific field configuration COLUMN:
445 $temp_cells = array();
446
447 // Fieldname
448 if ($this->special == 'formtype_mail' && $confData['type'] == 'file') {
449 $confData['fieldname'] = 'attachment'.(++$this->attachmentCounter);
450 }
451 if (!t3lib_div::inList('label', $confData['type'])) {
452 $temp_cells[$GLOBALS['LANG']->getLL('forms_fieldName')]='<input type="text"'.$this->doc->formWidth(10).' name="FORMCFG[c]['.(($k+1)*2).'][fieldname]" value="'.htmlspecialchars($confData['fieldname']).'" title="'.$GLOBALS['LANG']->getLL('forms_fieldName', 1).'" />';
453 }
454
455 // Field configuration depending on the fields type:
456 switch((string)$confData['type']) {
457 case 'textarea':
458 $temp_cells[$GLOBALS['LANG']->getLL('forms_cols')] = '<input type="text"'.$this->doc->formWidth(5).' name="FORMCFG[c]['.(($k+1)*2).'][cols]" value="'.htmlspecialchars($confData['cols']).'" title="'.$GLOBALS['LANG']->getLL('forms_cols', 1).'" />';
459 $temp_cells[$GLOBALS['LANG']->getLL('forms_rows')] = '<input type="text"'.$this->doc->formWidth(5).' name="FORMCFG[c]['.(($k+1)*2).'][rows]" value="'.htmlspecialchars($confData['rows']).'" title="'.$GLOBALS['LANG']->getLL('forms_rows', 1).'" />';
460 $temp_cells[$GLOBALS['LANG']->getLL('forms_extra')] = '<input type="checkbox" name="FORMCFG[c]['.(($k+1)*2).'][extra]" value="OFF"'.($confData['extra']=='OFF'?' checked="checked"':'').' title="'.$GLOBALS['LANG']->getLL('forms_extra', 1).'" />';
461 break;
462 case 'input':
463 case 'password':
464 $temp_cells[$GLOBALS['LANG']->getLL('forms_size')] = '<input type="text"'.$this->doc->formWidth(5).' name="FORMCFG[c]['.(($k+1)*2).'][size]" value="'.htmlspecialchars($confData['size']).'" title="'.$GLOBALS['LANG']->getLL('forms_size', 1).'" />';
465 $temp_cells[$GLOBALS['LANG']->getLL('forms_max')] = '<input type="text"'.$this->doc->formWidth(5).' name="FORMCFG[c]['.(($k+1)*2).'][max]" value="'.htmlspecialchars($confData['max']).'" title="'.$GLOBALS['LANG']->getLL('forms_max', 1).'" />';
466 break;
467 case 'file':
468 $temp_cells[$GLOBALS['LANG']->getLL('forms_size')] = '<input type="text"'.$this->doc->formWidth(5).' name="FORMCFG[c]['.(($k+1)*2).'][size]" value="'.htmlspecialchars($confData['size']).'" title="'.$GLOBALS['LANG']->getLL('forms_size', 1).'" />';
469 break;
470 case 'select':
471 $temp_cells[$GLOBALS['LANG']->getLL('forms_size')] = '<input type="text"'.$this->doc->formWidth(5).' name="FORMCFG[c]['.(($k+1)*2).'][size]" value="'.htmlspecialchars($confData['size']).'" title="'.$GLOBALS['LANG']->getLL('forms_size', 1).'" />';
472 $temp_cells[$GLOBALS['LANG']->getLL('forms_autosize')] = '<input type="checkbox" name="FORMCFG[c]['.(($k+1)*2).'][autosize]" value="1"'.($confData['autosize']?' checked="checked"':'').' title="'.$GLOBALS['LANG']->getLL('forms_autosize', 1).'" />';
473 $temp_cells[$GLOBALS['LANG']->getLL('forms_multiple')] = '<input type="checkbox" name="FORMCFG[c]['.(($k+1)*2).'][multiple]" value="1"'.($confData['multiple']?' checked="checked"':'').' title="'.$GLOBALS['LANG']->getLL('forms_multiple', 1).'" />';
474 break;
475 }
476
477 // Field configuration depending on the fields type:
478 switch((string)$confData['type']) {
479 case 'textarea':
480 case 'input':
481 case 'password':
482 if (strlen(trim($confData['specialEval']))) {
483 $hiddenFields[] = '<input type="hidden" name="FORMCFG[c]['.(($k+1)*2).'][specialEval]" value="'.htmlspecialchars($confData['specialEval']).'" />';
484 }
485 break;
486 }
487
488 // Default data
489 if ($confData['type'] == 'select' || $confData['type'] == 'radio') {
490 $temp_cells[$GLOBALS['LANG']->getLL('forms_options')] = '<textarea '.$this->doc->formWidthText(15).' rows="4" name="FORMCFG[c]['.(($k+1)*2).'][options]" title="'.$GLOBALS['LANG']->getLL('forms_options', 1).'">'.t3lib_div::formatForTextarea($confData['default']).'</textarea>';
491 } elseif ($confData['type'] == 'check') {
492 $temp_cells[$GLOBALS['LANG']->getLL('forms_checked')] = '<input type="checkbox" name="FORMCFG[c]['.(($k+1)*2).'][default]" value="1"'.(trim($confData['default'])?' checked="checked"':'').' title="'.$GLOBALS['LANG']->getLL('forms_checked', 1).'" />';
493 } elseif ($confData['type'] && $confData['type'] != 'file') {
494 $temp_cells[$GLOBALS['LANG']->getLL('forms_default')] = '<input type="text"'.$this->doc->formWidth(15).' name="FORMCFG[c]['.(($k+1)*2).'][default]" value="'.htmlspecialchars($confData['default']).'" title="'.$GLOBALS['LANG']->getLL('forms_default', 1).'" />';
495 }
496
497 $cells[] = $confData['type']?$this->formatCells($temp_cells):'';
498
499 // CTRL panel for an item (move up/down/around):
500 $ctrl = '';
501 $onClick ="document.wizardForm.action+='#ANC_".(($k+1)*2-2)."';";
502 $onClick = ' onclick="'.htmlspecialchars($onClick).'"';
503 // FIXME $inputStyle undefined
504 $brTag = $inputStyle?'':'<br />';
505 if ($k != 0) {
506 $ctrl .= '<input type="image" name="FORMCFG[row_up]['.(($k+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath, 'gfx/pil2up.gif', '').$onClick.' title="'.$GLOBALS['LANG']->getLL('table_up', 1).'" />'.$brTag;
507 } else {
508 $ctrl .= '<input type="image" name="FORMCFG[row_bottom]['.(($k+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath, 'gfx/turn_up.gif', '').$onClick.' title="'.$GLOBALS['LANG']->getLL('table_bottom', 1).'" />'.$brTag;
509 }
510 $ctrl .= '<input type="image" name="FORMCFG[row_remove]['.(($k+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath, 'gfx/garbage.gif', '').$onClick.' title="'.$GLOBALS['LANG']->getLL('table_removeRow', 1).'" />'.$brTag;
511 // FIXME $tLines undefined
512 if (($k+1) != count($tLines)) {
513 $ctrl.='<input type="image" name="FORMCFG[row_down]['.(($k+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath, 'gfx/pil2down.gif', '').$onClick.' title="'.$GLOBALS['LANG']->getLL('table_down', 1).'" />'.$brTag;
514 } else {
515 $ctrl.='<input type="image" name="FORMCFG[row_top]['.(($k+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath, 'gfx/turn_down.gif', '').$onClick.' title="'.$GLOBALS['LANG']->getLL('table_top', 1).'" />'.$brTag;
516 }
517 $ctrl .= '<input type="image" name="FORMCFG[row_add]['.(($k+1)*2).']"'.t3lib_iconWorks::skinImg($this->doc->backPath, 'gfx/add.gif', '').$onClick.' title="'.$GLOBALS['LANG']->getLL('table_addRow', 1).'" />'.$brTag;
518
519 $ctrl = '<span class="c-wizButtonsV">'.$ctrl.'</span>';
520
521 // Finally, put together the full row from the generated content above:
522 $bgC = $confData['type']?' class="bgColor5"':'';
523 $tRows[] = '
524 <tr' . $bgC . '>
525 <td><a name="ANC_' . (($k + 1) * 2) . '"></a>' . $ctrl . '</td>
526 <td class="bgColor4">' . implode('</td>
527 <td valign="top">', $cells) . '</td>
528 </tr>';
529 }
530 } else {
531 $hiddenFields[]='<input type="hidden" name="FORMCFG[c]['.(($k+1)*2).'][comment]" value="'.htmlspecialchars($confData['comment']).'" />';
532 }
533
534 // Increment counter:
535 $k++;
536 }
537
538 // If the form is of the special type "formtype_mail" (used for tt_content elements):
539 if ($this->special == 'formtype_mail') {
540
541 // Blank spacer:
542 $tRows[] = '
543 <tr>
544 <td colspan="4">&nbsp;</td>
545 </tr>';
546
547 // Header:
548 $tRows[] = '
549 <tr>
550 <td colspan="2" class="bgColor2">&nbsp;</td>
551 <td colspan="2" class="bgColor2"><strong>'.$GLOBALS['LANG']->getLL('forms_special_eform', 1).':</strong>'.
552 t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'wizard_forms_wiz_formmail_info', $GLOBALS['BACK_PATH'], '').
553 '</td>
554 </tr>';
555
556 // "FORM type":
557 $tRows[] = '
558 <tr class="bgColor5">
559 <td>&nbsp;</td>
560 <td class="bgColor4">&nbsp;</td>
561 <td>'.$GLOBALS['LANG']->getLL('forms_eform_formtype_mail', 1).':</td>
562 <td>
563 <input type="hidden" name="FORMCFG[c]['.(1000*2).'][fieldname]" value="formtype_mail" />
564 <input type="hidden" name="FORMCFG[c]['.(1000*2).'][type]" value="submit" />
565 <input type="text"'.$this->doc->formWidth(15).' name="FORMCFG[c]['.(1000*2).'][default]" value="'.htmlspecialchars($specParts['formtype_mail']).'" />
566 </td>
567 </tr>';
568
569 // "Send HTML mail":
570 $tRows[] = '
571 <tr class="bgColor5">
572 <td>&nbsp;</td>
573 <td class="bgColor4">&nbsp;</td>
574 <td>'.$GLOBALS['LANG']->getLL('forms_eform_html_enabled', 1).':</td>
575 <td>
576 <input type="hidden" name="FORMCFG[c]['.(1001*2).'][fieldname]" value="html_enabled" />
577 <input type="hidden" name="FORMCFG[c]['.(1001*2).'][type]" value="hidden" />
578 <input type="checkbox" name="FORMCFG[c]['.(1001*2).'][default]" value="1"'.($specParts['html_enabled']?' checked="checked"':'').' />
579 </td>
580 </tr>';
581
582 // "Subject":
583 $tRows[] = '
584 <tr class="bgColor5">
585 <td>&nbsp;</td>
586 <td class="bgColor4">&nbsp;</td>
587 <td>'.$GLOBALS['LANG']->getLL('forms_eform_subject', 1).':</td>
588 <td>
589 <input type="hidden" name="FORMCFG[c]['.(1002*2).'][fieldname]" value="subject" />
590 <input type="hidden" name="FORMCFG[c]['.(1002*2).'][type]" value="hidden" />
591 <input type="text"'.$this->doc->formWidth(15).' name="FORMCFG[c]['.(1002*2).'][default]" value="'.htmlspecialchars($specParts['subject']).'" />
592 </td>
593 </tr>';
594
595 // Recipient:
596 $tRows[] = '
597 <tr class="bgColor5">
598 <td>&nbsp;</td>
599 <td class="bgColor4">&nbsp;</td>
600 <td>'.$GLOBALS['LANG']->getLL('forms_eform_recipient', 1).':</td>
601 <td>
602 <input type="text"'.$this->doc->formWidth(15).' name="FORMCFG[recipient]" value="'.htmlspecialchars($row['subheader']).'" />
603 </td>
604 </tr>';
605 }
606
607 $content = '';
608
609 // Implode all table rows into a string, wrapped in table tags.
610 $content .= '
611
612 <!--
613 Form wizard
614 -->
615 <table border="0" cellpadding="1" cellspacing="1" id="typo3-formwizard">
616 '.implode('', $tRows).'
617 </table>';
618
619 // Add hidden fields:
620 $content .= implode('', $hiddenFields);
621
622 // Return content:
623 return $content;
624 }
625
626 /**
627 * Detects if a control button (up/down/around/delete) has been pressed for an item and accordingly it will manipulate the internal FORMCFG array
628 *
629 * @return void
630 * @access private
631 */
632 function changeFunc() {
633 if ($this->FORMCFG['row_remove']) {
634 $kk = key($this->FORMCFG['row_remove']);
635 $cmd='row_remove';
636 } elseif ($this->FORMCFG['row_add']) {
637 $kk = key($this->FORMCFG['row_add']);
638 $cmd='row_add';
639 } elseif ($this->FORMCFG['row_top']) {
640 $kk = key($this->FORMCFG['row_top']);
641 $cmd='row_top';
642 } elseif ($this->FORMCFG['row_bottom']) {
643 $kk = key($this->FORMCFG['row_bottom']);
644 $cmd='row_bottom';
645 } elseif ($this->FORMCFG['row_up']) {
646 $kk = key($this->FORMCFG['row_up']);
647 $cmd='row_up';
648 } elseif ($this->FORMCFG['row_down']) {
649 $kk = key($this->FORMCFG['row_down']);
650 $cmd='row_down';
651 }
652
653 if ($cmd && t3lib_utility_Math::canBeInterpretedAsInteger($kk)) {
654 if (substr($cmd, 0, 4)=='row_') {
655 switch($cmd) {
656 case 'row_remove':
657 unset($this->FORMCFG['c'][$kk]);
658 break;
659 case 'row_add':
660 $this->FORMCFG['c'][$kk+1]=array();
661 break;
662 case 'row_top':
663 $this->FORMCFG['c'][1]=$this->FORMCFG['c'][$kk];
664 unset($this->FORMCFG['c'][$kk]);
665 break;
666 case 'row_bottom':
667 $this->FORMCFG['c'][1000000]=$this->FORMCFG['c'][$kk];
668 unset($this->FORMCFG['c'][$kk]);
669 break;
670 case 'row_up':
671 $this->FORMCFG['c'][$kk-3]=$this->FORMCFG['c'][$kk];
672 unset($this->FORMCFG['c'][$kk]);
673 break;
674 case 'row_down':
675 $this->FORMCFG['c'][$kk+3]=$this->FORMCFG['c'][$kk];
676 unset($this->FORMCFG['c'][$kk]);
677 break;
678 }
679 ksort($this->FORMCFG['c']);
680 }
681 }
682 }
683
684 /**
685 * Converts the input array to a configuration code string
686 *
687 * @param array $cfgArr Array of form configuration (follows the input structure from the form wizard POST form)
688 * @return string The array converted into a string with line-based configuration.
689 * @see cfgString2CfgArray()
690 */
691 function cfgArray2CfgString($cfgArr) {
692
693 // Initialize:
694 $inLines = array();
695
696 // Traverse the elements of the form wizard and transform the settings into configuration code.
697 foreach ($cfgArr as $vv) {
698 // If "content" is found, then just pass it over.
699 if ($vv['comment']) {
700 $inLines[]=trim($vv['comment']);
701 } else { // Begin to put together the single-line configuration code of this field:
702
703 // Reset:
704 $thisLine = array();
705
706 // Set Label:
707 $thisLine[0] = str_replace('|', '', $vv['label']);
708
709 // Set Type:
710 if ($vv['type']) {
711 $thisLine[1] = ($vv['required']?'*':'').str_replace(',', '', ($vv['fieldname']?$vv['fieldname'].'=':'').$vv['type']);
712
713 // Default:
714 $tArr = array('', '', '', '', '', '');
715 switch((string)$vv['type']) {
716 case 'textarea':
717 if (intval($vv['cols'])) {
718 $tArr[0] = intval($vv['cols']);
719 }
720 if (intval($vv['rows'])) {
721 $tArr[1] = intval($vv['rows']);
722 }
723 if (trim($vv['extra'])) {
724 $tArr[2] = trim($vv['extra']);
725 }
726 if (strlen($vv['specialEval'])) {
727 // Preset blank default value so position 3 can get a value...
728 $thisLine[2] = '';
729 $thisLine[3] = $vv['specialEval'];
730 }
731 break;
732 case 'input':
733 case 'password':
734 if (intval($vv['size'])) {
735 $tArr[0] = intval($vv['size']);
736 }
737 if (intval($vv['max'])) {
738 $tArr[1] = intval($vv['max']);
739 }
740 if (strlen($vv['specialEval'])) {
741 // Preset blank default value so position 3 can get a value...
742 $thisLine[2] = '';
743 $thisLine[3] = $vv['specialEval'];
744 }
745 break;
746 case 'file':
747 if (intval($vv['size'])) {
748 $tArr[0] = intval($vv['size']);
749 }
750 break;
751 case 'select':
752 if (intval($vv['size'])) {
753 $tArr[0] = intval($vv['size']);
754 }
755 if ($vv['autosize']) {
756 $tArr[0] = 'auto';
757 }
758 if ($vv['multiple']) {
759 $tArr[1] = 'm';
760 }
761 break;
762 }
763 $tArr = $this->cleanT($tArr);
764 if (count($tArr)) {
765 $thisLine[1] .= ','.implode(',', $tArr);
766 }
767
768 $thisLine[1] = str_replace('|', '', $thisLine[1]);
769
770 // Default:
771 if ($vv['type'] == 'select' || $vv['type'] == 'radio') {
772 $thisLine[2] = str_replace(LF, ', ', str_replace(',', '', $vv['options']));
773 } elseif ($vv['type'] == 'check') {
774 if ($vv['default']) {
775 $thisLine[2] = 1;
776 }
777 } elseif (strcmp(trim($vv['default']), '')) {
778 $thisLine[2] = $vv['default'];
779 }
780 if (isset($thisLine[2])) {
781 $thisLine[2] = str_replace('|', '', $thisLine[2]);
782 }
783 }
784
785 // Compile the final line:
786 $inLines[] = preg_replace("/[\n\r]*/", '', implode(' | ', $thisLine));
787 }
788 }
789 // Finally, implode the lines into a string, and return it:
790 return implode(LF, $inLines);
791 }
792
793 /**
794 * Converts the input configuration code string into an array
795 *
796 * @param string $cfgStr Configuration code
797 * @return array Configuration array
798 * @see cfgArray2CfgString()
799 */
800 function cfgString2CfgArray($cfgStr) {
801
802 // Traverse the number of form elements:
803 $tLines = explode(LF, $cfgStr);
804 foreach ($tLines as $k => $v) {
805
806 // Initialize:
807 $confData = array();
808 $val = trim($v);
809
810 // Accept a line as configuration if a) it is blank(! - because blank lines indicates new,
811 // unconfigured fields) or b) it is NOT a comment.
812 if (!$val || strcspn($val, '#/')) {
813
814 // Split:
815 $parts = t3lib_div::trimExplode('|', $val);
816
817 // Label:
818 $confData['label'] = trim($parts[0]);
819
820 // Field:
821 $fParts = t3lib_div::trimExplode(',', $parts[1]);
822 $fParts[0] = trim($fParts[0]);
823 if (substr($fParts[0], 0, 1) == '*') {
824 $confData['required'] = 1;
825 $fParts[0] = substr($fParts[0], 1);
826 }
827
828 $typeParts = t3lib_div::trimExplode('=', $fParts[0]);
829 $confData['type'] = trim(strtolower(end($typeParts)));
830
831 if ($confData['type']) {
832 if (count($typeParts) == 1) {
833 $confData['fieldname'] = substr(preg_replace('/[^a-zA-Z0-9_]/', '', str_replace(' ', '_', trim($parts[0]))), 0, 30);
834
835 // Attachment names...
836 if ($confData['type'] == 'file') {
837 $confData['fieldname'] = 'attachment'.$attachmentCounter;
838 $attachmentCounter = intval($attachmentCounter)+1;
839 }
840 } else {
841 $confData['fieldname'] = str_replace(' ', '_', trim($typeParts[0]));
842 }
843
844 switch((string)$confData['type']) {
845 case 'select':
846 case 'radio':
847 $confData['default'] = implode(LF, t3lib_div::trimExplode(',', $parts[2]));
848 break;
849 default:
850 $confData['default'] = trim($parts[2]);
851 break;
852 }
853
854 // Field configuration depending on the fields type:
855 switch((string)$confData['type']) {
856 case 'textarea':
857 $confData['cols'] = $fParts[1];
858 $confData['rows'] = $fParts[2];
859 $confData['extra'] = strtoupper($fParts[3]) == 'OFF' ? 'OFF' : '';
860 $confData['specialEval'] = trim($parts[3]);
861 break;
862 case 'input':
863 case 'password':
864 $confData['size'] = $fParts[1];
865 $confData['max'] = $fParts[2];
866 $confData['specialEval'] = trim($parts[3]);
867 break;
868 case 'file':
869 $confData['size'] = $fParts[1];
870 break;
871 case 'select':
872 $confData['size'] = intval($fParts[1])?$fParts[1]:'';
873 $confData['autosize'] = strtolower(trim($fParts[1]))=='auto' ? 1 : 0;
874 $confData['multiple'] = strtolower(trim($fParts[2]))=='m' ? 1 : 0;
875 break;
876 }
877 }
878 } else {
879 // No configuration, only a comment:
880 $confData = array(
881 'comment' => $val
882 );
883 }
884
885 // Adding config array:
886 $cfgArr[] = $confData;
887 }
888
889 // Return cfgArr
890 return $cfgArr;
891 }
892
893 /**
894 * Removes any "trailing elements" in the array which consists of whitespace (little like trim() does for strings, so this does for arrays)
895 *
896 * @param array $tArr Single dim array
897 * @return array Processed array
898 * @access private
899 */
900 function cleanT($tArr) {
901 for($a = count($tArr); $a > 0; $a--) {
902 if (strcmp($tArr[$a-1], '')) {
903 break;
904 } else {
905 unset($tArr[$a-1]);
906 }
907 }
908 return $tArr;
909 }
910
911 /**
912 * Wraps items in $fArr in table cells/rows, displaying them vertically.
913 *
914 * @param array $fArr Array of label/HTML pairs.
915 * @return string HTML table
916 * @access private
917 */
918 function formatCells($fArr) {
919
920 // Traverse the elements in $fArr and wrap them in table cells:
921 $lines = array();
922 foreach ($fArr as $l => $c) {
923 $lines[] = '
924 <tr>
925 <td nowrap="nowrap">'.htmlspecialchars($l.':').'&nbsp;</td>
926 <td>'.$c.'</td>
927 </tr>';
928 }
929
930 // Add a cell which will set a minimum width:
931 $lines[] = '
932 <tr>
933 <td nowrap="nowrap"><img src="clear.gif" width="70" height="1" alt="" /></td>
934 <td></td>
935 </tr>';
936
937 // Wrap in table and return:
938 return '
939 <table border="0" cellpadding="0" cellspacing="0">
940 '.implode('', $lines).'
941 </table>';
942 }
943 }
944
945 // Make instance:
946 $SOBE = t3lib_div::makeInstance('SC_wizard_forms');
947 $SOBE->init();
948
949 // Include files?
950 foreach ($SOBE->include_once as $INC_FILE) {
951 include_once($INC_FILE);
952 }
953
954 $SOBE->main();
955 $SOBE->printContent();
956
957 ?>