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