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