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