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