/** * Processing of the data value in case the field type is "flex" * MUST NOT be called in case of already INSIDE a flexform! * * @param string The field value * @param array TCA field config * @param array TCEform TSconfig for the record * @param string Table name * @param array The row * @param string Field name * @return string The processed input field value ($data) * @access private * @see renderRecord() */ function renderRecord_flexProc($data, $fieldConfig, $TSconfig, $table, $row, $field) { global $TCA; // Convert the XML data to PHP array: $currentValueArray = t3lib_div::xml2array($data); if (is_array($currentValueArray)) { // Get current value array: $dataStructArray = t3lib_BEfunc::getFlexFormDS($fieldConfig['config'], $row, $table); // Manipulate Flexform DS via TSConfig and group access lists if (is_array($dataStructArray)) { $flexFormHelper = t3lib_div::makeInstance('t3lib_TCEforms_Flexforms'); $dataStructArray = $flexFormHelper->modifyFlexFormDS($dataStructArray, $table, $field, $row, $fieldConfig); unset($flexFormHelper); } if (is_array($dataStructArray)) { $currentValueArray['data'] = $this->renderRecord_flexProc_procInData($currentValueArray['data'], $dataStructArray, array($data, $fieldConfig, $TSconfig, $table, $row, $field)); $flexObj = t3lib_div::makeInstance('t3lib_flexformtools'); $data = $flexObj->flexArray2Xml($currentValueArray, TRUE); } } return $data; }
function ajaxExpandCollapse($params, &$ajaxObj) { $this->table = trim(t3lib_div::_GP('tceFormsTable')); $this->field = trim(t3lib_div::_GP('tceFormsField')); $this->field = t3lib_div::trimExplode(',', $this->field, 1); $this->recID = trim(t3lib_div::_GP('recID')); if (intval($this->recID) == $this->recID) { $this->row = t3lib_BEfunc::getRecord($this->table, $this->recID); } if (!is_array($this->row)) { $this->row = array('uid' => $this->recID, 'CType' => $this->field[4], 'list_type' => $this->field[5]); } t3lib_div::loadTCA($this->table); if ($this->table == 'tt_content') { $flexFormArray = t3lib_BEfunc::getFlexFormDS($GLOBALS['TCA']['tt_content']['columns']['pi_flexform']['config'], $this->row, $this->table); $this->fieldConfig = $flexFormArray['sheets'][$this->field[1]]['ROOT']['el'][$this->field[0]]['TCEforms']['config']; $this->PA['itemFormElName'] = 'data[' . $this->table . '][' . $this->recID . '][pi_flexform][data][' . $this->field[1] . '][' . $this->field[2] . '][' . $this->field[0] . '][' . $this->field[3] . ']'; $this->fieldConfig['piFlexFormSheet'] = $this->field[1]; $this->fieldConfig['piFlexFormLang'] = $this->field[2]; $this->fieldConfig['piFlexFormValue'] = $this->field[3]; } else { $this->fieldConfig = $GLOBALS['TCA'][$this->table]['columns'][$this->field[0]]['config']; $this->PA['itemFormElName'] = 'data[' . $this->table . '][' . $this->recID . '][' . $this->field[0] . ']'; } $this->itemFormElName = $this->PA['itemFormElName']; $this->field = $this->field[0]; if (isset($this->fieldConfig['MM'])) { $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid_foreign', $this->fieldConfig['MM'], 'uid_local=' . $this->row['uid']); while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) { $this->selectedItems[] = $row['uid_foreign']; } } else { $this->setSelectedItems(); } $tree = $this->renderTree(); $ajaxObj->addContent('tree', $tree); }
/** * Returns the content tree (based on the data structure) for a certain page or a flexible content element. In case of a page it will contain all the references * to content elements (and some more information) and in case of a FCE, references to its sub-elements. * * @param string $table: Table which contains the (XML) data structure. Only records from table 'pages' or flexible content elements from 'tt_content' are handled * @param array $row: Record of the root element where the tree starts (Possibly overlaid with workspace content) * @param array $tt_content_elementRegister: Register of used tt_content elements, don't mess with it! (passed by reference since data is built up) * @param string $prevRecList: comma separated list of uids, used internally for recursive calls. Don't mess with it! * @return array The content tree * @access protected */ function getContentTree_element($table, $row, &$tt_content_elementRegister, $prevRecList = '') { global $TCA, $LANG; $tree = array(); $tree['el'] = array('table' => $table, 'uid' => $row['uid'], 'pid' => $row['pid'], '_ORIG_uid' => $row['_ORIG_uid'], 'title' => t3lib_div::fixed_lgd_cs(t3lib_BEfunc::getRecordTitle($table, $row), 50), 'icon' => t3lib_iconWorks::getIcon($table, $row), 'sys_language_uid' => $row['sys_language_uid'], 'l18n_parent' => $row['l18n_parent'], 'CType' => $row['CType']); if ($this->includePreviewData) { $tree['previewData'] = array('fullRow' => $row); } // If element is a Flexible Content Element (or a page) then look at the content inside: if ($table == 'pages' || $table == $this->rootTable || $table == 'tt_content' && $row['CType'] == 'templavoila_pi1') { t3lib_div::loadTCA($table); $rawDataStructureArr = t3lib_BEfunc::getFlexFormDS($TCA[$table]['columns']['tx_templavoila_flex']['config'], $row, $table); $expandedDataStructureArr = $this->ds_getExpandedDataStructure($table, $row); switch ($table) { case 'pages': $currentTemplateObject = $this->getContentTree_fetchPageTemplateObject($row); break; case 'tt_content': $currentTemplateObject = t3lib_beFunc::getRecordWSOL('tx_templavoila_tmplobj', $row['tx_templavoila_to']); break; default: $currentTemplateObject = FALSE; } if (is_array($currentTemplateObject)) { $templateMappingArr = unserialize($currentTemplateObject['templatemapping']); } $tree['ds_is_found'] = is_array($rawDataStructureArr); $tree['ds_meta'] = $rawDataStructureArr['meta']; $flexformContentArr = t3lib_div::xml2array($row['tx_templavoila_flex']); if (!is_array($flexformContentArr)) { $flexformContentArr = array(); } // Respect the currently selected language, for both concepts - with langChildren enabled and disabled: $langChildren = intval($tree['ds_meta']['langChildren']); $langDisable = intval($tree['ds_meta']['langDisable']); $lKeys = $langDisable ? array('lDEF') : ($langChildren ? array('lDEF') : $this->allSystemWebsiteLanguages['all_lKeys']); $vKeys = $langDisable ? array('vDEF') : ($langChildren ? $this->allSystemWebsiteLanguages['all_vKeys'] : array('vDEF')); // Traverse each sheet in the FlexForm Structure: foreach ($expandedDataStructureArr as $sheetKey => $sheetData) { // Add some sheet meta information: $tree['sub'][$sheetKey] = array(); $tree['contentFields'][$sheetKey] = array(); $tree['meta'][$sheetKey] = array('title' => is_array($sheetData) && $sheetData['ROOT']['TCEforms']['sheetTitle'] ? $LANG->sL($sheetData['ROOT']['TCEforms']['sheetTitle']) : '', 'description' => is_array($sheetData) && $sheetData['ROOT']['TCEforms']['sheetDescription'] ? $LANG->sL($sheetData['ROOT']['TCEforms']['sheetDescription']) : '', 'short' => is_array($sheetData) && $sheetData['ROOT']['TCEforms']['sheetShortDescr'] ? $LANG->sL($sheetData['ROOT']['TCEforms']['sheetShortDescr']) : ''); // Traverse the sheet's elements: if (is_array($sheetData) && is_array($sheetData['ROOT']['el'])) { foreach ($sheetData['ROOT']['el'] as $fieldKey => $fieldData) { // Compile preview data: if ($this->includePreviewData) { $tree['previewData']['sheets'][$sheetKey][$fieldKey] = array('TCEforms' => $fieldData['TCEforms'], 'type' => $fieldData['type'], 'section' => $fieldData['section'], 'data' => array(), 'subElements' => array(), 'isMapped' => is_array($templateMappingArr['MappingInfo']['ROOT']['el'][$fieldKey])); foreach ($lKeys as $lKey) { foreach ($vKeys as $vKey) { if (is_array($flexformContentArr['data'])) { $tree['previewData']['sheets'][$sheetKey][$fieldKey]['data'][$lKey][$vKey] = $flexformContentArr['data'][$sheetKey][$lKey][$fieldKey][$vKey]; } } if ($fieldData['type'] == 'array') { $tree['previewData']['sheets'][$sheetKey][$fieldKey]['subElements'][$lKey] = $flexformContentArr['data'][$sheetKey][$lKey][$fieldKey]['el']; } } } // If the current field points to other content elements, process them: if ($fieldData['TCEforms']['config']['type'] == 'group' && $fieldData['TCEforms']['config']['internal_type'] == 'db' && $fieldData['TCEforms']['config']['allowed'] == 'tt_content') { foreach ($lKeys as $lKey) { foreach ($vKeys as $vKey) { $listOfSubElementUids = $flexformContentArr['data'][$sheetKey][$lKey][$fieldKey][$vKey]; $tree['sub'][$sheetKey][$lKey][$fieldKey][$vKey] = $this->getContentTree_processSubContent($listOfSubElementUids, $tt_content_elementRegister, $prevRecList); $tree['sub'][$sheetKey][$lKey][$fieldKey][$vKey]['meta']['title'] = $fieldData['TCEforms']['label']; } } } elseif ($fieldData['type'] != 'array' && $fieldData['TCEforms']['config']) { // If generally there are non-container fields, register them: $tree['contentFields'][$sheetKey][] = $fieldKey; } } } } } // Add localization info for this element: $tree['localizationInfo'] = $this->getContentTree_getLocalizationInfoForElement($tree, $tt_content_elementRegister); return $tree; }
/** * Renders the header fields menu item. * It iss possible to define a list of fields (currently only from the pages table) which should appear * as a header above the content zones while editing the content of a page. This function renders those fields. * The fields to be displayed are defined in the page's datastructure. * * @param $pObj: Reference to the parent object ($this) * @return string HTML output * @access private */ function renderItem_headerFields(&$pObj) { global $LANG, $TCA; $output = ''; if ($pObj->rootElementTable != 'pages') { return ''; } t3lib_div::loadTCA('pages'); $conf = $TCA['pages']['columns']['tx_templavoila_flex']['config']; $dataStructureArr = t3lib_BEfunc::getFlexFormDS($conf, $pObj->rootElementRecord, 'pages'); if (is_array($dataStructureArr) && is_array($dataStructureArr['ROOT']['tx_templavoila']['pageModule'])) { $headerTablesAndFieldNames = t3lib_div::trimExplode(chr(10), str_replace(chr(13), '', $dataStructureArr['ROOT']['tx_templavoila']['pageModule']['displayHeaderFields']), 1); if (is_array($headerTablesAndFieldNames)) { $fieldNames = array(); $headerFieldRows = array(); $headerFields = array(); foreach ($headerTablesAndFieldNames as $tableAndFieldName) { list($table, $field) = explode('.', $tableAndFieldName); $fieldNames[$table][] = $field; $headerFields[] = array('table' => $table, 'field' => $field, 'label' => $LANG->sL(t3lib_BEfunc::getItemLabel('pages', $field)), 'value' => t3lib_BEfunc::getProcessedValue('pages', $field, $pObj->rootElementRecord[$field], 200)); } if (count($headerFields)) { foreach ($headerFields as $headerFieldArr) { if ($headerFieldArr['table'] == 'pages') { $onClick = t3lib_BEfunc::editOnClick('&edit[pages][' . $pObj->id . ']=edit&columnsOnly=' . implode(',', $fieldNames['pages']), $this->doc->backPath); $linkedValue = '<a style="text-decoration: none;" href="#" onclick="' . htmlspecialchars($onClick) . '">' . htmlspecialchars($headerFieldArr['value']) . '</a>'; $linkedLabel = '<a style="text-decoration: none;" href="#" onclick="' . htmlspecialchars($onClick) . '">' . htmlspecialchars($headerFieldArr['label']) . '</a>'; $headerFieldRows[] = ' <tr> <td class="bgColor4-20" style="width: 10%; vertical-align:top">' . $linkedLabel . '</td><td class="bgColor4" style="vertical-align:top"><em>' . $linkedValue . '</em></td> </tr> '; } } $output = ' <table border="0" cellpadding="0" cellspacing="1" width="100%" class="lrPadding"> <tr> <td colspan="2" class="bgColor4-20">' . $LANG->getLL('pagerelatedinformation') . ':</td> </tr> ' . implode('', $headerFieldRows) . ' </table> '; } } } return $output; }
/** * Processing of soft references * * @return void */ function processSoftReferences() { global $TCA; // Initialize: $inData = array(); // Traverse records: if (is_array($this->dat['header']['records'])) { foreach ($this->dat['header']['records'] as $table => $recs) { foreach ($recs as $uid => $thisRec) { // If there are soft references defined, traverse those: if (isset($TCA[$table]) && is_array($thisRec['softrefs'])) { t3lib_div::loadTCA($table); // First traversal is to collect softref configuration and split them up based on fields. This could probably also have been done with the "records" key instead of the header. $fieldsIndex = array(); foreach ($thisRec['softrefs'] as $softrefDef) { // If a substitution token is set: if ($softrefDef['field'] && is_array($softrefDef['subst']) && $softrefDef['subst']['tokenID']) { $fieldsIndex[$softrefDef['field']][$softrefDef['subst']['tokenID']] = $softrefDef; } } // The new id: $thisNewUid = t3lib_BEfunc::wsMapId($table, $this->import_mapId[$table][$uid]); // Now, if there are any fields that require substitution to be done, lets go for that: foreach ($fieldsIndex as $field => $softRefCfgs) { if (is_array($TCA[$table]['columns'][$field])) { $conf = $TCA[$table]['columns'][$field]['config']; if ($conf['type'] === 'flex') { $origRecordRow = t3lib_BEfunc::getRecord($table, $thisNewUid, '*'); // This will fetch the new row for the element (which should be updated with any references to data structures etc.) if (is_array($origRecordRow)) { // Get current data structure and value array: $dataStructArray = t3lib_BEfunc::getFlexFormDS($conf, $origRecordRow, $table); $currentValueArray = t3lib_div::xml2array($origRecordRow[$field]); // Do recursive processing of the XML data: $iteratorObj = t3lib_div::makeInstance('t3lib_TCEmain'); $iteratorObj->callBackObj = $this; $currentValueArray['data'] = $iteratorObj->checkValue_flex_procInData($currentValueArray['data'], array(), array(), $dataStructArray, array($table, $uid, $field, $softRefCfgs), 'processSoftReferences_flexFormCallBack'); // The return value is set as an array which means it will be processed by tcemain for file and DB references! if (is_array($currentValueArray['data'])) { $inData[$table][$thisNewUid][$field] = $currentValueArray; } } } else { // Get tokenizedContent string and proceed only if that is not blank: $tokenizedContent = $this->dat['records'][$table . ':' . $uid]['rels'][$field]['softrefs']['tokenizedContent']; if (strlen($tokenizedContent) && is_array($softRefCfgs)) { $inData[$table][$thisNewUid][$field] = $this->processSoftReferences_substTokens($tokenizedContent, $softRefCfgs, $table, $uid); } } } } } } } } // Now write to database: $tce = $this->getNewTCE(); $this->callHook('before_processSoftReferences', array('tce' => &$tce, 'data' => &$inData)); $tce->enableLogging = TRUE; $tce->start($inData, array()); $tce->process_datamap(); $this->callHook('after_processSoftReferences', array('tce' => &$tce)); }
/** * Processes the fields with references as registered during the copy process. This includes all FlexForm fields which had references. * * @return void */ function remapListedDBRecords() { global $TCA; if (count($this->registerDBList)) { foreach ($this->registerDBList as $table => $records) { t3lib_div::loadTCA($table); foreach ($records as $uid => $fields) { $newData = array(); $theUidToUpdate = $this->copyMappingArray_merged[$table][$uid]; $theUidToUpdate_saveTo = t3lib_BEfunc::wsMapId($table, $theUidToUpdate); foreach ($fields as $fieldName => $value) { $conf = $TCA[$table]['columns'][$fieldName]['config']; switch ($conf['type']) { case 'group': case 'select': $vArray = $this->remapListedDBRecords_procDBRefs($conf, $value, $theUidToUpdate, $table); if (is_array($vArray)) { $newData[$fieldName] = implode(',', $vArray); } break; case 'flex': if ($value == 'FlexForm_reference') { $origRecordRow = $this->recordInfo($table, $theUidToUpdate, '*'); // This will fetch the new row for the element if (is_array($origRecordRow)) { t3lib_BEfunc::workspaceOL($table, $origRecordRow); // Get current data structure and value array: $dataStructArray = t3lib_BEfunc::getFlexFormDS($conf, $origRecordRow, $table); $currentValueArray = t3lib_div::xml2array($origRecordRow[$fieldName]); // Do recursive processing of the XML data: $currentValueArray['data'] = $this->checkValue_flex_procInData($currentValueArray['data'], array(), array(), $dataStructArray, array($table, $theUidToUpdate, $fieldName), 'remapListedDBRecords_flexFormCallBack'); // The return value should be compiled back into XML, ready to insert directly in the field (as we call updateDB() directly later): if (is_array($currentValueArray['data'])) { $newData[$fieldName] = $this->checkValue_flexArray2Xml($currentValueArray, TRUE); } } } break; case 'inline': $this->remapListedDBRecords_procInline($conf, $value, $uid, $table); break; default: debug('Field type should not appear here: ' . $conf['type']); break; } } if (count($newData)) { // If any fields were changed, those fields are updated! $this->updateDB($table, $theUidToUpdate_saveTo, $newData); } } } } }
/** * This method returns the contents of the flex-field given. * * @param array The page row * @param string The field name * @return string The contents of the field */ function getPageFlexValue($page, $field) { $xml = t3lib_div::xml2array($page['tx_templavoila_flex']); $GLOBALS['TSFE']->includeTCA(); t3lib_div::loadTCA('pages'); $ds = t3lib_BEfunc::getFlexFormDS($GLOBALS['TCA']['pages']['columns']['tx_templavoila_flex']['config'], $page, 'pages', 'tx_templavoila_flex'); if (is_array($ds) && is_array($ds['meta'])) { $langChildren = intval($ds['meta']['langChildren']); $langDisable = intval($ds['meta']['langDisable']); } else { $langChildren = 0; $langDisable = 0; } $translatedLanguagesArr = $this->getAvailableLanguages($pageUid); $tryLang = $GLOBALS['TSFE']->sys_language_content; $tryLangArr = $this->languageFallback; do { if ($langArr = $translatedLanguagesArr[$tryLang]) { $lKey = $langDisable ? 'lDEF' : ($langChildren ? 'lDEF' : 'l' . $langArr['ISOcode']); $vKey = $langDisable ? 'vDEF' : ($langChildren ? 'v' . $langArr['ISOcode'] : 'vDEF'); } else { $lKey = 'lDEF'; $vKey = 'vDEF'; } $value = ''; if (is_array($xml) && is_array($xml['data']) && is_array($xml['data']['sDEF']) && is_array($xml['data']['sDEF'][$lKey])) { $value = $this->getSubKey($xml['data']['sDEF'][$lKey], t3lib_div::trimExplode(',', $field, 1), $vKey); } } while (!strlen($value) && strlen($tryLang = array_shift($tryLangArr))); return $value; }
/** * References all unreferenced elements with the specified * parent id (page uid) * * @param integer $pageUid: Parent id of the elements to reference * @return void * @access protected */ function createReferencesForPage($pageUid) { $unreferencedElementRecordsArr = $this->getUnreferencedElementsRecords($pageUid); $langField = $GLOBALS['TCA']['tt_content']['ctrl']['languageField']; foreach ($unreferencedElementRecordsArr as $elementUid => $elementRecord) { $lDef = array(); $vDef = array(); if ($langField && $elementRecord[$langField]) { $pageRec = t3lib_BEfunc::getRecordWSOL('pages', $pageUid); $xml = t3lib_BEfunc::getFlexFormDS($GLOBALS['TCA']['pages']['columns']['tx_templavoila_flex']['config'], $pageRec, 'pages', 'tx_templavoila_ds'); $langChildren = intval($xml['meta']['langChildren']); $langDisable = intval($xml['meta']['langDisable']); if ($elementRecord[$langField] == -1) { $translatedLanguagesArr = $this->getAvailableLanguages($pageUid); foreach ($translatedLanguagesArr as $lUid => $lArr) { if ($lUid >= 0) { $lDef[] = $langDisable ? 'lDEF' : ($langChildren ? 'lDEF' : 'l' . $lArr['ISOcode']); $vDef[] = $langDisable ? 'vDEF' : ($langChildren ? 'v' . $lArr['ISOcode'] : 'vDEF'); } } } elseif ($rLang = $this->allAvailableLanguages[$elementRecord[$langField]]) { $lDef[] = $langDisable ? 'lDEF' : ($langChildren ? 'lDEF' : 'l' . $rLang['ISOcode']); $vDef[] = $langDisable ? 'vDEF' : ($langChildren ? 'v' . $rLang['ISOcode'] : 'vDEF'); } else { $lDef[] = 'lDEF'; $vDef[] = 'vDEF'; } } else { $lDef[] = 'lDEF'; $vDef[] = 'vDEF'; } $contentAreaFieldName = $this->templavoilaAPIObj->ds_getFieldNameByColumnPosition($pageUid, $elementRecord['colPos']); if ($contentAreaFieldName !== FALSE) { foreach ($lDef as $iKey => $lKey) { $vKey = $vDef[$iKey]; $destinationPointer = array('table' => 'pages', 'uid' => $pageUid, 'sheet' => 'sDEF', 'sLang' => $lKey, 'field' => $contentAreaFieldName, 'vLang' => $vKey, 'position' => -1); $this->templavoilaAPIObj->referenceElementByUid($elementUid, $destinationPointer); } } } }
/** * Handler for Flex Forms * * @param string The table name of the record * @param string The field name of the flexform field to work on * @param array The record data array * @param object Object (passed by reference) in which the call back function is located * @param string Method name of call back function in object for values * @return boolean If true, error happened (error string returned) */ function traverseFlexFormXMLData($table, $field, $row, $callBackObj, $callBackMethod_value) { if (!is_array($GLOBALS['TCA'][$table]) || !is_array($GLOBALS['TCA'][$table]['columns'][$field])) { return 'TCA table/field was not defined.'; } $this->callBackObj = $callBackObj; // Get Data Structure: $dataStructArray = t3lib_BEfunc::getFlexFormDS($GLOBALS['TCA'][$table]['columns'][$field]['config'], $row, $table); // If data structure was ok, proceed: if (is_array($dataStructArray)) { // Get flexform XML data: $xmlData = $row[$field]; // Convert charset: if ($this->convertCharset) { $xmlHeaderAttributes = t3lib_div::xmlGetHeaderAttribs($xmlData); $storeInCharset = strtolower($xmlHeaderAttributes['encoding']); if ($storeInCharset) { $currentCharset = $GLOBALS['LANG']->charSet; $xmlData = $GLOBALS['LANG']->csConvObj->conv($xmlData, $storeInCharset, $currentCharset, 1); } } $editData = t3lib_div::xml2array($xmlData); if (!is_array($editData)) { return 'Parsing error: ' . $editData; } // Language settings: $langChildren = $dataStructArray['meta']['langChildren'] ? 1 : 0; $langDisabled = $dataStructArray['meta']['langDisable'] ? 1 : 0; // empty or invalid <meta> if (!is_array($editData['meta'])) { $editData['meta'] = array(); } $editData['meta']['currentLangId'] = array(); $languages = $this->getAvailableLanguages(); foreach ($languages as $lInfo) { $editData['meta']['currentLangId'][] = $lInfo['ISOcode']; } if (!count($editData['meta']['currentLangId'])) { $editData['meta']['currentLangId'] = array('DEF'); } $editData['meta']['currentLangId'] = array_unique($editData['meta']['currentLangId']); if ($langChildren || $langDisabled) { $lKeys = array('DEF'); } else { $lKeys = $editData['meta']['currentLangId']; } // Tabs sheets if (is_array($dataStructArray['sheets'])) { $sKeys = array_keys($dataStructArray['sheets']); } else { $sKeys = array('sDEF'); } // Traverse languages: foreach ($lKeys as $lKey) { foreach ($sKeys as $sheet) { $sheetCfg = $dataStructArray['sheets'][$sheet]; list($dataStruct, $sheet) = t3lib_div::resolveSheetDefInDS($dataStructArray, $sheet); // Render sheet: if (is_array($dataStruct['ROOT']) && is_array($dataStruct['ROOT']['el'])) { $lang = 'l' . $lKey; // Separate language key $PA['vKeys'] = $langChildren && !$langDisabled ? $editData['meta']['currentLangId'] : array('DEF'); $PA['lKey'] = $lang; $PA['callBackMethod_value'] = $callBackMethod_value; $PA['table'] = $table; $PA['field'] = $field; $PA['uid'] = $row['uid']; $this->traverseFlexFormXMLData_DS =& $dataStruct; $this->traverseFlexFormXMLData_Data =& $editData; // Render flexform: $this->traverseFlexFormXMLData_recurse($dataStruct['ROOT']['el'], $editData['data'][$sheet][$lang], $PA, 'data/' . $sheet . '/' . $lang); } else { return 'Data Structure ERROR: No ROOT element found for sheet "' . $sheet . '".'; } } } } else { return 'Data Structure ERROR: ' . $dataStructArray; } }
/** * Look for flexform field and add to internal translation details * * @param string $table Table name * @param array $row Table row * @return void */ function _lookForFlexFormFieldAndAddToInternalTranslationDetails($table, $row) { global $TCA; foreach ($TCA[$table]['columns'] as $field => $cfg) { $conf = $cfg['config']; // For "flex" fieldtypes we need to traverse the structure looking for file and db references of course! if ($conf['type'] == 'flex') { // We might like to add the filter that detects if record is tt_content/CType is "tx_flex...:" since otherwise we would translate flexform content that might be hidden if say the record had a DS set but was later changed back to "Text w/Image" or so... But probably this is a rare case. // Get current data structure to see if translation is needed: $dataStructArray = t3lib_BEfunc::getFlexFormDS($conf, $row, $table); $this->detailsOutput['log'][] = 'FlexForm field "' . $field . '": DataStructure status: ' . (is_array($dataStructArray) ? 'OK' : 'Error: ' . $dataStructArray); if (is_array($dataStructArray) && !$dataStructArray['meta']['langDisable']) { $this->detailsOutput['log'][] = 'FlexForm Localization enabled, type: ' . ($dataStructArray['meta']['langChildren'] ? 'Inheritance: Continue' : 'Separate: Stop'); if ($dataStructArray['meta']['langChildren']) { $currentValueArray = t3lib_div::xml2array($row[$field]); // Traversing the XML structure, processing files: if (is_array($currentValueArray)) { // Create and call iterator object: /** @var $flexObj t3lib_flexformtools */ $flexObj = t3lib_div::makeInstance('t3lib_flexformtools'); $flexObj->traverseFlexFormXMLData($table, $field, $row, $this, 'translationDetails_flexFormCallBack'); } } } else { $this->detailsOutput['log'][] = 'FlexForm Localization disabled. Nothing to do.'; } } } }
/** * Handler for Flex Forms * * @param string The table name of the record * @param string The field name which this element is supposed to edit * @param array The record data array where the value(s) for the field can be found * @param array An array with additional configuration options. * @return string The HTML code for the TCEform field */ function getSingleField_typeFlex($table, $field, $row, &$PA) { // Data Structure: $dataStructArray = t3lib_BEfunc::getFlexFormDS($PA['fieldConf']['config'], $row, $table); // Manipulate Flexform DS via TSConfig and group access lists if (is_array($dataStructArray)) { $flexFormHelper = t3lib_div::makeInstance('t3lib_TCEforms_Flexforms'); $dataStructArray = $flexFormHelper->modifyFlexFormDS($dataStructArray, $table, $field, $row, $PA['fieldConf']['config']); unset($flexFormHelper); } // Get data structure: if (is_array($dataStructArray)) { // Get data: $xmlData = $PA['itemFormElValue']; $xmlHeaderAttributes = t3lib_div::xmlGetHeaderAttribs($xmlData); $storeInCharset = strtolower($xmlHeaderAttributes['encoding']); if ($storeInCharset) { $currentCharset = $GLOBALS['LANG']->charSet; $xmlData = $GLOBALS['LANG']->csConvObj->conv($xmlData, $storeInCharset, $currentCharset, 1); } $editData = t3lib_div::xml2array($xmlData); if (!is_array($editData)) { // Must be XML parsing error... $editData = array(); } elseif (!isset($editData['meta']) || !is_array($editData['meta'])) { $editData['meta'] = array(); } // Find the data structure if sheets are found: $sheet = $editData['meta']['currentSheetId'] ? $editData['meta']['currentSheetId'] : 'sDEF'; // Sheet to display // Create sheet menu: //TODO; Why is this commented out? // if (is_array($dataStructArray['sheets'])) { // #$item.=$this->getSingleField_typeFlex_sheetMenu($dataStructArray['sheets'], $PA['itemFormElName'].'[meta][currentSheetId]', $sheet).'<br />'; // } // Create language menu: $langChildren = $dataStructArray['meta']['langChildren'] ? 1 : 0; $langDisabled = $dataStructArray['meta']['langDisable'] ? 1 : 0; $editData['meta']['currentLangId'] = array(); // Look up page overlays: $checkPageLanguageOverlay = $GLOBALS['BE_USER']->getTSConfigVal('options.checkPageLanguageOverlay') ? TRUE : FALSE; if ($checkPageLanguageOverlay) { $pageOverlays = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'pages_language_overlay', 'pid=' . intval($row['pid']) . t3lib_BEfunc::deleteClause('pages_language_overlay') . t3lib_BEfunc::versioningPlaceholderClause('pages_language_overlay'), '', '', '', 'sys_language_uid'); } $languages = $this->getAvailableLanguages(); foreach ($languages as $lInfo) { if ($GLOBALS['BE_USER']->checkLanguageAccess($lInfo['uid']) && (!$checkPageLanguageOverlay || $lInfo['uid'] <= 0 || is_array($pageOverlays[$lInfo['uid']]))) { $editData['meta']['currentLangId'][] = $lInfo['ISOcode']; } } if (!is_array($editData['meta']['currentLangId']) || !count($editData['meta']['currentLangId'])) { $editData['meta']['currentLangId'] = array('DEF'); } $editData['meta']['currentLangId'] = array_unique($editData['meta']['currentLangId']); //TODO: Why is this commented out? // if (!$langDisabled && count($languages) > 1) { // $item.=$this->getSingleField_typeFlex_langMenu($languages, $PA['itemFormElName'].'[meta][currentLangId]', $editData['meta']['currentLangId']).'<br />'; // } $PA['_noEditDEF'] = FALSE; if ($langChildren || $langDisabled) { $rotateLang = array('DEF'); } else { if (!in_array('DEF', $editData['meta']['currentLangId'])) { array_unshift($editData['meta']['currentLangId'], 'DEF'); $PA['_noEditDEF'] = TRUE; } $rotateLang = $editData['meta']['currentLangId']; } // Tabs sheets if (is_array($dataStructArray['sheets'])) { $tabsToTraverse = array_keys($dataStructArray['sheets']); } else { $tabsToTraverse = array($sheet); } foreach ($rotateLang as $lKey) { if (!$langChildren && !$langDisabled) { $item .= '<strong>' . $this->getLanguageIcon($table, $row, 'v' . $lKey) . $lKey . ':</strong>'; } $tabParts = array(); foreach ($tabsToTraverse as $sheet) { list($dataStruct, $sheet) = t3lib_div::resolveSheetDefInDS($dataStructArray, $sheet); // Render sheet: if (is_array($dataStruct['ROOT']) && is_array($dataStruct['ROOT']['el'])) { $lang = 'l' . $lKey; // Default language, other options are "lUK" or whatever country code (independant of system!!!) $PA['_valLang'] = $langChildren && !$langDisabled ? $editData['meta']['currentLangId'] : 'DEF'; // Default language, other options are "lUK" or whatever country code (independant of system!!!) $PA['_lang'] = $lang; // Assemble key for loading the correct CSH file $dsPointerFields = t3lib_div::trimExplode(',', $GLOBALS['TCA'][$table]['columns'][$field]['config']['ds_pointerField'], TRUE); $PA['_cshKey'] = $table . '.' . $field; foreach ($dsPointerFields as $key) { $PA['_cshKey'] .= '.' . $row[$key]; } // Push the sheet level tab to DynNestedStack if (is_array($dataStructArray['sheets'])) { $tabIdentString = $GLOBALS['TBE_TEMPLATE']->getDynTabMenuId('TCEFORMS:flexform:' . $PA['itemFormElName'] . $PA['_lang']); $this->pushToDynNestedStack('tab', $tabIdentString . '-' . (count($tabParts) + 1)); } // Render flexform: $tRows = $this->getSingleField_typeFlex_draw($dataStruct['ROOT']['el'], $editData['data'][$sheet][$lang], $table, $field, $row, $PA, '[data][' . $sheet . '][' . $lang . ']'); $sheetContent = '<div class="typo3-TCEforms-flexForm">' . $tRows . '</div>'; // Pop the sheet level tab from DynNestedStack if (is_array($dataStructArray['sheets'])) { $this->popFromDynNestedStack('tab', $tabIdentString . '-' . (count($tabParts) + 1)); } } else { $sheetContent = 'Data Structure ERROR: No ROOT element found for sheet "' . $sheet . '".'; } // Add to tab: $tabParts[] = array('label' => $dataStruct['ROOT']['TCEforms']['sheetTitle'] ? $this->sL($dataStruct['ROOT']['TCEforms']['sheetTitle']) : $sheet, 'description' => $dataStruct['ROOT']['TCEforms']['sheetDescription'] ? $this->sL($dataStruct['ROOT']['TCEforms']['sheetDescription']) : '', 'linkTitle' => $dataStruct['ROOT']['TCEforms']['sheetShortDescr'] ? $this->sL($dataStruct['ROOT']['TCEforms']['sheetShortDescr']) : '', 'content' => $sheetContent); } if (is_array($dataStructArray['sheets'])) { $dividersToTabsBehaviour = isset($GLOBALS['TCA'][$table]['ctrl']['dividers2tabs']) ? $GLOBALS['TCA'][$table]['ctrl']['dividers2tabs'] : 1; $item .= $this->getDynTabMenu($tabParts, 'TCEFORMS:flexform:' . $PA['itemFormElName'] . $PA['_lang'], $dividersToTabsBehaviour); } else { $item .= $sheetContent; } } } else { $item = 'Data Structure ERROR: ' . $dataStructArray; } return $item; }
/** * Using the checkRecordUpdateAccess hook to grant access to flexfields if the user * make the attempt to update a reference list within a flex field * * @see http://bugs.typo3.org/view.php?id=485 * * @param string $table * @param integer $id * @param array $data * @param boolean $res * @param object $pObj * @return mixed - "1" if we grant access and "false" if we can't decide whether to give access or not */ function checkRecordUpdateAccess($table, $id, $data, $res, &$pObj) { global $TCA; // Only perform additional checks if not admin and just for pages table. if (($table=='pages') && is_array($data) && !$pObj->admin) { $res = 1; foreach ($data as $field => $value) { if (in_array($table.'-'.$field, $pObj->exclude_array) || $pObj->data_disableFields[$table][$id][$field]) { continue; } // we're not inserting useful data - can't make a decission if(!is_array($data[$field]['data'])) { $res = false; break; } // we're not inserting operating on an flex field - can't make a decission if (!is_array($TCA[$table]['columns'][$field]['config']) || $TCA[$table]['columns'][$field]['config']['type'] != 'flex') { $res = false; break; } // get the field-information and check if only "ce" fields are updated $conf = $TCA[$table]['columns'][$field]['config']; $currentRecord = t3lib_BEfunc::getRecord($table, $id); $dataStructArray = t3lib_BEfunc::getFlexFormDS($conf, $currentRecord, $table, $field, true); foreach ($data[$field]['data'] as $sheet => $sheetData) { if (!is_array($sheetData) || !is_array($dataStructArray['ROOT']['el'])) { $res = false; break; } foreach ($sheetData as $lDef => $lData) { if (!is_array($lData)) { $res = false; break; } foreach ($lData as $fieldName => $fieldData) { if (!isset($dataStructArray['ROOT']['el'][$fieldName])) { $res = false; break; } $fieldConf = $dataStructArray['ROOT']['el'][$fieldName]; if ($fieldConf['tx_templavoila']['eType'] != 'ce') { $res = false; break; } } } } } if (($res==1) && !$pObj->doesRecordExist($table, $id, 'editcontent')) { $res = false; } } return $res; }
/** * Handler for Flex Forms * * @param string The table name of the record * @param string The field name which this element is supposed to edit * @param array The record data array where the value(s) for the field can be found * @param array An array with additional configuration options. * @return string The HTML code for the TCEform field */ function getSingleField_typeFlex($table, $field, $row, &$PA) { // Data Structure: $dataStructArray = t3lib_BEfunc::getFlexFormDS($PA['fieldConf']['config'], $row, $table); // Get data structure: if (is_array($dataStructArray)) { // Get data: $xmlData = $PA['itemFormElValue']; $xmlHeaderAttributes = t3lib_div::xmlGetHeaderAttribs($xmlData); $storeInCharset = strtolower($xmlHeaderAttributes['encoding']); if ($storeInCharset) { $currentCharset = $GLOBALS['LANG']->charSet; $xmlData = $GLOBALS['LANG']->csConvObj->conv($xmlData, $storeInCharset, $currentCharset, 1); } $editData = t3lib_div::xml2array($xmlData); if (!is_array($editData)) { // Must be XML parsing error... $editData = array(); } elseif (!isset($editData['meta']) || !is_array($editData['meta'])) { $editData['meta'] = array(); } // Find the data structure if sheets are found: $sheet = $editData['meta']['currentSheetId'] ? $editData['meta']['currentSheetId'] : 'sDEF'; // Sheet to display // Create sheet menu: // if (is_array($dataStructArray['sheets'])) { // #$item.=$this->getSingleField_typeFlex_sheetMenu($dataStructArray['sheets'], $PA['itemFormElName'].'[meta][currentSheetId]', $sheet).'<br />'; // } // Create language menu: $langChildren = $dataStructArray['meta']['langChildren'] ? 1 : 0; $langDisabled = $dataStructArray['meta']['langDisable'] ? 1 : 0; $editData['meta']['currentLangId'] = array(); // Look up page overlays: $checkPageLanguageOverlay = $GLOBALS['BE_USER']->getTSConfigVal('options.checkPageLanguageOverlay') ? TRUE : FALSE; if ($checkPageLanguageOverlay) { $pageOverlays = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'pages_language_overlay', 'pid=' . intval($row['pid']) . t3lib_BEfunc::deleteClause('pages_language_overlay') . t3lib_BEfunc::versioningPlaceholderClause('pages_language_overlay'), '', '', '', 'sys_language_uid'); } $languages = $this->getAvailableLanguages(); foreach ($languages as $lInfo) { if ($GLOBALS['BE_USER']->checkLanguageAccess($lInfo['uid']) && (!$checkPageLanguageOverlay || $lInfo['uid'] <= 0 || is_array($pageOverlays[$lInfo['uid']]))) { $editData['meta']['currentLangId'][] = $lInfo['ISOcode']; } } if (!is_array($editData['meta']['currentLangId']) || !count($editData['meta']['currentLangId'])) { $editData['meta']['currentLangId'] = array('DEF'); } $editData['meta']['currentLangId'] = array_unique($editData['meta']['currentLangId']); // if (!$langDisabled && count($languages) > 1) { // $item.=$this->getSingleField_typeFlex_langMenu($languages, $PA['itemFormElName'].'[meta][currentLangId]', $editData['meta']['currentLangId']).'<br />'; // } $PA['_noEditDEF'] = FALSE; if ($langChildren || $langDisabled) { $rotateLang = array('DEF'); } else { if (!in_array('DEF', $editData['meta']['currentLangId'])) { array_unshift($editData['meta']['currentLangId'], 'DEF'); $PA['_noEditDEF'] = TRUE; } $rotateLang = $editData['meta']['currentLangId']; } // Tabs sheets if (is_array($dataStructArray['sheets'])) { $tabsToTraverse = array_keys($dataStructArray['sheets']); } else { $tabsToTraverse = array($sheet); } foreach ($rotateLang as $lKey) { if (!$langChildren && !$langDisabled) { $item .= '<strong>' . $this->getLanguageIcon($table, $row, 'v' . $lKey) . $lKey . ':</strong>'; } $tabParts = array(); foreach ($tabsToTraverse as $sheet) { list($dataStruct, $sheet) = t3lib_div::resolveSheetDefInDS($dataStructArray, $sheet); // Render sheet: if (is_array($dataStruct['ROOT']) && is_array($dataStruct['ROOT']['el'])) { $lang = 'l' . $lKey; // Default language, other options are "lUK" or whatever country code (independant of system!!!) $PA['_valLang'] = $langChildren && !$langDisabled ? $editData['meta']['currentLangId'] : 'DEF'; // Default language, other options are "lUK" or whatever country code (independant of system!!!) $PA['_lang'] = $lang; $PA['_cshFile'] = isset($dataStruct['ROOT']['TCEforms']) && isset($dataStruct['ROOT']['TCEforms']['cshFile']) ? $dataStruct['ROOT']['TCEforms']['cshFile'] : ''; // Render flexform: $tRows = $this->getSingleField_typeFlex_draw($dataStruct['ROOT']['el'], $editData['data'][$sheet][$lang], $table, $field, $row, $PA, '[data][' . $sheet . '][' . $lang . ']'); #$sheetContent= '<table border="0" cellpadding="1" cellspacing="1" class="typo3-TCEforms-flexForm">'.implode('',$tRows).'</table>'; $sheetContent = '<div class="typo3-TCEforms-flexForm">' . $tRows . '</div>'; # $item = '<div style=" position:absolute;">'.$item.'</div>'; //visibility:hidden; } else { $sheetContent = 'Data Structure ERROR: No ROOT element found for sheet "' . $sheet . '".'; } // Add to tab: $tabParts[] = array('label' => $dataStruct['ROOT']['TCEforms']['sheetTitle'] ? $this->sL($dataStruct['ROOT']['TCEforms']['sheetTitle']) : $sheet, 'description' => $dataStruct['ROOT']['TCEforms']['sheetDescription'] ? $this->sL($dataStruct['ROOT']['TCEforms']['sheetDescription']) : '', 'linkTitle' => $dataStruct['ROOT']['TCEforms']['sheetShortDescr'] ? $this->sL($dataStruct['ROOT']['TCEforms']['sheetShortDescr']) : '', 'content' => $sheetContent); } if (is_array($dataStructArray['sheets'])) { $dividersToTabsBehaviour = isset($GLOBALS['TCA'][$table]['ctrl']['dividers2tabs']) ? $GLOBALS['TCA'][$table]['ctrl']['dividers2tabs'] : 1; $item .= $this->getDynTabMenu($tabParts, 'TCEFORMS:flexform:' . $PA['itemFormElName'] . $PA['_lang'], $dividersToTabsBehaviour); } else { $item .= $sheetContent; } } } else { $item = 'Data Structure ERROR: ' . $dataStructArray; } return $item; }
/** * Processing of the data value in case the field type is "flex" * MUST NOT be called in case of already INSIDE a flexform! * * @param string The field value * @param array TCA field config * @param array TCEform TSconfig for the record * @param string Table name * @param array The row * @param string Field name * @return string The processed input field value ($data) * @access private * @see renderRecord() */ function renderRecord_flexProc($data, $fieldConfig, $TSconfig, $table, $row, $field) { global $TCA; // Convert the XML data to PHP array: $currentValueArray = t3lib_div::xml2array($data); if (is_array($currentValueArray)) { // Get current value array: $dataStructArray = t3lib_BEfunc::getFlexFormDS($fieldConfig['config'], $row, $table); if (is_array($dataStructArray)) { $currentValueArray['data'] = $this->renderRecord_flexProc_procInData($currentValueArray['data'], $dataStructArray, array($data, $fieldConfig, $TSconfig, $table, $row, $field)); $flexObj = t3lib_div::makeInstance('t3lib_flexformtools'); $data = $flexObj->flexArray2Xml($currentValueArray, TRUE); } } return $data; }
/** * Returns relation information for a $table/$row-array * Traverses all fields in input row which are configured in TCA/columns * It looks for hard relations to files and records in the TCA types "select" and "group" * * @param string Table name * @param array Row from table * @param string Specific field to fetch for. * @return array Array with information about relations * @see export_addRecord() */ function getRelations($table, $row, $onlyField = '') { global $TCA; // Load full table description t3lib_div::loadTCA($table); // Initialize: $uid = $row['uid']; $nonFields = explode(',', 'uid,perms_userid,perms_groupid,perms_user,perms_group,perms_everybody,pid'); $outRow = array(); foreach ($row as $field => $value) { if (!in_array($field, $nonFields) && is_array($TCA[$table]['columns'][$field]) && (!$onlyField || $onlyField === $field)) { $conf = $TCA[$table]['columns'][$field]['config']; // Add files if ($result = $this->getRelations_procFiles($value, $conf, $uid)) { // Creates an entry for the field with all the files: $outRow[$field] = array('type' => 'file', 'newValueFiles' => $result); } // Add DB: if ($result = $this->getRelations_procDB($value, $conf, $uid, $table)) { // Create an entry for the field with all DB relations: $outRow[$field] = array('type' => 'db', 'itemArray' => $result); } // For "flex" fieldtypes we need to traverse the structure looking for file and db references of course! if ($conf['type'] == 'flex') { // Get current value array: // NOTICE: failure to resolve Data Structures can lead to integrity problems with the reference index. Please look up the note in the JavaDoc documentation for the function t3lib_BEfunc::getFlexFormDS() $dataStructArray = t3lib_BEfunc::getFlexFormDS($conf, $row, $table, '', $this->WSOL); $currentValueArray = t3lib_div::xml2array($value); // Traversing the XML structure, processing files: if (is_array($currentValueArray)) { $this->temp_flexRelations = array('db' => array(), 'file' => array(), 'softrefs' => array()); // Create and call iterator object: $flexObj = t3lib_div::makeInstance('t3lib_flexformtools'); $flexObj->traverseFlexFormXMLData($table, $field, $row, $this, 'getRelations_flexFormCallBack'); // Create an entry for the field: $outRow[$field] = array('type' => 'flex', 'flexFormRels' => $this->temp_flexRelations); } } // Soft References: if (strlen($value) && ($softRefs = t3lib_BEfunc::explodeSoftRefParserList($conf['softref']))) { $softRefValue = $value; foreach ($softRefs as $spKey => $spParams) { $softRefObj = t3lib_BEfunc::softRefParserObj($spKey); if (is_object($softRefObj)) { $resultArray = $softRefObj->findRef($table, $field, $uid, $softRefValue, $spKey, $spParams); if (is_array($resultArray)) { $outRow[$field]['softrefs']['keys'][$spKey] = $resultArray['elements']; if (strlen($resultArray['content'])) { $softRefValue = $resultArray['content']; } } } } if (is_array($outRow[$field]['softrefs']) && count($outRow[$field]['softrefs']) && strcmp($value, $softRefValue) && strstr($softRefValue, '{softref:')) { $outRow[$field]['softrefs']['tokenizedContent'] = $softRefValue; } } } } return $outRow; }