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