|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 2006-2011 Kasper Skårhøj (kasperYYYY@typo3.com) 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * A copy is found in the textfile GPL.txt and important notices to the license 00017 * from the author is found in LICENSE.txt distributed with these scripts. 00018 * 00019 * 00020 * This script is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * This copyright notice MUST APPEAR in all copies of the script! 00026 ***************************************************************/ 00027 /** 00028 * Contains functions for manipulating flex form data 00029 * 00030 * $Id: class.t3lib_flexformtools.php 10121 2011-01-18 20:15:30Z ohader $ 00031 * 00032 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00033 */ 00034 /** 00035 * [CLASS/FUNCTION INDEX of SCRIPT] 00036 * 00037 * 00038 * 00039 * 71: class t3lib_flexformtools 00040 * 105: function traverseFlexFormXMLData($table,$field,$row,&$callBackObj,$callBackMethod_value) 00041 * 203: function traverseFlexFormXMLData_recurse($dataStruct,$editData,&$PA,$path='') 00042 * 274: function getAvailableLanguages() 00043 * 00044 * SECTION: Processing functions 00045 * 323: function cleanFlexFormXML($table,$field,$row) 00046 * 347: function cleanFlexFormXML_callBackFunction($dsArr, $data, $PA, $path, &$pObj) 00047 * 00048 * SECTION: Multi purpose functions 00049 * 374: function &getArrayValueByPath($pathArray,&$array) 00050 * 403: function setArrayValueByPath($pathArray,&$array,$value) 00051 * 433: function flexArray2Xml($array, $addPrologue=FALSE) 00052 * 00053 * TOTAL FUNCTIONS: 8 00054 * (This index is automatically created/updated by the extension "extdeveval") 00055 * 00056 */ 00057 00058 00059 /** 00060 * Contains functions for manipulating flex form data 00061 * 00062 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00063 * @package TYPO3 00064 * @subpackage t3lib 00065 */ 00066 class t3lib_flexformtools { 00067 00068 var $convertCharset = FALSE; // If set, the charset of data XML is converted to system charset. 00069 var $reNumberIndexesOfSectionData = FALSE; // If set, section indexes are re-numbered before processing 00070 00071 var $traverseFlexFormXMLData_DS = array(); // Contains data structure when traversing flexform 00072 var $traverseFlexFormXMLData_Data = array(); // Contains data array when traversing flexform 00073 00074 // Options for array2xml() for flexform. This will map the weird keys from the internal array to tags that could potentially be checked with a DTD/schema 00075 var $flexArray2Xml_options = array( 00076 'parentTagMap' => array( 00077 'data' => 'sheet', 00078 'sheet' => 'language', 00079 'language' => 'field', 00080 'el' => 'field', 00081 'field' => 'value', 00082 'field:el' => 'el', 00083 'el:_IS_NUM' => 'section', 00084 'section' => 'itemType' 00085 ), 00086 'disableTypeAttrib' => 2 00087 ); 00088 00089 // Internal: 00090 /** 00091 * Reference to object called 00092 */ 00093 var $callBackObj = NULL; 00094 var $cleanFlexFormXML = array(); // Used for accumulation of clean XML 00095 00096 /** 00097 * Handler for Flex Forms 00098 * 00099 * @param string The table name of the record 00100 * @param string The field name of the flexform field to work on 00101 * @param array The record data array 00102 * @param object Object (passed by reference) in which the call back function is located 00103 * @param string Method name of call back function in object for values 00104 * @return boolean If true, error happened (error string returned) 00105 */ 00106 function traverseFlexFormXMLData($table, $field, $row, $callBackObj, $callBackMethod_value) { 00107 00108 if (!is_array($GLOBALS['TCA'][$table]) || !is_array($GLOBALS['TCA'][$table]['columns'][$field])) { 00109 return 'TCA table/field was not defined.'; 00110 } 00111 00112 $this->callBackObj = $callBackObj; 00113 00114 // Get Data Structure: 00115 $dataStructArray = t3lib_BEfunc::getFlexFormDS($GLOBALS['TCA'][$table]['columns'][$field]['config'], $row, $table); 00116 00117 // If data structure was ok, proceed: 00118 if (is_array($dataStructArray)) { 00119 00120 // Get flexform XML data: 00121 $xmlData = $row[$field]; 00122 00123 // Convert charset: 00124 if ($this->convertCharset) { 00125 $xmlHeaderAttributes = t3lib_div::xmlGetHeaderAttribs($xmlData); 00126 $storeInCharset = strtolower($xmlHeaderAttributes['encoding']); 00127 if ($storeInCharset) { 00128 $currentCharset = $GLOBALS['LANG']->charSet; 00129 $xmlData = $GLOBALS['LANG']->csConvObj->conv($xmlData, $storeInCharset, $currentCharset, 1); 00130 } 00131 } 00132 00133 $editData = t3lib_div::xml2array($xmlData); 00134 if (!is_array($editData)) { 00135 return 'Parsing error: ' . $editData; 00136 } 00137 00138 // Language settings: 00139 $langChildren = $dataStructArray['meta']['langChildren'] ? 1 : 0; 00140 $langDisabled = $dataStructArray['meta']['langDisable'] ? 1 : 0; 00141 00142 // empty or invalid <meta> 00143 if (!is_array($editData['meta'])) { 00144 $editData['meta'] = array(); 00145 } 00146 $editData['meta']['currentLangId'] = array(); 00147 $languages = $this->getAvailableLanguages(); 00148 00149 foreach ($languages as $lInfo) { 00150 $editData['meta']['currentLangId'][] = $lInfo['ISOcode']; 00151 } 00152 if (!count($editData['meta']['currentLangId'])) { 00153 $editData['meta']['currentLangId'] = array('DEF'); 00154 } 00155 $editData['meta']['currentLangId'] = array_unique($editData['meta']['currentLangId']); 00156 00157 if ($langChildren || $langDisabled) { 00158 $lKeys = array('DEF'); 00159 } else { 00160 $lKeys = $editData['meta']['currentLangId']; 00161 } 00162 00163 // Tabs sheets 00164 if (is_array($dataStructArray['sheets'])) { 00165 $sKeys = array_keys($dataStructArray['sheets']); 00166 } else { 00167 $sKeys = array('sDEF'); 00168 } 00169 00170 // Traverse languages: 00171 foreach ($lKeys as $lKey) { 00172 foreach ($sKeys as $sheet) { 00173 $sheetCfg = $dataStructArray['sheets'][$sheet]; 00174 list ($dataStruct, $sheet) = t3lib_div::resolveSheetDefInDS($dataStructArray, $sheet); 00175 00176 // Render sheet: 00177 if (is_array($dataStruct['ROOT']) && is_array($dataStruct['ROOT']['el'])) { 00178 $lang = 'l' . $lKey; // Separate language key 00179 $PA['vKeys'] = $langChildren && !$langDisabled ? $editData['meta']['currentLangId'] : array('DEF'); 00180 $PA['lKey'] = $lang; 00181 $PA['callBackMethod_value'] = $callBackMethod_value; 00182 $PA['table'] = $table; 00183 $PA['field'] = $field; 00184 $PA['uid'] = $row['uid']; 00185 00186 $this->traverseFlexFormXMLData_DS = &$dataStruct; 00187 $this->traverseFlexFormXMLData_Data = &$editData; 00188 00189 // Render flexform: 00190 $this->traverseFlexFormXMLData_recurse( 00191 $dataStruct['ROOT']['el'], 00192 $editData['data'][$sheet][$lang], 00193 $PA, 00194 'data/' . $sheet . '/' . $lang 00195 ); 00196 } else { 00197 return 'Data Structure ERROR: No ROOT element found for sheet "' . $sheet . '".'; 00198 } 00199 } 00200 } 00201 } else { 00202 return 'Data Structure ERROR: ' . $dataStructArray; 00203 } 00204 } 00205 00206 /** 00207 * Recursively traversing flexform data according to data structure and element data 00208 * 00209 * @param array (Part of) data structure array that applies to the sub section of the flexform data we are processing 00210 * @param array (Part of) edit data array, reflecting current part of data structure 00211 * @param array Additional parameters passed. 00212 * @param string Telling the "path" to the element in the flexform XML 00213 * @return array 00214 */ 00215 function traverseFlexFormXMLData_recurse($dataStruct, $editData, &$PA, $path = '') { 00216 00217 if (is_array($dataStruct)) { 00218 foreach ($dataStruct as $key => $value) { 00219 if (is_array($value)) { // The value of each entry must be an array. 00220 00221 if ($value['type'] == 'array') { 00222 if ($value['section']) { // Array (Section) traversal: 00223 00224 $cc = 0; 00225 if (is_array($editData[$key]['el'])) { 00226 00227 if ($this->reNumberIndexesOfSectionData) { 00228 $temp = array(); 00229 $c3 = 0; 00230 foreach ($editData[$key]['el'] as $v3) { 00231 $temp[++$c3] = $v3; 00232 } 00233 $editData[$key]['el'] = $temp; 00234 } 00235 00236 foreach ($editData[$key]['el'] as $k3 => $v3) { 00237 if (is_array($v3)) { 00238 $cc = $k3; 00239 $theType = key($v3); 00240 $theDat = $v3[$theType]; 00241 $newSectionEl = $value['el'][$theType]; 00242 if (is_array($newSectionEl)) { 00243 $this->traverseFlexFormXMLData_recurse( 00244 array($theType => $newSectionEl), 00245 array($theType => $theDat), 00246 $PA, 00247 $path . '/' . $key . '/el/' . $cc 00248 ); 00249 } 00250 } 00251 } 00252 } 00253 } else { // Array traversal: 00254 $this->traverseFlexFormXMLData_recurse( 00255 $value['el'], 00256 $editData[$key]['el'], 00257 $PA, 00258 $path . '/' . $key . '/el' 00259 ); 00260 } 00261 } elseif (is_array($value['TCEforms']['config'])) { // Processing a field value: 00262 00263 foreach ($PA['vKeys'] as $vKey) { 00264 $vKey = 'v' . $vKey; 00265 00266 // Call back: 00267 if ($PA['callBackMethod_value']) { 00268 $this->callBackObj->$PA['callBackMethod_value']( 00269 $value, 00270 $editData[$key][$vKey], 00271 $PA, 00272 $path . '/' . $key . '/' . $vKey, 00273 $this 00274 ); 00275 } 00276 } 00277 } 00278 } 00279 } 00280 } 00281 } 00282 00283 /** 00284 * Returns an array of available languages to use for FlexForm operations 00285 * 00286 * @return array 00287 */ 00288 function getAvailableLanguages() { 00289 $isL = t3lib_extMgm::isLoaded('static_info_tables'); 00290 00291 // Find all language records in the system: 00292 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('static_lang_isocode,title,uid', 'sys_language', 'pid=0' . t3lib_BEfunc::deleteClause('sys_language'), '', 'title'); 00293 00294 // Traverse them: 00295 $output = array(); 00296 $output[0] = array( 00297 'uid' => 0, 00298 'title' => 'Default language', 00299 'ISOcode' => 'DEF' 00300 ); 00301 00302 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 00303 $output[$row['uid']] = $row; 00304 00305 if ($isL && $row['static_lang_isocode']) { 00306 $rr = t3lib_BEfunc::getRecord('static_languages', $row['static_lang_isocode'], 'lg_iso_2'); 00307 if ($rr['lg_iso_2']) { 00308 $output[$row['uid']]['ISOcode'] = $rr['lg_iso_2']; 00309 } 00310 } 00311 00312 if (!$output[$row['uid']]['ISOcode']) { 00313 unset($output[$row['uid']]); 00314 } 00315 } 00316 return $output; 00317 } 00318 00319 00320 /*********************************** 00321 * 00322 * Processing functions 00323 * 00324 ***********************************/ 00325 00326 /** 00327 * Cleaning up FlexForm XML to hold only the values it may according to its Data Structure. Also the order of tags will follow that of the data structure. 00328 * BE CAREFUL: DO not clean records in workspaces unless IN the workspace! The Data Structure might resolve falsely on a workspace record when cleaned from Live workspace. 00329 * 00330 * @param string Table name 00331 * @param string Field name of the flex form field in which the XML is found that should be cleaned. 00332 * @param array The record 00333 * @return string Clean XML from FlexForm field 00334 */ 00335 function cleanFlexFormXML($table, $field, $row) { 00336 00337 // New structure: 00338 $this->cleanFlexFormXML = array(); 00339 00340 // Create and call iterator object: 00341 $flexObj = t3lib_div::makeInstance('t3lib_flexformtools'); 00342 $flexObj->reNumberIndexesOfSectionData = TRUE; 00343 $flexObj->traverseFlexFormXMLData($table, $field, $row, $this, 'cleanFlexFormXML_callBackFunction'); 00344 00345 return $this->flexArray2Xml($this->cleanFlexFormXML, TRUE); 00346 } 00347 00348 /** 00349 * Call back function for t3lib_flexformtools class 00350 * Basically just setting the value in a new array (thus cleaning because only values that are valid are visited!) 00351 * 00352 * @param array Data structure for the current value 00353 * @param mixed Current value 00354 * @param array Additional configuration used in calling function 00355 * @param string Path of value in DS structure 00356 * @param object Object reference to caller 00357 * @return void 00358 */ 00359 function cleanFlexFormXML_callBackFunction($dsArr, $data, $PA, $path, $pObj) { 00360 #debug(array($dsArr, $data, $PA),$path); 00361 // Just setting value in our own result array, basically replicating the structure: 00362 $pObj->setArrayValueByPath($path, $this->cleanFlexFormXML, $data); 00363 00364 // Looking if an "extension" called ".vDEFbase" is found and if so, accept that too: 00365 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['flexFormXMLincludeDiffBase']) { 00366 $vDEFbase = $pObj->getArrayValueByPath($path . '.vDEFbase', $pObj->traverseFlexFormXMLData_Data); 00367 if (isset($vDEFbase)) { 00368 $pObj->setArrayValueByPath($path . '.vDEFbase', $this->cleanFlexFormXML, $vDEFbase); 00369 } 00370 } 00371 } 00372 00373 00374 /*********************************** 00375 * 00376 * Multi purpose functions 00377 * 00378 ***********************************/ 00379 00380 /** 00381 * Get a value from a multi-dimensional array by giving a path "../../.." pointing to the element 00382 * 00383 * @param string The path pointing to the value field, eg. test/2/title to access $array['test'][2]['title'] 00384 * @param array Array to get value from. Passed by reference so the value returned can be used to change the value in the array! 00385 * @return mixed Value returned 00386 */ 00387 function &getArrayValueByPath($pathArray, &$array) { 00388 if (!is_array($pathArray)) { 00389 $pathArray = explode('/', $pathArray); 00390 } 00391 if (is_array($array)) { 00392 if (count($pathArray)) { 00393 $key = array_shift($pathArray); 00394 00395 if (isset($array[$key])) { 00396 if (!count($pathArray)) { 00397 return $array[$key]; 00398 } else { 00399 return $this->getArrayValueByPath($pathArray, $array[$key]); 00400 } 00401 } else { 00402 return NULL; 00403 } 00404 } 00405 } 00406 } 00407 00408 /** 00409 * Set a value in a multi-dimensional array by giving a path "../../.." pointing to the element 00410 * 00411 * @param string The path pointing to the value field, eg. test/2/title to access $array['test'][2]['title'] 00412 * @param array Array to set value in. Passed by reference so the value returned can be used to change the value in the array! 00413 * @param mixed Value to set 00414 * @return mixed Value returned 00415 */ 00416 function setArrayValueByPath($pathArray, &$array, $value) { 00417 if (isset($value)) { 00418 if (!is_array($pathArray)) { 00419 $pathArray = explode('/', $pathArray); 00420 } 00421 if (is_array($array)) { 00422 if (count($pathArray)) { 00423 $key = array_shift($pathArray); 00424 00425 if (!count($pathArray)) { 00426 $array[$key] = $value; 00427 return TRUE; 00428 } else { 00429 if (!isset($array[$key])) { 00430 $array[$key] = array(); 00431 } 00432 return $this->setArrayValueByPath($pathArray, $array[$key], $value); 00433 } 00434 } 00435 } 00436 } 00437 } 00438 00439 /** 00440 * Convert FlexForm data array to XML 00441 * 00442 * @param array Array to output in <T3FlexForms> XML 00443 * @param boolean If set, the XML prologue is returned as well. 00444 * @return string XML content. 00445 */ 00446 function flexArray2Xml($array, $addPrologue = FALSE) { 00447 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['flexformForceCDATA']) { 00448 $this->flexArray2Xml_options['useCDATA'] = 1; 00449 } 00450 00451 $options = $GLOBALS['TYPO3_CONF_VARS']['BE']['niceFlexFormXMLtags'] ? $this->flexArray2Xml_options : array(); 00452 $spaceInd = ($GLOBALS['TYPO3_CONF_VARS']['BE']['compactFlexFormXML'] ? -1 : 4); 00453 $output = t3lib_div::array2xml($array, '', 0, 'T3FlexForms', $spaceInd, $options); 00454 00455 if ($addPrologue) { 00456 $output = '<?xml version="1.0" encoding="' . $GLOBALS['LANG']->charSet . '" standalone="yes" ?>' . LF . $output; 00457 } 00458 00459 return $output; 00460 } 00461 } 00462 00463 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_flexformtools.php'])) { 00464 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_flexformtools.php']); 00465 } 00466 ?>
1.8.0