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