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