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