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