b2evolution PHP Cross Reference Blogging Systems

Source: /inc/_core/ui/_menu.class.php - 447 lines - 12134 bytes - Summary - Text - Print

Description: This file implements the Menu class. This file is part of the evoCore framework - {@link http://evocore.net/} See also {@link http://sourceforge.net/projects/evocms/}.

   1  <?php
   2  /**
   3   * This file implements the Menu class.
   4   *
   5   * This file is part of the evoCore framework - {@link http://evocore.net/}
   6   * See also {@link http://sourceforge.net/projects/evocms/}.
   7   *
   8   * @copyright (c)2003-2014 by Francois Planque - {@link http://fplanque.com/}
   9   * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.
  10   *
  11   * {@internal License choice
  12   * - If you have received this file as part of a package, please find the license.txt file in
  13   *   the same folder or the closest folder above for complete license terms.
  14   * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
  15   *   then you must choose one of the following licenses before using the file:
  16   *   - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
  17   *   - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
  18   * }}
  19   *
  20   * {@internal Open Source relicensing agreement:
  21   * }}
  22   *
  23   * @package evocore
  24   *
  25   * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
  26   * @author fplanque: Francois PLANQUE
  27   *
  28   * @version $Id: _menu.class.php 6136 2014-03-08 07:59:48Z manuel $
  29   */
  30  if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
  31  
  32  load_class( '_core/ui/_uiwidget.class.php', 'Table' );
  33  load_class( '_core/ui/_uiwidget.class.php', 'Widget' );
  34  
  35  /**
  36   * Menu class
  37   *
  38   * @package evocore
  39   */
  40  class Menu extends Widget
  41  {
  42      /**
  43       * The menu structure (array of arrays)
  44       *
  45       * Use {@link add_menu_entries()} to add them here.
  46       *
  47       * @access protected
  48       * @var array
  49       */
  50      var $_menus = array();
  51  
  52  
  53      /**
  54       * Add menu entries to the list of entries for a given path.
  55       *
  56       * @param NULL|string|array The path to add the entries to. See {@link get_node_by_path()}.
  57       * @param array Menu entries to add (key (string) => entry (array)).
  58       *   An entry can have the following keys:
  59       *     'text': Text/Caption for this entry.
  60       *     'href': The link for this entry.
  61       *     'entries': array of sub-entries
  62       *     DEPRECATED 'style': CSS style for this entry.
  63       *     DEPRECATED 'onclick': onclick property for this entry.
  64       *     DEPRECATED 'name': name attribute of the link/entry.
  65       * @param string Node name after which we should insert the menu entries, NULL - to insert to the end
  66       */
  67  	function add_menu_entries( $path, $new_entries, $after_node = NULL )
  68      {
  69          // Get a reference to the node in the menu list.
  70          $node = & $this->get_node_by_path( $path, true );
  71  
  72          /*
  73          if( !is_array($node) )
  74          {
  75              debug_die( 'add_menu_entries() with non-existing path!' );
  76          }
  77          */
  78  
  79          $new_entires_are_inserted = false;
  80  
  81          if( !is_null( $after_node ) )
  82          {    // We should insert new entries after specific node
  83              $new_node = $node;
  84              $new_node['entries'] = array();
  85              if( isset( $node['entries'] ) )
  86              {
  87                  foreach( $node['entries'] as $node_key => $node_entry )
  88                  {
  89                      $new_node['entries'][ $node_key ] = $node_entry;
  90                      if( $node_key == $after_node )
  91                      {    // Insert new entires here after specific node
  92                          foreach( $new_entries as $l_key => $l_new_entry )
  93                          {
  94                              $new_node['entries'][$l_key] = $l_new_entry;
  95                          }
  96                          $new_entires_are_inserted = true;
  97                      }
  98                  }
  99              }
 100              $node = $new_node;
 101          }
 102  
 103          if( !$new_entires_are_inserted )
 104          {    // Insert new entries to the end if they are still not inserted after specific node
 105              foreach( $new_entries as $l_key => $l_new_entry )
 106              {
 107                  $node['entries'][$l_key] = $l_new_entry;
 108              }
 109          }
 110      }
 111  
 112      /**
 113       * Insert new menu entries right after the menu entry passed as path
 114       *
 115       * @param NULL|string|array The path. See {@link get_node_by_path()}.
 116       * @param new entries
 117       * @param position after which to insert new entries. If not given, new entries is inserted after Path
 118       * @returns boolean Whether inserting was successfull.
 119       */
 120  	function insert_menu_entries_after( $path, $new_entries, $index = false )
 121      {
 122          $menu_item = '';
 123          if( $index === false )
 124          { // get menu item after which to insert new entries
 125  
 126              if( is_array( $path ) )
 127              {
 128                  $menu_item = array_pop( $path );
 129              }
 130              elseif( is_string( $path ) )
 131              {
 132                  $menu_item = $path;
 133                  $path = NULL;
 134              }
 135          }
 136          $menu = & $this->get_node_by_path( $path );
 137          if( $menu === false )
 138          { // no such path
 139              return false;
 140          }
 141          $entries = & $menu['entries'];
 142          if( $menu_item )
 143          { // find index of menu itemafter which to insert new entries
 144              $keys = array_keys( $entries );
 145  
 146              if( !empty( $keys ) ) $index = array_search( $menu_item, $keys );
 147          }
 148  
 149          if( ( $index === false ) || ($index === NULL) )
 150          {
 151              return false;
 152          }
 153  
 154          // make new menu entries
 155          $menu['entries'] = array_merge(
 156              array_slice( $entries, 0, $index + 1 ),
 157              $new_entries,
 158              array_slice( $entries, $index )
 159          );
 160  
 161          return true;
 162      }
 163  
 164      /**
 165       * Get the reference of a node from the menu entries using a path.
 166       *
 167       * @param array|string|NULL The path. NULL means root, string means child of root,
 168       *                          array means path below root. (eg <code>array('options', 'general')</code>).
 169       * @param boolean Should the node be created if it does not exist already?
 170       * @return array|false The node as array or false, if the path does not exist (and we do not $createIfNotExisting).
 171       */
 172      function & get_node_by_path( $path, $createIfNotExisting = false )
 173      {
 174          if( is_null($path) )
 175          { // root element
 176              $path = array();
 177          }
 178          elseif( ! is_array($path) )
 179          {
 180              $path = array($path);
 181          }
 182  
 183          $node = & $this->_menus;
 184          foreach( $path as $lStep )
 185          {
 186              if( ! isset($node['entries'][$lStep]) )
 187              {
 188                  if( $createIfNotExisting )
 189                  {
 190                      $node['entries'][$lStep] = array();
 191                  }
 192                  else
 193                  {
 194                      $r = false;
 195                      return $r;
 196                  }
 197              }
 198              $node = & $node['entries'][$lStep];
 199          }
 200  
 201          return $node;
 202      }
 203  
 204  
 205      /**
 206       * Get menu entries for a given path.
 207       *
 208       * @param NULL|string|array The path. See {@link get_node_by_path()}.
 209       * @return array The menu entries (may be empty).
 210       */
 211  	function get_menu_entries( $path )
 212      {
 213          $node = & $this->get_node_by_path( $path );
 214  
 215          return isset( $node['entries'] ) ? $node['entries'] : array();
 216      }
 217  
 218  
 219      /**
 220       * Get the key of a selected entry for a path.
 221       *
 222       * @param NULL|string|array The path. See {@link get_node_by_path()}.
 223       * @return string|false
 224       */
 225  	function get_selected( $path )
 226      {
 227          $node = & $this->get_node_by_path($path);
 228  
 229          if( isset($node['selected']) )
 230          {
 231              return $node['selected'];
 232          }
 233  
 234          return false;
 235      }
 236  
 237  
 238      /**
 239       * Get the HTML for the menu entries of a specific path.
 240       *
 241       * @param NULL|string|array The path. See {@link get_node_by_path()}.
 242       * @param string Template name, see {@link get_template()}.
 243       * @return string The HTML for the menu.
 244       */
 245  	function get_html_menu( $path = NULL, $template = 'main', $level = 0 )
 246      {
 247          global $current_User;
 248  
 249          $r = '';
 250  
 251          if( is_null($path) )
 252          {
 253              $path = array();
 254          }
 255          elseif( ! is_array( $path ) )
 256          {
 257              $path = array( $path );
 258          }
 259  
 260          $templateForLevel = $this->get_template( $template, $level );
 261  
 262          if( !( $menuEntries = $this->get_menu_entries($path) ) )
 263          {    // No menu entries at this level
 264              if( isset($templateForLevel['empty']) )
 265              {
 266                  $r .= $templateForLevel['empty'];
 267              }
 268          }
 269          else
 270          {    // There are entries to display:
 271              $r .= $templateForLevel['before'];
 272  
 273              $selected = $this->get_selected($path);
 274  
 275              foreach( $menuEntries as $loop_key => $loop_details )
 276              {
 277                  if( empty($loop_details) )
 278                  {    // Empty placeholder, skip it. Might happen if the files module is disabled for example, then we had a file placeholder
 279                      // in the blog menu that will never be used. So don't display it...
 280                      continue;
 281                  }
 282  
 283                  if( !empty( $loop_details['separator'] ) )
 284                  {    // Separator
 285                      $r .= $templateForLevel['separator'];
 286                      continue;
 287                  }
 288  
 289  
 290                  // Menu entry
 291                  if( isset( $loop_details['href'] ) )
 292                  {
 293                      $href = $loop_details['href'];
 294                  }
 295                  elseif( !empty($loop_details['href_eval']) )
 296                  { // Useful for passing dynamic context vars (fp>> I AM using it)
 297                      $href = eval( $loop_details['href_eval'] );
 298                  }
 299                  else
 300                  {
 301                      $href = NULL;
 302                  }
 303  
 304                  $anchor = '<a';
 305  
 306                  if( !empty($href) )
 307                  {
 308                      $anchor .= ' href="'.$href.'"';
 309                  }
 310                  if( isset($loop_details['target']) )
 311                  {
 312                      $anchor .= ' target="'.$loop_details['target'].'"';
 313                  }
 314                  if( isset($loop_details['style']) )
 315                  {
 316                      $anchor .= ' style="'.$loop_details['style'].'"';
 317                  }
 318                  if( isset($loop_details['onclick']) )
 319                  {
 320                      $anchor .= ' onclick="'.$loop_details['onclick'].'"';
 321                  }
 322                  if( isset($loop_details['name']) )
 323                  {
 324                      $anchor .= ' name="'.$loop_details['name'].'"';
 325                  }
 326                  if( isset($loop_details['title']) )
 327                  {
 328                      $anchor .= ' title="'.$loop_details['title'].'"';
 329                  }
 330  
 331                  // CLASS
 332                  $class = '';
 333                  if( !empty( $loop_details['class'] ) )
 334                  {    // disabled
 335                      $class .= ' '.$loop_details['class'];
 336                  }
 337                  if( !empty( $loop_details['disabled'] ) )
 338                  {    // disabled
 339                      $class .= ' '.$templateForLevel['disabled_class'];
 340                  }
 341                  if( !empty($class) )
 342                  {    // disabled
 343                      $anchor .= ' class="'.trim($class).'"';
 344                  }
 345  
 346                  $anchor .= '>'.(isset($loop_details['text']) ? format_to_output( $loop_details['text'], 'htmlbody' ) : '?')."</a>";
 347  
 348                  if( $loop_key == $selected )
 349                  { // Highlight selected entry
 350                      if( isset( $templateForLevel['_props']['recurse'] )
 351                              && $templateForLevel['_props']['recurse'] != 'no'
 352                              && ( $recursePath = array_merge( $path, array($loop_key) ) )
 353                              && $this->get_menu_entries($recursePath) )
 354                      {
 355                          $r .= isset($templateForLevel['beforeEachSelWithSub']) ? $templateForLevel['beforeEachSelWithSub'] : $templateForLevel['beforeEachSel'];
 356                          $r .= $anchor;
 357  
 358                          if( $recurse != 'no' )
 359                          { // Recurse:
 360                              $r .= $this->get_html_menu( $recursePath, $template, $level+1 );
 361                          }
 362  
 363                          $r .= isset($templateForLevel['afterEachSelWithSub']) ? $templateForLevel['afterEachSelWithSub'] : $templateForLevel['afterEachSel'];
 364                      }
 365                      else
 366                      {
 367                          $r .= $templateForLevel['beforeEachSel'];
 368                          $r .= $anchor;
 369                          $r .= $templateForLevel['afterEachSel'];
 370                      }
 371                  }
 372                  else
 373                  {    // Not selected entry
 374                      if( isset( $templateForLevel['_props']['recurse'] )
 375                              && $templateForLevel['_props']['recurse'] == 'always'
 376                              && ( $recursePath = array_merge( $path, array($loop_key) ) )
 377                              && $this->get_menu_entries($recursePath) )
 378                      {
 379                          $r .= isset($templateForLevel['beforeEachWithSub']) ? $templateForLevel['beforeEachWithSub'] : $templateForLevel['beforeEachSel'];
 380                          $r .= $anchor;
 381                          // recurse:
 382                          $r .= $this->get_html_menu( $recursePath, $template, $level+1 );
 383                          $r .= isset($templateForLevel['afterEachWithSub']) ? $templateForLevel['afterEachWithSub'] : $templateForLevel['afterEachSel'];
 384                      }
 385                      else
 386                      {
 387                          $r .= $templateForLevel['beforeEach'];
 388                          $r .= $anchor;
 389                          $r .= $templateForLevel['afterEach'];
 390                      }
 391                  }
 392              }
 393              $r .= $templateForLevel['after'];
 394          }
 395  
 396          return $r;
 397      }
 398  
 399  
 400  
 401      /**
 402       * Get a template by name.
 403       *
 404       * This is a method (and not a member array) to allow dynamic generation and T_()
 405       *
 406       * @param string Name of the template ('main', 'sub')
 407       * @return array Associative array which defines layout and optionally properties.
 408       */
 409  	function get_template( $name, $level = 0 )
 410      {
 411          switch( $name )
 412          {
 413              case 'sf-menu-left':
 414              case 'sf-menu-right':
 415                  return array(
 416                      'before' => '<ul class="sf-menu '.$name.'">',
 417                      'after' => '</ul>',
 418                      'beforeEach' => '<li>',
 419                      'afterEach' => '</li>',
 420                      'beforeEachSel' => '<li class="current">',
 421                      'afterEachSel' => '</li>',
 422                      'separator' => '<li class="separator"><div><hr /></div></li>',
 423                      'disabled_class' => 'disabled',
 424                      '_props' => array(
 425                          'recurse' => 'always',  // options are: 'no' 'always' or 'intoselected'
 426                      ),
 427                  );
 428                  break;
 429  
 430              default:
 431                  debug_die( 'Unknown $name for Menu::get_template(): '.var_export($name, true) );
 432          }
 433      }
 434  
 435  
 436      /**
 437       * Check if menu is empty or contains at least one entry
 438       * 
 439       * @return boolean true if the menu is not empty | false otherwise
 440       */
 441  	function has_entires()
 442      {
 443          return !empty( $this->_menus );
 444      }
 445  }
 446  
 447  ?>

title

Description

title

Description

title

Description

title

title

Body