*** empty log message ***
[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 * 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 // Prepare normal settings
681 $NOconf = $this->tmpl->splitConfArray($this->mconf['NO.'],$splitCount);
682 // Prepare rollOver settings, overriding normal settings
683 $ROconf=array();
684 if ($this->mconf['RO']) {
685 $ROconf = $this->tmpl->splitConfArray($this->mconf['RO.'],$splitCount);
686 }
687
688 // Prepare IFSUB settings, overriding normal settings
689 // IFSUB is true if there exist submenu items to the current item
690 if ($this->mconf['IFSUB']) {
691 $IFSUBinit = 0; // Flag: If $IFSUB is generated
692 reset($NOconf);
693 while (list($key,$val)=each($NOconf)) {
694 if ($this->isItemState('IFSUB',$key)) {
695 if (!$IFSUBinit) { // if this is the first IFSUB element, we must generate IFSUB.
696 $IFSUBconf = $this->tmpl->splitConfArray($this->mconf['IFSUB.'],$splitCount);
697 if ($this->mconf['IFSUBRO']) {
698 $IFSUBROconf = $this->tmpl->splitConfArray($this->mconf['IFSUBRO.'],$splitCount);
699 }
700 $IFSUBinit = 1;
701 }
702 $NOconf[$key] = $IFSUBconf[$key]; // Substitute normal with ifsub
703 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
704 $ROconf[$key] = $IFSUBROconf[$key] ? $IFSUBROconf[$key] : $IFSUBconf[$key]; // If RollOver on active then apply this
705 }
706 }
707 }
708 }
709 // Prepare active settings, overriding normal settings
710 if ($this->mconf['ACT']) {
711 $ACTinit = 0; // Flag: If $ACT is generated
712 reset($NOconf);
713 while (list($key,$val)=each($NOconf)) { // Find active
714 if ($this->isItemState('ACT',$key)) {
715 if (!$ACTinit) { // if this is the first active, we must generate ACT.
716 $ACTconf = $this->tmpl->splitConfArray($this->mconf['ACT.'],$splitCount);
717 // Prepare active rollOver settings, overriding normal active settings
718 if ($this->mconf['ACTRO']) {
719 $ACTROconf = $this->tmpl->splitConfArray($this->mconf['ACTRO.'],$splitCount);
720 }
721 $ACTinit = 1;
722 }
723 $NOconf[$key] = $ACTconf[$key]; // Substitute normal with active
724 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
725 $ROconf[$key] = $ACTROconf[$key] ? $ACTROconf[$key] : $ACTconf[$key]; // If RollOver on active then apply this
726 }
727 }
728 }
729 }
730 // Prepare active/IFSUB settings, overriding normal settings
731 // ACTIFSUB is true if there exist submenu items to the current item and the current item is active
732 if ($this->mconf['ACTIFSUB']) {
733 $ACTIFSUBinit = 0; // Flag: If $ACTIFSUB is generated
734 reset($NOconf);
735 while (list($key,$val)=each($NOconf)) { // Find active
736 if ($this->isItemState('ACTIFSUB',$key)) {
737 if (!$ACTIFSUBinit) { // if this is the first active, we must generate ACTIFSUB.
738 $ACTIFSUBconf = $this->tmpl->splitConfArray($this->mconf['ACTIFSUB.'],$splitCount);
739 // Prepare active rollOver settings, overriding normal active settings
740 if ($this->mconf['ACTIFSUBRO']) {
741 $ACTIFSUBROconf = $this->tmpl->splitConfArray($this->mconf['ACTIFSUBRO.'],$splitCount);
742 }
743 $ACTIFSUBinit = 1;
744 }
745 $NOconf[$key] = $ACTIFSUBconf[$key]; // Substitute normal with active
746 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
747 $ROconf[$key] = $ACTIFSUBROconf[$key] ? $ACTIFSUBROconf[$key] : $ACTIFSUBconf[$key]; // If RollOver on active then apply this
748 }
749 }
750 }
751 }
752 // Prepare CUR (current) settings, overriding normal settings
753 // CUR is true if the current page equals the item here!
754 if ($this->mconf['CUR']) {
755 $CURinit = 0; // Flag: If $CUR is generated
756 reset($NOconf);
757 while (list($key,$val)=each($NOconf)) {
758 if ($this->isItemState('CUR',$key)) {
759 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)
760 $CURconf = $this->tmpl->splitConfArray($this->mconf['CUR.'],$splitCount);
761 if ($this->mconf['CURRO']) {
762 $CURROconf = $this->tmpl->splitConfArray($this->mconf['CURRO.'],$splitCount);
763 }
764 $CURinit = 1;
765 }
766 $NOconf[$key] = $CURconf[$key]; // Substitute normal with current
767 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
768 $ROconf[$key] = $CURROconf[$key] ? $CURROconf[$key] : $CURconf[$key]; // If RollOver on active then apply this
769 }
770 }
771 }
772 }
773 // Prepare active settings, overriding normal settings
774 if ($this->mconf['USR']) {
775 $USRinit = 0; // Flag: If $USR is generated
776 reset($NOconf);
777 while (list($key,$val)=each($NOconf)) { // Find active
778 if ($this->isItemState('USR',$key)) {
779 if (!$USRinit) { // if this is the first active, we must generate USR.
780 $USRconf = $this->tmpl->splitConfArray($this->mconf['USR.'],$splitCount);
781 // Prepare active rollOver settings, overriding normal active settings
782 if ($this->mconf['USRRO']) {
783 $USRROconf = $this->tmpl->splitConfArray($this->mconf['USRRO.'],$splitCount);
784 }
785 $USRinit = 1;
786 }
787 $NOconf[$key] = $USRconf[$key]; // Substitute normal with active
788 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
789 $ROconf[$key] = $USRROconf[$key] ? $USRROconf[$key] : $USRconf[$key]; // If RollOver on active then apply this
790 }
791 }
792 }
793 }
794 // Prepare spacer settings, overriding normal settings
795 if ($this->mconf['SPC']) {
796 $SPCinit = 0; // Flag: If $SPC is generated
797 reset($NOconf);
798 while (list($key,$val)=each($NOconf)) { // Find spacers
799 if ($this->isItemState('SPC',$key)) {
800 if (!$SPCinit) { // if this is the first spacer, we must generate SPC.
801 $SPCconf = $this->tmpl->splitConfArray($this->mconf['SPC.'],$splitCount);
802 $SPCinit = 1;
803 }
804 $NOconf[$key] = $SPCconf[$key]; // Substitute normal with spacer
805 }
806 }
807 }
808 // Prepare Userdefined settings
809 if ($this->mconf['USERDEF1']) {
810 $USERDEF1init = 0; // Flag: If $USERDEF1 is generated
811 reset($NOconf);
812 while (list($key,$val)=each($NOconf)) { // Find active
813 if ($this->isItemState('USERDEF1',$key)) {
814 if (!$USERDEF1init) { // if this is the first active, we must generate USERDEF1.
815 $USERDEF1conf = $this->tmpl->splitConfArray($this->mconf['USERDEF1.'],$splitCount);
816 // Prepare active rollOver settings, overriding normal active settings
817 if ($this->mconf['USERDEF1RO']) {
818 $USERDEF1ROconf = $this->tmpl->splitConfArray($this->mconf['USERDEF1RO.'],$splitCount);
819 }
820 $USERDEF1init = 1;
821 }
822 $NOconf[$key] = $USERDEF1conf[$key]; // Substitute normal with active
823 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
824 $ROconf[$key] = $USERDEF1ROconf[$key] ? $USERDEF1ROconf[$key] : $USERDEF1conf[$key]; // If RollOver on active then apply this
825 }
826 }
827 }
828 }
829 // Prepare Userdefined settings
830 if ($this->mconf['USERDEF2']) {
831 $USERDEF2init = 0; // Flag: If $USERDEF2 is generated
832 reset($NOconf);
833 while (list($key,$val)=each($NOconf)) { // Find active
834 if ($this->isItemState('USERDEF2',$key)) {
835 if (!$USERDEF2init) { // if this is the first active, we must generate USERDEF2.
836 $USERDEF2conf = $this->tmpl->splitConfArray($this->mconf['USERDEF2.'],$splitCount);
837 // Prepare active rollOver settings, overriding normal active settings
838 if ($this->mconf['USERDEF2RO']) {
839 $USERDEF2ROconf = $this->tmpl->splitConfArray($this->mconf['USERDEF2RO.'],$splitCount);
840 }
841 $USERDEF2init = 1;
842 }
843 $NOconf[$key] = $USERDEF2conf[$key]; // Substitute normal with active
844 if ($ROconf) { // If rollOver on normal, we must apply a state for rollOver on the active
845 $ROconf[$key] = $USERDEF2ROconf[$key] ? $USERDEF2ROconf[$key] : $USERDEF2conf[$key]; // If RollOver on active then apply this
846 }
847 }
848 }
849 }
850
851 return array($NOconf,$ROconf);
852 }
853
854 /**
855 * Creates a submenu level to the current level - if configured for.
856 *
857 * @param integer Page id of the current page for which a submenu MAY be produced (if conditions are met)
858 * @param integer Mount-point UID (basically the mount_pid field of the page record is passed along)
859 * @return string HTML content of the submenu
860 * @access private
861 */
862 function subMenu($uid,$mount_point=0) {
863 // starts a submenu...
864 if ($GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids'] && $mount_point>0) {
865 $MP=$mount_point.'-'.$uid;
866 $uid=$mount_point;
867 } else $MP=0;
868
869 // Setting alternative menu item array if _SUB_MENU has been defined in the current ->menuArr
870 $altArray='';
871 if (is_array($this->menuArr[$this->I['key']]['_SUB_MENU']) && count($this->menuArr[$this->I['key']]['_SUB_MENU'])) {
872 $altArray = $this->menuArr[$this->I['key']]['_SUB_MENU'];
873 }
874
875 if ($this->subLevelClass && ($this->mconf['expAll'] || ($uid && $uid==$this->nextActive) || is_array($altArray)) && !$this->mconf['sectionIndex']) {
876 $submenu = t3lib_div::makeInstance('tslib_'.$this->subLevelClass);
877 $submenu->entryLevel = $this->entryLevel+1;
878 $submenu->MP_array = $this->MP_array;
879 if ($MP) $submenu->MP_array[]=$MP;
880
881 // especially scripts that build the submenu needs the parent data
882 $submenu->parentMenuArr = $this->menuArr;
883
884 // Setting alternativeMenuTempArray (will be effective only if an array)
885 if (is_array($altArray)) {
886 $submenu->alternativeMenuTempArray = $altArray;
887 }
888
889 $submenu->start($this->tmpl,$this->sys_page,$uid,$this->conf,$this->menuNumber+1);
890 $submenu->makeMenu();
891 return $submenu->writeMenu();
892 }
893 }
894
895 /**
896 * 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
897 *
898 * @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)
899 * @param string Alternative target
900 * @param integer Alternative type
901 * @return array Returns an array with A-tag attributes as key/value pairs (HREF, TARGET and onClick)
902 * @access private
903 */
904 function link($key,$altTarget='',$typeOverride='') {
905 // this function doesn't care about the url, because if we let the url be redirected, it will be logged in the stat!!!
906 if ($this->mconf['overrideId'] || $this->menuArr[$key]['overrideId']) { // RF 22/10
907 $overrideArray = array();
908 // if a user script returned the value overrideId in the menu array we use that as page id
909 $overrideArray['uid'] = $this->mconf['overrideId']?$this->mconf['overrideId']:$this->menuArr[$key]['overrideId']; // RF 22/10
910 $overrideArray['alias'] = '';
911 } else {
912 $overrideArray='';
913 }
914 $mainTarget = $altTarget ? $altTarget : $this->mconf['target'];
915
916 if ($GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids']) {
917 $localMP_array = $this->MP_array;
918 if ($this->menuArr[$key]['_MP_PARAM']) $localMP_array[]=$this->menuArr[$key]['_MP_PARAM'];
919 $MP_params = count($localMP_array)?'&MP='.rawurlencode(implode(',',$localMP_array)):'';
920 } else $MP_params ='';
921
922 if ($this->mconf['collapse'] && $this->isActive($this->menuArr[$key]['uid'])) {
923 $thePage = $this->sys_page->getPage($this->menuArr[$key]['pid']);
924 $LD = $this->tmpl->linkData($thePage,$mainTarget,'','',$overrideArray, $this->mconf['addParams'].$MP_params, $typeOverride);
925 } else {
926 $LD = $this->tmpl->linkData($this->menuArr[$key],$mainTarget,'','',$overrideArray, $this->mconf['addParams'].$MP_params, $typeOverride);
927 }
928
929 // Overriding URL / Target if set to do so:
930 if ($this->menuArr[$key]['_OVERRIDE_HREF']) {
931 $LD['totalURL'] = $this->menuArr[$key]['_OVERRIDE_HREF'];
932 if ($this->menuArr[$key]['_OVERRIDE_TARGET']) $LD['target'] = $this->menuArr[$key]['_OVERRIDE_TARGET'];
933 }
934
935 // OnClick open in windows.
936 $onClick='';
937 if ($this->mconf['JSWindow']) {
938 $conf=$this->mconf['JSWindow.'];
939 $url=$LD['totalURL'];
940 $LD['totalURL'] = '#';
941 $onClick= 'openPic(\''.$url.'\',\''.($conf['newWindow']?md5($url):'theNewPage').'\',\''.$conf['params'].'\'); return false;';
942 $GLOBALS['TSFE']->setJS('openPic');
943 }
944 // out:
945 $list = array();
946 $list['HREF']=$LD['totalURL'];
947 $list['TARGET']=$LD['target'];
948 $list['onClick']=$onClick;
949
950 return $list;
951 }
952
953 /**
954 * Returns true if the page with UID $uid is active (in the current rootline)
955 *
956 * @param integer Page uid to evaluate.
957 * @return boolean True if page with $uid is active
958 * @access private
959 */
960 function isActive($uid) {
961 if ($uid && t3lib_div::inList($this->rL_uidList,$uid)) {return 1;}
962 }
963
964 /**
965 * Returns true if the page with UID $uid is the CURRENT page (equals $GLOBALS['TSFE']->id)
966 *
967 * @param integer Page uid to evaluate.
968 * @return boolean True if page $uid = $GLOBALS['TSFE']->id
969 * @access private
970 */
971 function isCurrent($uid) {
972 if ($uid && $GLOBALS['TSFE']->id==$uid) {return 1;}
973 }
974
975 /**
976 * Returns true if there is a submenu with items for the page id, $uid
977 * Used by the item states "IFSUB" and "ACTIFSUB" to check if there is a submenu
978 *
979 * @param integer Page uid for which to search for a submenu
980 * @param integer "mount_pid" field for the page record which is evaluated (this may affect whether a submenu is found!)
981 * @return boolean Returns true if there was a submenu with items found
982 * @access private
983 */
984 function isSubMenu($uid,$mount_point=0) {
985 if ($GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids'] && $mount_point>0) {$uid=$mount_point;}
986
987 $recs = $this->sys_page->getMenu($uid,'doktype,uid');
988 reset($recs);
989 $flag=0; // No menu by default;
990 while(list(,$theRec)=each($recs)) {
991 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!)
992 $flag=1;
993 break;
994 }
995 }
996 return $flag;
997 }
998
999 /**
1000 * Used by procesItemStates() to evaluate if a menu item (identified by $key) is in a certain state.
1001 *
1002 * @param string The item state to evaluate (SPC, IFSUB, ACT etc... but no xxxRO states of course)
1003 * @param integer Key pointing to menu item from ->menuArr
1004 * @return boolean True (integer!=0) if match, otherwise false (=0, zero)
1005 * @access private
1006 * @see procesItemStates()
1007 */
1008 function isItemState($kind,$key) {
1009 $natVal=0;
1010 if ($this->menuArr[$key]['ITEM_STATE']) { // If any value is set for ITEM_STATE the normal evaluation is discarded
1011 if (!strcmp($this->menuArr[$key]['ITEM_STATE'],$kind)) {$natVal=1;}
1012 } else {
1013 switch($kind) {
1014 case 'SPC':
1015 $natVal = $this->menuArr[$key]['isSpacer'];
1016 break;
1017 case 'IFSUB':
1018 $natVal = $this->isSubMenu($this->menuArr[$key]['uid'],$this->menuArr[$key]['mount_pid']);
1019 break;
1020 case 'ACT':
1021 $natVal = $this->isActive($this->menuArr[$key]['uid']);
1022 break;
1023 case 'ACTIFSUB':
1024 $natVal = $this->isActive($this->menuArr[$key]['uid']) && $this->isSubMenu($this->menuArr[$key]['uid'],$this->menuArr[$key]['mount_pid']);
1025 break;
1026 case 'CUR':
1027 $natVal = $this->isCurrent($this->menuArr[$key]['uid']);
1028 break;
1029 case 'USR':
1030 $natVal = $this->menuArr[$key]['fe_group'];
1031 break;
1032 }
1033 }
1034
1035 return $natVal;
1036 }
1037
1038 /**
1039 * Creates an access-key for a GMENU menu item based on the menu item titles first letter
1040 *
1041 * @param string Menu item title.
1042 * @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
1043 * @access private
1044 */
1045 function accessKey($title) {
1046 // The global array ACCESSKEY is used to globally control if letters are already used!!
1047 $result = Array();
1048
1049 $titleLen = strlen($title);
1050 for ($a=0;$a<$titleLen;$a++) {
1051 $key = strtoupper(trim(substr($title,$a,1)));
1052 if ($key && !isset($GLOBALS['TSFE']->accessKey[$key])) {
1053 $GLOBALS['TSFE']->accessKey[$key]=1;
1054 $result['code'] = ' accesskey="'.$key.'"';
1055 $result['alt'] = ' (ALT+'.$key.')';
1056 break;
1057 }
1058 }
1059 return $result;
1060 }
1061
1062 /**
1063 * Calls a user function for processing of internal data.
1064 * Used for the properties "IProcFunc" and "itemArrayProcFunc"
1065 *
1066 * @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".
1067 * @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
1068 * @return mixed The processed $passVar
1069 * @access private
1070 */
1071 function userProcess($mConfKey,$passVar) {
1072 if ($this->mconf[$mConfKey]) {
1073 $funcConf = $this->mconf[$mConfKey.'.'];
1074 $funcConf['parentObj']=&$this;
1075 $passVar = $GLOBALS['TSFE']->cObj->callUserFunction($this->mconf[$mConfKey], $funcConf, $passVar);
1076 }
1077 return $passVar;
1078 }
1079
1080 /**
1081 * 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'])
1082 *
1083 * @return void
1084 * @access private
1085 */
1086 function setATagParts() {
1087 $this->I['A1'] = '<a '.t3lib_div::implodeParams($this->I['linkHREF'],1).$this->I['val']['ATagParams'].$this->I['addATagParams'].$this->I['accessKey']['code'].'>';
1088 $this->I['A2'] = '</a>';
1089 }
1090
1091 /**
1092 * Returns the title for the navigation
1093 *
1094 * @param string The current page title
1095 * @param string The current value of the naviation title
1096 * @return string Returns the navigation title if it is NOT blank, otherwise the page title.
1097 * @access private
1098 */
1099 function getPageTitle($title,$nav_title) {
1100 return strcmp(trim($nav_title),'') ? $nav_title : $title;
1101 }
1102 }
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122 /**
1123 * Extension class creating text based menus
1124 *
1125 * @author Kasper Skaarhoj <kasper@typo3.com>
1126 * @package TYPO3
1127 * @subpackage tslib
1128 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=387&cHash=73a3116ab8
1129 */
1130 class tslib_tmenu extends tslib_menu {
1131
1132 /**
1133 * Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
1134 * Sets the result for the new "normal state" in $this->result
1135 *
1136 * @return void
1137 * @see tslib_menu::procesItemStates()
1138 */
1139 function generate() {
1140 $splitCount = count($this->menuArr);
1141 if ($splitCount) {
1142 list($NOconf) = $this->procesItemStates($splitCount);
1143 }
1144 if ($this->mconf['debugItemConf']) {echo '<h3>$NOconf:</h3>'; debug($NOconf); }
1145 $this->result = $NOconf;
1146 }
1147
1148 /**
1149 * Traverses the ->result array of menu items configuration (made by ->generate()) and renders each item.
1150 * 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
1151 * 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.
1152 *
1153 * @return string The HTML for the menu (returns result through $this->extProc_finish(); )
1154 */
1155 function writeMenu() {
1156 if (is_array($this->result) && count($this->result)) {
1157 $this->WMcObj =t3lib_div::makeInstance('tslib_cObj'); // Create new tslib_cObj for our use
1158 $this->WMresult='';
1159 $this->INPfixMD5 = substr(md5(microtime().'tmenu'),0,4);
1160 $this->WMmenuItems = count($this->result);
1161 $this->extProc_init();
1162 reset($this->result);
1163 while (list($key,$val)=each($this->result)) {
1164 $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']++;
1165 $GLOBALS['TSFE']->register['count_MENUOBJ']++;
1166
1167 $this->I=array();
1168 $this->WMcObj->start($this->menuArr[$key],'pages'); // Initialize the cObj with the page record of the menu item
1169 $this->I['key'] = $key;
1170 $this->I['INPfix']= $this->imgNameNotRandom?'':'_'.$this->INPfixMD5.'_'.$key;
1171 $this->I['val'] = $val;
1172 $this->I['title'] = $this->WMcObj->stdWrap($this->getPageTitle($this->menuArr[$key]['title'],$this->menuArr[$key]['nav_title']),$this->I['val']['stdWrap.']);
1173 $this->I['uid'] = $this->menuArr[$key]['uid'];
1174 $this->I['mount_pid'] = $this->menuArr[$key]['mount_pid'];
1175 $this->I['pid'] = $this->menuArr[$key]['pid'];
1176 $this->I['spacer'] = $this->menuArr[$key]['isSpacer'];
1177
1178 // Make link tag
1179 $this->I['val']['ATagParams'] = $this->I['val']['ATagParams'] ? ' '.$this->I['val']['ATagParams'] : '';
1180 $this->I['linkHREF'] = $this->link($key,$this->I['val']['altTarget'],$this->mconf['forceTypeValue']);
1181
1182 if (!$this->mconf['noBlur']) {
1183 $this->I['linkHREF']['onFocus']='blurLink(this);';
1184 }
1185
1186 // Make link:
1187 if ($this->I['val']['RO']) {
1188 $this->I['theName'] = $this->imgNamePrefix.$this->I['uid'].$this->I['INPfix'];
1189 $over='';
1190 $out ='';
1191 if ($this->I['val']['beforeROImg']) {
1192 $over.= $this->WMfreezePrefix."over('".$this->I['theName']."before');";
1193 $out.= $this->WMfreezePrefix."out('".$this->I['theName']."before');";
1194 }
1195 if ($this->I['val']['afterROImg']) {
1196 $over.= $this->WMfreezePrefix."over('".$this->I['theName']."after');";
1197 $out.= $this->WMfreezePrefix."out('".$this->I['theName']."after');";
1198 }
1199 $this->I['linkHREF']['onMouseover']=$over;
1200 $this->I['linkHREF']['onMouseout']=$out;
1201 if ($over || $out) $GLOBALS['TSFE']->setJS('mouseOver');
1202
1203 // Change background color:
1204 if ($this->I['val']['RO_chBgColor']) {
1205 $this->addJScolorShiftFunction();
1206 $chBgP = t3lib_div::trimExplode('|',$this->I['val']['RO_chBgColor']);
1207 $this->I['linkHREF']['onMouseover'].="changeBGcolor('".$chBgP[2].$this->I['uid']."','".$chBgP[0]."');";
1208 $this->I['linkHREF']['onMouseout'].="changeBGcolor('".$chBgP[2].$this->I['uid']."','".$chBgP[1]."');";
1209 }
1210
1211 $this->extProc_RO($key);
1212 }
1213
1214
1215
1216 // Calling extra processing function
1217 $this->extProc_beforeLinking($key);
1218
1219 // Compile link tag
1220 if (!$this->I['val']['doNotLinkIt']) {$this->I['val']['doNotLinkIt']=0;}
1221 if (!$this->I['val']['isSpacer'] && $this->I['val']['doNotLinkIt']!=1) {
1222 $this->setATagParts();
1223 } else {
1224 $this->I['A1'] = '';
1225 $this->I['A2'] = '';
1226 }
1227
1228 // ATAGBeforeWrap processing:
1229 if ($this->I['val']['ATagBeforeWrap']) {
1230 $wrapPartsBefore = explode('|',$this->I['val']['linkWrap']);
1231 $wrapPartsAfter = array('','');
1232 } else {
1233 $wrapPartsBefore = array('','');
1234 $wrapPartsAfter = explode('|',$this->I['val']['linkWrap']);
1235 }
1236 if ($this->I['val']['stdWrap2'] || isset($this->I['val']['stdWrap2.'])) {
1237 $wrapPartsStdWrap = explode($this->I['val']['stdWrap2']?$this->I['val']['stdWrap2']:'|',$this->WMcObj->stdWrap('|',$this->I['val']['stdWrap2.']));
1238 } else {$wrapPartsStdWrap = array('','');}
1239
1240 // Make before, middle and after parts
1241 $this->I['parts'] = array();
1242 $this->I['parts']['before']=$this->getBeforeAfter('before');
1243 $this->I['parts']['stdWrap2_begin']=$wrapPartsStdWrap[0];
1244 if (!$this->I['val']['doNotShowLink']) {
1245 $this->I['parts']['notATagBeforeWrap_begin'] = $wrapPartsAfter[0];
1246 $this->I['parts']['ATag_begin'] = $this->I['A1'];
1247 $this->I['parts']['ATagBeforeWrap_begin'] = $wrapPartsBefore[0];
1248 $this->I['parts']['title'] = $this->I['title'];
1249 $this->I['parts']['ATagBeforeWrap_end'] = $wrapPartsBefore[1];
1250 $this->I['parts']['ATag_end'] = $this->I['A2'];
1251 $this->I['parts']['notATagBeforeWrap_end'] = $wrapPartsAfter[1];
1252 }
1253 $this->I['parts']['stdWrap2_end']=$wrapPartsStdWrap[1];
1254 $this->I['parts']['after']=$this->getBeforeAfter('after');
1255
1256 // Passing I to a user function
1257 if ($this->mconf['IProcFunc']) {
1258 $this->I = $this->userProcess('IProcFunc',$this->I);
1259 }
1260
1261 // Merge parts + beforeAllWrap
1262 $this->I['theItem']= implode('',$this->I['parts']);
1263 $this->I['theItem']= $this->extProc_beforeAllWrap($this->I['theItem'],$key);
1264
1265 // allWrap:
1266 $allWrap = $this->WMcObj->stdWrap($this->I['val']['allWrap'],$this->I['val']['allWrap.']);
1267 $this->I['theItem'] = $this->tmpl->wrap($this->I['theItem'],$allWrap);
1268
1269 if ($this->I['val']['subst_elementUid']) $this->I['theItem'] = str_replace('{elementUid}',$this->I['uid'],$this->I['theItem']);
1270
1271 // Calling extra processing function
1272 $this->extProc_afterLinking($key);
1273 }
1274 return $this->extProc_finish();
1275 }
1276 }
1277
1278 /**
1279 * Generates the before* and after* images for TMENUs
1280 *
1281 * @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
1282 * @return string The resulting HTML of the image, if any.
1283 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=388&cHash=a7486044cd
1284 */
1285 function getBeforeAfter($pref) {
1286 $res = '';
1287 if ($imgInfo = $this->WMcObj->getImgResource($this->I['val'][$pref.'Img'],$this->I['val'][$pref.'Img.'])) {
1288 $imgInfo[3] = t3lib_div::png_to_gif_by_imagemagick($imgInfo[3]);
1289 if ($this->I['val']['RO'] && $this->I['val'][$pref.'ROImg'] && !$this->I['val']['isSpacer']) {
1290 $imgROInfo = $this->WMcObj->getImgResource($this->I['val'][$pref.'ROImg'],$this->I['val'][$pref.'ROImg.']);
1291 $imgROInfo[3] = t3lib_div::png_to_gif_by_imagemagick($imgROInfo[3]);
1292 if ($imgROInfo) {
1293 $theName = $this->imgNamePrefix.$this->I['uid'].$this->I['INPfix'].$pref;
1294 $name = ' name="'.$theName.'"';
1295 $GLOBALS['TSFE']->JSImgCode.= chr(10).$theName.'_n=new Image(); '.$theName.'_n.src = "'.$GLOBALS['TSFE']->absRefPrefix.$imgInfo[3].'"; ';
1296 $GLOBALS['TSFE']->JSImgCode.= chr(10).$theName.'_h=new Image(); '.$theName.'_h.src = "'.$GLOBALS['TSFE']->absRefPrefix.$imgROInfo[3].'"; ';
1297 }
1298 }
1299 $GLOBALS['TSFE']->imagesOnPage[]=$imgInfo[3];
1300 $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"';
1301 if (!strstr($res,'alt="')) $res.=' alt=""'; // Adding alt attribute if not set.
1302 $res.=' />';
1303 if ($this->I['val'][$pref.'ImgLink']) {$res=$this->I['A1'].$res.$this->I['A2'];}
1304 }
1305 return $this->tmpl->wrap($res.$this->WMcObj->stdWrap($this->I['val'][$pref],$this->I['val'][$pref.'.']), $this->I['val'][$pref.'Wrap']);
1306 }
1307
1308 /**
1309 * Adds a JavaScript function to the $GLOBALS['TSFE']->additionalJavaScript array
1310 *
1311 * @return void
1312 * @access private
1313 * @see writeMenu()
1314 */
1315 function addJScolorShiftFunction() {
1316 $GLOBALS['TSFE']->additionalJavaScript['TMENU:changeBGcolor()']='
1317 function changeBGcolor(id,color) { //
1318 if (document.getElementById && document.getElementById(id)) {
1319 document.getElementById(id).style.background = color;
1320 return true;
1321 } else if (document.layers && document.layers[id]) {
1322 document.layers[id].bgColor = color;
1323 return true;
1324 }
1325 }
1326 ';
1327 }
1328
1329 /**
1330 * Called right before the traversing of $this->result begins.
1331 * Can be used for various initialization
1332 *
1333 * @return void
1334 * @access private
1335 * @see writeMenu(), tslib_tmenu_layers::extProc_init()
1336 */
1337 function extProc_init() {
1338 }
1339
1340 /**
1341 * Called after all processing for RollOver of an element has been done.
1342 *
1343 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
1344 * @return void
1345 * @access private
1346 * @see writeMenu(), tslib_tmenu_layers::extProc_RO()
1347 */
1348 function extProc_RO($key) {
1349 }
1350
1351 /**
1352 * Called right before the creation of the link for the menu item
1353 *
1354 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
1355 * @return void
1356 * @access private
1357 * @see writeMenu(), tslib_tmenu_layers::extProc_beforeLinking()
1358 */
1359 function extProc_beforeLinking($key) {
1360 }
1361
1362 /**
1363 * 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.
1364 * This function MUST set $this->WMresult.=[HTML for menu item] to add the generated menu item to the internal accumulation of items.
1365 *
1366 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
1367 * @return void
1368 * @access private
1369 * @see writeMenu(), tslib_tmenu_layers::extProc_afterLinking()
1370 */
1371 function extProc_afterLinking($key) {
1372 // Add part to the accumulated result + fetch submenus
1373 if (!$this->I['spacer']) {
1374 $this->I['theItem'].= $this->subMenu($this->I['uid'],$this->I['mount_pid']);
1375 }
1376 $this->WMresult.= $this->I['val']['wrapItemAndSub'] ? $this->tmpl->wrap($this->I['theItem'],$this->I['val']['wrapItemAndSub']) : $this->I['theItem'];
1377 }
1378
1379 /**
1380 * Called before the "allWrap" happens on the menu item.
1381 *
1382 * @param string The current content of the menu item, $this->I['theItem'], passed along.
1383 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
1384 * @return string The modified version of $item, going back into $this->I['theItem']
1385 * @access private
1386 * @see writeMenu(), tslib_tmenu_layers::extProc_beforeAllWrap()
1387 */
1388 function extProc_beforeAllWrap($item,$key) {
1389 return $item;
1390 }
1391
1392 /**
1393 * Called before the writeMenu() function returns (only if a menu was generated)
1394 *
1395 * @return string The total menu content should be returned by this function
1396 * @access private
1397 * @see writeMenu(), tslib_tmenu_layers::extProc_finish()
1398 */
1399 function extProc_finish() {
1400 return $this->tmpl->wrap($this->WMresult,$this->mconf['wrap']).$this->WMextraScript;
1401 }
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 * Extension class creating graphic based menus (PNG or GIF files)
1429 *
1430 * @author Kasper Skaarhoj <kasper@typo3.com>
1431 * @package TYPO3
1432 * @subpackage tslib
1433 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=384&cHash=93a7644cba
1434 */
1435 class tslib_gmenu extends tslib_menu {
1436
1437 /**
1438 * Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
1439 * Calls makeGifs() for all "normal" items and if configured for, also the "rollover" items.
1440 *
1441 * @return void
1442 * @see tslib_menu::procesItemStates(), makeGifs()
1443 */
1444 function generate() {
1445 $splitCount = count($this->menuArr);
1446 if ($splitCount) {
1447 list($NOconf,$ROconf) = $this->procesItemStates($splitCount);
1448
1449 //store initial count value
1450 $temp_HMENU_MENUOBJ = $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ'];
1451 $temp_MENUOBJ = $GLOBALS['TSFE']->register['count_MENUOBJ'];
1452 // Now we generate the giffiles:
1453 $this->makeGifs($NOconf,'NO');
1454 // store count from NO obj
1455 $tempcnt_HMENU_MENUOBJ = $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ'];
1456 $tempcnt_MENUOBJ = $GLOBALS['TSFE']->register['count_MENUOBJ'];
1457
1458 if ($this->mconf['debugItemConf']) {echo '<h3>$NOconf:</h3>'; debug($NOconf); }
1459 if ($ROconf) { // RollOver
1460 //start recount for rollover with initial values
1461 $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']= $temp_HMENU_MENUOBJ;
1462 $GLOBALS['TSFE']->register['count_MENUOBJ']= $temp_MENUOBJ;
1463 $this->makeGifs($ROconf,'RO');
1464 if ($this->mconf['debugItemConf']) {echo '<h3>$ROconf:</h3>'; debug($ROconf); }
1465 }
1466 // use count from NO obj
1467 $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ'] = $tempcnt_HMENU_MENUOBJ;
1468 $GLOBALS['TSFE']->register['count_MENUOBJ'] = $tempcnt_MENUOBJ;
1469 }
1470 }
1471
1472 /**
1473 * Will traverse input array with configuratoin per-item and create corresponding GIF files for the menu.
1474 * The data of the files are stored in $this->result
1475 *
1476 * @param array Array with configuration for each item.
1477 * @param string Type of images: normal ("NO") or rollover ("RO"). Valid values are "NO" and "RO"
1478 * @return void
1479 * @access private
1480 * @see generate()
1481 */
1482 function makeGifs($conf, $resKey) {
1483 $isGD = $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'];
1484
1485 if (!is_array($conf)) {
1486 $conf = Array();
1487 }
1488
1489 $totalWH=array();
1490 $items = count($conf);
1491 if ($isGD) {
1492 // generate the gif-files. the $menuArr is filled with some values like output_w, output_h, output_file
1493 $Hcounter = 0;
1494 $Wcounter = 0;
1495 $Hobjs = $this->mconf['applyTotalH'];
1496 if ($Hobjs) {$Hobjs = t3lib_div::intExplode(',',$Hobjs);}
1497 $Wobjs = $this->mconf['applyTotalW'];
1498 if ($Wobjs) {$Wobjs = t3lib_div::intExplode(',',$Wobjs);}
1499 $minDim = $this->mconf['min'];
1500 if ($minDim) {$minDim = tslib_cObj::calcIntExplode(',',$minDim.',');}
1501 $maxDim = $this->mconf['max'];
1502 if ($maxDim) {$maxDim = tslib_cObj::calcIntExplode(',',$maxDim.',');}
1503
1504 if ($minDim) {
1505 $conf[$items]=$conf[$items-1];
1506 $this->menuArr[$items]=Array();
1507 $items = count($conf);
1508 }
1509
1510 // TOTAL width
1511 if ($this->mconf['useLargestItemX'] || $this->mconf['useLargestItemY'] || $this->mconf['distributeX'] || $this->mconf['distributeY']) {
1512 $totalWH = $this->findLargestDims($conf,$items,$Hobjs,$Wobjs,$minDim,$maxDim);
1513 }
1514 }
1515
1516 $c=0;
1517 $maxFlag=0;
1518 $distributeAccu=array('H'=>0,'W'=>0);
1519 reset($conf);
1520 while (list($key,$val)=each($conf)) {
1521 $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']++;
1522 $GLOBALS['TSFE']->register['count_MENUOBJ']++;
1523
1524 if ($items==($c+1) && $minDim) {
1525 $Lobjs = $this->mconf['removeObjectsOfDummy'];
1526 if ($Lobjs) {
1527 $Lobjs = t3lib_div::intExplode(',',$Lobjs);
1528 reset($Lobjs);
1529 while(list(,$remItem)=each($Lobjs)) {
1530 unset($val[$remItem]);
1531 unset($val[$remItem.'.']);
1532 }
1533 }
1534
1535 $flag =0;
1536 $tempXY = explode(',',$val['XY']);
1537 if ($Wcounter<$minDim[0]) {$tempXY[0]=$minDim[0]-$Wcounter; $flag=1;}
1538 if ($Hcounter<$minDim[1]) {$tempXY[1]=$minDim[1]-$Hcounter; $flag=1;}
1539 $val['XY'] = implode($tempXY,',');
1540 if (!$flag){break;}
1541 }
1542 $c++;
1543
1544
1545 if ($isGD) {
1546 // Pre-working the item
1547 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
1548 $gifCreator->init();
1549 $gifCreator->start($val,$this->menuArr[$key]);
1550
1551 // If useLargestItemH/W is specified
1552 if (count($totalWH) && ($this->mconf['useLargestItemX'] || $this->mconf['useLargestItemY'])) {
1553 $tempXY = explode(',',$gifCreator->setup['XY']);
1554 if ($this->mconf['useLargestItemX']) {$tempXY[0] = max($totalWH['W']);}
1555 if ($this->mconf['useLargestItemY']) {$tempXY[1] = max($totalWH['H']);}
1556 // regenerate the new values...
1557 $val['XY'] = implode($tempXY,',');
1558 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
1559 $gifCreator->init();
1560 $gifCreator->start($val,$this->menuArr[$key]);
1561 }
1562
1563 // If distributeH/W is specified
1564 if (count($totalWH) && ($this->mconf['distributeX'] || $this->mconf['distributeY'])) {
1565 $tempXY = explode(',',$gifCreator->setup['XY']);
1566
1567 if ($this->mconf['distributeX']) {
1568 $diff = $this->mconf['distributeX']-$totalWH['W_total']-$distributeAccu['W'];
1569 $compensate = round($diff /($items-$c+1));
1570 $distributeAccu['W']+=$compensate;
1571 $tempXY[0] = $totalWH['W'][$key]+$compensate;
1572 }
1573 if ($this->mconf['distributeY']) {
1574 $diff = $this->mconf['distributeY']-$totalWH['H_total']-$distributeAccu['H'];
1575 $compensate = round($diff /($items-$c+1));
1576 $distributeAccu['H']+=$compensate;
1577 $tempXY[1] = $totalWH['H'][$key]+$compensate;
1578 }
1579 // regenerate the new values...
1580 $val['XY'] = implode($tempXY,',');
1581 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
1582 $gifCreator->init();
1583 $gifCreator->start($val,$this->menuArr[$key]);
1584 }
1585
1586 // If max dimensions are specified
1587 if ($maxDim) {
1588 $tempXY = explode(',',$val['XY']);
1589 if ($maxDim[0] && $Wcounter+$gifCreator->XY[0]>=$maxDim[0]) {$tempXY[0]==$maxDim[0]-$Wcounter; $maxFlag=1;}
1590 if ($maxDim[1] && $Hcounter+$gifCreator->XY[1]>=$maxDim[1]) {$tempXY[1]=$maxDim[1]-$Hcounter; $maxFlag=1;}
1591 if ($maxFlag) {
1592 $val['XY'] = implode($tempXY,',');
1593 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
1594 $gifCreator->init();
1595 $gifCreator->start($val,$this->menuArr[$key]);
1596 }
1597 }
1598
1599
1600
1601
1602 // displace
1603 if ($Hobjs) {
1604 reset($Hobjs);
1605 while(list(,$index)=each($Hobjs)) {
1606 if ($gifCreator->setup[$index] && $gifCreator->setup[$index.'.']) {
1607 $oldOffset = explode(',',$gifCreator->setup[$index.'.']['offset']);
1608 $gifCreator->setup[$index.'.']['offset'] = implode($gifCreator->applyOffset($oldOffset,Array(0,-$Hcounter)), ',');
1609 }
1610 }
1611 }
1612
1613 if ($Wobjs) {
1614 reset($Wobjs);
1615 while(list(,$index)=each($Wobjs)) {
1616 if ($gifCreator->setup[$index] && $gifCreator->setup[$index.'.']) {
1617 $oldOffset = explode(',',$gifCreator->setup[$index.'.']['offset']);
1618 $gifCreator->setup[$index.'.']['offset'] = implode($gifCreator->applyOffset($oldOffset,Array(-$Wcounter,0)), ',');
1619 }
1620 }
1621 }
1622 }
1623
1624 // Finding alternative GIF names if any (by altImgResource)
1625 $gifFileName='';
1626 if ($conf[$key]['altImgResource'] || is_array($conf[$key]['altImgResource.'])) {
1627 if (!is_object($cObj)) {$cObj=t3lib_div::makeInstance('tslib_cObj');}
1628 $cObj->start($this->menuArr[$key],'pages');
1629 $altImgInfo = $cObj->getImgResource($conf[$key]['altImgResource'],$conf[$key]['altImgResource.']);
1630 $gifFileName=$altImgInfo[3];
1631 }
1632
1633 // If an alternative names was NOT given, find the GIFBUILDER name.
1634 if (!$gifFileName && $isGD) {
1635 $gifFileName = $gifCreator->fileName('m_');
1636 }
1637 // generation
1638 if (@file_exists($gifFileName)) { // File exists
1639 $info = @getimagesize($gifFileName);
1640 $this->result[$resKey][$key]['output_w']=intval($info[0]);
1641 $this->result[$resKey][$key]['output_h']=intval($info[1]);
1642 $this->result[$resKey][$key]['output_file']=$gifFileName;
1643 } elseif ($isGD) { // file is generated
1644 $gifCreator->make();
1645 $this->result[$resKey][$key]['output_w']=$gifCreator->w;
1646 $this->result[$resKey][$key]['output_h']=$gifCreator->h;
1647 $this->result[$resKey][$key]['output_file'] = $gifFileName;
1648 $gifCreator->output($this->result[$resKey][$key]['output_file']);
1649 $gifCreator->destroy();
1650 }
1651 $this->result[$resKey][$key]['output_file'] = t3lib_div::png_to_gif_by_imagemagick($this->result[$resKey][$key]['output_file']);
1652 $this->result[$resKey][$key]['wrap']=$conf[$key]['wrap'];
1653 $this->result[$resKey][$key]['noLink']=$conf[$key]['noLink'];
1654 $this->result[$resKey][$key]['altTarget']=$conf[$key]['altTarget'];
1655 $this->result[$resKey][$key]['imgParams']=$conf[$key]['imgParams'];
1656
1657 $Hcounter+=$this->result[$resKey][$key]['output_h']; // counter is increased
1658 $Wcounter+=$this->result[$resKey][$key]['output_w']; // counter is increased
1659
1660 if ($maxFlag){break;}
1661 }
1662 }
1663
1664 /**
1665 * Function searching for the largest width and height of the menu items to be generated.
1666 * 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.
1667 * Remember to upgrade the code in here if the makeGifs function is updated.
1668 *
1669 * @param array Same configuration array as passed to makeGifs()
1670 * @param integer The number of menu items
1671 * @param array Array with "applyTotalH" numbers
1672 * @param array Array with "applyTotalW" numbers
1673 * @param array Array with "min" x/y
1674 * @param array Array with "max" x/y
1675 * @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.
1676 * @access private
1677 * @see makeGifs()
1678 */
1679 function findLargestDims($conf,$items,$Hobjs,$Wobjs,$minDim,$maxDim) {
1680 $totalWH = array(
1681 'W' => array(),
1682 'H' => array(),
1683 'W_total' => 0,
1684 'H_total' => 0
1685 );
1686
1687 $Hcounter = 0;
1688 $Wcounter = 0;
1689 $c=0;
1690 $maxFlag=0;
1691 reset($conf);
1692 while (list($key,$val)=each($conf)) {
1693 // SAME CODE AS makeGifs()! BEGIN
1694 if ($items==($c+1) && $minDim) {
1695 $Lobjs = $this->mconf['removeObjectsOfDummy'];
1696 if ($Lobjs) {
1697 $Lobjs = t3lib_div::intExplode(',',$Lobjs);
1698 reset($Lobjs);
1699 while(list(,$remItem)=each($Lobjs)) {
1700 unset($val[$remItem]);
1701 unset($val[$remItem.'.']);
1702 }
1703 }
1704
1705 $flag =0;
1706 $tempXY = explode(',',$val['XY']);
1707 if ($Wcounter<$minDim[0]) {$tempXY[0]=$minDim[0]-$Wcounter; $flag=1;}
1708 if ($Hcounter<$minDim[1]) {$tempXY[1]=$minDim[1]-$Hcounter; $flag=1;}
1709 $val['XY'] = implode($tempXY,',');
1710 if (!$flag){break;}
1711 }
1712 $c++;
1713
1714 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
1715 $gifCreator->init();
1716 $gifCreator->start($val,$this->menuArr[$key]);
1717 if ($maxDim) {
1718 $tempXY = explode(',',$val['XY']);
1719 if ($maxDim[0] && $Wcounter+$gifCreator->XY[0]>=$maxDim[0]) {$tempXY[0]==$maxDim[0]-$Wcounter; $maxFlag=1;}
1720 if ($maxDim[1] && $Hcounter+$gifCreator->XY[1]>=$maxDim[1]) {$tempXY[1]=$maxDim[1]-$Hcounter; $maxFlag=1;}
1721 if ($maxFlag) {
1722 $val['XY'] = implode($tempXY,',');
1723 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
1724 $gifCreator->init();
1725 $gifCreator->start($val,$this->menuArr[$key]);
1726 }
1727 }
1728 // SAME CODE AS makeGifs()! END
1729
1730 // Setting the width/height
1731 $totalWH['W'][$key]=$gifCreator->XY[0];
1732 $totalWH['H'][$key]=$gifCreator->XY[1];
1733 $totalWH['W_total']+=$gifCreator->XY[0];
1734 $totalWH['H_total']+=$gifCreator->XY[1];
1735 // ---- //
1736
1737 $Hcounter+=$gifCreator->XY[1]; // counter is increased
1738 $Wcounter+=$gifCreator->XY[0]; // counter is increased
1739
1740 if ($maxFlag){break;}
1741 }
1742 return $totalWH;
1743 }
1744
1745 /**
1746 * 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())
1747 * 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
1748 *
1749 * @return string The HTML for the menu (returns result through $this->extProc_finish(); )
1750 */
1751 function writeMenu() {
1752 if (is_array($this->menuArr) && is_array($this->result) && count($this->result) && is_array($this->result['NO'])) {
1753 $this->WMresult='';
1754 $this->INPfixMD5 = substr(md5(microtime().$this->GMENU_fixKey),0,4);
1755 $this->WMmenuItems = count($this->result['NO']);
1756 $this->extProc_init();
1757 for ($key=0;$key<$this->WMmenuItems;$key++) {
1758 if ($this->result['NO'][$key]['output_file']) {
1759 $this->I =array();
1760 $this->I['key'] = $key;
1761 $this->I['INPfix']= $this->imgNameNotRandom?'':'_'.$this->INPfixMD5.'_'.$key;
1762 $this->I['val'] = $this->result['NO'][$key];
1763 $this->I['title'] = $this->getPageTitle($this->menuArr[$key]['title'],$this->menuArr[$key]['nav_title']);
1764 $this->I['uid'] = $this->menuArr[$key]['uid'];
1765 $this->I['mount_pid'] = $this->menuArr[$key]['mount_pid'];
1766 $this->I['pid'] = $this->menuArr[$key]['pid'];
1767 $this->I['spacer'] = $this->menuArr[$key]['isSpacer'];
1768 if (!$this->I['uid'] && !$this->menuArr[$key]['_OVERRIDE_HREF']) {$this->I['spacer']=1;}
1769 $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
1770 $this->I['name']='';
1771
1772 // Get link.
1773 $this->I['linkHREF'] = $this->link($key,$this->I['val']['altTarget'],$this->mconf['forceTypeValue']);
1774
1775 // Set noBlur
1776 if (!$this->mconf['noBlur']) {
1777 $this->I['linkHREF']['onFocus']='blurLink(this);';
1778 }
1779
1780 // Set rollover
1781 if ($this->result['RO'][$key] && !$this->I['noLink']) {
1782 $this->I['theName'] = $this->imgNamePrefix.$this->I['uid'].$this->I['INPfix'];
1783 $this->I['name'] = ' name="'.$this->I["theName"].'"';
1784 $this->I['linkHREF']['onMouseover']=$this->WMfreezePrefix.'over(\''.$this->I['theName'].'\');';
1785 $this->I['linkHREF']['onMouseout']=$this->WMfreezePrefix.'out(\''.$this->I['theName'].'\');';
1786 $GLOBALS['TSFE']->JSImgCode.= chr(10).$this->I['theName'].'_n=new Image(); '.$this->I['theName'].'_n.src = "'.$GLOBALS['TSFE']->absRefPrefix.$this->I['val']['output_file'].'"; ';
1787 $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'].'"; ';
1788 $GLOBALS['TSFE']->imagesOnPage[]=$this->result['RO'][$key]['output_file'];
1789 $GLOBALS['TSFE']->setJS('mouseOver');
1790 $this->extProc_RO($key);
1791 }
1792 // Set access key
1793 if ($this->mconf['accessKey']) {
1794 $this->I['accessKey'] = $this->accessKey($this->I['title']);
1795 } else {
1796 $this->I['accessKey']=Array();
1797 }
1798
1799 // Set altText
1800 $this->I['altText'] = $this->mconf['disableAltText'] ? '' : $this->I['title'].$this->I['accessKey']['alt'];
1801
1802 // Calling extra processing function
1803 $this->extProc_beforeLinking($key);
1804
1805 // Set linking
1806 if (!$this->I['noLink']) {
1807 $this->setATagParts();
1808 } else {
1809 $this->I['A1'] = '';
1810 $this->I['A2'] = '';
1811 }
1812 $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']:'').' />';
1813
1814 // Make before, middle and after parts
1815 $this->I['parts'] = array();
1816 $this->I['parts']['ATag_begin'] = $this->I['A1'];
1817 $this->I['parts']['image'] = $this->I['IMG'];
1818 $this->I['parts']['ATag_end'] = $this->I['A2'];
1819
1820 // Passing I to a user function
1821 if ($this->mconf['IProcFunc']) {
1822 $this->I = $this->userProcess('IProcFunc',$this->I);
1823 }
1824
1825 // Putting the item together.
1826 // Merge parts + beforeAllWrap
1827 $this->I['theItem']= implode('',$this->I['parts']);
1828 $this->I['theItem']= $this->extProc_beforeAllWrap($this->I['theItem'],$key);
1829
1830 // 'allWrap' (for GMENU's this is just the 'wrap' property)
1831 $this->I['theItem']= $this->tmpl->wrap($this->I['theItem'],$this->I['val']['wrap']);
1832 $GLOBALS['TSFE']->imagesOnPage[]=$this->I['val']['output_file'];
1833
1834 $this->extProc_afterLinking($key);
1835 }
1836 }
1837 return $this->extProc_finish();
1838 }
1839 }
1840
1841 /**
1842 * Called right before the traversing of $this->result begins.
1843 * Can be used for various initialization
1844 *
1845 * @return void
1846 * @access private
1847 * @see writeMenu(), tslib_gmenu_layers::extProc_init()
1848 */
1849 function extProc_init() {
1850 }
1851
1852 /**
1853 * Called after all processing for RollOver of an element has been done.
1854 *
1855 * @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!
1856 * @return void
1857 * @access private
1858 * @see writeMenu(), tslib_gmenu_layers::extProc_RO()
1859 */
1860 function extProc_RO($key) {
1861 }
1862
1863 /**
1864 * Called right before the creation of the link for the menu item
1865 *
1866 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
1867 * @return void
1868 * @access private
1869 * @see writeMenu(), tslib_gmenu_layers::extProc_beforeLinking()
1870 */
1871 function extProc_beforeLinking($key) {
1872 }
1873
1874 /**
1875 * 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.
1876 * This function MUST set $this->WMresult.=[HTML for menu item] to add the generated menu item to the internal accumulation of items.
1877 * Further this calls the subMenu function in the parent class to create any submenu there might be.
1878 *
1879 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
1880 * @return void
1881 * @access private
1882 * @see writeMenu(), tslib_gmenu_layers::extProc_afterLinking(), tslib_menu::subMenu()
1883 */
1884 function extProc_afterLinking($key) {
1885 $this->WMresult.=$this->I['theItem'];
1886 if (!$this->I['spacer']) {
1887 $this->WMresult.= $this->subMenu($this->I['uid'],$this->I['mount_pid']);
1888 }
1889 }
1890
1891
1892 /**
1893 * Called before the "wrap" happens on the menu item.
1894 *
1895 * @param string The current content of the menu item, $this->I['theItem'], passed along.
1896 * @param integer Pointer to $this->menuArr[$key] where the current menu element record is found
1897 * @return string The modified version of $item, going back into $this->I['theItem']
1898 * @access private
1899 * @see writeMenu(), tslib_gmenu_layers::extProc_beforeAllWrap()
1900 */
1901 function extProc_beforeAllWrap($item,$key) {
1902 return $item;
1903 }
1904
1905 /**
1906 * Called before the writeMenu() function returns (only if a menu was generated)
1907 *
1908 * @return string The total menu content should be returned by this function
1909 * @access private
1910 * @see writeMenu(), tslib_gmenu_layers::extProc_finish()
1911 */
1912 function extProc_finish() {
1913 return $this->tmpl->wrap($this->WMresult,$this->mconf['wrap']).$this->WMextraScript;
1914 }
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 * ImageMap based menus
1940 *
1941 * @author Kasper Skaarhoj <kasper@typo3.com>
1942 * @package TYPO3
1943 * @subpackage tslib
1944 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=389&cHash=fcf18c5d9f
1945 */
1946 class tslib_imgmenu extends tslib_menu {
1947
1948 /**
1949 * Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
1950 * Calls makeImageMap() to generate the image map image-file
1951 *
1952 * @return void
1953 * @see tslib_menu::procesItemStates(), makeImageMap()
1954 */
1955 function generate() {
1956 $splitCount = count($this->menuArr);
1957 if ($splitCount) {
1958 list($NOconf) = $this->procesItemStates($splitCount);
1959 }
1960 if ($this->mconf['debugItemConf']) {echo '<h3>$NOconf:</h3>'; debug($NOconf); }
1961 $this->makeImageMap($NOconf);
1962 }
1963
1964 /**
1965 * Will traverse input array with configuratoin per-item and create corresponding GIF files for the menu.
1966 * The data of the files are stored in $this->result
1967 *
1968 * @param array Array with configuration for each item.
1969 * @return void
1970 * @access private
1971 * @see generate()
1972 */
1973 function makeImageMap($conf) {
1974 if (!is_array($conf)) {
1975 $conf = Array();
1976 }
1977 if (is_array($this->mconf['main.'])) {
1978 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
1979 $gifCreator->init();
1980
1981 $itemsConf = $conf;
1982 $conf = $this->mconf['main.'];
1983 if (is_array($conf)) {
1984 $gifObjCount = 0;
1985
1986 $sKeyArray=t3lib_TStemplate::sortedKeyList($conf);
1987 $gifObjCount=intval(end($sKeyArray));
1988
1989 $lastOriginal = $gifObjCount;
1990
1991 // Now we add graphical objects to the gifbuilder-setup
1992 reset($itemsConf);
1993 $waArr = Array();
1994 while (list($key,$val)=each($itemsConf)) {
1995 if (is_array($val)) {
1996 $gifObjCount++;
1997 $waArr[$key]['free']=$gifObjCount;
1998
1999 $sKeyArray=t3lib_TStemplate::sortedKeyList($val);
2000 reset($sKeyArray);
2001 while(list(,$theKey)=each($sKeyArray)) {
2002 $theValue=$val[$theKey];
2003
2004
2005 if (intval($theKey) && $theValArr=$val[$theKey.'.']) {
2006 $cObjData = $this->menuArr[$key] ? $this->menuArr[$key] : Array();
2007
2008 $gifObjCount++;
2009 if ($theValue=='TEXT') {
2010 $waArr[$key]['textNum']=$gifObjCount;
2011
2012 $gifCreator->data = $cObjData;
2013 $theValArr = $gifCreator->checkTextObj($theValArr);
2014 unset($theValArr['text.']); // if this is not done it seems that imageMaps will be rendered wrong!!
2015 // check links
2016
2017 $LD = $this->tmpl->linkData($this->menuArr[$key],$this->mconf['target'],'','',array(),'',$this->mconf['forceTypeValue']);
2018
2019 // Overriding URL / Target if set to do so:
2020 if ($this->menuArr[$key]['_OVERRIDE_HREF']) {
2021 $LD['totalURL'] = $this->menuArr[$key]['_OVERRIDE_HREF'];
2022 if ($this->menuArr[$key]['_OVERRIDE_TARGET']) $LD['target'] = $this->menuArr[$key]['_OVERRIDE_TARGET'];
2023 }
2024
2025 // Setting target/url:
2026 if ($theValArr['imgMap.']['url']=='') {
2027 $theValArr['imgMap.']['url'] = $LD['totalURL'];
2028 }
2029 if ($theValArr['imgMap.']['target']=='') {
2030 $theValArr['imgMap.']['target'] = $LD['target'];
2031 }
2032 if ($theValArr['imgMap.']['noBlur']=='') {
2033 $theValArr['imgMap.']['noBlur'] = $this->mconf['noBlur'];
2034 }
2035 }
2036 // 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!!
2037 if ($theValue=='IMAGE') {
2038 if ($theValArr['file']=='GIFBUILDER') {
2039 $temp_sKeyArray=t3lib_TStemplate::sortedKeyList($theValArr['file.']);
2040 reset($temp_sKeyArray);
2041 while(list(,$temp_theKey)=each($temp_sKeyArray)) {
2042 if ($theValArr['mask.'][$temp_theKey]=='TEXT') {
2043 $gifCreator->data = $this->menuArr[$key] ? $this->menuArr[$key] : Array();
2044 $theValArr['mask.'][$temp_theKey.'.'] = $gifCreator->checkTextObj($theValArr['mask.'][$temp_theKey.'.']);
2045 unset($theValArr['mask.'][$temp_theKey.'.']['text.']); // if this is not done it seems that imageMaps will be rendered wrong!!
2046 }
2047 }
2048 }
2049 if ($theValArr['mask']=='GIFBUILDER') {
2050 $temp_sKeyArray=t3lib_TStemplate::sortedKeyList($theValArr['mask.']);
2051 reset($temp_sKeyArray);
2052 while(list(,$temp_theKey)=each($temp_sKeyArray)) {
2053 if ($theValArr['mask.'][$temp_theKey]=='TEXT') {
2054 $gifCreator->data = $this->menuArr[$key] ? $this->menuArr[$key] : Array();
2055 $theValArr['mask.'][$temp_theKey.'.'] = $gifCreator->checkTextObj($theValArr['mask.'][$temp_theKey.'.']);
2056 unset($theValArr['mask.'][$temp_theKey.'.']['text.']); // if this is not done it seems that imageMaps will be rendered wrong!!
2057 }
2058 }
2059 }
2060 }
2061
2062 // Checks if disabled is set...
2063 $setObjFlag=1;
2064 if ($theValArr['if.']) {
2065 $cObj =t3lib_div::makeInstance('tslib_cObj');
2066 $cObj->start($cObjData,'pages');
2067 if (!$cObj->checkIf($theValArr['if.'])) {
2068 $setObjFlag=0;
2069 }
2070 unset($theValArr['if.']);
2071 }
2072 // Set the object!
2073 if ($setObjFlag) {
2074 $conf[$gifObjCount] = $theValue;
2075 $conf[$gifObjCount.'.'] = $theValArr;
2076 }
2077 }
2078 }
2079 }
2080 }
2081
2082 $gifCreator->start($conf,$GLOBALS['TSFE']->page);
2083 // calculations
2084
2085 $sum=Array(0,0,0,0);
2086 reset($waArr);
2087 while (list($key,$val)=each($waArr)) {
2088 if ($dConf[$key] =$itemsConf[$key]['distrib']) {
2089 $textBB = $gifCreator->objBB[$val['textNum']];
2090 $dConf[$key] = str_replace('textX',$textBB[0],$dConf[$key]);
2091 $dConf[$key] = str_replace('textY',$textBB[1],$dConf[$key]);
2092 $dConf[$key] = t3lib_div::intExplode(',',$gifCreator->calcOffset($dConf[$key]));
2093 }
2094 }
2095 $workArea = t3lib_div::intExplode(',',$gifCreator->calcOffset($this->mconf['dWorkArea']));
2096 reset($waArr);
2097 while (list($key,$val)=each($waArr)) {
2098 $index = $val['free'];
2099 $gifCreator->setup[$index] = 'WORKAREA';
2100 $workArea[2] = $dConf[$key][2] ? $dConf[$key][2] : $dConf[$key][0];
2101 $workArea[3] = $dConf[$key][3] ? $dConf[$key][3] : $dConf[$key][1];
2102
2103 $gifCreator->setup[$index.'.']['set'] = implode($workArea,',');
2104 $workArea[0]+=$dConf[$key][0];
2105 $workArea[1]+=$dConf[$key][1];
2106 }
2107
2108 if ($this->mconf['debugRenumberedObject']) {echo '<h3>Renumbered GIFBUILDER object:</h3>'; debug($gifCreator->setup);}
2109
2110 $gifFileName = $gifCreator->fileName('m_');
2111 // Gets the ImageMap from the cache...
2112 $imgHash = md5($gifFileName);
2113 $imgMap = $this->sys_page->getHash($imgHash, 0);
2114
2115 if ($imgMap && @file_exists($gifFileName)) { // File exists
2116 $info = @getimagesize($gifFileName);
2117 $w=$info[0];
2118 $h=$info[1];
2119 } else { // file is generated
2120 $gifCreator->make();
2121 $w=$gifCreator->w;
2122 $h=$gifCreator->h;
2123 $gifCreator->output($gifFileName);
2124 $gifCreator->destroy();
2125 $imgMap=$gifCreator->map;
2126 $this->sys_page->storeHash($imgHash, $imgMap, 'MENU IMAGEMAP');
2127 }
2128 $imgMap.=$this->mconf['imgMapExtras'];
2129
2130 $gifFileName = t3lib_div::png_to_gif_by_imagemagick($gifFileName);
2131 $this->result = Array('output_file'=>$gifFileName, 'output_w'=>$w, 'output_h'=>$h, 'imgMap'=>$imgMap);
2132 }
2133 }
2134 }
2135
2136 /**
2137 * Returns the HTML for the image map menu.
2138 * If ->result is true it will create the HTML for the image map menu.
2139 *
2140 * @return string The HTML for the menu
2141 */
2142 function writeMenu() {
2143 if ($this->result) {
2144 $res = $this->result;
2145 $menuName = 'menu_'.t3lib_div::shortMD5($res['imgMap']); // shortMD5 260900
2146 $result = '<img src="'.$GLOBALS['TSFE']->absRefPrefix.$res['output_file'].'" width="'.$res['output_w'].'" height="'.$res['output_h'].'" usemap="#'.$menuName.'" border="0" '.$this->mconf['params'];
2147 if (!strstr($result,'alt="')) $result.=' alt="Menu Image Map"'; // Adding alt attribute if not set.
2148 $result.= ' /><map name="'.$menuName.'" id="'.$menuName.'">'.$res['imgMap'].'</map>';
2149
2150 $GLOBALS['TSFE']->imagesOnPage[]=$res['output_file'];
2151
2152 return $this->tmpl->wrap($result,$this->mconf['wrap']);
2153 }
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 * JavaScript/Selectorbox based menus
2179 *
2180 * @author Kasper Skaarhoj <kasper@typo3.com>
2181 * @package TYPO3
2182 * @subpackage tslib
2183 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=391&cHash=563435abbc
2184 */
2185 class tslib_jsmenu extends tslib_menu {
2186
2187 /**
2188 * Dummy. Should do nothing, because we don't use the result-array here!
2189 *
2190 * @return void
2191 */
2192 function generate() {
2193 }
2194
2195 /**
2196 * Creates the HTML (mixture of a <form> and a JavaScript section) for the JavaScript menu (basically an array of selector boxes with onchange handlers)
2197 *
2198 * @return string The HTML code for the menu
2199 */
2200 function writeMenu() {
2201 if ($this->id) {
2202 // Making levels:
2203 $levels = t3lib_div::intInRange($this->mconf['levels'],1,5);
2204 $this->levels = $levels;
2205 $this->JSVarName='eid';
2206 $this->JSMenuName= $this->mconf['menuName'] ? $this->mconf['menuName'] : 'JSmenu';
2207
2208 $JScode="\n var ".$this->JSMenuName." = new JSmenu(".$levels.",'".$this->JSMenuName."Form');";
2209
2210 for ($a=1;$a<=$levels;$a++) {
2211 $JScode.="\n var ".$this->JSVarName.$a."=0;";
2212 }
2213 $JScode.= $this->generate_level($levels,1,$this->id,$this->menuArr)."\n";
2214
2215 $GLOBALS['TSFE']->additionalHeaderData['JSMenuCode']='<script type="text/javascript" src="'.$GLOBALS['TSFE']->absRefPrefix.'t3lib/jsfunc.menu.js"></script>';
2216 $GLOBALS['TSFE']->JSCode.=$JScode;
2217
2218 // Printing:
2219 $allFormCode="";
2220 for ($a=1;$a<=$this->levels;$a++) {
2221 $formCode='';
2222 $levelConf = $this->mconf[$a.'.'];
2223 $length = $levelConf['width'] ? $levelConf['width'] : 14;
2224 $lenghtStr='';
2225 for ($b=0;$b<$length;$b++) {
2226 $lenghtStr.='_';
2227 }
2228 $height = $levelConf['elements'] ? $levelConf['elements'] : 5;
2229
2230 $formCode.= '<select name="selector'.$a.'" onchange="'.$this->JSMenuName.'.act('.$a.');"'.($levelConf['additionalParams']?' '.$levelConf['additionalParams']:'').'>';
2231 for ($b=0;$b<$height;$b++) {
2232 $formCode.= '<option value="0">';
2233 if ($b==0) {
2234 $formCode.= $lenghtStr;
2235 }
2236 $formCode.='</option>';
2237 }
2238 $formCode.= '</select>';
2239 $allFormCode.=$this->tmpl->wrap($formCode,$levelConf['wrap']);
2240 }
2241 $formCode = $this->tmpl->wrap($allFormCode,$this->mconf['wrap']);
2242
2243 $formCode= '<form action="" method="post" style="margin: 0 0 0 0;" name="'.$this->JSMenuName.'Form">'.$formCode.'</form>';
2244 $formCode.='<script type="text/javascript"> /*<![CDATA[*/ '.$this->JSMenuName.'.writeOut(1,'.$this->JSMenuName.'.openID,1); /*]]>*/ </script>';
2245 return $this->tmpl->wrap($formCode,$this->mconf['wrapAfterTags']);
2246 }
2247 }
2248
2249 /**
2250 * Generates a number of lines of JavaScript code for a menu level.
2251 * Calls itself recursively for additional levels.
2252 *
2253 * @param integer Number of levels to generate
2254 * @param integer Current level being generated - and if this number is less than $levels it will call itself recursively with $count incremented
2255 * @param integer Page id of the starting point.
2256 * @param array $this->menuArr passed along
2257 * @return string JavaScript code lines.
2258 * @access private
2259 */
2260 function generate_level($levels,$count,$pid,$menuItemArray='') {
2261 $levelConf = $this->mconf[$count.'.'];
2262
2263 $temp = is_array($menuItemArray) ? $menuItemArray : $this->sys_page->getMenu($pid);
2264 reset($temp);
2265
2266 $var = $this->JSVarName;
2267 $menuName = $this->JSMenuName;
2268
2269 $banUidArray=array();
2270 if (trim($this->conf['excludeUidList'])) {
2271 $banUidArray = t3lib_div::intExplode(',', $this->conf['excludeUidList']);
2272 }
2273
2274 $parent = $count==1 ? 0 : $var.($count-1);
2275 $prev=0;
2276 $c=0;
2277 reset($temp);
2278 while(list($uid,$data)=each($temp)) {
2279 $spacer = (t3lib_div::inList($this->spacerIDList,$data['doktype'])?1:0); // if item is a spacer, $spacer is set
2280 if ($this->mconf['SPC'] || !$spacer) { // If the spacer-function is not enabled, spacers will not enter the $menuArr
2281 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
2282 if ($count<$levels) {
2283 $addLines = $this->generate_level($levels,$count+1,$data['uid']);
2284 } else {
2285 $addLines = '';
2286 }
2287 $title=rawurlencode($data['title']);
2288 $url='';
2289 $target='';
2290 if ((!$addLines && !$levelConf['noLink']) || $levelConf['alwaysLink']) {
2291 $LD = $this->tmpl->linkData($data,$this->mconf['target'],'','',array(),'',$this->mconf['forceTypeValue']);
2292 $url = rawurlencode($LD['totalURL']);
2293 $target = rawurlencode($LD['target']);
2294 }
2295 $codeLines.="\n".$var.$count."=".$menuName.".add(".$parent.",".$prev.",0,'".$title."','".$url."','".$target."');";
2296 // If the active one should be chosen...
2297 $active = ($levelConf['showActive'] && $data['uid'] == $this->tmpl->rootLine[$count]['uid']);
2298 // If the first item should be shown
2299 $first = (!$c && $levelConf['showFirst']);
2300 // do it...
2301 if ($active || $first) {
2302 if ($count==1) {
2303 $codeLines.="\n".$menuName.".openID = ".$var.$count.";";
2304 } else {
2305 $codeLines.="\n".$menuName.".entry[".$parent."].openID = ".$var.$count.";";
2306 }
2307 }
2308 // Add submenu...
2309 $codeLines.=$addLines;
2310
2311 $prev=$var.$count;
2312 $c++;
2313 }
2314 }
2315 }
2316 if ($this->mconf['firstLabelGeneral'] && !$levelConf['firstLabel']) {$levelConf['firstLabel'] = $this->mconf['firstLabelGeneral'];}
2317 if ($levelConf['firstLabel'] && $codeLines) { $codeLines.="\n".$menuName.".defTopTitle[".$count."] = unescape('".rawurlencode($levelConf['firstLabel'])."');"; }
2318 return trim($codeLines);
2319 }
2320 }
2321
2322
2323 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['tslib/class.tslib_menu.php']) {
2324 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['tslib/class.tslib_menu.php']);
2325 }
2326
2327 ?>