[TASK] Merge submodule workspaces into core
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / Wizard / TableController.php
1 <?php
2 namespace TYPO3\CMS\Backend\Controller\Wizard;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 1999-2013 Kasper Skårhøj (kasperYYYY@typo3.com)
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29
30 use TYPO3\CMS\Backend\Utility\BackendUtility;
31 use TYPO3\CMS\Backend\Utility\IconUtility;
32 use TYPO3\CMS\Core\Utility\GeneralUtility;
33 use TYPO3\CMS\Core\Utility\MathUtility;
34
35 /**
36 * Script Class for rendering the Table Wizard
37 *
38 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
39 */
40 class TableController {
41
42 // Internal, dynamic:
43 /**
44 * document template object
45 *
46 * @var \TYPO3\CMS\Backend\Template\DocumentTemplate
47 * @todo Define visibility
48 */
49 public $doc;
50
51 // Content accumulation for the module.
52 /**
53 * @todo Define visibility
54 */
55 public $content;
56
57 // List of files to include.
58 /**
59 * @todo Define visibility
60 */
61 public $include_once = array();
62
63 // TRUE, then <input> fields are shown, not textareas.
64 /**
65 * @todo Define visibility
66 */
67 public $inputStyle = 0;
68
69 // Internal, static:
70 // If set, the string version of the content is interpreted/written as XML
71 // instead of the original linebased kind. This variable still needs binding
72 // to the wizard parameters - but support is ready!
73 /**
74 * @todo Define visibility
75 */
76 public $xmlStorage = 0;
77
78 // Number of new rows to add in bottom of wizard
79 /**
80 * @todo Define visibility
81 */
82 public $numNewRows = 1;
83
84 // Name of field in parent record which MAY contain the number of columns for the table
85 // - here hardcoded to the value of tt_content. Should be set by TCEform parameters (from P)
86 /**
87 * @todo Define visibility
88 */
89 public $colsFieldName = 'cols';
90
91 // Internal, static: GPvars
92 // Wizard parameters, coming from TCEforms linking to the wizard.
93 /**
94 * @todo Define visibility
95 */
96 public $P;
97
98 // The array which is constantly submitted by the multidimensional form of this wizard.
99 /**
100 * @todo Define visibility
101 */
102 public $TABLECFG;
103
104 // Table parsing
105 // quoting of table cells
106 /**
107 * @todo Define visibility
108 */
109 public $tableParsing_quote;
110
111 // delimiter between table cells
112 /**
113 * @todo Define visibility
114 */
115 public $tableParsing_delimiter;
116
117 /**
118 * Initialization of the class
119 *
120 * @return void
121 * @todo Define visibility
122 */
123 public function init() {
124 // GPvars:
125 $this->P = GeneralUtility::_GP('P');
126 $this->TABLECFG = GeneralUtility::_GP('TABLE');
127 // Setting options:
128 $this->xmlStorage = $this->P['params']['xmlOutput'];
129 $this->numNewRows = MathUtility::forceIntegerInRange($this->P['params']['numNewRows'], 1, 50, 5);
130 // Textareas or input fields:
131 $this->inputStyle = isset($this->TABLECFG['textFields']) ? $this->TABLECFG['textFields'] : 1;
132 // Document template object:
133 $this->doc = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Template\\DocumentTemplate');
134 $this->doc->backPath = $GLOBALS['BACK_PATH'];
135 $this->doc->setModuleTemplate('EXT:backend/Resources/Private/Templates/wizard_table.html');
136 $this->doc->JScode = $this->doc->wrapScriptTags('
137 function jumpToUrl(URL,formEl) { //
138 window.location.href = URL;
139 }
140 ');
141 // Setting form tag:
142 list($rUri) = explode('#', GeneralUtility::getIndpEnv('REQUEST_URI'));
143 $this->doc->form = '<form action="' . htmlspecialchars($rUri) . '" method="post" name="wizardForm">';
144 $this->tableParsing_delimiter = '|';
145 $this->tableParsing_quote = '';
146 }
147
148 /**
149 * Main function, rendering the table wizard
150 *
151 * @return void
152 * @todo Define visibility
153 */
154 public function main() {
155 if ($this->P['table'] && $this->P['field'] && $this->P['uid']) {
156 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('table_title'), $this->tableWizard(), 0, 1);
157 } else {
158 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('table_title'), '<span class="typo3-red">' . $GLOBALS['LANG']->getLL('table_noData', 1) . '</span>', 0, 1);
159 }
160 // Setting up the buttons and markers for docheader
161 $docHeaderButtons = $this->getButtons();
162 $markers['CSH'] = $docHeaderButtons['csh'];
163 $markers['CONTENT'] = $this->content;
164 // Build the <body> for the module
165 $this->content = $this->doc->startPage('Table');
166 $this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
167 $this->content .= $this->doc->endPage();
168 $this->content = $this->doc->insertStylesAndJS($this->content);
169 }
170
171 /**
172 * Outputting the accumulated content to screen
173 *
174 * @return void
175 * @todo Define visibility
176 */
177 public function printContent() {
178 echo $this->content;
179 }
180
181 /**
182 * Create the panel of buttons for submitting the form or otherwise perform operations.
183 *
184 * @return array All available buttons as an assoc. array
185 */
186 protected function getButtons() {
187 $buttons = array(
188 'csh' => '',
189 'csh_buttons' => '',
190 'close' => '',
191 'save' => '',
192 'save_close' => '',
193 'reload' => ''
194 );
195 if ($this->P['table'] && $this->P['field'] && $this->P['uid']) {
196 // CSH
197 $buttons['csh'] = BackendUtility::cshItem('xMOD_csh_corebe', 'wizard_table_wiz', $GLOBALS['BACK_PATH'], '');
198 // CSH Buttons
199 $buttons['csh_buttons'] = BackendUtility::cshItem('xMOD_csh_corebe', 'wizard_table_wiz_buttons', $GLOBALS['BACK_PATH'], '');
200 // Close
201 $buttons['close'] = '<a href="#" onclick="' . htmlspecialchars(('jumpToUrl(unescape(\'' . rawurlencode(GeneralUtility::sanitizeLocalUrl($this->P['returnUrl'])) . '\')); return false;')) . '">' . IconUtility::getSpriteIcon('actions-document-close', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:rm.closeDoc', TRUE))) . '</a>';
202 // Save
203 $buttons['save'] = '<input type="image" class="c-inputButton" name="savedok"' . IconUtility::skinImg($this->doc->backPath, 'gfx/savedok.gif') . ' title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDoc', 1) . '" />';
204 // Save & Close
205 $buttons['save_close'] = '<input type="image" class="c-inputButton" name="saveandclosedok"' . IconUtility::skinImg($this->doc->backPath, 'gfx/saveandclosedok.gif') . ' title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveCloseDoc', 1) . '" />';
206 // Reload
207 $buttons['reload'] = '<input type="image" class="c-inputButton" name="_refresh"' . IconUtility::skinImg($this->doc->backPath, 'gfx/refresh_n.gif') . ' title="' . $GLOBALS['LANG']->getLL('forms_refresh', 1) . '" />';
208 }
209 return $buttons;
210 }
211
212 /**
213 * Draws the table wizard content
214 *
215 * @return string HTML content for the form.
216 * @todo Define visibility
217 */
218 public function tableWizard() {
219 // First, check the references by selecting the record:
220 $row = BackendUtility::getRecord($this->P['table'], $this->P['uid']);
221 if (!is_array($row)) {
222 throw new \RuntimeException('Wizard Error: No reference to record', 1294587125);
223 }
224 // This will get the content of the form configuration code field to us - possibly cleaned up,
225 // saved to database etc. if the form has been submitted in the meantime.
226 $tableCfgArray = $this->getConfigCode($row);
227 // Generation of the Table Wizards HTML code:
228 $content = $this->getTableHTML($tableCfgArray, $row);
229 // Return content:
230 return $content;
231 }
232
233 /***************************
234 *
235 * Helper functions
236 *
237 ***************************/
238 /**
239 * Will get and return the configuration code string
240 * Will also save (and possibly redirect/exit) the content if a save button has been pressed
241 *
242 * @param array $row Current parent record row
243 * @return array Table config code in an array
244 * @access private
245 * @todo Define visibility
246 */
247 public function getConfigCode($row) {
248 // Get delimiter settings
249 $flexForm = GeneralUtility::xml2array($row['pi_flexform']);
250 if (is_array($flexForm)) {
251 $this->tableParsing_quote = $flexForm['data']['s_parsing']['lDEF']['tableparsing_quote']['vDEF'] ? chr(intval($flexForm['data']['s_parsing']['lDEF']['tableparsing_quote']['vDEF'])) : '';
252 $this->tableParsing_delimiter = $flexForm['data']['s_parsing']['lDEF']['tableparsing_delimiter']['vDEF'] ? chr(intval($flexForm['data']['s_parsing']['lDEF']['tableparsing_delimiter']['vDEF'])) : '|';
253 }
254 // If some data has been submitted, then construct
255 if (isset($this->TABLECFG['c'])) {
256 // Process incoming:
257 $this->changeFunc();
258 // Convert to string (either line based or XML):
259 if ($this->xmlStorage) {
260 // Convert the input array to XML:
261 $bodyText = GeneralUtility::array2xml_cs($this->TABLECFG['c'], 'T3TableWizard');
262 // Setting cfgArr directly from the input:
263 $cfgArr = $this->TABLECFG['c'];
264 } else {
265 // Convert the input array to a string of configuration code:
266 $bodyText = $this->cfgArray2CfgString($this->TABLECFG['c']);
267 // Create cfgArr from the string based configuration - that way it is cleaned up and any incompatibilities will be removed!
268 $cfgArr = $this->cfgString2CfgArray($bodyText, $row[$this->colsFieldName]);
269 }
270 // If a save button has been pressed, then save the new field content:
271 if ($_POST['savedok_x'] || $_POST['saveandclosedok_x']) {
272 // Make TCEmain object:
273 $tce = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\DataHandling\\DataHandler');
274 $tce->stripslashes_values = 0;
275 // Put content into the data array:
276 $data = array();
277 $data[$this->P['table']][$this->P['uid']][$this->P['field']] = $bodyText;
278 // Perform the update:
279 $tce->start($data, array());
280 $tce->process_datamap();
281 // If the save/close button was pressed, then redirect the screen:
282 if ($_POST['saveandclosedok_x']) {
283 \TYPO3\CMS\Core\Utility\HttpUtility::redirect(GeneralUtility::sanitizeLocalUrl($this->P['returnUrl']));
284 }
285 }
286 } else {
287 // If nothing has been submitted, load the $bodyText variable from the selected database row:
288 if ($this->xmlStorage) {
289 $cfgArr = GeneralUtility::xml2array($row[$this->P['field']]);
290 } else {
291 // Regular linebased table configuration:
292 $cfgArr = $this->cfgString2CfgArray($row[$this->P['field']], $row[$this->colsFieldName]);
293 }
294 $cfgArr = is_array($cfgArr) ? $cfgArr : array();
295 }
296 return $cfgArr;
297 }
298
299 /**
300 * Creates the HTML for the Table Wizard:
301 *
302 * @param array $cfgArr Table config array
303 * @param array $row Current parent record array
304 * @return string HTML for the table wizard
305 * @access private
306 * @todo Define visibility
307 */
308 public function getTableHTML($cfgArr, $row) {
309 // Traverse the rows:
310 $tRows = array();
311 $k = 0;
312 $countLines = count($cfgArr);
313 foreach ($cfgArr as $cellArr) {
314 if (is_array($cellArr)) {
315 // Initialize:
316 $cells = array();
317 $a = 0;
318 // Traverse the columns:
319 foreach ($cellArr as $cellContent) {
320 if ($this->inputStyle) {
321 $cells[] = '<input type="text"' . $this->doc->formWidth(20) . ' name="TABLE[c][' . ($k + 1) * 2 . '][' . ($a + 1) * 2 . ']" value="' . htmlspecialchars($cellContent) . '" />';
322 } else {
323 $cellContent = preg_replace('/<br[ ]?[\\/]?>/i', LF, $cellContent);
324 $cells[] = '<textarea ' . $this->doc->formWidth(20) . ' rows="5" name="TABLE[c][' . ($k + 1) * 2 . '][' . ($a + 1) * 2 . ']">' . GeneralUtility::formatForTextarea($cellContent) . '</textarea>';
325 }
326 // Increment counter:
327 $a++;
328 }
329 // CTRL panel for a table row (move up/down/around):
330 $onClick = 'document.wizardForm.action+=\'#ANC_' . (($k + 1) * 2 - 2) . '\';';
331 $onClick = ' onclick="' . htmlspecialchars($onClick) . '"';
332 $ctrl = '';
333 $brTag = $this->inputStyle ? '' : '<br />';
334 if ($k != 0) {
335 $ctrl .= '<input type="image" name="TABLE[row_up][' . ($k + 1) * 2 . ']"' . IconUtility::skinImg($this->doc->backPath, 'gfx/pil2up.gif', '') . $onClick . ' title="' . $GLOBALS['LANG']->getLL('table_up', 1) . '" />' . $brTag;
336 } else {
337 $ctrl .= '<input type="image" name="TABLE[row_bottom][' . ($k + 1) * 2 . ']"' . IconUtility::skinImg($this->doc->backPath, 'gfx/turn_up.gif', '') . $onClick . ' title="' . $GLOBALS['LANG']->getLL('table_bottom', 1) . '" />' . $brTag;
338 }
339 $ctrl .= '<input type="image" name="TABLE[row_remove][' . ($k + 1) * 2 . ']"' . IconUtility::skinImg($this->doc->backPath, 'gfx/garbage.gif', '') . $onClick . ' title="' . $GLOBALS['LANG']->getLL('table_removeRow', 1) . '" />' . $brTag;
340 if ($k + 1 != $countLines) {
341 $ctrl .= '<input type="image" name="TABLE[row_down][' . ($k + 1) * 2 . ']"' . IconUtility::skinImg($this->doc->backPath, 'gfx/pil2down.gif', '') . $onClick . ' title="' . $GLOBALS['LANG']->getLL('table_down', 1) . '" />' . $brTag;
342 } else {
343 $ctrl .= '<input type="image" name="TABLE[row_top][' . ($k + 1) * 2 . ']"' . IconUtility::skinImg($this->doc->backPath, 'gfx/turn_down.gif', '') . $onClick . ' title="' . $GLOBALS['LANG']->getLL('table_top', 1) . '" />' . $brTag;
344 }
345 $ctrl .= '<input type="image" name="TABLE[row_add][' . ($k + 1) * 2 . ']"' . IconUtility::skinImg($this->doc->backPath, 'gfx/add.gif', '') . $onClick . ' title="' . $GLOBALS['LANG']->getLL('table_addRow', 1) . '" />' . $brTag;
346 $tRows[] = '
347 <tr class="bgColor4">
348 <td class="bgColor5"><a name="ANC_' . ($k + 1) * 2 . '"></a><span class="c-wizButtonsV">' . $ctrl . '</span></td>
349 <td>' . implode('</td>
350 <td>', $cells) . '</td>
351 </tr>';
352 // Increment counter:
353 $k++;
354 }
355 }
356 // CTRL panel for a table column (move left/right/around/delete)
357 $cells = array();
358 $cells[] = '';
359 // Finding first row:
360 $firstRow = reset($cfgArr);
361 if (is_array($firstRow)) {
362 // Init:
363 $a = 0;
364 $cols = count($firstRow);
365 // Traverse first row:
366 foreach ($firstRow as $temp) {
367 $ctrl = '';
368 if ($a != 0) {
369 $ctrl .= '<input type="image" name="TABLE[col_left][' . ($a + 1) * 2 . ']"' . IconUtility::skinImg($this->doc->backPath, 'gfx/pil2left.gif', '') . ' title="' . $GLOBALS['LANG']->getLL('table_left', 1) . '" />';
370 } else {
371 $ctrl .= '<input type="image" name="TABLE[col_end][' . ($a + 1) * 2 . ']"' . IconUtility::skinImg($this->doc->backPath, 'gfx/turn_left.gif', '') . ' title="' . $GLOBALS['LANG']->getLL('table_end', 1) . '" />';
372 }
373 $ctrl .= '<input type="image" name="TABLE[col_remove][' . ($a + 1) * 2 . ']"' . IconUtility::skinImg($this->doc->backPath, 'gfx/garbage.gif', '') . ' title="' . $GLOBALS['LANG']->getLL('table_removeColumn', 1) . '" />';
374 if ($a + 1 != $cols) {
375 $ctrl .= '<input type="image" name="TABLE[col_right][' . ($a + 1) * 2 . ']"' . IconUtility::skinImg($this->doc->backPath, 'gfx/pil2right.gif', '') . ' title="' . $GLOBALS['LANG']->getLL('table_right', 1) . '" />';
376 } else {
377 $ctrl .= '<input type="image" name="TABLE[col_start][' . ($a + 1) * 2 . ']"' . IconUtility::skinImg($this->doc->backPath, 'gfx/turn_right.gif', '') . ' title="' . $GLOBALS['LANG']->getLL('table_start', 1) . '" />';
378 }
379 $ctrl .= '<input type="image" name="TABLE[col_add][' . ($a + 1) * 2 . ']"' . IconUtility::skinImg($this->doc->backPath, 'gfx/add.gif', '') . ' title="' . $GLOBALS['LANG']->getLL('table_addColumn', 1) . '" />';
380 $cells[] = '<span class="c-wizButtonsH">' . $ctrl . '</span>';
381 // Incr. counter:
382 $a++;
383 }
384 $tRows[] = '
385 <tr class="bgColor5">
386 <td align="center">' . implode('</td>
387 <td align="center">', $cells) . '</td>
388 </tr>';
389 }
390 $content = '';
391 // Implode all table rows into a string, wrapped in table tags.
392 $content .= '
393
394
395 <!--
396 Table wizard
397 -->
398 <table border="0" cellpadding="0" cellspacing="1" id="typo3-tablewizard">
399 ' . implode('', $tRows) . '
400 </table>';
401 // Input type checkbox:
402 $content .= '
403
404 <!--
405 Input mode check box:
406 -->
407 <div id="c-inputMode">
408 ' . '<input type="hidden" name="TABLE[textFields]" value="0" />' . '<input type="checkbox" name="TABLE[textFields]" id="textFields" value="1"' . ($this->inputStyle ? ' checked="checked"' : '') . ' /> <label for="textFields">' . $GLOBALS['LANG']->getLL('table_smallFields') . '</label>
409 </div>
410
411 <br /><br />
412 ';
413 // Return content:
414 return $content;
415 }
416
417 /**
418 * Detects if a control button (up/down/around/delete) has been pressed for an item and accordingly it will manipulate the internal TABLECFG array
419 *
420 * @return void
421 * @access private
422 * @todo Define visibility
423 */
424 public function changeFunc() {
425 if ($this->TABLECFG['col_remove']) {
426 $kk = key($this->TABLECFG['col_remove']);
427 $cmd = 'col_remove';
428 } elseif ($this->TABLECFG['col_add']) {
429 $kk = key($this->TABLECFG['col_add']);
430 $cmd = 'col_add';
431 } elseif ($this->TABLECFG['col_start']) {
432 $kk = key($this->TABLECFG['col_start']);
433 $cmd = 'col_start';
434 } elseif ($this->TABLECFG['col_end']) {
435 $kk = key($this->TABLECFG['col_end']);
436 $cmd = 'col_end';
437 } elseif ($this->TABLECFG['col_left']) {
438 $kk = key($this->TABLECFG['col_left']);
439 $cmd = 'col_left';
440 } elseif ($this->TABLECFG['col_right']) {
441 $kk = key($this->TABLECFG['col_right']);
442 $cmd = 'col_right';
443 } elseif ($this->TABLECFG['row_remove']) {
444 $kk = key($this->TABLECFG['row_remove']);
445 $cmd = 'row_remove';
446 } elseif ($this->TABLECFG['row_add']) {
447 $kk = key($this->TABLECFG['row_add']);
448 $cmd = 'row_add';
449 } elseif ($this->TABLECFG['row_top']) {
450 $kk = key($this->TABLECFG['row_top']);
451 $cmd = 'row_top';
452 } elseif ($this->TABLECFG['row_bottom']) {
453 $kk = key($this->TABLECFG['row_bottom']);
454 $cmd = 'row_bottom';
455 } elseif ($this->TABLECFG['row_up']) {
456 $kk = key($this->TABLECFG['row_up']);
457 $cmd = 'row_up';
458 } elseif ($this->TABLECFG['row_down']) {
459 $kk = key($this->TABLECFG['row_down']);
460 $cmd = 'row_down';
461 }
462 if ($cmd && MathUtility::canBeInterpretedAsInteger($kk)) {
463 if (substr($cmd, 0, 4) == 'row_') {
464 switch ($cmd) {
465 case 'row_remove':
466 unset($this->TABLECFG['c'][$kk]);
467 break;
468 case 'row_add':
469 for ($a = 1; $a <= $this->numNewRows; $a++) {
470 // Checking if set: The point is that any new row inbetween existing rows
471 // will be TRUE after one row is added while if rows are added in the bottom
472 // of the table there will be no existing rows to stop the addition of new rows
473 // which means it will add up to $this->numNewRows rows then.
474 if (!isset($this->TABLECFG['c'][($kk + $a)])) {
475 $this->TABLECFG['c'][$kk + $a] = array();
476 } else {
477 break;
478 }
479 }
480 break;
481 case 'row_top':
482 $this->TABLECFG['c'][1] = $this->TABLECFG['c'][$kk];
483 unset($this->TABLECFG['c'][$kk]);
484 break;
485 case 'row_bottom':
486 $this->TABLECFG['c'][10000000] = $this->TABLECFG['c'][$kk];
487 unset($this->TABLECFG['c'][$kk]);
488 break;
489 case 'row_up':
490 $this->TABLECFG['c'][$kk - 3] = $this->TABLECFG['c'][$kk];
491 unset($this->TABLECFG['c'][$kk]);
492 break;
493 case 'row_down':
494 $this->TABLECFG['c'][$kk + 3] = $this->TABLECFG['c'][$kk];
495 unset($this->TABLECFG['c'][$kk]);
496 break;
497 }
498 ksort($this->TABLECFG['c']);
499 }
500 if (substr($cmd, 0, 4) == 'col_') {
501 foreach ($this->TABLECFG['c'] as $cAK => $value) {
502 switch ($cmd) {
503 case 'col_remove':
504 unset($this->TABLECFG['c'][$cAK][$kk]);
505 break;
506 case 'col_add':
507 $this->TABLECFG['c'][$cAK][$kk + 1] = '';
508 break;
509 case 'col_start':
510 $this->TABLECFG['c'][$cAK][1] = $this->TABLECFG['c'][$cAK][$kk];
511 unset($this->TABLECFG['c'][$cAK][$kk]);
512 break;
513 case 'col_end':
514 $this->TABLECFG['c'][$cAK][1000000] = $this->TABLECFG['c'][$cAK][$kk];
515 unset($this->TABLECFG['c'][$cAK][$kk]);
516 break;
517 case 'col_left':
518 $this->TABLECFG['c'][$cAK][$kk - 3] = $this->TABLECFG['c'][$cAK][$kk];
519 unset($this->TABLECFG['c'][$cAK][$kk]);
520 break;
521 case 'col_right':
522 $this->TABLECFG['c'][$cAK][$kk + 3] = $this->TABLECFG['c'][$cAK][$kk];
523 unset($this->TABLECFG['c'][$cAK][$kk]);
524 break;
525 }
526 ksort($this->TABLECFG['c'][$cAK]);
527 }
528 }
529 }
530 // Convert line breaks to <br /> tags:
531 foreach ($this->TABLECFG['c'] as $a => $value) {
532 foreach ($this->TABLECFG['c'][$a] as $b => $value2) {
533 $this->TABLECFG['c'][$a][$b] = str_replace(LF, '<br />', str_replace(CR, '', $this->TABLECFG['c'][$a][$b]));
534 }
535 }
536 }
537
538 /**
539 * Converts the input array to a configuration code string
540 *
541 * @param array $cfgArr Array of table configuration (follows the input structure from the table wizard POST form)
542 * @return string The array converted into a string with line-based configuration.
543 * @see cfgString2CfgArray()
544 * @todo Define visibility
545 */
546 public function cfgArray2CfgString($cfgArr) {
547 // Initialize:
548 $inLines = array();
549 // Traverse the elements of the table wizard and transform the settings into configuration code.
550 foreach ($this->TABLECFG['c'] as $a => $value) {
551 $thisLine = array();
552 foreach ($this->TABLECFG['c'][$a] as $b => $value) {
553 $thisLine[] = $this->tableParsing_quote . str_replace($this->tableParsing_delimiter, '', $this->TABLECFG['c'][$a][$b]) . $this->tableParsing_quote;
554 }
555 $inLines[] = implode($this->tableParsing_delimiter, $thisLine);
556 }
557 // Finally, implode the lines into a string:
558 $bodyText = implode(LF, $inLines);
559 // Return the configuration code:
560 return $bodyText;
561 }
562
563 /**
564 * Converts the input configuration code string into an array
565 *
566 * @param string $cfgStr Configuration code
567 * @param integer $cols Default number of columns
568 * @return array Configuration array
569 * @see cfgArray2CfgString()
570 * @todo Define visibility
571 */
572 public function cfgString2CfgArray($cfgStr, $cols) {
573 // Explode lines in the configuration code - each line is a table row.
574 $tLines = explode(LF, $cfgStr);
575 // Setting number of columns
576 // auto...
577 if (!$cols && trim($tLines[0])) {
578 $cols = count(explode($this->tableParsing_delimiter, $tLines[0]));
579 }
580 $cols = $cols ? $cols : 4;
581 // Traverse the number of table elements:
582 $cfgArr = array();
583 foreach ($tLines as $k => $v) {
584 // Initialize:
585 $vParts = explode($this->tableParsing_delimiter, $v);
586 // Traverse columns:
587 for ($a = 0; $a < $cols; $a++) {
588 if ($this->tableParsing_quote && substr($vParts[$a], 0, 1) == $this->tableParsing_quote && substr($vParts[$a], -1, 1) == $this->tableParsing_quote) {
589 $vParts[$a] = substr(trim($vParts[$a]), 1, -1);
590 }
591 $cfgArr[$k][$a] = $vParts[$a];
592 }
593 }
594 // Return configuration array:
595 return $cfgArr;
596 }
597
598 }
599
600 ?>