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