Initial commit
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Compatibility6\Form\Container;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Backend\Form\Container\AbstractContainer;
|
||||
use TYPO3\CMS\Core\Imaging\Icon;
|
||||
use TYPO3\CMS\Core\Imaging\IconFactory;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Lang\LanguageService;
|
||||
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
|
||||
use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation;
|
||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||
|
||||
/**
|
||||
* The container handles single elements.
|
||||
*
|
||||
* This one is called by FlexFormTabsContainer, FlexFormNoTabsContainer or FlexFormContainerContainer.
|
||||
* For single fields, the code is similar to SingleFieldContainer, processing will end up in single
|
||||
* element classes depending on specific type of an element. Additionally, it determines if a
|
||||
* section is handled and hands over to FlexFormSectionContainer in this case.
|
||||
*/
|
||||
class FlexFormElementContainer extends AbstractContainer
|
||||
{
|
||||
/**
|
||||
* Entry method
|
||||
*
|
||||
* @return array As defined in initializeResultArray() of AbstractNode
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$table = $this->data['tableName'];
|
||||
$row = $this->data['databaseRow'];
|
||||
$flexFormDataStructureArray = $this->data['flexFormDataStructureArray'];
|
||||
$flexFormRowData = $this->data['flexFormRowData'];
|
||||
$flexFormFormPrefix = $this->data['flexFormFormPrefix'];
|
||||
$parameterArray = $this->data['parameterArray'];
|
||||
$metaData = $this->data['parameterArray']['fieldConf']['config']['ds']['meta'];
|
||||
|
||||
$languageService = $this->getLanguageService();
|
||||
/** @var IconFactory $iconFactory */
|
||||
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
|
||||
$resultArray = $this->initializeResultArray();
|
||||
foreach ($flexFormDataStructureArray as $flexFormFieldName => $flexFormFieldArray) {
|
||||
if (
|
||||
// No item array found at all
|
||||
!is_array($flexFormFieldArray)
|
||||
// Not a section or container and not a list of single items
|
||||
|| (!isset($flexFormFieldArray['type']) && !is_array($flexFormFieldArray['config']))
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($flexFormFieldArray['type'] === 'array') {
|
||||
// Section
|
||||
if (empty($flexFormFieldArray['section'])) {
|
||||
$resultArray['html'] = LF . 'Section expected at ' . $flexFormFieldName . ' but not found';
|
||||
continue;
|
||||
}
|
||||
|
||||
$sectionTitle = '';
|
||||
if (!empty($flexFormFieldArray['title'])) {
|
||||
$sectionTitle = $languageService->sL($flexFormFieldArray['title']);
|
||||
}
|
||||
|
||||
$options = $this->data;
|
||||
$options['flexFormDataStructureArray'] = $flexFormFieldArray['el'];
|
||||
$options['flexFormRowData'] = is_array($flexFormRowData[$flexFormFieldName]['el']) ? $flexFormRowData[$flexFormFieldName]['el'] : array();
|
||||
$options['flexFormSectionType'] = $flexFormFieldName;
|
||||
$options['flexFormSectionTitle'] = $sectionTitle;
|
||||
$options['renderType'] = 'flexFormSectionContainer';
|
||||
$sectionContainerResult = $this->nodeFactory->create($options)->render();
|
||||
$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $sectionContainerResult);
|
||||
} else {
|
||||
if (is_array($metaData) && isset($metaData['langChildren']) && isset($metaData['languagesOnElement'])) {
|
||||
$lkeys = $metaData['languagesOnElement'];
|
||||
array_walk($lkeys, function (&$value) {
|
||||
$value = 'v' . $value;
|
||||
});
|
||||
} else {
|
||||
$lkeys = array('vDEF');
|
||||
}
|
||||
$html = array();
|
||||
foreach ($lkeys as $lkey) {
|
||||
// Set up options for single element
|
||||
$fakeParameterArray = array(
|
||||
'fieldConf' => array(
|
||||
'label' => $languageService->sL(trim($flexFormFieldArray['label'])),
|
||||
'config' => $flexFormFieldArray['config'],
|
||||
'defaultExtras' => $flexFormFieldArray['defaultExtras'],
|
||||
'onChange' => $flexFormFieldArray['onChange'],
|
||||
),
|
||||
);
|
||||
|
||||
$alertMsgOnChange = '';
|
||||
if (
|
||||
$fakeParameterArray['fieldConf']['onChange'] === 'reload'
|
||||
|| !empty($GLOBALS['TCA'][$table]['ctrl']['type']) && $GLOBALS['TCA'][$table]['ctrl']['type'] === $flexFormFieldName
|
||||
|| !empty($GLOBALS['TCA'][$table]['ctrl']['requestUpdate']) && GeneralUtility::inList($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'], $flexFormFieldName)
|
||||
) {
|
||||
if ($this->getBackendUserAuthentication()->jsConfirmation(JsConfirmation::TYPE_CHANGE)) {
|
||||
$alertMsgOnChange = 'top.TYPO3.Modal.confirm(TBE_EDITOR.labels.refreshRequired.title, TBE_EDITOR.labels.refreshRequired.content).on("button.clicked", function(e) { if (e.target.name == "ok" && TBE_EDITOR.checkSubmit(-1)) { TBE_EDITOR.submitForm() } top.TYPO3.Modal.dismiss(); });';
|
||||
} else {
|
||||
$alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm();}';
|
||||
}
|
||||
}
|
||||
$fakeParameterArray['fieldChangeFunc'] = $parameterArray['fieldChangeFunc'];
|
||||
if ($alertMsgOnChange) {
|
||||
$fakeParameterArray['fieldChangeFunc']['alert'] = $alertMsgOnChange;
|
||||
}
|
||||
|
||||
$fakeParameterArray['onFocus'] = $parameterArray['onFocus'];
|
||||
$fakeParameterArray['label'] = $parameterArray['label'];
|
||||
$fakeParameterArray['itemFormElName'] = $parameterArray['itemFormElName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][' . $lkey . ']';
|
||||
$fakeParameterArray['itemFormElID'] = $fakeParameterArray['itemFormElName'];
|
||||
if (isset($flexFormRowData[$flexFormFieldName][$lkey])) {
|
||||
$fakeParameterArray['itemFormElValue'] = $flexFormRowData[$flexFormFieldName][$lkey];
|
||||
} else {
|
||||
$fakeParameterArray['itemFormElValue'] = $fakeParameterArray['fieldConf']['config']['default'];
|
||||
}
|
||||
|
||||
$options = $this->data;
|
||||
$options['parameterArray'] = $fakeParameterArray;
|
||||
$options['elementBaseName'] = $this->data['elementBaseName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][' . $lkey . ']';
|
||||
|
||||
if (!empty($flexFormFieldArray['config']['renderType'])) {
|
||||
$options['renderType'] = $flexFormFieldArray['config']['renderType'];
|
||||
} else {
|
||||
// Fallback to type if no renderType is given
|
||||
$options['renderType'] = $flexFormFieldArray['config']['type'];
|
||||
}
|
||||
$childResult = $this->nodeFactory->create($options)->render();
|
||||
|
||||
$theTitle = htmlspecialchars($fakeParameterArray['fieldConf']['label']);
|
||||
$defInfo = array();
|
||||
|
||||
// Possible line breaks in the label through xml: \n => <br/>, usage of nl2br() not possible, so it's done through str_replace (?!)
|
||||
$processedTitle = str_replace('\\n', '<br />', $theTitle);
|
||||
// @todo: Similar to the processing within SingleElementContainer ... use it from there?!
|
||||
$html[] = '<div class="form-group t3js-formengine-palette-field t3js-formengine-validation-marker">';
|
||||
$html[] = '<label class="t3js-formengine-label">';
|
||||
if (is_array($metaData) && isset($metaData['langChildren']) && $metaData['langChildren']) {
|
||||
// Find language uid of this iso code
|
||||
$languageUid = 0;
|
||||
$lKeyWithoutV = substr($lkey, 1);
|
||||
if ($lKeyWithoutV !== 'DEF') {
|
||||
foreach ($this->data['systemLanguageRows'] as $systemLanguageRow) {
|
||||
if ($systemLanguageRow['iso'] === $lKeyWithoutV) {
|
||||
$languageUid = $systemLanguageRow['uid'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$languageIcon = $iconFactory->getIcon($this->data['systemLanguageRows'][$languageUid]['flagIconIdentifier'], Icon::SIZE_SMALL)->render();
|
||||
$html[] = $languageIcon;
|
||||
}
|
||||
$html[] = BackendUtility::wrapInHelp($parameterArray['_cshKey'], $flexFormFieldName, $processedTitle);
|
||||
$html[] = '</label>';
|
||||
$html[] = '<div class="t3js-formengine-field-item">';
|
||||
$html[] = $childResult['html'];
|
||||
$html[] = implode(LF, $defInfo);
|
||||
$html[] = $this->renderVDEFDiff($flexFormRowData[$flexFormFieldName], $lkey);
|
||||
$html[] = '</div>';
|
||||
$html[] = '</div>';
|
||||
}
|
||||
|
||||
if (!empty($html)) {
|
||||
$resultArray['html'] .= '<div class="form-section">' . implode(LF, $html) . '</div>';
|
||||
}
|
||||
$childResult['html'] = '';
|
||||
$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $childResult);
|
||||
}
|
||||
}
|
||||
|
||||
return $resultArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the diff-view of vDEF fields in flex forms
|
||||
*
|
||||
* @param array $vArray Record array of the record being edited
|
||||
* @param string $vDEFkey HTML of the form field. This is what we add the content to.
|
||||
* @return string Item string returned again, possibly with the original value added to.
|
||||
*/
|
||||
protected function renderVDEFDiff($vArray, $vDEFkey)
|
||||
{
|
||||
$item = null;
|
||||
if (
|
||||
$GLOBALS['TYPO3_CONF_VARS']['BE']['flexFormXMLincludeDiffBase'] && isset($vArray[$vDEFkey . '.vDEFbase'])
|
||||
&& (string)$vArray[$vDEFkey . '.vDEFbase'] !== (string)$vArray['vDEF'][0]
|
||||
) {
|
||||
// Create diff-result:
|
||||
$diffUtility = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Utility\DiffUtility::class);
|
||||
$diffres = $diffUtility->makeDiffDisplay($vArray[$vDEFkey . '.vDEFbase'], $vArray['vDEF']);
|
||||
$item = '<div class="typo3-TCEforms-diffBox">' . '<div class="typo3-TCEforms-diffBox-header">'
|
||||
. htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:compatibility6/Resources/Private/Language/locallang.xlf:labels.changeInOrig')) . ':</div>' . $diffres . '</div>';
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LanguageService
|
||||
*/
|
||||
protected function getLanguageService()
|
||||
{
|
||||
return $GLOBALS['LANG'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BackendUserAuthentication
|
||||
*/
|
||||
protected function getBackendUserAuthentication()
|
||||
{
|
||||
return $GLOBALS['BE_USER'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Compatibility6\Form\Container;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Backend\Form\Container\AbstractContainer;
|
||||
use TYPO3\CMS\Core\Imaging\Icon;
|
||||
use TYPO3\CMS\Core\Imaging\IconFactory;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Entry container to a flex form element. This container is created by
|
||||
* SingleFieldContainer if a type='flex' field is rendered.
|
||||
*
|
||||
* It either forks a FlexFormTabsContainer or a FlexFormNoTabsContainer.
|
||||
*
|
||||
* This container additionally handles flex form languages on sheet level.
|
||||
*/
|
||||
class FlexFormEntryContainer extends AbstractContainer
|
||||
{
|
||||
/**
|
||||
* Entry method
|
||||
*
|
||||
* @return array As defined in initializeResultArray() of AbstractNode
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$flexFormDataStructureArray = $this->data['parameterArray']['fieldConf']['config']['ds'];
|
||||
$flexFormRowData = $this->data['parameterArray']['itemFormElValue'];
|
||||
|
||||
/** @var IconFactory $iconFactory */
|
||||
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
|
||||
|
||||
// Tabs or no tabs - that's the question
|
||||
$hasTabs = false;
|
||||
if (count($flexFormDataStructureArray['sheets']) > 1) {
|
||||
$hasTabs = true;
|
||||
}
|
||||
|
||||
$resultArray = $this->initializeResultArray();
|
||||
|
||||
foreach ($flexFormDataStructureArray['meta']['languagesOnSheetLevel'] as $lKey) {
|
||||
// Add language as header
|
||||
if (!$flexFormDataStructureArray['meta']['langChildren'] && !$flexFormDataStructureArray['meta']['langDisable']) {
|
||||
// Find language uid of this iso code
|
||||
$languageUid = 0;
|
||||
if ($lKey !== 'DEF') {
|
||||
foreach ($this->data['systemLanguageRows'] as $systemLanguageRow) {
|
||||
if ($systemLanguageRow['iso'] === $lKey) {
|
||||
$languageUid = $systemLanguageRow['uid'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$resultArray['html'] .= LF
|
||||
. '<strong>'
|
||||
. $iconFactory->getIcon($this->data['systemLanguageRows'][$languageUid]['flagIconIdentifier'], Icon::SIZE_SMALL)->render()
|
||||
. htmlspecialchars($this->data['systemLanguageRows'][$languageUid]['title'])
|
||||
. '</strong>';
|
||||
}
|
||||
|
||||
// Default language "lDEF", other options are "lUK" or whatever country code
|
||||
$flexFormCurrentLanguage = 'l' . $lKey;
|
||||
|
||||
$options = $this->data;
|
||||
$options['flexFormCurrentLanguage'] = $flexFormCurrentLanguage;
|
||||
$options['flexFormDataStructureArray'] = $flexFormDataStructureArray;
|
||||
$options['flexFormRowData'] = $flexFormRowData;
|
||||
if (!$hasTabs) {
|
||||
$options['renderType'] = 'flexFormNoTabsContainer';
|
||||
$flexFormNoTabsResult = $this->nodeFactory->create($options)->render();
|
||||
$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $flexFormNoTabsResult);
|
||||
} else {
|
||||
$options['renderType'] = 'flexFormTabsContainer';
|
||||
$flexFormTabsContainerResult = $this->nodeFactory->create($options)->render();
|
||||
$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $flexFormTabsContainerResult);
|
||||
}
|
||||
}
|
||||
$resultArray['requireJsModules'][] = 'TYPO3/CMS/Backend/FormEngineFlexForm';
|
||||
|
||||
return $resultArray;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Compatibility6\Form\Container;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Backend\Form\Container\AbstractContainer;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Handle a flex form that has no tabs.
|
||||
*
|
||||
* This container is called by FlexFormEntryContainer if only a default sheet
|
||||
* exists. It evaluates the display condition and hands over rendering of single
|
||||
* fields to FlexFormElementContainer.
|
||||
*/
|
||||
class FlexFormNoTabsContainer extends AbstractContainer
|
||||
{
|
||||
/**
|
||||
* Entry method
|
||||
*
|
||||
* @return array As defined in initializeResultArray() of AbstractNode
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$table = $this->data['tableName'];
|
||||
$row = $this->data['databaseRow'];
|
||||
$fieldName = $this->data['fieldName']; // field name of the flex form field in DB
|
||||
$parameterArray = $this->data['parameterArray'];
|
||||
$flexFormDataStructureArray = $this->data['flexFormDataStructureArray'];
|
||||
$flexFormCurrentLanguage = $this->data['flexFormCurrentLanguage'];
|
||||
$flexFormRowData = $this->data['flexFormRowData'];
|
||||
$resultArray = $this->initializeResultArray();
|
||||
|
||||
// Flex ds was normalized in flex provider to always have a sheet.
|
||||
// Determine this single sheet name, most often it ends up with sDEF, except if only one sheet was defined
|
||||
$sheetName = array_pop(array_keys($flexFormDataStructureArray['sheets']));
|
||||
$flexFormRowDataSubPart = $flexFormRowData['data'][$sheetName][$flexFormCurrentLanguage];
|
||||
|
||||
// That was taken from GeneralUtility::resolveSheetDefInDS - no idea if it is important
|
||||
unset($flexFormDataStructureArray['meta']);
|
||||
|
||||
if (!is_array($flexFormDataStructureArray['sheets'][$sheetName]['ROOT']['el'])) {
|
||||
$resultArray['html'] = 'Data Structure ERROR: No [\'ROOT\'][\'el\'] element found in flex form definition.';
|
||||
return $resultArray;
|
||||
}
|
||||
|
||||
// Assemble key for loading the correct CSH file
|
||||
// @todo: what is that good for? That is for the title of single elements ... see FlexFormElementContainer!
|
||||
$dsPointerFields = GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$table]['columns'][$fieldName]['config']['ds_pointerField'], true);
|
||||
$parameterArray['_cshKey'] = $table . '.' . $fieldName;
|
||||
foreach ($dsPointerFields as $key) {
|
||||
if ((string)$row[$key] !== '') {
|
||||
$parameterArray['_cshKey'] .= '.' . $row[$key];
|
||||
}
|
||||
}
|
||||
|
||||
$options = $this->data;
|
||||
$options['flexFormDataStructureArray'] = $flexFormDataStructureArray['sheets'][$sheetName]['ROOT']['el'];
|
||||
$options['flexFormRowData'] = $flexFormRowDataSubPart;
|
||||
$options['flexFormFormPrefix'] = '[data][' . $sheetName . '][' . $flexFormCurrentLanguage . ']';
|
||||
$options['parameterArray'] = $parameterArray;
|
||||
|
||||
$options['renderType'] = 'flexFormElementContainer';
|
||||
return $this->nodeFactory->create($options)->render();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Compatibility6\Form\Container;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Backend\Form\Container\AbstractContainer;
|
||||
use TYPO3\CMS\Backend\Template\DocumentTemplate;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Lang\LanguageService;
|
||||
|
||||
/**
|
||||
* Handle flex forms that have tabs (multiple "sheets").
|
||||
*
|
||||
* This container is called by FlexFormEntryContainer. It resolves each
|
||||
* sheet and hands rendering of single sheet content over to FlexFormElementContainer.
|
||||
*/
|
||||
class FlexFormTabsContainer extends AbstractContainer
|
||||
{
|
||||
/**
|
||||
* Entry method
|
||||
*
|
||||
* @return array As defined in initializeResultArray() of AbstractNode
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$languageService = $this->getLanguageService();
|
||||
|
||||
$table = $this->data['tableName'];
|
||||
$row = $this->data['databaseRow'];
|
||||
$fieldName = $this->data['fieldName']; // field name of the flex form field in DB
|
||||
$parameterArray = $this->data['parameterArray'];
|
||||
$flexFormDataStructureArray = $this->data['flexFormDataStructureArray'];
|
||||
$flexFormCurrentLanguage = $this->data['flexFormCurrentLanguage'];
|
||||
$flexFormRowData = $this->data['flexFormRowData'];
|
||||
|
||||
$resultArray = $this->initializeResultArray();
|
||||
$resultArray['requireJsModules'][] = 'TYPO3/CMS/Backend/Tabs';
|
||||
|
||||
$domIdPrefix = 'DTM-' . GeneralUtility::shortMD5($this->data['parameterArray']['itemFormElName'] . $flexFormCurrentLanguage);
|
||||
$tabCounter = 0;
|
||||
$tabElements = array();
|
||||
foreach ($flexFormDataStructureArray['sheets'] as $sheetName => $sheetDataStructure) {
|
||||
$flexFormRowSheetDataSubPart = $flexFormRowData['data'][$sheetName][$flexFormCurrentLanguage];
|
||||
|
||||
if (!is_array($sheetDataStructure['ROOT']['el'])) {
|
||||
$resultArray['html'] .= LF . 'No Data Structure ERROR: No [\'ROOT\'][\'el\'] found for sheet "' . $sheetName . '".';
|
||||
continue;
|
||||
}
|
||||
|
||||
$tabCounter ++;
|
||||
|
||||
// Assemble key for loading the correct CSH file
|
||||
// @todo: what is that good for? That is for the title of single elements ... see FlexFormElementContainer!
|
||||
$dsPointerFields = GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$table]['columns'][$fieldName]['config']['ds_pointerField'], true);
|
||||
$parameterArray['_cshKey'] = $table . '.' . $fieldName;
|
||||
foreach ($dsPointerFields as $key) {
|
||||
if ((string)$row[$key] !== '') {
|
||||
$parameterArray['_cshKey'] .= '.' . $row[$key];
|
||||
}
|
||||
}
|
||||
|
||||
$options = $this->data;
|
||||
$options['flexFormDataStructureArray'] = $sheetDataStructure['ROOT']['el'];
|
||||
$options['flexFormRowData'] = $flexFormRowSheetDataSubPart;
|
||||
$options['flexFormFormPrefix'] = '[data][' . $sheetName . '][' . $flexFormCurrentLanguage . ']';
|
||||
$options['parameterArray'] = $parameterArray;
|
||||
// Merge elements of this tab into a single list again and hand over to
|
||||
// palette and single field container to render this group
|
||||
$options['tabAndInlineStack'][] = array(
|
||||
'tab',
|
||||
$domIdPrefix . '-' . $tabCounter,
|
||||
);
|
||||
$options['renderType'] = 'flexFormElementContainer';
|
||||
$childReturn = $this->nodeFactory->create($options)->render();
|
||||
|
||||
$tabElements[] = array(
|
||||
'label' => !empty($sheetDataStructure['ROOT']['sheetTitle']) ? $languageService->sL($sheetDataStructure['ROOT']['sheetTitle']) : $sheetName,
|
||||
'content' => $childReturn['html'],
|
||||
'description' => $sheetDataStructure['ROOT']['sheetDescription'] ? $languageService->sL($sheetDataStructure['ROOT']['sheetDescription']) : '',
|
||||
'linkTitle' => $sheetDataStructure['ROOT']['sheetShortDescr'] ? $languageService->sL($sheetDataStructure['ROOT']['sheetShortDescr']) : '',
|
||||
);
|
||||
|
||||
$childReturn['html'] = '';
|
||||
$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $childReturn);
|
||||
}
|
||||
|
||||
// Feed everything to document template for tab rendering
|
||||
$resultArray['html'] = $this->renderTabMenu($tabElements, $domIdPrefix);
|
||||
return $resultArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LanguageService
|
||||
*/
|
||||
protected function getLanguageService()
|
||||
{
|
||||
return $GLOBALS['LANG'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,707 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Compatibility6\Form\FormDataProvider;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Backend\Form\FormDataCompiler;
|
||||
use TYPO3\CMS\Backend\Form\FormDataGroup\FlexFormSegment;
|
||||
use TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider;
|
||||
use TYPO3\CMS\Backend\Form\FormDataProviderInterface;
|
||||
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Process data structures and data values, calculate defaults.
|
||||
*
|
||||
* This is typically the last provider, executed after TcaFlexPrepare
|
||||
*/
|
||||
class TcaFlexProcess implements FormDataProviderInterface
|
||||
{
|
||||
/**
|
||||
* Determine possible pageTsConfig overrides and apply them to ds.
|
||||
* Determine available languages and sanitize dv for further processing. Then kick
|
||||
* and validate further details like excluded fields. Finally for each possible
|
||||
* value and ds call FormDataCompiler with set FlexFormSegment group to resolve
|
||||
* single field stuff like item processor functions.
|
||||
*
|
||||
* @param array $result
|
||||
* @return array
|
||||
*/
|
||||
public function addData(array $result)
|
||||
{
|
||||
foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfig) {
|
||||
if (empty($fieldConfig['config']['type']) || $fieldConfig['config']['type'] !== 'flex') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$flexIdentifier = $this->getFlexIdentifier($result, $fieldName);
|
||||
$pageTsConfigOfFlex = $this->getPageTsOfFlex($result, $fieldName, $flexIdentifier);
|
||||
$result = $this->modifyOuterDataStructure($result, $fieldName, $pageTsConfigOfFlex);
|
||||
$result = $this->removeExcludeFieldsFromDataStructure($result, $fieldName, $flexIdentifier);
|
||||
$result = $this->removeDisabledFieldsFromDataStructure($result, $fieldName, $pageTsConfigOfFlex);
|
||||
$result = $this->prepareLanguageHandlingInDataValues($result, $fieldName);
|
||||
$result = $this->modifyDataStructureAndDataValuesByFlexFormSegmentGroup($result, $fieldName, $pageTsConfigOfFlex);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take care of ds_pointerField and friends to determine the correct sub array within
|
||||
* TCA config ds.
|
||||
*
|
||||
* Gets extension identifier. Use second pointer field if it's value is not empty, "list" or "*",
|
||||
* else it must be a plugin and first one will be used.
|
||||
* This code basically determines the sub key of ds field:
|
||||
* config = array(
|
||||
* ds => array(
|
||||
* 'aFlexConfig' => '<flexXml ...
|
||||
* ^^^^^^^^^^^
|
||||
* $flexformIdentifier contains "aFlexConfig" after this operation.
|
||||
*
|
||||
* @todo: This method is only implemented half. It basically should do all the
|
||||
* @todo: pointer handling that is done within BackendUtility::getFlexFormDS() to $srcPointer.
|
||||
*
|
||||
* @param array $result Result array
|
||||
* @param string $fieldName Current handle field name
|
||||
* @return string Pointer
|
||||
*/
|
||||
protected function getFlexIdentifier(array $result, $fieldName)
|
||||
{
|
||||
// @todo: Current implementation with the "list_type, CType" fallback is rather limited and customized for
|
||||
// @todo: tt_content, also it forces a ds_pointerField to be defined and a casual "default" sub array does not work
|
||||
$pointerFields = !empty($result['processedTca']['columns'][$fieldName]['config']['ds_pointerField'])
|
||||
? $result['processedTca']['columns'][$fieldName]['config']['ds_pointerField']
|
||||
: 'list_type,CType';
|
||||
$pointerFields = GeneralUtility::trimExplode(',', $pointerFields);
|
||||
$flexformIdentifier = !empty($result['databaseRow'][$pointerFields[0]]) ? $result['databaseRow'][$pointerFields[0]] : '';
|
||||
if (!empty($result['databaseRow'][$pointerFields[1]])
|
||||
&& $result['databaseRow'][$pointerFields[1]] !== 'list'
|
||||
&& $result['databaseRow'][$pointerFields[1]] !== '*'
|
||||
) {
|
||||
$flexformIdentifier = $result['databaseRow'][$pointerFields[1]];
|
||||
}
|
||||
if (empty($flexformIdentifier)) {
|
||||
$flexformIdentifier = 'default';
|
||||
}
|
||||
|
||||
return $flexformIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine TCEFORM.aTable.aField.matchingIdentifier
|
||||
*
|
||||
* @param array $result Result array
|
||||
* @param string $fieldName Handled field name
|
||||
* @param string $flexIdentifier Determined identifier
|
||||
* @return array PageTsConfig for this flex
|
||||
*/
|
||||
protected function getPageTsOfFlex(array $result, $fieldName, $flexIdentifier)
|
||||
{
|
||||
$table = $result['tableName'];
|
||||
$pageTs = [];
|
||||
if (!empty($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.'][$flexIdentifier . '.'])
|
||||
&& is_array($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.'][$flexIdentifier . '.'])) {
|
||||
$pageTs = $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.'][$flexIdentifier . '.'];
|
||||
}
|
||||
return $pageTs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle "outer" flex data structure changes like language and sheet
|
||||
* description. Does not change "TCA" or values of single elements
|
||||
*
|
||||
* @param array $result Result array
|
||||
* @param string $fieldName Current handle field name
|
||||
* @param array $pageTsConfig Given pageTsConfig of this flex form
|
||||
* @return array Modified item array
|
||||
*/
|
||||
protected function modifyOuterDataStructure(array $result, $fieldName, $pageTsConfig)
|
||||
{
|
||||
$modifiedDataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
|
||||
|
||||
if (isset($pageTsConfig['langDisable'])) {
|
||||
$modifiedDataStructure['meta']['langDisable'] = $pageTsConfig['langDisable'];
|
||||
}
|
||||
if (isset($pageTsConfig['langChildren'])) {
|
||||
$modifiedDataStructure['meta']['langChildren'] = $pageTsConfig['langChildren'];
|
||||
}
|
||||
|
||||
if (isset($modifiedDataStructure['sheets']) && is_array($modifiedDataStructure['sheets'])) {
|
||||
// Handling multiple sheets
|
||||
foreach ($modifiedDataStructure['sheets'] as $sheetName => $sheetStructure) {
|
||||
if (isset($pageTsConfig[$sheetName . '.']) && is_array($pageTsConfig[$sheetName . '.'])) {
|
||||
$pageTsOfSheet = $pageTsConfig[$sheetName . '.'];
|
||||
|
||||
// Remove whole sheet if disabled
|
||||
if (!empty($pageTsOfSheet['disabled'])) {
|
||||
unset($modifiedDataStructure['sheets'][$sheetName]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// sheetTitle, sheetDescription, sheetShortDescr
|
||||
$modifiedDataStructure['sheets'][$sheetName] = $this->modifySingleSheetInformation($sheetStructure, $pageTsOfSheet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$modifiedDataStructure['meta']['langDisable'] = isset($modifiedDataStructure['meta']['langDisable'])
|
||||
? (bool)$modifiedDataStructure['meta']['langDisable']
|
||||
: false;
|
||||
$modifiedDataStructure['meta']['langChildren'] = isset($modifiedDataStructure['meta']['langChildren'])
|
||||
? (bool)$modifiedDataStructure['meta']['langChildren']
|
||||
: false;
|
||||
|
||||
$result['processedTca']['columns'][$fieldName]['config']['ds'] = $modifiedDataStructure;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes fields from data structure the user has no access to
|
||||
*
|
||||
* @param array $result Result array
|
||||
* @param string $fieldName Current handle field name
|
||||
* @param string $flexIdentifier Determined identifier
|
||||
* @return array Modified result
|
||||
*/
|
||||
protected function removeExcludeFieldsFromDataStructure(array $result, $fieldName, $flexIdentifier)
|
||||
{
|
||||
$dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
|
||||
$backendUser = $this->getBackendUser();
|
||||
if ($backendUser->isAdmin() || !isset($dataStructure['sheets']) || !is_array($dataStructure['sheets'])) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$userNonExcludeFields = GeneralUtility::trimExplode(',', $backendUser->groupData['non_exclude_fields']);
|
||||
$excludeFieldsPrefix = $result['tableName'] . ':' . $fieldName . ';' . $flexIdentifier . ';';
|
||||
$nonExcludeFields = [];
|
||||
foreach ($userNonExcludeFields as $userNonExcludeField) {
|
||||
if (strpos($userNonExcludeField, $excludeFieldsPrefix) !== false) {
|
||||
$exploded = explode(';', $userNonExcludeField);
|
||||
$sheetName = $exploded[2];
|
||||
$fieldName = $exploded[3];
|
||||
$nonExcludeFields[$sheetName] = $fieldName;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($dataStructure['sheets'] as $sheetName => $sheetDefinition) {
|
||||
if (!isset($sheetDefinition['ROOT']['el']) || !is_array($sheetDefinition['ROOT']['el'])) {
|
||||
continue;
|
||||
}
|
||||
foreach ($sheetDefinition['ROOT']['el'] as $flexFieldName => $fieldDefinition) {
|
||||
if (!empty($fieldDefinition['exclude']) && empty($nonExcludeFields[$sheetName])) {
|
||||
unset($result['processedTca']['columns'][$fieldName]['config']['ds']['sheets'][$sheetName]['ROOT']['el'][$flexFieldName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle "outer" flex data structure changes like language and sheet
|
||||
* description. Does not change "TCA" or values of single elements
|
||||
*
|
||||
* @param array $result Result array
|
||||
* @param string $fieldName Current handle field name
|
||||
* @param array $pageTsConfig Given pageTsConfig of this flex form
|
||||
* @return array Modified item array
|
||||
*/
|
||||
protected function removeDisabledFieldsFromDataStructure(array $result, $fieldName, $pageTsConfig)
|
||||
{
|
||||
$dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
|
||||
if (!isset($dataStructure['sheets']) || !is_array($dataStructure['sheets'])) {
|
||||
return $result;
|
||||
}
|
||||
foreach ($dataStructure['sheets'] as $sheetName => $sheetDefinition) {
|
||||
if (!isset($sheetDefinition['ROOT']['el']) || !is_array($sheetDefinition['ROOT']['el'])
|
||||
|| !isset($pageTsConfig[$sheetName . '.'])) {
|
||||
continue;
|
||||
}
|
||||
foreach ($sheetDefinition['ROOT']['el'] as $flexFieldName => $fieldDefinition) {
|
||||
if (!empty($pageTsConfig[$sheetName . '.'][$flexFieldName . '.']['disabled'])) {
|
||||
unset($result['processedTca']['columns'][$fieldName]['config']['ds']['sheets'][$sheetName]['ROOT']['el'][$flexFieldName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove data values in languages the user has no access to and add dummy entries
|
||||
* for languages that are available but do not exist in data values yet.
|
||||
*
|
||||
* @param array $result Result array
|
||||
* @param string $fieldName Current handle field name
|
||||
* @return array Modified item array
|
||||
*/
|
||||
protected function prepareLanguageHandlingInDataValues(array $result, $fieldName)
|
||||
{
|
||||
$backendUser = $this->getBackendUser();
|
||||
$dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
|
||||
|
||||
$langDisabled = $dataStructure['meta']['langDisable'];
|
||||
$langChildren = $dataStructure['meta']['langChildren'];
|
||||
|
||||
// Existing page language overlays are only considered if options.checkPageLanguageOverlay is set in userTs
|
||||
$checkPageLanguageOverlay = false;
|
||||
if (isset($result['userTsConfig']['options.']) && is_array($result['userTsConfig']['options.'])
|
||||
&& array_key_exists('checkPageLanguageOverlay', $result['userTsConfig']['options.'])
|
||||
) {
|
||||
$checkPageLanguageOverlay = (bool)$result['userTsConfig']['options.']['checkPageLanguageOverlay'];
|
||||
}
|
||||
|
||||
$systemLanguageRows = $result['systemLanguageRows'];
|
||||
|
||||
// Contains all language iso code that are valid and user has access to
|
||||
$availableLanguageCodes = [];
|
||||
$defaultCodeWasAdded = false;
|
||||
foreach ($systemLanguageRows as $systemLanguageRow) {
|
||||
$isoCode = $systemLanguageRow['iso'];
|
||||
$isAvailable = true;
|
||||
if ($langDisabled && $isoCode !== 'DEF') {
|
||||
$isAvailable = false;
|
||||
}
|
||||
// @todo: Is it possible a user has no write access to default lang? If so, what to do?
|
||||
if (!$backendUser->checkLanguageAccess($systemLanguageRow['uid'])) {
|
||||
$isAvailable = false;
|
||||
}
|
||||
if ($checkPageLanguageOverlay && $systemLanguageRow['uid'] > 0) {
|
||||
$found = false;
|
||||
foreach ($result['pageLanguageOverlayRows'] as $overlayRow) {
|
||||
if ((int)$overlayRow['sys_language_uid'] === (int)$systemLanguageRow['uid']) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
$isAvailable = false;
|
||||
}
|
||||
}
|
||||
if ($isoCode === 'DEF' && $defaultCodeWasAdded) {
|
||||
$isAvailable = false;
|
||||
}
|
||||
if ($isAvailable) {
|
||||
$availableLanguageCodes[] = $isoCode;
|
||||
}
|
||||
if ($isoCode === 'DEF') {
|
||||
$defaultCodeWasAdded = true;
|
||||
}
|
||||
}
|
||||
// Set the list of available languages in the data structure "meta" section to have it
|
||||
// available for the render engine to iterate over it.
|
||||
$result['processedTca']['columns'][$fieldName]['config']['ds']['meta']['availableLanguageCodes'] = $availableLanguageCodes;
|
||||
|
||||
if (!$langChildren) {
|
||||
$allowedLanguageSheetKeys = [];
|
||||
foreach ($availableLanguageCodes as $isoCode) {
|
||||
$allowedLanguageSheetKeys['l' . $isoCode] = [];
|
||||
}
|
||||
$result = $this->setLanguageSheetsInDataValues($result, $fieldName, $allowedLanguageSheetKeys);
|
||||
|
||||
// With $langChildren = 0, values must only contain vDEF prefixed keys
|
||||
$allowedValueLevelLanguageKeys = [];
|
||||
$allowedValueLevelLanguageKeys['vDEF'] = [];
|
||||
$allowedValueLevelLanguageKeys['vDEF.vDEFbase'] = [];
|
||||
// A richtext special
|
||||
$allowedValueLevelLanguageKeys['_TRANSFORM_vDEF.vDEFbase'] = [];
|
||||
$result = $this->setLanguageValueLevelValues($result, $fieldName, $allowedValueLevelLanguageKeys);
|
||||
} else {
|
||||
// langChildren is set - only lDEF as sheet language is allowed, but more fields on value field level
|
||||
$allowedLanguageSheetKeys = [
|
||||
'lDEF' => [],
|
||||
];
|
||||
$result = $this->setLanguageSheetsInDataValues($result, $fieldName, $allowedLanguageSheetKeys);
|
||||
|
||||
$allowedValueLevelLanguageKeys = [];
|
||||
foreach ($availableLanguageCodes as $isoCode) {
|
||||
$allowedValueLevelLanguageKeys['v' . $isoCode] = [];
|
||||
$allowedValueLevelLanguageKeys['v' . $isoCode . '.vDEFbase'] = [];
|
||||
$allowedValueLevelLanguageKeys['_TRANSFORM_v' . $isoCode . '.vDEFbase'] = [];
|
||||
}
|
||||
$result = $this->setLanguageValueLevelValues($result, $fieldName, $allowedValueLevelLanguageKeys);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Feed single flex field and data to FlexFormSegment FormData compiler and merge result.
|
||||
* This one is nasty. Goal is to have processed TCA stuff in DS and also have validated / processed data values.
|
||||
*
|
||||
* Three main parts in this method:
|
||||
* * Process values of existing section container for default values
|
||||
* * Process values and TCA of possible section container and create a default value row for each
|
||||
* * Process TCA of "normal" fields and have default values in data ['templateRows']['containerName'] parallel to section ['el']
|
||||
*
|
||||
* @param array $result Result array
|
||||
* @param string $fieldName Current handle field name
|
||||
* @param array $pageTsConfig Given pageTsConfig of this flex form
|
||||
* @return array Modified item array
|
||||
*/
|
||||
protected function modifyDataStructureAndDataValuesByFlexFormSegmentGroup(array $result, $fieldName, $pageTsConfig)
|
||||
{
|
||||
$dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
|
||||
$dataValues = $result['databaseRow'][$fieldName];
|
||||
$tableName = $result['tableName'];
|
||||
|
||||
$availableLanguageCodes = $result['processedTca']['columns'][$fieldName]['config']['ds']['meta']['availableLanguageCodes'];
|
||||
if ($dataStructure['meta']['langChildren']) {
|
||||
$languagesOnSheetLevel = [ 'DEF' ];
|
||||
$languagesOnElementLevel = $availableLanguageCodes;
|
||||
} else {
|
||||
$languagesOnSheetLevel = $availableLanguageCodes;
|
||||
$languagesOnElementLevel = [ 'DEF' ];
|
||||
}
|
||||
|
||||
$result['processedTca']['columns'][$fieldName]['config']['ds']['meta']['languagesOnSheetLevel'] = $languagesOnSheetLevel;
|
||||
$result['processedTca']['columns'][$fieldName]['config']['ds']['meta']['languagesOnElement'] = $languagesOnElementLevel;
|
||||
|
||||
if (!isset($dataStructure['sheets']) || !is_array($dataStructure['sheets'])) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
/** @var FlexFormSegment $formDataGroup */
|
||||
$formDataGroup = GeneralUtility::makeInstance(FlexFormSegment::class);
|
||||
/** @var FormDataCompiler $formDataCompiler */
|
||||
$formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
|
||||
|
||||
foreach ($dataStructure['sheets'] as $dataStructureSheetName => $dataStructureSheetDefinition) {
|
||||
if (!isset($dataStructureSheetDefinition['ROOT']['el']) || !is_array($dataStructureSheetDefinition['ROOT']['el'])) {
|
||||
continue;
|
||||
}
|
||||
$dataStructureSheetElements = $dataStructureSheetDefinition['ROOT']['el'];
|
||||
|
||||
// Prepare pageTsConfig of this sheet
|
||||
$pageTsConfig['TCEFORM.'][$tableName . '.'] = [];
|
||||
if (isset($pageTsConfig[$dataStructureSheetName . '.']) && is_array($pageTsConfig[$dataStructureSheetName . '.'])) {
|
||||
$pageTsConfig['TCEFORM.'][$tableName . '.'] = $pageTsConfig[$dataStructureSheetName . '.'];
|
||||
}
|
||||
|
||||
foreach ($languagesOnSheetLevel as $isoSheetLevel) {
|
||||
$langSheetLevel = 'l' . $isoSheetLevel;
|
||||
foreach ($dataStructureSheetElements as $dataStructureSheetElementName => $dataStructureSheetElementDefinition) {
|
||||
if (isset($dataStructureSheetElementDefinition['type']) && $dataStructureSheetElementDefinition['type'] === 'array'
|
||||
&& isset($dataStructureSheetElementDefinition['section']) && $dataStructureSheetElementDefinition['section'] === '1'
|
||||
) {
|
||||
// A section
|
||||
|
||||
// Existing section container elements
|
||||
if (isset($dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['el'])
|
||||
&& is_array($dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['el'])
|
||||
) {
|
||||
$containerArray = $dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['el'];
|
||||
foreach ($containerArray as $aContainerNumber => $aContainerArray) {
|
||||
if (is_array($aContainerArray)) {
|
||||
foreach ($aContainerArray as $aContainerName => $aContainerElementArray) {
|
||||
if ($aContainerName === '_TOGGLE') {
|
||||
// Don't handle internal toggle state field
|
||||
continue;
|
||||
}
|
||||
if (!isset($dataStructureSheetElements[$dataStructureSheetElementName]['el'][$aContainerName])) {
|
||||
// Container not defined in ds
|
||||
continue;
|
||||
}
|
||||
foreach ($dataStructureSheetElements[$dataStructureSheetElementName]['el'][$aContainerName]['el'] as $singleFieldName => $singleFieldConfiguration) {
|
||||
// $singleFieldValueArray = ['data']['sSections']['lDEF']['section_1']['el']['1']['container_1']['el']['element_1']
|
||||
$singleFieldValueArray = [];
|
||||
if (isset($aContainerElementArray['el'][$singleFieldName])
|
||||
&& is_array($aContainerElementArray['el'][$singleFieldName])
|
||||
) {
|
||||
$singleFieldValueArray = $aContainerElementArray['el'][$singleFieldName];
|
||||
}
|
||||
foreach ($languagesOnElementLevel as $isoElementLevel) {
|
||||
$langElementLevel = 'v' . $isoElementLevel;
|
||||
$valueArray = [
|
||||
'uid' => $result['databaseRow']['uid'],
|
||||
];
|
||||
$command = 'new';
|
||||
if (array_key_exists($langElementLevel, $singleFieldValueArray)) {
|
||||
$command = 'edit';
|
||||
$valueArray[$singleFieldName] = $singleFieldValueArray[$langElementLevel];
|
||||
}
|
||||
$inputToFlexFormSegment = [
|
||||
'tableName' => $result['tableName'],
|
||||
'command' => $command,
|
||||
// It is currently not possible to have pageTsConfig for section container
|
||||
'pageTsConfig' => [],
|
||||
'databaseRow' => $valueArray,
|
||||
'processedTca' => [
|
||||
'ctrl' => [],
|
||||
'columns' => [
|
||||
$singleFieldName => $singleFieldConfiguration,
|
||||
],
|
||||
],
|
||||
];
|
||||
$flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
|
||||
// Set data value result
|
||||
if (array_key_exists($singleFieldName, $flexSegmentResult['databaseRow'])) {
|
||||
$result['databaseRow'][$fieldName]
|
||||
['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['el']
|
||||
[$aContainerNumber][$aContainerName]['el']
|
||||
[$singleFieldName][$langElementLevel]
|
||||
= $flexSegmentResult['databaseRow'][$singleFieldName];
|
||||
}
|
||||
// Set TCA structure result, actually, this call *might* be obsolete since the "dummy"
|
||||
// handling below will set it again.
|
||||
$result['processedTca']['columns'][$fieldName]['config']['ds']
|
||||
['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]['el']
|
||||
[$aContainerName]['el'][$singleFieldName]
|
||||
= $flexSegmentResult['processedTca']['columns'][$singleFieldName];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // End of existing data value handling
|
||||
|
||||
// Prepare "fresh" row for every possible container
|
||||
if (isset($dataStructureSheetElements[$dataStructureSheetElementName]['el']) && is_array($dataStructureSheetElements[$dataStructureSheetElementName]['el'])) {
|
||||
foreach ($dataStructureSheetElements[$dataStructureSheetElementName]['el'] as $possibleContainerName => $possibleContainerConfiguration) {
|
||||
if (isset($possibleContainerConfiguration['el']) && is_array($possibleContainerConfiguration['el'])) {
|
||||
// Initialize result data array templateRows
|
||||
$result['databaseRow'][$fieldName]
|
||||
['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['templateRows']
|
||||
[$possibleContainerName]['el']
|
||||
= [];
|
||||
foreach ($possibleContainerConfiguration['el'] as $singleFieldName => $singleFieldConfiguration) {
|
||||
foreach ($languagesOnElementLevel as $isoElementLevel) {
|
||||
$langElementLevel = 'v' . $isoElementLevel;
|
||||
$inputToFlexFormSegment = [
|
||||
'tableName' => $result['tableName'],
|
||||
'command' => 'new',
|
||||
'pageTsConfig' => [],
|
||||
'databaseRow' => [
|
||||
'uid' => $result['databaseRow']['uid'],
|
||||
],
|
||||
'processedTca' => [
|
||||
'ctrl' => [],
|
||||
'columns' => [
|
||||
$singleFieldName => $singleFieldConfiguration,
|
||||
],
|
||||
],
|
||||
];
|
||||
$flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
|
||||
if (array_key_exists($singleFieldName, $flexSegmentResult['databaseRow'])) {
|
||||
$result['databaseRow'][$fieldName]
|
||||
['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['templateRows']
|
||||
[$possibleContainerName]['el'][$singleFieldName][$langElementLevel]
|
||||
= $flexSegmentResult['databaseRow'][$singleFieldName];
|
||||
}
|
||||
$result['processedTca']['columns'][$fieldName]['config']['ds']
|
||||
['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]['el']
|
||||
[$possibleContainerName]['el'][$singleFieldName]
|
||||
= $flexSegmentResult['processedTca']['columns'][$singleFieldName];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // End of preparation for each possible container
|
||||
|
||||
// type without section is not ok
|
||||
} elseif (isset($dataStructureSheetElementDefinition['type']) || isset($dataStructureSheetElementDefinition['section'])) {
|
||||
throw new \UnexpectedValueException(
|
||||
'Broken data structure on field name ' . $fieldName . '. section without type or vice versa is not allowed',
|
||||
1440685208
|
||||
);
|
||||
|
||||
// A "normal" TCA element
|
||||
} else {
|
||||
foreach ($languagesOnElementLevel as $isoElementLevel) {
|
||||
$langElementLevel = 'v' . $isoElementLevel;
|
||||
$valueArray = [
|
||||
// uid of "parent" is given down for inline elements to resolve correctly
|
||||
'uid' => $result['databaseRow']['uid'],
|
||||
];
|
||||
$command = 'new';
|
||||
if (isset($dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName])
|
||||
&& array_key_exists($langElementLevel, $dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName])
|
||||
) {
|
||||
$command = 'edit';
|
||||
$valueArray[$dataStructureSheetElementName] = $dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName][$langElementLevel];
|
||||
}
|
||||
$inputToFlexFormSegment = [
|
||||
// tablename of "parent" is given down for inline elements to resolve correctly
|
||||
'tableName' => $result['tableName'],
|
||||
'command' => $command,
|
||||
'pageTsConfig' => $pageTsConfig,
|
||||
'databaseRow' => $valueArray,
|
||||
'processedTca' => [
|
||||
'ctrl' => [],
|
||||
'columns' => [
|
||||
$dataStructureSheetElementName => $dataStructureSheetElementDefinition,
|
||||
],
|
||||
],
|
||||
];
|
||||
$flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
|
||||
// Set data value result
|
||||
if (array_key_exists($dataStructureSheetElementName, $flexSegmentResult['databaseRow'])) {
|
||||
$result['databaseRow'][$fieldName]
|
||||
['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName][$langElementLevel]
|
||||
= $flexSegmentResult['databaseRow'][$dataStructureSheetElementName];
|
||||
}
|
||||
// Set TCA structure result
|
||||
$result['processedTca']['columns'][$fieldName]['config']['ds']
|
||||
['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]
|
||||
= $flexSegmentResult['processedTca']['columns'][$dataStructureSheetElementName];
|
||||
}
|
||||
} // End of single element handling
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify data structure of a single "sheet"
|
||||
* Sets "secondary" data like sheet names and so on, but does NOT modify single elements
|
||||
*
|
||||
* @param array $dataStructure Given data structure
|
||||
* @param array $pageTsOfSheet Page Ts config of given field
|
||||
* @return array Modified data structure
|
||||
*/
|
||||
protected function modifySingleSheetInformation(array $dataStructure, array $pageTsOfSheet)
|
||||
{
|
||||
// Return if no elements defined
|
||||
if (!isset($dataStructure['ROOT']['el']) || !is_array($dataStructure['ROOT']['el'])) {
|
||||
return $dataStructure;
|
||||
}
|
||||
|
||||
// Rename sheet (tab)
|
||||
if (!empty($pageTsOfSheet['sheetTitle'])) {
|
||||
$dataStructure['ROOT']['sheetTitle'] = $pageTsOfSheet['sheetTitle'];
|
||||
}
|
||||
// Set sheet description (tab)
|
||||
if (!empty($pageTsOfSheet['sheetDescription'])) {
|
||||
$dataStructure['ROOT']['sheetDescription'] = $pageTsOfSheet['sheetDescription'];
|
||||
}
|
||||
// Set sheet short description (tab)
|
||||
if (!empty($pageTsOfSheet['sheetShortDescr'])) {
|
||||
$dataStructure['ROOT']['sheetShortDescr'] = $pageTsOfSheet['sheetShortDescr'];
|
||||
}
|
||||
|
||||
return $dataStructure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new sheet languages not yet in data values and remove invalid ones
|
||||
*
|
||||
* databaseRow['aFlex']['data']['sDEF'] = array('lDEF', 'lNotAllowed');
|
||||
* allowedLanguageKeys = array('lDEF', 'lNEW')
|
||||
* -> databaseRow['aFlex']['data']['sDEF'] = array('lDEF', 'lNEW');
|
||||
*
|
||||
* @param array $result Result array
|
||||
* @param string $fieldName Current handle field name
|
||||
* @param array $allowedKeys List of allowed keys
|
||||
* @return array Modified result
|
||||
*/
|
||||
protected function setLanguageSheetsInDataValues(array $result, $fieldName, array $allowedKeys)
|
||||
{
|
||||
$valueArray = [];
|
||||
if (isset($result['databaseRow'][$fieldName]['data']) && is_array($result['databaseRow'][$fieldName]['data'])) {
|
||||
$valueArray = $result['databaseRow'][$fieldName]['data'];
|
||||
}
|
||||
foreach ($valueArray as $sheetName => $sheetLanguages) {
|
||||
// Add iso code with empty array if it does not yet exist in data
|
||||
// and remove codes from data that do not exist in $allowed
|
||||
$result['databaseRow'][$fieldName]['data'][$sheetName]
|
||||
= array_intersect_key(array_merge($allowedKeys, $sheetLanguages), $allowedKeys);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove invalid keys from data value array the user has no access to
|
||||
* or that were removed or similar to prevent any rendering of this stuff
|
||||
*
|
||||
* Handles this for "normal" fields and also for section container element values.
|
||||
*
|
||||
* @param array $result Result array
|
||||
* @param string $fieldName Current handle field name
|
||||
* @param array $allowedKeys List of allowed keys
|
||||
* @return array Modified result
|
||||
*/
|
||||
protected function setLanguageValueLevelValues(array $result, $fieldName, $allowedKeys)
|
||||
{
|
||||
$valueArray = [];
|
||||
if (isset($result['databaseRow'][$fieldName]['data']) && is_array($result['databaseRow'][$fieldName]['data'])) {
|
||||
$valueArray = $result['databaseRow'][$fieldName]['data'];
|
||||
}
|
||||
foreach ($valueArray as $sheetName => $sheetLanguages) {
|
||||
if (!is_array($sheetLanguages)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($sheetLanguages as $languageName => $languageFields) {
|
||||
if (!is_array($languageFields)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($languageFields as $flexFieldName => $fieldValues) {
|
||||
if (!is_array($fieldValues)) {
|
||||
continue;
|
||||
}
|
||||
$allowedSingleValues = [];
|
||||
foreach ($fieldValues as $fieldValueName => $fieldValueValue) {
|
||||
if (is_array($fieldValueValue) && $fieldValueName === 'el') {
|
||||
// A section container
|
||||
foreach ($fieldValueValue as $sectionNumber => $sectionElementArray) {
|
||||
if (is_array($sectionElementArray)) {
|
||||
$allowedSingleValues['el'][$sectionNumber] = [];
|
||||
foreach ($sectionElementArray as $sectionElementName => $containerElementArray) {
|
||||
if (isset($containerElementArray['el']) && is_array($containerElementArray['el']) && !empty($containerElementArray['el'])) {
|
||||
foreach ($containerElementArray['el'] as $aContainerElementName => $aContainerElementValues) {
|
||||
if (is_array($aContainerElementValues)) {
|
||||
foreach ($aContainerElementValues as $aContainerElementValueKey => $aContainerElementValueValue) {
|
||||
if (array_key_exists($aContainerElementValueKey, $allowedKeys)) {
|
||||
$allowedSingleValues['el'][$sectionNumber][$sectionElementName]
|
||||
['el'][$aContainerElementName][$aContainerElementValueKey] = $aContainerElementValueValue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$allowedSingleValues['el'][$sectionNumber][$sectionElementName]['el']
|
||||
[$aContainerElementName] = $aContainerElementValues;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$allowedSingleValues['el'][$sectionNumber][$sectionElementName] = $containerElementArray;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$allowedSingleValues = $sectionElementArray;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// "normal" value field
|
||||
if (array_key_exists($fieldValueName, $allowedKeys)) {
|
||||
$allowedSingleValues[$fieldValueName] = $fieldValueValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
$result['databaseRow'][$fieldName]['data'][$sheetName][$languageName][$flexFieldName] = $allowedSingleValues;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BackendUserAuthentication
|
||||
*/
|
||||
protected function getBackendUser()
|
||||
{
|
||||
return $GLOBALS['BE_USER'];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user