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