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