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