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