Fixed bug #5048: JSMENU produces error if using baseurls (thanks to Jens Koester)
[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 // Get the cache timeout:
840 if ($this->conf['cache_period']) {
841 $cacheTimeout = $this->conf['cache_period'];
842 } else {
843 $cacheTimeout = $GLOBALS['TSFE']->get_cache_timeout();
844 }
845 $serData = $this->sys_page->getHash($this->hash, $cacheTimeout);
846 if (!$serData) {
847 $this->generate();
848 $this->sys_page->storeHash($this->hash, serialize($this->result),'MENUDATA');
849 } else {
850 $this->result = unserialize($serData);
851 }
852
853 // End showAccessRestrictedPages
854 if ($this->mconf['showAccessRestrictedPages']) {
855 // RESTORING where_groupAccess
856 $this->sys_page->where_groupAccess = $SAVED_where_groupAccess;
857 }
858 }
859 }
860
861 /**
862 * Includes the PHP script defined for the HMENU special type "userdefined".
863 * This script is supposed to populate the array $menuItemsArray with a set of page records comprising the menu.
864 * 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)
865 *
866 * @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.
867 * @param string The sorting field. Can be used from the script in the $incFile.
868 * @return array An array with the menu items
869 * @access private
870 */
871 function includeMakeMenu($conf,$altSortField) {
872 $incFile = $GLOBALS['TSFE']->tmpl->getFileName($conf['file']);
873 if ($incFile && $GLOBALS['TSFE']->checkFileInclude($incFile)) {
874 include($incFile);
875 }
876 return is_array($menuItemsArray) ? $menuItemsArray : array();
877 }
878
879 /**
880 * 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.
881 *
882 * @param array Array of menu items
883 * @param array Array of page uids which are to be excluded
884 * @param boolean If set, then the page is a spacer.
885 * @return boolean Returns true if the page can be safely included.
886 */
887 function filterMenuPages(&$data,$banUidArray,$spacer) {
888
889 if ($data['_SAFE']) return TRUE;
890
891 $uid = $data['uid'];
892 if ($this->mconf['SPC'] || !$spacer) { // If the spacer-function is not enabled, spacers will not enter the $menuArr
893 if (!t3lib_div::inList($this->doktypeExcludeList,$data['doktype'])) { // Page may not be 'not_in_menu' or 'Backend User Section'
894 if (!$data['nav_hide'] || $this->conf['includeNotInMenu']) { // Not hidden in navigation
895 if (!t3lib_div::inArray($banUidArray,$uid)) { // not in banned uid's
896
897 // Checks if the default language version can be shown:
898 // Block page is set, if l18n_cfg allows plus: 1) Either default language or 2) another language but NO overlay record set for page!
899 $blockPage = $data['l18n_cfg']&1 && (!$GLOBALS['TSFE']->sys_language_uid || ($GLOBALS['TSFE']->sys_language_uid && !$data['_PAGES_OVERLAY']));
900 if (!$blockPage) {
901
902 // Checking if a page should be shown in the menu depending on whether a translation exists:
903 $tok = TRUE;
904 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:
905 if (!$data['_PAGES_OVERLAY']) {
906 $tok = FALSE;
907 }
908 }
909
910 // Continue if token is true:
911 if ($tok) {
912
913 // Checking if "&L" should be modified so links to non-accessible pages will not happen.
914 if ($this->conf['protectLvar']) {
915 $languageUid = intval($GLOBALS['TSFE']->config['config']['sys_language_uid']);
916 if ($languageUid && ($this->conf['protectLvar']=='all' || t3lib_div::hideIfNotTranslated($data['l18n_cfg']))) {
917 $olRec = $GLOBALS['TSFE']->sys_page->getPageOverlay($data['uid'], $languageUid);
918 if (!count($olRec)) {
919 // 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"
920 $data['_ADD_GETVARS'].= '&L=0';
921 }
922 }
923 }
924
925 return TRUE;
926 }
927 }
928 }
929 }
930 }
931 }
932 }
933
934 /**
935 * 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)
936 * 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.
937 * 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.
938 *
939 * @param integer Number of menu items in the menu
940 * @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)
941 * @access private
942 */
943 function procesItemStates($splitCount) {
944
945 // Prepare normal settings
946 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.
947 $NOconf = $this->tmpl->splitConfArray($this->mconf['NO.'],$splitCount);
948
949 // Prepare rollOver settings, overriding normal settings
950 $ROconf=array();
951 if ($this->mconf['RO']) {
952 $ROconf = $this->tmpl->splitConfArray($this->mconf['RO.'],$splitCount);
953 }
954
955 // Prepare IFSUB settings, overriding normal settings
956 // IFSUB is true if there exist submenu items to the current item
957 if ($this->mconf['IFSUB']) {
958 $IFSUBinit = 0; // Flag: If $IFSUB is generated
959 reset($NOconf);
960 while (list($key,$val)=each($NOconf)) {
961 if ($this->isItemState('IFSUB',$key)) {
962 if (!$IFSUBinit) { // if this is the first IFSUB element, we must generate IFSUB.
963 $IFSUBconf = $this->tmpl->splitConfArray($this->mconf['IFSUB.'],$splitCount);
964 if ($this->mconf['IFSUBRO']) {
965 $IFSUBROconf = $this->tmpl->splitConfArray($this->mconf['IFSUBRO.'],$splitCount);
966 }
967 $IFSUBinit = 1;
968 }
969 $NOconf[$key] = $IFSUBconf[$key]; // Substitute normal with ifsub
970 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
971 $ROconf[$key] = $IFSUBROconf[$key] ? $IFSUBROconf[$key] : $IFSUBconf[$key]; // If RollOver on active then apply this
972 }
973 }
974 }
975 }
976 // Prepare active settings, overriding normal settings
977 if ($this->mconf['ACT']) {
978 $ACTinit = 0; // Flag: If $ACT is generated
979 reset($NOconf);
980 while (list($key,$val)=each($NOconf)) { // Find active
981 if ($this->isItemState('ACT',$key)) {
982 if (!$ACTinit) { // if this is the first 'active', we must generate ACT.
983 $ACTconf = $this->tmpl->splitConfArray($this->mconf['ACT.'],$splitCount);
984 // Prepare active rollOver settings, overriding normal active settings
985 if ($this->mconf['ACTRO']) {
986 $ACTROconf = $this->tmpl->splitConfArray($this->mconf['ACTRO.'],$splitCount);
987 }
988 $ACTinit = 1;
989 }
990 $NOconf[$key] = $ACTconf[$key]; // Substitute normal with active
991 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
992 $ROconf[$key] = $ACTROconf[$key] ? $ACTROconf[$key] : $ACTconf[$key]; // If RollOver on active then apply this
993 }
994 }
995 }
996 }
997 // Prepare ACT (active)/IFSUB settings, overriding normal settings
998 // ACTIFSUB is true if there exist submenu items to the current item and the current item is active
999 if ($this->mconf['ACTIFSUB']) {
1000 $ACTIFSUBinit = 0; // Flag: If $ACTIFSUB is generated
1001 reset($NOconf);
1002 while (list($key,$val)=each($NOconf)) { // Find active
1003 if ($this->isItemState('ACTIFSUB',$key)) {
1004 if (!$ACTIFSUBinit) { // if this is the first 'active', we must generate ACTIFSUB.
1005 $ACTIFSUBconf = $this->tmpl->splitConfArray($this->mconf['ACTIFSUB.'],$splitCount);
1006 // Prepare active rollOver settings, overriding normal active settings
1007 if ($this->mconf['ACTIFSUBRO']) {
1008 $ACTIFSUBROconf = $this->tmpl->splitConfArray($this->mconf['ACTIFSUBRO.'],$splitCount);
1009 }
1010 $ACTIFSUBinit = 1;
1011 }
1012 $NOconf[$key] = $ACTIFSUBconf[$key]; // Substitute normal with active
1013 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
1014 $ROconf[$key] = $ACTIFSUBROconf[$key] ? $ACTIFSUBROconf[$key] : $ACTIFSUBconf[$key]; // If RollOver on active then apply this
1015 }
1016 }
1017 }
1018 }
1019 // Prepare CUR (current) settings, overriding normal settings
1020 // CUR is true if the current page equals the item here!
1021 if ($this->mconf['CUR']) {
1022 $CURinit = 0; // Flag: If $CUR is generated
1023 reset($NOconf);
1024 while (list($key,$val)=each($NOconf)) {
1025 if ($this->isItemState('CUR',$key)) {
1026 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)
1027 $CURconf = $this->tmpl->splitConfArray($this->mconf['CUR.'],$splitCount);
1028 if ($this->mconf['CURRO']) {
1029 $CURROconf = $this->tmpl->splitConfArray($this->mconf['CURRO.'],$splitCount);
1030 }
1031 $CURinit = 1;
1032 }
1033 $NOconf[$key] = $CURconf[$key]; // Substitute normal with current
1034 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
1035 $ROconf[$key] = $CURROconf[$key] ? $CURROconf[$key] : $CURconf[$key]; // If RollOver on active then apply this
1036 }
1037 }
1038 }
1039 }
1040 // Prepare CUR (current)/IFSUB settings, overriding normal settings
1041 // CURIFSUB is true if there exist submenu items to the current item and the current page equals the item here!
1042 if ($this->mconf['CURIFSUB']) {
1043 $CURIFSUBinit = 0; // Flag: If $CURIFSUB is generated
1044 reset($NOconf);
1045 while (list($key,$val)=each($NOconf)) {
1046 if ($this->isItemState('CURIFSUB',$key)) {
1047 if (!$CURIFSUBinit) { // if this is the first 'current', we must generate CURIFSUB.
1048 $CURIFSUBconf = $this->tmpl->splitConfArray($this->mconf['CURIFSUB.'],$splitCount);
1049 // Prepare current rollOver settings, overriding normal current settings
1050 if ($this->mconf['CURIFSUBRO']) {
1051 $CURIFSUBROconf = $this->tmpl->splitConfArray($this->mconf['CURIFSUBRO.'],$splitCount);
1052 }
1053 $CURIFSUBinit = 1;
1054 }
1055 $NOconf[$key] = $CURIFSUBconf[$key]; // Substitute normal with active
1056 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the current
1057 $ROconf[$key] = $CURIFSUBROconf[$key] ? $CURIFSUBROconf[$key] : $CURIFSUBconf[$key]; // If RollOver on current then apply this
1058 }
1059 }
1060 }
1061 }
1062 // Prepare active settings, overriding normal settings
1063 if ($this->mconf['USR']) {
1064 $USRinit = 0; // Flag: If $USR is generated
1065 reset($NOconf);
1066 while (list($key,$val)=each($NOconf)) { // Find active
1067 if ($this->isItemState('USR',$key)) {
1068 if (!$USRinit) { // if this is the first active, we must generate USR.
1069 $USRconf = $this->tmpl->splitConfArray($this->mconf['USR.'],$splitCount);
1070 // Prepare active rollOver settings, overriding normal active settings
1071 if ($this->mconf['USRRO']) {
1072 $USRROconf = $this->tmpl->splitConfArray($this->mconf['USRRO.'],$splitCount);
1073 }
1074 $USRinit = 1;
1075 }
1076 $NOconf[$key] = $USRconf[$key]; // Substitute normal with active
1077 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
1078 $ROconf[$key] = $USRROconf[$key] ? $USRROconf[$key] : $USRconf[$key]; // If RollOver on active then apply this
1079 }
1080 }
1081 }
1082 }
1083 // Prepare spacer settings, overriding normal settings
1084 if ($this->mconf['SPC']) {
1085 $SPCinit = 0; // Flag: If $SPC is generated
1086 reset($NOconf);
1087 while (list($key,$val)=each($NOconf)) { // Find spacers
1088 if ($this->isItemState('SPC',$key)) {
1089 if (!$SPCinit) { // if this is the first spacer, we must generate SPC.
1090 $SPCconf = $this->tmpl->splitConfArray($this->mconf['SPC.'],$splitCount);
1091 $SPCinit = 1;
1092 }
1093 $NOconf[$key] = $SPCconf[$key]; // Substitute normal with spacer
1094 }
1095 }
1096 }
1097 // Prepare Userdefined settings
1098 if ($this->mconf['USERDEF1']) {
1099 $USERDEF1init = 0; // Flag: If $USERDEF1 is generated
1100 reset($NOconf);
1101 while (list($key,$val)=each($NOconf)) { // Find active
1102 if ($this->isItemState('USERDEF1',$key)) {
1103 if (!$USERDEF1init) { // if this is the first active, we must generate USERDEF1.
1104 $USERDEF1conf = $this->tmpl->splitConfArray($this->mconf['USERDEF1.'],$splitCount);
1105 // Prepare active rollOver settings, overriding normal active settings
1106 if ($this->mconf['USERDEF1RO']) {
1107 $USERDEF1ROconf = $this->tmpl->splitConfArray($this->mconf['USERDEF1RO.'],$splitCount);
1108 }
1109 $USERDEF1init = 1;
1110 }
1111 $NOconf[$key] = $USERDEF1conf[$key]; // Substitute normal with active
1112 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
1113 $ROconf[$key] = $USERDEF1ROconf[$key] ? $USERDEF1ROconf[$key] : $USERDEF1conf[$key]; // If RollOver on active then apply this
1114 }
1115 }
1116 }
1117 }
1118 // Prepare Userdefined settings
1119 if ($this->mconf['USERDEF2']) {
1120 $USERDEF2init = 0; // Flag: If $USERDEF2 is generated
1121 reset($NOconf);
1122 while (list($key,$val)=each($NOconf)) { // Find active
1123 if ($this->isItemState('USERDEF2',$key)) {
1124 if (!$USERDEF2init) { // if this is the first active, we must generate USERDEF2.
1125 $USERDEF2conf = $this->tmpl->splitConfArray($this->mconf['USERDEF2.'],$splitCount);
1126 // Prepare active rollOver settings, overriding normal active settings
1127 if ($this->mconf['USERDEF2RO']) {
1128 $USERDEF2ROconf = $this->tmpl->splitConfArray($this->mconf['USERDEF2RO.'],$splitCount);
1129 }
1130 $USERDEF2init = 1;
1131 }
1132 $NOconf[$key] = $USERDEF2conf[$key]; // Substitute normal with active
1133 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
1134 $ROconf[$key] = $USERDEF2ROconf[$key] ? $USERDEF2ROconf[$key] : $USERDEF2conf[$key]; // If RollOver on active then apply this
1135 }
1136 }
1137 }
1138 }
1139
1140 return array($NOconf,$ROconf);
1141 }
1142
1143 /**
1144 * 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
1145 * This function doesn't care about the url, because if we let the url be redirected, it will be logged in the stat!!!
1146 *
1147 * @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)
1148 * @param string Alternative target
1149 * @param integer Alternative type
1150 * @return array Returns an array with A-tag attributes as key/value pairs (HREF, TARGET and onClick)
1151 * @access private
1152 */
1153 function link($key,$altTarget='',$typeOverride='') {
1154
1155 // Mount points:
1156 $MP_var = $this->getMPvar($key);
1157 $MP_params = $MP_var ? '&MP='.rawurlencode($MP_var) : '';
1158
1159 // Setting override ID
1160 if ($this->mconf['overrideId'] || $this->menuArr[$key]['overrideId']) {
1161 $overrideArray = array();
1162 // If a user script returned the value overrideId in the menu array we use that as page id
1163 $overrideArray['uid'] = $this->mconf['overrideId']?$this->mconf['overrideId']:$this->menuArr[$key]['overrideId'];
1164 $overrideArray['alias'] = '';
1165 $MP_params = ''; // clear MP parameters since ID was changed.
1166 } else {
1167 $overrideArray='';
1168 }
1169
1170 // Setting main target:
1171 $mainTarget = $altTarget ? $altTarget : $this->mconf['target'];
1172
1173 // Creating link:
1174 if ($this->mconf['collapse'] && $this->isActive($this->menuArr[$key]['uid'], $this->getMPvar($key))) {
1175 $thePage = $this->sys_page->getPage($this->menuArr[$key]['pid']);
1176 $LD = $this->tmpl->linkData($thePage,$mainTarget,'','',$overrideArray, $this->mconf['addParams'].$MP_params.$this->menuArr[$key]['_ADD_GETVARS'], $typeOverride);
1177 } else {
1178 $LD = $this->tmpl->linkData($this->menuArr[$key],$mainTarget,'','',$overrideArray, $this->mconf['addParams'].$MP_params.$this->I['val']['additionalParams'].$this->menuArr[$key]['_ADD_GETVARS'], $typeOverride);
1179 }
1180
1181 // Override URL if using "External URL" as doktype with a valid e-mail address:
1182 if ($this->menuArr[$key]['doktype'] == 3 && $this->menuArr[$key]['urltype'] == 3 && t3lib_div::validEmail($this->menuArr[$key]['url'])) {
1183 // Create mailto-link using tslib_cObj::typolink (concerning spamProtectEmailAddresses):
1184 $LD['totalURL'] = $this->parent_cObj->typoLink_URL(array('parameter' => $this->menuArr[$key]['url']));
1185 $LD['target'] = '';
1186 }
1187
1188 // Manipulation in case of access restricted pages:
1189 $this->changeLinksForAccessRestrictedPages($LD,$this->menuArr[$key],$mainTarget,$typeOverride);
1190
1191 // Overriding URL / Target if set to do so:
1192 if ($this->menuArr[$key]['_OVERRIDE_HREF']) {
1193 $LD['totalURL'] = $this->menuArr[$key]['_OVERRIDE_HREF'];
1194 if ($this->menuArr[$key]['_OVERRIDE_TARGET']) $LD['target'] = $this->menuArr[$key]['_OVERRIDE_TARGET'];
1195 }
1196
1197 // OnClick open in windows.
1198 $onClick='';
1199 if ($this->mconf['JSWindow']) {
1200 $conf=$this->mconf['JSWindow.'];
1201 $url=$LD['totalURL'];
1202 $LD['totalURL'] = '#';
1203 $onClick= 'openPic(\''.$GLOBALS['TSFE']->baseUrlWrap($url).'\',\''.($conf['newWindow']?md5($url):'theNewPage').'\',\''.$conf['params'].'\'); return false;';
1204 $GLOBALS['TSFE']->setJS('openPic');
1205 }
1206
1207 // out:
1208 $list = array();
1209 $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.
1210 $list['TARGET'] = $LD['target'];
1211 $list['onClick'] = $onClick;
1212
1213 return $list;
1214 }
1215
1216 /**
1217 * Will change $LD (passed by reference) if the page is access restricted
1218 *
1219 * @param array $LD, the array from the linkData() function
1220 * @param array Page array
1221 * @param string Main target value
1222 * @param string Type number override if any
1223 * @return void ($LD passed by reference might be changed.)
1224 */
1225 function changeLinksForAccessRestrictedPages(&$LD, $page, $mainTarget, $typeOverride) {
1226
1227 // If access restricted pages should be shown in menus, change the link of such pages to link to a redirection page:
1228 if ($this->mconf['showAccessRestrictedPages'] && $this->mconf['showAccessRestrictedPages']!=='NONE' && !$GLOBALS['TSFE']->checkPageGroupAccess($page)) {
1229 $thePage = $this->sys_page->getPage($this->mconf['showAccessRestrictedPages']);
1230
1231 $addParams = $this->mconf['showAccessRestrictedPages.']['addParams'];
1232 $addParams = str_replace('###RETURN_URL###',rawurlencode($LD['totalURL']),$addParams);
1233 $addParams = str_replace('###PAGE_ID###',$page['uid'],$addParams);
1234 $LD = $this->tmpl->linkData($thePage,$mainTarget,'','','', $addParams, $typeOverride);
1235 }
1236 }
1237
1238 /**
1239 * Creates a submenu level to the current level - if configured for.
1240 *
1241 * @param integer Page id of the current page for which a submenu MAY be produced (if conditions are met)
1242 * @param string Object prefix, see ->start()
1243 * @return string HTML content of the submenu
1244 * @access private
1245 */
1246 function subMenu($uid, $objSuffix='') {
1247
1248 // Setting alternative menu item array if _SUB_MENU has been defined in the current ->menuArr
1249 $altArray = '';
1250 if (is_array($this->menuArr[$this->I['key']]['_SUB_MENU']) && count($this->menuArr[$this->I['key']]['_SUB_MENU'])) {
1251 $altArray = $this->menuArr[$this->I['key']]['_SUB_MENU'];
1252 }
1253
1254 // Make submenu if the page is the next active
1255 $cls = strtolower($this->conf[($this->menuNumber+1).$objSuffix]);
1256 $subLevelClass = ($cls && t3lib_div::inList($this->tmpl->menuclasses,$cls)) ? $cls : '';
1257
1258 if ($subLevelClass && ($this->mconf['expAll'] || $this->isNext($uid, $this->getMPvar($this->I['key'])) || is_array($altArray)) && !$this->mconf['sectionIndex']) {
1259 $submenu = t3lib_div::makeInstance('tslib_'.$subLevelClass);
1260 $submenu->entryLevel = $this->entryLevel+1;
1261 $submenu->rL_uidRegister = $this->rL_uidRegister;
1262 $submenu->MP_array = $this->MP_array;
1263 if ($this->menuArr[$this->I['key']]['_MP_PARAM']) {
1264 $submenu->MP_array[] = $this->menuArr[$this->I['key']]['_MP_PARAM'];
1265 }
1266
1267 // especially scripts that build the submenu needs the parent data
1268 $submenu->parent_cObj = &$this->parent_cObj;
1269 $submenu->parentMenuArr = $this->menuArr;
1270
1271 // Setting alternativeMenuTempArray (will be effective only if an array)
1272 if (is_array($altArray)) {
1273 $submenu->alternativeMenuTempArray = $altArray;
1274 }
1275
1276 if ($submenu->start($this->tmpl, $this->sys_page, $uid, $this->conf, $this->menuNumber+1, $objSuffix)) {
1277 $submenu->makeMenu();
1278 return $submenu->writeMenu();
1279 }
1280 }
1281 }
1282
1283 /**
1284 * Returns true if the page with UID $uid is the NEXT page in root line (which means a submenu should be drawn)
1285 *
1286 * @param integer Page uid to evaluate.
1287 * @param string MPvar for the current position of item.
1288 * @return boolean True if page with $uid is active
1289 * @access private
1290 * @see subMenu()
1291 */
1292 function isNext($uid, $MPvar='') {
1293
1294 // Check for always active PIDs:
1295 if (count($this->alwaysActivePIDlist) && in_array($uid,$this->alwaysActivePIDlist)) {
1296 return TRUE;
1297 }
1298
1299 $testUid = $uid.($MPvar?':'.$MPvar:'');
1300 if ($uid && $testUid==$this->nextActive) {
1301 return TRUE;
1302 }
1303 }
1304
1305 /**
1306 * Returns true if the page with UID $uid is active (in the current rootline)
1307 *
1308 * @param integer Page uid to evaluate.
1309 * @param string MPvar for the current position of item.
1310 * @return boolean True if page with $uid is active
1311 * @access private
1312 */
1313 function isActive($uid, $MPvar='') {
1314
1315 // Check for always active PIDs:
1316 if (count($this->alwaysActivePIDlist) && in_array($uid,$this->alwaysActivePIDlist)) {
1317 return TRUE;
1318 }
1319
1320 $testUid = $uid.($MPvar?':'.$MPvar:'');
1321 if ($uid && in_array('ITEM:'.$testUid, $this->rL_uidRegister)) {
1322 return TRUE;
1323 }
1324 }
1325
1326 /**
1327 * Returns true if the page with UID $uid is the CURRENT page (equals $GLOBALS['TSFE']->id)
1328 *
1329 * @param integer Page uid to evaluate.
1330 * @param string MPvar for the current position of item.
1331 * @return boolean True if page $uid = $GLOBALS['TSFE']->id
1332 * @access private
1333 */
1334 function isCurrent($uid, $MPvar='') {
1335 $testUid = $uid.($MPvar?':'.$MPvar:'');
1336 if ($uid && !strcmp(end($this->rL_uidRegister),'ITEM:'.$testUid)) {
1337 return TRUE;
1338 }
1339 }
1340
1341 /**
1342 * Returns true if there is a submenu with items for the page id, $uid
1343 * Used by the item states "IFSUB", "ACTIFSUB" and "CURIFSUB" to check if there is a submenu
1344 *
1345 * @param integer Page uid for which to search for a submenu
1346 * @return boolean Returns true if there was a submenu with items found
1347 * @access private
1348 */
1349 function isSubMenu($uid) {
1350
1351 // 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;
1352 $mount_info = $this->sys_page->getMountPointInfo($uid);
1353 if (is_array($mount_info)) {
1354 $uid = $mount_info['mount_pid'];
1355 }
1356
1357 $recs = $this->sys_page->getMenu($uid,'uid,pid,doktype,mount_pid,mount_pid_ol,nav_hide,shortcut,shortcut_mode');
1358 foreach($recs as $theRec) {
1359 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!)
1360 return TRUE;
1361 }
1362 }
1363 }
1364
1365 /**
1366 * Used by procesItemStates() to evaluate if a menu item (identified by $key) is in a certain state.
1367 *
1368 * @param string The item state to evaluate (SPC, IFSUB, ACT etc... but no xxxRO states of course)
1369 * @param integer Key pointing to menu item from ->menuArr
1370 * @return boolean True (integer!=0) if match, otherwise false (=0, zero)
1371 * @access private
1372 * @see procesItemStates()
1373 */
1374 function isItemState($kind,$key) {
1375 $natVal=0;
1376 if ($this->menuArr[$key]['ITEM_STATE']) { // If any value is set for ITEM_STATE the normal evaluation is discarded
1377 if (!strcmp($this->menuArr[$key]['ITEM_STATE'],$kind)) {$natVal=1;}
1378 } else {
1379 switch($kind) {
1380 case 'SPC':
1381 $natVal = $this->menuArr[$key]['isSpacer'];
1382 break;
1383 case 'IFSUB':
1384 $natVal = $this->isSubMenu($this->menuArr[$key]['uid']);
1385 break;
1386 case 'ACT':
1387 $natVal = $this->isActive($this->menuArr[$key]['uid'], $this->getMPvar($key));
1388 break;
1389 case 'ACTIFSUB':
1390 $natVal = $this->isActive($this->menuArr[$key]['uid'], $this->getMPvar($key)) && $this->isSubMenu($this->menuArr[$key]['uid']);
1391 break;
1392 case 'CUR':
1393 $natVal = $this->isCurrent($this->menuArr[$key]['uid'], $this->getMPvar($key));
1394 break;
1395 case 'CURIFSUB':
1396 $natVal = $this->isCurrent($this->menuArr[$key]['uid'], $this->getMPvar($key)) && $this->isSubMenu($this->menuArr[$key]['uid']);
1397 break;
1398 case 'USR':
1399 $natVal = $this->menuArr[$key]['fe_group'];
1400 break;
1401 }
1402 }
1403
1404 return $natVal;
1405 }
1406
1407 /**
1408 * Creates an access-key for a GMENU menu item based on the menu item titles first letter
1409 *
1410 * @param string Menu item title.
1411 * @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
1412 * @access private
1413 */
1414 function accessKey($title) {
1415 // The global array ACCESSKEY is used to globally control if letters are already used!!
1416 $result = Array();
1417
1418 $titleLen = strlen($title);
1419 for ($a=0;$a<$titleLen;$a++) {
1420 $key = strtoupper(trim(substr($title,$a,1)));
1421 if (preg_match('/[a-zA-Z]/', $key) && !isset($GLOBALS['TSFE']->accessKey[$key])) {
1422 $GLOBALS['TSFE']->accessKey[$key]=1;
1423 $result['code'] = ' accesskey="'.$key.'"';
1424 $result['alt'] = ' (ALT+'.$key.')';
1425 break;
1426 }
1427 }
1428 return $result;
1429 }
1430
1431 /**
1432 * Calls a user function for processing of internal data.
1433 * Used for the properties "IProcFunc" and "itemArrayProcFunc"
1434 *
1435 * @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".
1436 * @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
1437 * @return mixed The processed $passVar
1438 * @access private
1439 */
1440 function userProcess($mConfKey,$passVar) {
1441 if ($this->mconf[$mConfKey]) {
1442 $funcConf = $this->mconf[$mConfKey.'.'];
1443 $funcConf['parentObj']=&$this;
1444 $passVar = $GLOBALS['TSFE']->cObj->callUserFunction($this->mconf[$mConfKey], $funcConf, $passVar);
1445 }
1446 return $passVar;
1447 }
1448
1449 /**
1450 * 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'])
1451 *
1452 * @return void
1453 * @access private
1454 */
1455 function setATagParts() {
1456 $this->I['A1'] = '<a '.t3lib_div::implodeAttributes($this->I['linkHREF'],1).' '.$this->I['val']['ATagParams'].$this->I['accessKey']['code'].'>';
1457 $this->I['A2'] = '</a>';
1458 }
1459
1460 /**
1461 * Returns the title for the navigation
1462 *
1463 * @param string The current page title
1464 * @param string The current value of the navigation title
1465 * @return string Returns the navigation title if it is NOT blank, otherwise the page title.
1466 * @access private
1467 */
1468 function getPageTitle($title,$nav_title) {
1469 return strcmp(trim($nav_title),'') ? $nav_title : $title;
1470 }
1471
1472 /**
1473 * Return MPvar string for entry $key in ->menuArr
1474 *
1475 * @param integer Pointer to element in ->menuArr
1476 * @param string Implode token.
1477 * @return string MP vars for element.
1478 * @see link()
1479 */
1480 function getMPvar($key) {
1481 if ($GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids']) {
1482 $localMP_array = $this->MP_array;
1483 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!
1484 $MP_params = count($localMP_array) ? implode(',',$localMP_array) : '';
1485 return $MP_params;
1486 }
1487 }
1488
1489 /**
1490 * Returns where clause part to exclude 'not in menu' pages
1491 *
1492 * @return string where clause part.
1493 * @access private
1494 */
1495 function getDoktypeExcludeWhere() {
1496 return $this->doktypeExcludeList ? ' AND pages.doktype NOT IN ('.$this->doktypeExcludeList.')' : '';
1497 }
1498
1499 /**
1500 * Returns an array of banned UIDs (from excludeUidList)
1501 *
1502 * @return array Array of banned UIDs
1503 * @access private
1504 */
1505 function getBannedUids() {
1506 $banUidArray = array();
1507
1508 if (trim($this->conf['excludeUidList'])) {
1509 $banUidList = str_replace('current', $GLOBALS['TSFE']->page['uid'], $this->conf['excludeUidList']);
1510 $banUidArray = t3lib_div::intExplode(',', $banUidList);
1511 }
1512
1513 return $banUidArray;
1514 }
1515
1516 }
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536 /**
1537 * Extension class creating text based menus
1538 *
1539 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
1540 * @package TYPO3
1541 * @subpackage tslib
1542 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=387&cHash=73a3116ab8
1543 */
1544 class tslib_tmenu extends tslib_menu {
1545
1546 /**
1547 * Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
1548 * Sets the result for the new "normal state" in $this->result
1549 *
1550 * @return void
1551 * @see tslib_menu::procesItemStates()
1552 */
1553 function generate() {
1554 $splitCount = count($this->menuArr);
1555 if ($splitCount) {
1556 list($NOconf) = $this->procesItemStates($splitCount);
1557 }
1558 if ($this->mconf['debugItemConf']) {echo '<h3>$NOconf:</h3>'; debug($NOconf); }
1559 $this->result = $NOconf;
1560 }
1561
1562 /**
1563 * Traverses the ->result array of menu items configuration (made by ->generate()) and renders each item.
1564 * 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
1565 * 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.
1566 *
1567 * @return string The HTML for the menu (returns result through $this->extProc_finish(); )
1568 */
1569 function writeMenu() {
1570 if (is_array($this->result) && count($this->result)) {
1571 $this->WMcObj = t3lib_div::makeInstance('tslib_cObj'); // Create new tslib_cObj for our use
1572 $this->WMresult = '';
1573 $this->INPfixMD5 = substr(md5(microtime().'tmenu'),0,4);
1574 $this->WMmenuItems = count($this->result);
1575
1576 $this->WMsubmenuObjSuffixes = $this->tmpl->splitConfArray(array('sOSuffix'=>$this->mconf['submenuObjSuffixes']),$this->WMmenuItems);
1577
1578 $this->extProc_init();
1579 reset($this->result);
1580 while (list($key,$val)=each($this->result)) {
1581 $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']++;
1582 $GLOBALS['TSFE']->register['count_MENUOBJ']++;
1583
1584 $this->WMcObj->start($this->menuArr[$key],'pages'); // Initialize the cObj with the page record of the menu item
1585
1586 $this->I = array();
1587 $this->I['key'] = $key;
1588 $this->I['INPfix'] = ($this->imgNameNotRandom ? '' : '_'.$this->INPfixMD5).'_'.$key;
1589 $this->I['val'] = $val;
1590 $this->I['title'] = $this->WMcObj->stdWrap($this->getPageTitle($this->menuArr[$key]['title'],$this->menuArr[$key]['nav_title']),$this->I['val']['stdWrap.']);
1591 $this->I['uid'] = $this->menuArr[$key]['uid'];
1592 $this->I['mount_pid'] = $this->menuArr[$key]['mount_pid'];
1593 $this->I['pid'] = $this->menuArr[$key]['pid'];
1594 $this->I['spacer'] = $this->menuArr[$key]['isSpacer'];
1595
1596 // Set access key
1597 if ($this->mconf['accessKey']) {
1598 $this->I['accessKey'] = $this->accessKey($this->I['title']);
1599 } else {
1600 $this->I['accessKey'] = Array();
1601 }
1602
1603 // Make link tag
1604 $this->I['val']['ATagParams'] = $this->WMcObj->getATagParams($this->I['val']);
1605 $this->I['val']['additionalParams'] = $this->WMcObj->stdWrap($this->I['val']['additionalParams'],$this->I['val']['additionalParams.']);
1606 $this->I['linkHREF'] = $this->link($key,$this->I['val']['altTarget'],$this->mconf['forceTypeValue']);
1607
1608 // Title attribute of links:
1609 $titleAttrValue = $this->WMcObj->stdWrap($this->I['val']['ATagTitle'],$this->I['val']['ATagTitle.']).$this->I['accessKey']['alt'];
1610 if (strlen($titleAttrValue)) {
1611 $this->I['linkHREF']['title'] = $titleAttrValue;
1612 }
1613
1614 // Setting "blurlink()" function:
1615 if (!$this->mconf['noBlur']) {
1616 $this->I['linkHREF']['onFocus']='blurLink(this);';
1617 }
1618
1619 // Make link:
1620 if ($this->I['val']['RO']) {
1621 $this->I['theName'] = $this->imgNamePrefix.$this->I['uid'].$this->I['INPfix'];
1622 $over='';
1623 $out ='';
1624 if ($this->I['val']['beforeROImg']) {
1625 $over.= $this->WMfreezePrefix."over('".$this->I['theName']."before');";
1626 $out.= $this->WMfreezePrefix."out('".$this->I['theName']."before');";
1627 }
1628 if ($this->I['val']['afterROImg']) {
1629 $over.= $this->WMfreezePrefix."over('".$this->I['theName']."after');";
1630 $out.= $this->WMfreezePrefix."out('".$this->I['theName']."after');";
1631 }
1632 $this->I['linkHREF']['onMouseover']=$over;
1633 $this->I['linkHREF']['onMouseout']=$out;
1634 if ($over || $out) $GLOBALS['TSFE']->setJS('mouseOver');
1635
1636 // Change background color:
1637 if ($this->I['val']['RO_chBgColor']) {
1638 $this->addJScolorShiftFunction();
1639 $chBgP = t3lib_div::trimExplode('|',$this->I['val']['RO_chBgColor']);
1640 $this->I['linkHREF']['onMouseover'].="changeBGcolor('".$chBgP[2].$this->I['uid']."','".$chBgP[0]."');";
1641 $this->I['linkHREF']['onMouseout'].="changeBGcolor('".$chBgP[2].$this->I['uid']."','".$chBgP[1]."');";
1642 }
1643
1644 $this->extProc_RO($key);
1645 }
1646
1647
1648 // Calling extra processing function
1649 $this->extProc_beforeLinking($key);
1650
1651 // Compile link tag
1652 if (!$this->I['val']['doNotLinkIt']) {$this->I['val']['doNotLinkIt']=0;}
1653 if (!$this->I['spacer'] && $this->I['val']['doNotLinkIt']!=1) {
1654 $this->setATagParts();
1655 } else {
1656 $this->I['A1'] = '';
1657 $this->I['A2'] = '';
1658 }
1659
1660 // ATagBeforeWrap processing:
1661 if ($this->I['val']['ATagBeforeWrap']) {
1662 $wrapPartsBefore = explode('|',$this->I['val']['linkWrap']);
1663 $wrapPartsAfter = array('','');
1664 } else {
1665 $wrapPartsBefore = array('','');
1666 $wrapPartsAfter = explode('|',$this->I['val']['linkWrap']);
1667 }
1668 if ($this->I['val']['stdWrap2'] || isset($this->I['val']['stdWrap2.'])) {
1669 $wrapPartsStdWrap = explode($this->I['val']['stdWrap2']?$this->I['val']['stdWrap2']:'|',$this->WMcObj->stdWrap('|',$this->I['val']['stdWrap2.']));
1670 } else {$wrapPartsStdWrap = array('','');}
1671
1672 // Make before, middle and after parts
1673 $this->I['parts'] = array();
1674 $this->I['parts']['before']=$this->getBeforeAfter('before');
1675 $this->I['parts']['stdWrap2_begin']=$wrapPartsStdWrap[0];
1676 if (!$this->I['val']['doNotShowLink']) {
1677 $this->I['parts']['notATagBeforeWrap_begin'] = $wrapPartsAfter[0];
1678 $this->I['parts']['ATag_begin'] = $this->I['A1'];
1679 $this->I['parts']['ATagBeforeWrap_begin'] = $wrapPartsBefore[0];
1680 $this->I['parts']['title'] = $this->I['title'];
1681 $this->I['parts']['ATagBeforeWrap_end'] = $wrapPartsBefore[1];
1682 $this->I['parts']['ATag_end'] = $this->I['A2'];
1683 $this->I['parts']['notATagBeforeWrap_end'] = $wrapPartsAfter[1];
1684 }
1685 $this->I['parts']['stdWrap2_end']=$wrapPartsStdWrap[1];
1686 $this->I['parts']['after']=$this->getBeforeAfter('after');
1687
1688 // Passing I to a user function
1689 if ($this->mconf['IProcFunc']) {
1690 $this->I = $this->userProcess('IProcFunc',$this->I);
1691 }
1692
1693 // Merge parts + beforeAllWrap
1694 $this->I['theItem']= implode('',$this->I['parts']);
1695 $this->I['theItem']= $this->extProc_beforeAllWrap($this->I['theItem'],$key);
1696
1697 // allWrap:
1698 $allWrap = $this->WMcObj->stdWrap($this->I['val']['allWrap'],$this->I['val']['allWrap.']);
1699 $this->I['theItem'] = $this->tmpl->wrap($this->I['theItem'],$allWrap);
1700
1701 if ($this->I['val']['subst_elementUid']) $this->I['theItem'] = str_replace('{elementUid}',$this->I['uid'],$this->I['theItem']);
1702
1703 // allStdWrap:
1704 if (is_array($this->I['val']['allStdWrap.'])) {
1705 $this->I['theItem'] = $this->WMcObj->stdWrap($this->I['theItem'],$this->I['val']['allStdWrap.']);
1706 }
1707
1708 // Calling extra processing function
1709 $this->extProc_afterLinking($key);
1710 }
1711 return $this->extProc_finish();
1712 }
1713 }
1714
1715 /**
1716 * Generates the before* and after* images for TMENUs
1717 *
1718 * @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
1719 * @return string The resulting HTML of the image, if any.
1720 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=388&cHash=a7486044cd
1721 */
1722 function getBeforeAfter($pref) {
1723 $res = '';
1724 if ($imgInfo = $this->WMcObj->getImgResource($this->I['val'][$pref.'Img'],$this->I['val'][$pref.'Img.'])) {
1725 $imgInfo[3] = t3lib_div::png_to_gif_by_imagemagick($imgInfo[3]);
1726 if ($this->I['val']['RO'] && $this->I['val'][$pref.'ROImg'] && !$this->I['spacer']) {
1727 $imgROInfo = $this->WMcObj->getImgResource($this->I['val'][$pref.'ROImg'],$this->I['val'][$pref.'ROImg.']);
1728 $imgROInfo[3] = t3lib_div::png_to_gif_by_imagemagick($imgROInfo[3]);
1729 if ($imgROInfo) {
1730 $theName = $this->imgNamePrefix.$this->I['uid'].$this->I['INPfix'].$pref;
1731 $name = ' '.$this->nameAttribute.'="'.$theName.'"';
1732 $GLOBALS['TSFE']->JSImgCode.= chr(10).$theName.'_n=new Image(); '.$theName.'_n.src = "'.$GLOBALS['TSFE']->absRefPrefix.$imgInfo[3].'"; ';
1733 $GLOBALS['TSFE']->JSImgCode.= chr(10).$theName.'_h=new Image(); '.$theName.'_h.src = "'.$GLOBALS['TSFE']->absRefPrefix.$imgROInfo[3].'"; ';
1734 }
1735 }
1736 $GLOBALS['TSFE']->imagesOnPage[]=$imgInfo[3];
1737 $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"');
1738 if (!strstr($res,'alt="')) $res.=' alt=""'; // Adding alt attribute if not set.
1739 $res.=' />';
1740 if ($this->I['val'][$pref.'ImgLink']) {$res=$this->I['A1'].$res.$this->I['A2'];}
1741 }
1742 return $this->tmpl->wrap($res.$this->WMcObj->stdWrap($this->I['val'][$pref],$this->I['val'][$pref.'.']), $this->I['val'][$pref.'Wrap']);
1743 }
1744
1745 /**
1746 * Adds a JavaScript function to the $GLOBALS['TSFE']->additionalJavaScript array
1747 *
1748 * @return void
1749 * @access private
1750 * @see writeMenu()
1751 */
1752 function addJScolorShiftFunction() {
1753 $GLOBALS['TSFE']->additionalJavaScript['TMENU:changeBGcolor()']='
1754 function changeBGcolor(id,color) { //
1755 if (document.getElementById && document.getElementById(id)) {
1756 document.getElementById(id).style.background = color;
1757 return true;
1758 } else if (document.layers && document.layers[id]) {
1759 document.layers[id].bgColor = color;
1760 return true;
1761 }
1762 }
1763 ';
1764 }
1765
1766 /**
1767 * Called right before the traversing of $this->result begins.
1768 * Can be used for various initialization
1769 *
1770 * @return void
1771 * @access private
1772 * @see writeMenu(), tslib_tmenu_layers::extProc_init()
1773 */
1774 function extProc_init() {
1775 }
1776
1777 /**
1778 * Called after all processing for RollOver of an element has been done.
1779 *
1780 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
1781 * @return void
1782 * @access private
1783 * @see writeMenu(), tslib_tmenu_layers::extProc_RO()
1784 */
1785 function extProc_RO($key) {
1786 }
1787
1788 /**
1789 * Called right before the creation of the link for the menu item
1790 *
1791 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
1792 * @return void
1793 * @access private
1794 * @see writeMenu(), tslib_tmenu_layers::extProc_beforeLinking()
1795 */
1796 function extProc_beforeLinking($key) {
1797 }
1798
1799 /**
1800 * 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.
1801 * This function MUST set $this->WMresult.=[HTML for menu item] to add the generated menu item to the internal accumulation of items.
1802 *
1803 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
1804 * @return void
1805 * @access private
1806 * @see writeMenu(), tslib_tmenu_layers::extProc_afterLinking()
1807 */
1808 function extProc_afterLinking($key) {
1809 // Add part to the accumulated result + fetch submenus
1810 if (!$this->I['spacer']) {
1811 $this->I['theItem'].= $this->subMenu($this->I['uid'], $this->WMsubmenuObjSuffixes[$key]['sOSuffix']);
1812 }
1813 $this->WMresult.= $this->I['val']['wrapItemAndSub'] ? $this->tmpl->wrap($this->I['theItem'],$this->I['val']['wrapItemAndSub']) : $this->I['theItem'];
1814 }
1815
1816 /**
1817 * Called before the "allWrap" happens on the menu item.
1818 *
1819 * @param string The current content of the menu item, $this->I['theItem'], passed along.
1820 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
1821 * @return string The modified version of $item, going back into $this->I['theItem']
1822 * @access private
1823 * @see writeMenu(), tslib_tmenu_layers::extProc_beforeAllWrap()
1824 */
1825 function extProc_beforeAllWrap($item,$key) {
1826 return $item;
1827 }
1828
1829 /**
1830 * Called before the writeMenu() function returns (only if a menu was generated)
1831 *
1832 * @return string The total menu content should be returned by this function
1833 * @access private
1834 * @see writeMenu(), tslib_tmenu_layers::extProc_finish()
1835 */
1836 function extProc_finish() {
1837 // stdWrap:
1838 if (is_array($this->mconf['stdWrap.'])) {
1839 $this->WMresult = $this->WMcObj->stdWrap($this->WMresult,$this->mconf['stdWrap.']);
1840 }
1841 return $this->tmpl->wrap($this->WMresult,$this->mconf['wrap']).$this->WMextraScript;
1842 }
1843 }
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868 /**
1869 * Extension class creating graphic based menus (PNG or GIF files)
1870 *
1871 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
1872 * @package TYPO3
1873 * @subpackage tslib
1874 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=384&cHash=93a7644cba
1875 */
1876 class tslib_gmenu extends tslib_menu {
1877
1878 /**
1879 * Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
1880 * Calls makeGifs() for all "normal" items and if configured for, also the "rollover" items.
1881 *
1882 * @return void
1883 * @see tslib_menu::procesItemStates(), makeGifs()
1884 */
1885 function generate() {
1886 $splitCount = count($this->menuArr);
1887 if ($splitCount) {
1888 list($NOconf,$ROconf) = $this->procesItemStates($splitCount);
1889
1890 //store initial count value
1891 $temp_HMENU_MENUOBJ = $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ'];
1892 $temp_MENUOBJ = $GLOBALS['TSFE']->register['count_MENUOBJ'];
1893 // Now we generate the giffiles:
1894 $this->makeGifs($NOconf,'NO');
1895 // store count from NO obj
1896 $tempcnt_HMENU_MENUOBJ = $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ'];
1897 $tempcnt_MENUOBJ = $GLOBALS['TSFE']->register['count_MENUOBJ'];
1898
1899 if ($this->mconf['debugItemConf']) {echo '<h3>$NOconf:</h3>'; debug($NOconf); }
1900 if ($ROconf) { // RollOver
1901 //start recount for rollover with initial values
1902 $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']= $temp_HMENU_MENUOBJ;
1903 $GLOBALS['TSFE']->register['count_MENUOBJ']= $temp_MENUOBJ;
1904 $this->makeGifs($ROconf,'RO');
1905 if ($this->mconf['debugItemConf']) {echo '<h3>$ROconf:</h3>'; debug($ROconf); }
1906 }
1907 // use count from NO obj
1908 $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ'] = $tempcnt_HMENU_MENUOBJ;
1909 $GLOBALS['TSFE']->register['count_MENUOBJ'] = $tempcnt_MENUOBJ;
1910 }
1911 }
1912
1913 /**
1914 * Will traverse input array with configuratoin per-item and create corresponding GIF files for the menu.
1915 * The data of the files are stored in $this->result
1916 *
1917 * @param array Array with configuration for each item.
1918 * @param string Type of images: normal ("NO") or rollover ("RO"). Valid values are "NO" and "RO"
1919 * @return void
1920 * @access private
1921 * @see generate()
1922 */
1923 function makeGifs($conf, $resKey) {
1924 $isGD = $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'];
1925
1926 if (!is_array($conf)) {
1927 $conf = Array();
1928 }
1929
1930 $totalWH=array();
1931 $items = count($conf);
1932 if ($isGD) {
1933 // generate the gif-files. the $menuArr is filled with some values like output_w, output_h, output_file
1934 $Hcounter = 0;
1935 $Wcounter = 0;
1936 $Hobjs = $this->mconf['applyTotalH'];
1937 if ($Hobjs) {$Hobjs = t3lib_div::intExplode(',',$Hobjs);}
1938 $Wobjs = $this->mconf['applyTotalW'];
1939 if ($Wobjs) {$Wobjs = t3lib_div::intExplode(',',$Wobjs);}
1940 $minDim = $this->mconf['min'];
1941 if ($minDim) {$minDim = tslib_cObj::calcIntExplode(',',$minDim.',');}
1942 $maxDim = $this->mconf['max'];
1943 if ($maxDim) {$maxDim = tslib_cObj::calcIntExplode(',',$maxDim.',');}
1944
1945 if ($minDim) {
1946 $conf[$items]=$conf[$items-1];
1947 $this->menuArr[$items]=Array();
1948 $items = count($conf);
1949 }
1950
1951 // TOTAL width
1952 if ($this->mconf['useLargestItemX'] || $this->mconf['useLargestItemY'] || $this->mconf['distributeX'] || $this->mconf['distributeY']) {
1953 $totalWH = $this->findLargestDims($conf,$items,$Hobjs,$Wobjs,$minDim,$maxDim);
1954 }
1955 }
1956
1957 $c=0;
1958 $maxFlag=0;
1959 $distributeAccu=array('H'=>0,'W'=>0);
1960 reset($conf);
1961 while (list($key,$val)=each($conf)) {
1962 $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']++;
1963 $GLOBALS['TSFE']->register['count_MENUOBJ']++;
1964
1965 if ($items==($c+1) && $minDim) {
1966 $Lobjs = $this->mconf['removeObjectsOfDummy'];
1967 if ($Lobjs) {
1968 $Lobjs = t3lib_div::intExplode(',',$Lobjs);
1969 reset($Lobjs);
1970 while(list(,$remItem)=each($Lobjs)) {
1971 unset($val[$remItem]);
1972 unset($val[$remItem.'.']);
1973 }
1974 }
1975
1976 $flag =0;
1977 $tempXY = explode(',',$val['XY']);
1978 if ($Wcounter<$minDim[0]) {$tempXY[0]=$minDim[0]-$Wcounter; $flag=1;}
1979 if ($Hcounter<$minDim[1]) {$tempXY[1]=$minDim[1]-$Hcounter; $flag=1;}
1980 $val['XY'] = implode(',',$tempXY);
1981 if (!$flag){break;}
1982 }
1983 $c++;
1984
1985
1986 if ($isGD) {
1987 // Pre-working the item
1988 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
1989 $gifCreator->init();
1990 $gifCreator->start($val,$this->menuArr[$key]);
1991
1992 // If useLargestItemH/W is specified
1993 if (count($totalWH) && ($this->mconf['useLargestItemX'] || $this->mconf['useLargestItemY'])) {
1994 $tempXY = explode(',',$gifCreator->setup['XY']);
1995 if ($this->mconf['useLargestItemX']) {$tempXY[0] = max($totalWH['W']);}
1996 if ($this->mconf['useLargestItemY']) {$tempXY[1] = max($totalWH['H']);}
1997 // regenerate the new values...
1998 $val['XY'] = implode(',',$tempXY);
1999 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
2000 $gifCreator->init();
2001 $gifCreator->start($val,$this->menuArr[$key]);
2002 }
2003
2004 // If distributeH/W is specified
2005 if (count($totalWH) && ($this->mconf['distributeX'] || $this->mconf['distributeY'])) {
2006 $tempXY = explode(',',$gifCreator->setup['XY']);
2007
2008 if ($this->mconf['distributeX']) {
2009 $diff = $this->mconf['distributeX']-$totalWH['W_total']-$distributeAccu['W'];
2010 $compensate = round($diff /($items-$c+1));
2011 $distributeAccu['W']+=$compensate;
2012 $tempXY[0] = $totalWH['W'][$key]+$compensate;
2013 }
2014 if ($this->mconf['distributeY']) {
2015 $diff = $this->mconf['distributeY']-$totalWH['H_total']-$distributeAccu['H'];
2016 $compensate = round($diff /($items-$c+1));
2017 $distributeAccu['H']+=$compensate;
2018 $tempXY[1] = $totalWH['H'][$key]+$compensate;
2019 }
2020 // regenerate the new values...
2021 $val['XY'] = implode(',',$tempXY);
2022 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
2023 $gifCreator->init();
2024 $gifCreator->start($val,$this->menuArr[$key]);
2025 }
2026
2027 // If max dimensions are specified
2028 if ($maxDim) {
2029 $tempXY = explode(',',$val['XY']);
2030 if ($maxDim[0] && $Wcounter+$gifCreator->XY[0]>=$maxDim[0]) {$tempXY[0]==$maxDim[0]-$Wcounter; $maxFlag=1;}
2031 if ($maxDim[1] && $Hcounter+$gifCreator->XY[1]>=$maxDim[1]) {$tempXY[1]=$maxDim[1]-$Hcounter; $maxFlag=1;}
2032 if ($maxFlag) {
2033 $val['XY'] = implode(',',$tempXY);
2034 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
2035 $gifCreator->init();
2036 $gifCreator->start($val,$this->menuArr[$key]);
2037 }
2038 }
2039
2040
2041
2042
2043 // displace
2044 if ($Hobjs) {
2045 reset($Hobjs);
2046 while(list(,$index)=each($Hobjs)) {
2047 if ($gifCreator->setup[$index] && $gifCreator->setup[$index.'.']) {
2048 $oldOffset = explode(',',$gifCreator->setup[$index.'.']['offset']);
2049 $gifCreator->setup[$index.'.']['offset'] = implode(',',$gifCreator->applyOffset($oldOffset,Array(0,-$Hcounter)));
2050 }
2051 }
2052 }
2053
2054 if ($Wobjs) {
2055 reset($Wobjs);
2056 while(list(,$index)=each($Wobjs)) {
2057 if ($gifCreator->setup[$index] && $gifCreator->setup[$index.'.']) {
2058 $oldOffset = explode(',',$gifCreator->setup[$index.'.']['offset']);
2059 $gifCreator->setup[$index.'.']['offset'] = implode(',',$gifCreator->applyOffset($oldOffset,Array(-$Wcounter,0)));
2060 }
2061 }
2062 }
2063 }
2064
2065 // Finding alternative GIF names if any (by altImgResource)
2066 $gifFileName='';
2067 if ($conf[$key]['altImgResource'] || is_array($conf[$key]['altImgResource.'])) {
2068 if (!is_object($cObj)) {$cObj=t3lib_div::makeInstance('tslib_cObj');}
2069 $cObj->start($this->menuArr[$key],'pages');
2070 $altImgInfo = $cObj->getImgResource($conf[$key]['altImgResource'],$conf[$key]['altImgResource.']);
2071 $gifFileName=$altImgInfo[3];
2072 }
2073
2074 // If an alternative name was NOT given, find the GIFBUILDER name.
2075 if (!$gifFileName && $isGD) {
2076 $gifCreator->createTempSubDir('menu/');
2077 $gifFileName = $gifCreator->fileName('menu/');
2078 }
2079
2080 $this->result[$resKey][$key] = $conf[$key];
2081
2082 // Generation of image file:
2083 if (@file_exists($gifFileName)) { // File exists
2084 $info = @getimagesize($gifFileName);
2085 $this->result[$resKey][$key]['output_w']=intval($info[0]);
2086 $this->result[$resKey][$key]['output_h']=intval($info[1]);
2087 $this->result[$resKey][$key]['output_file'] = $gifFileName;
2088 } elseif ($isGD) { // file is generated
2089 $gifCreator->make();
2090 $this->result[$resKey][$key]['output_w']=$gifCreator->w;
2091 $this->result[$resKey][$key]['output_h']=$gifCreator->h;
2092 $this->result[$resKey][$key]['output_file'] = $gifFileName;
2093 $gifCreator->output($this->result[$resKey][$key]['output_file']);
2094 $gifCreator->destroy();
2095 }
2096
2097 $this->result[$resKey][$key]['output_file'] = t3lib_div::png_to_gif_by_imagemagick($this->result[$resKey][$key]['output_file']);
2098
2099 $Hcounter+=$this->result[$resKey][$key]['output_h']; // counter is increased
2100 $Wcounter+=$this->result[$resKey][$key]['output_w']; // counter is increased
2101
2102 if ($maxFlag) break;
2103 }
2104 }
2105
2106 /**
2107 * Function searching for the largest width and height of the menu items to be generated.
2108 * 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.
2109 * Remember to upgrade the code in here if the makeGifs function is updated.
2110 *
2111 * @param array Same configuration array as passed to makeGifs()
2112 * @param integer The number of menu items
2113 * @param array Array with "applyTotalH" numbers
2114 * @param array Array with "applyTotalW" numbers
2115 * @param array Array with "min" x/y
2116 * @param array Array with "max" x/y
2117 * @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.
2118 * @access private
2119 * @see makeGifs()
2120 */
2121 function findLargestDims($conf,$items,$Hobjs,$Wobjs,$minDim,$maxDim) {
2122 $totalWH = array(
2123 'W' => array(),
2124 'H' => array(),
2125 'W_total' => 0,
2126 'H_total' => 0
2127 );
2128
2129 $Hcounter = 0;
2130 $Wcounter = 0;
2131 $c=0;
2132 $maxFlag=0;
2133 reset($conf);
2134 while (list($key,$val)=each($conf)) {
2135 // SAME CODE AS makeGifs()! BEGIN
2136 if ($items==($c+1) && $minDim) {
2137 $Lobjs = $this->mconf['removeObjectsOfDummy'];
2138 if ($Lobjs) {
2139 $Lobjs = t3lib_div::intExplode(',',$Lobjs);
2140 reset($Lobjs);
2141 while(list(,$remItem)=each($Lobjs)) {
2142 unset($val[$remItem]);
2143 unset($val[$remItem.'.']);
2144 }
2145 }
2146
2147 $flag =0;
2148 $tempXY = explode(',',$val['XY']);
2149 if ($Wcounter<$minDim[0]) {$tempXY[0]=$minDim[0]-$Wcounter; $flag=1;}
2150 if ($Hcounter<$minDim[1]) {$tempXY[1]=$minDim[1]-$Hcounter; $flag=1;}
2151 $val['XY'] = implode(',',$tempXY);
2152 if (!$flag){break;}
2153 }
2154 $c++;
2155
2156 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
2157 $gifCreator->init();
2158 $gifCreator->start($val,$this->menuArr[$key]);
2159 if ($maxDim) {
2160 $tempXY = explode(',',$val['XY']);
2161 if ($maxDim[0] && $Wcounter+$gifCreator->XY[0]>=$maxDim[0]) {$tempXY[0]==$maxDim[0]-$Wcounter; $maxFlag=1;}
2162 if ($maxDim[1] && $Hcounter+$gifCreator->XY[1]>=$maxDim[1]) {$tempXY[1]=$maxDim[1]-$Hcounter; $maxFlag=1;}
2163 if ($maxFlag) {
2164 $val['XY'] = implode(',',$tempXY);
2165 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
2166 $gifCreator->init();
2167 $gifCreator->start($val,$this->menuArr[$key]);
2168 }
2169 }
2170 // SAME CODE AS makeGifs()! END
2171
2172 // Setting the width/height
2173 $totalWH['W'][$key]=$gifCreator->XY[0];
2174 $totalWH['H'][$key]=$gifCreator->XY[1];
2175 $totalWH['W_total']+=$gifCreator->XY[0];
2176 $totalWH['H_total']+=$gifCreator->XY[1];
2177 // ---- //
2178
2179 $Hcounter+=$gifCreator->XY[1]; // counter is increased
2180 $Wcounter+=$gifCreator->XY[0]; // counter is increased
2181
2182 if ($maxFlag){break;}
2183 }
2184 return $totalWH;
2185 }
2186
2187 /**
2188 * 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())
2189 * 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
2190 *
2191 * @return string The HTML for the menu (returns result through $this->extProc_finish(); )
2192 */
2193 function writeMenu() {
2194 if (is_array($this->menuArr) && is_array($this->result) && count($this->result) && is_array($this->result['NO'])) {
2195 $this->WMcObj = t3lib_div::makeInstance('tslib_cObj'); // Create new tslib_cObj for our use
2196 $this->WMresult = '';
2197 $this->INPfixMD5 = substr(md5(microtime().$this->GMENU_fixKey),0,4);
2198 $this->WMmenuItems = count($this->result['NO']);
2199
2200 $this->WMsubmenuObjSuffixes = $this->tmpl->splitConfArray(array('sOSuffix'=>$this->mconf['submenuObjSuffixes']),$this->WMmenuItems);
2201
2202 $this->extProc_init();
2203 for ($key=0;$key<$this->WMmenuItems;$key++) {
2204 if ($this->result['NO'][$key]['output_file']) {
2205 $this->WMcObj->start($this->menuArr[$key],'pages'); // Initialize the cObj with the page record of the menu item
2206
2207 $this->I = array();
2208 $this->I['key'] = $key;
2209 $this->I['INPfix']= ($this->imgNameNotRandom ? '' : '_'.$this->INPfixMD5).'_'.$key;
2210 $this->I['val'] = $this->result['NO'][$key];
2211 $this->I['title'] = $this->getPageTitle($this->menuArr[$key]['title'],$this->menuArr[$key]['nav_title']);
2212 $this->I['uid'] = $this->menuArr[$key]['uid'];
2213 $this->I['mount_pid'] = $this->menuArr[$key]['mount_pid'];
2214 $this->I['pid'] = $this->menuArr[$key]['pid'];
2215 $this->I['spacer'] = $this->menuArr[$key]['isSpacer'];
2216 if (!$this->I['uid'] && !$this->menuArr[$key]['_OVERRIDE_HREF']) {$this->I['spacer']=1;}
2217 $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
2218 $this->I['name'] = '';
2219
2220 // Set access key
2221 if ($this->mconf['accessKey']) {
2222 $this->I['accessKey'] = $this->accessKey($this->I['title']);
2223 } else {
2224 $this->I['accessKey'] = array();
2225 }
2226
2227 // Make link tag
2228 $this->I['val']['ATagParams'] = $this->WMcObj->getATagParams($this->I['val']);
2229 $this->I['val']['additionalParams'] = $this->WMcObj->stdWrap($this->I['val']['additionalParams'],$this->I['val']['additionalParams.']);
2230 $this->I['linkHREF'] = $this->link($key,$this->I['val']['altTarget'],$this->mconf['forceTypeValue']);
2231
2232 // Title attribute of links:
2233 $titleAttrValue = $this->WMcObj->stdWrap($this->I['val']['ATagTitle'],$this->I['val']['ATagTitle.']).$this->I['accessKey']['alt'];
2234 if (strlen($titleAttrValue)) {
2235 $this->I['linkHREF']['title'] = $titleAttrValue;
2236 }
2237 // Setting "blurlink()" function:
2238 if (!$this->mconf['noBlur']) {
2239 $this->I['linkHREF']['onFocus']='blurLink(this);';
2240 }
2241
2242 // Set rollover
2243 if ($this->result['RO'][$key] && !$this->I['noLink']) {
2244 $this->I['theName'] = $this->imgNamePrefix.$this->I['uid'].$this->I['INPfix'];
2245 $this->I['name'] = ' '.$this->nameAttribute.'="'.$this->I["theName"].'"';
2246 $this->I['linkHREF']['onMouseover']=$this->WMfreezePrefix.'over(\''.$this->I['theName'].'\');';
2247 $this->I['linkHREF']['onMouseout']=$this->WMfreezePrefix.'out(\''.$this->I['theName'].'\');';
2248 $GLOBALS['TSFE']->JSImgCode.= chr(10).$this->I['theName'].'_n=new Image(); '.$this->I['theName'].'_n.src = "'.$GLOBALS['TSFE']->absRefPrefix.$this->I['val']['output_file'].'"; ';
2249 $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'].'"; ';
2250 $GLOBALS['TSFE']->imagesOnPage[]=$this->result['RO'][$key]['output_file'];
2251 $GLOBALS['TSFE']->setJS('mouseOver');
2252 $this->extProc_RO($key);
2253 }
2254
2255 // Set altText
2256 $this->I['altText'] = $this->mconf['disableAltText'] ? '' : $this->I['title'].$this->I['accessKey']['alt'];
2257
2258 // Calling extra processing function
2259 $this->extProc_beforeLinking($key);
2260
2261 // Set linking
2262 if (!$this->I['noLink']) {
2263 $this->setATagParts();
2264 } else {
2265 $this->I['A1'] = '';
2266 $this->I['A2'] = '';
2267 }
2268 $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']:'').' />';
2269
2270 // Make before, middle and after parts
2271 $this->I['parts'] = array();
2272 $this->I['parts']['ATag_begin'] = $this->I['A1'];
2273 $this->I['parts']['image'] = $this->I['IMG'];
2274 $this->I['parts']['ATag_end'] = $this->I['A2'];
2275
2276 // Passing I to a user function
2277 if ($this->mconf['IProcFunc']) {
2278 $this->I = $this->userProcess('IProcFunc',$this->I);
2279 }
2280
2281 // Putting the item together.
2282 // Merge parts + beforeAllWrap
2283 $this->I['theItem']= implode('',$this->I['parts']);
2284 $this->I['theItem']= $this->extProc_beforeAllWrap($this->I['theItem'],$key);
2285
2286 // wrap:
2287 $this->I['theItem']= $this->tmpl->wrap($this->I['theItem'],$this->I['val']['wrap']);
2288
2289 // allWrap:
2290 $allWrap = $this->WMcObj->stdWrap($this->I['val']['allWrap'],$this->I['val']['allWrap.']);
2291 $this->I['theItem'] = $this->tmpl->wrap($this->I['theItem'],$allWrap);
2292
2293 if ($this->I['val']['subst_elementUid']) $this->I['theItem'] = str_replace('{elementUid}',$this->I['uid'],$this->I['theItem']);
2294
2295 // allStdWrap:
2296 if (is_array($this->I['val']['allStdWrap.'])) {
2297 $this->I['theItem'] = $this->WMcObj->stdWrap($this->I['theItem'],$this->I['val']['allStdWrap.']);
2298 }
2299
2300 $GLOBALS['TSFE']->imagesOnPage[]=$this->I['val']['output_file'];
2301
2302 $this->extProc_afterLinking($key);
2303 }
2304 }
2305 return $this->extProc_finish();
2306 }
2307 }
2308
2309 /**
2310 * Called right before the traversing of $this->result begins.
2311 * Can be used for various initialization
2312 *
2313 * @return void
2314 * @access private
2315 * @see writeMenu(), tslib_gmenu_layers::extProc_init()
2316 */
2317 function extProc_init() {
2318 }
2319
2320 /**
2321 * Called after all processing for RollOver of an element has been done.
2322 *
2323 * @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!
2324 * @return void
2325 * @access private
2326 * @see writeMenu(), tslib_gmenu_layers::extProc_RO()
2327 */
2328 function extProc_RO($key) {
2329 }
2330
2331 /**
2332 * Called right before the creation of the link for the menu item
2333 *
2334 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
2335 * @return void
2336 * @access private
2337 * @see writeMenu(), tslib_gmenu_layers::extProc_beforeLinking()
2338 */
2339 function extProc_beforeLinking($key) {
2340 }
2341
2342 /**
2343 * 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.
2344 * This function MUST set $this->WMresult.=[HTML for menu item] to add the generated menu item to the internal accumulation of items.
2345 * Further this calls the subMenu function in the parent class to create any submenu there might be.
2346 *
2347 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
2348 * @return void
2349 * @access private
2350 * @see writeMenu(), tslib_gmenu_layers::extProc_afterLinking(), tslib_menu::subMenu()
2351 */
2352 function extProc_afterLinking($key) {
2353 $this->WMresult.=$this->I['theItem'];
2354 if (!$this->I['spacer']) {
2355 $this->WMresult.= $this->subMenu($this->I['uid'], $this->WMsubmenuObjSuffixes[$key]['sOSuffix']);
2356 }
2357 }
2358
2359
2360 /**
2361 * Called before the "wrap" happens on the menu item.
2362 *
2363 * @param string The current content of the menu item, $this->I['theItem'], passed along.
2364 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
2365 * @return string The modified version of $item, going back into $this->I['theItem']
2366 * @access private
2367 * @see writeMenu(), tslib_gmenu_layers::extProc_beforeAllWrap()
2368 */
2369 function extProc_beforeAllWrap($item,$key) {
2370 return $item;
2371 }
2372
2373 /**
2374 * Called before the writeMenu() function returns (only if a menu was generated)
2375 *
2376 * @return string The total menu content should be returned by this function
2377 * @access private
2378 * @see writeMenu(), tslib_gmenu_layers::extProc_finish()
2379 */
2380 function extProc_finish() {
2381 // stdWrap:
2382 if (is_array($this->mconf['stdWrap.'])) {
2383 $this->WMresult = $this->WMcObj->stdWrap($this->WMresult,$this->mconf['stdWrap.']);
2384 }
2385 return $this->tmpl->wrap($this->WMresult,$this->mconf['wrap']).$this->WMextraScript;
2386 }
2387 }
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410 /**
2411 * ImageMap based menus
2412 *
2413 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
2414 * @package TYPO3
2415 * @subpackage tslib
2416 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=389&cHash=fcf18c5d9f
2417 */
2418 class tslib_imgmenu extends tslib_menu {
2419
2420 /**
2421 * Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
2422 * Calls makeImageMap() to generate the image map image-file
2423 *
2424 * @return void
2425 * @see tslib_menu::procesItemStates(), makeImageMap()
2426 */
2427 function generate() {
2428 $splitCount = count($this->menuArr);
2429 if ($splitCount) {
2430 list($NOconf) = $this->procesItemStates($splitCount);
2431 }
2432 if ($this->mconf['debugItemConf']) {echo '<h3>$NOconf:</h3>'; debug($NOconf); }
2433 $this->makeImageMap($NOconf);
2434 }
2435
2436 /**
2437 * Will traverse input array with configuratoin per-item and create corresponding GIF files for the menu.
2438 * The data of the files are stored in $this->result
2439 *
2440 * @param array Array with configuration for each item.
2441 * @return void
2442 * @access private
2443 * @see generate()
2444 */
2445 function makeImageMap($conf) {
2446 if (!is_array($conf)) {
2447 $conf = Array();
2448 }
2449 if (is_array($this->mconf['main.'])) {
2450 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
2451 $gifCreator->init();
2452
2453 $itemsConf = $conf;
2454 $conf = $this->mconf['main.'];
2455 if (is_array($conf)) {
2456 $gifObjCount = 0;
2457
2458 $sKeyArray=t3lib_TStemplate::sortedKeyList($conf);
2459 $gifObjCount=intval(end($sKeyArray));
2460
2461 $lastOriginal = $gifObjCount;
2462
2463 // Now we add graphical objects to the gifbuilder-setup
2464 reset($itemsConf);
2465 $waArr = Array();
2466 while (list($key,$val)=each($itemsConf)) {
2467 if (is_array($val)) {
2468 $gifObjCount++;
2469 $waArr[$key]['free']=$gifObjCount;
2470
2471 $sKeyArray=t3lib_TStemplate::sortedKeyList($val);
2472
2473 foreach($sKeyArray as $theKey) {
2474 $theValue=$val[$theKey];
2475
2476
2477 if (intval($theKey) && $theValArr=$val[$theKey.'.']) {
2478 $cObjData = $this->menuArr[$key] ? $this->menuArr[$key] : Array();
2479
2480 $gifObjCount++;
2481 if ($theValue=='TEXT') {
2482 $waArr[$key]['textNum']=$gifObjCount;
2483
2484 $gifCreator->data = $cObjData;
2485 $theValArr = $gifCreator->checkTextObj($theValArr);
2486 unset($theValArr['text.']); // if this is not done it seems that imageMaps will be rendered wrong!!
2487 // check links
2488
2489 $LD = $this->tmpl->linkData($this->menuArr[$key],$this->mconf['target'],'','',array(),'',$this->mconf['forceTypeValue']);
2490
2491 // If access restricted pages should be shown in menus, change the link of such pages to link to a redirection page:
2492 $this->changeLinksForAccessRestrictedPages($LD, $this->menuArr[$key], $this->mconf['target'], $this->mconf['forceTypeValue']);
2493
2494 // Overriding URL / Target if set to do so:
2495 if ($this->menuArr[$key]['_OVERRIDE_HREF']) {
2496 $LD['totalURL'] = $this->menuArr[$key]['_OVERRIDE_HREF'];
2497 if ($this->menuArr[$key]['_OVERRIDE_TARGET']) $LD['target'] = $this->menuArr[$key]['_OVERRIDE_TARGET'];
2498 }
2499
2500 // Setting target/url for Image Map:
2501 if ($theValArr['imgMap.']['url']=='') {
2502 $theValArr['imgMap.']['url'] = $LD['totalURL'];
2503 }
2504 if ($theValArr['imgMap.']['target']=='') {
2505 $theValArr['imgMap.']['target'] = $LD['target'];
2506 }
2507 if ($theValArr['imgMap.']['noBlur']=='') {
2508 $theValArr['imgMap.']['noBlur'] = $this->mconf['noBlur'];
2509 }
2510 if (is_array($theValArr['imgMap.']['altText.'])) {
2511 $cObj =t3lib_div::makeInstance('tslib_cObj');
2512 $cObj->start($cObjData,'pages');
2513 $theValArr['imgMap.']['altText'] = $cObj->stdWrap($theValArr['imgMap.']['altText'], $theValArr['imgMap.']['altText.']);
2514 unset($theValArr['imgMap.']['altText.']);
2515 }
2516 if (is_array($theValArr['imgMap.']['titleText.'])) {
2517 $cObj =t3lib_div::makeInstance('tslib_cObj');
2518 $cObj->start($cObjData,'pages');
2519 $theValArr['imgMap.']['titleText'] = $cObj->stdWrap($theValArr['imgMap.']['titleText'], $theValArr['imgMap.']['titleText.']);
2520 unset($theValArr['imgMap.']['titleText.']);
2521 }
2522 }
2523 // 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!!
2524 if ($theValue=='IMAGE') {
2525 if ($theValArr['file']=='GIFBUILDER') {
2526 $temp_sKeyArray=t3lib_TStemplate::sortedKeyList($theValArr['file.']);
2527 reset($temp_sKeyArray);
2528 while(list(,$temp_theKey)=each($temp_sKeyArray)) {
2529 if ($theValArr['mask.'][$temp_theKey]=='TEXT') {
2530 $gifCreator->data = $this->menuArr[$key] ? $this->menuArr[$key] : Array();
2531 $theValArr['mask.'][$temp_theKey.'.'] = $gifCreator->checkTextObj($theValArr['mask.'][$temp_theKey.'.']);
2532 unset($theValArr['mask.'][$temp_theKey.'.']['text.']); // if this is not done it seems that imageMaps will be rendered wrong!!
2533 }
2534 }
2535 }
2536 if ($theValArr['mask']=='GIFBUILDER') {
2537 $temp_sKeyArray=t3lib_TStemplate::sortedKeyList($theValArr['mask.']);
2538 reset($temp_sKeyArray);
2539 while(list(,$temp_theKey)=each($temp_sKeyArray)) {
2540 if ($theValArr['mask.'][$temp_theKey]=='TEXT') {
2541 $gifCreator->data = $this->menuArr[$key] ? $this->menuArr[$key] : Array();
2542 $theValArr['mask.'][$temp_theKey.'.'] = $gifCreator->checkTextObj($theValArr['mask.'][$temp_theKey.'.']);
2543 unset($theValArr['mask.'][$temp_theKey.'.']['text.']); // if this is not done it seems that imageMaps will be rendered wrong!!
2544 }
2545 }
2546 }
2547 }
2548
2549 // Checks if disabled is set...
2550 $setObjFlag=1;
2551 if ($theValArr['if.']) {
2552 $cObj =t3lib_div::makeInstance('tslib_cObj');
2553 $cObj->start($cObjData,'pages');
2554 if (!$cObj->checkIf($theValArr['if.'])) {
2555 $setObjFlag=0;
2556 }
2557 unset($theValArr['if.']);
2558 }
2559 // Set the object!
2560 if ($setObjFlag) {
2561 $conf[$gifObjCount] = $theValue;
2562 $conf[$gifObjCount.'.'] = $theValArr;
2563 }
2564 }
2565 }
2566 }
2567 }
2568
2569 $gifCreator->start($conf,$GLOBALS['TSFE']->page);
2570 // calculations
2571
2572 $sum=Array(0,0,0,0);
2573 reset($waArr);
2574 while (list($key,$val)=each($waArr)) {
2575 if ($dConf[$key] =$itemsConf[$key]['distrib']) {
2576 $textBB = $gifCreator->objBB[$val['textNum']];
2577 $dConf[$key] = str_replace('textX',$textBB[0],$dConf[$key]);
2578 $dConf[$key] = str_replace('textY',$textBB[1],$dConf[$key]);
2579 $dConf[$key] = t3lib_div::intExplode(',',$gifCreator->calcOffset($dConf[$key]));
2580 }
2581 }
2582 $workArea = t3lib_div::intExplode(',',$gifCreator->calcOffset($this->mconf['dWorkArea']));
2583 reset($waArr);
2584 while (list($key,$val)=each($waArr)) {
2585 $index = $val['free'];
2586 $gifCreator->setup[$index] = 'WORKAREA';
2587 $workArea[2] = $dConf[$key][2] ? $dConf[$key][2] : $dConf[$key][0];
2588 $workArea[3] = $dConf[$key][3] ? $dConf[$key][3] : $dConf[$key][1];
2589
2590 $gifCreator->setup[$index.'.']['set'] = implode(',',$workArea);
2591 $workArea[0]+=$dConf[$key][0];
2592 $workArea[1]+=$dConf[$key][1];
2593 }
2594
2595 if ($this->mconf['debugRenumberedObject']) {echo '<h3>Renumbered GIFBUILDER object:</h3>'; debug($gifCreator->setup);}
2596
2597 $gifCreator->createTempSubDir('menu/');
2598 $gifFileName = $gifCreator->fileName('menu/');
2599
2600 // Gets the ImageMap from the cache...
2601 $imgHash = md5($gifFileName);
2602 $imgMap = $this->sys_page->getHash($imgHash, 0);
2603
2604 if ($imgMap && @file_exists($gifFileName)) { // File exists
2605 $info = @getimagesize($gifFileName);
2606 $w=$info[0];
2607 $h=$info[1];
2608 } else { // file is generated
2609 $gifCreator->make();
2610 $w=$gifCreator->w;
2611 $h=$gifCreator->h;
2612 $gifCreator->output($gifFileName);
2613 $gifCreator->destroy();
2614 $imgMap=$gifCreator->map;
2615 $this->sys_page->storeHash($imgHash, $imgMap, 'MENU IMAGEMAP');
2616 }
2617 $imgMap.=$this->mconf['imgMapExtras'];
2618
2619 $gifFileName = t3lib_div::png_to_gif_by_imagemagick($gifFileName);
2620 $this->result = Array('output_file'=>$gifFileName, 'output_w'=>$w, 'output_h'=>$h, 'imgMap'=>$imgMap);
2621 }
2622 }
2623 }