| 1 | 827 | doc | <?php
 | 
      
        | 2 | 860 | Ruebenwurz | 
 | 
      
        | 3 |  |  | // $Id$
 | 
      
        | 4 |  |  | 
 | 
      
        | 5 | 827 | doc | /*
 | 
      
        | 6 |  |  |     show_menu2: show_menu replacement for Website Baker
 | 
      
        | 7 | 915 | Ruebenwurz |     Copyright (C) 2006-2009, Brodie Thiesfield
 | 
      
        | 8 | 827 | doc | 
 | 
      
        | 9 |  |  |     This program is free software; you can redistribute it and/or
 | 
      
        | 10 |  |  |     modify it under the terms of the GNU General Public License
 | 
      
        | 11 |  |  |     as published by the Free Software Foundation; either version 2
 | 
      
        | 12 |  |  |     of the License, or (at your option) any later version.
 | 
      
        | 13 |  |  | 
 | 
      
        | 14 |  |  |     This program is distributed in the hope that it will be useful,
 | 
      
        | 15 |  |  |     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
      
        | 16 |  |  |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
      
        | 17 |  |  |     GNU General Public License for more details.
 | 
      
        | 18 |  |  | 
 | 
      
        | 19 |  |  |     You should have received a copy of the GNU General Public License
 | 
      
        | 20 |  |  |     along with this program; if not, write to the Free Software
 | 
      
        | 21 |  |  |     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
      
        | 22 |  |  |     02110-1301, USA.
 | 
      
        | 23 |  |  | 
 | 
      
        | 24 |  |  |     ***********************************************
 | 
      
        | 25 | 971 | Ruebenwurz |     ** Version 4.8: see README for documentation **
 | 
      
        | 26 | 827 | doc |     ***********************************************
 | 
      
        | 27 |  |  | */
 | 
      
        | 28 |  |  | 
 | 
      
        | 29 |  |  | define('SM2_ROOT',       -1000);
 | 
      
        | 30 |  |  | define('SM2_CURR',       -2000);
 | 
      
        | 31 |  |  | define('SM2_ALLMENU',       -1);
 | 
      
        | 32 |  |  | define('SM2_START',       1000);
 | 
      
        | 33 |  |  | define('SM2_MAX',         2000);
 | 
      
        | 34 |  |  | define('SM2_ALL',       0x0001); // bit 0 (group 1) (Note: also used for max level!)
 | 
      
        | 35 |  |  | define('SM2_TRIM',      0x0002); // bit 1 (group 1)
 | 
      
        | 36 |  |  | define('SM2_CRUMB',     0x0004); // bit 2 (group 1)
 | 
      
        | 37 |  |  | define('SM2_SIBLING',   0x0008); // bit 3 (group 1)
 | 
      
        | 38 |  |  | define('SM2_NUMCLASS',  0x0010); // bit 4
 | 
      
        | 39 |  |  | define('SM2_ALLINFO',   0x0020); // bit 5
 | 
      
        | 40 |  |  | define('SM2_NOCACHE',   0x0040); // bit 6
 | 
      
        | 41 |  |  | define('SM2_PRETTY',    0x0080); // bit 7
 | 
      
        | 42 |  |  | define('SM2_ESCAPE',    0x0100); // bit 8
 | 
      
        | 43 |  |  | define('SM2_NOESCAPE',       0); // NOOP, unnecessary with WB 2.6.7+
 | 
      
        | 44 |  |  | define('SM2_BUFFER',    0x0200); // bit 9
 | 
      
        | 45 |  |  | define('SM2_CURRTREE',  0x0400); // bit 10
 | 
      
        | 46 |  |  | 
 | 
      
        | 47 |  |  | define('_SM2_GROUP_1',  0x000F); // exactly one flag from group 1 is required
 | 
      
        | 48 |  |  | 
 | 
      
        | 49 |  |  | 
 | 
      
        | 50 |  |  | // Implement support for page_menu and show_menu using show_menu2. If you remove
 | 
      
        | 51 |  |  | // the comments characters from the beginning of the following include, all menu
 | 
      
        | 52 |  |  | // functions in Website Baker will be implemented using show_menu2. While it is
 | 
      
        | 53 |  |  | // commented out, the original WB functions will be used.
 | 
      
        | 54 |  |  | //include('legacy.php');
 | 
      
        | 55 |  |  | 
 | 
      
        | 56 |  |  | // This class is the default menu formatter for sm2. If desired, you can
 | 
      
        | 57 |  |  | // create your own formatter class and pass the object into show_menu2
 | 
      
        | 58 |  |  | // as $aItemFormat.
 | 
      
        | 59 |  |  | define('SM2_CONDITIONAL','if\s*\(([^\)]+)\)\s*{([^}]*)}\s*(?:else\s*{([^}]*)}\s*)?');
 | 
      
        | 60 |  |  | define('SM2_COND_TERM','\s*(\w+)\s*(<|<=|==|=|=>|>|!=)\s*([\w\-]+)\s*');
 | 
      
        | 61 |  |  | class SM2_Formatter
 | 
      
        | 62 |  |  | {
 | 
      
        | 63 |  |  |     var $output;
 | 
      
        | 64 |  |  |     var $flags;
 | 
      
        | 65 |  |  |     var $itemOpen;
 | 
      
        | 66 |  |  |     var $itemClose;
 | 
      
        | 67 |  |  |     var $menuOpen;
 | 
      
        | 68 |  |  |     var $menuClose;
 | 
      
        | 69 |  |  |     var $topItemOpen;
 | 
      
        | 70 |  |  |     var $topMenuOpen;
 | 
      
        | 71 |  |  | 
 | 
      
        | 72 |  |  |     var $isFirst;
 | 
      
        | 73 |  |  |     var $page;
 | 
      
        | 74 |  |  |     var $url;
 | 
      
        | 75 |  |  |     var $currSib;
 | 
      
        | 76 |  |  |     var $sibCount;
 | 
      
        | 77 |  |  |     var $currClass;
 | 
      
        | 78 |  |  |     var $prettyLevel;
 | 
      
        | 79 |  |  | 
 | 
      
        | 80 |  |  |     // output the data
 | 
      
        | 81 |  |  |     function output($aString) {
 | 
      
        | 82 |  |  |         if ($this->flags & SM2_BUFFER) {
 | 
      
        | 83 |  |  |             $this->output .= $aString;
 | 
      
        | 84 |  |  |         }
 | 
      
        | 85 |  |  |         else {
 | 
      
        | 86 |  |  |             echo $aString;
 | 
      
        | 87 |  |  |         }
 | 
      
        | 88 |  |  |     }
 | 
      
        | 89 |  |  | 
 | 
      
        | 90 |  |  |     // set the default values for all of our formatting items
 | 
      
        | 91 |  |  |     function set($aFlags, $aItemOpen, $aItemClose, $aMenuOpen, $aMenuClose, $aTopItemOpen, $aTopMenuOpen) {
 | 
      
        | 92 |  |  |         $this->flags        = $aFlags;
 | 
      
        | 93 |  |  |         $this->itemOpen     = is_string($aItemOpen)    ? $aItemOpen    : '[li][a][menu_title]</a>';
 | 
      
        | 94 |  |  |         $this->itemClose    = is_string($aItemClose)   ? $aItemClose   : '</li>';
 | 
      
        | 95 |  |  |         $this->menuOpen     = is_string($aMenuOpen)    ? $aMenuOpen    : '[ul]';
 | 
      
        | 96 |  |  |         $this->menuClose    = is_string($aMenuClose)   ? $aMenuClose   : '</ul>';
 | 
      
        | 97 |  |  |         $this->topItemOpen  = is_string($aTopItemOpen) ? $aTopItemOpen : $this->itemOpen;
 | 
      
        | 98 |  |  |         $this->topMenuOpen  = is_string($aTopMenuOpen) ? $aTopMenuOpen : $this->menuOpen;
 | 
      
        | 99 |  |  |     }
 | 
      
        | 100 |  |  | 
 | 
      
        | 101 |  |  |     // initialize the state of the formatter before anything is output
 | 
      
        | 102 |  |  |     function initialize() {
 | 
      
        | 103 |  |  |         $this->output = '';
 | 
      
        | 104 |  |  |         $this->prettyLevel = 0;
 | 
      
        | 105 |  |  |         if ($this->flags & SM2_PRETTY) {
 | 
      
        | 106 |  |  |             $this->output("\n<!-- show_menu2 -->");
 | 
      
        | 107 |  |  |         }
 | 
      
        | 108 |  |  |     }
 | 
      
        | 109 |  |  | 
 | 
      
        | 110 |  |  |     // start a menu
 | 
      
        | 111 |  |  |     function startList(&$aPage, &$aUrl) {
 | 
      
        | 112 |  |  |         $currClass = '';
 | 
      
        | 113 |  |  |         $currItem = $this->menuOpen;
 | 
      
        | 114 |  |  | 
 | 
      
        | 115 |  |  |         // use the top level menu open if this is the first menu
 | 
      
        | 116 |  |  |         if ($this->topMenuOpen) {
 | 
      
        | 117 |  |  |             $currItem = $this->topMenuOpen;
 | 
      
        | 118 |  |  |             $currClass .= ' menu-top';
 | 
      
        | 119 |  |  |             $this->topMenuOpen = false;
 | 
      
        | 120 |  |  |         }
 | 
      
        | 121 |  |  | 
 | 
      
        | 122 |  |  |         // add the numbered menu class only if requested
 | 
      
        | 123 |  |  |         if (($this->flags & SM2_NUMCLASS) == SM2_NUMCLASS) {
 | 
      
        | 124 |  |  |             $currClass .= ' menu-'.$aPage['level'];
 | 
      
        | 125 |  |  |         }
 | 
      
        | 126 |  |  | 
 | 
      
        | 127 |  |  |         $this->prettyLevel += 1;
 | 
      
        | 128 |  |  | 
 | 
      
        | 129 |  |  |         // replace all keywords in the output
 | 
      
        | 130 |  |  |         if ($this->flags & SM2_PRETTY) {
 | 
      
        | 131 |  |  |             $this->output("\n".str_repeat(' ',$this->prettyLevel).
 | 
      
        | 132 |  |  |                 $this->format($aPage, $aUrl, $currItem, $currClass));
 | 
      
        | 133 |  |  |         }
 | 
      
        | 134 |  |  |         else {
 | 
      
        | 135 |  |  |             $this->output($this->format($aPage, $aUrl, $currItem, $currClass));
 | 
      
        | 136 |  |  |         }
 | 
      
        | 137 |  |  | 
 | 
      
        | 138 |  |  |         $this->prettyLevel += 3;
 | 
      
        | 139 |  |  |     }
 | 
      
        | 140 |  |  | 
 | 
      
        | 141 |  |  |     // start an item within the menu
 | 
      
        | 142 |  |  |     function startItem(&$aPage, &$aUrl, $aCurrSib, $aSibCount) {
 | 
      
        | 143 |  |  |         // generate our class list
 | 
      
        | 144 |  |  |         $currClass = '';
 | 
      
        | 145 |  |  |         if (($this->flags & SM2_NUMCLASS) == SM2_NUMCLASS) {
 | 
      
        | 146 |  |  |             $currClass .= ' menu-'.$aPage['level'];
 | 
      
        | 147 |  |  |         }
 | 
      
        | 148 |  |  |         if (array_key_exists('sm2_has_child', $aPage)) {
 | 
      
        | 149 |  |  |             // not set if false, so existence = true
 | 
      
        | 150 |  |  |             $currClass .= ' menu-expand';
 | 
      
        | 151 |  |  |         }
 | 
      
        | 152 | 845 | doc |         if (array_key_exists('sm2_is_curr', $aPage)) {
 | 
      
        | 153 | 827 | doc |             $currClass .= ' menu-current';
 | 
      
        | 154 |  |  |         }
 | 
      
        | 155 |  |  |         elseif (array_key_exists('sm2_is_parent', $aPage)) {
 | 
      
        | 156 |  |  |             // not set if false, so existence = true
 | 
      
        | 157 |  |  |             $currClass .= ' menu-parent';
 | 
      
        | 158 |  |  |         }
 | 
      
        | 159 |  |  |         elseif (array_key_exists('sm2_is_sibling', $aPage)) {
 | 
      
        | 160 |  |  |             // not set if false, so existence = true
 | 
      
        | 161 |  |  |             $currClass .= ' menu-sibling';
 | 
      
        | 162 |  |  |         }
 | 
      
        | 163 |  |  |         elseif (array_key_exists('sm2_child_level',$aPage)) {
 | 
      
        | 164 |  |  |             // not set if not a child
 | 
      
        | 165 |  |  |             $currClass .= ' menu-child';
 | 
      
        | 166 |  |  |             if (($this->flags & SM2_NUMCLASS) == SM2_NUMCLASS) {
 | 
      
        | 167 |  |  |                 $currClass .= ' menu-child-'.($aPage['sm2_child_level']-1);
 | 
      
        | 168 |  |  |             }
 | 
      
        | 169 |  |  |         }
 | 
      
        | 170 |  |  |         if ($aCurrSib == 1) {
 | 
      
        | 171 |  |  |             $currClass .= ' menu-first';
 | 
      
        | 172 |  |  |         }
 | 
      
        | 173 |  |  |         if ($aCurrSib == $aSibCount) {
 | 
      
        | 174 |  |  |             $currClass .= ' menu-last';
 | 
      
        | 175 |  |  |         }
 | 
      
        | 176 |  |  | 
 | 
      
        | 177 |  |  |         // use the top level item if this is the first item
 | 
      
        | 178 |  |  |         $currItem = $this->itemOpen;
 | 
      
        | 179 |  |  |         if ($this->topItemOpen) {
 | 
      
        | 180 |  |  |             $currItem = $this->topItemOpen;
 | 
      
        | 181 |  |  |             $this->topItemOpen = false;
 | 
      
        | 182 |  |  |         }
 | 
      
        | 183 |  |  | 
 | 
      
        | 184 |  |  |         // replace all keywords in the output
 | 
      
        | 185 |  |  |         if ($this->flags & SM2_PRETTY) {
 | 
      
        | 186 |  |  |             $this->output("\n".str_repeat(' ',$this->prettyLevel));
 | 
      
        | 187 |  |  |         }
 | 
      
        | 188 |  |  |         $this->output($this->format($aPage, $aUrl, $currItem, $currClass, $aCurrSib, $aSibCount));
 | 
      
        | 189 |  |  |     }
 | 
      
        | 190 |  |  | 
 | 
      
        | 191 |  |  |     // find and replace all keywords, setting the state variables first
 | 
      
        | 192 |  |  |     function format(&$aPage, &$aUrl, &$aCurrItem, &$aCurrClass,
 | 
      
        | 193 |  |  |         $aCurrSib = 0, $aSibCount = 0)
 | 
      
        | 194 |  |  |     {
 | 
      
        | 195 |  |  |         $this->page      = &$aPage;
 | 
      
        | 196 |  |  |         $this->url       = &$aUrl;
 | 
      
        | 197 |  |  |         $this->currClass = trim($aCurrClass);
 | 
      
        | 198 |  |  |         $this->currSib   = $aCurrSib;
 | 
      
        | 199 |  |  |         $this->sibCount  = $aSibCount;
 | 
      
        | 200 |  |  | 
 | 
      
        | 201 |  |  |         $item = $this->format2($aCurrItem);
 | 
      
        | 202 |  |  | 
 | 
      
        | 203 |  |  |         unset($this->page);
 | 
      
        | 204 |  |  |         unset($this->url);
 | 
      
        | 205 |  |  |         unset($this->currClass);
 | 
      
        | 206 |  |  | 
 | 
      
        | 207 |  |  |         return $item;
 | 
      
        | 208 |  |  |     }
 | 
      
        | 209 |  |  | 
 | 
      
        | 210 |  |  |     // find and replace all keywords
 | 
      
        | 211 |  |  |     function format2(&$aCurrItem) {
 | 
      
        | 212 |  |  |         if (!is_string($aCurrItem)) return '';
 | 
      
        | 213 |  |  |         return preg_replace(
 | 
      
        | 214 |  |  |             '@\[('.
 | 
      
        | 215 |  |  |                 'a|ac|/a|li|/li|ul|/ul|menu_title|page_title|url|target|page_id|'.
 | 
      
        | 216 |  |  |                 'parent|level|sib|sibCount|class|description|keywords|'.
 | 
      
        | 217 |  |  |                 SM2_CONDITIONAL.
 | 
      
        | 218 |  |  |             ')\]@e',
 | 
      
        | 219 |  |  |             '$this->replace("\1")', $aCurrItem);
 | 
      
        | 220 |  |  |     }
 | 
      
        | 221 |  |  | 
 | 
      
        | 222 |  |  |     // replace the keywords
 | 
      
        | 223 |  |  |     function replace($aMatch) {
 | 
      
        | 224 |  |  |         switch ($aMatch) {
 | 
      
        | 225 |  |  |         case 'a':
 | 
      
        | 226 |  |  |             return '<a href="'.$this->url.'" target="'.$this->page['target'].'">';
 | 
      
        | 227 |  |  |         case 'ac':
 | 
      
        | 228 |  |  |             return '<a href="'.$this->url.'" target="'.$this->page['target'].'" class="'.$this->currClass.'">';
 | 
      
        | 229 |  |  |         case '/a':
 | 
      
        | 230 |  |  |             return '</a>';
 | 
      
        | 231 |  |  |         case 'li':
 | 
      
        | 232 |  |  |             return '<li class="'.$this->currClass.'">';
 | 
      
        | 233 |  |  |         case '/li':
 | 
      
        | 234 |  |  |             return '</li>';
 | 
      
        | 235 |  |  |         case 'ul':
 | 
      
        | 236 |  |  |             return '<ul class="'.$this->currClass.'">';
 | 
      
        | 237 |  |  |         case '/ul':
 | 
      
        | 238 |  |  |             return '</ul>';
 | 
      
        | 239 |  |  |         case 'url':
 | 
      
        | 240 |  |  |             return $this->url;
 | 
      
        | 241 |  |  |         case 'sib':
 | 
      
        | 242 |  |  |             return $this->currSib;
 | 
      
        | 243 |  |  |         case 'sibCount':
 | 
      
        | 244 |  |  |             return $this->sibCount;
 | 
      
        | 245 |  |  |         case 'class':
 | 
      
        | 246 |  |  |             return $this->currClass;
 | 
      
        | 247 |  |  |         default:
 | 
      
        | 248 |  |  |             if (array_key_exists($aMatch, $this->page)) {
 | 
      
        | 249 |  |  |                 if ($this->flags & SM2_ESCAPE) {
 | 
      
        | 250 |  |  |                     return htmlspecialchars($this->page[$aMatch], ENT_QUOTES);
 | 
      
        | 251 |  |  |                 }
 | 
      
        | 252 |  |  |                 else {
 | 
      
        | 253 |  |  |                     return $this->page[$aMatch];
 | 
      
        | 254 |  |  |                 }
 | 
      
        | 255 |  |  |             }
 | 
      
        | 256 |  |  |             if (preg_match('/'.SM2_CONDITIONAL.'/', $aMatch, $rgMatches)) {
 | 
      
        | 257 |  |  |                 return $this->replaceIf($rgMatches[1], $rgMatches[2], $rgMatches[3]);
 | 
      
        | 258 |  |  |             }
 | 
      
        | 259 |  |  |         }
 | 
      
        | 260 |  |  |         return "[$aMatch=UNKNOWN]";
 | 
      
        | 261 |  |  |     }
 | 
      
        | 262 |  |  | 
 | 
      
        | 263 |  |  |     // conditional replacement
 | 
      
        | 264 |  |  |     function replaceIf(&$aExpression, &$aIfValue, &$aElseValue) {
 | 
      
        | 265 |  |  |         // evaluate all of the tests in the conditional (we don't do short-circuit
 | 
      
        | 266 |  |  |         // evaluation) and replace the string test with the boolean result
 | 
      
        | 267 |  |  |         $rgTests = preg_split('/(\|\||\&\&)/', $aExpression, -1, PREG_SPLIT_DELIM_CAPTURE);
 | 
      
        | 268 |  |  |         for ($n = 0; $n < count($rgTests); $n += 2) {
 | 
      
        | 269 |  |  |             if (preg_match('/'.SM2_COND_TERM.'/', $rgTests[$n], $rgMatches)) {
 | 
      
        | 270 |  |  |                 $rgTests[$n] = $this->ifTest($rgMatches[1], $rgMatches[2], $rgMatches[3]);
 | 
      
        | 271 |  |  |             }
 | 
      
        | 272 |  |  |             else {
 | 
      
        | 273 |  |  |                 error_log("show_menu2 error: conditional expression is invalid!");
 | 
      
        | 274 |  |  |                 $rgTests[$n] = false;
 | 
      
        | 275 |  |  |             }
 | 
      
        | 276 |  |  |         }
 | 
      
        | 277 |  |  | 
 | 
      
        | 278 |  |  |         // combine all test results for a final result
 | 
      
        | 279 |  |  |         $ok = $rgTests[0];
 | 
      
        | 280 |  |  |         for ($n = 1; $n+1 < count($rgTests); $n += 2) {
 | 
      
        | 281 |  |  |             if ($rgTests[$n] == '||') {
 | 
      
        | 282 |  |  |                 $ok = $ok || $rgTests[$n+1];
 | 
      
        | 283 |  |  |             }
 | 
      
        | 284 |  |  |             else {
 | 
      
        | 285 |  |  |                 $ok = $ok && $rgTests[$n+1];
 | 
      
        | 286 |  |  |             }
 | 
      
        | 287 |  |  |         }
 | 
      
        | 288 |  |  | 
 | 
      
        | 289 |  |  |         // return the formatted expression if the test succeeded
 | 
      
        | 290 |  |  |         return $ok ? $this->format2($aIfValue) : $this->format2($aElseValue);
 | 
      
        | 291 |  |  |     }
 | 
      
        | 292 |  |  | 
 | 
      
        | 293 |  |  |     // conditional test
 | 
      
        | 294 |  |  |     function ifTest(&$aKey, &$aOperator, &$aValue) {
 | 
      
        | 295 |  |  |         global $wb;
 | 
      
        | 296 |  |  | 
 | 
      
        | 297 |  |  |         // find the correct operand
 | 
      
        | 298 |  |  |         $operand = false;
 | 
      
        | 299 |  |  |         switch($aKey) {
 | 
      
        | 300 |  |  |         case 'class':
 | 
      
        | 301 |  |  |             // we need to wrap the class names in spaces so we can test for a unique
 | 
      
        | 302 |  |  |             // class name that will not match prefixes or suffixes. Same must be done
 | 
      
        | 303 |  |  |             // for the value we are testing.
 | 
      
        | 304 |  |  |             $operand = " $this->currClass ";
 | 
      
        | 305 |  |  |             break;
 | 
      
        | 306 |  |  |         case 'sib':
 | 
      
        | 307 |  |  |             $operand = $this->currSib;
 | 
      
        | 308 |  |  |             if ($aValue == 'sibCount') {
 | 
      
        | 309 |  |  |                 $aValue = $this->sibCount;
 | 
      
        | 310 |  |  |             }
 | 
      
        | 311 |  |  |             break;
 | 
      
        | 312 |  |  |         case 'sibCount':
 | 
      
        | 313 |  |  |             $operand = $this->sibCount;
 | 
      
        | 314 |  |  |             break;
 | 
      
        | 315 |  |  |         case 'level':
 | 
      
        | 316 |  |  |             $operand = $this->page['level'];
 | 
      
        | 317 |  |  |             switch ($aValue) {
 | 
      
        | 318 |  |  |             case 'root':    $aValue = 0; break;
 | 
      
        | 319 |  |  |             case 'granny':  $aValue = $wb->page['level']-2; break;
 | 
      
        | 320 |  |  |             case 'parent':  $aValue = $wb->page['level']-1; break;
 | 
      
        | 321 |  |  |             case 'current': $aValue = $wb->page['level'];   break;
 | 
      
        | 322 |  |  |             case 'child':   $aValue = $wb->page['level']+1; break;
 | 
      
        | 323 |  |  |             }
 | 
      
        | 324 |  |  |             if ($aValue < 0) $aValue = 0;
 | 
      
        | 325 |  |  |             break;
 | 
      
        | 326 |  |  |         case 'id':
 | 
      
        | 327 |  |  |             $operand = $this->page['page_id'];
 | 
      
        | 328 |  |  |             switch ($aValue) {
 | 
      
        | 329 |  |  |             case 'parent':  $aValue = $wb->page['parent'];  break;
 | 
      
        | 330 |  |  |             case 'current': $aValue = $wb->page['page_id']; break;
 | 
      
        | 331 |  |  |             }
 | 
      
        | 332 |  |  |             break;
 | 
      
        | 333 |  |  |         default:
 | 
      
        | 334 |  |  |             return '';
 | 
      
        | 335 |  |  |         }
 | 
      
        | 336 |  |  | 
 | 
      
        | 337 |  |  |         // do the test
 | 
      
        | 338 |  |  |         $ok = false;
 | 
      
        | 339 |  |  |         switch ($aOperator) {
 | 
      
        | 340 |  |  |         case '<':
 | 
      
        | 341 |  |  |             $ok = ($operand < $aValue);
 | 
      
        | 342 |  |  |             break;
 | 
      
        | 343 |  |  |         case '<=':
 | 
      
        | 344 |  |  |             $ok = ($operand <= $aValue);
 | 
      
        | 345 |  |  |             break;
 | 
      
        | 346 |  |  |         case '=':
 | 
      
        | 347 |  |  |         case '==':
 | 
      
        | 348 |  |  |         case '!=':
 | 
      
        | 349 |  |  |             if ($aKey == 'class') {
 | 
      
        | 350 |  |  |                 $ok = strstr($operand, " $aValue ") !== FALSE;
 | 
      
        | 351 |  |  |             }
 | 
      
        | 352 |  |  |             else {
 | 
      
        | 353 |  |  |                 $ok = ($operand == $aValue);
 | 
      
        | 354 |  |  |             }
 | 
      
        | 355 |  |  |             if ($aOperator == '!=') {
 | 
      
        | 356 |  |  |                 $ok = !$ok;
 | 
      
        | 357 |  |  |             }
 | 
      
        | 358 |  |  |             break;
 | 
      
        | 359 |  |  |         case '>=':
 | 
      
        | 360 |  |  |             $ok = ($operand >= $aValue);
 | 
      
        | 361 |  |  |         case '>':
 | 
      
        | 362 |  |  |             $ok = ($operand > $aValue);
 | 
      
        | 363 |  |  |         }
 | 
      
        | 364 |  |  | 
 | 
      
        | 365 |  |  |         return $ok;
 | 
      
        | 366 |  |  |     }
 | 
      
        | 367 |  |  | 
 | 
      
        | 368 |  |  |     // finish the current menu item
 | 
      
        | 369 |  |  |     function finishItem() {
 | 
      
        | 370 |  |  |         if ($this->flags & SM2_PRETTY) {
 | 
      
        | 371 |  |  |             $this->output(str_repeat(' ',$this->prettyLevel).$this->itemClose);
 | 
      
        | 372 |  |  |         }
 | 
      
        | 373 |  |  |         else {
 | 
      
        | 374 |  |  |             $this->output($this->itemClose);
 | 
      
        | 375 |  |  |         }
 | 
      
        | 376 |  |  |     }
 | 
      
        | 377 |  |  | 
 | 
      
        | 378 |  |  |     // finish the current menu
 | 
      
        | 379 |  |  |     function finishList() {
 | 
      
        | 380 |  |  |         $this->prettyLevel -= 3;
 | 
      
        | 381 |  |  | 
 | 
      
        | 382 |  |  |         if ($this->flags & SM2_PRETTY) {
 | 
      
        | 383 |  |  |             $this->output("\n".str_repeat(' ',$this->prettyLevel).$this->menuClose."\n");
 | 
      
        | 384 |  |  |         }
 | 
      
        | 385 |  |  |         else {
 | 
      
        | 386 |  |  |             $this->output($this->menuClose);
 | 
      
        | 387 |  |  |         }
 | 
      
        | 388 |  |  | 
 | 
      
        | 389 |  |  |         $this->prettyLevel -= 1;
 | 
      
        | 390 |  |  |     }
 | 
      
        | 391 |  |  | 
 | 
      
        | 392 |  |  |     // cleanup the state of the formatter after everything has been output
 | 
      
        | 393 |  |  |     function finalize() {
 | 
      
        | 394 |  |  |         if ($this->flags & SM2_PRETTY) {
 | 
      
        | 395 |  |  |             $this->output("\n");
 | 
      
        | 396 |  |  |         }
 | 
      
        | 397 |  |  |     }
 | 
      
        | 398 |  |  | 
 | 
      
        | 399 |  |  |     // return the output
 | 
      
        | 400 |  |  |     function getOutput() {
 | 
      
        | 401 |  |  |         return $this->output;
 | 
      
        | 402 |  |  |     }
 | 
      
        | 403 |  |  | };
 | 
      
        | 404 |  |  | 
 | 
      
        | 405 |  |  | function show_menu2(
 | 
      
        | 406 |  |  |     $aMenu          = 0,
 | 
      
        | 407 |  |  |     $aStart         = SM2_ROOT,
 | 
      
        | 408 |  |  |     $aMaxLevel      = -1999, // SM2_CURR+1
 | 
      
        | 409 | 859 | Ruebenwurz |     $aOptions       = SM2_TRIM,
 | 
      
        | 410 | 827 | doc |     $aItemOpen      = false,
 | 
      
        | 411 |  |  |     $aItemClose     = false,
 | 
      
        | 412 |  |  |     $aMenuOpen      = false,
 | 
      
        | 413 |  |  |     $aMenuClose     = false,
 | 
      
        | 414 |  |  |     $aTopItemOpen   = false,
 | 
      
        | 415 |  |  |     $aTopMenuOpen   = false
 | 
      
        | 416 |  |  |     )
 | 
      
        | 417 |  |  | {
 | 
      
        | 418 |  |  |     global $wb;
 | 
      
        | 419 |  |  | 
 | 
      
        | 420 | 859 | Ruebenwurz |     // extract the flags and set $aOptions to an array
 | 
      
        | 421 |  |  |     $flags = 0;
 | 
      
        | 422 |  |  |     if (is_int($aOptions)) {
 | 
      
        | 423 |  |  |         $flags = $aOptions;
 | 
      
        | 424 |  |  |         $aOptions = array();
 | 
      
        | 425 |  |  |     }
 | 
      
        | 426 |  |  |     else if (isset($aOptions['flags'])) {
 | 
      
        | 427 |  |  |         $flags = $aOptions['flags'];
 | 
      
        | 428 |  |  |     }
 | 
      
        | 429 |  |  |     else {
 | 
      
        | 430 |  |  |         $flags = SM2_TRIM;
 | 
      
        | 431 |  |  |         $aOptions = array();
 | 
      
        | 432 |  |  |         error_log('show_menu2 error: $aOptions is invalid. No flags supplied!');
 | 
      
        | 433 |  |  |     }
 | 
      
        | 434 |  |  | 
 | 
      
        | 435 | 827 | doc |     // ensure we have our group 1 flag, we don't check for the "exactly 1" part, but
 | 
      
        | 436 |  |  |     // we do ensure that they provide at least one.
 | 
      
        | 437 | 859 | Ruebenwurz |     if (0 == ($flags & _SM2_GROUP_1)) {
 | 
      
        | 438 |  |  |         error_log('show_menu2 error: $aOptions is invalid. No flags from group 1 supplied!');
 | 
      
        | 439 |  |  |         $flags |= SM2_TRIM; // default to TRIM
 | 
      
        | 440 | 827 | doc |     }
 | 
      
        | 441 |  |  | 
 | 
      
        | 442 | 845 | doc |     // search page results don't have any of the page data loaded by WB, so we load it
 | 
      
        | 443 |  |  |     // ourselves using the referrer ID as the current page
 | 
      
        | 444 |  |  |     $CURR_PAGE_ID = defined('REFERRER_ID') ? REFERRER_ID : PAGE_ID;
 | 
      
        | 445 |  |  |     if (count($wb->page) == 0 && defined('REFERRER_ID') && REFERRER_ID > 0) {
 | 
      
        | 446 |  |  |         global $database;
 | 
      
        | 447 |  |  |         $sql = "SELECT * FROM ".TABLE_PREFIX."pages WHERE page_id = '".REFERRER_ID."'";
 | 
      
        | 448 |  |  |         $result = $database->query($sql);
 | 
      
        | 449 |  |  |         if ($result->numRows() == 1) {
 | 
      
        | 450 |  |  |             $wb->page = $result->fetchRow();
 | 
      
        | 451 |  |  |         }
 | 
      
        | 452 |  |  |         unset($result);
 | 
      
        | 453 |  |  |     }
 | 
      
        | 454 |  |  | 
 | 
      
        | 455 | 827 | doc |     // fix up the menu number to default to the menu number
 | 
      
        | 456 |  |  |     // of the current page if no menu has been supplied
 | 
      
        | 457 |  |  |     if ($aMenu == 0) {
 | 
      
        | 458 |  |  |         $aMenu = $wb->page['menu'] == '' ? 1 : $wb->page['menu'];
 | 
      
        | 459 |  |  |     }
 | 
      
        | 460 |  |  | 
 | 
      
        | 461 |  |  |     // Set some of the $wb->page[] settings to defaults if not set
 | 
      
        | 462 | 845 | doc |     $pageLevel  = $wb->page['level']  == '' ? 0 : $wb->page['level'];
 | 
      
        | 463 | 827 | doc |     $pageParent = $wb->page['parent'] == '' ? 0 : $wb->page['parent'];
 | 
      
        | 464 |  |  | 
 | 
      
        | 465 |  |  |     // adjust the start level and start page ID as necessary to
 | 
      
        | 466 |  |  |     // handle the special values that can be passed in as $aStart
 | 
      
        | 467 |  |  |     $aStartLevel = 0;
 | 
      
        | 468 |  |  |     if ($aStart < SM2_ROOT) {   // SM2_CURR+N
 | 
      
        | 469 |  |  |         if ($aStart == SM2_CURR) {
 | 
      
        | 470 |  |  |             $aStartLevel = $pageLevel;
 | 
      
        | 471 | 845 | doc |             $aStart = $pageParent;
 | 
      
        | 472 | 827 | doc |         }
 | 
      
        | 473 |  |  |         else {
 | 
      
        | 474 |  |  |             $aStartLevel = $pageLevel + $aStart - SM2_CURR;
 | 
      
        | 475 | 845 | doc |             $aStart = $CURR_PAGE_ID;
 | 
      
        | 476 | 827 | doc |         }
 | 
      
        | 477 |  |  |     }
 | 
      
        | 478 |  |  |     elseif ($aStart < 0) {   // SM2_ROOT+N
 | 
      
        | 479 |  |  |         $aStartLevel = $aStart - SM2_ROOT;
 | 
      
        | 480 |  |  |         $aStart = 0;
 | 
      
        | 481 |  |  |     }
 | 
      
        | 482 |  |  | 
 | 
      
        | 483 |  |  |     // we get the menu data once and store it in a global variable. This allows
 | 
      
        | 484 |  |  |     // multiple calls to show_menu2 in a single page with only a single call to
 | 
      
        | 485 |  |  |     // the database. If this variable exists, then we have already retrieved all
 | 
      
        | 486 |  |  |     // of the information and processed it, so we don't need to do it again.
 | 
      
        | 487 | 859 | Ruebenwurz |     if (($flags & SM2_NOCACHE) != 0
 | 
      
        | 488 | 827 | doc |         || !array_key_exists('show_menu2_data', $GLOBALS)
 | 
      
        | 489 |  |  |         || !array_key_exists($aMenu, $GLOBALS['show_menu2_data']))
 | 
      
        | 490 |  |  |     {
 | 
      
        | 491 |  |  |         global $database;
 | 
      
        | 492 |  |  | 
 | 
      
        | 493 |  |  |         // create an array of all parents of the current page. As the page_trail
 | 
      
        | 494 |  |  |         // doesn't include the theoretical root element 0, we add it ourselves.
 | 
      
        | 495 |  |  |         $rgCurrParents = split(',', '0,'.$wb->page['page_trail']);
 | 
      
        | 496 |  |  |         array_pop($rgCurrParents); // remove the current page
 | 
      
        | 497 |  |  |         $rgParent = array();
 | 
      
        | 498 |  |  | 
 | 
      
        | 499 |  |  |         // if the caller wants all menus gathered together (e.g. for a sitemap)
 | 
      
        | 500 |  |  |         // then we don't limit our SQL query
 | 
      
        | 501 |  |  |         $menuLimitSql = ' AND menu = ' .$aMenu;
 | 
      
        | 502 |  |  |         if ($aMenu == SM2_ALLMENU) {
 | 
      
        | 503 |  |  |             $menuLimitSql = '';
 | 
      
        | 504 |  |  |         }
 | 
      
        | 505 |  |  | 
 | 
      
        | 506 |  |  |         // we only load the description and keywords if we have been told to,
 | 
      
        | 507 |  |  |         // this cuts the memory load for pages that don't use them. Note that if
 | 
      
        | 508 |  |  |         // we haven't been told to load these fields the *FIRST TIME* show_menu2
 | 
      
        | 509 |  |  |         // is called (i.e. where the database is loaded) then the info won't
 | 
      
        | 510 |  |  |         // exist anyhow.
 | 
      
        | 511 |  |  |         $fields = 'parent,page_id,menu_title,page_title,link,target,level,visibility,viewing_groups';
 | 
      
        | 512 | 845 | doc |         if (version_compare(WB_VERSION, '2.7', '>=')) { // WB 2.7+
 | 
      
        | 513 | 827 | doc |             $fields .= ',viewing_users';
 | 
      
        | 514 |  |  |         }
 | 
      
        | 515 | 859 | Ruebenwurz |         if ($flags & SM2_ALLINFO) {
 | 
      
        | 516 | 827 | doc |             $fields = '*';
 | 
      
        | 517 |  |  |         }
 | 
      
        | 518 |  |  | 
 | 
      
        | 519 |  |  |         // get this once for performance. We really should be calling only need to
 | 
      
        | 520 |  |  |         // call $wb->get_group_id() but that outputs a warning notice if the
 | 
      
        | 521 |  |  |         // groupid isn't set in the session, so we check it first here.
 | 
      
        | 522 |  |  |         $currGroup = array_key_exists('GROUP_ID', $_SESSION) ?
 | 
      
        | 523 |  |  |             ','.$wb->get_group_id().',' : 'NOGROUP';
 | 
      
        | 524 |  |  | 
 | 
      
        | 525 |  |  |         // we request all matching rows from the database for the menu that we
 | 
      
        | 526 |  |  |         // are about to create it is cheaper for us to get everything we need
 | 
      
        | 527 |  |  |         // from the database once and create the menu from memory then make
 | 
      
        | 528 |  |  |         // multiple calls to the database.
 | 
      
        | 529 |  |  |         $sql = "SELECT $fields FROM ".TABLE_PREFIX.
 | 
      
        | 530 |  |  |                "pages WHERE $wb->extra_where_sql $menuLimitSql ".
 | 
      
        | 531 |  |  |                'ORDER BY level ASC, position ASC';
 | 
      
        | 532 | 971 | Ruebenwurz |         $sql = str_replace('hidden', 'IGNOREME', $sql); // we want the hidden pages
 | 
      
        | 533 | 827 | doc |         $oRowset = $database->query($sql);
 | 
      
        | 534 |  |  |         if (is_object($oRowset) && $oRowset->numRows() > 0) {
 | 
      
        | 535 |  |  |             // create an in memory array of the database data based on the item's parent.
 | 
      
        | 536 |  |  |             // The array stores all elements in the correct display order.
 | 
      
        | 537 |  |  |             while ($page = $oRowset->fetchRow()) {
 | 
      
        | 538 | 845 | doc |                 // ignore all pages that the current user is not permitted to view
 | 
      
        | 539 | 827 | doc |                 if(version_compare(WB_VERSION, '2.7', '>=')) { // WB >= 2.7
 | 
      
        | 540 | 971 | Ruebenwurz |                     // 1. hidden pages aren't shown unless they are on the current page
 | 
      
        | 541 |  |  |                     if ($page['visibility'] == 'hidden') {
 | 
      
        | 542 |  |  |                         $page['sm2_hide'] = true;
 | 
      
        | 543 | 827 | doc |                     }
 | 
      
        | 544 | 971 | Ruebenwurz | 
 | 
      
        | 545 |  |  |                     // 2. all pages with no active sections (unless it is the top page) are ignored
 | 
      
        | 546 |  |  |                     else if (!$wb->page_is_active($page) && $page['link'] != $wb->default_link && !INTRO_PAGE) {
 | 
      
        | 547 | 827 | doc |                         continue;
 | 
      
        | 548 |  |  |                     }
 | 
      
        | 549 | 971 | Ruebenwurz | 
 | 
      
        | 550 |  |  |                     // 3. all pages not visible to this user (unless always visible to registered users) are ignored
 | 
      
        | 551 |  |  |                     else if (!$wb->page_is_visible($page) && $page['visibility'] != 'registered') {
 | 
      
        | 552 |  |  |                         continue;
 | 
      
        | 553 |  |  |                     }
 | 
      
        | 554 | 827 | doc |                 }
 | 
      
        | 555 |  |  |                 else {  // WB < 2.7
 | 
      
        | 556 |  |  |                     // We can't do this in SQL as the viewing_groups column contains multiple
 | 
      
        | 557 |  |  |                     // values which are hard to process correctly in SQL. Essentially we add the
 | 
      
        | 558 |  |  |                     // following limit to the SQL query above:
 | 
      
        | 559 |  |  |                     //  (visibility <> "private" OR $wb->get_group_id() IN viewing_groups)
 | 
      
        | 560 |  |  |                     if ($page['visibility'] == 'private'
 | 
      
        | 561 |  |  |                         && false === strstr(",{$page['viewing_groups']},", $currGroup))
 | 
      
        | 562 |  |  |                     {
 | 
      
        | 563 |  |  |                         continue;
 | 
      
        | 564 |  |  |                     }
 | 
      
        | 565 |  |  |                 }
 | 
      
        | 566 |  |  | 
 | 
      
        | 567 |  |  |                 // ensure that we have an array entry in the table to add this to
 | 
      
        | 568 |  |  |                 $idx = $page['parent'];
 | 
      
        | 569 |  |  |                 if (!array_key_exists($idx, $rgParent)) {
 | 
      
        | 570 |  |  |                     $rgParent[$idx] = array();
 | 
      
        | 571 |  |  |                 }
 | 
      
        | 572 |  |  | 
 | 
      
        | 573 |  |  |                 // mark our current page as being on the current path
 | 
      
        | 574 | 845 | doc |                 if ($page['page_id'] == $CURR_PAGE_ID) {
 | 
      
        | 575 |  |  |                     $page['sm2_is_curr'] = true;
 | 
      
        | 576 | 827 | doc |                     $page['sm2_on_curr_path'] = true;
 | 
      
        | 577 | 971 | Ruebenwurz |                     unset($page['sm2_hide']); // don't hide the current page
 | 
      
        | 578 | 827 | doc |                 }
 | 
      
        | 579 |  |  | 
 | 
      
        | 580 |  |  |                 // mark parents of the current page as such
 | 
      
        | 581 |  |  |                 if (in_array($page['page_id'], $rgCurrParents)) {
 | 
      
        | 582 |  |  |                     $page['sm2_is_parent'] = true;
 | 
      
        | 583 |  |  |                     $page['sm2_on_curr_path'] = true;
 | 
      
        | 584 | 971 | Ruebenwurz |                     unset($page['sm2_hide']); // don't hide a parent page
 | 
      
        | 585 | 827 | doc |                 }
 | 
      
        | 586 |  |  | 
 | 
      
        | 587 |  |  |                 // add the entry to the array
 | 
      
        | 588 |  |  |                 $rgParent[$idx][] = $page;
 | 
      
        | 589 |  |  |             }
 | 
      
        | 590 |  |  |         }
 | 
      
        | 591 |  |  |         unset($oRowset);
 | 
      
        | 592 |  |  | 
 | 
      
        | 593 |  |  |         // mark all elements that are siblings of any element on the current path
 | 
      
        | 594 |  |  |         foreach ($rgCurrParents as $x) {
 | 
      
        | 595 |  |  |             if (array_key_exists($x, $rgParent)) {
 | 
      
        | 596 |  |  |                 foreach (array_keys($rgParent[$x]) as $y) {
 | 
      
        | 597 |  |  |                     $mark =& $rgParent[$x][$y];
 | 
      
        | 598 |  |  |                     $mark['sm2_path_sibling'] = true;
 | 
      
        | 599 |  |  |                     unset($mark);
 | 
      
        | 600 |  |  |                 }
 | 
      
        | 601 |  |  |             }
 | 
      
        | 602 |  |  |         }
 | 
      
        | 603 |  |  | 
 | 
      
        | 604 |  |  |         // mark all elements that have children and are siblings of the current page
 | 
      
        | 605 |  |  |         $parentId = $pageParent;
 | 
      
        | 606 |  |  |         foreach (array_keys($rgParent) as $x) {
 | 
      
        | 607 |  |  |             $childSet =& $rgParent[$x];
 | 
      
        | 608 |  |  |             foreach (array_keys($childSet) as $y) {
 | 
      
        | 609 |  |  |                 $mark =& $childSet[$y];
 | 
      
        | 610 |  |  |                 if (array_key_exists($mark['page_id'], $rgParent)) {
 | 
      
        | 611 |  |  |                     $mark['sm2_has_child'] = true;
 | 
      
        | 612 |  |  |                 }
 | 
      
        | 613 | 845 | doc |                 if ($mark['parent'] == $parentId && $mark['page_id'] != $CURR_PAGE_ID) {
 | 
      
        | 614 | 827 | doc |                     $mark['sm2_is_sibling'] = true;
 | 
      
        | 615 |  |  |                 }
 | 
      
        | 616 |  |  |                 unset($mark);
 | 
      
        | 617 |  |  |             }
 | 
      
        | 618 |  |  |             unset($childSet);
 | 
      
        | 619 |  |  |         }
 | 
      
        | 620 |  |  | 
 | 
      
        | 621 |  |  |         // mark all children of the current page. We don't do this when
 | 
      
        | 622 | 845 | doc |         // $CURR_PAGE_ID is 0, as 0 is the parent of everything.
 | 
      
        | 623 |  |  |         // $CURR_PAGE_ID == 0 occurs on special pages like search results
 | 
      
        | 624 |  |  |         // when no referrer is available.s
 | 
      
        | 625 |  |  |         if ($CURR_PAGE_ID != 0) {
 | 
      
        | 626 |  |  |             sm2_mark_children($rgParent, $CURR_PAGE_ID, 1);
 | 
      
        | 627 | 827 | doc |         }
 | 
      
        | 628 |  |  | 
 | 
      
        | 629 |  |  |         // store the complete processed menu data as a global. We don't
 | 
      
        | 630 |  |  |         // need to read this from the database anymore regardless of how
 | 
      
        | 631 |  |  |         // many menus are displayed on the same page.
 | 
      
        | 632 |  |  |         if (!array_key_exists('show_menu2_data', $GLOBALS)) {
 | 
      
        | 633 |  |  |             $GLOBALS['show_menu2_data'] = array();
 | 
      
        | 634 |  |  |         }
 | 
      
        | 635 |  |  |         $GLOBALS['show_menu2_data'][$aMenu] =& $rgParent;
 | 
      
        | 636 |  |  |         unset($rgParent);
 | 
      
        | 637 |  |  |     }
 | 
      
        | 638 |  |  | 
 | 
      
        | 639 |  |  |     // adjust $aMaxLevel to the level number of the final level that
 | 
      
        | 640 |  |  |     // will be displayed. That is, we display all levels <= aMaxLevel.
 | 
      
        | 641 |  |  |     if ($aMaxLevel == SM2_ALL) {
 | 
      
        | 642 |  |  |         $aMaxLevel = 1000;
 | 
      
        | 643 |  |  |     }
 | 
      
        | 644 |  |  |     elseif ($aMaxLevel < 0) {   // SM2_CURR+N
 | 
      
        | 645 |  |  |         $aMaxLevel += $pageLevel - SM2_CURR;
 | 
      
        | 646 |  |  |     }
 | 
      
        | 647 |  |  |     elseif ($aMaxLevel >= SM2_MAX) { // SM2_MAX+N
 | 
      
        | 648 |  |  |         $aMaxLevel += $aStartLevel - SM2_MAX;
 | 
      
        | 649 |  |  |         if ($aMaxLevel > $pageLevel) {
 | 
      
        | 650 |  |  |             $aMaxLevel = $pageLevel;
 | 
      
        | 651 |  |  |         }
 | 
      
        | 652 |  |  |     }
 | 
      
        | 653 |  |  |     else {  // SM2_START+N
 | 
      
        | 654 |  |  |         $aMaxLevel += $aStartLevel - SM2_START;
 | 
      
        | 655 |  |  |     }
 | 
      
        | 656 |  |  | 
 | 
      
        | 657 |  |  |     // generate the menu
 | 
      
        | 658 |  |  |     $retval = false;
 | 
      
        | 659 |  |  |     if (array_key_exists($aStart, $GLOBALS['show_menu2_data'][$aMenu])) {
 | 
      
        | 660 |  |  |         $formatter = $aItemOpen;
 | 
      
        | 661 |  |  |         if (!is_object($aItemOpen)) {
 | 
      
        | 662 |  |  |             static $sm2formatter;
 | 
      
        | 663 |  |  |             if (!isset($sm2formatter)) {
 | 
      
        | 664 |  |  |                 $sm2formatter = new SM2_Formatter;
 | 
      
        | 665 |  |  |             }
 | 
      
        | 666 |  |  |             $formatter = $sm2formatter;
 | 
      
        | 667 | 859 | Ruebenwurz |             $formatter->set($flags, $aItemOpen, $aItemClose,
 | 
      
        | 668 | 827 | doc |                 $aMenuOpen, $aMenuClose, $aTopItemOpen, $aTopMenuOpen);
 | 
      
        | 669 |  |  |         }
 | 
      
        | 670 |  |  | 
 | 
      
        | 671 | 859 | Ruebenwurz |         // adjust the level until we show everything and ignore the SM2_TRIM flag.
 | 
      
        | 672 |  |  |         // Usually this will be less than the start level to disable it.
 | 
      
        | 673 |  |  |         $showAllLevel = $aStartLevel - 1;
 | 
      
        | 674 |  |  |         if (isset($aOptions['notrim'])) {
 | 
      
        | 675 |  |  |             $showAllLevel = $aStartLevel + $aOptions['notrim'];
 | 
      
        | 676 |  |  |         }
 | 
      
        | 677 |  |  | 
 | 
      
        | 678 | 827 | doc |         // display the menu
 | 
      
        | 679 |  |  |         $formatter->initialize();
 | 
      
        | 680 |  |  |         sm2_recurse(
 | 
      
        | 681 |  |  |             $GLOBALS['show_menu2_data'][$aMenu],
 | 
      
        | 682 |  |  |             $aStart,    // parent id to start displaying sub-menus
 | 
      
        | 683 | 859 | Ruebenwurz |             $aStartLevel, $showAllLevel, $aMaxLevel, $flags,
 | 
      
        | 684 | 827 | doc |             $formatter);
 | 
      
        | 685 |  |  |         $formatter->finalize();
 | 
      
        | 686 |  |  | 
 | 
      
        | 687 |  |  |         // if we are returning something, get the data
 | 
      
        | 688 | 859 | Ruebenwurz |         if (($flags & SM2_BUFFER) != 0) {
 | 
      
        | 689 | 827 | doc |             $retval = $formatter->getOutput();
 | 
      
        | 690 |  |  |         }
 | 
      
        | 691 |  |  |     }
 | 
      
        | 692 |  |  | 
 | 
      
        | 693 |  |  |     // clear the data if we aren't caching it
 | 
      
        | 694 | 859 | Ruebenwurz |     if (($flags & SM2_NOCACHE) != 0) {
 | 
      
        | 695 | 827 | doc |         unset($GLOBALS['show_menu2_data'][$aMenu]);
 | 
      
        | 696 |  |  |     }
 | 
      
        | 697 |  |  | 
 | 
      
        | 698 |  |  |     return $retval;
 | 
      
        | 699 |  |  | }
 | 
      
        | 700 |  |  | 
 | 
      
        | 701 |  |  | function sm2_mark_children(&$rgParent, $aStart, $aChildLevel)
 | 
      
        | 702 |  |  | {
 | 
      
        | 703 |  |  |     if (array_key_exists($aStart, $rgParent)) {
 | 
      
        | 704 |  |  |         foreach (array_keys($rgParent[$aStart]) as $y) {
 | 
      
        | 705 |  |  |             $mark =& $rgParent[$aStart][$y];
 | 
      
        | 706 |  |  |             $mark['sm2_child_level'] = $aChildLevel;
 | 
      
        | 707 |  |  |             $mark['sm2_on_curr_path'] = true;
 | 
      
        | 708 |  |  |             sm2_mark_children($rgParent, $mark['page_id'], $aChildLevel+1);
 | 
      
        | 709 |  |  |         }
 | 
      
        | 710 |  |  |     }
 | 
      
        | 711 |  |  | }
 | 
      
        | 712 |  |  | 
 | 
      
        | 713 |  |  | function sm2_recurse(
 | 
      
        | 714 |  |  |     &$rgParent, $aStart,
 | 
      
        | 715 | 859 | Ruebenwurz |     $aStartLevel, $aShowAllLevel, $aMaxLevel, $aFlags,
 | 
      
        | 716 | 827 | doc |     &$aFormatter
 | 
      
        | 717 |  |  |     )
 | 
      
        | 718 |  |  | {
 | 
      
        | 719 |  |  |     global $wb;
 | 
      
        | 720 |  |  | 
 | 
      
        | 721 |  |  |     // on entry to this function we know that there are entries for this
 | 
      
        | 722 |  |  |     // parent and all entries for that parent are being displayed. We also
 | 
      
        | 723 |  |  |     // need to check if any of the children need to be displayed too.
 | 
      
        | 724 |  |  |     $isListOpen = false;
 | 
      
        | 725 |  |  |     $currentLevel = $wb->page['level'] == '' ? 0 : $wb->page['level'];
 | 
      
        | 726 | 972 | Ruebenwurz | 
 | 
      
        | 727 |  |  |     // get the number of siblings skipping the hidden pages so we can pass
 | 
      
        | 728 |  |  |     // this in and check if the item is first or last
 | 
      
        | 729 |  |  |     $sibCount = 0;
 | 
      
        | 730 |  |  |     foreach ($rgParent[$aStart] as $page) {
 | 
      
        | 731 |  |  |         if (!array_key_exists('sm2_hide', $page)) $sibCount++;
 | 
      
        | 732 |  |  |     }
 | 
      
        | 733 | 827 | doc | 
 | 
      
        | 734 |  |  |     $currSib = 0;
 | 
      
        | 735 |  |  |     foreach ($rgParent[$aStart] as $page) {
 | 
      
        | 736 | 972 | Ruebenwurz |         // skip all hidden pages
 | 
      
        | 737 |  |  |         if (array_key_exists('sm2_hide', $page)) { // not set if false, so existence = true
 | 
      
        | 738 |  |  |             continue;
 | 
      
        | 739 |  |  |         }
 | 
      
        | 740 |  |  | 
 | 
      
        | 741 | 827 | doc |         $currSib++;
 | 
      
        | 742 |  |  | 
 | 
      
        | 743 |  |  |         // skip any elements that are lower than the maximum level
 | 
      
        | 744 |  |  |         $pageLevel = $page['level'];
 | 
      
        | 745 |  |  |         if ($pageLevel > $aMaxLevel) {
 | 
      
        | 746 |  |  |             continue;
 | 
      
        | 747 |  |  |         }
 | 
      
        | 748 |  |  | 
 | 
      
        | 749 |  |  |         // this affects ONLY the top level
 | 
      
        | 750 |  |  |         if ($aStart == 0 && ($aFlags & SM2_CURRTREE)) {
 | 
      
        | 751 |  |  |             if (!array_key_exists('sm2_on_curr_path', $page)) { // not set if false, so existence = true
 | 
      
        | 752 |  |  |                 continue;
 | 
      
        | 753 |  |  |             }
 | 
      
        | 754 |  |  |             $sibCount = 1;
 | 
      
        | 755 |  |  |         }
 | 
      
        | 756 |  |  | 
 | 
      
        | 757 |  |  |         // trim the tree as appropriate
 | 
      
        | 758 |  |  |         if ($aFlags & SM2_SIBLING) {
 | 
      
        | 759 |  |  |             // parents, and siblings and children of current only
 | 
      
        | 760 |  |  |             if (!array_key_exists('sm2_on_curr_path', $page)      // not set if false, so existence = true
 | 
      
        | 761 |  |  |                 && !array_key_exists('sm2_is_sibling', $page)     // not set if false, so existence = true
 | 
      
        | 762 |  |  |                 && !array_key_exists('sm2_child_level', $page)) { // not set if false, so existence = true
 | 
      
        | 763 |  |  |                 continue;
 | 
      
        | 764 |  |  |             }
 | 
      
        | 765 |  |  |         }
 | 
      
        | 766 |  |  |         else if ($aFlags & SM2_TRIM) {
 | 
      
        | 767 |  |  |             // parents and siblings of parents
 | 
      
        | 768 | 859 | Ruebenwurz |             if ($pageLevel > $aShowAllLevel  // permit all levels to be shown
 | 
      
        | 769 |  |  |                 && !array_key_exists('sm2_on_curr_path', $page)    // not set if false, so existence = true
 | 
      
        | 770 | 827 | doc |                 && !array_key_exists('sm2_path_sibling', $page)) {  // not set if false, so existence = true
 | 
      
        | 771 |  |  |                 continue;
 | 
      
        | 772 |  |  |             }
 | 
      
        | 773 |  |  |         }
 | 
      
        | 774 |  |  |         elseif ($aFlags & SM2_CRUMB) {
 | 
      
        | 775 |  |  |             // parents only
 | 
      
        | 776 |  |  |             if (!array_key_exists('sm2_on_curr_path', $page)    // not set if false, so existence = true
 | 
      
        | 777 |  |  |                 || array_key_exists('sm2_child_level', $page)) {  // not set if false, so existence = true
 | 
      
        | 778 |  |  |                 continue;
 | 
      
        | 779 |  |  |             }
 | 
      
        | 780 |  |  |         }
 | 
      
        | 781 |  |  | 
 | 
      
        | 782 |  |  |         // depth first traverse
 | 
      
        | 783 |  |  |         $nextParent = $page['page_id'];
 | 
      
        | 784 |  |  | 
 | 
      
        | 785 |  |  |         // display the current element if we have reached the start level
 | 
      
        | 786 |  |  |         if ($pageLevel >= $aStartLevel) {
 | 
      
        | 787 |  |  |             // massage the link into the correct form
 | 
      
        | 788 |  |  |             if(!INTRO_PAGE && $page['link'] == $wb->default_link) {
 | 
      
        | 789 |  |  |                 $url = WB_URL;
 | 
      
        | 790 |  |  |             }
 | 
      
        | 791 |  |  |             else {
 | 
      
        | 792 |  |  |                 $url = $wb->page_link($page['link']);
 | 
      
        | 793 |  |  |             }
 | 
      
        | 794 |  |  | 
 | 
      
        | 795 |  |  |             // we open the list only when we absolutely need to
 | 
      
        | 796 |  |  |             if (!$isListOpen) {
 | 
      
        | 797 |  |  |                 $aFormatter->startList($page, $url);
 | 
      
        | 798 |  |  |                 $isListOpen = true;
 | 
      
        | 799 |  |  |             }
 | 
      
        | 800 |  |  | 
 | 
      
        | 801 |  |  |             $aFormatter->startItem($page, $url, $currSib, $sibCount);
 | 
      
        | 802 |  |  |         }
 | 
      
        | 803 |  |  | 
 | 
      
        | 804 |  |  |         // display children as appropriate
 | 
      
        | 805 |  |  |         if ($pageLevel + 1 <= $aMaxLevel
 | 
      
        | 806 |  |  |             && array_key_exists('sm2_has_child', $page)) {  // not set if false, so existence = true
 | 
      
        | 807 |  |  |             sm2_recurse(
 | 
      
        | 808 |  |  |                 $rgParent, $nextParent, // parent id to start displaying sub-menus
 | 
      
        | 809 | 859 | Ruebenwurz |                 $aStartLevel, $aShowAllLevel, $aMaxLevel, $aFlags,
 | 
      
        | 810 | 827 | doc |                 $aFormatter);
 | 
      
        | 811 |  |  |         }
 | 
      
        | 812 |  |  | 
 | 
      
        | 813 |  |  |         // close the current element if appropriate
 | 
      
        | 814 |  |  |         if ($pageLevel >= $aStartLevel) {
 | 
      
        | 815 |  |  |             $aFormatter->finishItem($pageLevel, $page);
 | 
      
        | 816 |  |  |         }
 | 
      
        | 817 |  |  |     }
 | 
      
        | 818 |  |  | 
 | 
      
        | 819 |  |  |     // close the list if we opened one
 | 
      
        | 820 |  |  |     if ($isListOpen) {
 | 
      
        | 821 |  |  |         $aFormatter->finishList();
 | 
      
        | 822 |  |  |     }
 | 
      
        | 823 |  |  | }
 | 
      
        | 824 |  |  | 
 | 
      
        | 825 |  |  | ?>
 |