Fixed bug #633: Menu doesn't expand if ".special" is set
[Packages/TYPO3.CMS.git] / typo3 / sysext / cms / tslib / class.tslib_menu.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2007 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 * Generating navigation / menus from TypoScript
29 *
30 * This file contains five classes, four of which are extensions to the main class, tslib_menu.
31 * The main class, tslib_menu, is also extended by other external PHP scripts such as the GMENU_LAYERS and GMENU_FOLDOUT scripts which creates pop-up menus.
32 * Notice that extension classes (like "tslib_tmenu") must have their suffix (here "tmenu") listed in $this->tmpl->menuclasses - otherwise they cannot be instantiated.
33 *
34 * $Id$
35 * Revised for TYPO3 3.6 June/2003 by Kasper Skaarhoj
36 * XHTML compliant
37 *
38 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
39 */
40 /**
41 * [CLASS/FUNCTION INDEX of SCRIPT]
42 *
43 *
44 *
45 * 145: class tslib_menu
46 * 191: function start(&$tmpl,&$sys_page,$id,$conf,$menuNumber,$objSuffix='')
47 * 324: function makeMenu()
48 * 865: function includeMakeMenu($conf,$altSortField)
49 * 881: function filterMenuPages(&$data,$banUidArray,$spacer)
50 * 937: function procesItemStates($splitCount)
51 * 1147: function link($key,$altTarget='',$typeOverride='')
52 * 1212: function changeLinksForAccessRestrictedPages(&$LD, $page, $mainTarget, $typeOverride)
53 * 1233: function subMenu($uid, $objSuffix='')
54 * 1278: function isNext($uid, $MPvar='')
55 * 1299: function isActive($uid, $MPvar='')
56 * 1320: function isCurrent($uid, $MPvar='')
57 * 1335: function isSubMenu($uid)
58 * 1360: function isItemState($kind,$key)
59 * 1400: function accessKey($title)
60 * 1426: function userProcess($mConfKey,$passVar)
61 * 1441: function setATagParts()
62 * 1454: function getPageTitle($title,$nav_title)
63 * 1466: function getMPvar($key)
64 * 1481: function getDoktypeExcludeWhere()
65 * 1491: function getBannedUids()
66 *
67 *
68 * 1530: class tslib_tmenu extends tslib_menu
69 * 1539: function generate()
70 * 1555: function writeMenu()
71 * 1699: function getBeforeAfter($pref)
72 * 1729: function addJScolorShiftFunction()
73 * 1751: function extProc_init()
74 * 1762: function extProc_RO($key)
75 * 1773: function extProc_beforeLinking($key)
76 * 1785: function extProc_afterLinking($key)
77 * 1802: function extProc_beforeAllWrap($item,$key)
78 * 1813: function extProc_finish()
79 *
80 *
81 * 1849: class tslib_gmenu extends tslib_menu
82 * 1858: function generate()
83 * 1896: function makeGifs($conf, $resKey)
84 * 2101: function findLargestDims($conf,$items,$Hobjs,$Wobjs,$minDim,$maxDim)
85 * 2173: function writeMenu()
86 * 2294: function extProc_init()
87 * 2305: function extProc_RO($key)
88 * 2316: function extProc_beforeLinking($key)
89 * 2329: function extProc_afterLinking($key)
90 * 2346: function extProc_beforeAllWrap($item,$key)
91 * 2357: function extProc_finish()
92 *
93 *
94 * 2391: class tslib_imgmenu extends tslib_menu
95 * 2400: function generate()
96 * 2418: function makeImageMap($conf)
97 * 2604: function writeMenu()
98 *
99 *
100 * 2647: class tslib_jsmenu extends tslib_menu
101 * 2654: function generate()
102 * 2662: function writeMenu()
103 * 2723: function generate_level($levels,$count,$pid,$menuItemArray='',$MP_array=array())
104 *
105 * TOTAL FUNCTIONS: 46
106 * (This index is automatically created/updated by the extension "extdeveval")
107 *
108 */
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127 /**
128 * Base class. The HMENU content object uses this (or more precisely one of the extension classes).
129 * Amoung others the class generates an array of menuitems. Thereafter functions from the subclasses are called.
130 * The class is ALWAYS used through extension classes (like tslib_gmenu or tslib_tmenu which are classics) and
131 *
132 * Example of usage (from tslib_cObj):
133 *
134 * $menu = t3lib_div::makeInstance('tslib_'.$cls);
135 * $menu->parent_cObj = $this;
136 * $menu->start($GLOBALS['TSFE']->tmpl,$GLOBALS['TSFE']->sys_page,'',$conf,1);
137 * $menu->makeMenu();
138 * $content.=$menu->writeMenu();
139 *
140 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
141 * @package TYPO3
142 * @subpackage tslib
143 * @see tslib_cObj::HMENU()
144 */
145 class tslib_menu {
146 var $menuNumber = 1; // tells you which menu-number this is. This is important when getting data from the setup
147 var $entryLevel = 0; // 0 = rootFolder
148 var $spacerIDList = '199'; // The doktype-number that defines a spacer
149 var $doktypeExcludeList = '5,6'; // doktypes that define which should not be included in a menu
150 var $alwaysActivePIDlist=array();
151 var $imgNamePrefix = 'img';
152 var $imgNameNotRandom=0;
153 var $debug = 0;
154
155 /**
156 * Loaded with the parent cObj-object when a new HMENU is made
157 *
158 * @var tslib_cObj
159 */
160 var $parent_cObj;
161 var $GMENU_fixKey='gmenu';
162 var $MP_array=array(); // accumulation of mount point data
163
164 // internal
165 var $conf = Array(); // HMENU configuration
166 var $mconf = Array(); // xMENU configuration (TMENU, GMENU etc)
167
168 /**
169 * template-object
170 *
171 * @var t3lib_TStemplate
172 */
173 var $tmpl;
174
175 /**
176 * sys_page-object, pagefunctions
177 *
178 * @var t3lib_pageSelect
179 */
180 var $sys_page;
181 var $id; // The base page-id of the menu.
182 var $nextActive; // Holds the page uid of the NEXT page in the root line from the page pointed to by entryLevel; Used to expand the menu automatically if in a certain root line.
183 var $menuArr; // The array of menuItems which is built
184 var $hash;
185 var $result = Array();
186 var $rL_uidRegister = ''; // Array: Is filled with an array of page uid numbers + RL parameters which are in the current root line (used to evaluate whether a menu item is in active state)
187 var $INPfixMD5;
188 var $I;
189 var $WMresult;
190 var $WMfreezePrefix;
191 var $WMmenuItems;
192 var $WMsubmenuObjSuffixes;
193 var $WMextraScript;
194 var $alternativeMenuTempArray=''; // Can be set to contain menu item arrays for sub-levels.
195 var $nameAttribute = 'name'; // Will be 'id' in XHTML-mode
196
197 /**
198 * The initialization of the object. This just sets some internal variables.
199 *
200 * @param object The $GLOBALS['TSFE']->tmpl object
201 * @param object The $GLOBALS['TSFE']->sys_page object
202 * @param integer A starting point page id. This should probably be blank since the 'entryLevel' value will be used then.
203 * @param array The TypoScript configuration for the HMENU cObject
204 * @param integer Menu number; 1,2,3. Should probably be '1'
205 * @param string Submenu Object suffix. This offers submenus a way to use alternative configuration for specific positions in the menu; By default "1 = TMENU" would use "1." for the TMENU configuration, but if this string is set to eg. "a" then "1a." would be used for configuration instead (while "1 = " is still used for the overall object definition of "TMENU")
206 * @return boolean Returns true on success
207 * @see tslib_cObj::HMENU()
208 */
209 function start(&$tmpl,&$sys_page,$id,$conf,$menuNumber,$objSuffix='') {
210
211 // Init:
212 $this->conf = $conf;
213 $this->menuNumber = $menuNumber;
214 $this->mconf = $conf[$this->menuNumber.$objSuffix.'.'];
215 $this->debug=$GLOBALS['TSFE']->debug;
216
217 // In XHTML there is no "name" attribute anymore
218 switch ($GLOBALS['TSFE']->xhtmlDoctype) {
219 case 'xhtml_strict':
220 case 'xhtml_11':
221 case 'xhtml_2':
222 $this->nameAttribute = 'id';
223 break;
224 default:
225 $this->nameAttribute = 'name';
226 break;
227 }
228
229 // Sets the internal vars. $tmpl MUST be the template-object. $sys_page MUST be the sys_page object
230 if ($this->conf[$this->menuNumber.$objSuffix] && is_object($tmpl) && is_object($sys_page)) {
231 $this->tmpl = &$tmpl;
232 $this->sys_page = &$sys_page;
233
234 // alwaysActivePIDlist initialized:
235 if (trim($this->conf['alwaysActivePIDlist'])) {
236 $this->alwaysActivePIDlist = t3lib_div::intExplode(',', $this->conf['alwaysActivePIDlist']);
237 }
238
239 // 'not in menu' doktypes
240 if($this->conf['excludeDoktypes']) {
241 $this->doktypeExcludeList = $GLOBALS['TYPO3_DB']->cleanIntList($this->conf['excludeDoktypes']);
242 }
243 if($this->conf['includeNotInMenu']) {
244 $exclDoktypeArr = t3lib_div::trimExplode(',',$this->doktypeExcludeList,1);
245 $exclDoktypeArr = t3lib_div::removeArrayEntryByValue($exclDoktypeArr,'5');
246 $this->doktypeExcludeList = implode(',',$exclDoktypeArr);
247 }
248
249 // EntryLevel
250 $this->entryLevel = tslib_cObj::getKey ($conf['entryLevel'],$this->tmpl->rootLine);
251
252 // Set parent page: If $id not stated with start() then the base-id will be found from rootLine[$this->entryLevel]
253 if ($id) { // Called as the next level in a menu. It is assumed that $this->MP_array is set from parent menu.
254 $this->id = intval($id);
255 } else { // This is a BRAND NEW menu, first level. So we take ID from rootline and also find MP_array (mount points)
256 $this->id = intval($this->tmpl->rootLine[$this->entryLevel]['uid']);
257
258 // Traverse rootline to build MP_array of pages BEFORE the entryLevel
259 // (MP var for ->id is picked up in the next part of the code...)
260 foreach($this->tmpl->rootLine as $entryLevel => $levelRec) {
261 // For overlaid mount points, set the variable right now:
262 if ($levelRec['_MP_PARAM'] && $levelRec['_MOUNT_OL']) {
263 $this->MP_array[] = $levelRec['_MP_PARAM'];
264 }
265 // Break when entry level is reached:
266 if ($entryLevel>=$this->entryLevel) break;
267
268 // For normal mount points, set the variable for next level.
269 if ($levelRec['_MP_PARAM'] && !$levelRec['_MOUNT_OL']) {
270 $this->MP_array[] = $levelRec['_MP_PARAM'];
271 }
272 }
273 }
274
275 // Return false if no page ID was set (thus no menu of subpages can be made).
276 if ($this->id<=0) {
277 return FALSE;
278 }
279
280 // Check if page is a mount point, and if so set id and MP_array
281 // (basically this is ONLY for non-overlay mode, but in overlay mode an ID with a mount point should never reach this point anyways, so no harm done...)
282 $mount_info = $this->sys_page->getMountPointInfo($this->id);
283 if (is_array($mount_info)) {
284 $this->MP_array[] = $mount_info['MPvar'];
285 $this->id = $mount_info['mount_pid'];
286 }
287
288 // Gather list of page uids in root line (for "isActive" evaluation). Also adds the MP params in the path so Mount Points are respected.
289 // (List is specific for this rootline, so it may be supplied from parent menus for speed...)
290 if (!is_array($this->rL_uidRegister)) {
291 $rl_MParray = array();
292 foreach($this->tmpl->rootLine as $v_rl) {
293 // For overlaid mount points, set the variable right now:
294 if ($v_rl['_MP_PARAM'] && $v_rl['_MOUNT_OL']) {
295 $rl_MParray[] = $v_rl['_MP_PARAM'];
296 }
297
298 // Add to register:
299 $this->rL_uidRegister[] = 'ITEM:'.$v_rl['uid'].(count($rl_MParray) ? ':'.implode(',',$rl_MParray) : '');
300
301 // For normal mount points, set the variable for next level.
302 if ($v_rl['_MP_PARAM'] && !$v_rl['_MOUNT_OL']) {
303 $rl_MParray[] = $v_rl['_MP_PARAM'];
304 }
305 }
306 }
307
308 // Set $directoryLevel so the following evalution of the nextActive will not return
309 // an invalid value if .special=directory was set
310 $directoryLevel = 0;
311 if ($this->conf['special'] == 'directory') {
312 $value = $GLOBALS['TSFE']->cObj->stdWrap($this->conf['special.']['value'], $this->conf['special.']['value.']);
313 if ($value=='') {
314 $value=$GLOBALS['TSFE']->page['uid'];
315 }
316 $directoryLevel = intval($GLOBALS['TSFE']->tmpl->getRootlineLevel($value));
317 }
318
319 // Setting "nextActive": This is the page uid + MPvar of the NEXT page in rootline. Used to expand the menu if we are in the right branch of the tree
320 // Notice: The automatic expansion of a menu is designed to work only when no "special" modes (except "directory") are used.
321 $startLevel = $directoryLevel?$directoryLevel:$this->entryLevel;
322 if (is_array($this->tmpl->rootLine[$startLevel+$this->menuNumber])) {
323 $nextMParray = $this->MP_array;
324 if ($this->tmpl->rootLine[$startLevel+$this->menuNumber]['_MOUNT_OL']) { // In overlay mode, add next level MPvars as well:
325 $nextMParray[] = $this->tmpl->rootLine[$startLevel+$this->menuNumber]['_MP_PARAM'];
326 }
327 $this->nextActive = $this->tmpl->rootLine[$startLevel+$this->menuNumber]['uid'].(count($nextMParray)?':'.implode(',',$nextMParray):'');
328 } else {
329 $this->nextActive = '';
330 }
331
332 // imgNamePrefix
333 if ($this->mconf['imgNamePrefix']) {
334 $this->imgNamePrefix=$this->mconf['imgNamePrefix'];
335 }
336 $this->imgNameNotRandom = $this->mconf['imgNameNotRandom'];
337
338 $retVal = TRUE;
339 } else {
340 $GLOBALS['TT']->setTSlogMessage('ERROR in menu',3);
341 $retVal = FALSE;
342 }
343 return $retVal;
344 }
345
346 /**
347 * Creates the menu in the internal variables, ready for output.
348 * Basically this will read the page records needed and fill in the internal $this->menuArr
349 * Based on a hash of this array and some other variables the $this->result variable will be loaded either from cache OR by calling the generate() method of the class to create the menu for real.
350 *
351 * @return void
352 */
353 function makeMenu() {
354 if ($this->id) {
355
356 // Initializing showAccessRestrictedPages
357 if ($this->mconf['showAccessRestrictedPages']) {
358 // SAVING where_groupAccess
359 $SAVED_where_groupAccess = $this->sys_page->where_groupAccess;
360 $this->sys_page->where_groupAccess = ''; // Temporarily removing fe_group checking!
361 }
362
363 // Begin production of menu:
364 $temp = array();
365 $altSortFieldValue = trim($this->mconf['alternativeSortingField']);
366 $altSortField = $altSortFieldValue ? $altSortFieldValue : 'sorting';
367 if ($this->menuNumber==1 && $this->conf['special']) { // ... only for the FIRST level of a HMENU
368 $value = $this->parent_cObj->stdWrap($this->conf['special.']['value'], $this->conf['special.']['value.']);
369
370 switch($this->conf['special']) {
371 case 'userdefined':
372 $temp = $this->includeMakeMenu($this->conf['special.'],$altSortField);
373 break;
374 case 'userfunction':
375 $temp = $this->parent_cObj->callUserFunction(
376 $this->conf['special.']['userFunc'],
377 array_merge($this->conf['special.'],array('_altSortField'=>$altSortField)),
378 ''
379 );
380 if (!is_array($temp)) $temp=array();
381 break;
382 case 'language':
383 $temp = array();
384
385 // Getting current page record NOT overlaid by any translation:
386 $currentPageWithNoOverlay = $this->sys_page->getRawRecord('pages',$GLOBALS['TSFE']->page['uid']);
387
388 // Traverse languages set up:
389 $languageItems = t3lib_div::intExplode(',',$value);
390 foreach($languageItems as $sUid) {
391 // Find overlay record:
392 if ($sUid) {
393 $lRecs = $this->sys_page->getPageOverlay($GLOBALS['TSFE']->page['uid'],$sUid);
394 } else $lRecs=array();
395 // Checking if the "disabled" state should be set.
396 if (
397 (t3lib_div::hideIfNotTranslated($GLOBALS['TSFE']->page['l18n_cfg']) && $sUid && !count($lRecs)) // Blocking for all translations?
398 || ($GLOBALS['TSFE']->page['l18n_cfg']&1 && (!$sUid || !count($lRecs))) // Blocking default translation?
399 || (!$this->conf['special.']['normalWhenNoLanguage'] && $sUid && !count($lRecs))
400 ) {
401 $iState = $GLOBALS['TSFE']->sys_language_uid==$sUid ? 'USERDEF2' : 'USERDEF1';
402 } else {
403 $iState = $GLOBALS['TSFE']->sys_language_uid==$sUid ? 'ACT' : 'NO';
404 }
405
406 if ($this->conf['addQueryString']) {
407 $getVars = $this->parent_cObj->getQueryArguments($this->conf['addQueryString.'],array('L'=>$sUid),true);
408 } else {
409 $getVars = '&L='.$sUid;
410 }
411
412 // Adding menu item:
413 $temp[] = array_merge(
414 array_merge($currentPageWithNoOverlay, $lRecs),
415 array(
416 'ITEM_STATE' => $iState,
417 '_ADD_GETVARS' => $getVars,
418 '_SAFE' => TRUE
419 )
420 );
421 }
422 break;
423 case 'directory':
424 if ($value=='') {
425 $value=$GLOBALS['TSFE']->page['uid'];
426 }
427 $items=t3lib_div::intExplode(',',$value);
428
429 foreach($items as $id) {
430 $MP = $this->tmpl->getFromMPmap($id);
431
432 // Checking if a page is a mount page and if so, change the ID and set the MP var properly.
433 $mount_info = $this->sys_page->getMountPointInfo($id);
434 if (is_array($mount_info)) {
435 if ($mount_info['overlay']) { // Overlays should already have their full MPvars calculated:
436 $MP = $this->tmpl->getFromMPmap($mount_info['mount_pid']);
437 $MP = $MP ? $MP : $mount_info['MPvar'];
438 } else {
439 $MP = ($MP ? $MP.',' : '').$mount_info['MPvar'];
440 }
441 $id = $mount_info['mount_pid'];
442 }
443
444 // Get sub-pages:
445 $res = $GLOBALS['TSFE']->cObj->exec_getQuery('pages',Array('pidInList'=>$id,'orderBy'=>$altSortField));
446 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
447 $GLOBALS['TSFE']->sys_page->versionOL('pages',$row);
448
449 if (is_array($row)) {
450 // Keep mount point?
451 $mount_info = $this->sys_page->getMountPointInfo($row['uid'], $row);
452 if (is_array($mount_info) && $mount_info['overlay']) { // There is a valid mount point.
453 $mp_row = $this->sys_page->getPage($mount_info['mount_pid']); // Using "getPage" is OK since we need the check for enableFields AND for type 2 of mount pids we DO require a doktype < 200!
454 if (count($mp_row)) {
455 $row = $mp_row;
456 $row['_MP_PARAM'] = $mount_info['MPvar'];
457 } else unset($row); // If the mount point could not be fetched with respect to enableFields, unset the row so it does not become a part of the menu!
458 }
459
460 // Add external MP params, then the row:
461 if (is_array($row)) {
462 if ($MP) $row['_MP_PARAM'] = $MP.($row['_MP_PARAM'] ? ','.$row['_MP_PARAM'] : '');
463 $temp[$row['uid']] = $this->sys_page->getPageOverlay($row);
464 }
465 }
466 }
467 }
468 break;
469 case 'list':
470 if ($value=='') {
471 $value=$this->id;
472 }
473 $loadDB = t3lib_div::makeInstance('FE_loadDBGroup');
474 $loadDB->start($value, 'pages');
475 $loadDB->additionalWhere['pages']=tslib_cObj::enableFields('pages');
476 $loadDB->getFromDB();
477
478 foreach($loadDB->itemArray as $val) {
479 $MP = $this->tmpl->getFromMPmap($val['id']);
480
481 // Keep mount point?
482 $mount_info = $this->sys_page->getMountPointInfo($val['id']);
483 if (is_array($mount_info) && $mount_info['overlay']) { // There is a valid mount point.
484 $mp_row = $this->sys_page->getPage($mount_info['mount_pid']); // Using "getPage" is OK since we need the check for enableFields AND for type 2 of mount pids we DO require a doktype < 200!
485 if (count($mp_row)) {
486 $row = $mp_row;
487 $row['_MP_PARAM'] = $mount_info['MPvar'];
488
489 if ($mount_info['overlay']) { // Overlays should already have their full MPvars calculated:
490 $MP = $this->tmpl->getFromMPmap($mount_info['mount_pid']);
491 if ($MP) unset($row['_MP_PARAM']);
492 }
493 } else unset($row); // If the mount point could not be fetched with respect to enableFields, unset the row so it does not become a part of the menu!
494 } else {
495 $row = $loadDB->results['pages'][$val['id']];
496 }
497
498 // Add external MP params, then the row:
499 if (is_array($row)) {
500 if ($MP) $row['_MP_PARAM'] = $MP.($row['_MP_PARAM'] ? ','.$row['_MP_PARAM'] : '');
501 $temp[] = $this->sys_page->getPageOverlay($row);
502 }
503 }
504 break;
505 case 'updated':
506 if ($value=='') {
507 $value=$GLOBALS['TSFE']->page['uid'];
508 }
509 $items=t3lib_div::intExplode(',',$value);
510 if (t3lib_div::testInt($this->conf['special.']['depth'])) {
511 $depth = t3lib_div::intInRange($this->conf['special.']['depth'],1,20); // Tree depth
512 } else {
513 $depth=20;
514 }
515 $limit = t3lib_div::intInRange($this->conf['special.']['limit'],0,100); // max number of items
516 $maxAge = intval(tslib_cObj::calc($this->conf['special.']['maxAge']));
517 if (!$limit) $limit=10;
518 $mode = $this->conf['special.']['mode']; // *'auto', 'manual', 'tstamp'
519 // Get id's
520 $id_list_arr = Array();
521
522 foreach($items as $id) {
523 $bA = t3lib_div::intInRange($this->conf['special.']['beginAtLevel'],0,100);
524 $id_list_arr[] = tslib_cObj::getTreeList(-1*$id,$depth-1+$bA,$bA-1);
525 }
526 $id_list = implode(',',$id_list_arr);
527 // Get sortField (mode)
528 switch($mode) {
529 case 'starttime':
530 $sortField = 'starttime';
531 break;
532 case 'lastUpdated':
533 case 'manual':
534 $sortField = 'lastUpdated';
535 break;
536 case 'tstamp':
537 $sortField = 'tstamp';
538 break;
539 case 'crdate':
540 $sortField = 'crdate';
541 break;
542 default:
543 $sortField = 'SYS_LASTCHANGED';
544 break;
545 }
546 // Get
547 $extraWhere = ($this->conf['includeNotInMenu'] ? '' : ' AND pages.nav_hide=0').$this->getDoktypeExcludeWhere();
548
549 if ($this->conf['special.']['excludeNoSearchPages']) {
550 $extraWhere.= ' AND pages.no_search=0';
551 }
552 if ($maxAge>0) {
553 $extraWhere.=' AND '.$sortField.'>'.($GLOBALS['SIM_EXEC_TIME']-$maxAge);
554 }
555
556 $res = $GLOBALS['TSFE']->cObj->exec_getQuery('pages',Array('pidInList'=>'0', 'uidInList'=>$id_list, 'where'=>$sortField.'>=0'.$extraWhere, 'orderBy'=>($altSortFieldValue ? $altSortFieldValue : $sortField.' desc'),'max'=>$limit));
557 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
558 $GLOBALS['TSFE']->sys_page->versionOL('pages',$row);
559 if (is_array($row)) {
560 $temp[$row['uid']]=$this->sys_page->getPageOverlay($row);
561 }
562 }
563 break;
564 case 'keywords':
565 list($value)=t3lib_div::intExplode(',',$value);
566 if (!$value) {
567 $value=$GLOBALS['TSFE']->page['uid'];
568 }
569 if ($this->conf['special.']['setKeywords'] || $this->conf['special.']['setKeywords.']) {
570 $kw = $this->parent_cObj->stdWrap($this->conf['special.']['setKeywords'], $this->conf['special.']['setKeywords.']);
571 } else {
572 $value_rec=$this->sys_page->getPage($value); // The page record of the 'value'.
573
574 $kfieldSrc = $this->conf['special.']['keywordsField.']['sourceField'] ? $this->conf['special.']['keywordsField.']['sourceField'] : 'keywords';
575 $kw = trim(tslib_cObj::keywords($value_rec[$kfieldSrc])); // keywords.
576 }
577
578 $mode = $this->conf['special.']['mode']; // *'auto', 'manual', 'tstamp'
579 switch($mode) {
580 case 'starttime':
581 $sortField = 'starttime';
582 break;
583 case 'lastUpdated':
584 case 'manual':
585 $sortField = 'lastUpdated';
586 break;
587 case 'tstamp':
588 $sortField = 'tstamp';
589 break;
590 case 'crdate':
591 $sortField = 'crdate';
592 break;
593 default:
594 $sortField = 'SYS_LASTCHANGED';
595 break;
596 }
597
598 // depth, limit, extra where
599 if (t3lib_div::testInt($this->conf['special.']['depth'])) {
600 $depth = t3lib_div::intInRange($this->conf['special.']['depth'],0,20); // Tree depth
601 } else {
602 $depth=20;
603 }
604 $limit = t3lib_div::intInRange($this->conf['special.']['limit'],0,100); // max number of items
605 $extraWhere = ' AND pages.uid!='.$value.($this->conf['includeNotInMenu'] ? '' : ' AND pages.nav_hide=0').$this->getDoktypeExcludeWhere();
606 if ($this->conf['special.']['excludeNoSearchPages']) {
607 $extraWhere.= ' AND pages.no_search=0';
608 }
609 // start point
610 $eLevel = tslib_cObj::getKey (intval($this->conf['special.']['entryLevel']),$this->tmpl->rootLine);
611 $startUid = intval($this->tmpl->rootLine[$eLevel]['uid']);
612
613 // which field is for keywords
614 $kfield = 'keywords';
615 if ( $this->conf['special.']['keywordsField'] ) {
616 list($kfield) = explode(' ',trim ($this->conf['special.']['keywordsField']));
617 }
618
619 // If there are keywords and the startuid is present.
620 if ($kw && $startUid) {
621 $bA = t3lib_div::intInRange($this->conf['special.']['beginAtLevel'],0,100);
622 $id_list=tslib_cObj::getTreeList(-1*$startUid,$depth-1+$bA,$bA-1);
623
624 $kwArr = explode(',',$kw);
625 foreach($kwArr as $word) {
626 $word = trim($word);
627 if ($word) {
628 $keyWordsWhereArr[] = $kfield.' LIKE \'%'.$GLOBALS['TYPO3_DB']->quoteStr($word, 'pages').'%\'';
629 }
630 }
631 $res = $GLOBALS['TSFE']->cObj->exec_getQuery('pages',Array('pidInList'=>'0', 'uidInList'=>$id_list, 'where'=>'('.implode(' OR ',$keyWordsWhereArr).')'.$extraWhere, 'orderBy'=>($altSortFieldValue ? $altSortFieldValue : $sortField.' desc'),'max'=>$limit));
632 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
633 $GLOBALS['TSFE']->sys_page->versionOL('pages',$row);
634 if (is_array($row)) {
635 $temp[$row['uid']]=$this->sys_page->getPageOverlay($row);
636 }
637 }
638 }
639 break;
640 case 'rootline':
641 $begin_end = explode('|',$this->conf['special.']['range']);
642 if (!t3lib_div::testInt($begin_end[0])) {intval($begin_end[0]);}
643 if (!t3lib_div::testInt($begin_end[1])) {$begin_end[1]=-1;}
644
645 $beginKey = tslib_cObj::getKey ($begin_end[0],$this->tmpl->rootLine);
646 $endKey = tslib_cObj::getKey ($begin_end[1],$this->tmpl->rootLine);
647 if ($endKey<$beginKey) {$endKey=$beginKey;}
648
649 $rl_MParray = array();
650 foreach($this->tmpl->rootLine as $k_rl => $v_rl) {
651 // For overlaid mount points, set the variable right now:
652 if ($v_rl['_MP_PARAM'] && $v_rl['_MOUNT_OL']) {
653 $rl_MParray[] = $v_rl['_MP_PARAM'];
654 }
655 // Traverse rootline:
656 if ($k_rl>=$beginKey && $k_rl<=$endKey) {
657 $temp_key=$k_rl;
658 $temp[$temp_key]=$this->sys_page->getPage($v_rl['uid']);
659 if (count($temp[$temp_key])) {
660 if (!$temp[$temp_key]['target']) { // If there are no specific target for the page, put the level specific target on.
661 $temp[$temp_key]['target'] = $this->conf['special.']['targets.'][$k_rl];
662 $temp[$temp_key]['_MP_PARAM'] = implode(',',$rl_MParray);
663 }
664 } else unset($temp[$temp_key]);
665 }
666 // For normal mount points, set the variable for next level.
667 if ($v_rl['_MP_PARAM'] && !$v_rl['_MOUNT_OL']) {
668 $rl_MParray[] = $v_rl['_MP_PARAM'];
669 }
670 }
671 break;
672 case 'browse':
673 list($value)=t3lib_div::intExplode(',',$value);
674 if (!$value) {
675 $value=$GLOBALS['TSFE']->page['uid'];
676 }
677 if ($value!=$this->tmpl->rootLine[0]['uid']) { // Will not work out of rootline
678 $recArr=array();
679 $value_rec=$this->sys_page->getPage($value); // The page record of the 'value'.
680 if ($value_rec['pid']) { // 'up' page cannot be outside rootline
681 $recArr['up']=$this->sys_page->getPage($value_rec['pid']); // The page record of 'up'.
682 }
683 if ($recArr['up']['pid'] && $value_rec['pid']!=$this->tmpl->rootLine[0]['uid']) { // If the 'up' item was NOT level 0 in rootline...
684 $recArr['index']=$this->sys_page->getPage($recArr['up']['pid']); // The page record of "index".
685 }
686
687 // prev / next is found
688 $prevnext_menu = $this->sys_page->getMenu($value_rec['pid'],'*',$altSortField);
689 $lastKey=0;
690 $nextActive=0;
691 reset($prevnext_menu);
692 while(list($k_b,$v_b)=each($prevnext_menu)) {
693 if ($nextActive) {
694 $recArr['next']=$v_b;
695 $nextActive=0;
696 }
697 if ($v_b['uid']==$value) {
698 if ($lastKey) {
699 $recArr['prev']=$prevnext_menu[$lastKey];
700 }
701 $nextActive=1;
702 }
703 $lastKey=$k_b;
704 }
705 reset($prevnext_menu);
706 $recArr['first']=pos($prevnext_menu);
707 end($prevnext_menu);
708 $recArr['last']=pos($prevnext_menu);
709
710 // prevsection / nextsection is found
711 if (is_array($recArr['index'])) { // You can only do this, if there is a valid page two levels up!
712 $prevnextsection_menu = $this->sys_page->getMenu($recArr['index']['uid'],'*',$altSortField);
713 $lastKey=0;
714 $nextActive=0;
715 reset($prevnextsection_menu);
716 while(list($k_b,$v_b)=each($prevnextsection_menu)) {
717 if ($nextActive) {
718 $sectionRec_temp = $this->sys_page->getMenu($v_b['uid'],'*',$altSortField);
719 if (count($sectionRec_temp)) {
720 reset($sectionRec_temp);
721 $recArr['nextsection']=pos($sectionRec_temp);
722 end ($sectionRec_temp);
723 $recArr['nextsection_last']=pos($sectionRec_temp);
724 $nextActive=0;
725 }
726 }
727 if ($v_b['uid']==$value_rec['pid']) {
728 if ($lastKey) {
729 $sectionRec_temp = $this->sys_page->getMenu($prevnextsection_menu[$lastKey]['uid'],'*',$altSortField);
730 if (count($sectionRec_temp)) {
731 reset($sectionRec_temp);
732 $recArr['prevsection']=pos($sectionRec_temp);
733 end ($sectionRec_temp);
734 $recArr['prevsection_last']=pos($sectionRec_temp);
735 }
736 }
737 $nextActive=1;
738 }
739 $lastKey=$k_b;
740 }
741 }
742 if ($this->conf['special.']['items.']['prevnextToSection']) {
743 if (!is_array($recArr['prev']) && is_array($recArr['prevsection_last'])) {
744 $recArr['prev']=$recArr['prevsection_last'];
745 }
746 if (!is_array($recArr['next']) && is_array($recArr['nextsection'])) {
747 $recArr['next']=$recArr['nextsection'];
748 }
749 }
750
751 $items = explode('|',$this->conf['special.']['items']);
752 $c=0;
753 while(list($k_b,$v_b)=each($items)) {
754 $v_b=strtolower(trim($v_b));
755 if (intval($this->conf['special.'][$v_b.'.']['uid'])) {
756 $recArr[$v_b] = $this->sys_page->getPage(intval($this->conf['special.'][$v_b.'.']['uid'])); // fetches the page in case of a hardcoded pid in template
757 }
758 if (is_array($recArr[$v_b])) {
759 $temp[$c]=$recArr[$v_b];
760 if ($this->conf['special.'][$v_b.'.']['target']) {
761 $temp[$c]['target']=$this->conf['special.'][$v_b.'.']['target'];
762 }
763 if (is_array($this->conf['special.'][$v_b.'.']['fields.'])) {
764 reset($this->conf['special.'][$v_b.'.']['fields.']);
765 while(list($fk,$val)=each($this->conf['special.'][$v_b.'.']['fields.'])) {
766 $temp[$c][$fk]=$val;
767 }
768 }
769 $c++;
770 }
771 }
772 }
773 break;
774 }
775 } elseif (is_array($this->alternativeMenuTempArray)) { // Setting $temp array if not level 1.
776 $temp = $this->alternativeMenuTempArray;
777 } elseif ($this->mconf['sectionIndex']) {
778 if ($GLOBALS['TSFE']->sys_language_uid && count($this->sys_page->getPageOverlay($this->id))) {
779 $sys_language_uid = intval($GLOBALS['TSFE']->sys_language_uid);
780 } else $sys_language_uid=0;
781
782 $selectSetup = Array(
783 'pidInList'=>$this->id,
784 'orderBy'=>$altSortField,
785 'where' => 'colPos=0 AND sys_language_uid='.$sys_language_uid,
786 'andWhere' => 'sectionIndex!=0'
787 );
788 switch($this->mconf['sectionIndex.']['type']) {
789 case 'all':
790 unset($selectSetup['andWhere']);
791 break;
792 case 'header':
793 $selectSetup['andWhere']='header_layout!=100 AND header!=""';
794 break;
795 }
796 $basePageRow=$this->sys_page->getPage($this->id);
797 if (is_array($basePageRow)) {
798 $res = $GLOBALS['TSFE']->cObj->exec_getQuery('tt_content', $selectSetup);
799 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
800 $GLOBALS['TSFE']->sys_page->versionOL('tt_content',$row);
801
802 if (is_array($row)) {
803 $temp[$row['uid']] = $basePageRow;
804 $temp[$row['uid']]['title'] = $row['header'];
805 $temp[$row['uid']]['nav_title'] = $row['header'];
806 $temp[$row['uid']]['subtitle'] = $row['subheader'];
807 $temp[$row['uid']]['starttime'] = $row['starttime'];
808 $temp[$row['uid']]['endtime'] = $row['endtime'];
809 $temp[$row['uid']]['fe_group'] = $row['fe_group'];
810 $temp[$row['uid']]['media'] = $row['media'];
811
812 $temp[$row['uid']]['header_layout'] = $row['header_layout'];
813 $temp[$row['uid']]['bodytext'] = $row['bodytext'];
814 $temp[$row['uid']]['image'] = $row['image'];
815
816 $temp[$row['uid']]['sectionIndex_uid'] = $row['uid'];
817 }
818 }
819 }
820 } else { // Default:
821 $temp = $this->sys_page->getMenu($this->id,'*',$altSortField); // gets the menu
822 }
823
824 $c=0;
825 $c_b=0;
826 $minItems = intval($this->mconf['minItems'] ? $this->mconf['minItems'] : $this->conf['minItems']);
827 $maxItems = intval($this->mconf['maxItems'] ? $this->mconf['maxItems'] : $this->conf['maxItems']);
828 $begin = tslib_cObj::calc($this->mconf['begin'] ? $this->mconf['begin'] : $this->conf['begin']);
829
830 $banUidArray = $this->getBannedUids();
831
832 // Fill in the menuArr with elements that should go into the menu:
833 $this->menuArr = Array();
834 foreach($temp as $data) {
835 $spacer = (t3lib_div::inList($this->spacerIDList,$data['doktype']) || !strcmp($data['ITEM_STATE'],'SPC')) ? 1 : 0; // if item is a spacer, $spacer is set
836 if ($this->filterMenuPages($data, $banUidArray, $spacer)) {
837 $c_b++;
838 if ($begin<=$c_b) { // If the beginning item has been reached.
839 $this->menuArr[$c] = $data;
840 $this->menuArr[$c]['isSpacer'] = $spacer;
841 $c++;
842 if ($maxItems && $c>=$maxItems) {
843 break;
844 }
845 }
846 }
847 }
848
849 // Fill in fake items, if min-items is set.
850 if ($minItems) {
851 while($c<$minItems) {
852 $this->menuArr[$c] = Array(
853 'title' => '...',
854 'uid' => $GLOBALS['TSFE']->id
855 );
856 $c++;
857 }
858 }
859 // Setting number of menu items
860 $GLOBALS['TSFE']->register['count_menuItems'] = count($this->menuArr);
861 // Passing the menuArr through a user defined function:
862 if ($this->mconf['itemArrayProcFunc']) {
863 if (!is_array($this->parentMenuArr)) {$this->parentMenuArr=array();}
864 $this->menuArr = $this->userProcess('itemArrayProcFunc',$this->menuArr);
865 }
866 $this->hash = md5(serialize($this->menuArr).serialize($this->mconf).serialize($this->tmpl->rootLine).serialize($this->MP_array));
867
868 // Get the cache timeout:
869 if ($this->conf['cache_period']) {
870 $cacheTimeout = $this->conf['cache_period'];
871 } else {
872 $cacheTimeout = $GLOBALS['TSFE']->get_cache_timeout();
873 }
874 $serData = $this->sys_page->getHash($this->hash, $cacheTimeout);
875 if (!$serData) {
876 $this->generate();
877 $this->sys_page->storeHash($this->hash, serialize($this->result),'MENUDATA');
878 } else {
879 $this->result = unserialize($serData);
880 }
881
882 // End showAccessRestrictedPages
883 if ($this->mconf['showAccessRestrictedPages']) {
884 // RESTORING where_groupAccess
885 $this->sys_page->where_groupAccess = $SAVED_where_groupAccess;
886 }
887 }
888 }
889
890 /**
891 * Includes the PHP script defined for the HMENU special type "userdefined".
892 * This script is supposed to populate the array $menuItemsArray with a set of page records comprising the menu.
893 * The "userdefined" type is deprecated since "userfunction" has arrived since and is a better choice for many reasons (like using classes/functions for rendering the menu)
894 *
895 * @param array TypoScript parameters for "special.". In particular the property "file" is reserved and specifies the file to include. Seems like any other property can be used freely by the script.
896 * @param string The sorting field. Can be used from the script in the $incFile.
897 * @return array An array with the menu items
898 * @access private
899 */
900 function includeMakeMenu($conf,$altSortField) {
901 $incFile = $GLOBALS['TSFE']->tmpl->getFileName($conf['file']);
902 if ($incFile && $GLOBALS['TSFE']->checkFileInclude($incFile)) {
903 include($incFile);
904 }
905 return is_array($menuItemsArray) ? $menuItemsArray : array();
906 }
907
908 /**
909 * Checks if a page is OK to include in the final menu item array. Pages can be excluded if the doktype is wrong, if they are hidden in navigation, have a uid in the list of banned uids etc.
910 *
911 * @param array Array of menu items
912 * @param array Array of page uids which are to be excluded
913 * @param boolean If set, then the page is a spacer.
914 * @return boolean Returns true if the page can be safely included.
915 */
916 function filterMenuPages(&$data,$banUidArray,$spacer) {
917
918 if ($data['_SAFE']) return TRUE;
919
920 $uid = $data['uid'];
921 if ($this->mconf['SPC'] || !$spacer) { // If the spacer-function is not enabled, spacers will not enter the $menuArr
922 if (!t3lib_div::inList($this->doktypeExcludeList,$data['doktype'])) { // Page may not be 'not_in_menu' or 'Backend User Section'
923 if (!$data['nav_hide'] || $this->conf['includeNotInMenu']) { // Not hidden in navigation
924 if (!t3lib_div::inArray($banUidArray,$uid)) { // not in banned uid's
925
926 // Checks if the default language version can be shown:
927 // Block page is set, if l18n_cfg allows plus: 1) Either default language or 2) another language but NO overlay record set for page!
928 $blockPage = $data['l18n_cfg']&1 && (!$GLOBALS['TSFE']->sys_language_uid || ($GLOBALS['TSFE']->sys_language_uid && !$data['_PAGES_OVERLAY']));
929 if (!$blockPage) {
930
931 // Checking if a page should be shown in the menu depending on whether a translation exists:
932 $tok = TRUE;
933 if ($GLOBALS['TSFE']->sys_language_uid && t3lib_div::hideIfNotTranslated($data['l18n_cfg'])) { // There is an alternative language active AND the current page requires a translation:
934 if (!$data['_PAGES_OVERLAY']) {
935 $tok = FALSE;
936 }
937 }
938
939 // Continue if token is true:
940 if ($tok) {
941
942 // Checking if "&L" should be modified so links to non-accessible pages will not happen.
943 if ($this->conf['protectLvar']) {
944 $languageUid = intval($GLOBALS['TSFE']->config['config']['sys_language_uid']);
945 if ($languageUid && ($this->conf['protectLvar']=='all' || t3lib_div::hideIfNotTranslated($data['l18n_cfg']))) {
946 $olRec = $GLOBALS['TSFE']->sys_page->getPageOverlay($data['uid'], $languageUid);
947 if (!count($olRec)) {
948 // If no pages_language_overlay record then page can NOT be accessed in the language pointed to by "&L" and therefore we protect the link by setting "&L=0"
949 $data['_ADD_GETVARS'].= '&L=0';
950 }
951 }
952 }
953
954 return TRUE;
955 }
956 }
957 }
958 }
959 }
960 }
961 }
962
963 /**
964 * Generating the per-menu-item configuration arrays based on the settings for item states (NO, RO, ACT, CUR etc) set in ->mconf (config for the current menu object)
965 * Basically it will produce an individual array for each menu item based on the item states. BUT in addition the "optionSplit" syntax for the values is ALSO evaluated here so that all property-values are "option-splitted" and the output will thus be resolved.
966 * Is called from the "generate" functions in the extension classes. The function is processor intensive due to the option split feature in particular. But since the generate function is not always called (since the ->result array may be cached, see makeMenu) it doesn't hurt so badly.
967 *
968 * @param integer Number of menu items in the menu
969 * @return array An array with two keys: array($NOconf,$ROconf) - where $NOconf contains the resolved configuration for each item when NOT rolled-over and $ROconf contains the ditto for the mouseover state (if any)
970 * @access private
971 */
972 function procesItemStates($splitCount) {
973
974 // Prepare normal settings
975 if (!is_array($this->mconf['NO.']) && $this->mconf['NO']) $this->mconf['NO.']=array(); // Setting a blank array if NO=1 and there are no properties.
976 $NOconf = $this->tmpl->splitConfArray($this->mconf['NO.'],$splitCount);
977
978 // Prepare rollOver settings, overriding normal settings
979 $ROconf=array();
980 if ($this->mconf['RO']) {
981 $ROconf = $this->tmpl->splitConfArray($this->mconf['RO.'],$splitCount);
982 }
983
984 // Prepare IFSUB settings, overriding normal settings
985 // IFSUB is true if there exist submenu items to the current item
986 if ($this->mconf['IFSUB']) {
987 $IFSUBinit = 0; // Flag: If $IFSUB is generated
988 reset($NOconf);
989 while (list($key,$val)=each($NOconf)) {
990 if ($this->isItemState('IFSUB',$key)) {
991 if (!$IFSUBinit) { // if this is the first IFSUB element, we must generate IFSUB.
992 $IFSUBconf = $this->tmpl->splitConfArray($this->mconf['IFSUB.'],$splitCount);
993 if ($this->mconf['IFSUBRO']) {
994 $IFSUBROconf = $this->tmpl->splitConfArray($this->mconf['IFSUBRO.'],$splitCount);
995 }
996 $IFSUBinit = 1;
997 }
998 $NOconf[$key] = $IFSUBconf[$key]; // Substitute normal with ifsub
999 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
1000 $ROconf[$key] = $IFSUBROconf[$key] ? $IFSUBROconf[$key] : $IFSUBconf[$key]; // If RollOver on active then apply this
1001 }
1002 }
1003 }
1004 }
1005 // Prepare active settings, overriding normal settings
1006 if ($this->mconf['ACT']) {
1007 $ACTinit = 0; // Flag: If $ACT is generated
1008 reset($NOconf);
1009 while (list($key,$val)=each($NOconf)) { // Find active
1010 if ($this->isItemState('ACT',$key)) {
1011 if (!$ACTinit) { // if this is the first 'active', we must generate ACT.
1012 $ACTconf = $this->tmpl->splitConfArray($this->mconf['ACT.'],$splitCount);
1013 // Prepare active rollOver settings, overriding normal active settings
1014 if ($this->mconf['ACTRO']) {
1015 $ACTROconf = $this->tmpl->splitConfArray($this->mconf['ACTRO.'],$splitCount);
1016 }
1017 $ACTinit = 1;
1018 }
1019 $NOconf[$key] = $ACTconf[$key]; // Substitute normal with active
1020 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
1021 $ROconf[$key] = $ACTROconf[$key] ? $ACTROconf[$key] : $ACTconf[$key]; // If RollOver on active then apply this
1022 }
1023 }
1024 }
1025 }
1026 // Prepare ACT (active)/IFSUB settings, overriding normal settings
1027 // ACTIFSUB is true if there exist submenu items to the current item and the current item is active
1028 if ($this->mconf['ACTIFSUB']) {
1029 $ACTIFSUBinit = 0; // Flag: If $ACTIFSUB is generated
1030 reset($NOconf);
1031 while (list($key,$val)=each($NOconf)) { // Find active
1032 if ($this->isItemState('ACTIFSUB',$key)) {
1033 if (!$ACTIFSUBinit) { // if this is the first 'active', we must generate ACTIFSUB.
1034 $ACTIFSUBconf = $this->tmpl->splitConfArray($this->mconf['ACTIFSUB.'],$splitCount);
1035 // Prepare active rollOver settings, overriding normal active settings
1036 if ($this->mconf['ACTIFSUBRO']) {
1037 $ACTIFSUBROconf = $this->tmpl->splitConfArray($this->mconf['ACTIFSUBRO.'],$splitCount);
1038 }
1039 $ACTIFSUBinit = 1;
1040 }
1041 $NOconf[$key] = $ACTIFSUBconf[$key]; // Substitute normal with active
1042 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
1043 $ROconf[$key] = $ACTIFSUBROconf[$key] ? $ACTIFSUBROconf[$key] : $ACTIFSUBconf[$key]; // If RollOver on active then apply this
1044 }
1045 }
1046 }
1047 }
1048 // Prepare CUR (current) settings, overriding normal settings
1049 // CUR is true if the current page equals the item here!
1050 if ($this->mconf['CUR']) {
1051 $CURinit = 0; // Flag: If $CUR is generated
1052 reset($NOconf);
1053 while (list($key,$val)=each($NOconf)) {
1054 if ($this->isItemState('CUR',$key)) {
1055 if (!$CURinit) { // if this is the first 'current', we must generate CUR. Basically this control is just inherited from the other implementations as current would only exist one time and thats it (unless you use special-features of HMENU)
1056 $CURconf = $this->tmpl->splitConfArray($this->mconf['CUR.'],$splitCount);
1057 if ($this->mconf['CURRO']) {
1058 $CURROconf = $this->tmpl->splitConfArray($this->mconf['CURRO.'],$splitCount);
1059 }
1060 $CURinit = 1;
1061 }
1062 $NOconf[$key] = $CURconf[$key]; // Substitute normal with current
1063 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
1064 $ROconf[$key] = $CURROconf[$key] ? $CURROconf[$key] : $CURconf[$key]; // If RollOver on active then apply this
1065 }
1066 }
1067 }
1068 }
1069 // Prepare CUR (current)/IFSUB settings, overriding normal settings
1070 // CURIFSUB is true if there exist submenu items to the current item and the current page equals the item here!
1071 if ($this->mconf['CURIFSUB']) {
1072 $CURIFSUBinit = 0; // Flag: If $CURIFSUB is generated
1073 reset($NOconf);
1074 while (list($key,$val)=each($NOconf)) {
1075 if ($this->isItemState('CURIFSUB',$key)) {
1076 if (!$CURIFSUBinit) { // if this is the first 'current', we must generate CURIFSUB.
1077 $CURIFSUBconf = $this->tmpl->splitConfArray($this->mconf['CURIFSUB.'],$splitCount);
1078 // Prepare current rollOver settings, overriding normal current settings
1079 if ($this->mconf['CURIFSUBRO']) {
1080 $CURIFSUBROconf = $this->tmpl->splitConfArray($this->mconf['CURIFSUBRO.'],$splitCount);
1081 }
1082 $CURIFSUBinit = 1;
1083 }
1084 $NOconf[$key] = $CURIFSUBconf[$key]; // Substitute normal with active
1085 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the current
1086 $ROconf[$key] = $CURIFSUBROconf[$key] ? $CURIFSUBROconf[$key] : $CURIFSUBconf[$key]; // If RollOver on current then apply this
1087 }
1088 }
1089 }
1090 }
1091 // Prepare active settings, overriding normal settings
1092 if ($this->mconf['USR']) {
1093 $USRinit = 0; // Flag: If $USR is generated
1094 reset($NOconf);
1095 while (list($key,$val)=each($NOconf)) { // Find active
1096 if ($this->isItemState('USR',$key)) {
1097 if (!$USRinit) { // if this is the first active, we must generate USR.
1098 $USRconf = $this->tmpl->splitConfArray($this->mconf['USR.'],$splitCount);
1099 // Prepare active rollOver settings, overriding normal active settings
1100 if ($this->mconf['USRRO']) {
1101 $USRROconf = $this->tmpl->splitConfArray($this->mconf['USRRO.'],$splitCount);
1102 }
1103 $USRinit = 1;
1104 }
1105 $NOconf[$key] = $USRconf[$key]; // Substitute normal with active
1106 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
1107 $ROconf[$key] = $USRROconf[$key] ? $USRROconf[$key] : $USRconf[$key]; // If RollOver on active then apply this
1108 }
1109 }
1110 }
1111 }
1112 // Prepare spacer settings, overriding normal settings
1113 if ($this->mconf['SPC']) {
1114 $SPCinit = 0; // Flag: If $SPC is generated
1115 reset($NOconf);
1116 while (list($key,$val)=each($NOconf)) { // Find spacers
1117 if ($this->isItemState('SPC',$key)) {
1118 if (!$SPCinit) { // if this is the first spacer, we must generate SPC.
1119 $SPCconf = $this->tmpl->splitConfArray($this->mconf['SPC.'],$splitCount);
1120 $SPCinit = 1;
1121 }
1122 $NOconf[$key] = $SPCconf[$key]; // Substitute normal with spacer
1123 }
1124 }
1125 }
1126 // Prepare Userdefined settings
1127 if ($this->mconf['USERDEF1']) {
1128 $USERDEF1init = 0; // Flag: If $USERDEF1 is generated
1129 reset($NOconf);
1130 while (list($key,$val)=each($NOconf)) { // Find active
1131 if ($this->isItemState('USERDEF1',$key)) {
1132 if (!$USERDEF1init) { // if this is the first active, we must generate USERDEF1.
1133 $USERDEF1conf = $this->tmpl->splitConfArray($this->mconf['USERDEF1.'],$splitCount);
1134 // Prepare active rollOver settings, overriding normal active settings
1135 if ($this->mconf['USERDEF1RO']) {
1136 $USERDEF1ROconf = $this->tmpl->splitConfArray($this->mconf['USERDEF1RO.'],$splitCount);
1137 }
1138 $USERDEF1init = 1;
1139 }
1140 $NOconf[$key] = $USERDEF1conf[$key]; // Substitute normal with active
1141 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
1142 $ROconf[$key] = $USERDEF1ROconf[$key] ? $USERDEF1ROconf[$key] : $USERDEF1conf[$key]; // If RollOver on active then apply this
1143 }
1144 }
1145 }
1146 }
1147 // Prepare Userdefined settings
1148 if ($this->mconf['USERDEF2']) {
1149 $USERDEF2init = 0; // Flag: If $USERDEF2 is generated
1150 reset($NOconf);
1151 while (list($key,$val)=each($NOconf)) { // Find active
1152 if ($this->isItemState('USERDEF2',$key)) {
1153 if (!$USERDEF2init) { // if this is the first active, we must generate USERDEF2.
1154 $USERDEF2conf = $this->tmpl->splitConfArray($this->mconf['USERDEF2.'],$splitCount);
1155 // Prepare active rollOver settings, overriding normal active settings
1156 if ($this->mconf['USERDEF2RO']) {
1157 $USERDEF2ROconf = $this->tmpl->splitConfArray($this->mconf['USERDEF2RO.'],$splitCount);
1158 }
1159 $USERDEF2init = 1;
1160 }
1161 $NOconf[$key] = $USERDEF2conf[$key]; // Substitute normal with active
1162 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
1163 $ROconf[$key] = $USERDEF2ROconf[$key] ? $USERDEF2ROconf[$key] : $USERDEF2conf[$key]; // If RollOver on active then apply this
1164 }
1165 }
1166 }
1167 }
1168
1169 return array($NOconf,$ROconf);
1170 }
1171
1172 /**
1173 * Creates the URL, target and onclick values for the menu item link. Returns them in an array as key/value pairs for <A>-tag attributes
1174 * This function doesn't care about the url, because if we let the url be redirected, it will be logged in the stat!!!
1175 *
1176 * @param integer Pointer to a key in the $this->menuArr array where the value for that key represents the menu item we are linking to (page record)
1177 * @param string Alternative target
1178 * @param integer Alternative type
1179 * @return array Returns an array with A-tag attributes as key/value pairs (HREF, TARGET and onClick)
1180 * @access private
1181 */
1182 function link($key,$altTarget='',$typeOverride='') {
1183
1184 // Mount points:
1185 $MP_var = $this->getMPvar($key);
1186 $MP_params = $MP_var ? '&MP='.rawurlencode($MP_var) : '';
1187
1188 // Setting override ID
1189 if ($this->mconf['overrideId'] || $this->menuArr[$key]['overrideId']) {
1190 $overrideArray = array();
1191 // If a user script returned the value overrideId in the menu array we use that as page id
1192 $overrideArray['uid'] = $this->mconf['overrideId']?$this->mconf['overrideId']:$this->menuArr[$key]['overrideId'];
1193 $overrideArray['alias'] = '';
1194 $MP_params = ''; // clear MP parameters since ID was changed.
1195 } else {
1196 $overrideArray='';
1197 }
1198
1199 // Setting main target:
1200 $mainTarget = $altTarget ? $altTarget : $this->mconf['target'];
1201
1202 // Creating link:
1203 if ($this->mconf['collapse'] && $this->isActive($this->menuArr[$key]['uid'], $this->getMPvar($key))) {
1204 $thePage = $this->sys_page->getPage($this->menuArr[$key]['pid']);
1205 $LD = $this->tmpl->linkData($thePage,$mainTarget,'','',$overrideArray, $this->mconf['addParams'].$MP_params.$this->menuArr[$key]['_ADD_GETVARS'], $typeOverride);
1206 } else {
1207 $LD = $this->tmpl->linkData($this->menuArr[$key],$mainTarget,'','',$overrideArray, $this->mconf['addParams'].$MP_params.$this->I['val']['additionalParams'].$this->menuArr[$key]['_ADD_GETVARS'], $typeOverride);
1208 }
1209
1210 // Override URL if using "External URL" as doktype with a valid e-mail address:
1211 if ($this->menuArr[$key]['doktype'] == 3 && $this->menuArr[$key]['urltype'] == 3 && t3lib_div::validEmail($this->menuArr[$key]['url'])) {
1212 // Create mailto-link using tslib_cObj::typolink (concerning spamProtectEmailAddresses):
1213 $LD['totalURL'] = $this->parent_cObj->typoLink_URL(array('parameter' => $this->menuArr[$key]['url']));
1214 $LD['target'] = '';
1215 }
1216
1217 // Manipulation in case of access restricted pages:
1218 $this->changeLinksForAccessRestrictedPages($LD,$this->menuArr[$key],$mainTarget,$typeOverride);
1219
1220 // Overriding URL / Target if set to do so:
1221 if ($this->menuArr[$key]['_OVERRIDE_HREF']) {
1222 $LD['totalURL'] = $this->menuArr[$key]['_OVERRIDE_HREF'];
1223 if ($this->menuArr[$key]['_OVERRIDE_TARGET']) $LD['target'] = $this->menuArr[$key]['_OVERRIDE_TARGET'];
1224 }
1225
1226 // OnClick open in windows.
1227 $onClick='';
1228 if ($this->mconf['JSWindow']) {
1229 $conf=$this->mconf['JSWindow.'];
1230 $url=$LD['totalURL'];
1231 $LD['totalURL'] = '#';
1232 $onClick= 'openPic(\''.$GLOBALS['TSFE']->baseUrlWrap($url).'\',\''.($conf['newWindow']?md5($url):'theNewPage').'\',\''.$conf['params'].'\'); return false;';
1233 $GLOBALS['TSFE']->setJS('openPic');
1234 }
1235
1236 // out:
1237 $list = array();
1238 $list['HREF'] = strlen($LD['totalURL']) ? $LD['totalURL'] : $GLOBALS['TSFE']->baseUrl; // Added this check: What it does is to enter the baseUrl (if set, which it should for "realurl" based sites) as URL if the calculated value is empty. The problem is that no link is generated with a blank URL and blank URLs might appear when the realurl encoding is used and a link to the frontpage is generated.
1239 $list['TARGET'] = $LD['target'];
1240 $list['onClick'] = $onClick;
1241
1242 return $list;
1243 }
1244
1245 /**
1246 * Will change $LD (passed by reference) if the page is access restricted
1247 *
1248 * @param array $LD, the array from the linkData() function
1249 * @param array Page array
1250 * @param string Main target value
1251 * @param string Type number override if any
1252 * @return void ($LD passed by reference might be changed.)
1253 */
1254 function changeLinksForAccessRestrictedPages(&$LD, $page, $mainTarget, $typeOverride) {
1255
1256 // If access restricted pages should be shown in menus, change the link of such pages to link to a redirection page:
1257 if ($this->mconf['showAccessRestrictedPages'] && $this->mconf['showAccessRestrictedPages']!=='NONE' && !$GLOBALS['TSFE']->checkPageGroupAccess($page)) {
1258 $thePage = $this->sys_page->getPage($this->mconf['showAccessRestrictedPages']);
1259
1260 $addParams = $this->mconf['showAccessRestrictedPages.']['addParams'];
1261 $addParams = str_replace('###RETURN_URL###',rawurlencode($LD['totalURL']),$addParams);
1262 $addParams = str_replace('###PAGE_ID###',$page['uid'],$addParams);
1263 $LD = $this->tmpl->linkData($thePage,$mainTarget,'','','', $addParams, $typeOverride);
1264 }
1265 }
1266
1267 /**
1268 * Creates a submenu level to the current level - if configured for.
1269 *
1270 * @param integer Page id of the current page for which a submenu MAY be produced (if conditions are met)
1271 * @param string Object prefix, see ->start()
1272 * @return string HTML content of the submenu
1273 * @access private
1274 */
1275 function subMenu($uid, $objSuffix='') {
1276
1277 // Setting alternative menu item array if _SUB_MENU has been defined in the current ->menuArr
1278 $altArray = '';
1279 if (is_array($this->menuArr[$this->I['key']]['_SUB_MENU']) && count($this->menuArr[$this->I['key']]['_SUB_MENU'])) {
1280 $altArray = $this->menuArr[$this->I['key']]['_SUB_MENU'];
1281 }
1282
1283 // Make submenu if the page is the next active
1284 $cls = strtolower($this->conf[($this->menuNumber+1).$objSuffix]);
1285 $subLevelClass = ($cls && t3lib_div::inList($this->tmpl->menuclasses,$cls)) ? $cls : '';
1286
1287 if ($subLevelClass && ($this->mconf['expAll'] || $this->isNext($uid, $this->getMPvar($this->I['key'])) || is_array($altArray)) && !$this->mconf['sectionIndex']) {
1288 $submenu = t3lib_div::makeInstance('tslib_'.$subLevelClass);
1289 $submenu->entryLevel = $this->entryLevel+1;
1290 $submenu->rL_uidRegister = $this->rL_uidRegister;
1291 $submenu->MP_array = $this->MP_array;
1292 if ($this->menuArr[$this->I['key']]['_MP_PARAM']) {
1293 $submenu->MP_array[] = $this->menuArr[$this->I['key']]['_MP_PARAM'];
1294 }
1295
1296 // especially scripts that build the submenu needs the parent data
1297 $submenu->parent_cObj = &$this->parent_cObj;
1298 $submenu->parentMenuArr = $this->menuArr;
1299
1300 // Setting alternativeMenuTempArray (will be effective only if an array)
1301 if (is_array($altArray)) {
1302 $submenu->alternativeMenuTempArray = $altArray;
1303 }
1304
1305 if ($submenu->start($this->tmpl, $this->sys_page, $uid, $this->conf, $this->menuNumber+1, $objSuffix)) {
1306 $submenu->makeMenu();
1307 return $submenu->writeMenu();
1308 }
1309 }
1310 }
1311
1312 /**
1313 * Returns true if the page with UID $uid is the NEXT page in root line (which means a submenu should be drawn)
1314 *
1315 * @param integer Page uid to evaluate.
1316 * @param string MPvar for the current position of item.
1317 * @return boolean True if page with $uid is active
1318 * @access private
1319 * @see subMenu()
1320 */
1321 function isNext($uid, $MPvar='') {
1322
1323 // Check for always active PIDs:
1324 if (count($this->alwaysActivePIDlist) && in_array($uid,$this->alwaysActivePIDlist)) {
1325 return TRUE;
1326 }
1327
1328 $testUid = $uid.($MPvar?':'.$MPvar:'');
1329 if ($uid && $testUid==$this->nextActive) {
1330 return TRUE;
1331 }
1332 }
1333
1334 /**
1335 * Returns true if the page with UID $uid is active (in the current rootline)
1336 *
1337 * @param integer Page uid to evaluate.
1338 * @param string MPvar for the current position of item.
1339 * @return boolean True if page with $uid is active
1340 * @access private
1341 */
1342 function isActive($uid, $MPvar='') {
1343
1344 // Check for always active PIDs:
1345 if (count($this->alwaysActivePIDlist) && in_array($uid,$this->alwaysActivePIDlist)) {
1346 return TRUE;
1347 }
1348
1349 $testUid = $uid.($MPvar?':'.$MPvar:'');
1350 if ($uid && in_array('ITEM:'.$testUid, $this->rL_uidRegister)) {
1351 return TRUE;
1352 }
1353 }
1354
1355 /**
1356 * Returns true if the page with UID $uid is the CURRENT page (equals $GLOBALS['TSFE']->id)
1357 *
1358 * @param integer Page uid to evaluate.
1359 * @param string MPvar for the current position of item.
1360 * @return boolean True if page $uid = $GLOBALS['TSFE']->id
1361 * @access private
1362 */
1363 function isCurrent($uid, $MPvar='') {
1364 $testUid = $uid.($MPvar?':'.$MPvar:'');
1365 if ($uid && !strcmp(end($this->rL_uidRegister),'ITEM:'.$testUid)) {
1366 return TRUE;
1367 }
1368 }
1369
1370 /**
1371 * Returns true if there is a submenu with items for the page id, $uid
1372 * Used by the item states "IFSUB", "ACTIFSUB" and "CURIFSUB" to check if there is a submenu
1373 *
1374 * @param integer Page uid for which to search for a submenu
1375 * @return boolean Returns true if there was a submenu with items found
1376 * @access private
1377 */
1378 function isSubMenu($uid) {
1379
1380 // Looking for a mount-pid for this UID since if that exists we should look for a subpages THERE and not in the input $uid;
1381 $mount_info = $this->sys_page->getMountPointInfo($uid);
1382 if (is_array($mount_info)) {
1383 $uid = $mount_info['mount_pid'];
1384 }
1385
1386 $recs = $this->sys_page->getMenu($uid,'uid,pid,doktype,mount_pid,mount_pid_ol,nav_hide,shortcut,shortcut_mode');
1387 foreach($recs as $theRec) {
1388 if (!t3lib_div::inList($this->doktypeExcludeList,$theRec['doktype']) && (!$theRec['nav_hide'] || $this->conf['includeNotInMenu'])) { // If a menu item seems to be another type than 'Not in menu', then return true (there were items!)
1389 return TRUE;
1390 }
1391 }
1392 }
1393
1394 /**
1395 * Used by procesItemStates() to evaluate if a menu item (identified by $key) is in a certain state.
1396 *
1397 * @param string The item state to evaluate (SPC, IFSUB, ACT etc... but no xxxRO states of course)
1398 * @param integer Key pointing to menu item from ->menuArr
1399 * @return boolean True (integer!=0) if match, otherwise false (=0, zero)
1400 * @access private
1401 * @see procesItemStates()
1402 */
1403 function isItemState($kind,$key) {
1404 $natVal=0;
1405 if ($this->menuArr[$key]['ITEM_STATE']) { // If any value is set for ITEM_STATE the normal evaluation is discarded
1406 if (!strcmp($this->menuArr[$key]['ITEM_STATE'],$kind)) {$natVal=1;}
1407 } else {
1408 switch($kind) {
1409 case 'SPC':
1410 $natVal = $this->menuArr[$key]['isSpacer'];
1411 break;
1412 case 'IFSUB':
1413 $natVal = $this->isSubMenu($this->menuArr[$key]['uid']);
1414 break;
1415 case 'ACT':
1416 $natVal = $this->isActive($this->menuArr[$key]['uid'], $this->getMPvar($key));
1417 break;
1418 case 'ACTIFSUB':
1419 $natVal = $this->isActive($this->menuArr[$key]['uid'], $this->getMPvar($key)) && $this->isSubMenu($this->menuArr[$key]['uid']);
1420 break;
1421 case 'CUR':
1422 $natVal = $this->isCurrent($this->menuArr[$key]['uid'], $this->getMPvar($key));
1423 break;
1424 case 'CURIFSUB':
1425 $natVal = $this->isCurrent($this->menuArr[$key]['uid'], $this->getMPvar($key)) && $this->isSubMenu($this->menuArr[$key]['uid']);
1426 break;
1427 case 'USR':
1428 $natVal = $this->menuArr[$key]['fe_group'];
1429 break;
1430 }
1431 }
1432
1433 return $natVal;
1434 }
1435
1436 /**
1437 * Creates an access-key for a TMENU/GMENU menu item based on the menu item titles first letter
1438 *
1439 * @param string Menu item title.
1440 * @return array Returns an array with keys "code" ("accesskey" attribute for the img-tag) and "alt" (text-addition to the "alt" attribute) if an access key was defined. Otherwise array was empty
1441 * @access private
1442 */
1443 function accessKey($title) {
1444 // The global array ACCESSKEY is used to globally control if letters are already used!!
1445 $result = Array();
1446
1447 $title = trim(strip_tags($title));
1448 $titleLen = strlen($title);
1449 for ($a=0;$a<$titleLen;$a++) {
1450 $key = strtoupper(substr($title,$a,1));
1451 if (preg_match('/[A-Z]/', $key) && !isset($GLOBALS['TSFE']->accessKey[$key])) {
1452 $GLOBALS['TSFE']->accessKey[$key] = 1;
1453 $result['code'] = ' accesskey="'.$key.'"';
1454 $result['alt'] = ' (ALT+'.$key.')';
1455 $result['key'] = $key;
1456 break;
1457 }
1458 }
1459 return $result;
1460 }
1461
1462 /**
1463 * Calls a user function for processing of internal data.
1464 * Used for the properties "IProcFunc" and "itemArrayProcFunc"
1465 *
1466 * @param string Key pointing for the property in the current ->mconf array holding possibly parameters to pass along to the function/method. Currently the keys used are "IProcFunc" and "itemArrayProcFunc".
1467 * @param mixed A variable to pass to the user function and which should be returned again from the user function. The idea is that the user function modifies this variable according to what you want to achieve and then returns it. For "itemArrayProcFunc" this variable is $this->menuArr, for "IProcFunc" it is $this->I
1468 * @return mixed The processed $passVar
1469 * @access private
1470 */
1471 function userProcess($mConfKey,$passVar) {
1472 if ($this->mconf[$mConfKey]) {
1473 $funcConf = $this->mconf[$mConfKey.'.'];
1474 $funcConf['parentObj']=&$this;
1475 $passVar = $GLOBALS['TSFE']->cObj->callUserFunction($this->mconf[$mConfKey], $funcConf, $passVar);
1476 }
1477 return $passVar;
1478 }
1479
1480 /**
1481 * Creates the <A> tag parts for the current item (in $this->I, [A1] and [A2]) based on other information in this array (like $this->I['linkHREF'])
1482 *
1483 * @return void
1484 * @access private
1485 */
1486 function setATagParts() {
1487 $this->I['A1'] = '<a '.t3lib_div::implodeAttributes($this->I['linkHREF'],1).' '.$this->I['val']['ATagParams'].$this->I['accessKey']['code'].'>';
1488 $this->I['A2'] = '</a>';
1489 }
1490
1491 /**
1492 * Returns the title for the navigation
1493 *
1494 * @param string The current page title
1495 * @param string The current value of the navigation title
1496 * @return string Returns the navigation title if it is NOT blank, otherwise the page title.
1497 * @access private
1498 */
1499 function getPageTitle($title,$nav_title) {
1500 return strcmp(trim($nav_title),'') ? $nav_title : $title;
1501 }
1502
1503 /**
1504 * Return MPvar string for entry $key in ->menuArr
1505 *
1506 * @param integer Pointer to element in ->menuArr
1507 * @param string Implode token.
1508 * @return string MP vars for element.
1509 * @see link()
1510 */
1511 function getMPvar($key) {
1512 if ($GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids']) {
1513 $localMP_array = $this->MP_array;
1514 if ($this->menuArr[$key]['_MP_PARAM']) $localMP_array[] = $this->menuArr[$key]['_MP_PARAM']; // NOTICE: "_MP_PARAM" is allowed to be a commalist of PID pairs!
1515 $MP_params = count($localMP_array) ? implode(',',$localMP_array) : '';
1516 return $MP_params;
1517 }
1518 }
1519
1520 /**
1521 * Returns where clause part to exclude 'not in menu' pages
1522 *
1523 * @return string where clause part.
1524 * @access private
1525 */
1526 function getDoktypeExcludeWhere() {
1527 return $this->doktypeExcludeList ? ' AND pages.doktype NOT IN ('.$this->doktypeExcludeList.')' : '';
1528 }
1529
1530 /**
1531 * Returns an array of banned UIDs (from excludeUidList)
1532 *
1533 * @return array Array of banned UIDs
1534 * @access private
1535 */
1536 function getBannedUids() {
1537 $banUidArray = array();
1538
1539 if (trim($this->conf['excludeUidList'])) {
1540 $banUidList = str_replace('current', $GLOBALS['TSFE']->page['uid'], $this->conf['excludeUidList']);
1541 $banUidArray = t3lib_div::intExplode(',', $banUidList);
1542 }
1543
1544 return $banUidArray;
1545 }
1546
1547 }
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567 /**
1568 * Extension class creating text based menus
1569 *
1570 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
1571 * @package TYPO3
1572 * @subpackage tslib
1573 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=387&cHash=73a3116ab8
1574 */
1575 class tslib_tmenu extends tslib_menu {
1576
1577 /**
1578 * Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
1579 * Sets the result for the new "normal state" in $this->result
1580 *
1581 * @return void
1582 * @see tslib_menu::procesItemStates()
1583 */
1584 function generate() {
1585 $splitCount = count($this->menuArr);
1586 if ($splitCount) {
1587 list($NOconf) = $this->procesItemStates($splitCount);
1588 }
1589 if ($this->mconf['debugItemConf']) {echo '<h3>$NOconf:</h3>'; debug($NOconf); }
1590 $this->result = $NOconf;
1591 }
1592
1593 /**
1594 * Traverses the ->result array of menu items configuration (made by ->generate()) and renders each item.
1595 * During the execution of this function many internal methods prefixed "extProc_" from this class is called and many of these are for now dummy functions. But they can be used for processing as they are used by the TMENU_LAYERS
1596 * An instance of tslib_cObj is also made and for each menu item rendered it is loaded with the record for that page so that any stdWrap properties that applies will have the current menu items record available.
1597 *
1598 * @return string The HTML for the menu (returns result through $this->extProc_finish(); )
1599 */
1600 function writeMenu() {
1601 if (is_array($this->result) && count($this->result)) {
1602 $this->WMcObj = t3lib_div::makeInstance('tslib_cObj'); // Create new tslib_cObj for our use
1603 $this->WMresult = '';
1604 $this->INPfixMD5 = substr(md5(microtime().'tmenu'),0,4);
1605 $this->WMmenuItems = count($this->result);
1606
1607 $this->WMsubmenuObjSuffixes = $this->tmpl->splitConfArray(array('sOSuffix'=>$this->mconf['submenuObjSuffixes']),$this->WMmenuItems);
1608
1609 $this->extProc_init();
1610 reset($this->result);
1611 while (list($key,$val)=each($this->result)) {
1612 $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']++;
1613 $GLOBALS['TSFE']->register['count_MENUOBJ']++;
1614
1615 $this->WMcObj->start($this->menuArr[$key],'pages'); // Initialize the cObj with the page record of the menu item
1616
1617 $this->I = array();
1618 $this->I['key'] = $key;
1619 $this->I['INPfix'] = ($this->imgNameNotRandom ? '' : '_'.$this->INPfixMD5).'_'.$key;
1620 $this->I['val'] = $val;
1621 $this->I['title'] = $this->WMcObj->stdWrap($this->getPageTitle($this->menuArr[$key]['title'],$this->menuArr[$key]['nav_title']),$this->I['val']['stdWrap.']);
1622 $this->I['uid'] = $this->menuArr[$key]['uid'];
1623 $this->I['mount_pid'] = $this->menuArr[$key]['mount_pid'];
1624 $this->I['pid'] = $this->menuArr[$key]['pid'];
1625 $this->I['spacer'] = $this->menuArr[$key]['isSpacer'];
1626
1627 // Set access key
1628 if ($this->mconf['accessKey']) {
1629 $this->I['accessKey'] = $this->accessKey($this->I['title']);
1630 } else {
1631 $this->I['accessKey'] = Array();
1632 }
1633
1634 // Make link tag
1635 $this->I['val']['ATagParams'] = $this->WMcObj->getATagParams($this->I['val']);
1636 $this->I['val']['additionalParams'] = $this->WMcObj->stdWrap($this->I['val']['additionalParams'],$this->I['val']['additionalParams.']);
1637 $this->I['linkHREF'] = $this->link($key,$this->I['val']['altTarget'],$this->mconf['forceTypeValue']);
1638
1639 // Title attribute of links:
1640 $titleAttrValue = $this->WMcObj->stdWrap($this->I['val']['ATagTitle'],$this->I['val']['ATagTitle.']).$this->I['accessKey']['alt'];
1641 if (strlen($titleAttrValue)) {
1642 $this->I['linkHREF']['title'] = $titleAttrValue;
1643 }
1644
1645 // Setting "blurlink()" function:
1646 if (!$this->mconf['noBlur']) {
1647 $this->I['linkHREF']['onFocus']='blurLink(this);';
1648 }
1649
1650 // Make link:
1651 if ($this->I['val']['RO']) {
1652 $this->I['theName'] = $this->imgNamePrefix.$this->I['uid'].$this->I['INPfix'];
1653 $over='';
1654 $out ='';
1655 if ($this->I['val']['beforeROImg']) {
1656 $over.= $this->WMfreezePrefix."over('".$this->I['theName']."before');";
1657 $out.= $this->WMfreezePrefix."out('".$this->I['theName']."before');";
1658 }
1659 if ($this->I['val']['afterROImg']) {
1660 $over.= $this->WMfreezePrefix."over('".$this->I['theName']."after');";
1661 $out.= $this->WMfreezePrefix."out('".$this->I['theName']."after');";
1662 }
1663 $this->I['linkHREF']['onMouseover']=$over;
1664 $this->I['linkHREF']['onMouseout']=$out;
1665 if ($over || $out) $GLOBALS['TSFE']->setJS('mouseOver');
1666
1667 // Change background color:
1668 if ($this->I['val']['RO_chBgColor']) {
1669 $this->addJScolorShiftFunction();
1670 $chBgP = t3lib_div::trimExplode('|',$this->I['val']['RO_chBgColor']);
1671 $this->I['linkHREF']['onMouseover'].="changeBGcolor('".$chBgP[2].$this->I['uid']."','".$chBgP[0]."');";
1672 $this->I['linkHREF']['onMouseout'].="changeBGcolor('".$chBgP[2].$this->I['uid']."','".$chBgP[1]."');";
1673 }
1674
1675 $this->extProc_RO($key);
1676 }
1677
1678
1679 // Calling extra processing function
1680 $this->extProc_beforeLinking($key);
1681
1682 // Compile link tag
1683 if (!$this->I['val']['doNotLinkIt']) {$this->I['val']['doNotLinkIt']=0;}
1684 if (!$this->I['spacer'] && $this->I['val']['doNotLinkIt']!=1) {
1685 $this->setATagParts();
1686 } else {
1687 $this->I['A1'] = '';
1688 $this->I['A2'] = '';
1689 }
1690
1691 // ATagBeforeWrap processing:
1692 if ($this->I['val']['ATagBeforeWrap']) {
1693 $wrapPartsBefore = explode('|',$this->I['val']['linkWrap']);
1694 $wrapPartsAfter = array('','');
1695 } else {
1696 $wrapPartsBefore = array('','');
1697 $wrapPartsAfter = explode('|',$this->I['val']['linkWrap']);
1698 }
1699 if ($this->I['val']['stdWrap2'] || isset($this->I['val']['stdWrap2.'])) {
1700 $wrapPartsStdWrap = explode($this->I['val']['stdWrap2']?$this->I['val']['stdWrap2']:'|',$this->WMcObj->stdWrap('|',$this->I['val']['stdWrap2.']));
1701 } else {$wrapPartsStdWrap = array('','');}
1702
1703 // Make before, middle and after parts
1704 $this->I['parts'] = array();
1705 $this->I['parts']['before']=$this->getBeforeAfter('before');
1706 $this->I['parts']['stdWrap2_begin']=$wrapPartsStdWrap[0];
1707 if (!$this->I['val']['doNotShowLink']) {
1708 $this->I['parts']['notATagBeforeWrap_begin'] = $wrapPartsAfter[0];
1709 $this->I['parts']['ATag_begin'] = $this->I['A1'];
1710 $this->I['parts']['ATagBeforeWrap_begin'] = $wrapPartsBefore[0];
1711 $this->I['parts']['title'] = $this->I['title'];
1712 $this->I['parts']['ATagBeforeWrap_end'] = $wrapPartsBefore[1];
1713 $this->I['parts']['ATag_end'] = $this->I['A2'];
1714 $this->I['parts']['notATagBeforeWrap_end'] = $wrapPartsAfter[1];
1715 }
1716 $this->I['parts']['stdWrap2_end']=$wrapPartsStdWrap[1];
1717 $this->I['parts']['after']=$this->getBeforeAfter('after');
1718
1719 // Passing I to a user function
1720 if ($this->mconf['IProcFunc']) {
1721 $this->I = $this->userProcess('IProcFunc',$this->I);
1722 }
1723
1724 // Merge parts + beforeAllWrap
1725 $this->I['theItem']= implode('',$this->I['parts']);
1726 $this->I['theItem']= $this->extProc_beforeAllWrap($this->I['theItem'],$key);
1727
1728 // allWrap:
1729 $allWrap = $this->WMcObj->stdWrap($this->I['val']['allWrap'],$this->I['val']['allWrap.']);
1730 $this->I['theItem'] = $this->tmpl->wrap($this->I['theItem'],$allWrap);
1731
1732 if ($this->I['val']['subst_elementUid']) $this->I['theItem'] = str_replace('{elementUid}',$this->I['uid'],$this->I['theItem']);
1733
1734 // allStdWrap:
1735 if (is_array($this->I['val']['allStdWrap.'])) {
1736 $this->I['theItem'] = $this->WMcObj->stdWrap($this->I['theItem'],$this->I['val']['allStdWrap.']);
1737 }
1738
1739 // Calling extra processing function
1740 $this->extProc_afterLinking($key);
1741 }
1742 return $this->extProc_finish();
1743 }
1744 }
1745
1746 /**
1747 * Generates the before* and after* images for TMENUs
1748 *
1749 * @param string Can be "before" or "after" and determines which kind of image to create (basically this is the prefix of the TypoScript properties that are read from the ->I['val'] array
1750 * @return string The resulting HTML of the image, if any.
1751 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=388&cHash=a7486044cd
1752 */
1753 function getBeforeAfter($pref) {
1754 $res = '';
1755 if ($imgInfo = $this->WMcObj->getImgResource($this->I['val'][$pref.'Img'],$this->I['val'][$pref.'Img.'])) {
1756 $imgInfo[3] = t3lib_div::png_to_gif_by_imagemagick($imgInfo[3]);
1757 if ($this->I['val']['RO'] && $this->I['val'][$pref.'ROImg'] && !$this->I['spacer']) {
1758 $imgROInfo = $this->WMcObj->getImgResource($this->I['val'][$pref.'ROImg'],$this->I['val'][$pref.'ROImg.']);
1759 $imgROInfo[3] = t3lib_div::png_to_gif_by_imagemagick($imgROInfo[3]);
1760 if ($imgROInfo) {
1761 $theName = $this->imgNamePrefix.$this->I['uid'].$this->I['INPfix'].$pref;
1762 $name = ' '.$this->nameAttribute.'="'.$theName.'"';
1763 $GLOBALS['TSFE']->JSImgCode.= chr(10).$theName.'_n=new Image(); '.$theName.'_n.src = "'.$GLOBALS['TSFE']->absRefPrefix.$imgInfo[3].'"; ';
1764 $GLOBALS['TSFE']->JSImgCode.= chr(10).$theName.'_h=new Image(); '.$theName.'_h.src = "'.$GLOBALS['TSFE']->absRefPrefix.$imgROInfo[3].'"; ';
1765 }
1766 }
1767 $GLOBALS['TSFE']->imagesOnPage[]=$imgInfo[3];
1768 $res='<img src="'.$GLOBALS['TSFE']->absRefPrefix.$imgInfo[3].'" width="'.$imgInfo[0].'" height="'.$imgInfo[1].'"'.$name.($this->I['val'][$pref.'ImgTagParams']?" ".$this->I['val'][$pref.'ImgTagParams']:'').tslib_cObj::getBorderAttr('border="0"');
1769 if (!strstr($res,'alt="')) $res.=' alt=""'; // Adding alt attribute if not set.
1770 $res.=' />';
1771 if ($this->I['val'][$pref.'ImgLink']) {$res=$this->I['A1'].$res.$this->I['A2'];}
1772 }
1773 return $this->tmpl->wrap($res.$this->WMcObj->stdWrap($this->I['val'][$pref],$this->I['val'][$pref.'.']), $this->I['val'][$pref.'Wrap']);
1774 }
1775
1776 /**
1777 * Adds a JavaScript function to the $GLOBALS['TSFE']->additionalJavaScript array
1778 *
1779 * @return void
1780 * @access private
1781 * @see writeMenu()
1782 */
1783 function addJScolorShiftFunction() {
1784 $GLOBALS['TSFE']->additionalJavaScript['TMENU:changeBGcolor()']='
1785 function changeBGcolor(id,color) { //
1786 if (document.getElementById && document.getElementById(id)) {
1787 document.getElementById(id).style.background = color;
1788 return true;
1789 } else if (document.layers && document.layers[id]) {
1790 document.layers[id].bgColor = color;
1791 return true;
1792 }
1793 }
1794 ';
1795 }
1796
1797 /**
1798 * Called right before the traversing of $this->result begins.
1799 * Can be used for various initialization
1800 *
1801 * @return void
1802 * @access private
1803 * @see writeMenu(), tslib_tmenu_layers::extProc_init()
1804 */
1805 function extProc_init() {
1806 }
1807
1808 /**
1809 * Called after all processing for RollOver of an element has been done.
1810 *
1811 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
1812 * @return void
1813 * @access private
1814 * @see writeMenu(), tslib_tmenu_layers::extProc_RO()
1815 */
1816 function extProc_RO($key) {
1817 }
1818
1819 /**
1820 * Called right before the creation of the link for the menu item
1821 *
1822 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
1823 * @return void
1824 * @access private
1825 * @see writeMenu(), tslib_tmenu_layers::extProc_beforeLinking()
1826 */
1827 function extProc_beforeLinking($key) {
1828 }
1829
1830 /**
1831 * Called right after the creation of links for the menu item. This is also the last function call before the while-loop traversing menu items goes to the next item.
1832 * This function MUST set $this->WMresult.=[HTML for menu item] to add the generated menu item to the internal accumulation of items.
1833 *
1834 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
1835 * @return void
1836 * @access private
1837 * @see writeMenu(), tslib_tmenu_layers::extProc_afterLinking()
1838 */
1839 function extProc_afterLinking($key) {
1840 // Add part to the accumulated result + fetch submenus
1841 if (!$this->I['spacer']) {
1842 $this->I['theItem'].= $this->subMenu($this->I['uid'], $this->WMsubmenuObjSuffixes[$key]['sOSuffix']);
1843 }
1844 $this->WMresult.= $this->I['val']['wrapItemAndSub'] ? $this->tmpl->wrap($this->I['theItem'],$this->I['val']['wrapItemAndSub']) : $this->I['theItem'];
1845 }
1846
1847 /**
1848 * Called before the "allWrap" happens on the menu item.
1849 *
1850 * @param string The current content of the menu item, $this->I['theItem'], passed along.
1851 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
1852 * @return string The modified version of $item, going back into $this->I['theItem']
1853 * @access private
1854 * @see writeMenu(), tslib_tmenu_layers::extProc_beforeAllWrap()
1855 */
1856 function extProc_beforeAllWrap($item,$key) {
1857 return $item;
1858 }
1859
1860 /**
1861 * Called before the writeMenu() function returns (only if a menu was generated)
1862 *
1863 * @return string The total menu content should be returned by this function
1864 * @access private
1865 * @see writeMenu(), tslib_tmenu_layers::extProc_finish()
1866 */
1867 function extProc_finish() {
1868 // stdWrap:
1869 if (is_array($this->mconf['stdWrap.'])) {
1870 $this->WMresult = $this->WMcObj->stdWrap($this->WMresult,$this->mconf['stdWrap.']);
1871 }
1872 return $this->tmpl->wrap($this->WMresult,$this->mconf['wrap']).$this->WMextraScript;
1873 }
1874 }
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899 /**
1900 * Extension class creating graphic based menus (PNG or GIF files)
1901 *
1902 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
1903 * @package TYPO3
1904 * @subpackage tslib
1905 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=384&cHash=93a7644cba
1906 */
1907 class tslib_gmenu extends tslib_menu {
1908
1909 /**
1910 * Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
1911 * Calls makeGifs() for all "normal" items and if configured for, also the "rollover" items.
1912 *
1913 * @return void
1914 * @see tslib_menu::procesItemStates(), makeGifs()
1915 */
1916 function generate() {
1917 $splitCount = count($this->menuArr);
1918 if ($splitCount) {
1919 list($NOconf,$ROconf) = $this->procesItemStates($splitCount);
1920
1921 //store initial count value
1922 $temp_HMENU_MENUOBJ = $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ'];
1923 $temp_MENUOBJ = $GLOBALS['TSFE']->register['count_MENUOBJ'];
1924 // Now we generate the giffiles:
1925 $this->makeGifs($NOconf,'NO');
1926 // store count from NO obj
1927 $tempcnt_HMENU_MENUOBJ = $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ'];
1928 $tempcnt_MENUOBJ = $GLOBALS['TSFE']->register['count_MENUOBJ'];
1929
1930 if ($this->mconf['debugItemConf']) {echo '<h3>$NOconf:</h3>'; debug($NOconf); }
1931 if ($ROconf) { // RollOver
1932 //start recount for rollover with initial values
1933 $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']= $temp_HMENU_MENUOBJ;
1934 $GLOBALS['TSFE']->register['count_MENUOBJ']= $temp_MENUOBJ;
1935 $this->makeGifs($ROconf,'RO');
1936 if ($this->mconf['debugItemConf']) {echo '<h3>$ROconf:</h3>'; debug($ROconf); }
1937 }
1938 // use count from NO obj
1939 $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ'] = $tempcnt_HMENU_MENUOBJ;
1940 $GLOBALS['TSFE']->register['count_MENUOBJ'] = $tempcnt_MENUOBJ;
1941 }
1942 }
1943
1944 /**
1945 * Will traverse input array with configuratoin per-item and create corresponding GIF files for the menu.
1946 * The data of the files are stored in $this->result
1947 *
1948 * @param array Array with configuration for each item.
1949 * @param string Type of images: normal ("NO") or rollover ("RO"). Valid values are "NO" and "RO"
1950 * @return void
1951 * @access private
1952 * @see generate()
1953 */
1954 function makeGifs($conf, $resKey) {
1955 $isGD = $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'];
1956
1957 if (!is_array($conf)) {
1958 $conf = Array();
1959 }
1960
1961 $totalWH=array();
1962 $items = count($conf);
1963 if ($isGD) {
1964 // generate the gif-files. the $menuArr is filled with some values like output_w, output_h, output_file
1965 $Hcounter = 0;
1966 $Wcounter = 0;
1967 $Hobjs = $this->mconf['applyTotalH'];
1968 if ($Hobjs) {$Hobjs = t3lib_div::intExplode(',',$Hobjs);}
1969 $Wobjs = $this->mconf['applyTotalW'];
1970 if ($Wobjs) {$Wobjs = t3lib_div::intExplode(',',$Wobjs);}
1971 $minDim = $this->mconf['min'];
1972 if ($minDim) {$minDim = tslib_cObj::calcIntExplode(',',$minDim.',');}
1973 $maxDim = $this->mconf['max'];
1974 if ($maxDim) {$maxDim = tslib_cObj::calcIntExplode(',',$maxDim.',');}
1975
1976 if ($minDim) {
1977 $conf[$items]=$conf[$items-1];
1978 $this->menuArr[$items]=Array();
1979 $items = count($conf);
1980 }
1981
1982 // TOTAL width
1983 if ($this->mconf['useLargestItemX'] || $this->mconf['useLargestItemY'] || $this->mconf['distributeX'] || $this->mconf['distributeY']) {
1984 $totalWH = $this->findLargestDims($conf,$items,$Hobjs,$Wobjs,$minDim,$maxDim);
1985 }
1986 }
1987
1988 $c=0;
1989 $maxFlag=0;
1990 $distributeAccu=array('H'=>0,'W'=>0);
1991 reset($conf);
1992 while (list($key,$val)=each($conf)) {
1993 $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']++;
1994 $GLOBALS['TSFE']->register['count_MENUOBJ']++;
1995
1996 if ($items==($c+1) && $minDim) {
1997 $Lobjs = $this->mconf['removeObjectsOfDummy'];
1998 if ($Lobjs) {
1999 $Lobjs = t3lib_div::intExplode(',',$Lobjs);
2000 reset($Lobjs);
2001 while(list(,$remItem)=each($Lobjs)) {
2002 unset($val[$remItem]);
2003 unset($val[$remItem.'.']);
2004 }
2005 }
2006
2007 $flag =0;
2008 $tempXY = explode(',',$val['XY']);
2009 if ($Wcounter<$minDim[0]) {$tempXY[0]=$minDim[0]-$Wcounter; $flag=1;}
2010 if ($Hcounter<$minDim[1]) {$tempXY[1]=$minDim[1]-$Hcounter; $flag=1;}
2011 $val['XY'] = implode(',',$tempXY);
2012 if (!$flag){break;}
2013 }
2014 $c++;
2015
2016
2017 if ($isGD) {
2018 // Pre-working the item
2019 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
2020 $gifCreator->init();
2021 $gifCreator->start($val,$this->menuArr[$key]);
2022
2023 // If useLargestItemH/W is specified
2024 if (count($totalWH) && ($this->mconf['useLargestItemX'] || $this->mconf['useLargestItemY'])) {
2025 $tempXY = explode(',',$gifCreator->setup['XY']);
2026 if ($this->mconf['useLargestItemX']) {$tempXY[0] = max($totalWH['W']);}
2027 if ($this->mconf['useLargestItemY']) {$tempXY[1] = max($totalWH['H']);}
2028 // regenerate the new values...
2029 $val['XY'] = implode(',',$tempXY);
2030 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
2031 $gifCreator->init();
2032 $gifCreator->start($val,$this->menuArr[$key]);
2033 }
2034
2035 // If distributeH/W is specified
2036 if (count($totalWH) && ($this->mconf['distributeX'] || $this->mconf['distributeY'])) {
2037 $tempXY = explode(',',$gifCreator->setup['XY']);
2038
2039 if ($this->mconf['distributeX']) {
2040 $diff = $this->mconf['distributeX']-$totalWH['W_total']-$distributeAccu['W'];
2041 $compensate = round($diff /($items-$c+1));
2042 $distributeAccu['W']+=$compensate;
2043 $tempXY[0] = $totalWH['W'][$key]+$compensate;
2044 }
2045 if ($this->mconf['distributeY']) {
2046 $diff = $this->mconf['distributeY']-$totalWH['H_total']-$distributeAccu['H'];
2047 $compensate = round($diff /($items-$c+1));
2048 $distributeAccu['H']+=$compensate;
2049 $tempXY[1] = $totalWH['H'][$key]+$compensate;
2050 }
2051 // regenerate the new values...
2052 $val['XY'] = implode(',',$tempXY);
2053 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
2054 $gifCreator->init();
2055 $gifCreator->start($val,$this->menuArr[$key]);
2056 }
2057
2058 // If max dimensions are specified
2059 if ($maxDim) {
2060 $tempXY = explode(',',$val['XY']);
2061 if ($maxDim[0] && $Wcounter+$gifCreator->XY[0]>=$maxDim[0]) {$tempXY[0]==$maxDim[0]-$Wcounter; $maxFlag=1;}
2062 if ($maxDim[1] && $Hcounter+$gifCreator->XY[1]>=$maxDim[1]) {$tempXY[1]=$maxDim[1]-$Hcounter; $maxFlag=1;}
2063 if ($maxFlag) {
2064 $val['XY'] = implode(',',$tempXY);
2065 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
2066 $gifCreator->init();
2067 $gifCreator->start($val,$this->menuArr[$key]);
2068 }
2069 }
2070
2071
2072
2073
2074 // displace
2075 if ($Hobjs) {
2076 reset($Hobjs);
2077 while(list(,$index)=each($Hobjs)) {
2078 if ($gifCreator->setup[$index] && $gifCreator->setup[$index.'.']) {
2079 $oldOffset = explode(',',$gifCreator->setup[$index.'.']['offset']);
2080 $gifCreator->setup[$index.'.']['offset'] = implode(',',$gifCreator->applyOffset($oldOffset,Array(0,-$Hcounter)));
2081 }
2082 }
2083 }
2084
2085 if ($Wobjs) {
2086 reset($Wobjs);
2087 while(list(,$index)=each($Wobjs)) {
2088 if ($gifCreator->setup[$index] && $gifCreator->setup[$index.'.']) {
2089 $oldOffset = explode(',',$gifCreator->setup[$index.'.']['offset']);
2090 $gifCreator->setup[$index.'.']['offset'] = implode(',',$gifCreator->applyOffset($oldOffset,Array(-$Wcounter,0)));
2091 }
2092 }
2093 }
2094 }
2095
2096 // Finding alternative GIF names if any (by altImgResource)
2097 $gifFileName='';
2098 if ($conf[$key]['altImgResource'] || is_array($conf[$key]['altImgResource.'])) {
2099 if (!is_object($cObj)) {$cObj=t3lib_div::makeInstance('tslib_cObj');}
2100 $cObj->start($this->menuArr[$key],'pages');
2101 $altImgInfo = $cObj->getImgResource($conf[$key]['altImgResource'],$conf[$key]['altImgResource.']);
2102 $gifFileName=$altImgInfo[3];
2103 }
2104
2105 // If an alternative name was NOT given, find the GIFBUILDER name.
2106 if (!$gifFileName && $isGD) {
2107 $gifCreator->createTempSubDir('menu/');
2108 $gifFileName = $gifCreator->fileName('menu/');
2109 }
2110
2111 $this->result[$resKey][$key] = $conf[$key];
2112
2113 // Generation of image file:
2114 if (@file_exists($gifFileName)) { // File exists
2115 $info = @getimagesize($gifFileName);
2116 $this->result[$resKey][$key]['output_w']=intval($info[0]);
2117 $this->result[$resKey][$key]['output_h']=intval($info[1]);
2118 $this->result[$resKey][$key]['output_file'] = $gifFileName;
2119 } elseif ($isGD) { // file is generated
2120 $gifCreator->make();
2121 $this->result[$resKey][$key]['output_w']=$gifCreator->w;
2122 $this->result[$resKey][$key]['output_h']=$gifCreator->h;
2123 $this->result[$resKey][$key]['output_file'] = $gifFileName;
2124 $gifCreator->output($this->result[$resKey][$key]['output_file']);
2125 $gifCreator->destroy();
2126 }
2127
2128 $this->result[$resKey][$key]['output_file'] = t3lib_div::png_to_gif_by_imagemagick($this->result[$resKey][$key]['output_file']);
2129
2130 $Hcounter+=$this->result[$resKey][$key]['output_h']; // counter is increased
2131 $Wcounter+=$this->result[$resKey][$key]['output_w']; // counter is increased
2132
2133 if ($maxFlag) break;
2134 }
2135 }
2136
2137 /**
2138 * Function searching for the largest width and height of the menu items to be generated.
2139 * Uses some of the same code as makeGifs and even instantiates some gifbuilder objects BUT does not render the images - only reading out which width they would have.
2140 * Remember to upgrade the code in here if the makeGifs function is updated.
2141 *
2142 * @param array Same configuration array as passed to makeGifs()
2143 * @param integer The number of menu items
2144 * @param array Array with "applyTotalH" numbers
2145 * @param array Array with "applyTotalW" numbers
2146 * @param array Array with "min" x/y
2147 * @param array Array with "max" x/y
2148 * @return array Array with keys "H" and "W" which are in themselves arrays with the heights and widths of menu items inside. This can be used to find the max/min size of the menu items.
2149 * @access private
2150 * @see makeGifs()
2151 */
2152 function findLargestDims($conf,$items,$Hobjs,$Wobjs,$minDim,$maxDim) {
2153 $totalWH = array(
2154 'W' => array(),
2155 'H' => array(),
2156 'W_total' => 0,
2157 'H_total' => 0
2158 );
2159
2160 $Hcounter = 0;
2161 $Wcounter = 0;
2162 $c=0;
2163 $maxFlag=0;
2164 reset($conf);
2165 while (list($key,$val)=each($conf)) {
2166 // SAME CODE AS makeGifs()! BEGIN
2167 if ($items==($c+1) && $minDim) {
2168 $Lobjs = $this->mconf['removeObjectsOfDummy'];
2169 if ($Lobjs) {
2170 $Lobjs = t3lib_div::intExplode(',',$Lobjs);
2171 reset($Lobjs);
2172 while(list(,$remItem)=each($Lobjs)) {
2173 unset($val[$remItem]);
2174 unset($val[$remItem.'.']);
2175 }
2176 }
2177
2178 $flag =0;
2179 $tempXY = explode(',',$val['XY']);
2180 if ($Wcounter<$minDim[0]) {$tempXY[0]=$minDim[0]-$Wcounter; $flag=1;}
2181 if ($Hcounter<$minDim[1]) {$tempXY[1]=$minDim[1]-$Hcounter; $flag=1;}
2182 $val['XY'] = implode(',',$tempXY);
2183 if (!$flag){break;}
2184 }
2185 $c++;
2186
2187 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
2188 $gifCreator->init();
2189 $gifCreator->start($val,$this->menuArr[$key]);
2190 if ($maxDim) {
2191 $tempXY = explode(',',$val['XY']);
2192 if ($maxDim[0] && $Wcounter+$gifCreator->XY[0]>=$maxDim[0]) {$tempXY[0]==$maxDim[0]-$Wcounter; $maxFlag=1;}
2193 if ($maxDim[1] && $Hcounter+$gifCreator->XY[1]>=$maxDim[1]) {$tempXY[1]=$maxDim[1]-$Hcounter; $maxFlag=1;}
2194 if ($maxFlag) {
2195 $val['XY'] = implode(',',$tempXY);
2196 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
2197 $gifCreator->init();
2198 $gifCreator->start($val,$this->menuArr[$key]);
2199 }
2200 }
2201 // SAME CODE AS makeGifs()! END
2202
2203 // Setting the width/height
2204 $totalWH['W'][$key]=$gifCreator->XY[0];
2205 $totalWH['H'][$key]=$gifCreator->XY[1];
2206 $totalWH['W_total']+=$gifCreator->XY[0];
2207 $totalWH['H_total']+=$gifCreator->XY[1];
2208 // ---- //
2209
2210 $Hcounter+=$gifCreator->XY[1]; // counter is increased
2211 $Wcounter+=$gifCreator->XY[0]; // counter is increased
2212
2213 if ($maxFlag){break;}
2214 }
2215 return $totalWH;
2216 }
2217
2218 /**
2219 * Traverses the ->result['NO'] array of menu items configuration (made by ->generate()) and renders the HTML of each item (the images themselves was made with makeGifs() before this. See ->generate())
2220 * During the execution of this function many internal methods prefixed "extProc_" from this class is called and many of these are for now dummy functions. But they can be used for processing as they are used by the GMENU_LAYERS
2221 *
2222 * @return string The HTML for the menu (returns result through $this->extProc_finish(); )
2223 */
2224 function writeMenu() {
2225 if (is_array($this->menuArr) && is_array($this->result) && count($this->result) && is_array($this->result['NO'])) {
2226 $this->WMcObj = t3lib_div::makeInstance('tslib_cObj'); // Create new tslib_cObj for our use
2227 $this->WMresult = '';
2228 $this->INPfixMD5 = substr(md5(microtime().$this->GMENU_fixKey),0,4);
2229 $this->WMmenuItems = count($this->result['NO']);
2230
2231 $this->WMsubmenuObjSuffixes = $this->tmpl->splitConfArray(array('sOSuffix'=>$this->mconf['submenuObjSuffixes']),$this->WMmenuItems);
2232
2233 $this->extProc_init();
2234 for ($key=0;$key<$this->WMmenuItems;$key++) {
2235 if ($this->result['NO'][$key]['output_file']) {
2236 $this->WMcObj->start($this->menuArr[$key],'pages'); // Initialize the cObj with the page record of the menu item
2237
2238 $this->I = array();
2239 $this->I['key'] = $key;
2240 $this->I['INPfix']= ($this->imgNameNotRandom ? '' : '_'.$this->INPfixMD5).'_'.$key;
2241 $this->I['val'] = $this->result['NO'][$key];
2242 $this->I['title'] = $this->getPageTitle($this->menuArr[$key]['title'],$this->menuArr[$key]['nav_title']);
2243 $this->I['uid'] = $this->menuArr[$key]['uid'];
2244 $this->I['mount_pid'] = $this->menuArr[$key]['mount_pid'];
2245 $this->I['pid'] = $this->menuArr[$key]['pid'];
2246 $this->I['spacer'] = $this->menuArr[$key]['isSpacer'];
2247 if (!$this->I['uid'] && !$this->menuArr[$key]['_OVERRIDE_HREF']) {$this->I['spacer']=1;}
2248 $this->I['noLink'] = ($this->I['spacer'] || $this->I['val']['noLink'] || !count($this->menuArr[$key])); // !count($this->menuArr[$key]) means that this item is a dummyItem
2249 $this->I['name'] = '';
2250
2251 // Set access key
2252 if ($this->mconf['accessKey']) {
2253 $this->I['accessKey'] = $this->accessKey($this->I['title']);
2254 } else {
2255 $this->I['accessKey'] = array();
2256 }
2257
2258 // Make link tag
2259 $this->I['val']['ATagParams'] = $this->WMcObj->getATagParams($this->I['val']);
2260 $this->I['val']['additionalParams'] = $this->WMcObj->stdWrap($this->I['val']['additionalParams'],$this->I['val']['additionalParams.']);
2261 $this->I['linkHREF'] = $this->link($key,$this->I['val']['altTarget'],$this->mconf['forceTypeValue']);
2262
2263 // Title attribute of links:
2264 $titleAttrValue = $this->WMcObj->stdWrap($this->I['val']['ATagTitle'],$this->I['val']['ATagTitle.']).$this->I['accessKey']['alt'];
2265 if (strlen($titleAttrValue)) {
2266 $this->I['linkHREF']['title'] = $titleAttrValue;
2267 }
2268 // Setting "blurlink()" function:
2269 if (!$this->mconf['noBlur']) {
2270 $this->I['linkHREF']['onFocus']='blurLink(this);';
2271 }
2272
2273 // Set rollover
2274 if ($this->result['RO'][$key] && !$this->I['noLink']) {
2275 $this->I['theName'] = $this->imgNamePrefix.$this->I['uid'].$this->I['INPfix'];
2276 $this->I['name'] = ' '.$this->nameAttribute.'="'.$this->I["theName"].'"';
2277 $this->I['linkHREF']['onMouseover']=$this->WMfreezePrefix.'over(\''.$this->I['theName'].'\');';
2278 $this->I['linkHREF']['onMouseout']=$this->WMfreezePrefix.'out(\''.$this->I['theName'].'\');';
2279 $GLOBALS['TSFE']->JSImgCode.= chr(10).$this->I['theName'].'_n=new Image(); '.$this->I['theName'].'_n.src = "'.$GLOBALS['TSFE']->absRefPrefix.$this->I['val']['output_file'].'"; ';
2280 $GLOBALS['TSFE']->JSImgCode.= chr(10).$this->I['theName'].'_h=new Image(); '.$this->I['theName'].'_h.src = "'.$GLOBALS['TSFE']->absRefPrefix.$this->result['RO'][$key]['output_file'].'"; ';
2281 $GLOBALS['TSFE']->imagesOnPage[]=$this->result['RO'][$key]['output_file'];
2282 $GLOBALS['TSFE']->setJS('mouseOver');
2283 $this->extProc_RO($key);
2284 }
2285
2286 // Set altText
2287 $this->I['altText'] = $this->I['title'].$this->I['accessKey']['alt'];
2288
2289 // Calling extra processing function
2290 $this->extProc_beforeLinking($key);
2291
2292 // Set linking
2293 if (!$this->I['noLink']) {
2294 $this->setATagParts();
2295 } else {
2296 $this->I['A1'] = '';
2297 $this->I['A2'] = '';
2298 }
2299 $this->I['IMG'] = '<img src="'.$GLOBALS['TSFE']->absRefPrefix.$this->I['val']['output_file'].'" width="'.$this->I['val']['output_w'].'" height="'.$this->I['val']['output_h'].'" '.tslib_cObj::getBorderAttr('border="0"').($this->mconf['disableAltText'] ? '' : ' alt="'.htmlspecialchars($this->I['altText']).'"').$this->I['name'].($this->I['val']['imgParams']?' '.$this->I['val']['imgParams']:'').' />';
2300
2301 // Make before, middle and after parts
2302 $this->I['parts'] = array();
2303 $this->I['parts']['ATag_begin'] = $this->I['A1'];
2304 $this->I['parts']['image'] = $this->I['IMG'];
2305 $this->I['parts']['ATag_end'] = $this->I['A2'];
2306
2307 // Passing I to a user function
2308 if ($this->mconf['IProcFunc']) {
2309 $this->I = $this->userProcess('IProcFunc',$this->I);
2310 }
2311
2312 // Putting the item together.
2313 // Merge parts + beforeAllWrap
2314 $this->I['theItem']= implode('',$this->I['parts']);
2315 $this->I['theItem']= $this->extProc_beforeAllWrap($this->I['theItem'],$key);
2316
2317 // wrap:
2318 $this->I['theItem']= $this->tmpl->wrap($this->I['theItem'],$this->I['val']['wrap']);
2319
2320 // allWrap:
2321 $allWrap = $this->WMcObj->stdWrap($this->I['val']['allWrap'],$this->I['val']['allWrap.']);
2322 $this->I['theItem'] = $this->tmpl->wrap($this->I['theItem'],$allWrap);
2323
2324 if ($this->I['val']['subst_elementUid']) $this->I['theItem'] = str_replace('{elementUid}',$this->I['uid'],$this->I['theItem']);
2325
2326 // allStdWrap:
2327 if (is_array($this->I['val']['allStdWrap.'])) {
2328 $this->I['theItem'] = $this->WMcObj->stdWrap($this->I['theItem'],$this->I['val']['allStdWrap.']);
2329 }
2330
2331 $GLOBALS['TSFE']->imagesOnPage[]=$this->I['val']['output_file'];
2332
2333 $this->extProc_afterLinking($key);
2334 }
2335 }
2336 return $this->extProc_finish();
2337 }
2338 }
2339
2340 /**
2341 * Called right before the traversing of $this->result begins.
2342 * Can be used for various initialization
2343 *
2344 * @return void
2345 * @access private
2346 * @see writeMenu(), tslib_gmenu_layers::extProc_init()
2347 */
2348 function extProc_init() {
2349 }
2350
2351 /**
2352 * Called after all processing for RollOver of an element has been done.
2353 *
2354 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found OR $this->result['RO'][$key] where the configuration for that elements RO version is found!
2355 * @return void
2356 * @access private
2357 * @see writeMenu(), tslib_gmenu_layers::extProc_RO()
2358 */
2359 function extProc_RO($key) {
2360 }
2361
2362 /**
2363 * Called right before the creation of the link for the menu item
2364 *
2365 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
2366 * @return void
2367 * @access private
2368 * @see writeMenu(), tslib_gmenu_layers::extProc_beforeLinking()
2369 */
2370 function extProc_beforeLinking($key) {
2371 }
2372
2373 /**
2374 * Called right after the creation of links for the menu item. This is also the last function call before the for-loop traversing menu items goes to the next item.
2375 * This function MUST set $this->WMresult.=[HTML for menu item] to add the generated menu item to the internal accumulation of items.
2376 * Further this calls the subMenu function in the parent class to create any submenu there might be.
2377 *
2378 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
2379 * @return void
2380 * @access private
2381 * @see writeMenu(), tslib_gmenu_layers::extProc_afterLinking(), tslib_menu::subMenu()
2382 */
2383 function extProc_afterLinking($key) {
2384 $this->WMresult.=$this->I['theItem'];
2385 if (!$this->I['spacer']) {
2386 $this->WMresult.= $this->subMenu($this->I['uid'], $this->WMsubmenuObjSuffixes[$key]['sOSuffix']);
2387 }
2388 }
2389
2390
2391 /**
2392 * Called before the "wrap" happens on the menu item.
2393 *
2394 * @param string The current content of the menu item, $this->I['theItem'], passed along.
2395 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
2396 * @return string The modified version of $item, going back into $this->I['theItem']
2397 * @access private
2398 * @see writeMenu(), tslib_gmenu_layers::extProc_beforeAllWrap()
2399 */
2400 function extProc_beforeAllWrap($item,$key) {
2401 return $item;
2402 }
2403
2404 /**
2405 * Called before the writeMenu() function returns (only if a menu was generated)
2406 *
2407 * @return string The total menu content should be returned by this function
2408 * @access private
2409 * @see writeMenu(), tslib_gmenu_layers::extProc_finish()
2410 */
2411 function extProc_finish() {
2412 // stdWrap:
2413 if (is_array($this->mconf['stdWrap.'])) {
2414 $this->WMresult = $this->WMcObj->stdWrap($this->WMresult,$this->mconf['stdWrap.']);
2415 }
2416 return $this->tmpl->wrap($this->WMresult,$this->mconf['wrap']).$this->WMextraScript;
2417 }
2418 }
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441 /**
2442 * ImageMap based menus
2443 *
2444 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
2445 * @package TYPO3
2446 * @subpackage tslib
2447 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=389&cHash=fcf18c5d9f
2448 */
2449 class tslib_imgmenu extends tslib_menu {
2450
2451 /**
2452 * Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
2453 * Calls makeImageMap() to generate the image map image-file
2454 *
2455 * @return void
2456 * @see tslib_menu::procesItemStates(), makeImageMap()
2457 */
2458 function generate() {
2459 $splitCount = count($this->menuArr);
2460 if ($splitCount) {
2461 list($NOconf) = $this->procesItemStates($splitCount);
2462 }
2463 if ($this->mconf['debugItemConf']) {echo '<h3>$NOconf:</h3>'; debug($NOconf); }
2464 $this->makeImageMap($NOconf);
2465 }
2466
2467 /**
2468 * Will traverse input array with configuratoin per-item and create corresponding GIF files for the menu.
2469 * The data of the files are stored in $this->result
2470 *
2471 * @param array Array with configuration for each item.
2472 * @return void
2473 * @access private
2474 * @see generate()
2475 */
2476 function makeImageMap($conf) {
2477 if (!is_array($conf)) {
2478 $conf = Array();
2479 }
2480 if (is_array($this->mconf['main.'])) {
2481 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
2482 $gifCreator->init();
2483
2484 $itemsConf = $conf;
2485 $conf = $this->mconf['main.'];
2486 if (is_array($conf)) {
2487 $gifObjCount = 0;
2488
2489 $sKeyArray=t3lib_TStemplate::sortedKeyList($conf);
2490 $gifObjCount=intval(end($sKeyArray));
2491
2492 $lastOriginal = $gifObjCount;
2493
2494 // Now we add graphical objects to the gifbuilder-setup
2495 reset($itemsConf);
2496 $waArr = Array();
2497 while (list($key,$val)=each($itemsConf)) {
2498 if (is_array($val)) {
2499 $gifObjCount++;
2500 $waArr[$key]['free']=$gifObjCount;
2501
2502 $sKeyArray=t3lib_TStemplate::sortedKeyList($val);
2503
2504 foreach($sKeyArray as $theKey) {
2505 $theValue=$val[$theKey];
2506
2507
2508 if (intval($theKey) && $theValArr=$val[$theKey.'.']) {
2509 $cObjData = $this->menuArr[$key] ? $this->menuArr[$key] : Array();
2510
2511 $gifObjCount++;
2512 if ($theValue=='TEXT') {
2513 $waArr[$key]['textNum']=$gifObjCount;
2514
2515 $gifCreator->data = $cObjData;
2516 $theValArr = $gifCreator->checkTextObj($theValArr);
2517 unset($theValArr['text.']); // if this is not done it seems that imageMaps will be rendered wrong!!
2518 // check links
2519
2520 $LD = $this->tmpl->linkData($this->menuArr[$key],$this->mconf['target'],'','',array(),'',$this->mconf['forceTypeValue']);
2521
2522 // If access restricted pages should be shown in menus, change the link of such pages to link to a redirection page:
2523 $this->changeLinksForAccessRestrictedPages($LD, $this->menuArr[$key], $this->mconf['target'], $this->mconf['forceTypeValue']);
2524
2525 // Overriding URL / Target if set to do so:
2526 if ($this->menuArr[$key]['_OVERRIDE_HREF']) {
2527 $LD['totalURL'] = $this->menuArr[$key]['_OVERRIDE_HREF'];
2528 if ($this->menuArr[$key]['_OVERRIDE_TARGET']) $LD['target'] = $this->menuArr[$key]['_OVERRIDE_TARGET'];
2529 }
2530
2531 // Setting target/url for Image Map:
2532 if ($theValArr['imgMap.']['url']=='') {
2533 $theValArr['imgMap.']['url'] = $LD['totalURL'];
2534 }
2535 if ($theValArr['imgMap.']['target']=='') {
2536 $theValArr['imgMap.']['target'] = $LD['target'];
2537 }
2538 if ($theValArr['imgMap.']['noBlur']=='') {
2539 $theValArr['imgMap.']['noBlur'] = $this->mconf['noBlur'];
2540 }
2541 if (is_array($theValArr['imgMap.']['altText.'])) {
2542 $cObj =t3lib_div::makeInstance('tslib_cObj');
2543 $cObj->start($cObjData,'pages');
2544 $theValArr['imgMap.']['altText'] = $cObj->stdWrap($theValArr['imgMap.']['altText'], $theValArr['imgMap.']['altText.']);
2545 unset($theValArr['imgMap.']['altText.']);
2546 }
2547 if (is_array($theValArr['imgMap.']['titleText.'])) {
2548 $cObj =t3lib_div::makeInstance('tslib_cObj');
2549 $cObj->start($cObjData,'pages');
2550 $theValArr['imgMap.']['titleText'] = $cObj->stdWrap($theValArr['imgMap.']['titleText'], $theValArr['imgMap.']['titleText.']);
2551 unset($theValArr['imgMap.']['titleText.']);
2552 }
2553 }
2554 // This code goes one level in if the object is an image. If 'file' and/or 'mask' appears to be GIFBUILDER-objects, they are both searched for TEXT objects, and if a textobj is found, it's checked with the currently loaded record!!
2555 if ($theValue=='IMAGE') {
2556 if ($theValArr['file']=='GIFBUILDER') {
2557 $temp_sKeyArray=t3lib_TStemplate::sortedKeyList($theValArr['file.']);
2558 reset($temp_sKeyArray);
2559 while(list(,$temp_theKey)=each($temp_sKeyArray)) {
2560 if ($theValArr['mask.'][$temp_theKey]=='TEXT') {
2561 $gifCreator->data = $this->menuArr[$key] ? $this->menuArr[$key] : Array();
2562 $theValArr['mask.'][$temp_theKey.'.'] = $gifCreator->checkTextObj($theValArr['mask.'][$temp_theKey.'.']);
2563 unset($theValArr['mask.'][$temp_theKey.'.']['text.']); // if this is not done it seems that imageMaps will be rendered wrong!!
2564 }
2565 }
2566 }
2567 if ($theValArr['mask']=='GIFBUILDER') {
2568 $temp_sKeyArray=t3lib_TStemplate::sortedKeyList($theValArr['mask.']);
2569 reset($temp_sKeyArray);
2570 while(list(,$temp_theKey)=each($temp_sKeyArray)) {
2571 if ($theValArr['mask.'][$temp_theKey]=='TEXT') {
2572 $gifCreator->data = $this->menuArr[$key] ? $this->menuArr[$key] : Array();
2573 $theValArr['mask.'][$temp_theKey.'.'] = $gifCreator->checkTextObj($theValArr['mask.'][$temp_theKey.'.']);
2574 unset($theValArr['mask.'][$temp_theKey.'.']['text.']); // if this is not done it seems that imageMaps will be rendered wrong!!
2575 }
2576 }
2577 }
2578 }
2579
2580 // Checks if disabled is set...
2581 $setObjFlag=1;
2582 if ($theValArr['if.']) {
2583 $cObj =t3lib_div::makeInstance('tslib_cObj');
2584 $cObj->start($cObjData,'pages');
2585 if (!$cObj->checkIf($theValArr['if.'])) {
2586 $setObjFlag=0;
2587 }
2588 unset($theValArr['if.']);
2589 }
2590 // Set the object!
2591 if ($setObjFlag) {
2592 $conf[$gifObjCount] = $theValue;
2593 $conf[$gifObjCount.'.'] = $theValArr;
2594 }
2595 }
2596 }
2597 }
2598 }
2599
2600 $gifCreator->start($conf,$GLOBALS['TSFE']->page);
2601 // calculations
2602
2603 $sum=Array(0,0,0,0);
2604 reset($waArr);
2605 while (list($key,$val)=each($waArr)) {
2606 if ($dConf[$key] =$itemsConf[$key]['distrib']) {
2607 $textBB = $gifCreator->objBB[$val['textNum']];
2608 $dConf[$key] = str_replace('textX',$textBB[0],$dConf[$key]);
2609 $dConf[$key] = str_replace('textY',$textBB[1],$dConf[$key]);
2610 $dConf[$key] = t3lib_div::intExplode(',',$gifCreator->calcOffset($dConf[$key]));
2611 }
2612 }
2613 $workArea = t3lib_div::intExplode(',',$gifCreator->calcOffset($this->mconf['dWorkArea']));
2614 reset($waArr);
2615 while (list($key,$val)=each($waArr)) {
2616 $index = $val['free'];
2617 $gifCreator->setup[$index] = 'WORKAREA';
2618 $workArea[2] = $dConf[$key][2] ? $dConf[$key][2] : $dConf[$key][0];
2619 $workArea[3] = $dConf[$key][3] ? $dConf[$key][3] : $dConf[$key][1];
2620
2621 $gifCreator->setup[$index.'.']['set'] = implode(',',$workArea);
2622 $workArea[0]+=$dConf[$key][0];
2623 $workArea[1]+=$dConf[$key][1];
2624 }
2625
2626 if ($this->mconf['debugRenumberedObject']) {echo '<h3>Renumbered GIFBUILDER object:</h3>'; debug($gifCreator->setup);}
2627
2628 $gifCreator->createTempSubDir('menu/');
2629 $gifFileName = $gifCreator->fileNa