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