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