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