TYPO3 API  SVNRelease
class.tslib_menu.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00027 /**
00028  * Generating navigation / menus from TypoScript
00029  *
00030  * This file contains five classes, four of which are extensions to the main class, tslib_menu.
00031  * 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.
00032  * Notice that extension classes (like "tslib_tmenu") must have their suffix (here "tmenu") listed in $this->tmpl->menuclasses - otherwise they cannot be instantiated.
00033  *
00034  * $Id: class.tslib_menu.php 10382 2011-02-04 15:50:08Z francois $
00035  * Revised for TYPO3 3.6 June/2003 by Kasper Skårhøj
00036  * XHTML compliant
00037  *
00038  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00039  */
00040 /**
00041  * [CLASS/FUNCTION INDEX of SCRIPT]
00042  *
00043  *
00044  *
00045  *  146: class tslib_menu
00046  *  211:     function start(&$tmpl,&$sys_page,$id,$conf,$menuNumber,$objSuffix='')
00047  *  357:     function makeMenu()
00048  *  909:     function includeMakeMenu($conf,$altSortField)
00049  *  925:     function filterMenuPages(&$data,$banUidArray,$spacer)
00050  *  981:     function procesItemStates($splitCount)
00051  * 1191:     function link($key,$altTarget='',$typeOverride='')
00052  * 1263:     function changeLinksForAccessRestrictedPages(&$LD, $page, $mainTarget, $typeOverride)
00053  * 1284:     function subMenu($uid, $objSuffix='')
00054  * 1330:     function isNext($uid, $MPvar='')
00055  * 1351:     function isActive($uid, $MPvar='')
00056  * 1372:     function isCurrent($uid, $MPvar='')
00057  * 1387:     function isSubMenu($uid)
00058  * 1412:     function isItemState($kind,$key)
00059  * 1452:     function accessKey($title)
00060  * 1480:     function userProcess($mConfKey,$passVar)
00061  * 1495:     function setATagParts()
00062  * 1508:     function getPageTitle($title,$nav_title)
00063  * 1520:     function getMPvar($key)
00064  * 1535:     function getDoktypeExcludeWhere()
00065  * 1545:     function getBannedUids()
00066  * 1568:     function menuTypoLink($page, $oTarget, $no_cache, $script, $overrideArray = '', $addParams = '', $typeOverride = '')
00067  *
00068  *
00069  * 1618: class tslib_tmenu extends tslib_menu
00070  * 1627:     function generate()
00071  * 1643:     function writeMenu()
00072  * 1796:     function getBeforeAfter($pref)
00073  * 1826:     function addJScolorShiftFunction()
00074  * 1848:     function extProc_init()
00075  * 1859:     function extProc_RO($key)
00076  * 1870:     function extProc_beforeLinking($key)
00077  * 1882:     function extProc_afterLinking($key)
00078  * 1900:     function extProc_beforeAllWrap($item,$key)
00079  * 1911:     function extProc_finish()
00080  *
00081  *
00082  * 1951: class tslib_gmenu extends tslib_menu
00083  * 1960:     function generate()
00084  * 1998:     function makeGifs($conf, $resKey)
00085  * 2196:     function findLargestDims($conf,$items,$Hobjs,$Wobjs,$minDim,$maxDim)
00086  * 2268:     function writeMenu()
00087  * 2392:     function extProc_init()
00088  * 2403:     function extProc_RO($key)
00089  * 2414:     function extProc_beforeLinking($key)
00090  * 2427:     function extProc_afterLinking($key)
00091  * 2444:     function extProc_beforeAllWrap($item,$key)
00092  * 2455:     function extProc_finish()
00093  *
00094  *
00095  * 2493: class tslib_imgmenu extends tslib_menu
00096  * 2502:     function generate()
00097  * 2520:     function makeImageMap($conf)
00098  * 2706:     function writeMenu()
00099  *
00100  *
00101  * 2749: class tslib_jsmenu extends tslib_menu
00102  * 2756:     function generate()
00103  * 2764:     function writeMenu()
00104  * 2825:     function generate_level($levels,$count,$pid,$menuItemArray='',$MP_array=array())
00105  *
00106  * TOTAL FUNCTIONS: 47
00107  * (This index is automatically created/updated by the extension "extdeveval")
00108  *
00109  */
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 /**
00129  * Base class. The HMENU content object uses this (or more precisely one of the extension classes).
00130  * Amoung others the class generates an array of menuitems. Thereafter functions from the subclasses are called.
00131  * The class is ALWAYS used through extension classes (like tslib_gmenu or tslib_tmenu which are classics) and
00132  *
00133  * Example of usage (from tslib_cObj):
00134  *
00135  * $menu = t3lib_div::makeInstance('tslib_'.$cls);
00136  * $menu->parent_cObj = $this;
00137  * $menu->start($GLOBALS['TSFE']->tmpl,$GLOBALS['TSFE']->sys_page,'',$conf,1);
00138  * $menu->makeMenu();
00139  * $content.=$menu->writeMenu();
00140  *
00141  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00142  * @package TYPO3
00143  * @subpackage tslib
00144  * @see tslib_cObj::HMENU()
00145  */
00146 class tslib_menu {
00147     var $menuNumber = 1;                // tells you which menu-number this is. This is important when getting data from the setup
00148     var $entryLevel = 0;                // 0 = rootFolder
00149     var $spacerIDList = '199';          // The doktype-number that defines a spacer
00150         // @TODO: RFC #7370: doktype 2&5 are deprecated since TYPO3 4.2-beta1
00151     var $doktypeExcludeList = '5,6';            // doktypes that define which should not be included in a menu
00152     var $alwaysActivePIDlist=array();
00153     var $imgNamePrefix = 'img';
00154     var $imgNameNotRandom=0;
00155     var $debug = 0;
00156 
00157     /**
00158      * Loaded with the parent cObj-object when a new HMENU is made
00159      *
00160      * @var tslib_cObj
00161      */
00162     var $parent_cObj;
00163     var $GMENU_fixKey='gmenu';
00164     var $MP_array=array();              // accumulation of mount point data
00165 
00166         // internal
00167     var $conf = Array();                // HMENU configuration
00168     var $mconf = Array();               // xMENU configuration (TMENU, GMENU etc)
00169 
00170     /**
00171      * template-object
00172      *
00173      * @var t3lib_TStemplate
00174      */
00175     var $tmpl;
00176 
00177     /**
00178      * sys_page-object, pagefunctions
00179      *
00180      * @var t3lib_pageSelect
00181      */
00182     var $sys_page;
00183     var $id;                            // The base page-id of the menu.
00184     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.
00185     var $menuArr;   // The array of menuItems which is built
00186     var $hash;
00187     var $result = Array();
00188     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)
00189     var $INPfixMD5;
00190     var $I;
00191     var $WMresult;
00192     var $WMfreezePrefix;
00193     var $WMmenuItems;
00194     var $WMsubmenuObjSuffixes;
00195     var $WMextraScript;
00196     var $alternativeMenuTempArray='';       // Can be set to contain menu item arrays for sub-levels.
00197     var $nameAttribute = 'name';            // Will be 'id' in XHTML-mode
00198 
00199     /**
00200      * The initialization of the object. This just sets some internal variables.
00201      *
00202      * @param   object      The $GLOBALS['TSFE']->tmpl object
00203      * @param   object      The $GLOBALS['TSFE']->sys_page object
00204      * @param   integer     A starting point page id. This should probably be blank since the 'entryLevel' value will be used then.
00205      * @param   array       The TypoScript configuration for the HMENU cObject
00206      * @param   integer     Menu number; 1,2,3. Should probably be '1'
00207      * @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")
00208      * @return  boolean     Returns true on success
00209      * @see tslib_cObj::HMENU()
00210      */
00211     function start(&$tmpl,&$sys_page,$id,$conf,$menuNumber,$objSuffix='')   {
00212 
00213             // Init:
00214         $this->conf = $conf;
00215         $this->menuNumber = $menuNumber;
00216         $this->mconf = $conf[$this->menuNumber.$objSuffix.'.'];
00217         $this->debug=$GLOBALS['TSFE']->debug;
00218 
00219             // In XHTML there is no "name" attribute anymore
00220         switch ($GLOBALS['TSFE']->xhtmlDoctype) {
00221             case 'xhtml_strict':
00222             case 'xhtml_11':
00223             case 'xhtml_2':
00224             case 'html5':
00225                 $this->nameAttribute = 'id';
00226                 break;
00227             default:
00228                 $this->nameAttribute = 'name';
00229                 break;
00230         }
00231 
00232             // Sets the internal vars. $tmpl MUST be the template-object. $sys_page MUST be the sys_page object
00233         if ($this->conf[$this->menuNumber.$objSuffix] && is_object($tmpl) && is_object($sys_page))  {
00234             $this->tmpl = $tmpl;
00235             $this->sys_page = $sys_page;
00236 
00237                 // alwaysActivePIDlist initialized:
00238             if (trim($this->conf['alwaysActivePIDlist']) || isset($this->conf['alwaysActivePIDlist.'])) {
00239                 if (isset($this->conf['alwaysActivePIDlist.'])) {
00240                     $this->conf['alwaysActivePIDlist'] = $this->parent_cObj->stdWrap($this->conf['alwaysActivePIDlist'], $this->conf['alwaysActivePIDlist.']);
00241                 }
00242                 $this->alwaysActivePIDlist = t3lib_div::intExplode(',', $this->conf['alwaysActivePIDlist']);
00243             }
00244 
00245                 // 'not in menu' doktypes
00246             if($this->conf['excludeDoktypes']) {
00247                 $this->doktypeExcludeList = $GLOBALS['TYPO3_DB']->cleanIntList($this->conf['excludeDoktypes']);
00248             }
00249             if($this->conf['includeNotInMenu']) {
00250                 $exclDoktypeArr = t3lib_div::trimExplode(',',$this->doktypeExcludeList,1);
00251                     // @TODO: RFC #7370: doktype 2&5 are deprecated since TYPO3 4.2-beta1
00252                 $exclDoktypeArr = t3lib_div::removeArrayEntryByValue($exclDoktypeArr,'5');
00253                 $this->doktypeExcludeList = implode(',',$exclDoktypeArr);
00254             }
00255                 // EntryLevel
00256             $this->entryLevel = tslib_cObj::getKey (
00257                 isset($conf['entryLevel.'])
00258                 ? $this->parent_cObj->stdWrap($conf['entryLevel'], $conf['entryLevel.'])
00259                 : $conf['entryLevel'],
00260                 $this->tmpl->rootLine
00261             );
00262                 // Set parent page: If $id not stated with start() then the base-id will be found from rootLine[$this->entryLevel]
00263             if ($id)    {   // Called as the next level in a menu. It is assumed that $this->MP_array is set from parent menu.
00264                 $this->id = intval($id);
00265             } else {    // This is a BRAND NEW menu, first level. So we take ID from rootline and also find MP_array (mount points)
00266                 $this->id = intval($this->tmpl->rootLine[$this->entryLevel]['uid']);
00267 
00268                     // Traverse rootline to build MP_array of pages BEFORE the entryLevel
00269                     // (MP var for ->id is picked up in the next part of the code...)
00270                 foreach($this->tmpl->rootLine as $entryLevel => $levelRec)  {
00271                         // For overlaid mount points, set the variable right now:
00272                     if ($levelRec['_MP_PARAM'] && $levelRec['_MOUNT_OL'])   {
00273                         $this->MP_array[] = $levelRec['_MP_PARAM'];
00274             }
00275                         // Break when entry level is reached:
00276                     if ($entryLevel>=$this->entryLevel) break;
00277 
00278                         // For normal mount points, set the variable for next level.
00279                     if ($levelRec['_MP_PARAM'] && !$levelRec['_MOUNT_OL'])  {
00280                         $this->MP_array[] = $levelRec['_MP_PARAM'];
00281                     }
00282                 }
00283             }
00284 
00285                 // Return false if no page ID was set (thus no menu of subpages can be made).
00286             if ($this->id<=0)   {
00287                 return FALSE;
00288             }
00289 
00290                 // Check if page is a mount point, and if so set id and MP_array
00291                 // (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...)
00292             $mount_info = $this->sys_page->getMountPointInfo($this->id);
00293             if (is_array($mount_info))  {
00294                 $this->MP_array[] = $mount_info['MPvar'];
00295                 $this->id = $mount_info['mount_pid'];
00296             }
00297 
00298                 // Gather list of page uids in root line (for "isActive" evaluation). Also adds the MP params in the path so Mount Points are respected.
00299                 // (List is specific for this rootline, so it may be supplied from parent menus for speed...)
00300             if (!is_array($this->rL_uidRegister))   {
00301                 $rl_MParray = array();
00302                 foreach($this->tmpl->rootLine as $v_rl) {
00303                         // For overlaid mount points, set the variable right now:
00304                     if ($v_rl['_MP_PARAM'] && $v_rl['_MOUNT_OL'])   {
00305                         $rl_MParray[] = $v_rl['_MP_PARAM'];
00306                     }
00307 
00308                         // Add to register:
00309                     $this->rL_uidRegister[] = 'ITEM:'.$v_rl['uid'].(count($rl_MParray) ? ':'.implode(',',$rl_MParray) : '');
00310 
00311                         // For normal mount points, set the variable for next level.
00312                     if ($v_rl['_MP_PARAM'] && !$v_rl['_MOUNT_OL'])  {
00313                         $rl_MParray[] = $v_rl['_MP_PARAM'];
00314                     }
00315                 }
00316             }
00317 
00318             // Set $directoryLevel so the following evalution of the nextActive will not return
00319             // an invalid value if .special=directory was set
00320             $directoryLevel = 0;
00321             if ($this->conf['special'] == 'directory')  {
00322                 $value = isset($this->conf['special.']['value.'])
00323                     ? $this->parent_cObj->stdWrap($this->conf['special.']['value'], $this->conf['special.']['value.'])
00324                     : $this->conf['special.']['value'];
00325                 if ($value=='') {
00326                     $value=$GLOBALS['TSFE']->page['uid'];
00327                 }
00328                 $directoryLevel = intval($GLOBALS['TSFE']->tmpl->getRootlineLevel($value));
00329             }
00330 
00331                 // 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
00332                 // Notice: The automatic expansion of a menu is designed to work only when no "special" modes (except "directory") are used.
00333             $startLevel = $directoryLevel ? $directoryLevel : $this->entryLevel;
00334             $currentLevel = $startLevel + $this->menuNumber;
00335             if (is_array($this->tmpl->rootLine[$currentLevel])) {
00336                 $nextMParray = $this->MP_array;
00337                 if (!count($nextMParray) && !$this->tmpl->rootLine[$currentLevel]['_MOUNT_OL'] && $currentLevel > 0) {
00338                         // Make sure to slide-down any mount point information (_MP_PARAM) to children records in the rootline
00339                         // otherwise automatic expansion will not work
00340                     $parentRecord = $this->tmpl->rootLine[$currentLevel - 1];
00341                     if (isset($parentRecord['_MP_PARAM'])) {
00342                         $nextMParray[] = $parentRecord['_MP_PARAM'];
00343                     }
00344                 }
00345 
00346                 if ($this->tmpl->rootLine[$currentLevel]['_MOUNT_OL']) {    // In overlay mode, add next level MPvars as well:
00347                     $nextMParray[] = $this->tmpl->rootLine[$currentLevel]['_MP_PARAM'];
00348                 }
00349                 $this->nextActive = $this->tmpl->rootLine[$currentLevel]['uid'] . (count($nextMParray) ? ':' . implode(',', $nextMParray) : '');
00350             } else {
00351                 $this->nextActive = '';
00352             }
00353 
00354                 // imgNamePrefix
00355             if ($this->mconf['imgNamePrefix']) {
00356                 $this->imgNamePrefix=$this->mconf['imgNamePrefix'];
00357             }
00358             $this->imgNameNotRandom = $this->mconf['imgNameNotRandom'];
00359 
00360             $retVal = TRUE;
00361         } else {
00362             $GLOBALS['TT']->setTSlogMessage('ERROR in menu',3);
00363             $retVal = FALSE;
00364         }
00365         return $retVal;
00366     }
00367 
00368     /**
00369      * Creates the menu in the internal variables, ready for output.
00370      * Basically this will read the page records needed and fill in the internal $this->menuArr
00371      * 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.
00372      *
00373      * @return  void
00374      */
00375     function makeMenu() {
00376         if ($this->id)  {
00377 
00378                 // Initializing showAccessRestrictedPages
00379             if ($this->mconf['showAccessRestrictedPages'])  {
00380                     // SAVING where_groupAccess
00381                 $SAVED_where_groupAccess = $this->sys_page->where_groupAccess;
00382                 $this->sys_page->where_groupAccess = '';    // Temporarily removing fe_group checking!
00383             }
00384 
00385                 // Begin production of menu:
00386             $temp = array();
00387             $altSortFieldValue = trim($this->mconf['alternativeSortingField']);
00388             $altSortField = $altSortFieldValue ? $altSortFieldValue : 'sorting';
00389             if ($this->menuNumber==1 && $this->conf['special']) {       // ... only for the FIRST level of a HMENU
00390                 $value = isset($this->conf['special.']['value.'])
00391                     ? $this->parent_cObj->stdWrap($this->conf['special.']['value'], $this->conf['special.']['value.'])
00392                     : $this->conf['special.']['value'];
00393 
00394                 switch($this->conf['special'])  {
00395                     case 'userdefined':
00396                         $temp = $this->includeMakeMenu($this->conf['special.'],$altSortField);
00397                     break;
00398                     case 'userfunction':
00399                         $temp = $this->parent_cObj->callUserFunction(
00400                             $this->conf['special.']['userFunc'],
00401                             array_merge($this->conf['special.'],array('_altSortField'=>$altSortField)),
00402                             ''
00403                         );
00404                         if (!is_array($temp))   $temp=array();
00405                     break;
00406                     case 'language':
00407                         $temp = array();
00408 
00409                             // Getting current page record NOT overlaid by any translation:
00410                         $currentPageWithNoOverlay = $this->sys_page->getRawRecord('pages',$GLOBALS['TSFE']->page['uid']);
00411 
00412                             // Traverse languages set up:
00413                         $languageItems = t3lib_div::intExplode(',',$value);
00414                         foreach($languageItems as $sUid)    {
00415                                 // Find overlay record:
00416                             if ($sUid)  {
00417                                 $lRecs = $this->sys_page->getPageOverlay($GLOBALS['TSFE']->page['uid'],$sUid);
00418                             } else $lRecs=array();
00419                                 // Checking if the "disabled" state should be set.
00420                             if (
00421                                         (t3lib_div::hideIfNotTranslated($GLOBALS['TSFE']->page['l18n_cfg']) && $sUid && !count($lRecs)) // Blocking for all translations?
00422                                     || ($GLOBALS['TSFE']->page['l18n_cfg']&1 && (!$sUid || !count($lRecs))) // Blocking default translation?
00423                                     || (!$this->conf['special.']['normalWhenNoLanguage'] && $sUid && !count($lRecs))
00424                                 )   {
00425                                 $iState = $GLOBALS['TSFE']->sys_language_uid==$sUid ? 'USERDEF2' : 'USERDEF1';
00426                             } else {
00427                                 $iState = $GLOBALS['TSFE']->sys_language_uid==$sUid ? 'ACT' : 'NO';
00428                             }
00429 
00430                             if ($this->conf['addQueryString'])  {
00431                                 $getVars = $this->parent_cObj->getQueryArguments($this->conf['addQueryString.'],array('L'=>$sUid),true);
00432                             } else {
00433                                 $getVars = '&L='.$sUid;
00434                             }
00435 
00436                                 // Adding menu item:
00437                             $temp[] = array_merge(
00438                                 array_merge($currentPageWithNoOverlay, $lRecs),
00439                                 array(
00440                                     'ITEM_STATE' => $iState,
00441                                     '_ADD_GETVARS' => $getVars,
00442                                     '_SAFE' => TRUE
00443                                 )
00444                             );
00445                         }
00446                     break;
00447                     case 'directory':
00448                         if ($value=='') {
00449                             $value=$GLOBALS['TSFE']->page['uid'];
00450                         }
00451                         $items=t3lib_div::intExplode(',',$value);
00452 
00453                         foreach($items as $id)  {
00454                             $MP = $this->tmpl->getFromMPmap($id);
00455 
00456                                 // Checking if a page is a mount page and if so, change the ID and set the MP var properly.
00457                             $mount_info = $this->sys_page->getMountPointInfo($id);
00458                             if (is_array($mount_info))  {
00459                                 if ($mount_info['overlay']) {   // Overlays should already have their full MPvars calculated:
00460                                     $MP = $this->tmpl->getFromMPmap($mount_info['mount_pid']);
00461                                     $MP = $MP ? $MP : $mount_info['MPvar'];
00462                                 } else {
00463                                     $MP = ($MP ? $MP.',' : '').$mount_info['MPvar'];
00464                                 }
00465                                 $id = $mount_info['mount_pid'];
00466                             }
00467 
00468                                 // Get sub-pages:
00469                             $res = $this->parent_cObj->exec_getQuery('pages',Array('pidInList'=>$id,'orderBy'=>$altSortField));
00470                             while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))  {
00471                                 $GLOBALS['TSFE']->sys_page->versionOL('pages',$row);
00472 
00473                                 if (is_array($row)) {
00474                                         // Keep mount point?
00475                                     $mount_info = $this->sys_page->getMountPointInfo($row['uid'], $row);
00476                                     if (is_array($mount_info) && $mount_info['overlay'])    {   // There is a valid mount point.
00477                                         $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!
00478                                         if (count($mp_row)) {
00479                                             $row = $mp_row;
00480                                             $row['_MP_PARAM'] = $mount_info['MPvar'];
00481                                         } 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!
00482                                     }
00483 
00484                                         // Add external MP params, then the row:
00485                                     if (is_array($row)) {
00486                                         if ($MP)    $row['_MP_PARAM'] = $MP.($row['_MP_PARAM'] ? ','.$row['_MP_PARAM'] : '');
00487                                         $temp[$row['uid']] = $this->sys_page->getPageOverlay($row);
00488                                     }
00489                                 }
00490                             }
00491                         }
00492                     break;
00493                     case 'list':
00494                         if ($value=='') {
00495                             $value=$this->id;
00496                         }
00497                         $loadDB = t3lib_div::makeInstance('FE_loadDBGroup');
00498                         $loadDB->start($value, 'pages');
00499                         $loadDB->additionalWhere['pages']=tslib_cObj::enableFields('pages');
00500                         $loadDB->getFromDB();
00501 
00502                         foreach($loadDB->itemArray as $val) {
00503                             $MP = $this->tmpl->getFromMPmap($val['id']);
00504 
00505                                 // Keep mount point?
00506                             $mount_info = $this->sys_page->getMountPointInfo($val['id']);
00507                             if (is_array($mount_info) && $mount_info['overlay'])    {   // There is a valid mount point.
00508                                 $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!
00509                                 if (count($mp_row)) {
00510                                     $row = $mp_row;
00511                                     $row['_MP_PARAM'] = $mount_info['MPvar'];
00512 
00513                                     if ($mount_info['overlay']) {   // Overlays should already have their full MPvars calculated:
00514                                         $MP = $this->tmpl->getFromMPmap($mount_info['mount_pid']);
00515                                         if ($MP) unset($row['_MP_PARAM']);
00516                                     }
00517                                 } 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!
00518                             } else {
00519                                 $row = $loadDB->results['pages'][$val['id']];
00520                             }
00521 
00522                                 //Add versioning overlay for current page (to respect workspaces)
00523                             if (is_array($row)) {
00524                                 $this->sys_page->versionOL('pages', $row, true);
00525                             }
00526 
00527                                 // Add external MP params, then the row:
00528                             if (is_array($row)) {
00529                                 if ($MP)    $row['_MP_PARAM'] = $MP.($row['_MP_PARAM'] ? ','.$row['_MP_PARAM'] : '');
00530                                 $temp[] = $this->sys_page->getPageOverlay($row);
00531                             }
00532                         }
00533                     break;
00534                     case 'updated':
00535                         if ($value=='') {
00536                             $value=$GLOBALS['TSFE']->page['uid'];
00537                         }
00538                         $items=t3lib_div::intExplode(',',$value);
00539                         if (t3lib_div::testInt($this->conf['special.']['depth']))   {
00540                             $depth = t3lib_div::intInRange($this->conf['special.']['depth'],1,20);      // Tree depth
00541                         } else {
00542                             $depth=20;
00543                         }
00544                         $limit = t3lib_div::intInRange($this->conf['special.']['limit'],0,100); // max number of items
00545                         $maxAge = intval(tslib_cObj::calc($this->conf['special.']['maxAge']));
00546                         if (!$limit)    $limit=10;
00547                         $mode = $this->conf['special.']['mode'];    // *'auto', 'manual', 'tstamp'
00548                             // Get id's
00549                         $id_list_arr = Array();
00550 
00551                         foreach($items as $id)  {
00552                             $bA = t3lib_div::intInRange($this->conf['special.']['beginAtLevel'],0,100);
00553                             $id_list_arr[] = tslib_cObj::getTreeList(-1*$id,$depth-1+$bA,$bA-1);
00554                         }
00555                         $id_list = implode(',',$id_list_arr);
00556                             // Get sortField (mode)
00557                         switch($mode)   {
00558                             case 'starttime':
00559                                 $sortField = 'starttime';
00560                             break;
00561                             case 'lastUpdated':
00562                             case 'manual':
00563                                 $sortField = 'lastUpdated';
00564                             break;
00565                             case 'tstamp':
00566                                 $sortField = 'tstamp';
00567                             break;
00568                             case 'crdate':
00569                                 $sortField = 'crdate';
00570                             break;
00571                             default:
00572                                 $sortField = 'SYS_LASTCHANGED';
00573                             break;
00574                         }
00575                             // Get
00576                         $extraWhere = ($this->conf['includeNotInMenu'] ? '' : ' AND pages.nav_hide=0').$this->getDoktypeExcludeWhere();
00577 
00578                         if ($this->conf['special.']['excludeNoSearchPages']) {
00579                             $extraWhere.= ' AND pages.no_search=0';
00580                         }
00581                         if ($maxAge>0)  {
00582                             $extraWhere.=' AND '.$sortField.'>'.($GLOBALS['SIM_ACCESS_TIME']-$maxAge);
00583                         }
00584 
00585                         $res = $this->parent_cObj->exec_getQuery('pages',Array('pidInList'=>'0', 'uidInList'=>$id_list, 'where'=>$sortField.'>=0'.$extraWhere, 'orderBy'=>($altSortFieldValue ? $altSortFieldValue : $sortField.' desc'),'max'=>$limit));
00586                         while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))  {
00587                             $GLOBALS['TSFE']->sys_page->versionOL('pages',$row);
00588                             if (is_array($row)) {
00589                                 $temp[$row['uid']]=$this->sys_page->getPageOverlay($row);
00590                             }
00591                         }
00592                     break;
00593                     case 'keywords':
00594                         list($value)=t3lib_div::intExplode(',',$value);
00595                         if (!$value) {
00596                             $value=$GLOBALS['TSFE']->page['uid'];
00597                         }
00598                         if ($this->conf['special.']['setKeywords'] || $this->conf['special.']['setKeywords.']) {
00599                             $kw = isset($this->conf['special.']['setKeywords.'])
00600                                 ? $this->parent_cObj->stdWrap($this->conf['special.']['setKeywords'], $this->conf['special.']['setKeywords.'])
00601                                 : $this->conf['special.']['setKeywords'];
00602                         } else {
00603                             $value_rec=$this->sys_page->getPage($value);    // The page record of the 'value'.
00604 
00605                             $kfieldSrc = $this->conf['special.']['keywordsField.']['sourceField'] ? $this->conf['special.']['keywordsField.']['sourceField'] : 'keywords';
00606                             $kw = trim(tslib_cObj::keywords($value_rec[$kfieldSrc]));       // keywords.
00607                         }
00608 
00609                         $mode = $this->conf['special.']['mode'];    // *'auto', 'manual', 'tstamp'
00610                         switch($mode)   {
00611                             case 'starttime':
00612                                 $sortField = 'starttime';
00613                             break;
00614                             case 'lastUpdated':
00615                             case 'manual':
00616                                 $sortField = 'lastUpdated';
00617                             break;
00618                             case 'tstamp':
00619                                 $sortField = 'tstamp';
00620                             break;
00621                             case 'crdate':
00622                                 $sortField = 'crdate';
00623                             break;
00624                             default:
00625                                 $sortField = 'SYS_LASTCHANGED';
00626                             break;
00627                         }
00628 
00629                             // depth, limit, extra where
00630                         if (t3lib_div::testInt($this->conf['special.']['depth']))   {
00631                             $depth = t3lib_div::intInRange($this->conf['special.']['depth'],0,20);      // Tree depth
00632                         } else {
00633                             $depth=20;
00634                         }
00635                         $limit = t3lib_div::intInRange($this->conf['special.']['limit'],0,100); // max number of items
00636                         $extraWhere = ' AND pages.uid!='.$value.($this->conf['includeNotInMenu'] ? '' : ' AND pages.nav_hide=0').$this->getDoktypeExcludeWhere();
00637                         if ($this->conf['special.']['excludeNoSearchPages']) {
00638                             $extraWhere.= ' AND pages.no_search=0';
00639                         }
00640                             // start point
00641                         $eLevel = tslib_cObj::getKey(
00642                             isset($this->conf['special.']['entryLevel.'])
00643                                 ? $this->parent_cObj->stdWrap($this->conf['special.']['entryLevel'], $this->conf['special.']['entryLevel.'])
00644                                 : $this->conf['special.']['entryLevel'],
00645                             $this->tmpl->rootLine
00646                         );
00647                         $startUid = intval($this->tmpl->rootLine[$eLevel]['uid']);
00648 
00649                             // which field is for keywords
00650                         $kfield = 'keywords';
00651                         if ( $this->conf['special.']['keywordsField'] ) {
00652                             list($kfield) = explode(' ',trim ($this->conf['special.']['keywordsField']));
00653                         }
00654 
00655                             // If there are keywords and the startuid is present.
00656                         if ($kw && $startUid)   {
00657                             $bA = t3lib_div::intInRange($this->conf['special.']['beginAtLevel'],0,100);
00658                             $id_list=tslib_cObj::getTreeList(-1*$startUid,$depth-1+$bA,$bA-1);
00659 
00660                             $kwArr = explode(',',$kw);
00661                             foreach($kwArr as $word)    {
00662                                 $word = trim($word);
00663                                 if ($word)  {
00664                                     $keyWordsWhereArr[] = $kfield.' LIKE \'%'.$GLOBALS['TYPO3_DB']->quoteStr($word, 'pages').'%\'';
00665                                 }
00666                             }
00667                             $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));
00668                             while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))  {
00669                                 $GLOBALS['TSFE']->sys_page->versionOL('pages',$row);
00670                                 if (is_array($row)) {
00671                                     $temp[$row['uid']]=$this->sys_page->getPageOverlay($row);
00672                                 }
00673                             }
00674                         }
00675                     break;
00676                     case 'rootline':
00677                         $range = isset($this->conf['special.']['range.'])
00678                             ? $this->parent_cObj->stdWrap($this->conf['special.']['range'], $this->conf['special.']['range.'])
00679                             : $this->conf['special.']['range'];
00680                         $begin_end = explode('|', $range);
00681                         $begin_end[0] = intval($begin_end[0]);
00682                         if (!t3lib_div::testInt($begin_end[1])) {
00683                             $begin_end[1] = -1;
00684                         }
00685 
00686                         $beginKey = tslib_cObj::getKey ($begin_end[0],$this->tmpl->rootLine);
00687                         $endKey = tslib_cObj::getKey ($begin_end[1],$this->tmpl->rootLine);
00688                         if ($endKey<$beginKey)  {$endKey=$beginKey;}
00689 
00690                         $rl_MParray = array();
00691                         foreach($this->tmpl->rootLine as $k_rl => $v_rl)    {
00692                                 // For overlaid mount points, set the variable right now:
00693                             if ($v_rl['_MP_PARAM'] && $v_rl['_MOUNT_OL'])   {
00694                                 $rl_MParray[] = $v_rl['_MP_PARAM'];
00695                             }
00696                                 // Traverse rootline:
00697                             if ($k_rl>=$beginKey && $k_rl<=$endKey) {
00698                                 $temp_key=$k_rl;
00699                                 $temp[$temp_key]=$this->sys_page->getPage($v_rl['uid']);
00700                                 if (count($temp[$temp_key]))    {
00701                                     if (!$temp[$temp_key]['target'])    {   // If there are no specific target for the page, put the level specific target on.
00702                                         $temp[$temp_key]['target'] = $this->conf['special.']['targets.'][$k_rl];
00703                                         $temp[$temp_key]['_MP_PARAM'] = implode(',',$rl_MParray);
00704                                     }
00705                                 } else unset($temp[$temp_key]);
00706                             }
00707                                 // For normal mount points, set the variable for next level.
00708                             if ($v_rl['_MP_PARAM'] && !$v_rl['_MOUNT_OL'])  {
00709                                 $rl_MParray[] = $v_rl['_MP_PARAM'];
00710                             }
00711                         }
00712                             // Reverse order of elements (e.g. "1,2,3,4" gets "4,3,2,1"):
00713                         if (isset($this->conf['special.']['reverseOrder']) && $this->conf['special.']['reverseOrder']) {
00714                             $temp = array_reverse($temp);
00715                             $rl_MParray = array_reverse($rl_MParray);
00716                         }
00717                     break;
00718                     case 'browse':
00719                         list($value)=t3lib_div::intExplode(',',$value);
00720                         if (!$value) {
00721                             $value=$GLOBALS['TSFE']->page['uid'];
00722                         }
00723                         if ($value!=$this->tmpl->rootLine[0]['uid'])    {   // Will not work out of rootline
00724                             $recArr=array();
00725                             $value_rec=$this->sys_page->getPage($value);    // The page record of the 'value'.
00726                             if ($value_rec['pid'])  {   // 'up' page cannot be outside rootline
00727                                 $recArr['up']=$this->sys_page->getPage($value_rec['pid']);  // The page record of 'up'.
00728                             }
00729                             if ($recArr['up']['pid'] && $value_rec['pid']!=$this->tmpl->rootLine[0]['uid']) {   // If the 'up' item was NOT level 0 in rootline...
00730                                 $recArr['index']=$this->sys_page->getPage($recArr['up']['pid']);    // The page record of "index".
00731                             }
00732 
00733                                 // prev / next is found
00734                             $prevnext_menu = $this->sys_page->getMenu($value_rec['pid'],'*',$altSortField);
00735                             $lastKey=0;
00736                             $nextActive=0;
00737                             foreach ($prevnext_menu as $k_b => $v_b) {
00738                                 if ($nextActive)    {
00739                                     $recArr['next']=$v_b;
00740                                     $nextActive=0;
00741                                 }
00742                                 if ($v_b['uid']==$value)    {
00743                                     if ($lastKey)   {
00744                                         $recArr['prev']=$prevnext_menu[$lastKey];
00745                                     }
00746                                     $nextActive=1;
00747                                 }
00748                                 $lastKey=$k_b;
00749                             }
00750                             reset($prevnext_menu);
00751                             $recArr['first']=pos($prevnext_menu);
00752                             end($prevnext_menu);
00753                             $recArr['last']=pos($prevnext_menu);
00754 
00755                                 // prevsection / nextsection is found
00756                             if (is_array($recArr['index'])) {   // You can only do this, if there is a valid page two levels up!
00757                                 $prevnextsection_menu = $this->sys_page->getMenu($recArr['index']['uid'],'*',$altSortField);
00758                                 $lastKey=0;
00759                                 $nextActive=0;
00760                                 foreach ($prevnextsection_menu as $k_b => $v_b) {
00761                                     if ($nextActive)    {
00762                                         $sectionRec_temp = $this->sys_page->getMenu($v_b['uid'],'*',$altSortField);
00763                                         if (count($sectionRec_temp))    {
00764                                             reset($sectionRec_temp);
00765                                             $recArr['nextsection']=pos($sectionRec_temp);
00766                                             end ($sectionRec_temp);
00767                                             $recArr['nextsection_last']=pos($sectionRec_temp);
00768                                             $nextActive=0;
00769                                         }
00770                                     }
00771                                     if ($v_b['uid']==$value_rec['pid']) {
00772                                         if ($lastKey)   {
00773                                             $sectionRec_temp = $this->sys_page->getMenu($prevnextsection_menu[$lastKey]['uid'],'*',$altSortField);
00774                                             if (count($sectionRec_temp))    {
00775                                                 reset($sectionRec_temp);
00776                                                 $recArr['prevsection']=pos($sectionRec_temp);
00777                                                 end ($sectionRec_temp);
00778                                                 $recArr['prevsection_last']=pos($sectionRec_temp);
00779                                             }
00780                                         }
00781                                         $nextActive=1;
00782                                     }
00783                                     $lastKey=$k_b;
00784                                 }
00785                             }
00786                             if ($this->conf['special.']['items.']['prevnextToSection']) {
00787                                 if (!is_array($recArr['prev']) && is_array($recArr['prevsection_last']))    {
00788                                     $recArr['prev']=$recArr['prevsection_last'];
00789                                 }
00790                                 if (!is_array($recArr['next']) && is_array($recArr['nextsection'])) {
00791                                     $recArr['next']=$recArr['nextsection'];
00792                                 }
00793                             }
00794 
00795                             $items = explode('|',$this->conf['special.']['items']);
00796                             $c=0;
00797                             foreach ($items as $k_b => $v_b) {
00798                                 $v_b=strtolower(trim($v_b));
00799                                 if (intval($this->conf['special.'][$v_b.'.']['uid']))   {
00800                                     $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
00801                                 }
00802                                 if (is_array($recArr[$v_b]))    {
00803                                     $temp[$c]=$recArr[$v_b];
00804                                     if ($this->conf['special.'][$v_b.'.']['target'])    {
00805                                         $temp[$c]['target']=$this->conf['special.'][$v_b.'.']['target'];
00806                                     }
00807                                     $tmpSpecialFields = $this->conf['special.'][$v_b.'.']['fields.'];
00808                                     if (is_array($tmpSpecialFields)) {
00809                                         foreach ($tmpSpecialFields as $fk => $val) {
00810                                             $temp[$c][$fk]=$val;
00811                                         }
00812                                     }
00813                                     $c++;
00814                                 }
00815                             }
00816                         }
00817                     break;
00818                 }
00819             } elseif (is_array($this->alternativeMenuTempArray))    {   // Setting $temp array if not level 1.
00820                 $temp = $this->alternativeMenuTempArray;
00821             } elseif ($this->mconf['sectionIndex']) {
00822                 if ($GLOBALS['TSFE']->sys_language_uid && count($this->sys_page->getPageOverlay($this->id)))    {
00823                     $sys_language_uid = intval($GLOBALS['TSFE']->sys_language_uid);
00824                 } else $sys_language_uid=0;
00825 
00826                 $selectSetup = Array(
00827                     'pidInList'=>$this->id,
00828                     'orderBy'=>$altSortField,
00829                     'where' => 'colPos=0 AND sys_language_uid='.$sys_language_uid,
00830                     'andWhere' => 'sectionIndex!=0'
00831                     );
00832                 switch($this->mconf['sectionIndex.']['type'])   {
00833                     case 'all':
00834                         unset($selectSetup['andWhere']);
00835                     break;
00836                     case 'header':
00837                         $selectSetup['andWhere'] .= ' AND header_layout!=100 AND header!=""';
00838                     break;
00839                 }
00840                 $basePageRow=$this->sys_page->getPage($this->id);
00841                 if (is_array($basePageRow)) {
00842                     $res = $this->parent_cObj->exec_getQuery('tt_content',  $selectSetup);
00843                     while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))  {
00844                         $GLOBALS['TSFE']->sys_page->versionOL('tt_content',$row);
00845 
00846                         if (is_array($row)) {
00847                             $temp[$row['uid']] = $basePageRow;
00848                             $temp[$row['uid']]['title'] = $row['header'];
00849                             $temp[$row['uid']]['nav_title'] = $row['header'];
00850                             $temp[$row['uid']]['subtitle'] = $row['subheader'];
00851                             $temp[$row['uid']]['starttime'] = $row['starttime'];
00852                             $temp[$row['uid']]['endtime'] = $row['endtime'];
00853                             $temp[$row['uid']]['fe_group'] = $row['fe_group'];
00854                             $temp[$row['uid']]['media'] = $row['media'];
00855 
00856                             $temp[$row['uid']]['header_layout'] = $row['header_layout'];
00857                             $temp[$row['uid']]['bodytext'] = $row['bodytext'];
00858                             $temp[$row['uid']]['image'] = $row['image'];
00859 
00860                             $temp[$row['uid']]['sectionIndex_uid'] = $row['uid'];
00861                         }
00862                     }
00863                 }
00864             } else {    // Default:
00865                 $temp = $this->sys_page->getMenu($this->id,'*',$altSortField);      // gets the menu
00866             }
00867 
00868             $c=0;
00869             $c_b=0;
00870             $minItems = intval($this->mconf['minItems'] ? $this->mconf['minItems'] : $this->conf['minItems']);
00871             $maxItems = intval($this->mconf['maxItems'] ? $this->mconf['maxItems'] : $this->conf['maxItems']);
00872             $begin = tslib_cObj::calc($this->mconf['begin'] ? $this->mconf['begin'] : $this->conf['begin']);
00873 
00874             $banUidArray = $this->getBannedUids();
00875 
00876                 // Fill in the menuArr with elements that should go into the menu:
00877             $this->menuArr = Array();
00878             foreach($temp as $data) {
00879                 $spacer = (t3lib_div::inList($this->spacerIDList,$data['doktype']) || !strcmp($data['ITEM_STATE'],'SPC')) ? 1 : 0;      // if item is a spacer, $spacer is set
00880                 if ($this->filterMenuPages($data, $banUidArray, $spacer))   {
00881                     $c_b++;
00882                     if ($begin<=$c_b)   {       // If the beginning item has been reached.
00883                         $this->menuArr[$c] = $data;
00884                         $this->menuArr[$c]['isSpacer'] = $spacer;
00885                         $c++;
00886                         if ($maxItems && $c>=$maxItems) {
00887                             break;
00888                         }
00889                     }
00890                 }
00891             }
00892 
00893                 // Fill in fake items, if min-items is set.
00894             if ($minItems)  {
00895                 while($c<$minItems) {
00896                     $this->menuArr[$c] = Array(
00897                         'title' => '...',
00898                         'uid' => $GLOBALS['TSFE']->id
00899                     );
00900                     $c++;
00901                 }
00902             }
00903                 // Setting number of menu items
00904             $GLOBALS['TSFE']->register['count_menuItems'] = count($this->menuArr);
00905                 //  Passing the menuArr through a user defined function:
00906             if ($this->mconf['itemArrayProcFunc'])  {
00907                 if (!is_array($this->parentMenuArr)) {$this->parentMenuArr=array();}
00908                 $this->menuArr = $this->userProcess('itemArrayProcFunc',$this->menuArr);
00909             }
00910             $this->hash = md5(serialize($this->menuArr).serialize($this->mconf).serialize($this->tmpl->rootLine).serialize($this->MP_array));
00911 
00912                 // Get the cache timeout:
00913             if ($this->conf['cache_period']) {
00914                 $cacheTimeout = $this->conf['cache_period'];
00915             } else {
00916                 $cacheTimeout = $GLOBALS['TSFE']->get_cache_timeout();
00917             }
00918 
00919             $serData = $this->sys_page->getHash($this->hash);
00920             if (!$serData)  {
00921                 $this->generate();
00922                 $this->sys_page->storeHash($this->hash, serialize($this->result), 'MENUDATA', $cacheTimeout);
00923             } else {
00924                 $this->result = unserialize($serData);
00925             }
00926 
00927                 // End showAccessRestrictedPages
00928             if ($this->mconf['showAccessRestrictedPages'])  {
00929                     // RESTORING where_groupAccess
00930                 $this->sys_page->where_groupAccess = $SAVED_where_groupAccess;
00931             }
00932         }
00933     }
00934 
00935     /**
00936      * Includes the PHP script defined for the HMENU special type "userdefined".
00937      * This script is supposed to populate the array $menuItemsArray with a set of page records comprising the menu.
00938      * The "userdefined" type is deprecated since "userfunction" has arrived since and is a better choice for many reasons (like using classes/functions for rendering the menu)
00939      *
00940      * @param   array       TypoScript parameters for "special.". In particular the property "file" is reserved and specifies the file to include. Seems like any other property can be used freely by the script.
00941      * @param   string      The sorting field. Can be used from the script in the $incFile.
00942      * @return  array       An array with the menu items
00943      * @deprecated since TYPO3 3.6, this function will be removed in TYPO3 4.6, use HMENU of type "userfunction" instead of "userdefined"
00944      * @access private
00945      */
00946     function includeMakeMenu($conf,$altSortField)   {
00947         t3lib_div::logDeprecatedFunction();
00948 
00949         $incFile = $GLOBALS['TSFE']->tmpl->getFileName($conf['file']);
00950         if ($incFile && $GLOBALS['TSFE']->checkFileInclude($incFile))   {
00951             include($incFile);
00952         }
00953         return is_array($menuItemsArray) ? $menuItemsArray : array();
00954     }
00955 
00956     /**
00957      * 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.
00958      *
00959      * @param   array       Array of menu items
00960      * @param   array       Array of page uids which are to be excluded
00961      * @param   boolean     If set, then the page is a spacer.
00962      * @return  boolean     Returns true if the page can be safely included.
00963      */
00964     function filterMenuPages(&$data,$banUidArray,$spacer)   {
00965 
00966         $includePage = TRUE;
00967         if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/tslib/class.tslib_menu.php']['filterMenuPages'])) {
00968             foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/tslib/class.tslib_menu.php']['filterMenuPages'] as $classRef) {
00969                 $hookObject = t3lib_div::getUserObj($classRef);
00970 
00971                 if (!($hookObject instanceof tslib_menu_filterMenuPagesHook)) {
00972                     throw new UnexpectedValueException('$hookObject must implement interface tslib_menu_filterMenuPagesHook', 1269877402);
00973                 }
00974 
00975                 $includePage = $includePage && $hookObject->tslib_menu_filterMenuPagesHook($data, $banUidArray, $spacer, $this);
00976             }
00977         }
00978         if (!$includePage) {
00979             return FALSE;
00980         }
00981 
00982         if ($data['_SAFE']) return TRUE;
00983 
00984         $uid = $data['uid'];
00985         if ($this->mconf['SPC'] || !$spacer)    {   // If the spacer-function is not enabled, spacers will not enter the $menuArr
00986             if (!t3lib_div::inList($this->doktypeExcludeList,$data['doktype'])) {       // Page may not be 'not_in_menu' or 'Backend User Section'
00987                 if (!$data['nav_hide'] || $this->conf['includeNotInMenu'])  {   // Not hidden in navigation
00988                     if (!t3lib_div::inArray($banUidArray,$uid)) {   // not in banned uid's
00989 
00990                             // Checks if the default language version can be shown:
00991                             // Block page is set, if l18n_cfg allows plus: 1) Either default language or 2) another language but NO overlay record set for page!
00992                         $blockPage = $data['l18n_cfg']&1 && (!$GLOBALS['TSFE']->sys_language_uid || ($GLOBALS['TSFE']->sys_language_uid && !$data['_PAGES_OVERLAY']));
00993                         if (!$blockPage)    {
00994 
00995                                 // Checking if a page should be shown in the menu depending on whether a translation exists:
00996                             $tok = TRUE;
00997                             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:
00998                                 if (!$data['_PAGES_OVERLAY'])   {
00999                                     $tok = FALSE;
01000                                 }
01001                             }
01002 
01003                                 // Continue if token is true:
01004                             if ($tok)   {
01005 
01006                                     // Checking if "&L" should be modified so links to non-accessible pages will not happen.
01007                                 if ($this->conf['protectLvar']) {
01008                                     $languageUid = intval($GLOBALS['TSFE']->config['config']['sys_language_uid']);
01009                                     if ($languageUid && ($this->conf['protectLvar']=='all' || t3lib_div::hideIfNotTranslated($data['l18n_cfg'])))   {
01010                                         $olRec = $GLOBALS['TSFE']->sys_page->getPageOverlay($data['uid'], $languageUid);
01011                                         if (!count($olRec)) {
01012                                                 // 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"
01013                                             $data['_ADD_GETVARS'].= '&L=0';
01014                                         }
01015                                     }
01016                                 }
01017 
01018                                 return TRUE;
01019                             }
01020                         }
01021                     }
01022                 }
01023             }
01024         }
01025     }
01026 
01027     /**
01028      * 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)
01029      * 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.
01030      * 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.
01031      *
01032      * @param   integer     Number of menu items in the menu
01033      * @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)
01034      * @access private
01035      */
01036     function procesItemStates($splitCount)  {
01037 
01038             // Prepare normal settings
01039         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.
01040         $NOconf = $this->tmpl->splitConfArray($this->mconf['NO.'],$splitCount);
01041 
01042             // Prepare rollOver settings, overriding normal settings
01043         $ROconf=array();
01044         if ($this->mconf['RO']) {
01045             $ROconf = $this->tmpl->splitConfArray($this->mconf['RO.'],$splitCount);
01046         }
01047 
01048             // Prepare IFSUB settings, overriding normal settings
01049             // IFSUB is true if there exist submenu items to the current item
01050         if ($this->mconf['IFSUB'])  {
01051             $IFSUBinit = 0; // Flag: If $IFSUB is generated
01052             foreach ($NOconf as $key => $val) {
01053                 if ($this->isItemState('IFSUB',$key))   {
01054                     if (!$IFSUBinit)    {   // if this is the first IFSUB element, we must generate IFSUB.
01055                         $IFSUBconf = $this->tmpl->splitConfArray($this->mconf['IFSUB.'],$splitCount);
01056                         if ($this->mconf['IFSUBRO'])    {
01057                             $IFSUBROconf = $this->tmpl->splitConfArray($this->mconf['IFSUBRO.'],$splitCount);
01058                         }
01059                         $IFSUBinit = 1;
01060                     }
01061                     $NOconf[$key] = $IFSUBconf[$key];       // Substitute normal with ifsub
01062                     if ($ROconf)    {   // If rollOver on normal, we must apply a state for rollOver on the active
01063                         $ROconf[$key] = $IFSUBROconf[$key] ? $IFSUBROconf[$key] : $IFSUBconf[$key];     // If RollOver on active then apply this
01064                     }
01065                 }
01066             }
01067         }
01068             // Prepare active settings, overriding normal settings
01069         if ($this->mconf['ACT'])    {
01070             $ACTinit = 0;   // Flag: If $ACT is generated
01071             foreach ($NOconf as $key => $val) { // Find active
01072                 if ($this->isItemState('ACT',$key)) {
01073                     if (!$ACTinit)  {   // if this is the first 'active', we must generate ACT.
01074                         $ACTconf = $this->tmpl->splitConfArray($this->mconf['ACT.'],$splitCount);
01075                             // Prepare active rollOver settings, overriding normal active settings
01076                         if ($this->mconf['ACTRO'])  {
01077                             $ACTROconf = $this->tmpl->splitConfArray($this->mconf['ACTRO.'],$splitCount);
01078                         }
01079                         $ACTinit = 1;
01080                     }
01081                     $NOconf[$key] = $ACTconf[$key];     // Substitute normal with active
01082                     if ($ROconf)    {   // If rollOver on normal, we must apply a state for rollOver on the active
01083                         $ROconf[$key] = $ACTROconf[$key] ? $ACTROconf[$key] : $ACTconf[$key];       // If RollOver on active then apply this
01084                     }
01085                 }
01086             }
01087         }
01088             // Prepare ACT (active)/IFSUB settings, overriding normal settings
01089             // ACTIFSUB is true if there exist submenu items to the current item and the current item is active
01090         if ($this->mconf['ACTIFSUB'])   {
01091             $ACTIFSUBinit = 0;  // Flag: If $ACTIFSUB is generated
01092             foreach ($NOconf as $key => $val) { // Find active
01093                 if ($this->isItemState('ACTIFSUB',$key))    {
01094                     if (!$ACTIFSUBinit) {   // if this is the first 'active', we must generate ACTIFSUB.
01095                         $ACTIFSUBconf = $this->tmpl->splitConfArray($this->mconf['ACTIFSUB.'],$splitCount);
01096                             // Prepare active rollOver settings, overriding normal active settings
01097                         if ($this->mconf['ACTIFSUBRO']) {
01098                             $ACTIFSUBROconf = $this->tmpl->splitConfArray($this->mconf['ACTIFSUBRO.'],$splitCount);
01099                         }
01100                         $ACTIFSUBinit = 1;
01101                     }
01102                     $NOconf[$key] = $ACTIFSUBconf[$key];        // Substitute normal with active
01103                     if ($ROconf)    {   // If rollOver on normal, we must apply a state for rollOver on the active
01104                         $ROconf[$key] = $ACTIFSUBROconf[$key] ? $ACTIFSUBROconf[$key] : $ACTIFSUBconf[$key];        // If RollOver on active then apply this
01105                     }
01106                 }
01107             }
01108         }
01109             // Prepare CUR (current) settings, overriding normal settings
01110             // CUR is true if the current page equals the item here!
01111         if ($this->mconf['CUR'])    {
01112             $CURinit = 0;   // Flag: If $CUR is generated
01113             foreach ($NOconf as $key => $val) {
01114                 if ($this->isItemState('CUR',$key)) {
01115                     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)
01116                         $CURconf = $this->tmpl->splitConfArray($this->mconf['CUR.'],$splitCount);
01117                         if ($this->mconf['CURRO'])  {
01118                             $CURROconf = $this->tmpl->splitConfArray($this->mconf['CURRO.'],$splitCount);
01119                         }
01120                         $CURinit = 1;
01121                     }
01122                     $NOconf[$key] = $CURconf[$key];     // Substitute normal with current
01123                     if ($ROconf)    {   // If rollOver on normal, we must apply a state for rollOver on the active
01124                         $ROconf[$key] = $CURROconf[$key] ? $CURROconf[$key] : $CURconf[$key];       // If RollOver on active then apply this
01125                     }
01126                 }
01127             }
01128         }
01129             // Prepare CUR (current)/IFSUB settings, overriding normal settings
01130             // CURIFSUB is true if there exist submenu items to the current item and the current page equals the item here!
01131         if ($this->mconf['CURIFSUB'])   {
01132             $CURIFSUBinit = 0;  // Flag: If $CURIFSUB is generated
01133             foreach ($NOconf as $key => $val) {
01134                 if ($this->isItemState('CURIFSUB',$key))    {
01135                     if (!$CURIFSUBinit) {   // if this is the first 'current', we must generate CURIFSUB.
01136                         $CURIFSUBconf = $this->tmpl->splitConfArray($this->mconf['CURIFSUB.'],$splitCount);
01137                             // Prepare current rollOver settings, overriding normal current settings
01138                         if ($this->mconf['CURIFSUBRO']) {
01139                             $CURIFSUBROconf = $this->tmpl->splitConfArray($this->mconf['CURIFSUBRO.'],$splitCount);
01140                         }
01141                         $CURIFSUBinit = 1;
01142                     }
01143                     $NOconf[$key] = $CURIFSUBconf[$key];        // Substitute normal with active
01144                     if ($ROconf)    {   // If rollOver on normal, we must apply a state for rollOver on the current
01145                         $ROconf[$key] = $CURIFSUBROconf[$key] ? $CURIFSUBROconf[$key] : $CURIFSUBconf[$key];        // If RollOver on current then apply this
01146                     }
01147                 }
01148             }
01149         }
01150             // Prepare active settings, overriding normal settings
01151         if ($this->mconf['USR'])    {
01152             $USRinit = 0;   // Flag: If $USR is generated
01153             foreach ($NOconf as $key => $val) { // Find active
01154                 if ($this->isItemState('USR',$key)) {
01155                     if (!$USRinit)  {   // if this is the first active, we must generate USR.
01156                         $USRconf = $this->tmpl->splitConfArray($this->mconf['USR.'],$splitCount);
01157                             // Prepare active rollOver settings, overriding normal active settings
01158                         if ($this->mconf['USRRO'])  {
01159                             $USRROconf = $this->tmpl->splitConfArray($this->mconf['USRRO.'],$splitCount);
01160                         }
01161                         $USRinit = 1;
01162                     }
01163                     $NOconf[$key] = $USRconf[$key];     // Substitute normal with active
01164                     if ($ROconf)    {   // If rollOver on normal, we must apply a state for rollOver on the active
01165                         $ROconf[$key] = $USRROconf[$key] ? $USRROconf[$key] : $USRconf[$key];       // If RollOver on active then apply this
01166                     }
01167                 }
01168             }
01169         }
01170             // Prepare spacer settings, overriding normal settings
01171         if ($this->mconf['SPC'])    {
01172             $SPCinit = 0;   // Flag: If $SPC is generated
01173             foreach ($NOconf as $key => $val) { // Find spacers
01174                 if ($this->isItemState('SPC',$key)) {
01175                     if (!$SPCinit)  {   // if this is the first spacer, we must generate SPC.
01176                         $SPCconf = $this->tmpl->splitConfArray($this->mconf['SPC.'],$splitCount);
01177                         $SPCinit = 1;
01178                     }
01179                     $NOconf[$key] = $SPCconf[$key];     // Substitute normal with spacer
01180                 }
01181             }
01182         }
01183             // Prepare Userdefined settings
01184         if ($this->mconf['USERDEF1'])   {
01185             $USERDEF1init = 0;  // Flag: If $USERDEF1 is generated
01186             foreach ($NOconf as $key => $val) { // Find active
01187                 if ($this->isItemState('USERDEF1',$key))    {
01188                     if (!$USERDEF1init) {   // if this is the first active, we must generate USERDEF1.
01189                         $USERDEF1conf = $this->tmpl->splitConfArray($this->mconf['USERDEF1.'],$splitCount);
01190                             // Prepare active rollOver settings, overriding normal active settings
01191                         if ($this->mconf['USERDEF1RO']) {
01192                             $USERDEF1ROconf = $this->tmpl->splitConfArray($this->mconf['USERDEF1RO.'],$splitCount);
01193                         }
01194                         $USERDEF1init = 1;
01195                     }
01196                     $NOconf[$key] = $USERDEF1conf[$key];        // Substitute normal with active
01197                     if ($ROconf)    {   // If rollOver on normal, we must apply a state for rollOver on the active
01198                         $ROconf[$key] = $USERDEF1ROconf[$key] ? $USERDEF1ROconf[$key] : $USERDEF1conf[$key];        // If RollOver on active then apply this
01199                     }
01200                 }
01201             }
01202         }
01203             // Prepare Userdefined settings
01204         if ($this->mconf['USERDEF2'])   {
01205             $USERDEF2init = 0;  // Flag: If $USERDEF2 is generated
01206             foreach ($NOconf as $key => $val) { // Find active
01207                 if ($this->isItemState('USERDEF2',$key))    {
01208                     if (!$USERDEF2init) {   // if this is the first active, we must generate USERDEF2.
01209                         $USERDEF2conf = $this->tmpl->splitConfArray($this->mconf['USERDEF2.'],$splitCount);
01210                             // Prepare active rollOver settings, overriding normal active settings
01211                         if ($this->mconf['USERDEF2RO']) {
01212                             $USERDEF2ROconf = $this->tmpl->splitConfArray($this->mconf['USERDEF2RO.'],$splitCount);
01213                         }
01214                         $USERDEF2init = 1;
01215                     }
01216                     $NOconf[$key] = $USERDEF2conf[$key];        // Substitute normal with active
01217                     if ($ROconf)    {   // If rollOver on normal, we must apply a state for rollOver on the active
01218                         $ROconf[$key] = $USERDEF2ROconf[$key] ? $USERDEF2ROconf[$key] : $USERDEF2conf[$key];        // If RollOver on active then apply this
01219                     }
01220                 }
01221             }
01222         }
01223 
01224         return array($NOconf,$ROconf);
01225     }
01226 
01227     /**
01228      * 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
01229      * This function doesn't care about the url, because if we let the url be redirected, it will be logged in the stat!!!
01230      *
01231      * @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)
01232      * @param   string      Alternative target
01233      * @param   integer     Alternative type
01234      * @return  array       Returns an array with A-tag attributes as key/value pairs (HREF, TARGET and onClick)
01235      * @access private
01236      */
01237     function link($key,$altTarget='',$typeOverride='') {
01238 
01239             // Mount points:
01240         $MP_var = $this->getMPvar($key);
01241         $MP_params = $MP_var ? '&MP='.rawurlencode($MP_var) : '';
01242 
01243             // Setting override ID
01244         if ($this->mconf['overrideId'] || $this->menuArr[$key]['overrideId'])   {
01245             $overrideArray = array();
01246                 // If a user script returned the value overrideId in the menu array we use that as page id
01247             $overrideArray['uid'] = $this->mconf['overrideId']?$this->mconf['overrideId']:$this->menuArr[$key]['overrideId'];
01248             $overrideArray['alias'] = '';
01249             $MP_params = '';    // clear MP parameters since ID was changed.
01250         } else {
01251             $overrideArray='';
01252         }
01253 
01254             // Setting main target:
01255         $mainTarget = $altTarget ? $altTarget : $this->mconf['target'];
01256 
01257             // Creating link:
01258         if ($this->mconf['collapse'] && $this->isActive($this->menuArr[$key]['uid'], $this->getMPvar($key)))    {
01259             $thePage = $this->sys_page->getPage($this->menuArr[$key]['pid']);
01260             $LD = $this->menuTypoLink($thePage,$mainTarget,'','',$overrideArray, $this->mconf['addParams'].$MP_params.$this->menuArr[$key]['_ADD_GETVARS'], $typeOverride);
01261         } else {
01262             $LD = $this->menuTypoLink($this->menuArr[$key],$mainTarget,'','',$overrideArray, $this->mconf['addParams'].$MP_params.$this->I['val']['additionalParams'].$this->menuArr[$key]['_ADD_GETVARS'], $typeOverride);
01263         }
01264 
01265             // Override URL if using "External URL" as doktype with a valid e-mail address:
01266         if ($this->menuArr[$key]['doktype'] == t3lib_pageSelect::DOKTYPE_LINK && $this->menuArr[$key]['urltype'] == 3 && t3lib_div::validEmail($this->menuArr[$key]['url'])) {
01267                 // Create mailto-link using tslib_cObj::typolink (concerning spamProtectEmailAddresses):
01268             $LD['totalURL'] = $this->parent_cObj->typoLink_URL(array('parameter' => $this->menuArr[$key]['url']));
01269             $LD['target'] = '';
01270         }
01271 
01272             // Manipulation in case of access restricted pages:
01273         $this->changeLinksForAccessRestrictedPages($LD,$this->menuArr[$key],$mainTarget,$typeOverride);
01274 
01275             // Overriding URL / Target if set to do so:
01276         if ($this->menuArr[$key]['_OVERRIDE_HREF']) {
01277             $LD['totalURL'] = $this->menuArr[$key]['_OVERRIDE_HREF'];
01278             if ($this->menuArr[$key]['_OVERRIDE_TARGET'])   $LD['target'] = $this->menuArr[$key]['_OVERRIDE_TARGET'];
01279         }
01280 
01281             // OnClick open in windows.
01282         $onClick='';
01283         if ($this->mconf['JSWindow'])   {
01284             $conf=$this->mconf['JSWindow.'];
01285             $url=$LD['totalURL'];
01286             $LD['totalURL'] = '#';
01287             $onClick= 'openPic(\''.$GLOBALS['TSFE']->baseUrlWrap($url).'\',\''.($conf['newWindow']?md5($url):'theNewPage').'\',\''.$conf['params'].'\'); return false;';
01288             $GLOBALS['TSFE']->setJS('openPic');
01289         }
01290 
01291             // look for type and popup
01292             // following settings are valid in field target:
01293             // 230                              will add type=230 to the link
01294             // 230 500x600                      will add type=230 to the link and open in popup window with 500x600 pixels
01295             // 230 _blank                       will add type=230 to the link and open with target "_blank"
01296             // 230x450:resizable=0,location=1   will open in popup window with 500x600 pixels with settings "resizable=0,location=1"
01297         $matches = array();
01298         $targetIsType = $LD['target'] && (string) intval($LD['target']) == trim($LD['target']) ? intval($LD['target']) : FALSE;
01299         if (preg_match('/([0-9]+[\s])?(([0-9]+)x([0-9]+))?(:.+)?/s', $LD['target'], $matches) || $targetIsType) {
01300                 // has type?
01301             if(intval($matches[1]) || $targetIsType) {
01302                 $LD['totalURL'] .= '&type=' . ($targetIsType ?  $targetIsType : intval($matches[1]));
01303                 $LD['target'] = $targetIsType ?  '' : trim(substr($LD['target'], strlen($matches[1]) + 1));
01304             }
01305                 // open in popup window?
01306             if ($matches[3] && $matches[4]) {
01307                 $JSparamWH = 'width=' . $matches[3] . ',height=' . $matches[4] . ($matches[5] ? ',' . substr($matches[5], 1) : '');
01308                 $onClick = 'vHWin=window.open(\'' . $LD['totalURL'] . '\',\'FEopenLink\',\'' . $JSparamWH . '\');vHWin.focus();return false;';
01309                 $LD['target'] = '';
01310             }
01311         }
01312 
01313             // out:
01314         $list = array();
01315         $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.
01316         $list['TARGET'] = $LD['target'];
01317         $list['onClick'] = $onClick;
01318 
01319         return $list;
01320     }
01321 
01322     /**
01323      * Will change $LD (passed by reference) if the page is access restricted
01324      *
01325      * @param   array       $LD, the array from the linkData() function
01326      * @param   array       Page array
01327      * @param   string      Main target value
01328      * @param   string      Type number override if any
01329      * @return  void        ($LD passed by reference might be changed.)
01330      */
01331     function changeLinksForAccessRestrictedPages(&$LD, $page, $mainTarget, $typeOverride)   {
01332 
01333             // If access restricted pages should be shown in menus, change the link of such pages to link to a redirection page:
01334         if ($this->mconf['showAccessRestrictedPages'] && $this->mconf['showAccessRestrictedPages']!=='NONE' && !$GLOBALS['TSFE']->checkPageGroupAccess($page))  {
01335             $thePage = $this->sys_page->getPage($this->mconf['showAccessRestrictedPages']);
01336 
01337             $addParams = $this->mconf['showAccessRestrictedPages.']['addParams'];
01338             $addParams = str_replace('###RETURN_URL###',rawurlencode($LD['totalURL']),$addParams);
01339             $addParams = str_replace('###PAGE_ID###',$page['uid'],$addParams);
01340             $LD = $this->menuTypoLink($thePage,$mainTarget,'','','', $addParams, $typeOverride);
01341         }
01342     }
01343 
01344     /**
01345      * Creates a submenu level to the current level - if configured for.
01346      *
01347      * @param   integer     Page id of the current page for which a submenu MAY be produced (if conditions are met)
01348      * @param   string      Object prefix, see ->start()
01349      * @return  string      HTML content of the submenu
01350      * @access private
01351      */
01352     function subMenu($uid, $objSuffix='')   {
01353 
01354             // Setting alternative menu item array if _SUB_MENU has been defined in the current ->menuArr
01355         $altArray = '';
01356         if (is_array($this->menuArr[$this->I['key']]['_SUB_MENU']) && count($this->menuArr[$this->I['key']]['_SUB_MENU']))  {
01357             $altArray = $this->menuArr[$this->I['key']]['_SUB_MENU'];
01358         }
01359 
01360             // Make submenu if the page is the next active
01361         $cls = strtolower($this->conf[($this->menuNumber+1).$objSuffix]);
01362         $subLevelClass = ($cls && t3lib_div::inList($this->tmpl->menuclasses,$cls)) ? $cls : '';
01363 
01364             // stdWrap for expAll
01365         if (isset($this->mconf['expAll.'])) {
01366             $this->mconf['expAll'] = $this->parent_cObj->stdWrap($this->mconf['expAll'], $this->mconf['expAll.']);
01367         }
01368 
01369         if ($subLevelClass && ($this->mconf['expAll'] || $this->isNext($uid, $this->getMPvar($this->I['key'])) || is_array($altArray)) && !$this->mconf['sectionIndex'])    {
01370             $submenu = t3lib_div::makeInstance('tslib_'.$subLevelClass);
01371             $submenu->entryLevel = $this->entryLevel+1;
01372             $submenu->rL_uidRegister = $this->rL_uidRegister;
01373             $submenu->MP_array = $this->MP_array;
01374             if ($this->menuArr[$this->I['key']]['_MP_PARAM'])   {
01375                 $submenu->MP_array[] = $this->menuArr[$this->I['key']]['_MP_PARAM'];
01376             }
01377 
01378                 // especially scripts that build the submenu needs the parent data
01379             $submenu->parent_cObj = $this->parent_cObj;
01380             $submenu->parentMenuArr = $this->menuArr;
01381 
01382                 // Setting alternativeMenuTempArray (will be effective only if an array)
01383             if (is_array($altArray))    {
01384                 $submenu->alternativeMenuTempArray = $altArray;
01385             }
01386 
01387             if ($submenu->start($this->tmpl, $this->sys_page, $uid, $this->conf, $this->menuNumber+1, $objSuffix))  {
01388                 $submenu->makeMenu();
01389                     // Memorize the current menu item count
01390                 $tempCountMenuObj = $GLOBALS['TSFE']->register['count_MENUOBJ'];
01391                     // Reset the menu item count for the submenu
01392                 $GLOBALS['TSFE']->register['count_MENUOBJ'] = 0;
01393                 $content = $submenu->writeMenu();
01394                     // Restore the item count now that the submenu has been handled
01395                 $GLOBALS['TSFE']->register['count_MENUOBJ'] = $tempCountMenuObj;
01396                 $GLOBALS['TSFE']->register['count_menuItems'] = count($this->menuArr);
01397                 return $content;
01398             }
01399         }
01400     }
01401 
01402     /**
01403      * Returns true if the page with UID $uid is the NEXT page in root line (which means a submenu should be drawn)
01404      *
01405      * @param   integer     Page uid to evaluate.
01406      * @param   string      MPvar for the current position of item.
01407      * @return  boolean     True if page with $uid is active
01408      * @access private
01409      * @see subMenu()
01410      */
01411     function isNext($uid, $MPvar='')    {
01412 
01413             // Check for always active PIDs:
01414         if (count($this->alwaysActivePIDlist) && in_array($uid,$this->alwaysActivePIDlist)) {
01415             return TRUE;
01416         }
01417 
01418         $testUid = $uid.($MPvar?':'.$MPvar:'');
01419         if ($uid && $testUid==$this->nextActive)    {
01420             return TRUE;
01421         }
01422     }
01423 
01424     /**
01425      * Returns true if the page with UID $uid is active (in the current rootline)
01426      *
01427      * @param   integer     Page uid to evaluate.
01428      * @param   string      MPvar for the current position of item.
01429      * @return  boolean     True if page with $uid is active
01430      * @access private
01431      */
01432     function isActive($uid, $MPvar='')  {
01433 
01434             // Check for always active PIDs:
01435         if (count($this->alwaysActivePIDlist) && in_array($uid,$this->alwaysActivePIDlist)) {
01436             return TRUE;
01437         }
01438 
01439         $testUid = $uid.($MPvar?':'.$MPvar:'');
01440         if ($uid && in_array('ITEM:'.$testUid, $this->rL_uidRegister))  {
01441             return TRUE;
01442         }
01443     }
01444 
01445     /**
01446      * Returns true if the page with UID $uid is the CURRENT page (equals $GLOBALS['TSFE']->id)
01447      *
01448      * @param   integer     Page uid to evaluate.
01449      * @param   string      MPvar for the current position of item.
01450      * @return  boolean     True if page $uid = $GLOBALS['TSFE']->id
01451      * @access private
01452      */
01453     function isCurrent($uid, $MPvar='') {
01454         $testUid = $uid.($MPvar?':'.$MPvar:'');
01455         if ($uid && !strcmp(end($this->rL_uidRegister),'ITEM:'.$testUid))   {
01456             return TRUE;
01457         }
01458     }
01459 
01460     /**
01461      * Returns true if there is a submenu with items for the page id, $uid
01462      * Used by the item states "IFSUB", "ACTIFSUB" and "CURIFSUB" to check if there is a submenu
01463      *
01464      * @param   integer     Page uid for which to search for a submenu
01465      * @return  boolean     Returns true if there was a submenu with items found
01466      * @access private
01467      */
01468     function isSubMenu($uid)    {
01469 
01470             // Looking for a mount-pid for this UID since if that exists we should look for a subpages THERE and not in the input $uid;
01471         $mount_info = $this->sys_page->getMountPointInfo($uid);
01472         if (is_array($mount_info))  {
01473             $uid = $mount_info['mount_pid'];
01474         }
01475 
01476         $recs = $this->sys_page->getMenu($uid,'uid,pid,doktype,mount_pid,mount_pid_ol,nav_hide,shortcut,shortcut_mode');
01477         foreach($recs as $theRec)   {
01478             if (!t3lib_div::inList($this->doktypeExcludeList,$theRec['doktype']) && (!$theRec['nav_hide'] || $this->conf['includeNotInMenu']))  {   // If a menu item seems to be another type than 'Not in menu', then return true (there were items!)
01479                 return TRUE;
01480             }
01481         }
01482     }
01483 
01484     /**
01485      * Used by procesItemStates() to evaluate if a menu item (identified by $key) is in a certain state.
01486      *
01487      * @param   string      The item state to evaluate (SPC, IFSUB, ACT etc... but no xxxRO states of course)
01488      * @param   integer     Key pointing to menu item from ->menuArr
01489      * @return  boolean     True (integer!=0) if match, otherwise false (=0, zero)
01490      * @access private
01491      * @see procesItemStates()
01492      */
01493     function isItemState($kind,$key)    {
01494         $natVal=0;
01495         if ($this->menuArr[$key]['ITEM_STATE']) {       // If any value is set for ITEM_STATE the normal evaluation is discarded
01496             if (!strcmp($this->menuArr[$key]['ITEM_STATE'],$kind))  {$natVal=1;}
01497         } else {
01498             switch($kind)   {
01499                 case 'SPC':
01500                     $natVal = $this->menuArr[$key]['isSpacer'];
01501                 break;
01502                 case 'IFSUB':
01503                     $natVal = $this->isSubMenu($this->menuArr[$key]['uid']);
01504                 break;
01505                 case 'ACT':
01506                     $natVal = $this->isActive($this->menuArr[$key]['uid'], $this->getMPvar($key));
01507                 break;
01508                 case 'ACTIFSUB':
01509                     $natVal = $this->isActive($this->menuArr[$key]['uid'], $this->getMPvar($key)) && $this->isSubMenu($this->menuArr[$key]['uid']);
01510                 break;
01511                 case 'CUR':
01512                     $natVal = $this->isCurrent($this->menuArr[$key]['uid'], $this->getMPvar($key));
01513                 break;
01514                 case 'CURIFSUB':
01515                     $natVal = $this->isCurrent($this->menuArr[$key]['uid'], $this->getMPvar($key)) && $this->isSubMenu($this->menuArr[$key]['uid']);
01516                 break;
01517                 case 'USR':
01518                     $natVal = $this->menuArr[$key]['fe_group'];
01519                 break;
01520             }
01521         }
01522 
01523         return $natVal;
01524     }
01525 
01526     /**
01527      * Creates an access-key for a TMENU/GMENU menu item based on the menu item titles first letter
01528      *
01529      * @param   string      Menu item title.
01530      * @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
01531      * @access private
01532      */
01533     function accessKey($title)  {
01534             // The global array ACCESSKEY is used to globally control if letters are already used!!
01535         $result = Array();
01536 
01537         $title = trim(strip_tags($title));
01538         $titleLen = strlen($title);
01539         for ($a=0;$a<$titleLen;$a++)    {
01540             $key = strtoupper(substr($title,$a,1));
01541             if (preg_match('/[A-Z]/', $key) && !isset($GLOBALS['TSFE']->accessKey[$key]))   {
01542                 $GLOBALS['TSFE']->accessKey[$key] = 1;
01543                 $result['code'] = ' accesskey="'.$key.'"';
01544                 $result['alt'] = ' (ALT+'.$key.')';
01545                 $result['key'] = $key;
01546                 break;
01547             }
01548         }
01549         return $result;
01550     }
01551 
01552     /**
01553      * Calls a user function for processing of internal data.
01554      * Used for the properties "IProcFunc" and "itemArrayProcFunc"
01555      *
01556      * @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".
01557      * @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
01558      * @return  mixed       The processed $passVar
01559      * @access private
01560      */
01561     function userProcess($mConfKey,$passVar)    {
01562         if ($this->mconf[$mConfKey])    {
01563             $funcConf = $this->mconf[$mConfKey.'.'];
01564             $funcConf['parentObj'] = $this;
01565             $passVar = $this->parent_cObj->callUserFunction($this->mconf[$mConfKey], $funcConf, $passVar);
01566         }
01567         return $passVar;
01568     }
01569 
01570     /**
01571      * 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'])
01572      *
01573      * @return  void
01574      * @access private
01575      */
01576     function setATagParts() {
01577         $this->I['A1'] = '<a '.t3lib_div::implodeAttributes($this->I['linkHREF'],1).' '.$this->I['val']['ATagParams'].$this->I['accessKey']['code'].'>';
01578         $this->I['A2'] = '</a>';
01579     }
01580 
01581     /**
01582      * Returns the title for the navigation
01583      *
01584      * @param   string      The current page title
01585      * @param   string      The current value of the navigation title
01586      * @return  string      Returns the navigation title if it is NOT blank, otherwise the page title.
01587      * @access private
01588      */
01589     function getPageTitle($title,$nav_title)    {
01590         return strcmp(trim($nav_title),'') ? $nav_title : $title;
01591     }
01592 
01593     /**
01594      * Return MPvar string for entry $key in ->menuArr
01595      *
01596      * @param   integer     Pointer to element in ->menuArr
01597      * @param   string      Implode token.
01598      * @return  string      MP vars for element.
01599      * @see link()
01600      */
01601     function getMPvar($key) {
01602         if ($GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids']) {
01603             $localMP_array = $this->MP_array;
01604             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!
01605             $MP_params = count($localMP_array) ? implode(',',$localMP_array) : '';
01606             return $MP_params;
01607         }
01608     }
01609 
01610     /**
01611      * Returns where clause part to exclude 'not in menu' pages
01612      *
01613      * @return  string      where clause part.
01614      * @access private
01615      */
01616     function getDoktypeExcludeWhere() {
01617         return $this->doktypeExcludeList ? ' AND pages.doktype NOT IN ('.$this->doktypeExcludeList.')' : '';
01618     }
01619 
01620     /**
01621      * Returns an array of banned UIDs (from excludeUidList)
01622      *
01623      * @return  array       Array of banned UIDs
01624      * @access private
01625      */
01626     function getBannedUids() {
01627         $banUidArray = array();
01628 
01629         if (trim($this->conf['excludeUidList']))        {
01630             $banUidList = str_replace('current', $GLOBALS['TSFE']->page['uid'], $this->conf['excludeUidList']);
01631             $banUidArray = t3lib_div::intExplode(',', $banUidList);
01632         }
01633 
01634         return $banUidArray;
01635     }
01636 
01637     /**
01638      * Calls typolink to create menu item links.
01639      *
01640      * @param   array       $page   Page record (uid points where to link to)
01641      * @param   string      $oTarget    Target frame/window
01642      * @param   boolean     $no_cache   true if caching should be disabled
01643      * @param   string      $script Alternative script name
01644      * @param   array       $overrideArray  Array to override values in $page
01645      * @param   string      $addParams  Parameters to add to URL
01646      * @param   array       $typeOverride   "type" value
01647      * @return  array       See linkData
01648      */
01649     function menuTypoLink($page, $oTarget, $no_cache, $script, $overrideArray = '', $addParams = '', $typeOverride = '') {
01650         $conf = array(
01651             'parameter' => is_array($overrideArray) && $overrideArray['uid'] ? $overrideArray['uid'] : $page['uid'],
01652         );
01653         if ($typeOverride && t3lib_div::testInt($typeOverride)) {
01654             $conf['parameter'] .= ',' . $typeOverride;
01655         }
01656         if ($addParams) {
01657             $conf['additionalParams'] = $addParams;
01658         }
01659         if ($no_cache) {
01660             $conf['no_cache'] = true;
01661         }
01662         if ($oTarget) {
01663             $conf['target'] = $oTarget;
01664         }
01665         if ($page['sectionIndex_uid']) {
01666             $conf['section'] = $page['sectionIndex_uid'];
01667         }
01668 
01669         $this->parent_cObj->typoLink('|', $conf);
01670         $LD = $this->parent_cObj->lastTypoLinkLD;
01671         $LD['totalURL'] = $this->parent_cObj->lastTypoLinkUrl;
01672         return $LD;
01673     }
01674 
01675 }
01676 
01677 
01678 
01679 
01680 
01681 
01682 
01683 
01684 
01685 
01686 
01687 
01688 
01689 
01690 
01691 
01692 
01693 
01694 
01695 /**
01696  * Extension class creating text based menus
01697  *
01698  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
01699  * @package TYPO3
01700  * @subpackage tslib
01701  */
01702 class tslib_tmenu extends tslib_menu {
01703 
01704     /**
01705      * Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
01706      * Sets the result for the new "normal state" in $this->result
01707      *
01708      * @return  void
01709      * @see tslib_menu::procesItemStates()
01710      */
01711     function generate() {
01712         $splitCount = count($this->menuArr);
01713         if ($splitCount)    {
01714             list($NOconf) = $this->procesItemStates($splitCount);
01715         }
01716         if ($this->mconf['debugItemConf'])  {echo '<h3>$NOconf:</h3>';  debug($NOconf); }
01717         $this->result = $NOconf;
01718     }
01719 
01720     /**
01721      * Traverses the ->result array of menu items configuration (made by ->generate()) and renders each item.
01722      * 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
01723      * 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.
01724      *
01725      * @return  string      The HTML for the menu (returns result through $this->extProc_finish(); )
01726      */
01727     function writeMenu()    {
01728         if (is_array($this->result) && count($this->result))    {
01729             $this->WMcObj = t3lib_div::makeInstance('tslib_cObj');  // Create new tslib_cObj for our use
01730             $this->WMresult = '';
01731             $this->INPfixMD5 = substr(md5(microtime().'tmenu'),0,4);
01732             $this->WMmenuItems = count($this->result);
01733 
01734             $this->WMsubmenuObjSuffixes = $this->tmpl->splitConfArray(array('sOSuffix'=>$this->mconf['submenuObjSuffixes']),$this->WMmenuItems);
01735 
01736             $this->extProc_init();
01737             foreach ($this->result as $key => $val) {
01738                 $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']++;
01739                 $GLOBALS['TSFE']->register['count_MENUOBJ']++;
01740 
01741                 $this->WMcObj->start($this->menuArr[$key],'pages');     // Initialize the cObj with the page record of the menu item
01742 
01743                 $this->I = array();
01744                 $this->I['key'] = $key;
01745                 $this->I['INPfix'] = ($this->imgNameNotRandom ? '' : '_'.$this->INPfixMD5).'_'.$key;
01746                 $this->I['val'] = $val;
01747                 $this->I['title'] = isset($this->I['val']['stdWrap.'])
01748                     ? $this->WMcObj->stdWrap($this->getPageTitle($this->menuArr[$key]['title'], $this->menuArr[$key]['nav_title']), $this->I['val']['stdWrap.'])
01749                     : $this->getPageTitle($this->menuArr[$key]['title'],$this->menuArr[$key]['nav_title']);
01750                 $this->I['uid'] = $this->menuArr[$key]['uid'];
01751                 $this->I['mount_pid'] = $this->menuArr[$key]['mount_pid'];
01752                 $this->I['pid'] = $this->menuArr[$key]['pid'];
01753                 $this->I['spacer'] = $this->menuArr[$key]['isSpacer'];
01754 
01755                     // Set access key
01756                 if ($this->mconf['accessKey'])  {
01757                     $this->I['accessKey'] = $this->accessKey($this->I['title']);
01758                 } else {
01759                     $this->I['accessKey'] = Array();
01760                 }
01761 
01762                     // Make link tag
01763                 $this->I['val']['ATagParams'] = $this->WMcObj->getATagParams($this->I['val']);
01764                 if(isset($this->I['val']['additionalParams.'])) {
01765                     $this->I['val']['additionalParams'] = $this->WMcObj->stdWrap($this->I['val']['additionalParams'], $this->I['val']['additionalParams.']);
01766                 }
01767                 $this->I['linkHREF'] = $this->link($key,$this->I['val']['altTarget'],$this->mconf['forceTypeValue']);
01768 
01769                     // Title attribute of links:
01770                 $titleAttrValue = isset($this->I['val']['ATagTitle.'])
01771                     ? $this->WMcObj->stdWrap($this->I['val']['ATagTitle'], $this->I['val']['ATagTitle.']) . $this->I['accessKey']['alt']
01772                     : $this->I['val']['ATagTitle'].$this->I['accessKey']['alt'];
01773                 if (strlen($titleAttrValue))    {
01774                     $this->I['linkHREF']['title'] = $titleAttrValue;
01775                 }
01776 
01777                     // Setting "blurlink()" function:
01778                 if (!$this->mconf['noBlur'])    {
01779                     $this->I['linkHREF']['onFocus']='blurLink(this);';
01780                 }
01781 
01782                     // Make link:
01783                 if ($this->I['val']['RO'])  {
01784                     $this->I['theName'] = $this->imgNamePrefix.$this->I['uid'].$this->I['INPfix'];
01785                     $over='';
01786                     $out ='';
01787                     if ($this->I['val']['beforeROImg']) {
01788                         $over.= $this->WMfreezePrefix."over('".$this->I['theName']."before');";
01789                         $out.= $this->WMfreezePrefix."out('".$this->I['theName']."before');";
01790                     }
01791                     if ($this->I['val']['afterROImg'])  {
01792                         $over.= $this->WMfreezePrefix."over('".$this->I['theName']."after');";
01793                         $out.= $this->WMfreezePrefix."out('".$this->I['theName']."after');";
01794                     }
01795                     $this->I['linkHREF']['onMouseover']=$over;
01796                     $this->I['linkHREF']['onMouseout']=$out;
01797                     if ($over || $out)  $GLOBALS['TSFE']->setJS('mouseOver');
01798 
01799                         // Change background color:
01800                     if ($this->I['val']['RO_chBgColor'])    {
01801                         $this->addJScolorShiftFunction();
01802                         $chBgP = t3lib_div::trimExplode('|',$this->I['val']['RO_chBgColor']);
01803                         $this->I['linkHREF']['onMouseover'].="changeBGcolor('".$chBgP[2].$this->I['uid']."','".$chBgP[0]."');";
01804                         $this->I['linkHREF']['onMouseout'].="changeBGcolor('".$chBgP[2].$this->I['uid']."','".$chBgP[1]."');";
01805                     }
01806 
01807                     $this->extProc_RO($key);
01808                 }
01809 
01810 
01811                     // Calling extra processing function
01812                 $this->extProc_beforeLinking($key);
01813 
01814                     // stdWrap for doNotLinkIt
01815                 if (isset($this->I['val']['doNotLinkIt.'])) {
01816                     $this->I['val']['doNotLinkIt'] = $this->WMcObj->stdWrap($this->I['val']['doNotLinkIt'], $this->I['val']['doNotLinkIt.']);
01817                 }
01818 
01819                     // Compile link tag
01820                 if (!$this->I['val']['doNotLinkIt']) {$this->I['val']['doNotLinkIt']=0;}
01821                 if (!$this->I['spacer'] && $this->I['val']['doNotLinkIt']!=1)   {
01822                     $this->setATagParts();
01823                 } else {
01824                     $this->I['A1'] = '';
01825                     $this->I['A2'] = '';
01826                 }
01827 
01828                     // ATagBeforeWrap processing:
01829                 if ($this->I['val']['ATagBeforeWrap'])  {
01830                     $wrapPartsBefore = explode('|',$this->I['val']['linkWrap']);
01831                     $wrapPartsAfter = array('','');
01832                 } else {
01833                     $wrapPartsBefore = array('','');
01834                     $wrapPartsAfter = explode('|',$this->I['val']['linkWrap']);
01835                 }
01836                 if ($this->I['val']['stdWrap2'] || isset($this->I['val']['stdWrap2.'])) {
01837                     $stdWrap2 = isset($this->I['val']['stdWrap2.'])
01838                         ? $this->WMcObj->stdWrap('|', $this->I['val']['stdWrap2.'])
01839                         : '|';
01840                     $wrapPartsStdWrap = explode($this->I['val']['stdWrap2'] ? $this->I['val']['stdWrap2'] : '|', $stdWrap2);
01841                 } else {$wrapPartsStdWrap = array('','');}
01842 
01843                     // Make before, middle and after parts
01844                 $this->I['parts'] = array();
01845                 $this->I['parts']['before']=$this->getBeforeAfter('before');
01846                 $this->I['parts']['stdWrap2_begin']=$wrapPartsStdWrap[0];
01847 
01848                     // stdWrap for doNotShowLink
01849                 if (isset($this->I['val']['doNotShowLink.'])) {
01850                     $this->I['val']['doNotShowLink'] = $this->WMcObj->stdWrap($this->I['val']['doNotShowLink'], $this->I['val']['doNotShowLink.']);
01851                 }
01852 
01853                 if (!$this->I['val']['doNotShowLink']) {
01854                     $this->I['parts']['notATagBeforeWrap_begin'] = $wrapPartsAfter[0];
01855                     $this->I['parts']['ATag_begin'] = $this->I['A1'];
01856                     $this->I['parts']['ATagBeforeWrap_begin'] = $wrapPartsBefore[0];
01857                     $this->I['parts']['title'] = $this->I['title'];
01858                     $this->I['parts']['ATagBeforeWrap_end'] = $wrapPartsBefore[1];
01859                     $this->I['parts']['ATag_end'] = $this->I['A2'];
01860                     $this->I['parts']['notATagBeforeWrap_end'] = $wrapPartsAfter[1];
01861                 }
01862                 $this->I['parts']['stdWrap2_end']=$wrapPartsStdWrap[1];
01863                 $this->I['parts']['after']=$this->getBeforeAfter('after');
01864 
01865                     // Passing I to a user function
01866                 if ($this->mconf['IProcFunc'])  {
01867                     $this->I = $this->userProcess('IProcFunc',$this->I);
01868                 }
01869 
01870                     // Merge parts + beforeAllWrap
01871                 $this->I['theItem']= implode('',$this->I['parts']);
01872                 $this->I['theItem']= $this->extProc_beforeAllWrap($this->I['theItem'],$key);
01873 
01874                     // allWrap:
01875                 $allWrap = isset($this->I['val']['allWrap.'])
01876                     ? $this->WMcObj->stdWrap($this->I['val']['allWrap'], $this->I['val']['allWrap.'])
01877                     : $this->I['val']['allWrap'];
01878                 $this->I['theItem'] = $this->tmpl->wrap($this->I['theItem'],$allWrap);
01879 
01880                 if ($this->I['val']['subst_elementUid'])    $this->I['theItem'] = str_replace('{elementUid}',$this->I['uid'],$this->I['theItem']);
01881 
01882                     // allStdWrap:
01883                 if (is_array($this->I['val']['allStdWrap.']))   {
01884                     $this->I['theItem'] = $this->WMcObj->stdWrap($this->I['theItem'], $this->I['val']['allStdWrap.']);
01885                 }
01886 
01887                     // Calling extra processing function
01888                 $this->extProc_afterLinking($key);
01889             }
01890             return $this->extProc_finish();
01891         }
01892     }
01893 
01894     /**
01895      * Generates the before* and after* images for TMENUs
01896      *
01897      * @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
01898      * @return  string      The resulting HTML of the image, if any.
01899      */
01900     function getBeforeAfter($pref)  {
01901         $res = '';
01902         if ($imgInfo = $this->WMcObj->getImgResource($this->I['val'][$pref.'Img'],$this->I['val'][$pref.'Img.']))   {
01903             $imgInfo[3] = t3lib_div::png_to_gif_by_imagemagick($imgInfo[3]);
01904             if ($this->I['val']['RO'] && $this->I['val'][$pref.'ROImg'] && !$this->I['spacer']) {
01905                 $imgROInfo = $this->WMcObj->getImgResource($this->I['val'][$pref.'ROImg'],$this->I['val'][$pref.'ROImg.']);
01906                 $imgROInfo[3] = t3lib_div::png_to_gif_by_imagemagick($imgROInfo[3]);
01907                 if ($imgROInfo) {
01908                     $theName = $this->imgNamePrefix.$this->I['uid'].$this->I['INPfix'].$pref;
01909                     $name = ' '.$this->nameAttribute.'="'.$theName.'"';
01910                     $GLOBALS['TSFE']->JSImgCode.= LF.$theName.'_n=new Image(); '.$theName.'_n.src = "'.$GLOBALS['TSFE']->absRefPrefix.$imgInfo[3].'"; ';
01911                     $GLOBALS['TSFE']->JSImgCode.= LF.$theName.'_h=new Image(); '.$theName.'_h.src = "'.$GLOBALS['TSFE']->absRefPrefix.$imgROInfo[3].'"; ';
01912                 }
01913             }
01914             $GLOBALS['TSFE']->imagesOnPage[]=$imgInfo[3];
01915             $res='<img' .
01916                 ' src="' . $GLOBALS['TSFE']->absRefPrefix . $imgInfo[3] . '"' .
01917                 ' width="' . $imgInfo[0] . '"' .
01918                 ' height="' . $imgInfo[1] . '"' .
01919                 $name .
01920                 ($this->I['val'][$pref.'ImgTagParams'] ? ' ' . $this->I['val'][$pref.'ImgTagParams'] : '') .
01921                 tslib_cObj::getBorderAttr(' border="0"');
01922             if (!strstr($res,'alt="')) {
01923                 $res .= ' alt=""'; // Adding alt attribute if not set.
01924             }
01925             $res.=' />';
01926             if ($this->I['val'][$pref.'ImgLink']) {
01927                 $res=$this->I['A1'].$res.$this->I['A2'];
01928             }
01929         }
01930         $processedPref = isset($this->I['val'][$pref . '.'])
01931             ? $this->WMcObj->stdWrap($this->I['val'][$pref], $this->I['val'][$pref . '.'])
01932             : $this->I['val'][$pref];
01933         if (isset($this->I['val'][$pref . 'Wrap'])) {
01934             return $this->tmpl->wrap($res . $processedPref, $this->I['val'][$pref . 'Wrap']);
01935         } else {
01936              return $res . $processedPref;
01937         }
01938     }
01939 
01940     /**
01941      * Adds a JavaScript function to the $GLOBALS['TSFE']->additionalJavaScript array
01942      *
01943      * @return  void
01944      * @access private
01945      * @see writeMenu()
01946      */
01947     function addJScolorShiftFunction()  {
01948         $GLOBALS['TSFE']->additionalJavaScript['TMENU:changeBGcolor()']='
01949             function changeBGcolor(id,color) {  //
01950                 if (document.getElementById && document.getElementById(id)) {
01951                     document.getElementById(id).style.background = color;
01952                     return true;
01953                 } else if (document.layers && document.layers[id]) {
01954                     document.layers[id].bgColor = color;
01955                     return true;
01956                 }
01957             }
01958         ';
01959     }
01960 
01961     /**
01962      * Called right before the traversing of $this->result begins.
01963      * Can be used for various initialization
01964      *
01965      * @return  void
01966      * @access private
01967      * @see writeMenu(), tslib_tmenu_layers::extProc_init()
01968      */
01969     function extProc_init() {
01970     }
01971 
01972     /**
01973      * Called after all processing for RollOver of an element has been done.
01974      *
01975      * @param   integer     Pointer to $this->menuArr[$key] where the current menu element record is found
01976      * @return  void
01977      * @access private
01978      * @see writeMenu(), tslib_tmenu_layers::extProc_RO()
01979      */
01980     function extProc_RO($key)   {
01981     }
01982 
01983     /**
01984      * Called right before the creation of the link for the menu item
01985      *
01986      * @param   integer     Pointer to $this->menuArr[$key] where the current menu element record is found
01987      * @return  void
01988      * @access private
01989      * @see writeMenu(), tslib_tmenu_layers::extProc_beforeLinking()
01990      */
01991     function extProc_beforeLinking($key)    {
01992     }
01993 
01994     /**
01995      * 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.
01996      * This function MUST set $this->WMresult.=[HTML for menu item] to add the generated menu item to the internal accumulation of items.
01997      *
01998      * @param   integer     Pointer to $this->menuArr[$key] where the current menu element record is found
01999      * @return  void
02000      * @access private
02001      * @see writeMenu(), tslib_tmenu_layers::extProc_afterLinking()
02002      */
02003     function extProc_afterLinking($key) {
02004             // Add part to the accumulated result + fetch submenus
02005         if (!$this->I['spacer'])    {
02006             $this->I['theItem'].= $this->subMenu($this->I['uid'], $this->WMsubmenuObjSuffixes[$key]['sOSuffix']);
02007         }
02008         $part = isset($this->I['val']['wrapItemAndSub.'])
02009             ? $this->WMcObj->stdWrap($this->I['val']['wrapItemAndSub'], $this->I['val']['wrapItemAndSub.'])
02010             : $this->I['val']['wrapItemAndSub'];
02011         $this->WMresult.= $part ? $this->tmpl->wrap($this->I['theItem'],$part) : $this->I['theItem'];
02012     }
02013 
02014     /**
02015      * Called before the "allWrap" happens on the menu item.
02016      *
02017      * @param   string      The current content of the menu item, $this->I['theItem'], passed along.
02018      * @param   integer     Pointer to $this->menuArr[$key] where the current menu element record is found
02019      * @return  string      The modified version of $item, going back into $this->I['theItem']
02020      * @access private
02021      * @see writeMenu(), tslib_tmenu_layers::extProc_beforeAllWrap()
02022      */
02023     function extProc_beforeAllWrap($item,$key)  {
02024         return $item;
02025     }
02026 
02027     /**
02028      * Called before the writeMenu() function returns (only if a menu was generated)
02029      *
02030      * @return  string      The total menu content should be returned by this function
02031      * @access private
02032      * @see writeMenu(), tslib_tmenu_layers::extProc_finish()
02033      */
02034     function extProc_finish()   {
02035             // stdWrap:
02036         if (is_array($this->mconf['stdWrap.'])) {
02037             $this->WMresult = $this->WMcObj->stdWrap($this->WMresult, $this->mconf['stdWrap.']);
02038         }
02039         return $this->tmpl->wrap($this->WMresult,$this->mconf['wrap']).$this->WMextraScript;
02040     }
02041 }
02042 
02043 
02044 
02045 
02046 
02047 
02048 
02049 
02050 
02051 
02052 
02053 
02054 
02055 
02056 
02057 
02058 
02059 
02060 
02061 
02062 
02063 
02064 
02065 
02066 /**
02067  * Extension class creating graphic based menus (PNG or GIF files)
02068  *
02069  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
02070  * @package TYPO3
02071  * @subpackage tslib
02072  */
02073 class tslib_gmenu extends tslib_menu {
02074 
02075     /**
02076      * Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
02077      * Calls makeGifs() for all "normal" items and if configured for, also the "rollover" items.
02078      *
02079      * @return  void
02080      * @see tslib_menu::procesItemStates(), makeGifs()
02081      */
02082     function generate() {
02083         $splitCount = count($this->menuArr);
02084         if ($splitCount)    {
02085             list($NOconf,$ROconf) = $this->procesItemStates($splitCount);
02086 
02087                 //store initial count value
02088             $temp_HMENU_MENUOBJ = $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ'];
02089             $temp_MENUOBJ = $GLOBALS['TSFE']->register['count_MENUOBJ'];
02090                 // Now we generate the giffiles:
02091             $this->makeGifs($NOconf,'NO');
02092                 // store count from NO obj
02093             $tempcnt_HMENU_MENUOBJ = $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ'];
02094             $tempcnt_MENUOBJ = $GLOBALS['TSFE']->register['count_MENUOBJ'];
02095 
02096             if ($this->mconf['debugItemConf'])  {echo '<h3>$NOconf:</h3>';  debug($NOconf); }
02097             if ($ROconf)    {       // RollOver
02098                     //start recount for rollover with initial values
02099                 $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']= $temp_HMENU_MENUOBJ;
02100                 $GLOBALS['TSFE']->register['count_MENUOBJ']= $temp_MENUOBJ;
02101                 $this->makeGifs($ROconf,'RO');
02102                 if ($this->mconf['debugItemConf'])  {echo '<h3>$ROconf:</h3>';  debug($ROconf); }
02103             }
02104                 // use count from NO obj
02105             $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ'] = $tempcnt_HMENU_MENUOBJ;
02106             $GLOBALS['TSFE']->register['count_MENUOBJ'] = $tempcnt_MENUOBJ;
02107         }
02108     }
02109 
02110     /**
02111      * Will traverse input array with configuratoin per-item and create corresponding GIF files for the menu.
02112      * The data of the files are stored in $this->result
02113      *
02114      * @param   array       Array with configuration for each item.
02115      * @param   string      Type of images: normal ("NO") or rollover ("RO"). Valid values are "NO" and "RO"
02116      * @return  void
02117      * @access private
02118      * @see generate()
02119      */
02120     function makeGifs($conf, $resKey)   {
02121         $isGD = $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'];
02122 
02123         if (!is_array($conf)) {
02124             $conf = Array();
02125         }
02126 
02127         $totalWH=array();
02128         $items = count($conf);
02129         if ($isGD)  {
02130                 // generate the gif-files. the $menuArr is filled with some values like output_w, output_h, output_file
02131             $Hcounter = 0;
02132             $Wcounter = 0;
02133             $Hobjs = $this->mconf['applyTotalH'];
02134             if ($Hobjs) {$Hobjs = t3lib_div::intExplode(',',$Hobjs);}
02135             $Wobjs = $this->mconf['applyTotalW'];
02136             if ($Wobjs) {$Wobjs = t3lib_div::intExplode(',',$Wobjs);}
02137             $minDim = $this->mconf['min'];
02138             if ($minDim) {$minDim = tslib_cObj::calcIntExplode(',',$minDim.',');}
02139             $maxDim = $this->mconf['max'];
02140             if ($maxDim) {$maxDim = tslib_cObj::calcIntExplode(',',$maxDim.',');}
02141 
02142             if ($minDim)    {
02143                 $conf[$items]=$conf[$items-1];
02144                 $this->menuArr[$items]=Array();
02145                 $items = count($conf);
02146             }
02147 
02148             // TOTAL width
02149             if ($this->mconf['useLargestItemX'] || $this->mconf['useLargestItemY'] || $this->mconf['distributeX'] || $this->mconf['distributeY'])   {
02150                 $totalWH = $this->findLargestDims($conf,$items,$Hobjs,$Wobjs,$minDim,$maxDim);
02151             }
02152         }
02153 
02154         $c=0;
02155         $maxFlag=0;
02156         $distributeAccu=array('H'=>0,'W'=>0);
02157         foreach ($conf as $key => $val) {
02158             $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']++;
02159             $GLOBALS['TSFE']->register['count_MENUOBJ']++;
02160 
02161             if ($items==($c+1) && $minDim)  {
02162                 $Lobjs = $this->mconf['removeObjectsOfDummy'];
02163                 if ($Lobjs) {
02164                     $Lobjs = t3lib_div::intExplode(',',$Lobjs);
02165                     foreach ($Lobjs as $remItem) {
02166                         unset($val[$remItem]);
02167                         unset($val[$remItem.'.']);
02168                     }
02169                 }
02170 
02171                 $flag =0;
02172                 $tempXY = explode(',',$val['XY']);
02173                 if ($Wcounter<$minDim[0])   {$tempXY[0]=$minDim[0]-$Wcounter; $flag=1;}
02174                 if ($Hcounter<$minDim[1])   {$tempXY[1]=$minDim[1]-$Hcounter; $flag=1;}
02175                 $val['XY'] = implode(',',$tempXY);
02176                 if (!$flag){break;}
02177             }
02178             $c++;
02179 
02180 
02181             if ($isGD)  {
02182                     // Pre-working the item
02183                 $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
02184                 $gifCreator->init();
02185                 $gifCreator->start($val,$this->menuArr[$key]);
02186 
02187                     // If useLargestItemH/W is specified
02188                 if (count($totalWH) && ($this->mconf['useLargestItemX'] || $this->mconf['useLargestItemY']))    {
02189                     $tempXY = explode(',',$gifCreator->setup['XY']);
02190                     if ($this->mconf['useLargestItemX'])    {$tempXY[0] = max($totalWH['W']);}
02191                     if ($this->mconf['useLargestItemY'])    {$tempXY[1] = max($totalWH['H']);}
02192                         // regenerate the new values...
02193                     $val['XY'] = implode(',',$tempXY);
02194                     $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
02195                     $gifCreator->init();
02196                     $gifCreator->start($val,$this->menuArr[$key]);
02197                 }
02198 
02199                     // If distributeH/W is specified
02200                 if (count($totalWH) && ($this->mconf['distributeX'] || $this->mconf['distributeY']))    {
02201                     $tempXY = explode(',',$gifCreator->setup['XY']);
02202 
02203                     if ($this->mconf['distributeX'])    {
02204                         $diff = $this->mconf['distributeX']-$totalWH['W_total']-$distributeAccu['W'];
02205                         $compensate = round($diff /($items-$c+1));
02206                         $distributeAccu['W']+=$compensate;
02207                         $tempXY[0] = $totalWH['W'][$key]+$compensate;
02208                     }
02209                     if ($this->mconf['distributeY'])    {
02210                         $diff = $this->mconf['distributeY']-$totalWH['H_total']-$distributeAccu['H'];
02211                         $compensate = round($diff /($items-$c+1));
02212                         $distributeAccu['H']+=$compensate;
02213                         $tempXY[1] = $totalWH['H'][$key]+$compensate;
02214                     }
02215                         // regenerate the new values...
02216                     $val['XY'] = implode(',',$tempXY);
02217                     $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
02218                     $gifCreator->init();
02219                     $gifCreator->start($val,$this->menuArr[$key]);
02220                 }
02221 
02222                     // If max dimensions are specified
02223                 if ($maxDim)    {
02224                     $tempXY = explode(',',$val['XY']);
02225                     if ($maxDim[0] && $Wcounter+$gifCreator->XY[0]>=$maxDim[0]) {$tempXY[0]==$maxDim[0]-$Wcounter; $maxFlag=1;}
02226                     if ($maxDim[1] && $Hcounter+$gifCreator->XY[1]>=$maxDim[1]) {$tempXY[1]=$maxDim[1]-$Hcounter; $maxFlag=1;}
02227                     if ($maxFlag)   {
02228                         $val['XY'] = implode(',',$tempXY);
02229                         $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
02230                         $gifCreator->init();
02231                         $gifCreator->start($val,$this->menuArr[$key]);
02232                     }
02233                 }
02234 
02235 
02236 
02237 
02238                 // displace
02239                 if ($Hobjs) {
02240                     foreach ($Hobjs as $index) {
02241                         if ($gifCreator->setup[$index] && $gifCreator->setup[$index.'.'])   {
02242                             $oldOffset = explode(',',$gifCreator->setup[$index.'.']['offset']);
02243                             $gifCreator->setup[$index.'.']['offset'] = implode(',',$gifCreator->applyOffset($oldOffset,Array(0,-$Hcounter)));
02244                         }
02245                     }
02246                 }
02247 
02248                 if ($Wobjs) {
02249                     foreach ($Wobjs as $index) {
02250                         if ($gifCreator->setup[$index] && $gifCreator->setup[$index.'.'])   {
02251                             $oldOffset = explode(',',$gifCreator->setup[$index.'.']['offset']);
02252                             $gifCreator->setup[$index.'.']['offset'] = implode(',',$gifCreator->applyOffset($oldOffset,Array(-$Wcounter,0)));
02253                         }
02254                     }
02255                 }
02256             }
02257 
02258                 // Finding alternative GIF names if any (by altImgResource)
02259             $gifFileName='';
02260             if ($conf[$key]['altImgResource'] || is_array($conf[$key]['altImgResource.']))  {
02261                 if (!is_object($cObj)) {$cObj=t3lib_div::makeInstance('tslib_cObj');}
02262                 $cObj->start($this->menuArr[$key],'pages');
02263                 $altImgInfo = $cObj->getImgResource($conf[$key]['altImgResource'],$conf[$key]['altImgResource.']);
02264                 $gifFileName=$altImgInfo[3];
02265             }
02266 
02267                 // If an alternative name was NOT given, find the GIFBUILDER name.
02268             if (!$gifFileName && $isGD) {
02269                 $gifCreator->createTempSubDir('menu/');
02270                 $gifFileName = $gifCreator->fileName('menu/');
02271             }
02272 
02273             $this->result[$resKey][$key] = $conf[$key];
02274 
02275                 // Generation of image file:
02276             if (file_exists($gifFileName))  {       // File exists
02277                 $info = @getimagesize($gifFileName);
02278                 $this->result[$resKey][$key]['output_w']=intval($info[0]);
02279                 $this->result[$resKey][$key]['output_h']=intval($info[1]);
02280                 $this->result[$resKey][$key]['output_file'] = $gifFileName;
02281             } elseif ($isGD) {      // file is generated
02282                 $gifCreator->make();
02283                 $this->result[$resKey][$key]['output_w']=$gifCreator->w;
02284                 $this->result[$resKey][$key]['output_h']=$gifCreator->h;
02285                 $this->result[$resKey][$key]['output_file'] = $gifFileName;
02286                 $gifCreator->output($this->result[$resKey][$key]['output_file']);
02287                 $gifCreator->destroy();
02288             }
02289 
02290             $this->result[$resKey][$key]['output_file'] = t3lib_div::png_to_gif_by_imagemagick($this->result[$resKey][$key]['output_file']);
02291 
02292             $Hcounter+=$this->result[$resKey][$key]['output_h'];        // counter is increased
02293             $Wcounter+=$this->result[$resKey][$key]['output_w'];        // counter is increased
02294 
02295             if ($maxFlag)   break;
02296         }
02297     }
02298 
02299     /**
02300      * Function searching for the largest width and height of the menu items to be generated.
02301      * 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.
02302      * Remember to upgrade the code in here if the makeGifs function is updated.
02303      *
02304      * @param   array       Same configuration array as passed to makeGifs()
02305      * @param   integer     The number of menu items
02306      * @param   array       Array with "applyTotalH" numbers
02307      * @param   array       Array with "applyTotalW" numbers
02308      * @param   array       Array with "min" x/y
02309      * @param   array       Array with "max" x/y
02310      * @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.
02311      * @access private
02312      * @see makeGifs()
02313      */
02314     function findLargestDims($conf,$items,$Hobjs,$Wobjs,$minDim,$maxDim)    {
02315         $totalWH = array(
02316             'W' => array(),
02317             'H' => array(),
02318             'W_total' => 0,
02319             'H_total' => 0
02320         );
02321 
02322         $Hcounter = 0;
02323         $Wcounter = 0;
02324         $c=0;
02325         $maxFlag=0;
02326         foreach ($conf as $key => $val) {
02327             // SAME CODE AS makeGifs()! BEGIN
02328             if ($items==($c+1) && $minDim)  {
02329                 $Lobjs = $this->mconf['removeObjectsOfDummy'];
02330                 if ($Lobjs) {
02331                     $Lobjs = t3lib_div::intExplode(',',$Lobjs);
02332                     foreach ($Lobjs as $remItem) {
02333                         unset($val[$remItem]);
02334                         unset($val[$remItem.'.']);
02335                     }
02336                 }
02337 
02338                 $flag =0;
02339                 $tempXY = explode(',',$val['XY']);
02340                 if ($Wcounter<$minDim[0])   {$tempXY[0]=$minDim[0]-$Wcounter; $flag=1;}
02341                 if ($Hcounter<$minDim[1])   {$tempXY[1]=$minDim[1]-$Hcounter; $flag=1;}
02342                 $val['XY'] = implode(',',$tempXY);
02343                 if (!$flag){break;}
02344             }
02345             $c++;
02346 
02347             $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
02348             $gifCreator->init();
02349             $gifCreator->start($val,$this->menuArr[$key]);
02350             if ($maxDim)    {
02351                 $tempXY = explode(',',$val['XY']);
02352                 if ($maxDim[0] && $Wcounter+$gifCreator->XY[0]>=$maxDim[0]) {$tempXY[0]==$maxDim[0]-$Wcounter; $maxFlag=1;}
02353                 if ($maxDim[1] && $Hcounter+$gifCreator->XY[1]>=$maxDim[1]) {$tempXY[1]=$maxDim[1]-$Hcounter; $maxFlag=1;}
02354                 if ($maxFlag)   {
02355                     $val['XY'] = implode(',',$tempXY);
02356                     $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
02357                     $gifCreator->init();
02358                     $gifCreator->start($val,$this->menuArr[$key]);
02359                 }
02360             }
02361             // SAME CODE AS makeGifs()! END
02362 
02363                 // Setting the width/height
02364             $totalWH['W'][$key]=$gifCreator->XY[0];
02365             $totalWH['H'][$key]=$gifCreator->XY[1];
02366             $totalWH['W_total']+=$gifCreator->XY[0];
02367             $totalWH['H_total']+=$gifCreator->XY[1];
02368                 // ---- //
02369 
02370             $Hcounter+=$gifCreator->XY[1];      // counter is increased
02371             $Wcounter+=$gifCreator->XY[0];      // counter is increased
02372 
02373             if ($maxFlag){break;}
02374         }
02375         return $totalWH;
02376     }
02377 
02378     /**
02379      * 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())
02380      * 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
02381      *
02382      * @return  string      The HTML for the menu (returns result through $this->extProc_finish(); )
02383      */
02384     function writeMenu()    {
02385         if (is_array($this->menuArr) && is_array($this->result) && count($this->result) && is_array($this->result['NO']))   {
02386             $this->WMcObj = t3lib_div::makeInstance('tslib_cObj');  // Create new tslib_cObj for our use
02387             $this->WMresult = '';
02388             $this->INPfixMD5 = substr(md5(microtime().$this->GMENU_fixKey),0,4);
02389             $this->WMmenuItems = count($this->result['NO']);
02390 
02391             $this->WMsubmenuObjSuffixes = $this->tmpl->splitConfArray(array('sOSuffix'=>$this->mconf['submenuObjSuffixes']),$this->WMmenuItems);
02392 
02393             $this->extProc_init();
02394             for ($key=0;$key<$this->WMmenuItems;$key++) {
02395                 if ($this->result['NO'][$key]['output_file'])   {
02396                     $this->WMcObj->start($this->menuArr[$key],'pages');     // Initialize the cObj with the page record of the menu item
02397 
02398                     $this->I = array();
02399                     $this->I['key'] = $key;
02400                     $this->I['INPfix']= ($this->imgNameNotRandom ? '' : '_'.$this->INPfixMD5).'_'.$key;
02401                     $this->I['val'] = $this->result['NO'][$key];
02402                     $this->I['title'] = $this->getPageTitle($this->menuArr[$key]['title'],$this->menuArr[$key]['nav_title']);
02403                     $this->I['uid'] = $this->menuArr[$key]['uid'];
02404                     $this->I['mount_pid'] = $this->menuArr[$key]['mount_pid'];
02405                     $this->I['pid'] = $this->menuArr[$key]['pid'];
02406                     $this->I['spacer'] = $this->menuArr[$key]['isSpacer'];
02407                     if (!$this->I['uid'] && !$this->menuArr[$key]['_OVERRIDE_HREF']) {$this->I['spacer']=1;}
02408                     $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
02409                     $this->I['name'] = '';
02410 
02411                         // Set access key
02412                     if ($this->mconf['accessKey'])  {
02413                         $this->I['accessKey'] = $this->accessKey($this->I['title']);
02414                     } else {
02415                         $this->I['accessKey'] = array();
02416                     }
02417 
02418                         // Make link tag
02419                     $this->I['val']['ATagParams'] = $this->WMcObj->getATagParams($this->I['val']);
02420                     if (isset($this->I['val']['additionalParams.'])) {
02421                         $this->I['val']['additionalParams'] = $this->WMcObj->stdWrap($this->I['val']['additionalParams'], $this->I['val']['additionalParams.']);
02422                     }
02423                     $this->I['linkHREF'] = $this->link($key,$this->I['val']['altTarget'],$this->mconf['forceTypeValue']);
02424 
02425                         // Title attribute of links:
02426                     $titleAttrValue = isset($this->I['val']['ATagTitle.'])
02427                         ? $this->WMcObj->stdWrap($this->I['val']['ATagTitle'], $this->I['val']['ATagTitle.']) . $this->I['accessKey']['alt']
02428                         : $this->I['val']['ATagTitle'].$this->I['accessKey']['alt'];
02429                     if (strlen($titleAttrValue))    {
02430                         $this->I['linkHREF']['title'] = $titleAttrValue;
02431                     }
02432                         // Setting "blurlink()" function:
02433                     if (!$this->mconf['noBlur'])    {
02434                         $this->I['linkHREF']['onFocus']='blurLink(this);';
02435                     }
02436 
02437                         // Set rollover
02438                     if ($this->result['RO'][$key] && !$this->I['noLink'])   {
02439                         $this->I['theName'] = $this->imgNamePrefix.$this->I['uid'].$this->I['INPfix'];
02440                         $this->I['name'] = ' '.$this->nameAttribute.'="'.$this->I["theName"].'"';
02441                         $this->I['linkHREF']['onMouseover']=$this->WMfreezePrefix.'over(\''.$this->I['theName'].'\');';
02442                         $this->I['linkHREF']['onMouseout']=$this->WMfreezePrefix.'out(\''.$this->I['theName'].'\');';
02443                         $GLOBALS['TSFE']->JSImgCode.= LF.$this->I['theName'].'_n=new Image(); '.$this->I['theName'].'_n.src = "'.$GLOBALS['TSFE']->absRefPrefix.$this->I['val']['output_file'].'"; ';
02444                         $GLOBALS['TSFE']->JSImgCode.= LF.$this->I['theName'].'_h=new Image(); '.$this->I['theName'].'_h.src = "'.$GLOBALS['TSFE']->absRefPrefix.$this->result['RO'][$key]['output_file'].'"; ';
02445                         $GLOBALS['TSFE']->imagesOnPage[]=$this->result['RO'][$key]['output_file'];
02446                         $GLOBALS['TSFE']->setJS('mouseOver');
02447                         $this->extProc_RO($key);
02448                     }
02449 
02450                         // Set altText
02451                     $this->I['altText'] = $this->I['title'].$this->I['accessKey']['alt'];
02452 
02453                         // Calling extra processing function
02454                     $this->extProc_beforeLinking($key);
02455 
02456                         // Set linking
02457                     if (!$this->I['noLink'])    {
02458                         $this->setATagParts();
02459                     } else {
02460                         $this->I['A1'] = '';
02461                         $this->I['A2'] = '';
02462                     }
02463                     $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']:'').' />';
02464 
02465                         // Make before, middle and after parts
02466                     $this->I['parts'] = array();
02467                     $this->I['parts']['ATag_begin'] = $this->I['A1'];
02468                     $this->I['parts']['image'] = $this->I['IMG'];
02469                     $this->I['parts']['ATag_end'] = $this->I['A2'];
02470 
02471                         // Passing I to a user function
02472                     if ($this->mconf['IProcFunc'])  {
02473                         $this->I = $this->userProcess('IProcFunc',$this->I);
02474                     }
02475 
02476                         // Putting the item together.
02477                         // Merge parts + beforeAllWrap
02478                     $this->I['theItem']= implode('',$this->I['parts']);
02479                     $this->I['theItem']= $this->extProc_beforeAllWrap($this->I['theItem'],$key);
02480 
02481                         // wrap:
02482                     $this->I['theItem']= $this->tmpl->wrap($this->I['theItem'],$this->I['val']['wrap']);
02483 
02484                         // allWrap:
02485                     $allWrap = isset($this->I['val']['allWrap.'])
02486                         ? $this->WMcObj->stdWrap($this->I['val']['allWrap'], $this->I['val']['allWrap.'])
02487                         : $this->I['val']['allWrap'];
02488                     $this->I['theItem'] = $this->tmpl->wrap($this->I['theItem'],$allWrap);
02489 
02490                     if ($this->I['val']['subst_elementUid'])    $this->I['theItem'] = str_replace('{elementUid}',$this->I['uid'],$this->I['theItem']);
02491 
02492                         // allStdWrap:
02493                     if (is_array($this->I['val']['allStdWrap.']))   {
02494                         $this->I['theItem'] = $this->WMcObj->stdWrap($this->I['theItem'], $this->I['val']['allStdWrap.']);
02495                     }
02496 
02497                     $GLOBALS['TSFE']->imagesOnPage[]=$this->I['val']['output_file'];
02498 
02499                     $this->extProc_afterLinking($key);
02500                 }
02501             }
02502             return $this->extProc_finish();
02503         }
02504     }
02505 
02506     /**
02507      * Called right before the traversing of $this->result begins.
02508      * Can be used for various initialization
02509      *
02510      * @return  void
02511      * @access private
02512      * @see writeMenu(), tslib_gmenu_layers::extProc_init()
02513      */
02514     function extProc_init() {
02515     }
02516 
02517     /**
02518      * Called after all processing for RollOver of an element has been done.
02519      *
02520      * @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!
02521      * @return  void
02522      * @access private
02523      * @see writeMenu(), tslib_gmenu_layers::extProc_RO()
02524      */
02525     function extProc_RO($key)   {
02526     }
02527 
02528     /**
02529      * Called right before the creation of the link for the menu item
02530      *
02531      * @param   integer     Pointer to $this->menuArr[$key] where the current menu element record is found
02532      * @return  void
02533      * @access private
02534      * @see writeMenu(), tslib_gmenu_layers::extProc_beforeLinking()
02535      */
02536     function extProc_beforeLinking($key)    {
02537     }
02538 
02539     /**
02540      * 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.
02541      * This function MUST set $this->WMresult.=[HTML for menu item] to add the generated menu item to the internal accumulation of items.
02542      * Further this calls the subMenu function in the parent class to create any submenu there might be.
02543      *
02544      * @param   integer     Pointer to $this->menuArr[$key] where the current menu element record is found
02545      * @return  void
02546      * @access private
02547      * @see writeMenu(), tslib_gmenu_layers::extProc_afterLinking(), tslib_menu::subMenu()
02548      */
02549     function extProc_afterLinking($key) {
02550             // Add part to the accumulated result + fetch submenus
02551         if (!$this->I['spacer'])    {
02552             $this->I['theItem'].= $this->subMenu($this->I['uid'], $this->WMsubmenuObjSuffixes[$key]['sOSuffix']);
02553         }
02554         $part = isset($this->I['val']['wrapItemAndSub.'])
02555             ? $this->WMcObj->stdWrap($this->I['val']['wrapItemAndSub'], $this->I['val']['wrapItemAndSub.'])
02556             : $this->I['val']['wrapItemAndSub'];
02557         $this->WMresult.= $part ? $this->tmpl->wrap($this->I['theItem'],$part) : $this->I['theItem'];
02558     }
02559 
02560 
02561     /**
02562      * Called before the "wrap" happens on the menu item.
02563      *
02564      * @param   string      The current content of the menu item, $this->I['theItem'], passed along.
02565      * @param   integer     Pointer to $this->menuArr[$key] where the current menu element record is found
02566      * @return  string      The modified version of $item, going back into $this->I['theItem']
02567      * @access private
02568      * @see writeMenu(), tslib_gmenu_layers::extProc_beforeAllWrap()
02569      */
02570     function extProc_beforeAllWrap($item,$key)  {
02571         return $item;
02572     }
02573 
02574     /**
02575      * Called before the writeMenu() function returns (only if a menu was generated)
02576      *
02577      * @return  string      The total menu content should be returned by this function
02578      * @access private
02579      * @see writeMenu(), tslib_gmenu_layers::extProc_finish()
02580      */
02581     function extProc_finish()   {
02582             // stdWrap:
02583         if (is_array($this->mconf['stdWrap.'])) {
02584             $this->WMresult = $this->WMcObj->stdWrap($this->WMresult, $this->mconf['stdWrap.']);
02585         }
02586         return $this->tmpl->wrap($this->WMresult,$this->mconf['wrap']).$this->WMextraScript;
02587     }
02588 }
02589 
02590 
02591 
02592 
02593 
02594 
02595 
02596 
02597 
02598 
02599 
02600 
02601 
02602 
02603 
02604 
02605 
02606 
02607 
02608 
02609 
02610 
02611 /**
02612  * ImageMap based menus
02613  *
02614  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
02615  * @package TYPO3
02616  * @subpackage tslib
02617  */
02618 class tslib_imgmenu extends tslib_menu {
02619 
02620     /**
02621      * Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
02622      * Calls makeImageMap() to generate the image map image-file
02623      *
02624      * @return  void
02625      * @see tslib_menu::procesItemStates(), makeImageMap()
02626      */
02627     function generate() {
02628         $splitCount = count($this->menuArr);
02629         if ($splitCount)    {
02630             list($NOconf) = $this->procesItemStates($splitCount);
02631         }
02632         if ($this->mconf['debugItemConf'])  {echo '<h3>$NOconf:</h3>';  debug($NOconf); }
02633         $this->makeImageMap($NOconf);
02634     }
02635 
02636     /**
02637      * Will traverse input array with configuratoin per-item and create corresponding GIF files for the menu.
02638      * The data of the files are stored in $this->result
02639      *
02640      * @param   array       Array with configuration for each item.
02641      * @return  void
02642      * @access private
02643      * @see generate()
02644      */
02645     function makeImageMap($conf)    {
02646         if (!is_array($conf)) {
02647             $conf = Array();
02648         }
02649         if (is_array($this->mconf['main.']))    {
02650             $gifCreator = t3lib_div::makeInstance('tslib_gifBuilder');
02651             $gifCreator->init();
02652 
02653             $itemsConf = $conf;
02654             $conf = $this->mconf['main.'];
02655             if (is_array($conf))    {
02656                 $gifObjCount = 0;
02657 
02658                 $sKeyArray=t3lib_TStemplate::sortedKeyList($conf);
02659                 $gifObjCount=intval(end($sKeyArray));
02660 
02661                 $lastOriginal = $gifObjCount;
02662 
02663                     // Now we add graphical objects to the gifbuilder-setup
02664                 $waArr = Array();
02665                 foreach ($itemsConf as $key => $val) {
02666                     if (is_array($val)) {
02667                         $gifObjCount++;
02668                         $waArr[$key]['free']=$gifObjCount;
02669 
02670                         $sKeyArray=t3lib_TStemplate::sortedKeyList($val);
02671 
02672                         foreach($sKeyArray as $theKey)  {
02673                             $theValue=$val[$theKey];
02674 
02675 
02676                             if (intval($theKey) && $theValArr=$val[$theKey.'.'])    {
02677                                 $cObjData = $this->menuArr[$key] ? $this->menuArr[$key] : Array();
02678 
02679                                 $gifObjCount++;
02680                                 if ($theValue=='TEXT') {
02681                                     $waArr[$key]['textNum']=$gifObjCount;
02682 
02683                                     $gifCreator->data = $cObjData;
02684                                     $theValArr = $gifCreator->checkTextObj($theValArr);
02685                                     unset($theValArr['text.']); // if this is not done it seems that imageMaps will be rendered wrong!!
02686                                         // check links
02687 
02688                                     $LD = $this->menuTypoLink($this->menuArr[$key],$this->mconf['target'],'','',array(),'',$this->mconf['forceTypeValue']);
02689 
02690                                         // If access restricted pages should be shown in menus, change the link of such pages to link to a redirection page:
02691                                     $this->changeLinksForAccessRestrictedPages($LD, $this->menuArr[$key], $this->mconf['target'], $this->mconf['forceTypeValue']);
02692 
02693                                         // Overriding URL / Target if set to do so:
02694                                     if ($this->menuArr[$key]['_OVERRIDE_HREF']) {
02695                                         $LD['totalURL'] = $this->menuArr[$key]['_OVERRIDE_HREF'];
02696                                         if ($this->menuArr[$key]['_OVERRIDE_TARGET'])   $LD['target'] = $this->menuArr[$key]['_OVERRIDE_TARGET'];
02697                                     }
02698 
02699                                         // Setting target/url for Image Map:
02700                                     if ($theValArr['imgMap.']['url']=='')   {
02701                                         $theValArr['imgMap.']['url'] = $LD['totalURL'];
02702                                     }
02703                                     if ($theValArr['imgMap.']['target']=='')    {
02704                                         $theValArr['imgMap.']['target'] = $LD['target'];
02705                                     }
02706                                     if ($theValArr['imgMap.']['noBlur']=='')    {
02707                                         $theValArr['imgMap.']['noBlur'] = $this->mconf['noBlur'];
02708                                     }
02709                                     if (is_array($theValArr['imgMap.']['altText.']))    {
02710                                         $cObj =t3lib_div::makeInstance('tslib_cObj');
02711                                         $cObj->start($cObjData,'pages');
02712                                         if(isset($theValArr['imgMap.']['altText.'])) {
02713                                             $theValArr['imgMap.']['altText'] = $cObj->stdWrap($theValArr['imgMap.']['altText'], $theValArr['imgMap.']['altText.']);
02714                                         }
02715                                         unset($theValArr['imgMap.']['altText.']);
02716                                 }
02717                                     if (is_array($theValArr['imgMap.']['titleText.']))  {
02718                                         $cObj =t3lib_div::makeInstance('tslib_cObj');
02719                                         $cObj->start($cObjData,'pages');
02720                                         if(isset($theValArr['imgMap.']['titleText.'])) {
02721                                             $theValArr['imgMap.']['titleText'] = $cObj->stdWrap($theValArr['imgMap.']['titleText'], $theValArr['imgMap.']['titleText.']);
02722                                         }
02723                                         unset($theValArr['imgMap.']['titleText.']);
02724                                     }
02725                                 }
02726                                     // This code goes one level in if the object is an image. If 'file' and/or 'mask' appears to be GIFBUILDER-objects, they are both searched for TEXT objects, and if a textobj is found, it's checked with the currently loaded record!!
02727                                 if ($theValue=='IMAGE') {
02728                                     if ($theValArr['file']=='GIFBUILDER')   {
02729                                         $temp_sKeyArray=t3lib_TStemplate::sortedKeyList($theValArr['file.']);
02730                                         foreach ($temp_sKeyArray as $temp_theKey) {
02731                                             if ($theValArr['mask.'][$temp_theKey]=='TEXT')  {
02732                                                 $gifCreator->data = $this->menuArr[$key] ? $this->menuArr[$key] : Array();
02733                                                 $theValArr['mask.'][$temp_theKey.'.'] = $gifCreator->checkTextObj($theValArr['mask.'][$temp_theKey.'.']);
02734                                                 unset($theValArr['mask.'][$temp_theKey.'.']['text.']);  // if this is not done it seems that imageMaps will be rendered wrong!!
02735                                             }
02736                                         }
02737                                     }
02738                                     if ($theValArr['mask']=='GIFBUILDER')   {
02739                                         $temp_sKeyArray=t3lib_TStemplate::sortedKeyList($theValArr['mask.']);
02740                                         foreach ($temp_sKeyArray as $temp_theKey) {
02741                                             if ($theValArr['mask.'][$temp_theKey]=='TEXT')  {
02742                                                 $gifCreator->data = $this->menuArr[$key] ? $this->menuArr[$key] : Array();
02743                                                 $theValArr['mask.'][$temp_theKey.'.'] = $gifCreator->checkTextObj($theValArr['mask.'][$temp_theKey.'.']);
02744                                                 unset($theValArr['mask.'][$temp_theKey.'.']['text.']);  // if this is not done it seems that imageMaps will be rendered wrong!!
02745                                             }
02746                                         }
02747                                     }
02748                                 }
02749 
02750                                     // Checks if disabled is set...
02751                                 $setObjFlag=1;
02752                                 if ($theValArr['if.'])  {
02753                                     $cObj =t3lib_div::makeInstance('tslib_cObj');
02754                                     $cObj->start($cObjData,'pages');
02755                                     if (!$cObj->checkIf($theValArr['if.'])) {
02756                                         $setObjFlag=0;
02757                                     }
02758                                     unset($theValArr['if.']);
02759                                 }
02760                                     // Set the object!
02761                                 if ($setObjFlag)    {
02762                                     $conf[$gifObjCount] = $theValue;
02763                                     $conf[$gifObjCount.'.'] = $theValArr;
02764                                 }
02765                             }
02766                         }
02767                     }
02768                 }
02769 
02770                 $gifCreator->start($conf,$GLOBALS['TSFE']->page);
02771                     // calculations
02772 
02773                 $sum=Array(0,0,0,0);
02774                 foreach ($waArr as $key => $val) {
02775                     if (($dConf[$key] = $itemsConf[$key]['distrib'])) {
02776                         $textBB = $gifCreator->objBB[$val['textNum']];
02777                         $dConf[$key] = str_replace('textX',$textBB[0],$dConf[$key]);
02778                         $dConf[$key] = str_replace('textY',$textBB[1],$dConf[$key]);
02779                         $dConf[$key] = t3lib_div::intExplode(',',$gifCreator->calcOffset($dConf[$key]));
02780                     }
02781                 }
02782                 $workArea = t3lib_div::intExplode(',',$gifCreator->calcOffset($this->mconf['dWorkArea']));
02783                 foreach ($waArr as $key => $val) {
02784                     $index = $val['free'];
02785                     $gifCreator->setup[$index] = 'WORKAREA';
02786                     $workArea[2] = $dConf[$key][2] ? $dConf[$key][2] : $dConf[$key][0];
02787                     $workArea[3] = $dConf[$key][3] ? $dConf[$key][3] : $dConf[$key][1];
02788 
02789                     $gifCreator->setup[$index.'.']['set'] = implode(',',$workArea);
02790                     $workArea[0]+=$dConf[$key][0];
02791                     $workArea[1]+=$dConf[$key][1];
02792                 }
02793 
02794                 if ($this->mconf['debugRenumberedObject'])  {echo '<h3>Renumbered GIFBUILDER object:</h3>'; debug($gifCreator->setup);}
02795 
02796                 $gifCreator->createTempSubDir('menu/');
02797                 $gifFileName = $gifCreator->fileName('menu/');
02798 
02799                     // Gets the ImageMap from the cache...
02800                 $imgHash = md5($gifFileName);
02801                 $imgMap = $this->sys_page->getHash($imgHash);
02802 
02803                 if ($imgMap && file_exists($gifFileName))   {       // File exists
02804                     $info = @getimagesize($gifFileName);
02805                     $w=$info[0];
02806                     $h=$info[1];
02807                 } else {        // file is generated
02808                     $gifCreator->make();
02809                     $w=$gifCreator->w;
02810                     $h=$gifCreator->h;
02811                     $gifCreator->output($gifFileName);
02812                     $gifCreator->destroy();
02813                     $imgMap=$gifCreator->map;
02814                     $this->sys_page->storeHash($imgHash, $imgMap, 'MENUIMAGEMAP');
02815                 }
02816                 $imgMap.=$this->mconf['imgMapExtras'];
02817 
02818                 $gifFileName = t3lib_div::png_to_gif_by_imagemagick($gifFileName);
02819                 $this->result = Array('output_file'=>$gifFileName, 'output_w'=>$w, 'output_h'=>$h, 'imgMap'=>$imgMap);
02820             }
02821         }
02822     }
02823 
02824     /**
02825      * Returns the HTML for the image map menu.
02826      * If ->result is true it will create the HTML for the image map menu.
02827      *
02828      * @return  string      The HTML for the menu
02829      */
02830     function writeMenu()    {
02831         if ($this->result)  {
02832             $res = &$this->result;
02833             $menuName = 'menu_'.t3lib_div::shortMD5($res['imgMap']);    // shortMD5 260900
02834             $result = '<img src="'.$GLOBALS['TSFE']->absRefPrefix.$res['output_file'].'" width="'.$res['output_w'].'" height="'.$res['output_h'].'" usemap="#'.$menuName.'" border="0" '.$this->mconf['params'];
02835             if (!strstr($result,'alt="'))   $result.=' alt="Menu Image Map"';   // Adding alt attribute if not set.
02836             $result.= ' /><map name="'.$menuName.'" id="'.$menuName.'">'.$res['imgMap'].'</map>';
02837 
02838             $GLOBALS['TSFE']->imagesOnPage[]=$res['output_file'];
02839 
02840             return $this->tmpl->wrap($result,$this->mconf['wrap']);
02841         }
02842     }
02843 }
02844 
02845 
02846 
02847 
02848 
02849 
02850 
02851 
02852 
02853 
02854 
02855 
02856 
02857 
02858 
02859 
02860 
02861 
02862 
02863 
02864 
02865 /**
02866  * JavaScript/Selectorbox based menus
02867  *
02868  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
02869  * @package TYPO3
02870  * @subpackage tslib
02871  */
02872 class tslib_jsmenu extends tslib_menu {
02873 
02874     /**
02875      * Dummy. Should do nothing, because we don't use the result-array here!
02876      *
02877      * @return  void
02878      */
02879     function generate() {
02880     }
02881 
02882     /**
02883      * Creates the HTML (mixture of a <form> and a JavaScript section) for the JavaScript menu (basically an array of selector boxes with onchange handlers)
02884      *
02885      * @return  string      The HTML code for the menu
02886      */
02887     function writeMenu()    {
02888         if ($this->id)  {
02889                 // Making levels:
02890             $levels = t3lib_div::intInRange($this->mconf['levels'],1,5);
02891             $this->levels = $levels;
02892             $uniqueParam = t3lib_div::shortMD5(microtime(), 5);
02893             $this->JSVarName = 'eid' . $uniqueParam;
02894             $this->JSMenuName = ($this->mconf['menuName'] ? $this->mconf['menuName'] : 'JSmenu' . $uniqueParam);
02895 
02896             $JScode="\n var ".$this->JSMenuName." = new JSmenu(".$levels.",'".$this->JSMenuName."Form');";
02897 
02898             for ($a=1;$a<=$levels;$a++) {
02899                 $JScode.="\n var ".$this->JSVarName.$a."=0;";
02900             }
02901             $JScode.= $this->generate_level($levels,1,$this->id,$this->menuArr,$this->MP_array).LF;
02902 
02903             $GLOBALS['TSFE']->additionalHeaderData['JSMenuCode']='<script type="text/javascript" src="'.$GLOBALS['TSFE']->absRefPrefix.'t3lib/jsfunc.menu.js"></script>';
02904             $GLOBALS['TSFE']->JSCode.=$JScode;
02905 
02906                 // Printing:
02907             $allFormCode="";
02908             for ($a=1;$a<=$this->levels;$a++)   {
02909                 $formCode='';
02910                 $levelConf = $this->mconf[$a.'.'];
02911                 $length = $levelConf['width'] ? $levelConf['width'] : 14;
02912                 $lenghtStr='';
02913                 for ($b=0;$b<$length;$b++)  {
02914                     $lenghtStr.='_';
02915                 }
02916                 $height = $levelConf['elements'] ? $levelConf['elements'] : 5;
02917 
02918                 $formCode.= '<select name="selector'.$a.'" onchange="'.$this->JSMenuName.'.act('.$a.');"'.($levelConf['additionalParams']?' '.$levelConf['additionalParams']:'').'>';
02919                 for ($b=0;$b<$height;$b++)  {
02920                     $formCode.= '<option value="0">';
02921                     if ($b==0)  {
02922                         $formCode.= $lenghtStr;
02923                     }
02924                     $formCode.='</option>';
02925                 }
02926                 $formCode.= '</select>';
02927                 $allFormCode.=$this->tmpl->wrap($formCode,$levelConf['wrap']);
02928             }
02929             $formCode = $this->tmpl->wrap($allFormCode,$this->mconf['wrap']);
02930 
02931             $formCode= '<form action="" method="post" style="margin: 0 0 0 0;" name="'.$this->JSMenuName.'Form">'.$formCode.'</form>';
02932             $formCode.='<script type="text/javascript"> /*<![CDATA[*/ '.$this->JSMenuName.'.writeOut(1,'.$this->JSMenuName.'.openID,1); /*]]>*/ </script>';
02933             return $this->tmpl->wrap($formCode,$this->mconf['wrapAfterTags']);
02934         }
02935     }
02936 
02937     /**
02938      * Generates a number of lines of JavaScript code for a menu level.
02939      * Calls itself recursively for additional levels.
02940      *
02941      * @param   integer     Number of levels to generate
02942      * @param   integer     Current level being generated - and if this number is less than $levels it will call itself recursively with $count incremented
02943      * @param   integer     Page id of the starting point.
02944      * @param   array       $this->menuArr passed along
02945      * @param   array       Previous MP vars
02946      * @return  string      JavaScript code lines.
02947      * @access private
02948      */
02949     function generate_level($levels,$count,$pid,$menuItemArray='',$MP_array=array())    {
02950         $levelConf = $this->mconf[$count.'.'];
02951 
02952             // Translate PID to a mount page, if any:
02953         $mount_info = $this->sys_page->getMountPointInfo($pid);
02954         if (is_array($mount_info))  {
02955             $MP_array[] = $mount_info['MPvar'];
02956             $pid = $mount_info['mount_pid'];
02957         }
02958 
02959             // UIDs to ban:
02960         $banUidArray = $this->getBannedUids();
02961 
02962             // Initializing variables:
02963         $var = $this->JSVarName;
02964         $menuName = $this->JSMenuName;
02965         $parent = $count==1 ? 0 : $var.($count-1);
02966         $prev=0;
02967         $c=0;
02968 
02969         $menuItems = is_array($menuItemArray) ? $menuItemArray : $this->sys_page->getMenu($pid);
02970         foreach($menuItems as $uid => $data)    {
02971 
02972                 // $data['_MP_PARAM'] contains MP param for overlay mount points (MPs with "substitute this page" set)
02973                 // if present: add param to copy of MP array (copy used for that submenu branch only)
02974             $MP_array_sub = $MP_array;
02975             if (array_key_exists('_MP_PARAM', $data) && $data['_MP_PARAM']) {
02976                 $MP_array_sub[] = $data['_MP_PARAM'];
02977             }
02978                 // Set "&MP=" var:
02979             $MP_var = implode(',', $MP_array_sub);
02980             $MP_params = ($MP_var ? '&MP='.rawurlencode($MP_var) : '');
02981 
02982             $spacer = (t3lib_div::inList($this->spacerIDList,$data['doktype'])?1:0);        // if item is a spacer, $spacer is set
02983             if ($this->mconf['SPC'] || !$spacer)    {   // If the spacer-function is not enabled, spacers will not enter the $menuArr
02984                 if (!t3lib_div::inList($this->doktypeExcludeList,$data['doktype']) && (!$data['nav_hide'] || $this->conf['includeNotInMenu']) && !t3lib_div::inArray($banUidArray,$uid))    {       // Page may not be 'not_in_menu' or 'Backend User Section' + not in banned uid's
02985                     if ($count<$levels) {
02986                         $addLines = $this->generate_level($levels, $count+1, $data['uid'], '', $MP_array_sub);
02987                     } else {
02988                         $addLines = '';
02989                     }
02990                     $title=$data['title'];
02991                     $url='';
02992                     $target='';
02993                     if ((!$addLines && !$levelConf['noLink']) || $levelConf['alwaysLink']) {
02994                         $LD = $this->menuTypoLink($data,$this->mconf['target'],'','',array(),$MP_params,$this->mconf['forceTypeValue']);
02995 
02996                             // If access restricted pages should be shown in menus, change the link of such pages to link to a redirection page:
02997                         $this->changeLinksForAccessRestrictedPages($LD, $data, $this->mconf['target'], $this->mconf['forceTypeValue']);
02998 
02999                         $url = $GLOBALS['TSFE']->baseUrlWrap($LD['totalURL']);
03000                         $target = $LD['target'];
03001                     }
03002                     $codeLines.=LF.$var.$count."=".$menuName.".add(".$parent.",".$prev.",0,".t3lib_div::quoteJSvalue($title, true).",".t3lib_div::quoteJSvalue($url, true).",".t3lib_div::quoteJSvalue($target, true).");";
03003                         // If the active one should be chosen...
03004                     $active = ($levelConf['showActive'] && $this->isActive($data['uid'], $MP_var));
03005                         // If the first item should be shown
03006                     $first = (!$c && $levelConf['showFirst']);
03007                         // do it...
03008                     if ($active || $first)  {
03009                         if ($count==1)  {
03010                             $codeLines.=LF.$menuName.".openID = ".$var.$count.";";
03011                         } else {
03012                             $codeLines.=LF.$menuName.".entry[".$parent."].openID = ".$var.$count.";";
03013                         }
03014                     }
03015                         // Add submenu...
03016                     $codeLines.=$addLines;
03017 
03018                     $prev=$var.$count;
03019                     $c++;
03020                 }
03021             }
03022         }
03023         if ($this->mconf['firstLabelGeneral'] && !$levelConf['firstLabel']) {
03024             $levelConf['firstLabel'] = $this->mconf['firstLabelGeneral'];
03025         }
03026         if ($levelConf['firstLabel'] && $codeLines) {
03027             $codeLines.= LF.$menuName.'.defTopTitle['.$count.'] = '.t3lib_div::quoteJSvalue($levelConf['firstLabel'], true).';';
03028         }
03029         return $codeLines;
03030     }
03031 }
03032 
03033 
03034 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['tslib/class.tslib_menu.php'])) {
03035     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['tslib/class.tslib_menu.php']);
03036 }
03037 
03038 ?>