2 declare(strict_types = 1);
18 use Psr\Http\Message\ResponseInterface;
19 use Psr\Http\Message\ServerRequestInterface;
48 'content' =>
'Using $content of class TableController from the outside is discouraged, as this variable is only used for internal storage.',
49 'inputStyle' =>
'Using $inputStyle of class TableController from the outside is discouraged, as this variable is only used for internal storage.',
50 'xmlStorage' =>
'Using $xmlStorage of class TableController from the outside is discouraged, as this variable is only used for internal storage.',
51 'numNewRows' =>
'Using $numNewRows of class TableController from the outside is discouraged, as this variable is only used for internal storage.',
52 'colsFieldName' =>
'Using $colsFieldName of class TableController from the outside is discouraged, as this variable is only used for internal storage.',
53 'P' =>
'Using $P of class TableController from the outside is discouraged, as this variable is only used for internal storage.',
54 'TABLECFG' =>
'Using $TABLECFG of class TableController from the outside is discouraged, as this variable is only used for internal storage.',
55 'tableParsing_quote' =>
'Using $tableParsing_quote of class TableController from the outside is discouraged, as this variable is only used for internal storage.',
56 'tableParsing_delimiter' =>
'Using $tableParsing_delimiter of class TableController from the outside is discouraged, as this variable is only used for internal storage.',
143 $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
157 public function mainAction(ServerRequestInterface $request): ResponseInterface
161 if (empty($response)) {
162 $response =
new HtmlResponse($this->moduleTemplate->renderContent());
173 public function main()
175 trigger_error(
'TableController->main() will be replaced by protected method renderContent() in TYPO3 v10.0. Do not call from other extensions.', E_USER_DEPRECATED);
194 trigger_error(
'TableController->tableWizard() will be replaced by protected method renderTableWizard() in TYPO3 v10.0. Do not call from other extensions.', E_USER_DEPRECATED);
216 trigger_error(
'TableController->getConfigCode() will be replaced by protected method getConfiguration() in TYPO3 v10.0. Do not call from other extensions.', E_USER_DEPRECATED);
238 trigger_error(
'TableController->getTableHTML() will be replaced by protected method getTableWizard() in TYPO3 v10.0. Do not call from other extensions.', E_USER_DEPRECATED);
252 trigger_error(
'TableController->changeFunc() will be replaced by protected method manipulateTable() in TYPO3 v10.0. Do not call from other extensions.', E_USER_DEPRECATED);
267 trigger_error(
'TableController->cfgArray2CfgString() will be replaced by protected method configurationArrayToString() in TYPO3 v10.0. Do not call from other extensions.', E_USER_DEPRECATED);
283 trigger_error(
'TableController->cfgString2CfgArray() will be replaced by protected method configurationStringToArray() in TYPO3 v10.0. Do not call from other extensions.', E_USER_DEPRECATED);
292 protected function init(ServerRequestInterface $request): void
294 $parsedBody = $request->getParsedBody();
295 $queryParams = $request->getQueryParams();
297 $this->P = $parsedBody[
'P'] ?? $queryParams[
'P'] ??
null;
298 $this->TABLECFG = $parsedBody[
'TABLE'] ?? $queryParams[
'TABLE'] ??
null;
300 $this->xmlStorage = $this->P[
'params'][
'xmlOutput'];
303 $this->inputStyle = isset($this->TABLECFG[
'textFields']) ? (bool)$this->TABLECFG[
'textFields'] :
true;
304 $this->tableParsing_delimiter =
'|';
305 $this->tableParsing_quote =
'';
314 protected function renderContent(ServerRequestInterface $request): ?ResponseInterface
316 $normalizedParams = $request->getAttribute(
'normalizedParams');
317 $requestUri = $normalizedParams->getRequestUri();
318 list($rUri) = explode(
'#', $requestUri);
319 $this->content .=
'<form action="' . htmlspecialchars($rUri) .
'" method="post" id="TableController" name="wizardForm">';
320 if ($this->P[
'table'] && $this->P[
'field'] && $this->P[
'uid']) {
327 $this->content .=
'<h2>' . htmlspecialchars($this->
getLanguageService()->getLL(
'table_title')) .
'</h2>'
328 .
'<div>' . $tableWizard .
'</div>';
330 $this->content .=
'<h2>' . htmlspecialchars($this->
getLanguageService()->getLL(
'table_title')) .
'</h2>'
331 .
'<div><span class="text-danger">' . htmlspecialchars($this->
getLanguageService()->getLL(
'table_noData')) .
'</span></div>';
333 $this->content .=
'</form>';
337 $this->moduleTemplate->setContent($this->content);
347 $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
348 if ($this->P[
'table'] && $this->P[
'field'] && $this->P[
'uid']) {
350 $cshButton = $buttonBar->makeHelpButton()
351 ->setModuleName(
'xMOD_csh_corebe')
352 ->setFieldName(
'wizard_table_wiz');
353 $buttonBar->addButton($cshButton);
355 $closeButton = $buttonBar->makeLinkButton()
356 ->setHref($this->P[
'returnUrl'])
357 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-close',
Icon::SIZE_SMALL))
358 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.closeDoc'))
359 ->setShowLabelText(
true);
362 $saveButton = $buttonBar->makeInputButton()
363 ->setName(
'_savedok')
365 ->setForm(
'TableController')
366 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-document-save',
Icon::SIZE_SMALL))
367 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.saveDoc'))
368 ->setShowLabelText(
true);
371 $reloadButton = $buttonBar->makeInputButton()
372 ->setName(
'_refresh')
374 ->setForm(
'TableController')
375 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-refresh',
Icon::SIZE_SMALL))
391 throw new \RuntimeException(
'Wizard Error: No access', 1349692692);
395 if (!is_array($row)) {
396 throw new \RuntimeException(
'Wizard Error: No reference to record', 1294587125);
402 if ($tableCfgArray instanceof ResponseInterface) {
403 return $tableCfgArray;
420 protected function getConfiguration(array $row, ServerRequestInterface $request)
423 $this->tableParsing_quote = $row[
'table_enclosure'] ? chr((
int)$row[
'table_enclosure']) :
'';
424 $this->tableParsing_delimiter = $row[
'table_delimiter'] ? chr((
int)$row[
'table_delimiter']) :
'|';
426 if (isset($this->TABLECFG[
'c'])) {
430 if ($this->xmlStorage) {
432 $bodyText =
'<?xml version="1.0" encoding="utf-8" standalone="yes" ?>' . LF . GeneralUtility::array2xml($this->TABLECFG[
'c'],
'', 0,
'T3TableWizard');
434 $configuration = $this->TABLECFG[
'c'];
443 if ($_POST[
'_savedok'] || $_POST[
'_saveandclosedok']) {
446 $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
449 if ($this->P[
'flexFormPath']) {
451 $currentFlexFormData = GeneralUtility::xml2array($row[$this->P[
'field']]);
453 $flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
454 $flexFormTools->setArrayValueByPath($this->P[
'flexFormPath'], $currentFlexFormData, $bodyText);
455 $data[$this->P[
'table']][$this->P[
'uid']][$this->P[
'field']] = $currentFlexFormData;
457 $data[$this->P[
'table']][$this->P[
'uid']][$this->P[
'field']] = $bodyText;
460 $dataHandler->start($data, []);
461 $dataHandler->process_datamap();
463 if ($_POST[
'_saveandclosedok']) {
464 return new RedirectResponse(GeneralUtility::sanitizeLocalUrl($this->P[
'returnUrl']));
469 if ($this->xmlStorage) {
470 $configuration = GeneralUtility::xml2array($row[$this->P[
'field']]);
472 if ($this->P[
'flexFormPath']) {
474 $currentFlexFormData = GeneralUtility::xml2array($row[$this->P[
'field']]);
476 $flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
477 $configuration = $flexFormTools->getArrayValueByPath(
478 $this->P[
'flexFormPath'],
488 $configuration = is_array($configuration) ? $configuration : [];
490 return $configuration;
504 $countLines = count($configuration);
505 foreach ($configuration as $cellArr) {
506 if (is_array($cellArr)) {
511 foreach ($cellArr as $cellContent) {
512 if ($this->inputStyle) {
513 $cells[] =
'<input class="form-control" type="text" name="TABLE[c][' . ($k + 1) * 2 .
'][' . ($a + 1) * 2 .
']" value="' . htmlspecialchars($cellContent) .
'" />';
515 $cellContent = preg_replace(
'/<br[ ]?[\\/]?>/i', LF, $cellContent);
516 $cells[] =
'<textarea class="form-control" rows="6" name="TABLE[c][' . ($k + 1) * 2 .
'][' . ($a + 1) * 2 .
']">' . htmlspecialchars($cellContent) .
'</textarea>';
522 $onClick =
'document.wizardForm.action+=' . GeneralUtility::quoteJSvalue(
'#ANC_' . (($k + 1) * 2 - 2)) .
';';
523 $onClick =
' onclick="' . htmlspecialchars($onClick) .
'"';
526 $ctrl .=
'<button class="btn btn-default" name="TABLE[row_up][' . ($k + 1) * 2 .
']" title="' . htmlspecialchars($this->
getLanguageService()->
getLL(
'table_up')) .
'"' . $onClick .
'><span class="t3-icon fa fa-fw fa-angle-up"></span></button>';
528 $ctrl .=
'<button class="btn btn-default" name="TABLE[row_bottom][' . ($k + 1) * 2 .
']" title="' . htmlspecialchars($this->
getLanguageService()->
getLL(
'table_bottom')) .
'"' . $onClick .
'><span class="t3-icon fa fa-fw fa-angle-double-down"></span></button>';
530 if ($k + 1 !== $countLines) {
531 $ctrl .=
'<button class="btn btn-default" name="TABLE[row_down][' . ($k + 1) * 2 .
']" title="' . htmlspecialchars($this->
getLanguageService()->
getLL(
'table_down')) .
'"' . $onClick .
'><span class="t3-icon fa fa-fw fa-angle-down"></span></button>';
533 $ctrl .=
'<button class="btn btn-default" name="TABLE[row_top][' . ($k + 1) * 2 .
']" title="' . htmlspecialchars($this->
getLanguageService()->
getLL(
'table_top')) .
'"' . $onClick .
'><span class="t3-icon fa fa-fw fa-angle-double-up"></span></button>';
535 $ctrl .=
'<button class="btn btn-default" name="TABLE[row_remove][' . ($k + 1) * 2 .
']" title="' . htmlspecialchars($this->
getLanguageService()->
getLL(
'table_removeRow')) .
'"' . $onClick .
'><span class="t3-icon fa fa-fw fa-trash"></span></button>';
536 $ctrl .=
'<button class="btn btn-default" name="TABLE[row_add][' . ($k + 1) * 2 .
']" title="' . htmlspecialchars($this->
getLanguageService()->
getLL(
'table_addRow')) .
'"' . $onClick .
'><span class="t3-icon fa fa-fw fa-plus"></span></button>';
540 <a name="ANC_' . ($k + 1) * 2 .
'"></a>
541 <span class="btn-group' . ($this->inputStyle ?
'' :
'-vertical') .
'">' . $ctrl .
'</span>
543 <td>' . implode(
'</td>
544 <td>', $cells) .
'</td>
554 $firstRow = reset($configuration);
555 if (is_array($firstRow)) {
556 $cols = count($firstRow);
557 for ($a = 1; $a <= $cols; $a++) {
561 $ctrl .=
'<button class="btn btn-default" name="TABLE[col_left][' . $b .
']" title="' . htmlspecialchars($this->
getLanguageService()->getLL(
'table_left')) .
'"><span class="t3-icon fa fa-fw fa-angle-left"></span></button>';
563 $ctrl .=
'<button class="btn btn-default" name="TABLE[col_end][' . $b .
']" title="' . htmlspecialchars($this->
getLanguageService()->getLL(
'table_end')) .
'"><span class="t3-icon fa fa-fw fa-angle-double-right"></span></button>';
566 $ctrl .=
'<button class="btn btn-default" name="TABLE[col_right][' . $b .
']" title="' . htmlspecialchars($this->
getLanguageService()->getLL(
'table_right')) .
'"><span class="t3-icon fa fa-fw fa-angle-right"></span></button>';
568 $ctrl .=
'<button class="btn btn-default" name="TABLE[col_start][' . $b .
']" title="' . htmlspecialchars($this->
getLanguageService()->getLL(
'table_start')) .
'"><span class="t3-icon fa fa-fw fa-angle-double-left"></span></button>';
570 $ctrl .=
'<button class="btn btn-default" name="TABLE[col_remove][' . $b .
']" title="' . htmlspecialchars($this->
getLanguageService()->getLL(
'table_removeColumn')) .
'"><span class="t3-icon fa fa-fw fa-trash"></span></button>';
571 $ctrl .=
'<button class="btn btn-default" name="TABLE[col_add][' . $b .
']" title="' . htmlspecialchars($this->
getLanguageService()->getLL(
'table_addColumn')) .
'"><span class="t3-icon fa fa-fw fa-plus"></span></button>';
572 $cells[] =
'<span class="btn-group">' . $ctrl .
'</span>';
577 <td>' . implode(
'</td>
578 <td>', $cells) .
'</td>
583 $addSubmitOnClick =
'onclick="document.getElementById(\'TableController\').submit();"';
587 <!-- Table wizard -->
588 <div class="table-fit table-fit-inline-block">
589 <table id="typo3-tablewizard" class="table table-center">
590 ' . implode(
'', $tRows) .
'
596 <!-- Input mode check box: -->
597 <div class="checkbox">
598 <input type="hidden" name="TABLE[textFields]" value="0" />
599 <label for="textFields">
600 <input type="checkbox" ' . $addSubmitOnClick .
' name="TABLE[textFields]" id="textFields" value="1"' . ($this->inputStyle ?
' checked="checked"' :
'') .
' />
613 if ($this->TABLECFG[
'col_remove']) {
614 $kk = key($this->TABLECFG[
'col_remove']);
616 } elseif ($this->TABLECFG[
'col_add']) {
617 $kk = key($this->TABLECFG[
'col_add']);
619 } elseif ($this->TABLECFG[
'col_start']) {
620 $kk = key($this->TABLECFG[
'col_start']);
622 } elseif ($this->TABLECFG[
'col_end']) {
623 $kk = key($this->TABLECFG[
'col_end']);
625 } elseif ($this->TABLECFG[
'col_left']) {
626 $kk = key($this->TABLECFG[
'col_left']);
628 } elseif ($this->TABLECFG[
'col_right']) {
629 $kk = key($this->TABLECFG[
'col_right']);
631 } elseif ($this->TABLECFG[
'row_remove']) {
632 $kk = key($this->TABLECFG[
'row_remove']);
634 } elseif ($this->TABLECFG[
'row_add']) {
635 $kk = key($this->TABLECFG[
'row_add']);
637 } elseif ($this->TABLECFG[
'row_top']) {
638 $kk = key($this->TABLECFG[
'row_top']);
640 } elseif ($this->TABLECFG[
'row_bottom']) {
641 $kk = key($this->TABLECFG[
'row_bottom']);
643 } elseif ($this->TABLECFG[
'row_up']) {
644 $kk = key($this->TABLECFG[
'row_up']);
646 } elseif ($this->TABLECFG[
'row_down']) {
647 $kk = key($this->TABLECFG[
'row_down']);
654 if (strpos($cmd,
'row_') === 0) {
657 unset($this->TABLECFG[
'c'][$kk]);
665 if (!isset($this->TABLECFG[
'c'][$kk + $a])) {
666 $this->TABLECFG[
'c'][$kk + $a] = [];
673 $this->TABLECFG[
'c'][1] = $this->TABLECFG[
'c'][$kk];
674 unset($this->TABLECFG[
'c'][$kk]);
677 $this->TABLECFG[
'c'][10000000] = $this->TABLECFG[
'c'][$kk];
678 unset($this->TABLECFG[
'c'][$kk]);
681 $this->TABLECFG[
'c'][$kk - 3] = $this->TABLECFG[
'c'][$kk];
682 unset($this->TABLECFG[
'c'][$kk]);
685 $this->TABLECFG[
'c'][$kk + 3] = $this->TABLECFG[
'c'][$kk];
686 unset($this->TABLECFG[
'c'][$kk]);
689 ksort($this->TABLECFG[
'c']);
691 if (strpos($cmd,
'col_') === 0) {
692 foreach ($this->TABLECFG[
'c'] as $cAK => $value) {
695 unset($this->TABLECFG[
'c'][$cAK][$kk]);
698 $this->TABLECFG[
'c'][$cAK][$kk + 1] =
'';
701 $this->TABLECFG[
'c'][$cAK][1] = $this->TABLECFG[
'c'][$cAK][$kk];
702 unset($this->TABLECFG[
'c'][$cAK][$kk]);
705 $this->TABLECFG[
'c'][$cAK][1000000] = $this->TABLECFG[
'c'][$cAK][$kk];
706 unset($this->TABLECFG[
'c'][$cAK][$kk]);
709 $this->TABLECFG[
'c'][$cAK][$kk - 3] = $this->TABLECFG[
'c'][$cAK][$kk];
710 unset($this->TABLECFG[
'c'][$cAK][$kk]);
713 $this->TABLECFG[
'c'][$cAK][$kk + 3] = $this->TABLECFG[
'c'][$cAK][$kk];
714 unset($this->TABLECFG[
'c'][$cAK][$kk]);
717 ksort($this->TABLECFG[
'c'][$cAK]);
722 foreach ($this->TABLECFG[
'c'] as $a => $value) {
723 foreach ($this->TABLECFG[
'c'][$a] as $b => $value2) {
724 $this->TABLECFG[
'c'][$a][$b] = str_replace(
727 $this->TABLECFG[
'c'][$a][$b]
744 foreach ($cfgArr as $valueA) {
746 foreach ($valueA as $valueB) {
747 $thisLine[] = $this->tableParsing_quote
750 $inLines[] = implode($this->tableParsing_delimiter, $thisLine);
753 return implode(LF, $inLines);
767 $tableLines = explode(LF, $configurationCode);
770 if (!$columns && trim($tableLines[0])) {
771 $columns = count(explode($this->tableParsing_delimiter, $tableLines[0]));
773 $columns = $columns ?: 4;
775 $configurationArray = [];
776 foreach ($tableLines as $key => $value) {
778 $valueParts = explode($this->tableParsing_delimiter, $value);
780 for ($a = 0; $a < $columns; $a++) {
781 if ($this->tableParsing_quote
782 && $valueParts[$a][0] === $this->tableParsing_quote
783 && substr($valueParts[$a], -1, 1) === $this->tableParsing_quote
785 $valueParts[$a] = substr(trim($valueParts[$a]), 1, -1);
787 $configurationArray[$key][$a] = (string)$valueParts[$a];
790 return $configurationArray;