* Implemented additional, simple API for logging to sys_log plus extended the sys...
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_befunc.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Standard functions available for the TYPO3 backend.
29 * You are encouraged to use this class in your own applications (Backend Modules)
30 *
31 * Call ALL methods without making an object!
32 * Eg. to get a page-record 51 do this: 't3lib_BEfunc::getRecord('pages',51)'
33 *
34 * $Id$
35 * Usage counts are based on search 22/2 2003 through whole backend source of typo3/
36 * Revised for TYPO3 3.6 July/2003 by Kasper Skaarhoj
37 * XHTML compliant
38 *
39 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
40 */
41 /**
42 * [CLASS/FUNCTION INDEX of SCRIPT]
43 *
44 *
45 *
46 * 176: class t3lib_BEfunc
47 *
48 * SECTION: SQL-related, selecting records, searching
49 * 197: function deleteClause($table,$tableAlias='')
50 * 220: function getRecord($table,$uid,$fields='*',$where='')
51 * 242: function getRecordRaw($table,$where='',$fields='*')
52 * 264: function getRecordsByField($theTable,$theField,$theValue,$whereClause='',$groupBy='',$orderBy='',$limit='')
53 * 296: function searchQuery($searchWords,$fields,$table='')
54 * 311: function listQuery($field,$value)
55 * 323: function splitTable_Uid($str)
56 * 338: function getSQLselectableList($in_list,$tablename,$default_tablename)
57 * 366: function BEenableFields($table,$inv=0)
58 *
59 * SECTION: SQL-related, DEPRECIATED functions
60 * 430: function mm_query($select,$local_table,$mm_table,$foreign_table,$whereClause='',$groupBy='',$orderBy='',$limit='')
61 * 452: function DBcompileInsert($table,$fields_values)
62 * 466: function DBcompileUpdate($table,$where,$fields_values)
63 *
64 * SECTION: Page tree, TCA related
65 * 495: function BEgetRootLine($uid,$clause='')
66 * 547: function openPageTree($pid,$clearExpansion)
67 * 592: function getRecordPath($uid, $clause, $titleLimit, $fullTitleLimit=0)
68 * 635: function getExcludeFields()
69 * 665: function getExplicitAuthFieldValues()
70 * 736: function getSystemLanguages()
71 * 761: function readPageAccess($id,$perms_clause)
72 * 790: function getTCAtypes($table,$rec,$useFieldNameAsKey=0)
73 * 843: function getTCAtypeValue($table,$rec)
74 * 866: function getSpecConfParts($str, $defaultExtras)
75 * 896: function getSpecConfParametersFromArray($pArr)
76 * 923: function getFlexFormDS($conf,$row,$table, $fieldName = '')
77 *
78 * SECTION: Caching related
79 * 1043: function storeHash($hash,$data,$ident)
80 * 1063: function getHash($hash,$expTime=0)
81 *
82 * SECTION: TypoScript related
83 * 1099: function getPagesTSconfig($id,$rootLine='',$returnPartArray=0)
84 * 1150: function updatePagesTSconfig($id,$pageTS,$TSconfPrefix,$impParams='')
85 * 1205: function implodeTSParams($p,$k='')
86 *
87 * SECTION: Users / Groups related
88 * 1242: function getUserNames($fields='username,usergroup,usergroup_cached_list,uid',$where='')
89 * 1260: function getGroupNames($fields='title,uid', $where='')
90 * 1277: function getListGroupNames($fields='title,uid')
91 * 1296: function blindUserNames($usernames,$groupArray,$excludeBlindedFlag=0)
92 * 1329: function blindGroupNames($groups,$groupArray,$excludeBlindedFlag=0)
93 *
94 * SECTION: Output related
95 * 1370: function daysUntil($tstamp)
96 * 1382: function date($tstamp)
97 * 1393: function datetime($value)
98 * 1405: function time($value)
99 * 1421: function calcAge($seconds,$labels = 'min|hrs|days|yrs')
100 * 1447: function dateTimeAge($tstamp,$prefix=1,$date='')
101 * 1465: function titleAttrib($content='',$hsc=0)
102 * 1478: function titleAltAttrib($content)
103 * 1502: function thumbCode($row,$table,$field,$backPath,$thumbScript='',$uploaddir=NULL,$abs=0,$tparams='',$size='')
104 * 1571: function getThumbNail($thumbScript,$theFile,$tparams='',$size='')
105 * 1588: function titleAttribForPages($row,$perms_clause='',$includeAttrib=1)
106 * 1647: function getRecordIconAltText($row,$table='pages')
107 * 1684: function getLabelFromItemlist($table,$col,$key)
108 * 1710: function getItemLabel($table,$col,$printAllWrap='')
109 * 1735: function getRecordTitle($table,$row,$prep=0)
110 * 1773: function getProcessedValue($table,$col,$value,$fixed_lgd_chars=0,$defaultPassthrough=0,$noRecordLookup=FALSE,$uid=0)
111 * 1894: function getProcessedValueExtra($table,$fN,$fV,$fixed_lgd_chars=0,$uid=0)
112 * 1918: function getFileIcon($ext)
113 * 1932: function getCommonSelectFields($table,$prefix)
114 * 1974: function makeConfigForm($configArray,$defaults,$dataPrefix)
115 *
116 * SECTION: Backend Modules API functions
117 * 2049: function helpTextIcon($table,$field,$BACK_PATH,$force=0)
118 * 2071: function helpText($table,$field,$BACK_PATH,$styleAttrib='')
119 * 2123: function cshItem($table,$field,$BACK_PATH,$wrap='',$onlyIconMode=FALSE, $styleAttrib='')
120 * 2161: function editOnClick($params,$backPath='',$requestUri='')
121 * 2180: function viewOnClick($id,$backPath='',$rootLine='',$anchor='',$altUrl='',$addGetVars='',$switchFocus=TRUE)
122 * 2207: function getModTSconfig($id,$TSref)
123 * 2228: function getFuncMenu($mainParams,$elementName,$currentValue,$menuItems,$script='',$addparams='')
124 * 2271: function getFuncCheck($mainParams,$elementName,$currentValue,$script='',$addparams='',$tagParams='')
125 * 2296: function getFuncInput($mainParams,$elementName,$currentValue,$size=10,$script="",$addparams="")
126 * 2317: function unsetMenuItems($modTSconfig,$itemArray,$TSref)
127 * 2340: function getSetUpdateSignal($set='')
128 * 2391: function getModuleData($MOD_MENU, $CHANGED_SETTINGS, $modName, $type='', $dontValidateList='', $setDefaultList='')
129 *
130 * SECTION: Core
131 * 2464: function lockRecords($table='',$uid=0,$pid=0)
132 * 2493: function isRecordLocked($table,$uid)
133 * 2533: function exec_foreign_table_where_query($fieldValue,$field='',$TSconfig=array(),$prefix='')
134 * 2614: function getTCEFORM_TSconfig($table,$row)
135 * 2664: function getTSconfig_pidValue($table,$uid,$pid)
136 * 2692: function getPidForModTSconfig($table,$uid,$pid)
137 * 2708: function getTSCpid($table,$uid,$pid)
138 * 2724: function firstDomainRecord($rootLine)
139 * 2746: function getDomainStartPage($domain, $path='')
140 * 2776: function RTEsetup($RTEprop,$table,$field,$type='')
141 * 2795: function &RTEgetObj()
142 * 2834: function &softRefParserObj($spKey)
143 * 2866: function explodeSoftRefParserList($parserList, $table, $field)
144 * 2898: function isModuleSetInTBE_MODULES($modName)
145 *
146 * SECTION: Workspaces / Versioning
147 * 2942: function selectVersionsOfRecord($table, $uid, $fields='*', $workspace=0)
148 * 2986: function fixVersioningPid($table,&$rr)
149 * 3018: function workspaceOL($table,&$row,$wsid=-99)
150 * 3062: function getWorkspaceVersionOfRecord($workspace, $table, $uid, $fields='*')
151 * 3087: function isPidInVersionizedBranch($pid)
152 *
153 * SECTION: Miscellaneous
154 * 3120: function typo3PrintError($header,$text,$js='',$head=1)
155 * 3164: function TYPO3_copyRightNotice()
156 * 3188: function displayWarningMessages()
157 * 3230: function getPathType_web_nonweb($path)
158 * 3242: function ADMCMD_previewCmds($pageinfo)
159 * 3264: function processParams($params)
160 * 3290: function getListOfBackendModules($name,$perms_clause,$backPath='',$script='index.php')
161 *
162 * TOTAL FUNCTIONS: 92
163 * (This index is automatically created/updated by the extension "extdeveval")
164 *
165 */
166
167
168 /**
169 * Standard functions available for the TYPO3 backend.
170 * Don't instantiate - call functions with "t3lib_BEfunc::" prefixed the function name.
171 *
172 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
173 * @package TYPO3
174 * @subpackage t3lib
175 */
176 class t3lib_BEfunc {
177
178
179
180 /*******************************************
181 *
182 * SQL-related, selecting records, searching
183 *
184 *******************************************/
185
186
187 /**
188 * Returns the WHERE clause " AND NOT [tablename].[deleted-field]" if a deleted-field is configured in $TCA for the tablename, $table
189 * 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!)
190 * 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.
191 * Usage: 71
192 *
193 * @param string Table name present in $TCA
194 * @param string Table alias if any
195 * @return string WHERE clause for filtering out deleted records, eg " AND tablename.deleted=0"
196 */
197 function deleteClause($table,$tableAlias='') {
198 global $TCA;
199 if ($TCA[$table]['ctrl']['delete']) {
200 return ' AND '.($tableAlias ? $tableAlias : $table).'.'.$TCA[$table]['ctrl']['delete'].'=0';
201 } else {
202 return '';
203 }
204 }
205
206 /**
207 * Gets record with uid=$uid from $table
208 * You can set $field to a list of fields (default is '*')
209 * Additional WHERE clauses can be added by $where (fx. ' AND blabla=1')
210 * Will automatically check if records has been deleted and if so, not return anything.
211 * $table must be found in $TCA
212 * Usage: 99
213 *
214 * @param string Table name present in $TCA
215 * @param integer UID of record
216 * @param string List of fields to select
217 * @param string Additional WHERE clause, eg. " AND blablabla=0"
218 * @return array Returns the row if found, otherwise nothing
219 */
220 function getRecord($table,$uid,$fields='*',$where='') {
221 if ($GLOBALS['TCA'][$table]) {
222 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fields, $table, 'uid='.intval($uid).t3lib_BEfunc::deleteClause($table).$where);
223 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
224 return $row;
225 }
226 }
227 }
228
229 /**
230 * Like getRecord(), but overlays workspace version if any.
231 *
232 * @param string Table name present in $TCA
233 * @param integer UID of record
234 * @param string List of fields to select
235 * @param string Additional WHERE clause, eg. " AND blablabla=0"
236 * @return array Returns the row if found, otherwise nothing
237 */
238 function getRecordWSOL($table,$uid,$fields='*',$where='') {
239 $row = t3lib_BEfunc::getRecord($table,$uid,$fields,$where);
240 t3lib_BEfunc::workspaceOL($table,$row);
241 return $row;
242 }
243
244 /**
245 * Returns the first record found from $table with $where as WHERE clause
246 * This function does NOT check if a record has the deleted flag set.
247 * $table does NOT need to be configured in $TCA
248 * The query used is simply this:
249 * $query='SELECT '.$fields.' FROM '.$table.' WHERE '.$where;
250 * Usage: 5 (ext: sys_todos)
251 *
252 * @param string Table name (not necessarily in TCA)
253 * @param string WHERE clause
254 * @param string $fields is a list of fields to select, default is '*'
255 * @return array First row found, if any
256 */
257 function getRecordRaw($table,$where='',$fields='*') {
258 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fields, $table, $where);
259 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
260 return $row;
261 }
262 }
263
264 /**
265 * Returns records from table, $theTable, where a field ($theField) equals the value, $theValue
266 * The records are returned in an array
267 * If no records were selected, the function returns nothing
268 * Usage: 8
269 *
270 * @param string Table name present in $TCA
271 * @param string Field to select on
272 * @param string Value that $theField must match
273 * @param string Optional additional WHERE clauses put in the end of the query. DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
274 * @param string Optional GROUP BY field(s), if none, supply blank string.
275 * @param string Optional ORDER BY field(s), if none, supply blank string.
276 * @param string Optional LIMIT value ([begin,]max), if none, supply blank string.
277 * @return mixed Multidimensional array with selected records (if any is selected)
278 */
279 function getRecordsByField($theTable,$theField,$theValue,$whereClause='',$groupBy='',$orderBy='',$limit='') {
280 global $TCA;
281 if (is_array($TCA[$theTable])) {
282 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
283 '*',
284 $theTable,
285 $theField.'='.$GLOBALS['TYPO3_DB']->fullQuoteStr($theValue, $theTable).
286 t3lib_BEfunc::deleteClause($theTable).' '.
287 $whereClause, // whereClauseMightContainGroupOrderBy
288 $groupBy,
289 $orderBy,
290 $limit
291 );
292 $rows = array();
293 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
294 $rows[] = $row;
295 }
296 $GLOBALS['TYPO3_DB']->sql_free_result($res);
297 if (count($rows)) return $rows;
298 }
299 }
300
301 /**
302 * 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.
303 * Usage: 0
304 *
305 * @param array Array of search words
306 * @param array Array of fields
307 * @param string Table in which we are searching (for DBAL detection of quoteStr() method)
308 * @return string WHERE clause for search
309 * @depreciated Use $GLOBALS['TYPO3_DB']->searchQuery() directly!
310 */
311 function searchQuery($searchWords,$fields,$table='') {
312 return $GLOBALS['TYPO3_DB']->searchQuery($searchWords,$fields,$table);
313 }
314
315 /**
316 * Returns a WHERE clause that can find a value ($value) in a list field ($field)
317 * 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).
318 * Is nice to look up list-relations to records or files in TYPO3 database tables.
319 * Usage: 0
320 *
321 * @param string Table field name
322 * @param string Value to find in list
323 * @return string WHERE clause for a query
324 * @depreciated Use $GLOBALS['TYPO3_DB']->listQuery() directly!
325 */
326 function listQuery($field,$value) {
327 return $GLOBALS['TYPO3_DB']->listQuery($field,$value,'');
328 }
329
330 /**
331 * Makes an backwards explode on the $str and returns an array with ($table,$uid).
332 * Example: tt_content_45 => array('tt_content',45)
333 * Usage: 1
334 *
335 * @param string [tablename]_[uid] string to explode
336 * @return array
337 */
338 function splitTable_Uid($str) {
339 list($uid,$table) = explode('_',strrev($str),2);
340 return array(strrev($table),strrev($uid));
341 }
342
343 /**
344 * Returns a list of pure integers based on $in_list being a list of records with table-names prepended.
345 * 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.
346 * Usage: 1 (t3lib_userauthgroup)
347 *
348 * @param string Input list
349 * @param string Table name from which ids is returned
350 * @param string $default_tablename denotes what table the number '45' is from (if nothing is prepended on the value)
351 * @return string List of ids
352 */
353 function getSQLselectableList($in_list,$tablename,$default_tablename) {
354 $list = Array();
355 if ((string)trim($in_list)!='') {
356 $tempItemArray = explode(',',trim($in_list));
357 while(list($key,$val)=each($tempItemArray)) {
358 $val = strrev($val);
359 $parts = explode('_',$val,2);
360 if ((string)trim($parts[0])!='') {
361 $theID = intval(strrev($parts[0]));
362 $theTable = trim($parts[1]) ? strrev(trim($parts[1])) : $default_tablename;
363 if ($theTable==$tablename) {$list[]=$theID;}
364 }
365 }
366 }
367 return implode(',',$list);
368 }
369
370 /**
371 * Backend implementation of enableFields()
372 * Notice that "fe_groups" is not selected for - only disabled, starttime and endtime.
373 * Notice that deleted-fields are NOT filtered - you must ALSO call deleteClause in addition.
374 * $GLOBALS["SIM_EXEC_TIME"] is used for date.
375 * Usage: 5
376 *
377 * @param string $table is the table from which to return enableFields WHERE clause. Table name must have a 'ctrl' section in $TCA.
378 * @param boolean $inv means that the query will select all records NOT VISIBLE records (inverted selection)
379 * @return string WHERE clause part
380 */
381 function BEenableFields($table,$inv=0) {
382 $ctrl = $GLOBALS['TCA'][$table]['ctrl'];
383 $query=array();
384 $invQuery=array();
385 if (is_array($ctrl)) {
386 if (is_array($ctrl['enablecolumns'])) {
387 if ($ctrl['enablecolumns']['disabled']) {
388 $field = $table.'.'.$ctrl['enablecolumns']['disabled'];
389 $query[]=$field.'=0';
390 $invQuery[]=$field.'!=0';
391 }
392 if ($ctrl['enablecolumns']['starttime']) {
393 $field = $table.'.'.$ctrl['enablecolumns']['starttime'];
394 $query[]='('.$field.'<='.$GLOBALS['SIM_EXEC_TIME'].')';
395 $invQuery[]='('.$field.'!=0 AND '.$field.'>'.$GLOBALS['SIM_EXEC_TIME'].')';
396 }
397 if ($ctrl['enablecolumns']['endtime']) {
398 $field = $table.'.'.$ctrl['enablecolumns']['endtime'];
399 $query[]='('.$field.'=0 OR '.$field.'>'.$GLOBALS['SIM_EXEC_TIME'].')';
400 $invQuery[]='('.$field.'!=0 AND '.$field.'<='.$GLOBALS['SIM_EXEC_TIME'].')';
401 }
402 }
403 }
404 $outQ = ' AND '.($inv ? '('.implode(' OR ',$invQuery).')' : implode(' AND ',$query));
405
406 return $outQ;
407 }
408
409
410
411
412
413
414
415
416
417
418 /*******************************************
419 *
420 * SQL-related, DEPRECIATED functions
421 * (use t3lib_DB functions instead)
422 *
423 *******************************************/
424
425
426 /**
427 * Returns a SELECT query, selecting fields ($select) from two/three tables joined
428 * $local_table and $mm_table is mandatory. $foreign_table is optional.
429 * The JOIN is done with [$local_table].uid <--> [$mm_table].uid_local / [$mm_table].uid_foreign <--> [$foreign_table].uid
430 * 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.
431 * DEPRECIATED - 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.
432 *
433 * @param string Field list for SELECT
434 * @param string Tablename, local table
435 * @param string Tablename, relation table
436 * @param string Tablename, foreign table
437 * @param string Optional additional WHERE clauses put in the end of the query. DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
438 * @param string Optional GROUP BY field(s), if none, supply blank string.
439 * @param string Optional ORDER BY field(s), if none, supply blank string.
440 * @param string Optional LIMIT value ([begin,]max), if none, supply blank string.
441 * @return string Full SQL query
442 * @depreciated
443 * @see t3lib_DB::exec_SELECT_mm_query()
444 */
445 function mm_query($select,$local_table,$mm_table,$foreign_table,$whereClause='',$groupBy='',$orderBy='',$limit='') {
446 $query = $GLOBALS['TYPO3_DB']->SELECTquery(
447 $select,
448 $local_table.','.$mm_table.($foreign_table?','.$foreign_table:''),
449 $local_table.'.uid='.$mm_table.'.uid_local'.($foreign_table?' AND '.$foreign_table.'.uid='.$mm_table.'.uid_foreign':'').' '.
450 $whereClause, // whereClauseMightContainGroupOrderBy
451 $groupBy,
452 $orderBy,
453 $limit
454 );
455 return $query;
456 }
457
458 /**
459 * Creates an INSERT SQL-statement for $table from the array with field/value pairs $fields_values.
460 * DEPRECIATED - $GLOBALS['TYPO3_DB']->INSERTquery() directly instead! But better yet, use $GLOBALS['TYPO3_DB']->exec_INSERTquery()
461 *
462 * @param string Table name
463 * @param array Field values as key=>value pairs.
464 * @return string Full SQL query for INSERT
465 * @depreciated
466 */
467 function DBcompileInsert($table,$fields_values) {
468 return $GLOBALS['TYPO3_DB']->INSERTquery($table, $fields_values);
469 }
470
471 /**
472 * Creates an UPDATE SQL-statement for $table where $where-clause (typ. 'uid=...') from the array with field/value pairs $fields_values.
473 * DEPRECIATED - $GLOBALS['TYPO3_DB']->UPDATEquery() directly instead! But better yet, use $GLOBALS['TYPO3_DB']->exec_UPDATEquery()
474 *
475 * @param string Database tablename
476 * @param string WHERE clause, eg. "uid=1"
477 * @param array Field values as key=>value pairs.
478 * @return string Full SQL query for UPDATE
479 * @depreciated
480 */
481 function DBcompileUpdate($table,$where,$fields_values) {
482 return $GLOBALS['TYPO3_DB']->UPDATEquery($table, $where, $fields_values);
483 }
484
485
486
487
488
489
490
491
492
493
494 /*******************************************
495 *
496 * Page tree, TCA related
497 *
498 *******************************************/
499
500 /**
501 * 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.
502 * By default deleted pages are filtered.
503 * 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.
504 * Usage: 1
505 *
506 * @param integer Page id for which to create the root line.
507 * @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.
508 * @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!
509 * @return array Root line array, all the way to the page tree root (or as far as $clause allows!)
510 */
511 function BEgetRootLine($uid,$clause='',$workspaceOL=FALSE) {
512 $loopCheck = 100;
513 $theRowArray = Array();
514 $output = Array();
515 while ($uid!=0 && $loopCheck>0) {
516 $loopCheck--;
517 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
518 'pid,uid,title,TSconfig,is_siteroot,storage_pid,t3ver_oid,t3ver_wsid,t3ver_state,t3ver_swapmode,t3ver_stage',
519 'pages',
520 'uid='.intval($uid).' '.
521 t3lib_BEfunc::deleteClause('pages').' '.
522 $clause // whereClauseMightContainGroupOrderBy
523 );
524 if ($GLOBALS['TYPO3_DB']->sql_error()) {
525 debug($GLOBALS['TYPO3_DB']->sql_error(),1);
526 }
527 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
528 if($workspaceOL) t3lib_BEfunc::workspaceOL('pages',$row);
529 t3lib_BEfunc::fixVersioningPid('pages',$row);
530 $uid = $row['pid'];
531 $theRowArray[] = $row;
532 } else {
533 break;
534 }
535 }
536 if ($uid==0) {$theRowArray[] = Array('uid'=>0,'title'=>'');}
537 if (is_array($theRowArray)) {
538 reset($theRowArray);
539 $c=count($theRowArray);
540 while(list($key,$val)=each($theRowArray)) {
541 $c--;
542 $output[$c]['uid'] = $val['uid'];
543 $output[$c]['pid'] = $val['pid'];
544 if (isset($val['_ORIG_pid'])) $output[$c]['_ORIG_pid'] = $val['_ORIG_pid'];
545 $output[$c]['title'] = $val['title'];
546 $output[$c]['TSconfig'] = $val['TSconfig'];
547 $output[$c]['is_siteroot'] = $val['is_siteroot'];
548 $output[$c]['storage_pid'] = $val['storage_pid'];
549 $output[$c]['t3ver_oid'] = $val['t3ver_oid'];
550 $output[$c]['t3ver_wsid'] = $val['t3ver_wsid'];
551 $output[$c]['t3ver_state'] = $val['t3ver_state'];
552 $output[$c]['t3ver_swapmode'] = $val['t3ver_swapmode'];
553 $output[$c]['t3ver_stage'] = $val['t3ver_stage'];
554 }
555 }
556
557 return $output;
558 }
559
560 /**
561 * Opens the page tree to the specified page id
562 *
563 * @param integer Page id.
564 * @param boolean If set, then other open branches are closed.
565 * @return void
566 */
567 function openPageTree($pid,$clearExpansion) {
568 global $BE_USER;
569
570 // Get current expansion data:
571 if ($clearExpansion) {
572 $expandedPages = array();
573 } else {
574 $expandedPages = unserialize($BE_USER->uc['browseTrees']['browsePages']);
575 }
576
577 // Get rootline:
578 $rL = t3lib_BEfunc::BEgetRootLine($pid);
579
580 // First, find out what mount index to use (if more than one DB mount exists):
581 $mountIndex = 0;
582 $mountKeys = array_flip($BE_USER->returnWebmounts());
583 foreach($rL as $rLDat) {
584 if (isset($mountKeys[$rLDat['uid']])) {
585 $mountIndex = $mountKeys[$rLDat['uid']];
586 break;
587 }
588 }
589
590 // Traverse rootline and open paths:
591 foreach($rL as $rLDat) {
592 $expandedPages[$mountIndex][$rLDat['uid']] = 1;
593 }
594
595 // Write back:
596 $BE_USER->uc['browseTrees']['browsePages'] = serialize($expandedPages);
597 $BE_USER->writeUC();
598 }
599
600 /**
601 * Returns the path (visually) of a page $uid, fx. "/First page/Second page/Another subpage"
602 * Each part of the path will be limited to $titleLimit characters
603 * Deleted pages are filtered out.
604 * Usage: 15
605 *
606 * @param integer Page uid for which to create record path
607 * @param string $clause is additional where clauses, eg. "
608 * @param integer Title limit
609 * @param integer Title limit of Full title (typ. set to 1000 or so)
610 * @return mixed Path of record (string) OR array with short/long title if $fullTitleLimit is set.
611 */
612 function getRecordPath($uid, $clause, $titleLimit, $fullTitleLimit=0) {
613 if (!$titleLimit) { $titleLimit=1000; }
614
615 $loopCheck = 100;
616 $output = $fullOutput = '/';
617 while ($uid!=0 && $loopCheck>0) {
618 $loopCheck--;
619 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
620 'uid,pid,title,t3ver_oid,t3ver_wsid,t3ver_swapmode',
621 'pages',
622 'uid='.intval($uid).
623 t3lib_BEfunc::deleteClause('pages').
624 (strlen(trim($clause)) ? ' AND '.$clause : '')
625 );
626 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
627 t3lib_BEfunc::workspaceOL('pages',$row);
628 t3lib_BEfunc::fixVersioningPid('pages',$row);
629
630 if ($row['_ORIG_pid'] && $row['t3ver_swapmode']>0) { // Branch points
631 $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...
632 }
633 $uid = $row['pid'];
634 $output = '/'.t3lib_div::fixed_lgd_cs(strip_tags($row['title']),$titleLimit).$output;
635 if ($fullTitleLimit) $fullOutput = '/'.t3lib_div::fixed_lgd_cs(strip_tags($row['title']),$fullTitleLimit).$fullOutput;
636 } else {
637 break;
638 }
639 }
640
641 if ($fullTitleLimit) {
642 return array($output, $fullOutput);
643 } else {
644 return $output;
645 }
646 }
647
648 /**
649 * Returns an array with the exclude-fields as defined in TCA
650 * Used for listing the exclude-fields in be_groups forms
651 * Usage: 2 (t3lib_tceforms + t3lib_transferdata)
652 *
653 * @return array Array of arrays with excludeFields (fieldname, table:fieldname) from all TCA entries
654 */
655 function getExcludeFields() {
656 global $TCA;
657 // All TCA keys:
658 $theExcludeArray = Array();
659 $tc_keys = array_keys($TCA);
660 foreach($tc_keys as $table) {
661 // Load table
662 t3lib_div::loadTCA($table);
663 // All field names configured:
664 if (is_array($TCA[$table]['columns'])) {
665 $f_keys = array_keys($TCA[$table]['columns']);
666 foreach($f_keys as $field) {
667 if ($TCA[$table]['columns'][$field]['exclude']) {
668 // Get Human Readable names of fields and table:
669 $Fname=$GLOBALS['LANG']->sl($TCA[$table]['ctrl']['title']).': '.$GLOBALS['LANG']->sl($TCA[$table]['columns'][$field]['label']);
670 // add entry:
671 $theExcludeArray[] = Array($Fname , $table.':'.$field);
672 }
673 }
674 }
675 }
676 return $theExcludeArray;
677 }
678
679 /**
680 * Returns an array with explicit Allow/Deny fields.
681 * Used for listing these field/value pairs in be_groups forms
682 *
683 * @return array Array with information from all of $TCA
684 */
685 function getExplicitAuthFieldValues() {
686 global $TCA;
687
688 // Initialize:
689 $adLabel = array(
690 'ALLOW' => $GLOBALS['LANG']->sl('LLL:EXT:lang/locallang_core.xml:labels.allow'),
691 'DENY' => $GLOBALS['LANG']->sl('LLL:EXT:lang/locallang_core.xml:labels.deny'),
692 );
693
694 // All TCA keys:
695 $allowDenyOptions = Array();
696 $tc_keys = array_keys($TCA);
697 foreach($tc_keys as $table) {
698
699 // Load table
700 t3lib_div::loadTCA($table);
701
702 // All field names configured:
703 if (is_array($TCA[$table]['columns'])) {
704 $f_keys = array_keys($TCA[$table]['columns']);
705 foreach($f_keys as $field) {
706 $fCfg = $TCA[$table]['columns'][$field]['config'];
707 if ($fCfg['type']=='select' && $fCfg['authMode']) {
708
709 // Check for items:
710 if (is_array($fCfg['items'])) {
711 // Get Human Readable names of fields and table:
712 $allowDenyOptions[$table.':'.$field]['tableFieldLabel'] = $GLOBALS['LANG']->sl($TCA[$table]['ctrl']['title']).': '.$GLOBALS['LANG']->sl($TCA[$table]['columns'][$field]['label']);
713
714 // Check for items:
715 foreach($fCfg['items'] as $iVal) {
716 if (strcmp($iVal[1],'')) { // Values '' is not controlled by this setting.
717
718 // Find iMode:
719 $iMode = '';
720 switch((string)$fCfg['authMode']) {
721 case 'explicitAllow':
722 $iMode = 'ALLOW';
723 break;
724 case 'explicitDeny':
725 $iMode = 'DENY';
726 break;
727 case 'individual':
728 if (!strcmp($iVal[4],'EXPL_ALLOW')) {
729 $iMode = 'ALLOW';
730 } elseif (!strcmp($iVal[4],'EXPL_DENY')) {
731 $iMode = 'DENY';
732 }
733 break;
734 }
735
736 // Set iMode:
737 if ($iMode) {
738 $allowDenyOptions[$table.':'.$field]['items'][$iVal[1]] = array($iMode, $GLOBALS['LANG']->sl($iVal[0]), $adLabel[$iMode]);
739 }
740 }
741 }
742 }
743 }
744 }
745 }
746 }
747
748 return $allowDenyOptions;
749 }
750
751 /**
752 * Returns an array with system languages:
753 *
754 * @return array Array with languages
755 */
756 function getSystemLanguages() {
757
758 // Initialize, add default language:
759 $sysLanguages = array();
760 $sysLanguages[] = array('Default language', 0);
761
762 // Traverse languages
763 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,title,flag','sys_language','pid=0'.t3lib_BEfunc::deleteClause('sys_language'));
764 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
765 $sysLanguages[] = array($row['title'].' ['.$row['uid'].']', $row['uid'], ($row['flag'] ? '../t3lib/gfx/flags/'.$row['flag'] : ''));
766 }
767
768 return $sysLanguages;
769 }
770
771 /**
772 * 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.
773 * If $id is zero a pseudo root-page with "_thePath" set is returned IF the current BE_USER is admin.
774 * In any case ->isInWebMount must return true for the user (regardless of $perms_clause)
775 * Usage: 21
776 *
777 * @param integer Page uid for which to check read-access
778 * @param string $perms_clause is typically a value generated with $BE_USER->getPagePermsClause(1);
779 * @return array Returns page record if OK, otherwise false.
780 */
781 function readPageAccess($id,$perms_clause) {
782 if ((string)$id!='') {
783 $id = intval($id);
784 if (!$id) {
785 if ($GLOBALS['BE_USER']->isAdmin()) {
786 $path = '/';
787 $pageinfo['_thePath'] = $path;
788 return $pageinfo;
789 }
790 } else {
791 $pageinfo = t3lib_BEfunc::getRecord('pages',$id,'*',($perms_clause ? ' AND '.$perms_clause : ''));
792 if ($pageinfo['uid'] && $GLOBALS['BE_USER']->isInWebMount($id,$perms_clause)) {
793 t3lib_BEfunc::workspaceOL('pages', $pageinfo);
794 list($pageinfo['_thePath'],$pageinfo['_thePathFull']) = t3lib_BEfunc::getRecordPath(intval($pageinfo['uid']), $perms_clause, 15, 1000);
795 return $pageinfo;
796 }
797 }
798 }
799 return false;
800 }
801
802 /**
803 * Returns the "types" configuration parsed into an array for the record, $rec, from table, $table
804 * Usage: 6
805 *
806 * @param string Table name (present in TCA)
807 * @param array Record from $table
808 * @param boolean If $useFieldNameAsKey is set, then the fieldname is associative keys in the return array, otherwise just numeric keys.
809 * @return array
810 */
811 function getTCAtypes($table,$rec,$useFieldNameAsKey=0) {
812 global $TCA;
813
814 t3lib_div::loadTCA($table);
815 if ($TCA[$table]) {
816
817 // Get type value:
818 $fieldValue = t3lib_BEfunc::getTCAtypeValue($table,$rec);
819
820 // Get typesConf
821 $typesConf = $TCA[$table]['types'][$fieldValue];
822
823 // Get fields list and traverse it
824 $fieldList = explode(',', $typesConf['showitem']);
825 $altFieldList = array();
826
827 // Traverse fields in types config and parse the configuration into a nice array:
828 foreach($fieldList as $k => $v) {
829 list($pFieldName, $pAltTitle, $pPalette, $pSpec) = t3lib_div::trimExplode(';', $v);
830 $defaultExtras = is_array($TCA[$table]['columns'][$pFieldName]) ? $TCA[$table]['columns'][$pFieldName]['defaultExtras'] : '';
831 $specConfParts = t3lib_BEfunc::getSpecConfParts($pSpec, $defaultExtras);
832
833 $fieldList[$k]=array(
834 'field' => $pFieldName,
835 'title' => $pAltTitle,
836 'palette' => $pPalette,
837 'spec' => $specConfParts,
838 'origString' => $v
839 );
840 if ($useFieldNameAsKey) {
841 $altFieldList[$fieldList[$k]['field']] = $fieldList[$k];
842 }
843 }
844 if ($useFieldNameAsKey) {
845 $fieldList = $altFieldList;
846 }
847
848 // Return array:
849 return $fieldList;
850 }
851 }
852
853 /**
854 * Returns the "type" value of $rec from $table which can be used to look up the correct "types" rendering section in $TCA
855 * If no "type" field is configured in the "ctrl"-section of the $TCA for the table, zero is used.
856 * 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)
857 * Usage: 7
858 *
859 * @param string Table name present in TCA
860 * @param array Record from $table
861 * @return string Field value
862 * @see getTCAtypes()
863 */
864 function getTCAtypeValue($table,$rec) {
865 global $TCA;
866
867 // 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.
868 t3lib_div::loadTCA($table);
869 if ($TCA[$table]) {
870 $field = $TCA[$table]['ctrl']['type'];
871 $fieldValue = $field ? ($rec[$field] ? $rec[$field] : 0) : 0;
872 if (!is_array($TCA[$table]['types'][$fieldValue])) $fieldValue = 1;
873 return $fieldValue;
874 }
875 }
876
877 /**
878 * Parses a part of the field lists in the "types"-section of $TCA arrays, namely the "special configuration" at index 3 (position 4)
879 * Elements are splitted by ":" and within those parts, parameters are splitted by "|".
880 * 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
881 * Usage: 5
882 *
883 * @param string Content from the "types" configuration of TCA (the special configuration) - see description of function
884 * @param string The ['defaultExtras'] value from field configuration
885 * @return array
886 */
887 function getSpecConfParts($str, $defaultExtras) {
888
889 // Add defaultExtras:
890 $specConfParts = t3lib_div::trimExplode(':', $defaultExtras.':'.$str, 1);
891
892 if (count($specConfParts)) {
893 foreach($specConfParts as $k2 => $v2) {
894 unset($specConfParts[$k2]);
895 if (ereg('(.*)\[(.*)\]',$v2,$reg)) {
896 $specConfParts[trim($reg[1])] = array(
897 'parameters' => t3lib_div::trimExplode('|', $reg[2], 1)
898 );
899 } else {
900 $specConfParts[trim($v2)] = 1;
901 }
902 }
903 } else {
904 $specConfParts = array();
905 }
906 return $specConfParts;
907 }
908
909 /**
910 * Takes an array of "[key]=[value]" strings and returns an array with the keys set as keys pointing to the value.
911 * Better see it in action! Find example in Inside TYPO3
912 * Usage: 6
913 *
914 * @param array Array of "[key]=[value]" strings to convert.
915 * @return array
916 */
917 function getSpecConfParametersFromArray($pArr) {
918 $out=array();
919 if (is_array($pArr)) {
920 reset($pArr);
921 while(list($k,$v)=each($pArr)) {
922 $parts=explode('=',$v,2);
923 if (count($parts)==2) {
924 $out[trim($parts[0])]=trim($parts[1]);
925 } else {
926 $out[$k]=$v;
927 }
928 }
929 }
930 return $out;
931 }
932
933 /**
934 * Finds the Data Structure for a FlexForm field
935 * Usage: 5
936 *
937 * @param array Field config array
938 * @param array Record data
939 * @param string The table name
940 * @param [type] $fieldName: ...
941 * @return mixed If array, the data structure was found and returned as an array. Otherwise (string) it is an error message.
942 * @see t3lib_TCEforms::getSingleField_typeFlex()
943 */
944 function getFlexFormDS($conf,$row,$table, $fieldName = '') {
945 global $TYPO3_CONF_VARS;
946
947 // Get pointer field etc from TCA-config:
948 $ds_pointerField = $conf['ds_pointerField'];
949 $ds_array = $conf['ds'];
950 $ds_tableField = $conf['ds_tableField'];
951 $ds_searchParentField = $conf['ds_pointerField_searchParent'];
952
953 // Find source value:
954 $dataStructArray='';
955 if (is_array($ds_array)) { // If there is a data source array, that takes precedence
956 // If a pointer field is set, take the value from that field in the $row array and use as key.
957 if ($ds_pointerField) {
958 $srcPointer = $row[$ds_pointerField];
959 $srcPointer = isset($ds_array[$srcPointer]) ? $srcPointer : 'default';
960 } else $srcPointer='default';
961
962 // Get Data Source: Detect if it's a file reference and in that case read the file and parse as XML. Otherwise the value is expected to be XML.
963 if (substr($ds_array[$srcPointer],0,5)=='FILE:') {
964 $file = t3lib_div::getFileAbsFileName(substr($ds_array[$srcPointer],5));
965 if ($file && @is_file($file)) {
966 $dataStructArray = t3lib_div::xml2array(t3lib_div::getUrl($file));
967 } else $dataStructArray = 'The file "'.substr($dsSrc,5).'" in ds-array key "'.$srcPointer.'" was not found ("'.$file.'")'; // Error message.
968 } else {
969 $dataStructArray = t3lib_div::xml2array($ds_array[$srcPointer]);
970 }
971
972 } elseif ($ds_pointerField) { // If pointer field AND possibly a table/field is set:
973 // Value of field pointed to:
974 $srcPointer = $row[$ds_pointerField];
975
976 // Searching recursively back if 'ds_pointerField_searchParent' is defined (typ. a page rootline, or maybe a tree-table):
977 if ($ds_searchParentField && !$srcPointer) {
978 $rr = t3lib_BEfunc::getRecord($table,$row['uid'],'uid,'.$ds_searchParentField); // Get the "pid" field - we cannot know that it is in the input record!
979 #t3lib_BEfunc::workspaceOL($table,$rr); // KASPER: Not tested, but assumed correct
980 t3lib_BEfunc::fixVersioningPid($table,$rr);
981 $uidAcc=array(); // Used to avoid looping, if any should happen.
982 $subFieldPointer = $conf['ds_pointerField_searchParent_subField'];
983 while(!$srcPointer) {
984 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
985 'uid,'.$ds_pointerField.','.$ds_searchParentField.($subFieldPointer?','.$subFieldPointer:''),
986 $table,
987 'uid='.intval($rr[$ds_searchParentField]).t3lib_BEfunc::deleteClause($table)
988 );
989 $rr = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
990
991 // break if no result from SQL db or if looping...
992 if (!is_array($rr) || isset($uidAcc[$rr['uid']])) break;
993 $uidAcc[$rr['uid']]=1;
994
995 #t3lib_BEfunc::workspaceOL($table,$rr); // KASPER: Not tested, but assumed correct
996 t3lib_BEfunc::fixVersioningPid($table,$rr);
997 $srcPointer = ($subFieldPointer && $rr[$subFieldPointer]) ? $rr[$subFieldPointer] : $rr[$ds_pointerField];
998 }
999 }
1000
1001 // If there is a srcPointer value:
1002 if ($srcPointer) {
1003 if (t3lib_div::testInt($srcPointer)) { // If integer, then its a record we will look up:
1004 list($tName,$fName) = explode(':',$ds_tableField,2);
1005 if ($tName && $fName && is_array($GLOBALS['TCA'][$tName])) {
1006 $dataStructRec = t3lib_BEfunc::getRecord($tName, $srcPointer);
1007 $dataStructArray = t3lib_div::xml2array($dataStructRec[$fName]);
1008 } else $dataStructArray = 'No tablename ('.$tName.') or fieldname ('.$fName.') was found an valid!';
1009 } else { // Otherwise expect it to be a file:
1010 $file = t3lib_div::getFileAbsFileName($srcPointer);
1011 if ($file && @is_file($file)) {
1012 $dataStructArray = t3lib_div::xml2array(t3lib_div::getUrl($file));
1013 } else $dataStructArray='The file "'.$srcPointer.'" was not found ("'.$file.'")'; // Error message.
1014 }
1015 } else $dataStructArray='No source value in fieldname "'.$ds_pointerField.'"'; // Error message.
1016 } else $dataStructArray='No proper configuration!';
1017
1018 // Hook for post-processing the Flexform DS. Introduces the possibility to configure Flexforms via TSConfig
1019 if (is_array ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['getFlexFormDSClass'])) {
1020 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['getFlexFormDSClass'] as $classRef) {
1021 $hookObj = &t3lib_div::getUserObj($classRef);
1022 if (method_exists($hookObj, 'getFlexFormDS_postProcessDS')) {
1023 $hookObj->getFlexFormDS_postProcessDS($dataStructArray, $conf, $row, $table, $fieldName);
1024 }
1025 }
1026 }
1027
1028 return $dataStructArray;
1029 }
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048 /*******************************************
1049 *
1050 * Caching related
1051 *
1052 *******************************************/
1053
1054 /**
1055 * Stores the string value $data in the 'cache_hash' table with the hash key, $hash, and visual/symbolic identification, $ident
1056 * IDENTICAL to the function by same name found in t3lib_page:
1057 * Usage: 2
1058 *
1059 * @param string Hash key, 32 bytes hex
1060 * @param string $data must be serialized before function call
1061 * @param string Visual/symbolic identification (informational only)
1062 * @return void
1063 */
1064 function storeHash($hash,$data,$ident) {
1065 $insertFields = array(
1066 'hash' => $hash,
1067 'content' => $data,
1068 'ident' => $ident,
1069 'tstamp' => time()
1070 );
1071 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_hash', 'hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($hash, 'cache_hash'));
1072 $GLOBALS['TYPO3_DB']->exec_INSERTquery('cache_hash', $insertFields);
1073 }
1074
1075 /**
1076 * Retrieves the string content stored with hash key, $hash, in cache_hash
1077 * IDENTICAL to the function by same name found in t3lib_page:
1078 * Usage: 2
1079 *
1080 * @param string Hash key, 32 bytes hex
1081 * @param integer $expTime represents the expire time in seconds. For instance a value of 3600 would allow cached content within the last hour, otherwise nothing is returned.
1082 * @return string
1083 */
1084 function getHash($hash,$expTime=0) {
1085 // if expTime is not set, the hash will never expire
1086 $expTime = intval($expTime);
1087 if ($expTime) {
1088 $whereAdd = ' AND tstamp > '.(time()-$expTime);
1089 }
1090 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('content', 'cache_hash', 'hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($hash, 'cache_hash').$whereAdd);
1091 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
1092 return $row['content'];
1093 }
1094 }
1095
1096
1097
1098
1099
1100
1101
1102
1103 /*******************************************
1104 *
1105 * TypoScript related
1106 *
1107 *******************************************/
1108
1109 /**
1110 * Returns the Page TSconfig for page with id, $id
1111 * Requires class "t3lib_TSparser"
1112 * Usage: 26 (spec. in ext info_pagetsconfig)
1113 *
1114 * @param integer Page uid for which to create Page TSconfig
1115 * @param array If $rootLine is an array, that is used as rootline, otherwise rootline is just calculated
1116 * @param boolean If $returnPartArray is set, then the array with accumulated Page TSconfig is returned non-parsed. Otherwise the output will be parsed by the TypoScript parser.
1117 * @return array Page TSconfig
1118 * @see t3lib_TSparser
1119 */
1120 function getPagesTSconfig($id,$rootLine='',$returnPartArray=0) {
1121 $id=intval($id);
1122 if (!is_array($rootLine)) {
1123 $rootLine = t3lib_BEfunc::BEgetRootLine($id,'');
1124 }
1125 ksort($rootLine); // Order correctly, changed 030102
1126 reset($rootLine);
1127 $TSdataArray = array();
1128 $TSdataArray['defaultPageTSconfig']=$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPageTSconfig']; // Setting default configuration:
1129 while(list($k,$v)=each($rootLine)) {
1130 $TSdataArray['uid_'.$v['uid']]=$v['TSconfig'];
1131 }
1132 $TSdataArray = t3lib_TSparser::checkIncludeLines_array($TSdataArray);
1133 if ($returnPartArray) {
1134 return $TSdataArray;
1135 }
1136
1137 // Parsing the user TS (or getting from cache)
1138 $userTS = implode($TSdataArray,chr(10).'[GLOBAL]'.chr(10));
1139 $hash = md5('pageTS:'.$userTS);
1140 $cachedContent = t3lib_BEfunc::getHash($hash,0);
1141 $TSconfig = array();
1142 if (isset($cachedContent)) {
1143 $TSconfig = unserialize($cachedContent);
1144 } else {
1145 $parseObj = t3lib_div::makeInstance('t3lib_TSparser');
1146 $parseObj->parse($userTS);
1147 $TSconfig = $parseObj->setup;
1148 t3lib_BEfunc::storeHash($hash,serialize($TSconfig),'PAGES_TSconfig');
1149 }
1150 return $TSconfig;
1151 }
1152
1153 /**
1154 * Updates Page TSconfig for a page with $id
1155 * The function seems to take $pageTS as an array with properties and compare the values with those that already exists for the "object string", $TSconfPrefix, for the page, then sets those values which were not present.
1156 * $impParams can be supplied as already known Page TSconfig, otherwise it's calculated.
1157 *
1158 * THIS DOES NOT CHECK ANY PERMISSIONS. SHOULD IT?
1159 * More documentation is needed.
1160 *
1161 * Usage: 1 (ext. direct_mail)
1162 *
1163 * @param integer Page id
1164 * @param array Page TS array to write
1165 * @param string Prefix for object paths
1166 * @param array [Description needed.]
1167 * @return void
1168 * @internal
1169 * @see implodeTSParams(), getPagesTSconfig()
1170 */
1171 function updatePagesTSconfig($id,$pageTS,$TSconfPrefix,$impParams='') {
1172 $id=intval($id);
1173 if (is_array($pageTS) && $id>0) {
1174 if (!is_array($impParams)) {
1175 $impParams =t3lib_BEfunc::implodeTSParams(t3lib_BEfunc::getPagesTSconfig($id));
1176 }
1177 reset($pageTS);
1178 $set=array();
1179 while(list($f,$v)=each($pageTS)) {
1180 $f = $TSconfPrefix.$f;
1181 if ((!isset($impParams[$f])&&trim($v)) || strcmp(trim($impParams[$f]),trim($v))) {
1182 $set[$f]=trim($v);
1183 }
1184 }
1185 if (count($set)) {
1186 // Get page record and TS config lines
1187 $pRec = t3lib_befunc::getRecord('pages',$id);
1188 $TSlines = explode(chr(10),$pRec['TSconfig']);
1189 $TSlines = array_reverse($TSlines);
1190 // Reset the set of changes.
1191 reset($set);
1192 while(list($f,$v)=each($set)) {
1193 reset($TSlines);
1194 $inserted=0;
1195 while(list($ki,$kv)=each($TSlines)) {
1196 if (substr($kv,0,strlen($f)+1)==$f.'=') {
1197 $TSlines[$ki]=$f.'='.$v;
1198 $inserted=1;
1199 break;
1200 }
1201 }
1202 if (!$inserted) {
1203 $TSlines = array_reverse($TSlines);
1204 $TSlines[]=$f.'='.$v;
1205 $TSlines = array_reverse($TSlines);
1206 }
1207 }
1208 $TSlines = array_reverse($TSlines);
1209
1210 // store those changes
1211 $TSconf = implode(chr(10),$TSlines);
1212
1213 $GLOBALS['TYPO3_DB']->exec_UPDATEquery('pages', 'uid='.intval($id), array('TSconfig' => $TSconf));
1214 }
1215 }
1216 }
1217
1218 /**
1219 * Implodes a multi dimensional TypoScript array, $p, into a one-dimentional array (return value)
1220 * Usage: 3
1221 *
1222 * @param array TypoScript structure
1223 * @param string Prefix string
1224 * @return array Imploded TypoScript objectstring/values
1225 */
1226 function implodeTSParams($p,$k='') {
1227 $implodeParams=array();
1228 if (is_array($p)) {
1229 reset($p);
1230 while(list($kb,$val)=each($p)) {
1231 if (is_array($val)) {
1232 $implodeParams = array_merge($implodeParams,t3lib_BEfunc::implodeTSParams($val,$k.$kb));
1233 } else {
1234 $implodeParams[$k.$kb]=$val;
1235 }
1236 }
1237 }
1238 return $implodeParams;
1239 }
1240
1241
1242
1243
1244
1245
1246
1247
1248 /*******************************************
1249 *
1250 * Users / Groups related
1251 *
1252 *******************************************/
1253
1254 /**
1255 * Returns an array with be_users records of all user NOT DELETED sorted by their username
1256 * Keys in the array is the be_users uid
1257 * Usage: 14 (spec. ext. "beuser" and module "web_perm")
1258 *
1259 * @param string Optional $fields list (default: username,usergroup,usergroup_cached_list,uid) can be used to set the selected fields
1260 * @param string Optional $where clause (fx. "AND username='pete'") can be used to limit query
1261 * @return array
1262 */
1263 function getUserNames($fields='username,usergroup,usergroup_cached_list,uid',$where='') {
1264 $be_user_Array=Array();
1265
1266 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fields, 'be_users', 'pid=0 '.$where.t3lib_BEfunc::deleteClause('be_users'), '', 'username');
1267 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
1268 $be_user_Array[$row['uid']]=$row;
1269 }
1270 return $be_user_Array;
1271 }
1272
1273 /**
1274 * Returns an array with be_groups records (title, uid) of all groups NOT DELETED sorted by their title
1275 * Usage: 8 (spec. ext. "beuser" and module "web_perm")
1276 *
1277 * @param string Field list
1278 * @param string WHERE clause
1279 * @return array
1280 */
1281 function getGroupNames($fields='title,uid', $where='') {
1282 $be_group_Array = Array();
1283 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fields, 'be_groups', 'pid=0 '.$where.t3lib_BEfunc::deleteClause('be_groups'), '', 'title');
1284 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
1285 $be_group_Array[$row['uid']] = $row;
1286 }
1287 return $be_group_Array;
1288 }
1289
1290 /**
1291 * Returns an array with be_groups records (like ->getGroupNames) but:
1292 * - if the current BE_USER is admin, then all groups are returned, otherwise only groups that the current user is member of (usergroup_cached_list) will be returned.
1293 * Usage: 2 (module "web_perm" and ext. taskcenter)
1294 *
1295 * @param string Field list; $fields specify the fields selected (default: title,uid)
1296 * @return array
1297 */
1298 function getListGroupNames($fields='title,uid') {
1299 $exQ=' AND hide_in_lists=0';
1300 if (!$GLOBALS['BE_USER']->isAdmin()) {
1301 $exQ.=' AND uid IN ('.($GLOBALS['BE_USER']->user['usergroup_cached_list']?$GLOBALS['BE_USER']->user['usergroup_cached_list']:0).')';
1302 }
1303 return t3lib_BEfunc::getGroupNames($fields,$exQ);
1304 }
1305
1306 /**
1307 * Returns the array $usernames with the names of all users NOT IN $groupArray changed to the uid (hides the usernames!).
1308 * If $excludeBlindedFlag is set, then these records are unset from the array $usernames
1309 * Takes $usernames (array made by t3lib_BEfunc::getUserNames()) and a $groupArray (array with the groups a certain user is member of) as input
1310 * Usage: 8
1311 *
1312 * @param array User names
1313 * @param array Group names
1314 * @param boolean If $excludeBlindedFlag is set, then these records are unset from the array $usernames
1315 * @return array User names, blinded
1316 */
1317 function blindUserNames($usernames,$groupArray,$excludeBlindedFlag=0) {
1318 if (is_array($usernames) && is_array($groupArray)) {
1319 while(list($uid,$row)=each($usernames)) {
1320 $userN=$uid;
1321 $set=0;
1322 if ($row['uid']!=$GLOBALS['BE_USER']->user['uid']) {
1323 reset($groupArray);
1324 while(list(,$v)=each($groupArray)) {
1325 if ($v && t3lib_div::inList($row['usergroup_cached_list'],$v)) {
1326 $userN = $row['username'];
1327 $set=1;
1328 }
1329 }
1330 } else {
1331 $userN = $row['username'];
1332 $set=1;
1333 }
1334 $usernames[$uid]['username']=$userN;
1335 if ($excludeBlindedFlag && !$set) {unset($usernames[$uid]);}
1336 }
1337 }
1338 return $usernames;
1339 }
1340
1341 /**
1342 * Corresponds to blindUserNames but works for groups instead
1343 * Usage: 2 (module web_perm)
1344 *
1345 * @param array Group names
1346 * @param array Group names (reference)
1347 * @param boolean If $excludeBlindedFlag is set, then these records are unset from the array $usernames
1348 * @return array
1349 */
1350 function blindGroupNames($groups,$groupArray,$excludeBlindedFlag=0) {
1351 if (is_array($groups) && is_array($groupArray)) {
1352 while(list($uid,$row)=each($groups)) {
1353 $groupN=$uid;
1354 $set=0;
1355 if (t3lib_div::inArray($groupArray,$uid)) {
1356 $groupN=$row['title'];
1357 $set=1;
1358 }
1359 $groups[$uid]['title']=$groupN;
1360 if ($excludeBlindedFlag && !$set) {unset($groups[$uid]);}
1361 }
1362 }
1363 return $groups;
1364 }
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378 /*******************************************
1379 *
1380 * Output related
1381 *
1382 *******************************************/
1383
1384 /**
1385 * Returns the difference in days between input $tstamp and $EXEC_TIME
1386 * Usage: 2 (class t3lib_BEfunc)
1387 *
1388 * @param integer Time stamp, seconds
1389 * @return integer
1390 */
1391 function daysUntil($tstamp) {
1392 $delta_t = $tstamp-$GLOBALS['EXEC_TIME'];
1393 return ceil($delta_t/(3600*24));
1394 }
1395
1396 /**
1397 * Returns $tstamp formatted as "ddmmyy" (According to $TYPO3_CONF_VARS['SYS']['ddmmyy'])
1398 * Usage: 11
1399 *
1400 * @param integer Time stamp, seconds
1401 * @return string Formatted time
1402 */
1403 function date($tstamp) {
1404 return date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'],$tstamp);
1405 }
1406
1407 /**
1408 * Returns $tstamp formatted as "ddmmyy hhmm" (According to $TYPO3_CONF_VARS['SYS']['ddmmyy'] AND $TYPO3_CONF_VARS['SYS']['hhmm'])
1409 * Usage: 28
1410 *
1411 * @param integer Time stamp, seconds
1412 * @return string Formatted time
1413 */
1414 function datetime($value) {
1415 return date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'].' '.$GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'], $value);
1416 }
1417
1418 /**
1419 * Returns $value (in seconds) formatted as hh:mm:ss
1420 * For instance $value = 3600 + 60*2 + 3 should return "01:02:03"
1421 * Usage: 1 (class t3lib_BEfunc)
1422 *
1423 * @param integer Time stamp, seconds
1424 * @return string Formatted time
1425 */
1426 function time($value) {
1427 $hh = floor($value/3600);
1428 $min = floor(($value-$hh*3600)/60);
1429 $sec = $value-$hh*3600-$min*60;
1430 $l = sprintf('%02d',$hh).':'.sprintf('%02d',$min).':'.sprintf('%02d',$sec);
1431 return $l;
1432 }
1433
1434 /**
1435 * Returns the "age" in minutes / hours / days / years of the number of $seconds inputted.
1436 * Usage: 15
1437 *
1438 * @param integer $seconds could be the difference of a certain timestamp and time()
1439 * @param string $labels should be something like ' min| hrs| days| yrs'. This value is typically delivered by this function call: $GLOBALS["LANG"]->sL("LLL:EXT:lang/locallang_core.php:labels.minutesHoursDaysYears")
1440 * @return string Formatted time
1441 */
1442 function calcAge($seconds,$labels = 'min|hrs|days|yrs') {
1443 $labelArr = explode('|',$labels);
1444 $prefix='';
1445 if ($seconds<0) {$prefix='-'; $seconds=abs($seconds);}
1446 if ($seconds<3600) {
1447 $seconds = round ($seconds/60).' '.trim($labelArr[0]);
1448 } elseif ($seconds<24*3600) {
1449 $seconds = round ($seconds/3600).' '.trim($labelArr[1]);
1450 } elseif ($seconds<365*24*3600) {
1451 $seconds = round ($seconds/(24*3600)).' '.trim($labelArr[2]);
1452 } else {
1453 $seconds = round ($seconds/(365*24*3600)).' '.trim($labelArr[3]);
1454 }
1455 return $prefix.$seconds;
1456 }
1457
1458 /**
1459 * Returns a formatted timestamp if $tstamp is set.
1460 * The date/datetime will be followed by the age in parenthesis.
1461 * Usage: 3
1462 *
1463 * @param integer Time stamp, seconds
1464 * @param integer 1/-1 depending on polarity of age.
1465 * @param string $date=="date" will yield "dd:mm:yy" formatting, otherwise "dd:mm:yy hh:mm"
1466 * @return string
1467 */
1468 function dateTimeAge($tstamp,$prefix=1,$date='') {
1469 return $tstamp ?
1470 ($date=='date' ? t3lib_BEfunc::date($tstamp) : t3lib_BEfunc::datetime($tstamp)).
1471 ' ('.t3lib_BEfunc::calcAge($prefix*(time()-$tstamp),$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.minutesHoursDaysYears')).')' : '';
1472 }
1473
1474 /**
1475 * Returns either title='' or alt='' attribute. This depends on the client browser and whether it supports title='' or not (which is the default)
1476 * If no $content is given only the attribute name is returned.
1477 * The returned attribute with content will have a leading space char.
1478 * Warning: Be careful to submit empty $content var - that will return just the attribute name!
1479 * Usage: 0
1480 *
1481 * @param string String to set as title-attribute. If no $content is given only the attribute name is returned.
1482 * @param boolean If $hsc is set, then content of the attribute is htmlspecialchar()'ed (which is good for XHTML and other reasons...)
1483 * @return string
1484 * @depreciated The idea made sense with older browsers, but now all browsers should support the "title" attribute - so just hardcode the title attribute instead!
1485 */
1486 function titleAttrib($content='',$hsc=0) {
1487 global $CLIENT;
1488 $attrib= ($CLIENT['BROWSER']=='net'&&$CLIENT['VERSION']<5)||$CLIENT['BROWSER']=='konqu' ? 'alt' : 'title';
1489 return strcmp($content,'')?' '.$attrib.'="'.($hsc?htmlspecialchars($content):$content).'"' : $attrib;
1490 }
1491
1492 /**
1493 * Returns alt="" and title="" attributes with the value of $content.
1494 * Usage: 7
1495 *
1496 * @param string Value for 'alt' and 'title' attributes (will be htmlspecialchars()'ed before output)
1497 * @return string
1498 */
1499 function titleAltAttrib($content) {
1500 $out='';
1501 $out.=' alt="'.htmlspecialchars($content).'"';
1502 $out.=' title="'.htmlspecialchars($content).'"';
1503 return $out;
1504 }
1505
1506 /**
1507 * Returns a linked image-tag for thumbnail(s)/fileicons/truetype-font-previews from a database row with a list of image files in a field
1508 * All $TYPO3_CONF_VARS['GFX']['imagefile_ext'] extension are made to thumbnails + ttf file (renders font-example)
1509 * Thumbsnails are linked to the show_item.php script which will display further details.
1510 * Usage: 7
1511 *
1512 * @param array $row is the database row from the table, $table.
1513 * @param string Table name for $row (present in TCA)
1514 * @param string $field is pointing to the field with the list of image files
1515 * @param string Back path prefix for image tag src="" field
1516 * @param string Optional: $thumbScript os by default 'thumbs.php' if you don't set it otherwise
1517 * @param string Optional: $uploaddir is the directory relative to PATH_site where the image files from the $field value is found (Is by default set to the entry in $TCA for that field! so you don't have to!)
1518 * @param boolean If set, uploaddir is NOT prepended with "../"
1519 * @param string Optional: $tparams is additional attributes for the image tags
1520 * @param integer Optional: $size is [w]x[h] of the thumbnail. 56 is default.
1521 * @return string Thumbnail image tag.
1522 */
1523 function thumbCode($row,$table,$field,$backPath,$thumbScript='',$uploaddir=NULL,$abs=0,$tparams='',$size='') {
1524 global $TCA;
1525 // Load table.
1526 t3lib_div::loadTCA($table);
1527
1528 // Find uploaddir automatically
1529 $uploaddir = (is_null($uploaddir)) ? $TCA[$table]['columns'][$field]['config']['uploadfolder'] : $uploaddir;
1530 $uploaddir = preg_replace('#/$#','',$uploaddir);
1531
1532 // Set thumbs-script:
1533 if (!$GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails']) {
1534 $thumbScript='gfx/notfound_thumb.gif';
1535 } elseif(!$thumbScript) {
1536 $thumbScript='thumbs.php';
1537 }
1538 // Check and parse the size parameter
1539 $sizeParts=array();
1540 if ($size = trim($size)) {
1541 $sizeParts = explode('x', $size.'x'.$size);
1542 if(!intval($sizeParts[0])) $size='';
1543 }
1544
1545 // Traverse files:
1546 $thumbs = explode(',', $row[$field]);
1547 $thumbData='';
1548 while(list(,$theFile)=each($thumbs)) {
1549 if (trim($theFile)) {
1550 $fI = t3lib_div::split_fileref($theFile);
1551 $ext = $fI['fileext'];
1552 // New 190201 start
1553 $max=0;
1554 if (t3lib_div::inList('gif,jpg,png',$ext)) {
1555 $imgInfo=@getimagesize(PATH_site.$uploaddir.'/'.$theFile);
1556 if (is_array($imgInfo)) {$max = max($imgInfo[0],$imgInfo[1]);}
1557 }
1558 // use the original image if it's size fits to the thumbnail size
1559 if ($max && $max<=(count($sizeParts)&&max($sizeParts)?max($sizeParts):56)) {
1560 $url = $uploaddir.'/'.trim($theFile);
1561 $theFile = '../'.$url;
1562 $onClick='top.launchView(\''.$theFile.'\',\'\',\''.$backPath.'\');return false;';
1563 $thumbData.='<a href="#" onclick="'.htmlspecialchars($onClick).'"><img src="../'.$backPath.$url.'" '.$imgInfo[3].' hspace="2" border="0" title="'.trim($url).'"'.$tparams.' alt="" /></a> ';
1564 // New 190201 stop
1565 } elseif ($ext=='ttf' || t3lib_div::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'],$ext)) {
1566 $theFile = ($abs?'':'../').($uploaddir?$uploaddir.'/':'').trim($theFile);
1567 $params = '&file='.rawurlencode($theFile);
1568 $params .= $size?'&size='.$size:'';
1569 $url = $thumbScript.'?&dummy='.$GLOBALS['EXEC_TIME'].$params;
1570 $onClick='top.launchView(\''.$theFile.'\',\'\',\''.$backPath.'\');return false;';
1571 $thumbData.='<a href="#" onclick="'.htmlspecialchars($onClick).'"><img src="'.htmlspecialchars($backPath.$url).'" hspace="2" border="0" title="'.trim($theFile).'"'.$tparams.' alt="" /></a> ';
1572 } else {
1573 $icon = t3lib_BEfunc::getFileIcon($ext);
1574 $url = 'gfx/fileicons/'.$icon;
1575 $thumbData.='<img src="'.$backPath.$url.'" hspace="2" border="0" title="'.trim($theFile).'"'.$tparams.' alt="" /> ';
1576 }
1577 }
1578 }
1579 return $thumbData;
1580 }
1581
1582 /**
1583 * Returns single image tag to thumbnail using a thumbnail script (like thumbs.php)
1584 * Usage: 3
1585 *
1586 * @param string $thumbScript must point to "thumbs.php" relative to the script position
1587 * @param string $theFile must be the proper reference to the file thumbs.php should show
1588 * @param string $tparams are additional attributes for the image tag
1589 * @param integer $size is the size of the thumbnail send along to "thumbs.php"
1590 * @return string Image tag
1591 */
1592 function getThumbNail($thumbScript,$theFile,$tparams='',$size='') {
1593 $params = '&file='.rawurlencode($theFile);
1594 $params .= trim($size)?'&size='.trim($size):'';
1595 $url = $thumbScript.'?&dummy='.$GLOBALS['EXEC_TIME'].$params;
1596 $th='<img src="'.htmlspecialchars($url).'" title="'.trim(basename($theFile)).'"'.($tparams?" ".$tparams:"").' alt="" />';
1597 return $th;
1598 }
1599
1600 /**
1601 * Returns title-attribute information for a page-record informing about id, alias, doktype, hidden, starttime, endtime, fe_group etc.
1602 * Usage: 8
1603 *
1604 * @param array Input must be a page row ($row) with the proper fields set (be sure - send the full range of fields for the table)
1605 * @param string $perms_clause is used to get the record path of the shortcut page, if any (and doktype==4)
1606 * @param boolean If $includeAttrib is set, then the 'title=""' attribute is wrapped about the return value, which is in any case htmlspecialchar()'ed already
1607 * @return string
1608 */
1609 function titleAttribForPages($row,$perms_clause='',$includeAttrib=1) {
1610 global $TCA,$LANG;
1611 $parts=array();
1612 $parts[] = 'id='.$row['uid'];
1613 if ($row['alias']) $parts[]=$LANG->sL($TCA['pages']['columns']['alias']['label']).' '.$row['alias'];
1614 if ($row['pid']<0) $parts[] = 'v#1.'.$row['t3ver_id'];
1615 if ($row['doktype']=='3') {
1616 $parts[]=$LANG->sL($TCA['pages']['columns']['url']['label']).' '.$row['url'];
1617 } elseif ($row['doktype']=='4') {
1618 if ($perms_clause) {
1619 $label = t3lib_BEfunc::getRecordPath(intval($row['shortcut']),$perms_clause,20);
1620 } else {
1621 $lRec = t3lib_BEfunc::getRecord('pages',intval($row['shortcut']),'title');
1622 $label = $lRec['title'];
1623 }
1624 if ($row['shortcut_mode']>0) {
1625 $label.=', '.$LANG->sL($TCA['pages']['columns']['shortcut_mode']['label']).' '.
1626 $LANG->sL(t3lib_BEfunc::getLabelFromItemlist('pages','shortcut_mode',$row['shortcut_mode']));
1627 }
1628 $parts[]=$LANG->sL($TCA['pages']['columns']['shortcut']['label']).' '.$label;
1629 } elseif ($row['doktype']=='7') {
1630 if ($perms_clause) {
1631 $label = t3lib_BEfunc::getRecordPath(intval($row['mount_pid']),$perms_clause,20);
1632 } else {
1633 $lRec = t3lib_BEfunc::getRecord('pages',intval($row['mount_pid']),'title');
1634 $label = $lRec['title'];
1635 }
1636 $parts[]=$LANG->sL($TCA['pages']['columns']['mount_pid']['label']).' '.$label;
1637 if ($row['mount_pid_ol']) {
1638 $parts[] = $LANG->sL($TCA['pages']['columns']['mount_pid_ol']['label']);
1639 }
1640 }
1641 if ($row['nav_hide']) $parts[] = ereg_replace(':$','',$LANG->sL($TCA['pages']['columns']['nav_hide']['label']));
1642 if ($row['hidden']) $parts[] = $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.hidden');
1643 if ($row['starttime']) $parts[] = $LANG->sL($TCA['pages']['columns']['starttime']['label']).' '.t3lib_BEfunc::dateTimeAge($row['starttime'],-1,'date');
1644 if ($row['endtime']) $parts[] = $LANG->sL($TCA['pages']['columns']['endtime']['label']).' '.t3lib_BEfunc::dateTimeAge($row['endtime'],-1,'date');
1645 if ($row['fe_group']) {
1646 if ($row['fe_group']<0) {
1647 $label = $LANG->sL(t3lib_BEfunc::getLabelFromItemlist('pages','fe_group',$row['fe_group']));
1648 } else {
1649 $lRec = t3lib_BEfunc::getRecord('fe_groups',$row['fe_group'],'title');
1650 $label = $lRec['title'];
1651 }
1652 $parts[] = $LANG->sL($TCA['pages']['columns']['fe_group']['label']).' '.$label;
1653 }
1654 $out = htmlspecialchars(implode(' - ',$parts));
1655 return $includeAttrib ? 'title="'.$out.'"' : $out;
1656 }
1657
1658 /**
1659 * Returns title-attribute information for ANY record (from a table defined in TCA of course)
1660 * The included information depends on features of the table, but if hidden, starttime, endtime and fe_group fields are configured for, information about the record status in regard to these features are is included.
1661 * "pages" table can be used as well and will return the result of ->titleAttribForPages() for that page.
1662 * Usage: 10
1663 *
1664 * @param array Table row; $row is a row from the table, $table
1665 * @param string Table name
1666 * @return string
1667 */
1668 function getRecordIconAltText($row,$table='pages') {
1669 if ($table=='pages') {
1670 $out = t3lib_BEfunc::titleAttribForPages($row,'',0);
1671 } else {
1672 $ctrl = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns'];
1673
1674 $out='id='.$row['uid']; // Uid is added
1675 if ($table=='pages' && $row['alias']) {
1676 $out.=' / '.$row['alias'];
1677 }
1678 if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS'] && $row['pid']<0) {
1679 $out.=' - v#1.'.$row['t3ver_id'];
1680 }
1681 if ($ctrl['disabled']) { // Hidden ...
1682 $out.=($row[$ctrl['disabled']]?' - '.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.hidden'):'');
1683 }
1684 if ($ctrl['starttime']) {
1685 if ($row[$ctrl['starttime']] > $GLOBALS['EXEC_TIME']) {
1686 $out.=' - '.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.starttime').':'.t3lib_BEfunc::date($row[$ctrl['starttime']]).' ('.t3lib_BEfunc::daysUntil($row[$ctrl['starttime']]).' '.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.days').')';
1687 }
1688 }
1689 if ($row[$ctrl['endtime']]) {
1690 $out.=' - '.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.endtime').': '.t3lib_BEfunc::date($row[$ctrl['endtime']]).' ('.t3lib_BEfunc::daysUntil($row[$ctrl['endtime']]).' '.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.days').')';
1691 }
1692 }
1693 return htmlspecialchars($out);
1694 }
1695
1696 /**
1697 * Returns the label of the first found entry in an "items" array from $TCA (tablename=$table/fieldname=$col) where the value is $key
1698 * Usage: 9
1699 *
1700 * @param string Table name, present in $TCA
1701 * @param string Field name, present in $TCA
1702 * @param string items-array value to match
1703 * @return string Label for item entry
1704 */
1705 function getLabelFromItemlist($table,$col,$key) {
1706 global $TCA;
1707 // Load full TCA for $table
1708 t3lib_div::loadTCA($table);
1709
1710 // Check, if there is an "items" array:
1711 if (is_array($TCA[$table]) && is_array($TCA[$table]['columns'][$col]) && is_array($TCA[$table]['columns'][$col]['config']['items'])) {
1712 // Traverse the items-array...
1713 reset($TCA[$table]['columns'][$col]['config']['items']);
1714 while(list($k,$v)=each($TCA[$table]['columns'][$col]['config']['items'])) {
1715 // ... and return the first found label where the value was equal to $key
1716 if (!strcmp($v[1],$key)) return $v[0];
1717 }
1718 }
1719 }
1720
1721 /**
1722 * Returns the label-value for fieldname $col in table, $table
1723 * If $printAllWrap is set (to a "wrap") then it's wrapped around the $col value IF THE COLUMN $col DID NOT EXIST in TCA!, eg. $printAllWrap='<b>|</b>' and the fieldname was 'not_found_field' then the return value would be '<b>not_found_field</b>'
1724 * Usage: 17
1725 *
1726 * @param string Table name, present in $TCA
1727 * @param string Field name
1728 * @param string Wrap value - set function description
1729 * @return string
1730 */
1731 function getItemLabel($table,$col,$printAllWrap='') {
1732 global $TCA;
1733 // Load full TCA for $table
1734 t3lib_div::loadTCA($table);
1735 // Check if column exists
1736 if (is_array($TCA[$table]) && is_array($TCA[$table]['columns'][$col])) {
1737 // Re
1738 return $TCA[$table]['columns'][$col]['label'];
1739 }
1740 if ($printAllWrap) {
1741 $parts = explode('|',$printAllWrap);
1742 return $parts[0].$col.$parts[1];
1743 }
1744 }
1745
1746 /**
1747 * Returns the "title"-value in record, $row, from table, $table
1748 * The field(s) from which the value is taken is determined by the "ctrl"-entries 'label', 'label_alt' and 'label_alt_force'
1749 * Usage: 26
1750 *
1751 * @param string Table name, present in TCA
1752 * @param array Row from table
1753 * @param boolean If set, result is prepared for output: The output is cropped to a limited lenght (depending on BE_USER->uc['titleLen']) and if no value is found for the title, '<em>[No title]</em>' is returned (localized). Further, the output is htmlspecialchars()'ed
1754 * @return string
1755 */
1756 function getRecordTitle($table,$row,$prep=0) {
1757 global $TCA;
1758 if (is_array($TCA[$table])) {
1759 $t = $row[$TCA[$table]['ctrl']['label']];
1760 if ($TCA[$table]['ctrl']['label_alt'] && ($TCA[$table]['ctrl']['label_alt_force'] || !strcmp($t,''))) {
1761 $altFields=t3lib_div::trimExplode(',',$TCA[$table]['ctrl']['label_alt'],1);
1762 $tA=array();
1763 $tA[]=$t;
1764 while(list(,$fN)=each($altFields)) {
1765 $t = $tA[] = trim(strip_tags($row[$fN]));
1766 if (strcmp($t,'') && !$TCA[$table]['ctrl']['label_alt_force']) break;
1767 }
1768 if ($TCA[$table]['ctrl']['label_alt_force']) $t=implode(', ',$tA);
1769 }
1770 if ($prep) {
1771 $t = htmlspecialchars(t3lib_div::fixed_lgd_cs($t,$GLOBALS['BE_USER']->uc['titleLen']));
1772 if (!strcmp(trim($t),'')) $t='<em>['.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.no_title',1).']</em>';
1773 }
1774 return $t;
1775 }
1776 }
1777
1778 /**
1779 * Returns a human readable output of a value from a record
1780 * For instance a database record relation would be looked up to display the title-value of that record. A checkbox with a "1" value would be "Yes", etc.
1781 * $table/$col is tablename and fieldname
1782 * REMEMBER to pass the output through htmlspecialchars() if you output it to the browser! (To protect it from XSS attacks and be XHTML compliant)
1783 * Usage: 24
1784 *
1785 * @param string Table name, present in TCA
1786 * @param string Field name, present in TCA
1787 * @param string $value is the value of that field from a selected record
1788 * @param integer $fixed_lgd_chars is the max amount of characters the value may occupy
1789 * @param boolean $defaultPassthrough flag means that values for columns that has no conversion will just be pass through directly (otherwise cropped to 200 chars or returned as "N/A")
1790 * @param boolean If set, no records will be looked up, UIDs are just shown.
1791 * @param integer uid of the current record
1792 * @return string
1793 */
1794 function getProcessedValue($table,$col,$value,$fixed_lgd_chars=0,$defaultPassthrough=0,$noRecordLookup=FALSE,$uid=0) {
1795 global $TCA;
1796 // Load full TCA for $table
1797 t3lib_div::loadTCA($table);
1798 // Check if table and field is configured:
1799 if (is_array($TCA[$table]) && is_array($TCA[$table]['columns'][$col])) {
1800 // Depending on the fields configuration, make a meaningful output value.
1801 $theColConf = $TCA[$table]['columns'][$col]['config'];
1802 $l='';
1803 switch((string)$theColConf['type']) {
1804 case 'radio':
1805 $l=t3lib_BEfunc::getLabelFromItemlist($table,$col,$value);
1806 $l=$GLOBALS['LANG']->sL($l);
1807 break;
1808 case 'select':
1809 if ($theColConf['MM']) {
1810 // Display the title of MM related records in lists
1811 $MMres = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query(
1812 $theColConf['foreign_table'].'.'.$TCA[$theColConf['foreign_table']]['ctrl']['label'],
1813 $table,
1814 $theColConf['MM'],
1815 $theColConf['foreign_table'],
1816 'AND '.$table.'.uid ='.intval($uid).t3lib_BEfunc::deleteClause($theColConf['foreign_table'])
1817 );
1818 if ($MMres) {
1819 while($MMrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($MMres)) {
1820 $mmlA[] = $MMrow[$TCA[$theColConf['foreign_table']]['ctrl']['label']];
1821 }
1822 if (is_array($mmlA)) {
1823 $l=implode(', ',$mmlA);
1824 } else {
1825 $l = '';
1826 }
1827 } else {
1828 $l = 'n/A';
1829 }
1830 } else {
1831 $l = t3lib_BEfunc::getLabelFromItemlist($table,$col,$value);
1832 $l = $GLOBALS['LANG']->sL($l);
1833 if ($theColConf['foreign_table'] && !$l && $TCA[$theColConf['foreign_table']]) {
1834 if ($noRecordLookup) {
1835 $l = $value;
1836 } else {
1837 $rParts = t3lib_div::trimExplode(',',$value,1);
1838 reset($rParts);
1839 $lA = array();
1840 while(list(,$rVal)=each($rParts)) {
1841 $rVal = intval($rVal);
1842 if ($rVal>0) {
1843 $r=t3lib_BEfunc::getRecord($theColConf['foreign_table'],$rVal);
1844 } else {
1845 $r=t3lib_BEfunc::getRecord($theColConf['neg_foreign_table'],-$rVal);
1846 }
1847 if (is_array($r)) {
1848 $lA[]=$GLOBALS['LANG']->sL($rVal>0?$theColConf['foreign_table_prefix']:$theColConf['neg_foreign_table_prefix']).t3lib_BEfunc::getRecordTitle($rVal>0?$theColConf['foreign_table']:$theColConf['neg_foreign_table'],$r);
1849 } else {
1850 $lA[]=$rVal?'['.$rVal.'!]':'';
1851 }
1852 }
1853 $l = implode(', ',$lA);
1854 }
1855 }
1856 }
1857 break;
1858 case 'group':
1859 $l = implode(', ',t3lib_div::trimExplode(',',$value,1));
1860 break;
1861 case 'check':
1862 if (!is_array($theColConf['items']) || count($theColConf['items'])==1) {
1863 $l = $value ? 'Yes' : '';
1864 } else {
1865 reset($theColConf['items']);
1866 $lA=Array();
1867 while(list($key,$val)=each($theColConf['items'])) {
1868 if ($value & pow(2,$key)) {$lA[]=$GLOBALS['LANG']->sL($val[0]);}
1869 }
1870 $l = implode(', ',$lA);
1871 }
1872 break;
1873 case 'input':
1874 if ($value) {
1875 if (t3lib_div::inList($theColConf['eval'],'date')) {
1876 $l = t3lib_BEfunc::date($value).' ('.(time()-$value>0?'-':'').t3lib_BEfunc::calcAge(abs(time()-$value), $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.minutesHoursDaysYears')).')';
1877 } elseif (t3lib_div::inList($theColConf['eval'],'time')) {
1878 $l = t3lib_BEfunc::time($value);
1879 } elseif (t3lib_div::inList($theColConf['eval'],'datetime')) {
1880 $l = t3lib_BEfunc::datetime($value);
1881 } else {
1882 $l = $value;
1883 }
1884 }
1885 break;
1886 default:
1887 if ($defaultPassthrough) {
1888 $l=$value;
1889 } elseif ($theColConf['MM']) {
1890 $l='N/A';
1891 } elseif ($value) {
1892 $l=t3lib_div::fixed_lgd_cs(strip_tags($value),200);
1893 }
1894 break;
1895 }
1896 if ($fixed_lgd_chars) {
1897 return t3lib_div::fixed_lgd_cs($l,$fixed_lgd_chars);
1898 } else {
1899 return $l;
1900 }
1901 }
1902 }
1903
1904 /**
1905 * Same as ->getProcessedValue() but will go easy on fields like "tstamp" and "pid" which are not configured in TCA - they will be formatted by this function instead.
1906 * Usage: 2
1907 *
1908 * @param string Table name, present in TCA
1909 * @param string Field name
1910 * @param string Field value
1911 * @param integer $fixed_lgd_chars is the max amount of characters the value may occupy
1912 * @param integer uid of the current record
1913 * @return string
1914 * @see getProcessedValue()
1915 */
1916 function getProcessedValueExtra($table,$fN,$fV,$fixed_lgd_chars=0,$uid=0) {
1917 global $TCA;
1918 $fVnew = t3lib_BEfunc::getProcessedValue($table,$fN,$fV,$fixed_lgd_chars,0,0,$uid);
1919 if (!isset($fVnew)) {
1920 if (is_array($TCA[$table])) {
1921 if ($fN==$TCA[$table]['ctrl']['tstamp'] || $fN==$TCA[$table]['ctrl']['crdate']) {
1922 $fVnew = t3lib_BEfunc::datetime($fV);
1923 } elseif ($fN=='pid'){
1924 $fVnew = t3lib_BEfunc::getRecordPath($fV,'1=1',20); // Fetches the path with no regard to the users permissions to select pages.
1925 } else {
1926 $fVnew = $fV;
1927 }
1928 }
1929 }
1930 return $fVnew;
1931 }
1932
1933 /**
1934 * Returns file icon name (from $FILEICONS) for the fileextension $ext
1935 * Usage: 10
1936 *
1937 * @param string File extension, lowercase
1938 * @return string File icon filename
1939 */
1940 function getFileIcon($ext) {
1941 return $GLOBALS['FILEICONS'][$ext] ? $GLOBALS['FILEICONS'][$ext] : $GLOBALS['FILEICONS']['default'];
1942 }
1943
1944 /**
1945 * Returns fields for a table, $table, which would typically be interesting to select
1946 * This includes uid, the fields defined for title, icon-field.
1947 * Returned as a list ready for query ($prefix can be set to eg. "pages." if you are selecting from the pages table and want the table name prefixed)
1948 * Usage: 3
1949 *
1950 * @param string Table name, present in TCA
1951 * @param string Table prefix
1952 * @return string List of fields.
1953 */
1954 function getCommonSelectFields($table,$prefix) {
1955 global $TCA;
1956 $fields = array();
1957 $fields[] = $prefix.'uid';
1958 $fields[] = $prefix.$TCA[$table]['ctrl']['label'];
1959
1960 if ($TCA[$table]['ctrl']['label_alt']) {
1961 $secondFields = t3lib_div::trimExplode(',',$TCA[$table]['ctrl']['label_alt'],1);
1962 foreach($secondFields as $fieldN) {
1963 $fields[] = $prefix.$fieldN;
1964 }
1965 }
1966 if ($TCA[$table]['ctrl']['versioningWS']) {
1967 $fields[] = $prefix.'t3ver_id';
1968 $fields[] = $prefix.'t3ver_state';
1969 }
1970
1971 if ($TCA[$table]['ctrl']['selicon_field']) $fields[] = $prefix.$TCA[$table]['ctrl']['selicon_field'];
1972 if ($TCA[$table]['ctrl']['typeicon_column']) $fields[] = $prefix.$TCA[$table]['ctrl']['typeicon_column'];
1973
1974 if (is_array($TCA[$table]['ctrl']['enablecolumns'])) {
1975 if ($TCA[$table]['ctrl']['enablecolumns']['disabled']) $fields[] = $prefix.$TCA[$table]['ctrl']['enablecolumns']['disabled'];
1976 if ($TCA[$table]['ctrl']['enablecolumns']['starttime']) $fields[] = $prefix.$TCA[$table]['ctrl']['enablecolumns']['starttime'];
1977 if ($TCA[$table]['ctrl']['enablecolumns']['endtime']) $fields[] = $prefix.$TCA[$table]['ctrl']['enablecolumns']['endtime'];
1978 if ($TCA[$table]['ctrl']['enablecolumns']['fe_group']) $fields[] = $prefix.$TCA[$table]['ctrl']['enablecolumns']['fe_group'];
1979 }
1980
1981 return implode(',', array_unique($fields));
1982 }
1983
1984 /**
1985 * Makes a form for configuration of some values based on configuration found in the array $configArray, with default values from $defaults and a data-prefix $dataPrefix
1986 * <form>-tags must be supplied separately
1987 * Needs more documentation and examples, in particular syntax for configuration array. See Inside TYPO3. That's were you can expect to find example, if anywhere.
1988 * Usage: 1 (ext. direct_mail)
1989 *
1990 * @param array Field configuration code.
1991 * @param array Defaults
1992 * @param string Prefix for formfields
1993 * @return string HTML for a form.
1994 */
1995 function makeConfigForm($configArray,$defaults,$dataPrefix) {
1996 $params = $defaults;
1997 if (is_array($configArray)) {
1998 reset($configArray);
1999 $lines=array();
2000 while(list($fname,$config)=each($configArray)) {
2001 if (is_array($config)) {
2002 $lines[$fname]='<strong>'.htmlspecialchars($config[1]).'</strong><br />';
2003 $lines[$fname].=$config[2].'<br />';
2004 switch($config[0]) {
2005 case 'string':
2006 case 'short':
2007 $formEl = '<input type="text" name="'.$dataPrefix.'['.$fname.']" value="'.$params[$fname].'"'.$GLOBALS['TBE_TEMPLATE']->formWidth($config[0]=='short'?24:48).' />';
2008 break;
2009 case 'check':
2010 $formEl = '<input type="hidden" name="'.$dataPrefix.'['.$fname.']" value="0" /><input type="checkbox" name="'.$dataPrefix.'['.$fname.']" value="1"'.($params[$fname]?' checked="checked"':'').' />';
2011 break;
2012 case 'comment':
2013 $formEl = '';
2014 break;
2015 case 'select':
2016 reset($config[3]);
2017 $opt=array();
2018 while(list($k,$v)=each($config[3])) {
2019 $opt[]='<option value="'.htmlspecialchars($k).'"'.($params[$fname]==$k?' selected="selected"':'').'>'.htmlspecialchars($v).'</option>';
2020 }
2021 $formEl = '<select name="'.$dataPrefix.'['.$fname.']">'.implode('',$opt).'</select>';
2022 break;
2023 default:
2024 debug($config);
2025 break;
2026 }
2027 $lines[$fname].=$formEl;
2028 $lines[$fname].='<br /><br />';
2029 } else {
2030 $lines[$fname]='<hr />';
2031 if ($config) $lines[$fname].='<strong>'.strtoupper(htmlspecialchars($config)).'</strong><br />';
2032 if ($config) $lines[$fname].='<br />';
2033 }
2034 }
2035 }
2036 $out = implode('',$lines);
2037 $out.='<input type="submit" name="submit" value="Update configuration" />';
2038 return $out;
2039 }
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053 /*******************************************
2054 *
2055 * Backend Modules API functions
2056 *
2057 *******************************************/
2058
2059 /**
2060 * Returns help-text icon if configured for.
2061 * TCA_DESCR must be loaded prior to this function and $BE_USER must have 'edit_showFieldHelp' set to 'icon', otherwise nothing is returned
2062 * Usage: 6
2063 *
2064 * @param string Table name
2065 * @param string Field name
2066 * @param string Back path
2067 * @param boolean Force display of icon nomatter BE_USER setting for help
2068 * @return string HTML content for a help icon/text
2069 */
2070 function helpTextIcon($table,$field,$BACK_PATH,$force=0) {
2071 global $TCA_DESCR,$BE_USER;
2072 if (is_array($TCA_DESCR[$table]) && is_array($TCA_DESCR[$table]['columns'][$field]) && ($BE_USER->uc['edit_showFieldHelp']=='icon' || $force)) {
2073 $onClick = 'vHWin=window.open(\''.$BACK_PATH.'view_help.php?tfID='.($table.'.'.$field).'\',\'viewFieldHelp\',\'height=400,width=600,status=0,menubar=0,scrollbars=1\');vHWin.focus();return false;';
2074 return '<a href="#" onclick="'.htmlspecialchars($onClick).'">'.
2075 '<img'.t3lib_iconWorks::skinImg($BACK_PATH,'gfx/helpbubble.gif','width="14" height="14"').' hspace="2" border="0" class="typo3-csh-icon" alt="" />'.
2076 '</a>';
2077 }
2078 }
2079
2080 /**
2081 * Returns CSH help text (description), if configured for.
2082 * TCA_DESCR must be loaded prior to this function and $BE_USER must have "edit_showFieldHelp" set to "text", otherwise nothing is returned
2083 * Will automatically call t3lib_BEfunc::helpTextIcon() to get the icon for the text.
2084 * Usage: 4
2085 *
2086 * @param string Table name
2087 * @param string Field name
2088 * @param string Back path
2089 * @param string Additional style-attribute content for wrapping table
2090 * @return string HTML content for help text
2091 */
2092 function helpText($table,$field,$BACK_PATH,$styleAttrib='') {
2093 global $TCA_DESCR,$BE_USER;
2094 if (is_array($TCA_DESCR[$table]) && is_array($TCA_DESCR[$table]['columns'][$field]) && $BE_USER->uc['edit_showFieldHelp']=='text') {
2095 $fDat = $TCA_DESCR[$table]['columns'][$field];
2096
2097 // Get Icon:
2098 $editIcon = t3lib_BEfunc::helpTextIcon(
2099 $table,
2100 $field,
2101 $BACK_PATH,
2102 TRUE
2103 );
2104 // Add title?
2105 $onClick = 'vHWin=window.open(\''.$BACK_PATH.'view_help.php?tfID='.($table.'.'.$field).'\',\'viewFieldHelp\',\'height=400,width=600,status=0,menubar=0,scrollbars=1\');vHWin.focus();return false;';
2106 $text =
2107 ($fDat['alttitle'] ? '<h4><a href="#" onclick="'.htmlspecialchars($onClick).'">'.$fDat['alttitle'].'</a></h4>' : '').
2108 $fDat['description'];
2109
2110 // More information to get?
2111 if ($fDat['image_descr'] || $fDat['seeAlso'] || $fDat['details'] || $fDat['syntax']) { // || $fDat['image'];
2112 $text.=' <a href="#" onclick="'.htmlspecialchars($onClick).'">'.
2113 '<img'.t3lib_iconWorks::skinImg($BACK_PATH,'gfx/rel_db.gif','width="13" height="12"').' class="absmiddle typo3-csh-more" alt="" />'.
2114 '</a>';
2115 }
2116
2117 // Additional styles?
2118 $params = $styleAttrib ? ' style="'.$styleAttrib.'"' : '';
2119
2120 // Compile table with CSH information:
2121 return '<table border="0" cellpadding="2" cellspacing="0" class="typo3-csh-inline"'.$params.'>
2122 <tr>
2123 <td valign="top" width="14">'.$editIcon.'</td>
2124 <td valign="top">'.$text.'</td>
2125 </tr>
2126 </table>';
2127 }
2128 }
2129
2130 /**
2131 * API for getting CSH icons/text for use in backend modules.
2132 * TCA_DESCR will be loaded if it isn't already
2133 * Usage: ?
2134 *
2135 * @param string Table name ('_MOD_'+module name)
2136 * @param string Field name (CSH locallang main key)
2137 * @param string Back path
2138 * @param string Wrap code for icon-mode, splitted by "|". Not used for full-text mode.
2139 * @param boolean If set, the full text will never be shown (only icon). Useful for places where it will break the page if the table with full text is shown.
2140 * @param string Additional style-attribute content for wrapping table (full text mode only)
2141 * @return string HTML content for help text
2142 * @see helpText(), helpTextIcon()
2143 */
2144 function cshItem($table,$field,$BACK_PATH,$wrap='',$onlyIconMode=FALSE, $styleAttrib='') {
2145 global $TCA_DESCR, $LANG, $BE_USER;
2146 if ($BE_USER->uc['edit_showFieldHelp']) {
2147 $LANG->loadSingleTableDescription($table);
2148
2149 if (is_array($TCA_DESCR[$table])) {
2150 // Creating CSH icon and short description:
2151 $fullText = t3lib_BEfunc::helpText($table,$field,$BACK_PATH,$styleAttrib);
2152 $icon = t3lib_BEfunc::helpTextIcon($table,$field,$BACK_PATH,$onlyIconMode);
2153
2154 if ($fullText && !$onlyIconMode) {
2155 $output = $fullText;
2156 } else {
2157 #$output = '<span style="position:absolute; filter: alpha(opacity=50); -moz-opacity: 0.50;">'.$icon.'</span>';
2158 $output = $icon;
2159
2160 if ($output && $wrap) {
2161 $wrParts = explode('|',$wrap);
2162 $output = $wrParts[0].$output.$wrParts[1];
2163 }
2164 }
2165
2166 return $output;
2167 }
2168 }
2169 }
2170
2171 /**
2172 * Returns a JavaScript string (for an onClick handler) which will load the alt_doc.php script that shows the form for editing of the record(s) you have send as params.
2173 * REMEMBER to always htmlspecialchar() content in href-properties to ampersands get converted to entities (XHTML requirement and XSS precaution)
2174 * Usage: 35
2175 *
2176 * @param string $params is parameters sent along to alt_doc.php. This requires a much more details description which you must seek in Inside TYPO3s documentation of the alt_doc.php API. And example could be '&edit[pages][123]=edit' which will show edit form for page record 123.
2177 * @param string $backPath must point back to the TYPO3_mainDir directory (where alt_doc.php is)
2178 * @param string $requestUri is an optional returnUrl you can set - automatically set to REQUEST_URI.
2179 * @return string
2180 * @see template::issueCommand()
2181 */
2182 function editOnClick($params,$backPath='',$requestUri='') {
2183 $retUrl = 'returnUrl='.($requestUri==-1?"'+T3_THIS_LOCATION+'":rawurlencode($requestUri?$requestUri:t3lib_div::getIndpEnv('REQUEST_URI')));
2184 return "document.location='".$backPath."alt_doc.php?".$retUrl.$params."'; return false;";
2185 }
2186
2187 /**
2188 * Returns a JavaScript string for viewing the page id, $id
2189 * It will detect the correct domain name if needed and provide the link with the right back path. Also it will re-use any window already open.
2190 * Usage: 8
2191 *
2192 * @param integer $id is page id
2193 * @param string $backpath must point back to TYPO3_mainDir (where the site is assumed to be one level above)
2194 * @param array If root line is supplied the function will look for the first found domain record and use that URL instead (if found)
2195 * @param string $anchor is optional anchor to the URL
2196 * @param string $altUrl is an alternative URL which - if set - will make all other parameters ignored: The function will just return the window.open command wrapped around this URL!
2197 * @param string Additional GET variables.
2198 * @param boolean If true, then the preview window will gain the focus.
2199 * @return string
2200 */
2201 function viewOnClick($id,$backPath='',$rootLine='',$anchor='',$altUrl='',$addGetVars='',$switchFocus=TRUE) {
2202 if ($altUrl) {
2203 $url = $altUrl;
2204 } else {
2205 if ($rootLine) {
2206 $parts = parse_url(t3lib_div::getIndpEnv('TYPO3_SITE_URL'));
2207 if (t3lib_BEfunc::getDomainStartPage($parts['host'],$parts['path'])) {
2208 $preUrl_temp = t3lib_BEfunc::firstDomainRecord($rootLine);
2209 }
2210 }
2211 $preUrl = $preUrl_temp ? (t3lib_div::getIndpEnv('TYPO3_SSL') ? 'https://' : 'http://').$preUrl_temp : $backPath.'..';
2212 $url = $preUrl.'/index.php?id='.$id.$addGetVars.$anchor;
2213 }
2214
2215 return "previewWin=window.open('".$url."','newTypo3FrontendWindow','status=1,menubar=1,resizable=1,location=1,scrollbars=1,toolbar=1');".
2216 ($switchFocus ? 'previewWin.focus();' : '');
2217 }
2218
2219 /**
2220 * Returns the merged User/Page TSconfig for page id, $id.
2221 * Please read details about module programming elsewhere!
2222 * Usage: 15
2223 *
2224 * @param integer Page uid
2225 * @param string $TSref is an object string which determines the path of the TSconfig to return.
2226 * @return array
2227 */
2228 function getModTSconfig($id,$TSref) {
2229 $pageTS_modOptions = $GLOBALS['BE_USER']->getTSConfig($TSref,t3lib_BEfunc::getPagesTSconfig($id));
2230 $BE_USER_modOptions = $GLOBALS['BE_USER']->getTSConfig($TSref);
2231 $modTSconfig = t3lib_div::array_merge_recursive_overrule($pageTS_modOptions,$BE_USER_modOptions);
2232 return $modTSconfig;
2233 }
2234
2235 /**
2236 * Returns a selector box "function menu" for a module
2237 * Requires the JS function jumpToUrl() to be available
2238 * See Inside TYPO3 for details about how to use / make Function menus
2239 * Usage: 50
2240 *
2241 * @param mixed $id is the "&id=" parameter value to be sent to the module, but it can be also a parameter array which will be passed instead of the &id=...
2242 * @param string $elementName it the form elements name, probably something like "SET[...]"
2243 * @param string $currentValue is the value to be selected currently.
2244 * @param array $menuItems is an array with the menu items for the selector box
2245 * @param string $script is the script to send the &id to, if empty it's automatically found
2246 * @param string $addParams is additional parameters to pass to the script.
2247 * @return string HTML code for selector box
2248 */
2249 function getFuncMenu($mainParams,$elementName,$currentValue,$menuItems,$script='',$addparams='') {
2250 if (is_array($menuItems)) {
2251 if (!is_array($mainParams)) {
2252 $mainParams = array('id' => $mainParams);
2253 }
2254 $mainParams = t3lib_div::implodeArrayForUrl('',$mainParams);
2255
2256 if (!$script) { $script=basename(PATH_thisScript); }
2257
2258 $options = array();
2259 foreach($menuItems as $value => $label) {
2260 $options[] = '<option value="'.htmlspecialchars($value).'"'.(!strcmp($currentValue,$value)?' selected="selected"':'').'>'.
2261 t3lib_div::deHSCentities(htmlspecialchars($label)).
2262 '</option>';
2263 }
2264 if (count($options)) {
2265 $onChange = 'jumpToUrl(\''.$script.'?'.$mainParams.$addparams.'&'.$elementName.'=\'+this.options[this.selectedIndex].value,this);';
2266 return '
2267
2268 <!-- Function Menu of module -->
2269 <select name="'.$elementName.'" onchange="'.htmlspecialchars($onChange).'">
2270 '.implode('
2271 ',$options).'
2272 </select>
2273 ';
2274 }
2275 }
2276 }
2277
2278 /**
2279 * Checkbox function menu.
2280 * Works like ->getFuncMenu() but takes no $menuItem array since this is a simple checkbox.
2281 * Usage: 34
2282 *
2283 * @param mixed $mainParams $id is the "&id=" parameter value to be sent to the module, but it can be also a parameter array which will be passed instead of the &id=...
2284 * @param string $elementName it the form elements name, probably something like "SET[...]"
2285 * @param string $currentValue is the value to be selected currently.
2286 * @param string $script is the script to send the &id to, if empty it's automatically found
2287 * @param string $addParams is additional parameters to pass to the script.
2288 * @param string Additional attributes for the checkbox input tag
2289 * @return string HTML code for checkbox
2290 * @see getFuncMenu()
2291 */
2292 function getFuncCheck($mainParams,$elementName,$currentValue,$script='',$addparams='',$tagParams='') {
2293 if (!is_array($mainParams)) {
2294 $mainParams = array('id' => $mainParams);
2295 }
2296 $mainParams = t3lib_div::implodeArrayForUrl('',$mainParams);
2297
2298 if (!$script) {basename(PATH_thisScript);}
2299 $onClick = 'jumpToUrl(\''.$script.'?'.$mainParams.$addparams.'&'.$elementName.'=\'+(this.checked?1:0),this);';
2300 return '<input type="checkbox" name="'.$elementName.'"'.($currentValue?' checked="checked"':'').' onclick="'.htmlspecialchars($onClick).'"'.($tagParams?' '.$tagParams:'').' />';
2301 }
2302
2303 /**
2304 * Input field function menu
2305 * Works like ->getFuncMenu() / ->getFuncCheck() but displays a input field instead which updates the script "onchange"
2306 * Usage: 1
2307 *
2308 * @param mixed $id is the "&id=" parameter value to be sent to the module, but it can be also a parameter array which will be passed instead of the &id=...
2309 * @param string $elementName it the form elements name, probably something like "SET[...]"
2310 * @param string $currentValue is the value to be selected currently.
2311 * @param integer Relative size of input field, max is 48
2312 * @param string $script is the script to send the &id to, if empty it's automatically found
2313 * @param string $addParams is additional parameters to pass to the script.
2314 * @return string HTML code for input text field.
2315 * @see getFuncMenu()
2316 */
2317 function getFuncInput($mainParams,$elementName,$currentValue,$size=10,$script="",$addparams="") {
2318 if (!is_array($mainParams)) {
2319 $mainParams = array('id' => $mainParams);
2320 }
2321 $mainParams = t3lib_div::implodeArrayForUrl('',$mainParams);
2322
2323 if (!$script) {basename(PATH_thisScript);}
2324 $onChange = 'jumpToUrl(\''.$script.'?'.$mainParams.$addparams.'&'.$elementName.'=\'+escape(this.value),this);';
2325 return '<input type="text"'.$GLOBALS['TBE_TEMPLATE']->formWidth($size).' name="'.$elementName.'" value="'.htmlspecialchars($currentValue).'" onchange="'.htmlspecialchars($onChange).'" />';
2326 }
2327
2328 /**
2329 * Removes menu items from $itemArray if they are configured to be removed by TSconfig for the module ($modTSconfig)
2330 * See Inside TYPO3 about how to program modules and use this API.
2331 * Usage: 4
2332 *
2333 * @param array Module TS config array
2334 * @param array Array of items from which to remove items.
2335 * @param string $TSref points to the "object string" in $modTSconfig
2336 * @return array The modified $itemArray is returned.
2337 */
2338 function unsetMenuItems($modTSconfig,$itemArray,$TSref) {
2339 // Getting TS-config options for this module for the Backend User:
2340 $conf = $GLOBALS['BE_USER']->getTSConfig($TSref,$modTSconfig);
2341 if (is_array($conf['properties'])) {
2342 reset($conf['properties']);
2343 while(list($key,$val)=each($conf['properties'])) {
2344 if (!$val) {
2345 unset($itemArray[$key]);
2346 }
2347 }
2348 }
2349 return $itemArray;
2350 }
2351
2352 /**
2353 * Call to update the page tree frame (or something else..?) after
2354 * t3lib_BEfunc::getSetUpdateSignal('updatePageTree') -> will set the page tree to be updated.
2355 * t3lib_BEfunc::getSetUpdateSignal() -> will return some JavaScript that does the update (called in the typo3/template.php file, end() function)
2356 * Usage: 11
2357 *
2358 * @param string Whether to set or clear the update signal. When setting, this value contains strings telling WHAT to set. At this point it seems that the value "updatePageTree" is the only one it makes sense to set.
2359 * @return string HTML code (<script> section)
2360 */
2361 function getSetUpdateSignal($set='') {
2362 global $BE_USER;
2363 $key = 't3lib_BEfunc::getSetUpdateSignal';
2364 $out='';
2365 if ($set) {
2366 $modData=array();
2367 $modData['set']=$set;
2368 $BE_USER->pushModuleData($key,$modData);
2369 } else {
2370 $modData = $BE_USER->getModuleData($key,'ses');
2371 if (trim($modData['set'])) {
2372 $l=explode(',',$modData['set']);
2373 while(list(,$v)=each($l)) {
2374 switch($v) {
2375 case 'updatePageTree':
2376 case 'updateFolderTree':
2377 $out.='
2378 <script type="text/javascript">
2379 /*<![CDATA[*/
2380 if (top.content && top.content.nav_frame && top.content.nav_frame.refresh_nav) {
2381 top.content.nav_frame.refresh_nav();
2382 }
2383 /*]]>*/
2384 </script>';
2385 break;
2386 }
2387 }
2388 $modData=array();
2389 $modData['set']='';
2390 $BE_USER->pushModuleData($key,$modData);
2391 }
2392 }
2393 return $out;
2394 }
2395
2396
2397 /**
2398 * Returns an array which is most backend modules becomes MOD_SETTINGS containing values from function menus etc. determining the function of the module.
2399 * This is kind of session variable management framework for the backend users.
2400 * If a key from MOD_MENU is set in the CHANGED_SETTINGS array (eg. a value is passed to the script from the outside), this value is put into the settings-array
2401 * Ultimately, see Inside TYPO3 for how to use this function in relation to your modules.
2402 * Usage: 23
2403 *
2404 * @param array MOD_MENU is an array that defines the options in menus.
2405 * @param array CHANGED_SETTINGS represents the array used when passing values to the script from the menus.
2406 * @param string modName is the name of this module. Used to get the correct module data.
2407 * @param string If type is 'ses' then the data is stored as session-lasting data. This means that it'll be wiped out the next time the user logs in.
2408 * @param string dontValidateList can be used to list variables that should not be checked if their value is found in the MOD_MENU array. Used for dynamically generated menus.
2409 * @param string List of default values from $MOD_MENU to set in the output array (only if the values from MOD_MENU are not arrays)
2410 * @return array The array $settings, which holds a key for each MOD_MENU key and the values of each key will be within the range of values for each menuitem
2411 */
2412 function getModuleData($MOD_MENU, $CHANGED_SETTINGS, $modName, $type='', $dontValidateList='', $setDefaultList='') {
2413
2414 if ($modName && is_string($modName)) {
2415 // GETTING stored user-data from this module:
2416 $settings = $GLOBALS['BE_USER']->getModuleData($modName,$type);
2417
2418 $changed=0;
2419 if (!is_array($settings)) {
2420 $changed=1;
2421 $settings=array();
2422 }
2423 if (is_array($MOD_MENU)) {
2424 reset($MOD_MENU);
2425 while(list($key,$var)=each($MOD_MENU)) {
2426 // If a global var is set before entering here. eg if submitted, then it's substituting the current value the array.
2427 if (is_array($CHANGED_SETTINGS) && isset($CHANGED_SETTINGS[$key]) && strcmp($settings[$key],$CHANGED_SETTINGS[$key])) {
2428 $settings[$key] = (string)$CHANGED_SETTINGS[$key];
2429 $changed=1;
2430 }
2431 // If the $var is an array, which denotes the existence of a menu, we check if the value is permitted
2432 if (is_array($var) && (!$dontValidateList || !t3lib_div::inList($dontValidateList,$key))) {
2433 // If the setting is an array or not present in the menu-array, MOD_MENU, then the default value is inserted.
2434 if (is_array($settings[$key]) || !isset($MOD_MENU[$key][$settings[$key]])) {
2435 $settings[$key]=(string)key($var);
2436 $changed=1;
2437 }
2438 }
2439 if ($setDefaultList && !is_array($var)) { // Sets default values (only strings/checkboxes, not menus)
2440 if (t3lib_div::inList($setDefaultList,$key) && !isset($settings[$key])) {
2441 $settings[$key]=$var;
2442 }
2443 }
2444 }
2445 } else {die ('No menu!');}
2446
2447 if ($changed) {
2448 $GLOBALS['BE_USER']->pushModuleData($modName,$settings);
2449 }
2450
2451 return $settings;
2452 } else {die ('Wrong module name: "'.$modName.'"');}
2453 }
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467 /*******************************************
2468 *
2469 * Core
2470 *
2471 *******************************************/
2472
2473 /**
2474 * Unlock or Lock a record from $table with $uid
2475 * If $table and $uid is not set, then all locking for the current BE_USER is removed!
2476 * Usage: 5
2477 *
2478 * @param string Table name
2479 * @param integer Record uid
2480 * @param integer Record pid
2481 * @return void
2482 * @internal
2483 * @see t3lib_transferData::lockRecord(), alt_doc.php, db_layout.php, db_list.php, wizard_rte.php
2484 */
2485 function lockRecords($table='',$uid=0,$pid=0) {
2486 $user_id = intval($GLOBALS['BE_USER']->user['uid']);
2487 if ($table && $uid) {
2488 $fields_values = array(
2489 'userid' => $user_id,
2490 'tstamp' => $GLOBALS['EXEC_TIME'],
2491 'record_table' => $table,
2492 'record_uid' => $uid,
2493 'username' => $GLOBALS['BE_USER']->user['username'],
2494 'record_pid' => $pid
2495 );
2496
2497 $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_lockedrecords', $fields_values);
2498 } else {
2499 $GLOBALS['TYPO3_DB']->exec_DELETEquery('sys_lockedrecords', 'userid='.intval($user_id));
2500 }
2501 }
2502
2503 /**
2504 * Returns information about whether the record from table, $table, with uid, $uid is currently locked (edited by another user - which should issue a warning).
2505 * Notice: Locking is not strictly carried out since locking is abandoned when other backend scripts are activated - which means that a user CAN have a record "open" without having it locked. So this just serves as a warning that counts well in 90% of the cases, which should be sufficient.
2506 * Usage: 5
2507 *
2508 * @param string Table name
2509 * @param integer Record uid
2510 * @return array
2511 * @internal
2512 * @see class.db_layout.inc, alt_db_navframe.php, alt_doc.php, db_layout.php
2513 */
2514 function isRecordLocked($table,$uid) {
2515 global $LOCKED_RECORDS;
2516 if (!is_array($LOCKED_RECORDS)) {
2517 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
2518 '*',
2519 'sys_lockedrecords',
2520 'sys_lockedrecords.userid!='.intval($GLOBALS['BE_USER']->user['uid']).'
2521 AND sys_lockedrecords.tstamp > '.($GLOBALS['EXEC_TIME']-2*3600)
2522 );
2523 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
2524 $LOCKED_RECORDS[$row['record_table'].':'.$row['record_uid']]=$row;
2525 $LOCKED_RECORDS[$row['record_table'].':'.$row['record_uid']]['msg']=sprintf(
2526 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.lockedRecord'),
2527 $row['username'],
2528 t3lib_BEfunc::calcAge($GLOBALS['EXEC_TIME']-$row['tstamp'],$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.minutesHoursDaysYears'))
2529 );
2530 if ($row['record_pid'] && !isset($LOCKED_RECORDS[$row['record_table'].':'.$row['record_pid']])) {
2531 $LOCKED_RECORDS['pages:'.$row['record_pid']]['msg']=sprintf(
2532 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.lockedRecord_content'),
2533 $row['username'],
2534 t3lib_BEfunc::calcAge($GLOBALS['EXEC_TIME']-$row['tstamp'],$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.minutesHoursDaysYears'))
2535 );
2536 }
2537 }
2538 }
2539 return $LOCKED_RECORDS[$table.':'.$uid];
2540 }
2541
2542 /**
2543 * Returns select statement for MM relations (as used by TCEFORMs etc)
2544 * Usage: 3
2545 *
2546 * @param array Configuration array for the field, taken from $TCA
2547 * @param string Field name
2548 * @param array TSconfig array from which to get further configuration settings for the field name
2549 * @param string Prefix string for the key "*foreign_table_where" from $fieldValue array
2550 * @return string Part of query
2551 * @internal
2552 * @see t3lib_transferData::renderRecord(), t3lib_TCEforms::foreignTable()
2553 */
2554 function exec_foreign_table_where_query($fieldValue,$field='',$TSconfig=array(),$prefix='') {
2555 global $TCA;
2556 $foreign_table = $fieldValue['config'][$prefix.'foreign_table'];
2557 $rootLevel = $TCA[$foreign_table]['ctrl']['rootLevel'];
2558
2559 $fTWHERE = $fieldValue['config'][$prefix.'foreign_table_where'];
2560 if (strstr($fTWHERE,'###REC_FIELD_')) {
2561 $fTWHERE_parts = explode('###REC_FIELD_',$fTWHERE);
2562 while(list($kk,$vv)=each($fTWHERE_parts)) {
2563 if ($kk) {
2564 $fTWHERE_subpart = explode('###',$vv,2);
2565 $fTWHERE_parts[$kk]=$TSconfig['_THIS_ROW'][$fTWHERE_subpart[0]].$fTWHERE_subpart[1];
2566 }
2567 }
2568 $fTWHERE = implode('',$fTWHERE_parts);
2569 }
2570
2571 $fTWHERE = str_replace('###CURRENT_PID###',intval($TSconfig['_CURRENT_PID']),$fTWHERE);
2572 $fTWHERE = str_replace('###THIS_UID###',intval($TSconfig['_THIS_UID']),$fTWHERE);
2573 $fTWHERE = str_replace('###THIS_CID###',intval($TSconfig['_THIS_CID']),$fTWHERE);
2574 $fTWHERE = str_replace('###STORAGE_PID###',intval($TSconfig['_STORAGE_PID']),$fTWHERE);
2575 $fTWHERE = str_replace('###SITEROOT###',intval($TSconfig['_SITEROOT']),$fTWHERE);
2576 $fTWHERE = str_replace('###PAGE_TSCONFIG_ID###',intval($TSconfig[$field]['PAGE_TSCONFIG_ID']),$fTWHERE);
2577 $fTWHERE = str_replace('###PAGE_TSCONFIG_IDLIST###',$GLOBALS['TYPO3_DB']->cleanIntList($TSconfig[$field]['PAGE_TSCONFIG_IDLIST']),$fTWHERE);
2578 $fTWHERE = str_replace('###PAGE_TSCONFIG_STR###',$GLOBALS['TYPO3_DB']->quoteStr($TSconfig[$field]['PAGE_TSCONFIG_STR'], $foreign_table),$fTWHERE);
2579
2580 // rootLevel = -1 is not handled 'properly' here - it goes as if it was rootLevel = 1 (that is pid=0)
2581 $wgolParts = $GLOBALS['TYPO3_DB']->splitGroupOrderLimit($fTWHERE);
2582 if ($rootLevel) {
2583 $queryParts = array(
2584 'SELECT' => t3lib_BEfunc::getCommonSelectFields($foreign_table,$foreign_table.'.'),
2585 'FROM' => $foreign_table,
2586 'WHERE' => $foreign_table.'.pid=0 '.
2587 t3lib_BEfunc::deleteClause($foreign_table).' '.
2588 $wgolParts['WHERE'],
2589 'GROUPBY' => $wgolParts['GROUPBY'],
2590 'ORDERBY' => $wgolParts['ORDERBY'],
2591 'LIMIT' => $wgolParts['LIMIT']
2592 );
2593 } else {
2594 $pageClause = $GLOBALS['BE_USER']->getPagePermsClause(1);
2595 if ($foreign_table!='pages') {
2596 $queryParts = array(
2597 'SELECT' => t3lib_BEfunc::getCommonSelectFields($foreign_table,$foreign_table.'.'),
2598 'FROM' => $foreign_table.',pages',
2599 'WHERE' => 'pages.uid='.$foreign_table.'.pid
2600 AND pages.deleted=0 '.
2601 t3lib_BEfunc::deleteClause($foreign_table).
2602 ' AND '.$pageClause.' '.
2603 $wgolParts['WHERE'],
2604 'GROUPBY' => $wgolParts['GROUPBY'],
2605 'ORDERBY' => $wgolParts['ORDERBY'],
2606 'LIMIT' => $wgolParts['LIMIT']
2607 );
2608 } else {
2609 $queryParts = array(
2610 'SELECT' => t3lib_BEfunc::getCommonSelectFields($foreign_table,$foreign_table.'.'),
2611 'FROM' => 'pages',
2612 'WHERE' => 'pages.deleted=0
2613 AND '.$pageClause.' '.
2614 $wgolParts['WHERE'],
2615 'GROUPBY' => $wgolParts['GROUPBY'],
2616 'ORDERBY' => $wgolParts['ORDERBY'],
2617 'LIMIT' => $wgolParts['LIMIT']
2618 );
2619 }
2620 }
2621
2622 return $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts);
2623 }
2624
2625 /**
2626 * Returns TSConfig for the TCEFORM object in Page TSconfig.
2627 * Used in TCEFORMs
2628 * Usage: 4
2629 *
2630 * @param string Table name present in TCA
2631 * @param array Row from table
2632 * @return array
2633 * @see t3lib_transferData::renderRecord(), t3lib_TCEforms::setTSconfig(), SC_wizard_list::main(), SC_wizard_add::main()
2634 */
2635 function getTCEFORM_TSconfig($table,$row) {
2636 t3lib_BEfunc::fixVersioningPid($table,$row);
2637
2638 $res = array();
2639 $typeVal = t3lib_BEfunc::getTCAtypeValue($table,$row);
2640
2641 // Get main config for the table
2642 list($TScID,$cPid) = t3lib_BEfunc::getTSCpid($table,$row['uid'],$row['pid']);
2643
2644 $rootLine = t3lib_BEfunc::BEgetRootLine($TScID,'');
2645 if ($TScID>=0) {
2646 $tempConf = $GLOBALS['BE_USER']->getTSConfig('TCEFORM.'.$table,t3lib_BEfunc::getPagesTSconfig($TScID,$rootLine));
2647 if (is_array($tempConf['properties'])) {
2648 while(list($key,$val)=each($tempConf['properties'])) {
2649 if (is_array($val)) {
2650 $fieldN = substr($key,0,-1);
2651 $res[$fieldN] = $val;
2652 unset($res[$fieldN]['types.']);
2653 if (strcmp($typeVal,'') && is_array($val['types.'][$typeVal.'.'])) {
2654 $res[$fieldN] = t3lib_div::array_merge_recursive_overrule($res[$fieldN],$val['types.'][$typeVal.'.']);
2655 }
2656 }
2657 }
2658 }
2659 }
2660 $res['_CURRENT_PID']=$cPid;
2661 $res['_THIS_UID']=$row['uid'];
2662 $res['_THIS_CID']=$row['cid'];
2663 $res['_THIS_ROW']=$row; // So the row will be passed to foreign_table_where_query()
2664
2665 reset($rootLine);
2666 while(list(,$rC)=each($rootLine)) {
2667 if (!$res['_STORAGE_PID']) $res['_STORAGE_PID']=intval($rC['storage_pid']);
2668 if (!$res['_SITEROOT']) $res['_SITEROOT']=$rC['is_siteroot']?intval($rC['uid']):0;
2669 }
2670
2671 return $res;
2672 }
2673
2674 /**
2675 * Find the real PID of the record (with $uid from $table). This MAY be impossible if the pid is set as a reference to the former record or a page (if two records are created at one time).
2676 * Usage: 2
2677 *
2678 * @param string Table name
2679 * @param integer Record uid
2680 * @param integer Record pid
2681 * @return integer
2682 * @internal
2683 * @see t3lib_TCEmain::copyRecord(), getTSCpid()
2684 */
2685 function getTSconfig_pidValue($table,$uid,$pid) {
2686 if (t3lib_div::testInt($pid)) { // If pid is an integer this takes precedence in our lookup.
2687 $thePidValue = intval($pid);
2688 if ($thePidValue<0) { // If ref to another record, look that record up.
2689 $pidRec = t3lib_BEfunc::getRecord($table,abs($thePidValue),'pid');
2690 $thePidValue= is_array($pidRec) ? $pidRec['pid'] : -2; // Returns -2 if the record did not exist.
2691 }
2692 // ... else the pos/zero pid is just returned here.
2693 } else { // No integer pid and we are forced to look up the $pid
2694 $rr = t3lib_BEfunc::getRecord($table,$uid,'pid'); // Try to fetch the record pid from uid. If the uid is 'NEW...' then this will of course return nothing...
2695 if (is_array($rr)) {
2696 $thePidValue = $rr['pid']; // Returning the 'pid' of the record
2697 } else $thePidValue=-1; // Returns -1 if the record with the pid was not found.
2698 }
2699 return $thePidValue;
2700 }
2701
2702 /**
2703 * Return $uid if $table is pages and $uid is integer - otherwise the $pid
2704 * Usage: 1
2705 *
2706 * @param string Table name
2707 * @param integer Record uid
2708 * @param integer Record pid
2709 * @return integer
2710 * @internal
2711 * @see t3lib_TCEforms::getTSCpid()
2712 */
2713 function getPidForModTSconfig($table,$uid,$pid) {
2714 $retVal = ($table=='pages' && t3lib_div::testInt($uid)) ? $uid : $pid;
2715 return $retVal;
2716 }
2717
2718 /**
2719 * Returns the REAL pid of the record, if possible. If both $uid and $pid is strings, then pid=-1 is returned as an error indication.
2720 * Usage: 8
2721 *
2722 * @param string Table name
2723 * @param integer Record uid
2724 * @param integer Record pid
2725 * @return array Array of two integers; first is the REAL PID of a record and if its a new record negative values are resolved to the true PID, second value is the PID value for TSconfig (uid if table is pages, otherwise the pid)
2726 * @internal
2727 * @see t3lib_TCEmain::setHistory(), t3lib_TCEmain::process_datamap()
2728 */
2729 function getTSCpid($table,$uid,$pid) {
2730 // If pid is negative (referring to another record) the pid of the other record is fetched and returned.
2731 $cPid = t3lib_BEfunc::getTSconfig_pidValue($table,$uid,$pid);
2732 // $TScID is the id of $table=pages, else it's the pid of the record.
2733 $TScID = t3lib_BEfunc::getPidForModTSconfig($table,$uid,$cPid);
2734
2735 return array($TScID,$cPid);
2736 }
2737
2738 /**
2739 * Returns first found domain record "domainName" (without trailing slash) if found in the input $rootLine
2740 * Usage: 2
2741 *
2742 * @param array Root line array
2743 * @return string Domain name, if found.
2744 */
2745 function firstDomainRecord($rootLine) {
2746 if (t3lib_extMgm::isLoaded('cms')) {
2747 reset($rootLine);
2748 while(list(,$row)=each($rootLine)) {
2749 $dRec = t3lib_BEfunc::getRecordsByField('sys_domain','pid',$row['uid'],' AND redirectTo=\'\' AND hidden=0', '', 'sorting');
2750 if (is_array($dRec)) {
2751 reset($dRec);
2752 $dRecord = current($dRec);
2753 return ereg_replace('\/$','',$dRecord['domainName']);
2754 }
2755 }
2756 }
2757 }
2758
2759 /**
2760 * Returns the sys_domain record for $domain, optionally with $path appended.
2761 * Usage: 2
2762 *
2763 * @param string Domain name
2764 * @param string Appended path
2765 * @return array Domain record, if found
2766 */
2767 function getDomainStartPage($domain, $path='') {
2768 if (t3lib_extMgm::isLoaded('cms')) {
2769 $domain = explode(':',$domain);
2770 $domain = strtolower(ereg_replace('\.$','',$domain[0]));
2771 // path is calculated.
2772 $path = trim(ereg_replace('\/[^\/]*$','',$path));
2773 // stuff:
2774 $domain.=$path;
2775
2776 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('sys_domain.*', 'pages,sys_domain', '
2777 pages.uid=sys_domain.pid
2778 AND sys_domain.hidden=0
2779 AND (sys_domain.domainName='.$GLOBALS['TYPO3_DB']->fullQuoteStr($domain, 'sys_domain').' or sys_domain.domainName='.$GLOBALS['TYPO3_DB']->fullQuoteStr($domain.'/', 'sys_domain').')'.
2780 t3lib_BEfunc::deleteClause('pages'),
2781 '', '', '1');
2782 return $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
2783 }
2784 }
2785
2786 /**
2787 * Returns overlayered RTE setup from an array with TSconfig. Used in TCEforms and TCEmain
2788 * Usage: 8
2789 *
2790 * @param array The properties of Page TSconfig in the key "RTE."
2791 * @param string Table name
2792 * @param string Field name
2793 * @param string Type value of the current record (like from CType of tt_content)
2794 * @return array Array with the configuration for the RTE
2795 * @internal
2796 */
2797 function RTEsetup($RTEprop,$table,$field,$type='') {
2798 $thisConfig = is_array($RTEprop['default.']) ? $RTEprop['default.'] : array();
2799 $thisFieldConf = $RTEprop['config.'][$table.'.'][$field.'.'];
2800 if (is_array($thisFieldConf)) {
2801 unset($thisFieldConf['types.']);
2802 $thisConfig = t3lib_div::array_merge_recursive_overrule($thisConfig,$thisFieldConf);
2803 }
2804 if ($type && is_array($RTEprop['config.'][$table.'.'][$field.'.']['types.'][$type.'.'])) {
2805 $thisConfig = t3lib_div::array_merge_recursive_overrule($thisConfig,$RTEprop['config.'][$table.'.'][$field.'.']['types.'][$type.'.']);
2806 }
2807 return $thisConfig;
2808 }
2809
2810 /**
2811 * Returns first possible RTE object if available.
2812 * Usage: $RTEobj = &t3lib_BEfunc::RTEgetObj();
2813 *
2814 * @return mixed If available, returns RTE object, otherwise an array of messages from possible RTEs
2815 */
2816 function &RTEgetObj() {
2817
2818 // If no RTE object has been set previously, try to create it:
2819 if (!isset($GLOBALS['T3_VAR']['RTEobj'])) {
2820
2821 // Set the object string to blank by default:
2822 $GLOBALS['T3_VAR']['RTEobj'] = array();
2823
2824 // Traverse registered RTEs:
2825 if (is_array($GLOBALS['TYPO3_CONF_VARS']['BE']['RTE_reg'])) {
2826 foreach($GLOBALS['TYPO3_CONF_VARS']['BE']['RTE_reg'] as $extKey => $rteObjCfg) {
2827 $rteObj = &t3lib_div::getUserObj($rteObjCfg['objRef']);
2828 if (is_object($rteObj)) {
2829 if ($rteObj->isAvailable()) {
2830 $GLOBALS['T3_VAR']['RTEobj'] = &$rteObj;
2831 break;
2832 } else {
2833 $GLOBALS['T3_VAR']['RTEobj'] = array_merge($GLOBALS['T3_VAR']['RTEobj'], $rteObj->errorLog);
2834 }
2835 }
2836 }
2837 }
2838
2839 if (!count($GLOBALS['T3_VAR']['RTEobj'])) {
2840 $GLOBALS['T3_VAR']['RTEobj'][] = 'No RTEs configured at all';
2841 }
2842 }
2843
2844 // Return RTE object (if any!)
2845 return $GLOBALS['T3_VAR']['RTEobj'];
2846 }
2847
2848 /**
2849 * Returns soft-reference parser for the softRef processing type
2850 * Usage: $softRefObj = &t3lib_BEfunc::softRefParserObj('[parser key]');
2851 *
2852 * @param string softRef parser key
2853 * @return mixed If available, returns Soft link parser object.
2854 */
2855 function &softRefParserObj($spKey) {
2856
2857 // If no softRef parser object has been set previously, try to create it:
2858 if (!isset($GLOBALS['T3_VAR']['softRefParser'][$spKey])) {
2859
2860 // Set the object string to blank by default:
2861 $GLOBALS['T3_VAR']['softRefParser'][$spKey] = '';
2862
2863 // Now, try to create parser object:
2864 $objRef = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser'][$spKey] ?
2865 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser'][$spKey] :
2866 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser_GL'][$spKey];
2867 if ($objRef) {
2868 $softRefParserObj = &t3lib_div::getUserObj($objRef,'');
2869 if (is_object($softRefParserObj)) {
2870 $GLOBALS['T3_VAR']['softRefParser'][$spKey] = &$softRefParserObj;
2871 }
2872 }
2873 }
2874
2875 // Return RTE object (if any!)
2876 return $GLOBALS['T3_VAR']['softRefParser'][$spKey];
2877 }
2878
2879 /**
2880 * Returns array of soft parser references
2881 *
2882 * @param string softRef parser list
2883 * @param string Table name
2884 * @param string Field name
2885 * @return array Array where the parser key is the key and the value is the parameter string
2886 */
2887 function explodeSoftRefParserList($parserList, $table, $field) {
2888
2889 // Looking for global parsers:
2890 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser_GL'])) {
2891 $parserList = implode(',',array_keys($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser_GL'])).','.$parserList;
2892 }
2893
2894 // Return immediately if list is blank:
2895 if (!strlen($parserList)) return FALSE;
2896
2897 // Otherwise parse the list:
2898 $keyList = t3lib_div::trimExplode(',', $parserList, 1);
2899 $output = array();
2900
2901 foreach($keyList as $val) {
2902 $reg = array();
2903 if (ereg('^([[:alnum:]_-]+)\[(.*)\]$', $val, $reg)) {
2904 $output[$reg[1]] = t3lib_div::trimExplode(';', $reg[2], 1);
2905 } else {
2906 $output[$val] = '';
2907 }
2908 }
2909 return $output;
2910 }
2911
2912 /**
2913 * Returns true if $modName is set and is found as a main- or submodule in $TBE_MODULES array
2914 * Usage: 1
2915 *
2916 * @param string Module name
2917 * @return boolean
2918 */
2919 function isModuleSetInTBE_MODULES($modName) {
2920 reset($GLOBALS['TBE_MODULES']);
2921 $loaded=array();
2922 while(list($mkey,$list)=each($GLOBALS['TBE_MODULES'])) {
2923 $loaded[$mkey]=1;
2924 if (trim($list)) {
2925 $subList = t3lib_div::trimExplode(',',$list,1);
2926 while(list(,$skey)=each($subList)) {
2927 $loaded[$mkey.'_'.$skey]=1;
2928 }
2929 }
2930 }
2931 return $modName && isset($loaded[$modName]);
2932 }
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948 /*******************************************
2949 *
2950 * Workspaces / Versioning
2951 *
2952 *******************************************/
2953
2954 /**
2955 * Select all versions of a record, ordered by version id (DESC)
2956 *
2957 * @param string Table name to select from
2958 * @param integer Record uid for which to find versions.
2959 * @param string Field list to select
2960 * @param integer Workspace ID, if zero all versions regardless of workspace is found.
2961 * @return array Array of versions of table/uid
2962 */
2963 function selectVersionsOfRecord($table, $uid, $fields='*', $workspace=0) {
2964 global $TCA;
2965
2966 if ($TCA[$table] && $TCA[$table]['ctrl']['versioningWS']) {
2967
2968 // Select all versions of record:
2969 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
2970 $fields,
2971 $table,
2972 '((t3ver_oid='.intval($uid).($workspace!=0?' AND t3ver_wsid='.intval($workspace):'').') OR uid='.intval($uid).')'.
2973 t3lib_BEfunc::deleteClause($table),
2974 '',
2975 't3ver_id DESC'
2976 );
2977
2978 // Add rows to output array:
2979 $realPid = 0;
2980 $outputRows = array();
2981 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
2982 if ($uid==$row['uid']) {
2983 $row['_CURRENT_VERSION']=TRUE;
2984 $realPid = $row['pid'];
2985 }
2986 $outputRows[] = $row;
2987 }
2988
2989 // Set real-pid:
2990 foreach($outputRows as $idx => $oRow) {
2991 $outputRows[$idx]['_REAL_PID'] = $realPid;
2992 }
2993
2994 return $outputRows;
2995 }
2996 }
2997
2998 /**
2999 * Find page-tree PID for versionized record
3000 * Will look if the "pid" value of the input record is -1 and if the table supports versioning - if so, it will translate the -1 PID into the PID of the original record
3001 * Used whenever you are tracking something back, like making the root line.
3002 * Principle; Record offline! => Find online?
3003 *
3004 * @param string Table name
3005 * @param array Record array passed by reference. As minimum, "pid" and "uid" fields must exist! "t3ver_oid" and "t3ver_wsid" is nice and will save you a DB query.
3006 * @return void (Passed by ref). If the record had its pid corrected to the online versions pid, then "_ORIG_pid" is set to the original pid value (-1 of course). The field "_ORIG_pid" is used by various other functions to detect if a record was in fact in a versionized branch.
3007 * @see t3lib_page::fixVersioningPid()
3008 */
3009 function fixVersioningPid($table,&$rr) {
3010 global $TCA;
3011
3012 // Check that the input record is an offline version from a table that supports versioning:
3013 if (is_array($rr) && $rr['pid']==-1 && $TCA[$table]['ctrl']['versioningWS']) {
3014
3