00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 1999-2008 Kasper Skaarhoj (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 * Standard functions available for the TYPO3 backend. 00029 * You are encouraged to use this class in your own applications (Backend Modules) 00030 * 00031 * Call ALL methods without making an object! 00032 * Eg. to get a page-record 51 do this: 't3lib_BEfunc::getRecord('pages',51)' 00033 * 00034 * $Id: class.t3lib_befunc.php 4486 2008-11-25 08:51:53Z steffenk $ 00035 * Usage counts are based on search 22/2 2003 through whole backend source of typo3/ 00036 * Revised for TYPO3 3.6 July/2003 by Kasper Skaarhoj 00037 * XHTML compliant 00038 * 00039 * @author Kasper Skaarhoj <kasperYYYY@typo3.com> 00040 */ 00041 /** 00042 * [CLASS/FUNCTION INDEX of SCRIPT] 00043 * 00044 * 00045 * 00046 * 185: class t3lib_BEfunc 00047 * 00048 * SECTION: SQL-related, selecting records, searching 00049 * 206: function deleteClause($table,$tableAlias='') 00050 * 230: function getRecord($table,$uid,$fields='*',$where='',$useDeleteClause=true) 00051 * 253: function getRecordWSOL($table,$uid,$fields='*',$where='',$useDeleteClause=true) 00052 * 286: function getRecordRaw($table,$where='',$fields='*') 00053 * 309: function getRecordsByField($theTable,$theField,$theValue,$whereClause='',$groupBy='',$orderBy='',$limit='',$useDeleteClause=true) 00054 * 342: function searchQuery($searchWords,$fields,$table='') 00055 * 357: function listQuery($field,$value) 00056 * 369: function splitTable_Uid($str) 00057 * 384: function getSQLselectableList($in_list,$tablename,$default_tablename) 00058 * 412: function BEenableFields($table,$inv=0) 00059 * 00060 * SECTION: SQL-related, DEPRECATED functions 00061 * 476: function mm_query($select,$local_table,$mm_table,$foreign_table,$whereClause='',$groupBy='',$orderBy='',$limit='') 00062 * 498: function DBcompileInsert($table,$fields_values) 00063 * 512: function DBcompileUpdate($table,$where,$fields_values) 00064 * 00065 * SECTION: Page tree, TCA related 00066 * 542: function BEgetRootLine($uid,$clause='',$workspaceOL=FALSE) 00067 * 598: function openPageTree($pid,$clearExpansion) 00068 * 643: function getRecordPath($uid, $clause, $titleLimit, $fullTitleLimit=0) 00069 * 686: function getExcludeFields() 00070 * 716: function getExplicitAuthFieldValues() 00071 * 787: function getSystemLanguages() 00072 * 812: function readPageAccess($id,$perms_clause) 00073 * 843: function getTCAtypes($table,$rec,$useFieldNameAsKey=0) 00074 * 896: function getTCAtypeValue($table,$rec) 00075 * 919: function getSpecConfParts($str, $defaultExtras) 00076 * 950: function getSpecConfParametersFromArray($pArr) 00077 * 978: function getFlexFormDS($conf,$row,$table,$fieldName='',$WSOL=TRUE) 00078 * 00079 * SECTION: Caching related 00080 * 1105: function storeHash($hash,$data,$ident) 00081 * 1125: function getHash($hash) 00082 * 00083 * SECTION: TypoScript related 00084 * 1161: function getPagesTSconfig($id,$rootLine='',$returnPartArray=0) 00085 * 1217: function updatePagesTSconfig($id,$pageTS,$TSconfPrefix,$impParams='') 00086 * 1272: function implodeTSParams($p,$k='') 00087 * 00088 * SECTION: Users / Groups related 00089 * 1309: function getUserNames($fields='username,usergroup,usergroup_cached_list,uid',$where='') 00090 * 1327: function getGroupNames($fields='title,uid', $where='') 00091 * 1344: function getListGroupNames($fields='title,uid') 00092 * 1363: function blindUserNames($usernames,$groupArray,$excludeBlindedFlag=0) 00093 * 1396: function blindGroupNames($groups,$groupArray,$excludeBlindedFlag=0) 00094 * 00095 * SECTION: Output related 00096 * 1437: function daysUntil($tstamp) 00097 * 1449: function date($tstamp) 00098 * 1460: function datetime($value) 00099 * 1472: function time($value) 00100 * 1488: function calcAge($seconds,$labels = 'min|hrs|days|yrs') 00101 * 1514: function dateTimeAge($tstamp,$prefix=1,$date='') 00102 * 1532: function titleAttrib($content='',$hsc=0) 00103 * 1545: function titleAltAttrib($content) 00104 * 1569: function thumbCode($row,$table,$field,$backPath,$thumbScript='',$uploaddir=NULL,$abs=0,$tparams='',$size='') 00105 * 1637: function getThumbNail($thumbScript,$theFile,$tparams='',$size='') 00106 * 1654: function titleAttribForPages($row,$perms_clause='',$includeAttrib=1) 00107 * 1716: function getRecordIconAltText($row,$table='pages') 00108 * 1758: function getLabelFromItemlist($table,$col,$key) 00109 * 1784: function getItemLabel($table,$col,$printAllWrap='') 00110 * 1809: function getRecordTitle($table,$row,$prep=0) 00111 * 1847: function getProcessedValue($table,$col,$value,$fixed_lgd_chars=0,$defaultPassthrough=0,$noRecordLookup=FALSE,$uid=0) 00112 * 2009: function getProcessedValueExtra($table,$fN,$fV,$fixed_lgd_chars=0,$uid=0) 00113 * 2033: function getFileIcon($ext) 00114 * 2047: function getCommonSelectFields($table,$prefix='') 00115 * 2090: function makeConfigForm($configArray,$defaults,$dataPrefix) 00116 * 00117 * SECTION: Backend Modules API functions 00118 * 2165: function helpTextIcon($table,$field,$BACK_PATH,$force=0) 00119 * 2187: function helpText($table,$field,$BACK_PATH,$styleAttrib='') 00120 * 2239: function cshItem($table,$field,$BACK_PATH,$wrap='',$onlyIconMode=FALSE, $styleAttrib='') 00121 * 2277: function editOnClick($params,$backPath='',$requestUri='') 00122 * 2296: function viewOnClick($id,$backPath='',$rootLine='',$anchor='',$altUrl='',$addGetVars='',$switchFocus=TRUE) 00123 * 2328: function getModTSconfig($id,$TSref) 00124 * 2349: function getFuncMenu($mainParams,$elementName,$currentValue,$menuItems,$script='',$addparams='') 00125 * 2392: function getFuncCheck($mainParams,$elementName,$currentValue,$script='',$addparams='',$tagParams='') 00126 * 2417: function getFuncInput($mainParams,$elementName,$currentValue,$size=10,$script="",$addparams="") 00127 * 2438: function unsetMenuItems($modTSconfig,$itemArray,$TSref) 00128 * 2461: function getSetUpdateSignal($set='') 00129 * 2512: function getModuleData($MOD_MENU, $CHANGED_SETTINGS, $modName, $type='', $dontValidateList='', $setDefaultList='') 00130 * 00131 * SECTION: Core 00132 * 2585: function compilePreviewKeyword($getVarsStr, $beUserUid, $ttl=172800) 00133 * 2613: function lockRecords($table='',$uid=0,$pid=0) 00134 * 2642: function isRecordLocked($table,$uid) 00135 * 2682: function exec_foreign_table_where_query($fieldValue,$field='',$TSconfig=array(),$prefix='') 00136 * 2763: function getTCEFORM_TSconfig($table,$row) 00137 * 2814: function getTSconfig_pidValue($table,$uid,$pid) 00138 * 2844: function getPidForModTSconfig($table,$uid,$pid) 00139 * 2860: function getTSCpid($table,$uid,$pid) 00140 * 2876: function firstDomainRecord($rootLine) 00141 * 2898: function getDomainStartPage($domain, $path='') 00142 * 2928: function RTEsetup($RTEprop,$table,$field,$type='') 00143 * 2947: function &RTEgetObj() 00144 * 2986: function &softRefParserObj($spKey) 00145 * 3018: function explodeSoftRefParserList($parserList) 00146 * 3050: function isModuleSetInTBE_MODULES($modName) 00147 * 3073: function referenceCount($table,$ref,$msg='') 00148 * 00149 * SECTION: Workspaces / Versioning 00150 * 3132: function selectVersionsOfRecord($table, $uid, $fields='*', $workspace=0) 00151 * 3180: function fixVersioningPid($table,&$rr,$ignoreWorkspaceMatch=FALSE) 00152 * 3220: function workspaceOL($table,&$row,$wsid=-99) 00153 * 3268: function getWorkspaceVersionOfRecord($workspace, $table, $uid, $fields='*') 00154 * 3297: function getLiveVersionOfRecord($table,$uid,$fields='*') 00155 * 3319: function isPidInVersionizedBranch($pid, $table='',$returnStage=FALSE) 00156 * 3342: function versioningPlaceholderClause($table) 00157 * 3356: function countVersionsOfRecordsOnPage($workspace,$pageId, $allTables=FALSE) 00158 * 3391: function wsMapId($table,$uid) 00159 * 00160 * SECTION: Miscellaneous 00161 * 3421: function typo3PrintError($header,$text,$js='',$head=1) 00162 * 3465: function TYPO3_copyRightNotice() 00163 * 3489: function displayWarningMessages() 00164 * 3546: function getPathType_web_nonweb($path) 00165 * 3558: function ADMCMD_previewCmds($pageinfo) 00166 * 3580: function processParams($params) 00167 * 3606: function getListOfBackendModules($name,$perms_clause,$backPath='',$script='index.php') 00168 * 00169 * TOTAL FUNCTIONS: 99 00170 * (This index is automatically created/updated by the extension "extdeveval") 00171 * 00172 */ 00173 00174 require_once (PATH_t3lib.'class.t3lib_loaddbgroup.php'); 00175 00176 00177 /** 00178 * Standard functions available for the TYPO3 backend. 00179 * Don't instantiate - call functions with "t3lib_BEfunc::" prefixed the function name. 00180 * 00181 * @author Kasper Skaarhoj <kasperYYYY@typo3.com> 00182 * @package TYPO3 00183 * @subpackage t3lib 00184 */ 00185 final class t3lib_BEfunc { 00186 00187 00188 00189 /******************************************* 00190 * 00191 * SQL-related, selecting records, searching 00192 * 00193 *******************************************/ 00194 00195 00196 /** 00197 * Returns the WHERE clause " AND NOT [tablename].[deleted-field]" if a deleted-field is configured in $TCA for the tablename, $table 00198 * This function should ALWAYS be called in the backend for selection on tables which are configured in TCA since it will ensure consistent selection of records, even if they are marked deleted (in which case the system must always treat them as non-existent!) 00199 * In the frontend a function, ->enableFields(), is known to filter hidden-field, start- and endtime and fe_groups as well. But that is a job of the frontend, not the backend. If you need filtering on those fields as well in the backend you can use ->BEenableFields() though. 00200 * Usage: 71 00201 * 00202 * @param string Table name present in $TCA 00203 * @param string Table alias if any 00204 * @return string WHERE clause for filtering out deleted records, eg " AND tablename.deleted=0" 00205 */ 00206 public static function deleteClause($table,$tableAlias = '') { 00207 global $TCA; 00208 if ($TCA[$table]['ctrl']['delete']) { 00209 return ' AND '.($tableAlias ? $tableAlias : $table).'.'.$TCA[$table]['ctrl']['delete'].'=0'; 00210 } else { 00211 return ''; 00212 } 00213 } 00214 00215 /** 00216 * Gets record with uid = $uid from $table 00217 * You can set $field to a list of fields (default is '*') 00218 * Additional WHERE clauses can be added by $where (fx. ' AND blabla = 1') 00219 * Will automatically check if records has been deleted and if so, not return anything. 00220 * $table must be found in $TCA 00221 * Usage: 99 00222 * 00223 * @param string Table name present in $TCA 00224 * @param integer UID of record 00225 * @param string List of fields to select 00226 * @param string Additional WHERE clause, eg. " AND blablabla = 0" 00227 * @param boolean Use the deleteClause to check if a record is deleted (default true) 00228 * @return array Returns the row if found, otherwise nothing 00229 */ 00230 public static function getRecord($table, $uid, $fields = '*', $where = '', $useDeleteClause = true) { 00231 if ($GLOBALS['TCA'][$table]) { 00232 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 00233 $fields, 00234 $table, 00235 'uid='.intval($uid).($useDeleteClause ? t3lib_BEfunc::deleteClause($table) : '').$where 00236 ); 00237 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); 00238 $GLOBALS['TYPO3_DB']->sql_free_result($res); 00239 if ($row) { 00240 return $row; 00241 } 00242 } 00243 } 00244 00245 /** 00246 * Like getRecord(), but overlays workspace version if any. 00247 * 00248 * @param string Table name present in $TCA 00249 * @param integer UID of record 00250 * @param string List of fields to select 00251 * @param string Additional WHERE clause, eg. " AND blablabla = 0" 00252 * @param boolean Use the deleteClause to check if a record is deleted (default true) 00253 * @return array Returns the row if found, otherwise nothing 00254 */ 00255 public static function getRecordWSOL($table, $uid, $fields = '*', $where = '', $useDeleteClause = true) { 00256 if ($fields !== '*') { 00257 $internalFields = t3lib_div::uniqueList($fields.',uid,pid'.($table == 'pages' ? ',t3ver_swapmode' : '')); 00258 $row = t3lib_BEfunc::getRecord($table, $uid, $internalFields, $where, $useDeleteClause); 00259 t3lib_BEfunc::workspaceOL($table, $row); 00260 00261 if (is_array ($row)) { 00262 foreach (array_keys($row) as $key) { 00263 if (!t3lib_div::inList($fields, $key) && $key{0} !== '_') { 00264 unset ($row[$key]); 00265 } 00266 } 00267 } 00268 } else { 00269 $row = t3lib_BEfunc::getRecord($table, $uid, $fields, $where); 00270 t3lib_BEfunc::workspaceOL($table, $row); 00271 } 00272 return $row; 00273 } 00274 00275 /** 00276 * Returns the first record found from $table with $where as WHERE clause 00277 * This function does NOT check if a record has the deleted flag set. 00278 * $table does NOT need to be configured in $TCA 00279 * The query used is simply this: 00280 * $query = 'SELECT '.$fields.' FROM '.$table.' WHERE '.$where; 00281 * Usage: 5 (ext: sys_todos) 00282 * 00283 * @param string Table name (not necessarily in TCA) 00284 * @param string WHERE clause 00285 * @param string $fields is a list of fields to select, default is '*' 00286 * @return array First row found, if any, FALSE otherwise 00287 */ 00288 public static function getRecordRaw($table, $where = '', $fields = '*') { 00289 $row = FALSE; 00290 if (FALSE !== ($res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fields, $table, $where, '', '', '1'))) { 00291 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); 00292 $GLOBALS['TYPO3_DB']->sql_free_result($res); 00293 } 00294 return $row; 00295 } 00296 00297 /** 00298 * Returns records from table, $theTable, where a field ($theField) equals the value, $theValue 00299 * The records are returned in an array 00300 * If no records were selected, the function returns nothing 00301 * Usage: 8 00302 * 00303 * @param string Table name present in $TCA 00304 * @param string Field to select on 00305 * @param string Value that $theField must match 00306 * @param string Optional additional WHERE clauses put in the end of the query. DO NOT PUT IN GROUP BY, ORDER BY or LIMIT! 00307 * @param string Optional GROUP BY field(s), if none, supply blank string. 00308 * @param string Optional ORDER BY field(s), if none, supply blank string. 00309 * @param string Optional LIMIT value ([begin,]max), if none, supply blank string. 00310 * @param boolean Use the deleteClause to check if a record is deleted (default true) 00311 * @return mixed Multidimensional array with selected records (if any is selected) 00312 */ 00313 public static function getRecordsByField($theTable, $theField, $theValue, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '', $useDeleteClause = true) { 00314 global $TCA; 00315 if (is_array($TCA[$theTable])) { 00316 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 00317 '*', 00318 $theTable, 00319 $theField.'='.$GLOBALS['TYPO3_DB']->fullQuoteStr($theValue, $theTable). 00320 ($useDeleteClause ? t3lib_BEfunc::deleteClause($theTable).' ' : ''). 00321 t3lib_BEfunc::versioningPlaceholderClause($theTable).' '. 00322 $whereClause, // whereClauseMightContainGroupOrderBy 00323 $groupBy, 00324 $orderBy, 00325 $limit 00326 ); 00327 $rows = array(); 00328 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 00329 $rows[] = $row; 00330 } 00331 $GLOBALS['TYPO3_DB']->sql_free_result($res); 00332 if (count($rows)) return $rows; 00333 } 00334 } 00335 00336 /** 00337 * Returns a WHERE clause which will make an AND search for the words in the $searchWords array in any of the fields in array $fields. 00338 * Usage: 0 00339 * 00340 * @param array Array of search words 00341 * @param array Array of fields 00342 * @param string Table in which we are searching (for DBAL detection of quoteStr() method) 00343 * @return string WHERE clause for search 00344 * @deprecated since TYPO3 4.0 - Use $GLOBALS['TYPO3_DB']->searchQuery() directly! 00345 */ 00346 public static function searchQuery($searchWords, $fields, $table = '') { 00347 return $GLOBALS['TYPO3_DB']->searchQuery($searchWords, $fields, $table); 00348 } 00349 00350 /** 00351 * Returns a WHERE clause that can find a value ($value) in a list field ($field) 00352 * For instance a record in the database might contain a list of numbers, "34,234,5" (with no spaces between). This query would be able to select that record based on the value "34", "234" or "5" regardless of their positioni in the list (left, middle or right). 00353 * Is nice to look up list-relations to records or files in TYPO3 database tables. 00354 * Usage: 0 00355 * 00356 * @param string Table field name 00357 * @param string Value to find in list 00358 * @return string WHERE clause for a query 00359 * @deprecated since TYPO3 4.0 - Use $GLOBALS['TYPO3_DB']->listQuery() directly! 00360 */ 00361 public static function listQuery($field, $value) { 00362 return $GLOBALS['TYPO3_DB']->listQuery($field, $value, ''); 00363 } 00364 00365 /** 00366 * Makes an backwards explode on the $str and returns an array with ($table, $uid). 00367 * Example: tt_content_45 => array('tt_content', 45) 00368 * Usage: 1 00369 * 00370 * @param string [tablename]_[uid] string to explode 00371 * @return array 00372 */ 00373 public static function splitTable_Uid($str) { 00374 list($uid, $table) = explode('_', strrev($str), 2); 00375 return array(strrev($table), strrev($uid)); 00376 } 00377 00378 /** 00379 * Returns a list of pure integers based on $in_list being a list of records with table-names prepended. 00380 * Ex: $in_list = "pages_4,tt_content_12,45" would result in a return value of "4,45" if $tablename is "pages" and $default_tablename is 'pages' as well. 00381 * Usage: 1 (t3lib_userauthgroup) 00382 * 00383 * @param string Input list 00384 * @param string Table name from which ids is returned 00385 * @param string $default_tablename denotes what table the number '45' is from (if nothing is prepended on the value) 00386 * @return string List of ids 00387 */ 00388 public static function getSQLselectableList($in_list, $tablename, $default_tablename) { 00389 $list = Array(); 00390 if ((string)trim($in_list)!='') { 00391 $tempItemArray = explode(',', trim($in_list)); 00392 while(list($key, $val) = each($tempItemArray)) { 00393 $val = strrev($val); 00394 $parts = explode('_', $val, 2); 00395 if ((string)trim($parts[0])!='') { 00396 $theID = intval(strrev($parts[0])); 00397 $theTable = trim($parts[1]) ? strrev(trim($parts[1])) : $default_tablename; 00398 if ($theTable==$tablename) {$list[] = $theID;} 00399 } 00400 } 00401 } 00402 return implode(',', $list); 00403 } 00404 00405 /** 00406 * Backend implementation of enableFields() 00407 * Notice that "fe_groups" is not selected for - only disabled, starttime and endtime. 00408 * Notice that deleted-fields are NOT filtered - you must ALSO call deleteClause in addition. 00409 * $GLOBALS["SIM_ACCESS_TIME"] is used for date. 00410 * Usage: 5 00411 * 00412 * @param string $table is the table from which to return enableFields WHERE clause. Table name must have a 'ctrl' section in $TCA. 00413 * @param boolean $inv means that the query will select all records NOT VISIBLE records (inverted selection) 00414 * @return string WHERE clause part 00415 */ 00416 public static function BEenableFields($table, $inv = 0) { 00417 $ctrl = $GLOBALS['TCA'][$table]['ctrl']; 00418 $query = array(); 00419 $invQuery = array(); 00420 if (is_array($ctrl)) { 00421 if (is_array($ctrl['enablecolumns'])) { 00422 if ($ctrl['enablecolumns']['disabled']) { 00423 $field = $table.'.'.$ctrl['enablecolumns']['disabled']; 00424 $query[] = $field.'=0'; 00425 $invQuery[] = $field.'!=0'; 00426 } 00427 if ($ctrl['enablecolumns']['starttime']) { 00428 $field = $table.'.'.$ctrl['enablecolumns']['starttime']; 00429 $query[] = '('.$field.'<='.$GLOBALS['SIM_ACCESS_TIME'].')'; 00430 $invQuery[] = '('.$field.'!=0 AND '.$field.'>'.$GLOBALS['SIM_ACCESS_TIME'].')'; 00431 } 00432 if ($ctrl['enablecolumns']['endtime']) { 00433 $field = $table.'.'.$ctrl['enablecolumns']['endtime']; 00434 $query[] = '('.$field.'=0 OR '.$field.'>'.$GLOBALS['SIM_ACCESS_TIME'].')'; 00435 $invQuery[] = '('.$field.'!=0 AND '.$field.'<='.$GLOBALS['SIM_ACCESS_TIME'].')'; 00436 } 00437 } 00438 } 00439 $outQ = ($inv ? '(' . implode(' OR ', $invQuery) . ')' : implode(' AND ', $query)); 00440 00441 return $outQ ? ' AND ' . $outQ : ''; 00442 } 00443 00444 /** 00445 * Fetches the localization for a given record. 00446 * 00447 * @param string $table: Table name present in $TCA 00448 * @param integer $uid: The uid of the record 00449 * @param integer $language: The uid of the language record in sys_language 00450 * @param string $andWhereClause: Optional additional WHERE clause (default: '') 00451 * @return mixed Multidimensional array with selected records; if none exist, false is returned 00452 */ 00453 public function getRecordLocalization($table, $uid, $language, $andWhereClause = '') { 00454 $recordLocalization = false; 00455 if (self::isTableLocalizable($table)) { 00456 $tcaCtrl = $GLOBALS['TCA'][$table]['ctrl']; 00457 $recordLocalization = t3lib_BEfunc::getRecordsByField( 00458 $table, 00459 $tcaCtrl['transOrigPointerField'], 00460 $uid, 00461 'AND '.$tcaCtrl['languageField'].'='.intval($language).($andWhereClause ? ' '.$andWhereClause : ''), 00462 '', 00463 '', 00464 '1' 00465 ); 00466 } 00467 return $recordLocalization; 00468 } 00469 00470 00471 00472 00473 00474 00475 00476 00477 00478 00479 /******************************************* 00480 * 00481 * SQL-related, DEPRECATED functions 00482 * (use t3lib_DB functions instead) 00483 * 00484 *******************************************/ 00485 00486 00487 /** 00488 * Returns a SELECT query, selecting fields ($select) from two/three tables joined 00489 * $local_table and $mm_table is mandatory. $foreign_table is optional. 00490 * The JOIN is done with [$local_table].uid <--> [$mm_table].uid_local / [$mm_table].uid_foreign <--> [$foreign_table].uid 00491 * The function is very useful for selecting MM-relations between tables adhering to the MM-format used by TCE (TYPO3 Core Engine). See the section on $TCA in Inside TYPO3 for more details. 00492 * DEPRECATED - Use $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query() instead since that will return the result pointer while this returns the query. Using this function may make your application less fitted for DBAL later. 00493 * 00494 * @param string Field list for SELECT 00495 * @param string Tablename, local table 00496 * @param string Tablename, relation table 00497 * @param string Tablename, foreign table 00498 * @param string Optional additional WHERE clauses put in the end of the query. DO NOT PUT IN GROUP BY, ORDER BY or LIMIT! 00499 * @param string Optional GROUP BY field(s), if none, supply blank string. 00500 * @param string Optional ORDER BY field(s), if none, supply blank string. 00501 * @param string Optional LIMIT value ([begin,]max), if none, supply blank string. 00502 * @return string Full SQL query 00503 * @deprecated since TYPO3 4.0 00504 * @see t3lib_DB::exec_SELECT_mm_query() 00505 */ 00506 public static function mm_query($select, $local_table, $mm_table, $foreign_table, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '') { 00507 $query = $GLOBALS['TYPO3_DB']->SELECTquery( 00508 $select, 00509 $local_table.','.$mm_table.($foreign_table?','.$foreign_table:''), 00510 $local_table.'.uid='.$mm_table.'.uid_local'.($foreign_table?' AND '.$foreign_table.'.uid='.$mm_table.'.uid_foreign':'').' '. 00511 $whereClause, // whereClauseMightContainGroupOrderBy 00512 $groupBy, 00513 $orderBy, 00514 $limit 00515 ); 00516 return $query; 00517 } 00518 00519 /** 00520 * Creates an INSERT SQL-statement for $table from the array with field/value pairs $fields_values. 00521 * DEPRECATED - $GLOBALS['TYPO3_DB']->INSERTquery() directly instead! But better yet, use $GLOBALS['TYPO3_DB']->exec_INSERTquery() 00522 * 00523 * @param string Table name 00524 * @param array Field values as key=>value pairs. 00525 * @return string Full SQL query for INSERT 00526 * @deprecated since TYPO3 4.0 00527 */ 00528 public static function DBcompileInsert($table, $fields_values) { 00529 return $GLOBALS['TYPO3_DB']->INSERTquery($table, $fields_values); 00530 } 00531 00532 /** 00533 * Creates an UPDATE SQL-statement for $table where $where-clause (typ. 'uid=...') from the array with field/value pairs $fields_values. 00534 * DEPRECATED - $GLOBALS['TYPO3_DB']->UPDATEquery() directly instead! But better yet, use $GLOBALS['TYPO3_DB']->exec_UPDATEquery() 00535 * 00536 * @param string Database tablename 00537 * @param string WHERE clause, eg. "uid=1" 00538 * @param array Field values as key=>value pairs. 00539 * @return string Full SQL query for UPDATE 00540 * @deprecated since TYPO3 4.0 00541 */ 00542 public static function DBcompileUpdate($table, $where, $fields_values) { 00543 return $GLOBALS['TYPO3_DB']->UPDATEquery($table, $where, $fields_values); 00544 } 00545 00546 00547 00548 00549 00550 00551 00552 00553 00554 00555 /******************************************* 00556 * 00557 * Page tree, TCA related 00558 * 00559 *******************************************/ 00560 00561 /** 00562 * Returns what is called the 'RootLine'. That is an array with information about the page records from a page id ($uid) and back to the root. 00563 * By default deleted pages are filtered. 00564 * This RootLine will follow the tree all the way to the root. This is opposite to another kind of root line known from the frontend where the rootline stops when a root-template is found. 00565 * Usage: 1 00566 * 00567 * @param integer Page id for which to create the root line. 00568 * @param string $clause can be used to select other criteria. It would typically be where-clauses that stops the process if we meet a page, the user has no reading access to. 00569 * @param boolean If true, version overlay is applied. This must be requested specifically because it is usually only wanted when the rootline is used for visual output while for permission checking you want the raw thing! 00570 * @return array Root line array, all the way to the page tree root (or as far as $clause allows!) 00571 */ 00572 public static function BEgetRootLine($uid, $clause = '', $workspaceOL = FALSE) { 00573 if (is_array($GLOBALS['T3_VAR']['BEgetRootLine_cache'][$uid][$clause][$workspaceOL?1:0])) { 00574 return $GLOBALS['T3_VAR']['BEgetRootLine_cache'][$uid][$clause][$workspaceOL?1:0]; 00575 } 00576 $pid = $uid; 00577 $loopCheck = 100; 00578 $theRowArray = Array(); 00579 $output = Array(); 00580 while ($uid!=0 && $loopCheck>0) { 00581 $loopCheck--; 00582 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 00583 'pid,uid,title,TSconfig,is_siteroot,storage_pid,t3ver_oid,t3ver_wsid,t3ver_state,t3ver_swapmode,t3ver_stage', 00584 'pages', 00585 'uid='.intval($uid).' '. 00586 t3lib_BEfunc::deleteClause('pages').' '. 00587 $clause // whereClauseMightContainGroupOrderBy 00588 ); 00589 if ($GLOBALS['TYPO3_DB']->sql_error()) { 00590 debug($GLOBALS['TYPO3_DB']->sql_error(), 1); 00591 } 00592 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 00593 if($workspaceOL) t3lib_BEfunc::workspaceOL('pages', $row); 00594 if (is_array($row)) { 00595 t3lib_BEfunc::fixVersioningPid('pages', $row); 00596 $uid = $row['pid']; 00597 $theRowArray[] = $row; 00598 } else break; 00599 } else { 00600 break; 00601 } 00602 $GLOBALS['TYPO3_DB']->sql_free_result($res); 00603 } 00604 if ($uid==0) {$theRowArray[] = Array('uid'=>0, 'title'=>'');} 00605 if (is_array($theRowArray)) { 00606 reset($theRowArray); 00607 $c = count($theRowArray); 00608 while(list($key, $val) = each($theRowArray)) { 00609 $c--; 00610 $output[$c]['uid'] = $val['uid']; 00611 $output[$c]['pid'] = $val['pid']; 00612 if (isset($val['_ORIG_pid'])) $output[$c]['_ORIG_pid'] = $val['_ORIG_pid']; 00613 $output[$c]['title'] = $val['title']; 00614 $output[$c]['TSconfig'] = $val['TSconfig']; 00615 $output[$c]['is_siteroot'] = $val['is_siteroot']; 00616 $output[$c]['storage_pid'] = $val['storage_pid']; 00617 $output[$c]['t3ver_oid'] = $val['t3ver_oid']; 00618 $output[$c]['t3ver_wsid'] = $val['t3ver_wsid']; 00619 $output[$c]['t3ver_state'] = $val['t3ver_state']; 00620 $output[$c]['t3ver_swapmode'] = $val['t3ver_swapmode']; 00621 $output[$c]['t3ver_stage'] = $val['t3ver_stage']; 00622 } 00623 } 00624 $GLOBALS['T3_VAR']['BEgetRootLine_cache'][$pid][$clause][$workspaceOL?1:0] = $output; 00625 00626 return $output; 00627 } 00628 00629 /** 00630 * Opens the page tree to the specified page id 00631 * 00632 * @param integer Page id. 00633 * @param boolean If set, then other open branches are closed. 00634 * @return void 00635 */ 00636 public static function openPageTree($pid, $clearExpansion) { 00637 global $BE_USER; 00638 00639 // Get current expansion data: 00640 if ($clearExpansion) { 00641 $expandedPages = array(); 00642 } else { 00643 $expandedPages = unserialize($BE_USER->uc['browseTrees']['browsePages']); 00644 } 00645 00646 // Get rootline: 00647 $rL = t3lib_BEfunc::BEgetRootLine($pid); 00648 00649 // First, find out what mount index to use (if more than one DB mount exists): 00650 $mountIndex = 0; 00651 $mountKeys = array_flip($BE_USER->returnWebmounts()); 00652 foreach($rL as $rLDat) { 00653 if (isset($mountKeys[$rLDat['uid']])) { 00654 $mountIndex = $mountKeys[$rLDat['uid']]; 00655 break; 00656 } 00657 } 00658 00659 // Traverse rootline and open paths: 00660 foreach($rL as $rLDat) { 00661 $expandedPages[$mountIndex][$rLDat['uid']] = 1; 00662 } 00663 00664 // Write back: 00665 $BE_USER->uc['browseTrees']['browsePages'] = serialize($expandedPages); 00666 $BE_USER->writeUC(); 00667 } 00668 00669 /** 00670 * Returns the path (visually) of a page $uid, fx. "/First page/Second page/Another subpage" 00671 * Each part of the path will be limited to $titleLimit characters 00672 * Deleted pages are filtered out. 00673 * Usage: 15 00674 * 00675 * @param integer Page uid for which to create record path 00676 * @param string $clause is additional where clauses, eg. " 00677 * @param integer Title limit 00678 * @param integer Title limit of Full title (typ. set to 1000 or so) 00679 * @return mixed Path of record (string) OR array with short/long title if $fullTitleLimit is set. 00680 */ 00681 public static function getRecordPath($uid, $clause, $titleLimit, $fullTitleLimit = 0) { 00682 if (!$titleLimit) { $titleLimit = 1000; } 00683 00684 $loopCheck = 100; 00685 $output = $fullOutput = '/'; 00686 while ($uid!=0 && $loopCheck>0) { 00687 $loopCheck--; 00688 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 00689 'uid,pid,title,t3ver_oid,t3ver_wsid,t3ver_swapmode', 00690 'pages', 00691 'uid='.intval($uid). 00692 t3lib_BEfunc::deleteClause('pages'). 00693 (strlen(trim($clause)) ? ' AND '.$clause : '') 00694 ); 00695 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 00696 t3lib_BEfunc::workspaceOL('pages', $row); 00697 if (is_array($row)) { 00698 t3lib_BEfunc::fixVersioningPid('pages', $row); 00699 00700 if ($row['_ORIG_pid'] && $row['t3ver_swapmode']>0) { // Branch points 00701 $output = ' [#VEP#]'.$output; // Adding visual token - Versioning Entry Point - that tells that THIS position was where the versionized branch got connected to the main tree. I will have to find a better name or something... 00702 } 00703 $uid = $row['pid']; 00704 $output = '/'.t3lib_div::fixed_lgd_cs(strip_tags($row['title']), $titleLimit).$output; 00705 if ($fullTitleLimit) $fullOutput = '/'.t3lib_div::fixed_lgd_cs(strip_tags($row['title']), $fullTitleLimit).$fullOutput; 00706 } else break; 00707 } else { 00708 break; 00709 } 00710 $GLOBALS['TYPO3_DB']->sql_free_result($res); 00711 } 00712 00713 if ($fullTitleLimit) { 00714 return array($output, $fullOutput); 00715 } else { 00716 return $output; 00717 } 00718 } 00719 00720 /** 00721 * Returns an array with the exclude-fields as defined in TCA 00722 * Used for listing the exclude-fields in be_groups forms 00723 * Usage: 2 (t3lib_tceforms + t3lib_transferdata) 00724 * 00725 * @return array Array of arrays with excludeFields (fieldname, table:fieldname) from all TCA entries 00726 */ 00727 public static function getExcludeFields() { 00728 global $TCA; 00729 // All TCA keys: 00730 $theExcludeArray = Array(); 00731 $tc_keys = array_keys($TCA); 00732 foreach($tc_keys as $table) { 00733 // Load table 00734 t3lib_div::loadTCA($table); 00735 // All field names configured: 00736 if (is_array($TCA[$table]['columns'])) { 00737 $f_keys = array_keys($TCA[$table]['columns']); 00738 foreach($f_keys as $field) { 00739 if ($TCA[$table]['columns'][$field]['exclude']) { 00740 // Get Human Readable names of fields and table: 00741 $Fname = $GLOBALS['LANG']->sl($TCA[$table]['ctrl']['title']).': '.$GLOBALS['LANG']->sl($TCA[$table]['columns'][$field]['label']); 00742 // add entry: 00743 $theExcludeArray[] = Array($Fname, $table.':'.$field); 00744 } 00745 } 00746 } 00747 } 00748 return $theExcludeArray; 00749 } 00750 00751 /** 00752 * Returns an array with explicit Allow/Deny fields. 00753 * Used for listing these field/value pairs in be_groups forms 00754 * 00755 * @return array Array with information from all of $TCA 00756 */ 00757 public static function getExplicitAuthFieldValues() { 00758 global $TCA; 00759 00760 // Initialize: 00761 $adLabel = array( 00762 'ALLOW' => $GLOBALS['LANG']->sl('LLL:EXT:lang/locallang_core.xml:labels.allow'), 00763 'DENY' => $GLOBALS['LANG']->sl('LLL:EXT:lang/locallang_core.xml:labels.deny'), 00764 ); 00765 00766 // All TCA keys: 00767 $allowDenyOptions = Array(); 00768 $tc_keys = array_keys($TCA); 00769 foreach($tc_keys as $table) { 00770 00771 // Load table 00772 t3lib_div::loadTCA($table); 00773 00774 // All field names configured: 00775 if (is_array($TCA[$table]['columns'])) { 00776 $f_keys = array_keys($TCA[$table]['columns']); 00777 foreach($f_keys as $field) { 00778 $fCfg = $TCA[$table]['columns'][$field]['config']; 00779 if ($fCfg['type']=='select' && $fCfg['authMode']) { 00780 00781 // Check for items: 00782 if (is_array($fCfg['items'])) { 00783 // Get Human Readable names of fields and table: 00784 $allowDenyOptions[$table.':'.$field]['tableFieldLabel'] = $GLOBALS['LANG']->sl($TCA[$table]['ctrl']['title']).': '.$GLOBALS['LANG']->sl($TCA[$table]['columns'][$field]['label']); 00785 00786 // Check for items: 00787 foreach($fCfg['items'] as $iVal) { 00788 if (strcmp($iVal[1], '')) { // Values '' is not controlled by this setting. 00789 00790 // Find iMode: 00791 $iMode = ''; 00792 switch((string)$fCfg['authMode']) { 00793 case 'explicitAllow': 00794 $iMode = 'ALLOW'; 00795 break; 00796 case 'explicitDeny': 00797 $iMode = 'DENY'; 00798 break; 00799 case 'individual': 00800 if (!strcmp($iVal[4], 'EXPL_ALLOW')) { 00801 $iMode = 'ALLOW'; 00802 } elseif (!strcmp($iVal[4], 'EXPL_DENY')) { 00803 $iMode = 'DENY'; 00804 } 00805 break; 00806 } 00807 00808 // Set iMode: 00809 if ($iMode) { 00810 $allowDenyOptions[$table.':'.$field]['items'][$iVal[1]] = array($iMode, $GLOBALS['LANG']->sl($iVal[0]), $adLabel[$iMode]); 00811 } 00812 } 00813 } 00814 } 00815 } 00816 } 00817 } 00818 } 00819 00820 return $allowDenyOptions; 00821 } 00822 00823 /** 00824 * Returns an array with system languages: 00825 * 00826 * @return array Array with languages 00827 */ 00828 public static function getSystemLanguages() { 00829 00830 // Initialize, add default language: 00831 $sysLanguages = array(); 00832 $sysLanguages[] = array('Default language', 0); 00833 00834 // Traverse languages 00835 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,title,flag', 'sys_language', 'pid=0'.t3lib_BEfunc::deleteClause('sys_language')); 00836 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 00837 $sysLanguages[] = array($row['title'].' ['.$row['uid'].']', $row['uid'], ($row['flag'] ? 'flags/'.$row['flag'] : '')); 00838 } 00839 $GLOBALS['TYPO3_DB']->sql_free_result($res); 00840 00841 return $sysLanguages; 00842 } 00843 00844 /** 00845 * Determines whether a table is localizable and has the languageField and transOrigPointerField set in $TCA. 00846 * 00847 * @param string $table: The table to check 00848 * @return boolean Whether a table is localizable 00849 */ 00850 public function isTableLocalizable($table) { 00851 $isLocalizable = false; 00852 if (isset($GLOBALS['TCA'][$table]['ctrl']) && is_array($GLOBALS['TCA'][$table]['ctrl'])) { 00853 $tcaCtrl = $GLOBALS['TCA'][$table]['ctrl']; 00854 $isLocalizable = (isset($tcaCtrl['languageField']) && $tcaCtrl['languageField'] && isset($tcaCtrl['transOrigPointerField']) && $tcaCtrl['transOrigPointerField']); 00855 } 00856 return $isLocalizable; 00857 } 00858 00859 /** 00860 * Returns the value of the property localizationMode in the given $config array ($TCA[<table>]['columns'][<field>]['config']). 00861 * If the table is prepared for localization and no localizationMode is set, 'select' is returned by default. 00862 * If the table is not prepared for localization or not defined at all in $TCA, false is returned. 00863 * 00864 * @param string $table: The name of the table to lookup in TCA 00865 * @param mixed $fieldOrConfig: The fieldname (string) or the configuration of the field to check (array) 00866 * @return mixed If table is localizable, the set localizationMode is returned (if property is not set, 'select' is returned by default); if table is not localizable, false is returned 00867 */ 00868 public function getInlineLocalizationMode($table, $fieldOrConfig) { 00869 $localizationMode = false; 00870 if (is_array($fieldOrConfig) && count($fieldOrConfig)) { 00871 $config = $fieldOrConfig; 00872 } elseif (is_string($fieldOrConfig) && isset($GLOBALS['TCA'][$table]['columns'][$fieldOrConfig]['config'])) { 00873 $config = $GLOBALS['TCA'][$table]['columns'][$fieldOrConfig]['config']; 00874 } 00875 if (is_array($config) && isset($config['type']) && $config['type']=='inline' && self::isTableLocalizable($table)) { 00876 $localizationMode = (isset($config['behaviour']['localizationMode']) && $config['behaviour']['localizationMode'] ? $config['behaviour']['localizationMode'] : 'select'); 00877 // The mode 'select' is not possible when child table is not localizable at all: 00878 if ($localizationMode=='select' && !self::isTableLocalizable($config['foreign_table'])) { 00879 $localizationMode = false; 00880 } 00881 } 00882 return $localizationMode; 00883 } 00884 00885 /** 00886 * Returns a page record (of page with $id) with an extra field "_thePath" set to the record path IF the WHERE clause, $perms_clause, selects the record. Thus is works as an access check that returns a page record if access was granted, otherwise not. 00887 * If $id is zero a pseudo root-page with "_thePath" set is returned IF the current BE_USER is admin. 00888 * In any case ->isInWebMount must return true for the user (regardless of $perms_clause) 00889 * Usage: 21 00890 * 00891 * @param integer Page uid for which to check read-access 00892 * @param string $perms_clause is typically a value generated with $BE_USER->getPagePermsClause(1); 00893 * @return array Returns page record if OK, otherwise false. 00894 */ 00895 public static function readPageAccess($id, $perms_clause) { 00896 if ((string)$id!='') { 00897 $id = intval($id); 00898 if (!$id) { 00899 if ($GLOBALS['BE_USER']->isAdmin()) { 00900 $path = '/'; 00901 $pageinfo['_thePath'] = $path; 00902 return $pageinfo; 00903 } 00904 } else { 00905 $pageinfo = t3lib_BEfunc::getRecord('pages', $id, '*', ($perms_clause ? ' AND '.$perms_clause : '')); 00906 if ($pageinfo['uid'] && $GLOBALS['BE_USER']->isInWebMount($id, $perms_clause)) { 00907 t3lib_BEfunc::workspaceOL('pages', $pageinfo); 00908 if (is_array($pageinfo)) { 00909 t3lib_BEfunc::fixVersioningPid('pages', $pageinfo); 00910 list($pageinfo['_thePath'], $pageinfo['_thePathFull']) = t3lib_BEfunc::getRecordPath(intval($pageinfo['uid']), $perms_clause, 15, 1000); 00911 return $pageinfo; 00912 } 00913 } 00914 } 00915 } 00916 return false; 00917 } 00918 00919 /** 00920 * Returns the "types" configuration parsed into an array for the record, $rec, from table, $table 00921 * Usage: 6 00922 * 00923 * @param string Table name (present in TCA) 00924 * @param array Record from $table 00925 * @param boolean If $useFieldNameAsKey is set, then the fieldname is associative keys in the return array, otherwise just numeric keys. 00926 * @return array 00927 */ 00928 public static function getTCAtypes($table, $rec, $useFieldNameAsKey = 0) { 00929 global $TCA; 00930 00931 t3lib_div::loadTCA($table); 00932 if ($TCA[$table]) { 00933 00934 // Get type value: 00935 $fieldValue = t3lib_BEfunc::getTCAtypeValue($table, $rec); 00936 00937 // Get typesConf 00938 $typesConf = $TCA[$table]['types'][$fieldValue]; 00939 00940 // Get fields list and traverse it 00941 $fieldList = explode(',', $typesConf['showitem']); 00942 $altFieldList = array(); 00943 00944 // Traverse fields in types config and parse the configuration into a nice array: 00945 foreach($fieldList as $k => $v) { 00946 list($pFieldName, $pAltTitle, $pPalette, $pSpec) = t3lib_div::trimExplode(';', $v); 00947 $defaultExtras = is_array($TCA[$table]['columns'][$pFieldName]) ? $TCA[$table]['columns'][$pFieldName]['defaultExtras'] : ''; 00948 $specConfParts = t3lib_BEfunc::getSpecConfParts($pSpec, $defaultExtras); 00949 00950 $fieldList[$k] = array( 00951 'field' => $pFieldName, 00952 'title' => $pAltTitle, 00953 'palette' => $pPalette, 00954 'spec' => $specConfParts, 00955 'origString' => $v 00956 ); 00957 if ($useFieldNameAsKey) { 00958 $altFieldList[$fieldList[$k]['field']] = $fieldList[$k]; 00959 } 00960 } 00961 if ($useFieldNameAsKey) { 00962 $fieldList = $altFieldList; 00963 } 00964 00965 // Return array: 00966 return $fieldList; 00967 } 00968 } 00969 00970 /** 00971 * Returns the "type" value of $rec from $table which can be used to look up the correct "types" rendering section in $TCA 00972 * If no "type" field is configured in the "ctrl"-section of the $TCA for the table, zero is used. 00973 * If zero is not an index in the "types" section of $TCA for the table, then the $fieldValue returned will default to 1 (no matter if that is an index or not) 00974 * Usage: 7 00975 * 00976 * @param string Table name present in TCA 00977 * @param array Record from $table 00978 * @return string Field value 00979 * @see getTCAtypes() 00980 */ 00981 public static function getTCAtypeValue($table, $rec) { 00982 global $TCA; 00983 00984 // If no field-value, set it to zero. If there is no type matching the field-value (which now may be zero...) test field-value '1' as default. 00985 t3lib_div::loadTCA($table); 00986 if ($TCA[$table]) { 00987 $field = $TCA[$table]['ctrl']['type']; 00988 $fieldValue = $field ? ($rec[$field] ? $rec[$field] : 0) : 0; 00989 if (!is_array($TCA[$table]['types'][$fieldValue])) $fieldValue = 1; 00990 return $fieldValue; 00991 } 00992 } 00993 00994 /** 00995 * Parses a part of the field lists in the "types"-section of $TCA arrays, namely the "special configuration" at index 3 (position 4) 00996 * Elements are splitted by ":" and within those parts, parameters are splitted by "|". 00997 * Everything is returned in an array and you should rather see it visually than listen to me anymore now... Check out example in Inside TYPO3 00998 * Usage: 5 00999 * 01000 * @param string Content from the "types" configuration of TCA (the special configuration) - see description of function 01001 * @param string The ['defaultExtras'] value from field configuration 01002 * @return array 01003 */ 01004 public static function getSpecConfParts($str, $defaultExtras) { 01005 01006 // Add defaultExtras: 01007 $specConfParts = t3lib_div::trimExplode(':', $defaultExtras.':'.$str, 1); 01008 01009 $reg = array(); 01010 if (count($specConfParts)) { 01011 foreach($specConfParts as $k2 => $v2) { 01012 unset($specConfParts[$k2]); 01013 if (ereg('(.*)\[(.*)\]', $v2, $reg)) { 01014 $specConfParts[trim($reg[1])] = array( 01015 'parameters' => t3lib_div::trimExplode('|', $reg[2], 1) 01016 ); 01017 } else { 01018 $specConfParts[trim($v2)] = 1; 01019 } 01020 } 01021 } else { 01022 $specConfParts = array(); 01023 } 01024 return $specConfParts; 01025 } 01026 01027 /** 01028 * Takes an array of "[key] = [value]" strings and returns an array with the keys set as keys pointing to the value. 01029 * Better see it in action! Find example in Inside TYPO3 01030 * Usage: 6 01031 * 01032 * @param array Array of "[key] = [value]" strings to convert. 01033 * @return array 01034 */ 01035 public static function getSpecConfParametersFromArray($pArr) { 01036 $out = array(); 01037 if (is_array($pArr)) { 01038 reset($pArr); 01039 while(list($k, $v) = each($pArr)) { 01040 $parts = explode('=', $v, 2); 01041 if (count($parts)==2) { 01042 $out[trim($parts[0])] = trim($parts[1]); 01043 } else { 01044 $out[$k] = $v; 01045 } 01046 } 01047 } 01048 return $out; 01049 } 01050 01051 /** 01052 * Finds the Data Structure for a FlexForm field 01053 * NOTE ON data structures for deleted records: This function may fail to deliver the data structure for a record for a few reasons: a) The data structure could be deleted (either with deleted-flagged or hard-deleted), b) the data structure is fetched using the ds_pointerField_searchParent in which case any deleted record on the route to the final location of the DS will make it fail. In theory, we can solve the problem in the case where records that are deleted-flagged keeps us from finding the DS - this is done at the markers ###NOTE_A### where we make sure to also select deleted records. However, we generally want the DS lookup to fail for deleted records since for the working website we expect a deleted-flagged record to be as inaccessible as one that is completely deleted from the DB. Any way we look at it, this may lead to integrity problems of the reference index and even lost files if attached. However, that is not really important considering that a single change to a data structure can instantly invalidate large amounts of the reference index which we do accept as a cost for the flexform features. Other than requiring a reference index update, deletion of/changes in data structure or the failure to look them up when completely deleting records may lead to lost files in the uploads/ folders since those are now without a proper reference. 01054 * Usage: 5 01055 * 01056 * @param array Field config array 01057 * @param array Record data 01058 * @param string The table name 01059 * @param string Optional fieldname passed to hook object 01060 * @param boolean Boolean; If set, workspace overlay is applied to records. This is correct behaviour for all presentation and export, but NOT if you want a true reflection of how things are in the live workspace. 01061 * @param integer SPECIAL CASES: Use this, if the DataStructure may come from a parent record and the INPUT row doesn't have a uid yet (hence, the pid cannot be looked up). Then it is necessary to supply a PID value to search recursively in for the DS (used from TCEmain) 01062 * @return mixed If array, the data structure was found and returned as an array. Otherwise (string) it is an error message. 01063 * @see t3lib_TCEforms::getSingleField_typeFlex() 01064 */ 01065 public static function getFlexFormDS($conf, $row, $table, $fieldName = '', $WSOL = TRUE, $newRecordPidValue = 0) { 01066 global $TYPO3_CONF_VARS; 01067 01068 // Get pointer field etc from TCA-config: 01069 $ds_pointerField = $conf['ds_pointerField']; 01070 $ds_array = $conf['ds']; 01071 $ds_tableField = $conf['ds_tableField']; 01072 $ds_searchParentField = $conf['ds_pointerField_searchParent']; 01073 01074 // Find source value: 01075 $dataStructArray = ''; 01076 if (is_array($ds_array)) { // If there is a data source array, that takes precedence 01077 // If a pointer field is set, take the value from that field in the $row array and use as key. 01078 if ($ds_pointerField) { 01079 01080 // Up to two pointer fields can be specified in a comma separated list. 01081 $pointerFields = t3lib_div::trimExplode(',', $ds_pointerField); 01082 if(count($pointerFields) == 2) { // If we have two pointer fields, the array keys should contain both field values separated by comma. The asterisk "*" catches all values. For backwards compatibility, it's also possible to specify only the value of the first defined ds_pointerField. 01083 if($ds_array[$row[$pointerFields[0]].','.$row[$pointerFields[1]]]) { // Check if we have a DS for the combination of both pointer fields values 01084 $srcPo