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