Cleanup: Updated copyright comments
[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 * 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 Skårhøj
32 * XHTML compliant
33 *
34 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
35 */
36 /**
37 * [CLASS/FUNCTION INDEX of SCRIPT]
38 *
39 *
40 *
41 * 175: class SC_wizard_forms
42 * 203: function init()
43 * 242: function main()
44 * 257: function printContent()
45 * 268: function formsWizard()
46 *
47 * SECTION: Helper functions
48 * 311: function getConfigCode(&$row)
49 * 382: function getFormHTML($formCfgArray,$row)
50 * 662: function changeFunc()
51 * 721: function cfgArray2CfgString($cfgArr)
52 * 803: function cfgString2CfgArray($cfgStr)
53 * 902: function cleanT($tArr)
54 * 920: 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 $LANG->includeLLFile('EXT:lang/locallang_wizards.xml');
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 Skårhøj <kasperYYYY@typo3.com>
172 * @package TYPO3
173 * @subpackage core
174 */
175 class SC_wizard_forms {
176
177 // Internal, dynamic:
178 /**
179 * document template object
180 *
181 * @var mediumDoc
182 */
183 var $doc;
184 var $content; // Content accumulation for the module.
185 var $include_once=array(); // List of files to include.
186 var $attachmentCounter = 0; // Used to numerate attachments automatically.
187
188
189 // Internal, static:
190 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!
191
192
193 // Internal, static: GPvars
194 var $P; // Wizard parameters, coming from TCEforms linking to the wizard.
195 var $FORMCFG; // The array which is constantly submitted by the multidimensional form of this wizard.
196 var $special; // Indicates if the form is of a dedicated type, like "formtype_mail" (for tt_content element "Form")
197
198
199
200
201
202
203 /**
204 * Initialization the class
205 *
206 * @return void
207 */
208 function init() {
209 // GPvars:
210 $this->P = t3lib_div::_GP('P');
211 $this->special = t3lib_div::_GP('special');
212 $this->FORMCFG = t3lib_div::_GP('FORMCFG');
213
214 // Setting options:
215 $this->xmlStorage = $this->P['params']['xmlOutput'];
216
217 // Document template object:
218 $this->doc = t3lib_div::makeInstance('template');
219 $this->doc->backPath = $GLOBALS['BACK_PATH'];
220 $this->doc->setModuleTemplate('templates/wizard_forms.html');
221 $this->doc->JScode=$this->doc->wrapScriptTags('
222 function jumpToUrl(URL,formEl) { //
223 window.location.href = URL;
224 }
225 ');
226
227 // Setting form tag:
228 list($rUri) = explode('#',t3lib_div::getIndpEnv('REQUEST_URI'));
229 $this->doc->form ='<form action="'.htmlspecialchars($rUri).'" method="post" name="wizardForm">';
230
231 // If save command found, include tcemain:
232 if ($_POST['savedok_x'] || $_POST['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 if ($this->P['table'] && $this->P['field'] && $this->P['uid']) {
244 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('forms_title'), $this->formsWizard(), 0, 1);
245 } else {
246 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('forms_title'), '<span class="typo3-red">' . $GLOBALS['LANG']->getLL('table_noData',1) . '</span>', 0, 1);
247 }
248
249 // Setting up the buttons and markers for docheader
250 $docHeaderButtons = $this->getButtons();
251 $markers['CSH'] = $docHeaderButtons['csh'];
252 $markers['CONTENT'] = $this->content;
253
254 // Build the <body> for the module
255 $this->content = $this->doc->startPage('Form Wizard');
256 $this->content.= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
257 $this->content.= $this->doc->endPage();
258 $this->content = $this->doc->insertStylesAndJS($this->content);
259 }
260
261 /**
262 * Outputting the accumulated content to screen
263 *
264 * @return void
265 */
266 function printContent() {
267 echo $this->content;
268 }
269
270 /**
271 * Create the panel of buttons for submitting the form or otherwise perform operations.
272 *
273 * @return array all available buttons as an assoc. array
274 */
275 protected function getButtons() {
276 $buttons = array(
277 'csh' => '',
278 'csh_buttons' => '',
279 'close' => '',
280 'save' => '',
281 'save_close' => '',
282 'reload' => '',
283 );
284
285 if ($this->P['table'] && $this->P['field'] && $this->P['uid']) {
286 // CSH
287 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'wizard_forms_wiz', $GLOBALS['BACK_PATH'], '');
288
289 // CSH Buttons
290 $buttons['csh_buttons'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'wizard_forms_wiz_buttons', $GLOBALS['BACK_PATH'], '');
291
292 // Close
293 $buttons['close'] = '<a href="#" onclick="' . htmlspecialchars('jumpToUrl(unescape(\'' . rawurlencode(t3lib_div::sanitizeLocalUrl($this->P['returnUrl'])) . '\')); return false;') . '">' .
294 t3lib_iconWorks::getSpriteIcon('actions-document-close', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:rm.closeDoc', TRUE))) .
295 '</a>';
296
297 // Save
298 $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) . '" />';
299
300 // Save & Close
301 $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) . '" />';
302
303 // Reload
304 $buttons['reload'] = '<input type="image" class="c-inputButton" name="_refresh"' . t3lib_iconWorks::skinImg('', 'gfx/refresh_n.gif') . ' title="' . $GLOBALS['LANG']->getLL('forms_refresh', 1) . '" />';
305 }
306
307 return $buttons;
308 }
309
310 /**
311 * Draws the form wizard content
312 *
313 * @return string HTML content for the form.
314 */
315 function formsWizard() {
316
317 // First, check the references by selecting the record:
318 $row = t3lib_BEfunc::getRecord($this->P['table'],$this->P['uid']);
319 if (!is_array($row)) {
320 throw new RuntimeException('Wizard Error: No reference to record');
321 }
322
323 // 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.
324 $formCfgArray = $this->getConfigCode($row);
325
326 // Generation of the Form Wizards HTML code:
327 $content = $this->getFormHTML($formCfgArray,$row);
328
329 // Return content:
330 return $content;
331 }
332
333
334
335
336
337
338
339
340
341
342
343 /****************************
344 *
345 * Helper functions
346 *
347 ***************************/
348
349 /**
350 * Will get and return the configuration code string
351 * Will also save (and possibly redirect/exit) the content if a save button has been pressed
352 *
353 * @param array Current parent record row (passed by value!)
354 * @return array Configuration Array
355 * @access private
356 */
357 function getConfigCode(&$row) {
358
359 // If some data has been submitted, then construct
360 if (isset($this->FORMCFG['c'])) {
361
362 // Process incoming:
363 $this->changeFunc();
364
365 // Convert to string (either line based or XML):
366 if ($this->xmlStorage) {
367 // Convert the input array to XML:
368 $bodyText = t3lib_div::array2xml_cs($this->FORMCFG['c'],'T3FormWizard');
369
370 // Setting cfgArr directly from the input:
371 $cfgArr = $this->FORMCFG['c'];
372 } else {
373 // Convert the input array to a string of configuration code:
374 $bodyText = $this->cfgArray2CfgString($this->FORMCFG['c']);
375
376 // Create cfgArr from the string based configuration - that way it is cleaned up and any incompatibilities will be removed!
377 $cfgArr = $this->cfgString2CfgArray($bodyText);
378 }
379
380 // If a save button has been pressed, then save the new field content:
381 if ($_POST['savedok_x'] || $_POST['saveandclosedok_x']) {
382
383 // Make TCEmain object:
384 $tce = t3lib_div::makeInstance('t3lib_TCEmain');
385 $tce->stripslashes_values=0;
386
387 // Put content into the data array:
388 $data=array();
389 $data[$this->P['table']][$this->P['uid']][$this->P['field']]=$bodyText;
390 if ($this->special=='formtype_mail') {
391 $data[$this->P['table']][$this->P['uid']]['subheader']=$this->FORMCFG['recipient'];
392 }
393
394 // Perform the update:
395 $tce->start($data,array());
396 $tce->process_datamap();
397
398 // Re-load the record content:
399 $row = t3lib_BEfunc::getRecord($this->P['table'],$this->P['uid']);
400
401 // If the save/close button was pressed, then redirect the screen:
402 if ($_POST['saveandclosedok_x']) {
403 t3lib_utility_Http::redirect(t3lib_div::sanitizeLocalUrl($this->P['returnUrl']));
404 }
405 }
406 } else { // If nothing has been submitted, load the $bodyText variable from the selected database row:
407 if ($this->xmlStorage) {
408 $cfgArr = t3lib_div::xml2array($row[$this->P['field']]);
409 } else { // Regular linebased form configuration:
410 $cfgArr = $this->cfgString2CfgArray($row[$this->P['field']]);
411 }
412 $cfgArr = is_array($cfgArr) ? $cfgArr : array();
413 }
414
415 // Return configuration code:
416 return $cfgArr;
417 }
418
419 /**
420 * Creates the HTML for the Form Wizard:
421 *
422 * @param string Form config array
423 * @param array Current parent record array
424 * @return string HTML for the form wizard
425 * @access private
426 */
427 function getFormHTML($formCfgArray,$row) {
428 global $LANG;
429
430 // Initialize variables:
431 $specParts=array();
432 $hiddenFields=array();
433 $tRows=array();
434
435 // Set header row:
436 $cells=array($LANG->getLL('forms_preview',1).':',
437 $LANG->getLL('forms_element',1).':',
438 $LANG->getLL('forms_config',1).':',
439 );
440 $tRows[]='
441 <tr class="bgColor2" id="typo3-formWizardHeader">
442 <td>&nbsp;</td>
443 <td>'.implode('</td>
444 <td>',$cells).'</td>
445 </tr>';
446
447 // Traverse the number of form elements:
448 $k=0;
449 foreach($formCfgArray as $confData) {
450
451 // Initialize:
452 $cells=array();
453
454 // If there is a configuration line which is active, then render it:
455 if (!isset($confData['comment'])) {
456
457 // Special parts:
458 if ($this->special=='formtype_mail' && t3lib_div::inList('formtype_mail,subject,html_enabled',$confData['fieldname'])) {
459 $specParts[$confData['fieldname']] = $confData['default'];
460 } else {
461
462 // Render title/field preview COLUMN
463 $cells[]=$confData['type']!='hidden' ? '<strong>'.htmlspecialchars($confData['label']).'</strong>' : '';
464
465
466 // Render general type/title COLUMN:
467 $temp_cells=array();
468
469 // Field type selector:
470 $opt=array();
471 $opt[]='<option value=""></option>';
472 $types = explode(',','input,textarea,select,check,radio,password,file,hidden,submit,property,label');
473 foreach($types as $t) {
474 $opt[]='
475 <option value="'.$t.'"'.($confData['type']==$t?' selected="selected"':'').'>'.$LANG->getLL('forms_type_'.$t,1).'</option>';
476 }
477 $temp_cells[$LANG->getLL('forms_type')]='
478 <select name="FORMCFG[c]['.(($k+1)*2).'][type]">
479 '.implode('
480 ',$opt).'
481 </select>';
482
483 // Title field:
484 if (!t3lib_div::inList('hidden,submit',$confData['type'])) {
485 $temp_cells[$LANG->getLL('forms_label')]='<input type="text"'.$this->doc->formWidth(15).' name="FORMCFG[c]['.(($k+1)*2).'][label]" value="'.htmlspecialchars($confData['label']).'" />';
486 }
487
488 // Required checkbox:
489 if (!t3lib_div::inList('check,hidden,submit,label',$confData['type'])) {
490 $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).'" />';
491 }
492
493 // Put sub-items together into table cell:
494 $cells[]=$this->formatCells($temp_cells);
495
496
497 // Render specific field configuration COLUMN:
498 $temp_cells=array();
499
500 // Fieldname
501 if ($this->special=='formtype_mail' && $confData['type']=='file') {
502 $confData['fieldname'] = 'attachment'.(++$this->attachmentCounter);
503 }
504 if (!t3lib_div::inList('label',$confData['type'])) {
505 $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).'" />';
506 }
507
508 // Field configuration depending on the fields type:
509 switch((string)$confData['type']) {
510 case 'textarea':
511 $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).'" />';
512 $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).'" />';
513 $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).'" />';
514 break;
515 case 'input':
516 case 'password':
517 $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).'" />';
518 $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).'" />';
519 break;
520 case 'file':
521 $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).'" />';
522 break;
523 case 'select':
524 $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).'" />';
525 $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).'" />';
526 $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).'" />';
527 break;
528 }
529
530 // Field configuration depending on the fields type:
531 switch((string)$confData['type']) {
532 case 'textarea':
533 case 'input':
534 case 'password':
535 if (strlen(trim($confData['specialEval']))) {
536 $hiddenFields[] = '<input type="hidden" name="FORMCFG[c]['.(($k+1)*2).'][specialEval]" value="'.htmlspecialchars($confData['specialEval']).'" />';
537 }
538 break;
539 }
540
541 // Default data
542 if ($confData['type']=='select' || $confData['type']=='radio') {
543 $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>';
544 } elseif ($confData['type']=='check') {
545 $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).'" />';
546 } elseif ($confData['type'] && $confData['type']!='file') {
547 $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).'" />';
548 }
549
550 $cells[]=$confData['type']?$this->formatCells($temp_cells):'';
551
552 // CTRL panel for an item (move up/down/around):
553 $ctrl='';
554 $onClick="document.wizardForm.action+='#ANC_".(($k+1)*2-2)."';";
555 $onClick=' onclick="'.htmlspecialchars($onClick).'"';
556 // FIXME $inputStyle undefined
557 $brTag=$inputStyle?'':'<br />';
558 if ($k!=0) {
559 $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;
560 } else {
561 $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;
562 }
563 $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;
564 // FIXME $tLines undefined
565 if (($k+1)!=count($tLines)) {
566 $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;
567 } else {
568 $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;
569 }
570 $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;
571
572 $ctrl='<span class="c-wizButtonsV">'.$ctrl.'</span>';
573
574 // Finally, put together the full row from the generated content above:
575 $bgC = $confData['type']?' class="bgColor5"':'';
576 $tRows[]='
577 <tr'.$bgC.'>
578 <td><a name="ANC_'.(($k+1)*2).'"></a>'.$ctrl.'</td>
579 <td class="bgColor4">'.implode('</td>
580 <td valign="top">',$cells).'</td>
581 </tr>';
582 }
583 } else {
584 $hiddenFields[]='<input type="hidden" name="FORMCFG[c]['.(($k+1)*2).'][comment]" value="'.htmlspecialchars($confData['comment']).'" />';
585 }
586
587 // Increment counter:
588 $k++;
589 }
590
591 // If the form is of the special type "formtype_mail" (used for tt_content elements):
592 if ($this->special=='formtype_mail') {
593
594 // Blank spacer:
595 $tRows[]='
596 <tr>
597 <td colspan="4">&nbsp;</td>
598 </tr>';
599
600 // Header:
601 $tRows[]='
602 <tr>
603 <td colspan="2" class="bgColor2">&nbsp;</td>
604 <td colspan="2" class="bgColor2"><strong>'.$LANG->getLL('forms_special_eform',1).':</strong>'.
605 t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'wizard_forms_wiz_formmail_info', $GLOBALS['BACK_PATH'],'').
606 '</td>
607 </tr>';
608
609 // "FORM type":
610 $tRows[]='
611 <tr class="bgColor5">
612 <td>&nbsp;</td>
613 <td class="bgColor4">&nbsp;</td>
614 <td>'.$LANG->getLL('forms_eform_formtype_mail',1).':</td>
615 <td>
616 <input type="hidden" name="FORMCFG[c]['.(1000*2).'][fieldname]" value="formtype_mail" />
617 <input type="hidden" name="FORMCFG[c]['.(1000*2).'][type]" value="submit" />
618 <input type="text"'.$this->doc->formWidth(15).' name="FORMCFG[c]['.(1000*2).'][default]" value="'.htmlspecialchars($specParts['formtype_mail']).'" />
619 </td>
620 </tr>';
621
622 // "Send HTML mail":
623 $tRows[]='
624 <tr class="bgColor5">
625 <td>&nbsp;</td>
626 <td class="bgColor4">&nbsp;</td>
627 <td>'.$LANG->getLL('forms_eform_html_enabled',1).':</td>
628 <td>
629 <input type="hidden" name="FORMCFG[c]['.(1001*2).'][fieldname]" value="html_enabled" />
630 <input type="hidden" name="FORMCFG[c]['.(1001*2).'][type]" value="hidden" />
631 <input type="checkbox" name="FORMCFG[c]['.(1001*2).'][default]" value="1"'.($specParts['html_enabled']?' checked="checked"':'').' />
632 </td>
633 </tr>';
634
635 // "Subject":
636 $tRows[]='
637 <tr class="bgColor5">
638 <td>&nbsp;</td>
639 <td class="bgColor4">&nbsp;</td>
640 <td>'.$LANG->getLL('forms_eform_subject',1).':</td>
641 <td>
642 <input type="hidden" name="FORMCFG[c]['.(1002*2).'][fieldname]" value="subject" />
643 <input type="hidden" name="FORMCFG[c]['.(1002*2).'][type]" value="hidden" />
644 <input type="text"'.$this->doc->formWidth(15).' name="FORMCFG[c]['.(1002*2).'][default]" value="'.htmlspecialchars($specParts['subject']).'" />
645 </td>
646 </tr>';
647
648 // Recipient:
649 $tRows[]='
650 <tr class="bgColor5">
651 <td>&nbsp;</td>
652 <td class="bgColor4">&nbsp;</td>
653 <td>'.$LANG->getLL('forms_eform_recipient',1).':</td>
654 <td>
655 <input type="text"'.$this->doc->formWidth(15).' name="FORMCFG[recipient]" value="'.htmlspecialchars($row['subheader']).'" />
656 </td>
657 </tr>';
658 }
659
660 $content = '';
661
662 // Implode all table rows into a string, wrapped in table tags.
663 $content.= '
664
665 <!--
666 Form wizard
667 -->
668 <table border="0" cellpadding="1" cellspacing="1" id="typo3-formwizard">
669 '.implode('',$tRows).'
670 </table>';
671
672 // Add hidden fields:
673 $content.= implode('',$hiddenFields);
674
675 // Return content:
676 return $content;
677 }
678
679 /**
680 * Detects if a control button (up/down/around/delete) has been pressed for an item and accordingly it will manipulate the internal FORMCFG array
681 *
682 * @return void
683 * @access private
684 */
685 function changeFunc() {
686 if ($this->FORMCFG['row_remove']) {
687 $kk = key($this->FORMCFG['row_remove']);
688 $cmd='row_remove';
689 } elseif ($this->FORMCFG['row_add']) {
690 $kk = key($this->FORMCFG['row_add']);
691 $cmd='row_add';
692 } elseif ($this->FORMCFG['row_top']) {
693 $kk = key($this->FORMCFG['row_top']);
694 $cmd='row_top';
695 } elseif ($this->FORMCFG['row_bottom']) {
696 $kk = key($this->FORMCFG['row_bottom']);
697 $cmd='row_bottom';
698 } elseif ($this->FORMCFG['row_up']) {
699 $kk = key($this->FORMCFG['row_up']);
700 $cmd='row_up';
701 } elseif ($this->FORMCFG['row_down']) {
702 $kk = key($this->FORMCFG['row_down']);
703 $cmd='row_down';
704 }
705
706 if ($cmd && t3lib_div::testInt($kk)) {
707 if (substr($cmd,0,4)=='row_') {
708 switch($cmd) {
709 case 'row_remove':
710 unset($this->FORMCFG['c'][$kk]);
711 break;
712 case 'row_add':
713 $this->FORMCFG['c'][$kk+1]=array();
714 break;
715 case 'row_top':
716 $this->FORMCFG['c'][1]=$this->FORMCFG['c'][$kk];
717 unset($this->FORMCFG['c'][$kk]);
718 break;
719 case 'row_bottom':
720 $this->FORMCFG['c'][1000000]=$this->FORMCFG['c'][$kk];
721 unset($this->FORMCFG['c'][$kk]);
722 break;
723 case 'row_up':
724 $this->FORMCFG['c'][$kk-3]=$this->FORMCFG['c'][$kk];
725 unset($this->FORMCFG['c'][$kk]);
726 break;
727 case 'row_down':
728 $this->FORMCFG['c'][$kk+3]=$this->FORMCFG['c'][$kk];
729 unset($this->FORMCFG['c'][$kk]);
730 break;
731 }
732 ksort($this->FORMCFG['c']);
733 }
734 }
735 }
736
737 /**
738 * Converts the input array to a configuration code string
739 *
740 * @param array Array of form configuration (follows the input structure from the form wizard POST form)
741 * @return string The array converted into a string with line-based configuration.
742 * @see cfgString2CfgArray()
743 */
744 function cfgArray2CfgString($cfgArr) {
745
746 // Initialize:
747 $inLines=array();
748
749 // Traverse the elements of the form wizard and transform the settings into configuration code.
750 foreach($cfgArr as $vv) {
751 if ($vv['comment']) { // If "content" is found, then just pass it over.
752 $inLines[]=trim($vv['comment']);
753 } else { // Begin to put together the single-line configuration code of this field:
754
755 // Reset:
756 $thisLine=array();
757
758 // Set Label:
759 $thisLine[0]=str_replace('|','',$vv['label']);
760
761 // Set Type:
762 if ($vv['type']) {
763 $thisLine[1]=($vv['required']?'*':'').str_replace(',','',($vv['fieldname']?$vv['fieldname'].'=':'').$vv['type']);
764
765 // Default:
766 $tArr=array('','','','','','');
767 switch((string)$vv['type']) {
768 case 'textarea':
769 if (intval($vv['cols'])) $tArr[0]=intval($vv['cols']);
770 if (intval($vv['rows'])) $tArr[1]=intval($vv['rows']);
771 if (trim($vv['extra'])) $tArr[2]=trim($vv['extra']);
772 if (strlen($vv['specialEval'])) {
773 $thisLine[2] = ''; // Preset blank default value so position 3 can get a value...
774 $thisLine[3] = $vv['specialEval'];
775 }
776 break;
777 case 'input':
778 case 'password':
779 if (intval($vv['size'])) $tArr[0]=intval($vv['size']);
780 if (intval($vv['max'])) $tArr[1]=intval($vv['max']);
781 if (strlen($vv['specialEval'])) {
782 $thisLine[2] = ''; // Preset blank default value so position 3 can get a value...
783 $thisLine[3] = $vv['specialEval'];
784 }
785 break;
786 case 'file':
787 if (intval($vv['size'])) $tArr[0]=intval($vv['size']);
788 break;
789 case 'select':
790 if (intval($vv['size'])) $tArr[0]=intval($vv['size']);
791 if ($vv['autosize']) $tArr[0]='auto';
792 if ($vv['multiple']) $tArr[1]='m';
793 break;
794 }
795 $tArr = $this->cleanT($tArr);
796 if (count($tArr)) $thisLine[1].=','.implode(',',$tArr);
797
798 $thisLine[1]=str_replace('|','',$thisLine[1]);
799
800 // Default:
801 if ($vv['type']=='select' || $vv['type']=='radio') {
802 $thisLine[2]=str_replace(LF,', ',str_replace(',','',$vv['options']));
803 } elseif ($vv['type']=='check') {
804 if ($vv['default']) $thisLine[2]=1;
805 } elseif (strcmp(trim($vv['default']),'')) {
806 $thisLine[2]=$vv['default'];
807 }
808 if (isset($thisLine[2])) $thisLine[2]=str_replace('|','',$thisLine[2]);
809 }
810
811 // Compile the final line:
812 $inLines[]=preg_replace("/[\n\r]*/",'',implode(' | ',$thisLine));
813 }
814 }
815 // Finally, implode the lines into a string, and return it:
816 return implode(LF,$inLines);
817 }
818
819 /**
820 * Converts the input configuration code string into an array
821 *
822 * @param string Configuration code
823 * @return array Configuration array
824 * @see cfgArray2CfgString()
825 */
826 function cfgString2CfgArray($cfgStr) {
827
828 // Traverse the number of form elements:
829 $tLines=explode(LF,$cfgStr);
830 foreach($tLines as $k => $v) {
831
832 // Initialize:
833 $confData=array();
834 $val=trim($v);
835
836 // Accept a line as configuration if a) it is blank(! - because blank lines indicates new, unconfigured fields) or b) it is NOT a comment.
837 if (!$val || strcspn($val,'#/')) {
838
839 // Split:
840 $parts = t3lib_div::trimExplode('|',$val);
841
842 // Label:
843 $confData['label'] = trim($parts[0]);
844
845 // Field:
846 $fParts = t3lib_div::trimExplode(',',$parts[1]);
847 $fParts[0]=trim($fParts[0]);
848 if (substr($fParts[0],0,1)=='*') {
849 $confData['required'] = 1;
850 $fParts[0] = substr($fParts[0],1);
851 }
852
853 $typeParts = t3lib_div::trimExplode('=',$fParts[0]);
854 $confData['type'] = trim(strtolower(end($typeParts)));
855
856 if ($confData['type']) {
857 if (count($typeParts)==1) {
858 $confData['fieldname'] = substr(preg_replace('/[^a-zA-Z0-9_]/','',str_replace(' ','_',trim($parts[0]))),0,30);
859
860 // Attachment names...
861 if ($confData['type']=='file') {
862 $confData['fieldname']='attachment'.$attachmentCounter;
863 $attachmentCounter=intval($attachmentCounter)+1;
864 }
865 } else {
866 $confData['fieldname'] = str_replace(' ','_',trim($typeParts[0]));
867 }
868
869 switch((string)$confData['type']) {
870 case 'select':
871 case 'radio':
872 $confData['default'] = implode(LF,t3lib_div::trimExplode(',',$parts[2]));
873 break;
874 default:
875 $confData['default'] = trim($parts[2]);
876 break;
877 }
878
879 // Field configuration depending on the fields type:
880 switch((string)$confData['type']) {
881 case 'textarea':
882 $confData['cols'] = $fParts[1];
883 $confData['rows'] = $fParts[2];
884 $confData['extra'] = strtoupper($fParts[3])=='OFF' ? 'OFF' : '';
885 $confData['specialEval'] = trim($parts[3]);
886 break;
887 case 'input':
888 case 'password':
889 $confData['size'] = $fParts[1];
890 $confData['max'] = $fParts[2];
891 $confData['specialEval'] = trim($parts[3]);
892 break;
893 case 'file':
894 $confData['size'] = $fParts[1];
895 break;
896 case 'select':
897 $confData['size'] = intval($fParts[1])?$fParts[1]:'';
898 $confData['autosize'] = strtolower(trim($fParts[1]))=='auto' ? 1 : 0;
899 $confData['multiple'] = strtolower(trim($fParts[2]))=='m' ? 1 : 0;
900 break;
901 }
902 }
903 } else {
904 // No configuration, only a comment:
905 $confData=array(
906 'comment' => $val
907 );
908 }
909
910 // Adding config array:
911 $cfgArr[]=$confData;
912 }
913
914 // Return cfgArr
915 return $cfgArr;
916 }
917
918 /**
919 * Removes any "trailing elements" in the array which consists of whitespace (little like trim() does for strings, so this does for arrays)
920 *
921 * @param array Single dim array
922 * @return array Processed array
923 * @access private
924 */
925 function cleanT($tArr) {
926 for($a=count($tArr);$a>0;$a--) {
927 if (strcmp($tArr[$a-1],'')) {
928 break;
929 } else {
930 unset($tArr[$a-1]);
931 }
932 }
933 return $tArr;
934 }
935
936 /**
937 * Wraps items in $fArr in table cells/rows, displaying them vertically.
938 *
939 * @param array Array of label/HTML pairs.
940 * @return string HTML table
941 * @access private
942 */
943 function formatCells($fArr) {
944
945 // Traverse the elements in $fArr and wrap them in table cells:
946 $lines=array();
947 foreach($fArr as $l => $c) {
948 $lines[]='
949 <tr>
950 <td nowrap="nowrap">'.htmlspecialchars($l.':').'&nbsp;</td>
951 <td>'.$c.'</td>
952 </tr>';
953 }
954
955 // Add a cell which will set a minimum width:
956 $lines[]='
957 <tr>
958 <td nowrap="nowrap"><img src="clear.gif" width="70" height="1" alt="" /></td>
959 <td></td>
960 </tr>';
961
962 // Wrap in table and return:
963 return '
964 <table border="0" cellpadding="0" cellspacing="0">
965 '.implode('',$lines).'
966 </table>';
967 }
968 }
969
970
971 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/wizard_forms.php'])) {
972 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/wizard_forms.php']);
973 }
974
975
976
977 // Make instance:
978 $SOBE = t3lib_div::makeInstance('SC_wizard_forms');
979 $SOBE->init();
980
981 // Include files?
982 foreach($SOBE->include_once as $INC_FILE) include_once($INC_FILE);
983
984 $SOBE->main();
985 $SOBE->printContent();
986
987 ?>