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