[PHPLIB] a rewrite of the menu class From: Alex Vorobiev (sasha <email protected>)
Date: 01/25/00

i took a shot at rewriting the menu class a bit. please take a look
and let me know what you think.

thanks!

--sasha / sasha <email protected>

info:

menu2 is similar in functionality to men.inc by kristian. i wrote menu2
to be recursive as much as possible, and extended it to provide three
types of menus: tree (i.e., cascading,), "urhere", and rows.

1. user only needs to subclass the Menu2 class and provide one data
   structure represented as a nested array of menu groups and their
   properties:

class mymenu extends Menu2 {

  var $menumap = array(
    m1 => array( url => "/menu/m1.php3", title => "menu1",
      sub => array(
              m11 => array( url => "/menu/m11.php3", title => "menu11",
          sub => array(
                  m111 => array(url => "/menu/m111.php3", title => "menu111"),
                  m112 => array(url => "/menu/m112.php3", title => "menu112")
          )),
              m12 => array(url => "/menu/m12.php3", title => "menu12")
      )),
    m2 => array(url => "/menu/m2.php3", title => "menu2"),
    m3 => array(url => "/menu/m3.php3", title => "menu3",
      sub => array(
              m31 => array( url => "/menu/m31.php3", title => "menu31",
          sub => array(
                  m311 => array(url => "/menu/m311.php3", title => "menu311"),
                  m312 => array(url => "/menu/m312.php3", title => "menu312")
          )),
              m32 => array(url => "/menu/m32.php3", title => "menu32")
      ))
  );

  function mymenu() {
    $this->setup();
  }

}

2. user may also subclass three functions: get_cell, which draws an
   actual menu cell; start_menu and end_menu which may be necessary if
   the menu is enclosed in a table, etc.

3. there are 3 types of menus that can be generated: tree (standard
   cascading menus);
   urhere, of format "you are here: support >> systems >> pc";
   or rows, where menu levels are stacked:

                  sales service *support* feedback
                      software *systems* parts
                           -pc- mac unix

   menu2 may be used to display the same menu in multiple ways on the
   same page.

4. $this->setup takes the user provided menu array and generates another
   datastructure, urlmap, which creates a mapping for every valid url
   to a menupath (to that url/page).

   setup also calls $this->get_path which uses PHP_SELF to retrieve the
   appropriate menupath for the newly created urlmap.

4. $this->show calls $this->build_menu to build the current menu as a
   string that can be displayed later.

5. here is an example (that could be put in a .inc file included by all
   .php pages):

   $m = new mymenu;

   $m -> type = 'rows'; // or urhere; tree is the default
   $m -> start_menu();
   $m -> show();
   $m -> end_menu();

code:

<?
# menu2.inc - menu class

class Menu2 {

  var $classname = "Menu2";

  # menupath -> menuelement; provided by user
  var $menumap = array();

  # url -> menupath; built from menumap at run-time
  var $urlmap = array();

  # p - menu path
  var $p = "";

  # type - type of menu (tree, urhere, rows), default to tree
  var $type = "tree";

  # str - final HTML code
  var $str = "";

  # class - a common css class, if provided
  var $class = "";

  # constructor
  function Menu2() {

            $this->setup();

  }

  # prepare
  function setup() {

        # build urlmap
        $this->build_urlmap($this->menumap, array(""));

        # retrieve current menupath
        $this->get_path();
    
  }

  # build and display menu
  function show() {

          # reinitialize str
        $this->str = "";

          # build menu
        $this->build_menu($this->menumap, $this->p);

        # print menu
            print $this->str;

  }

  # build urlmap
  function build_urlmap($m, $p) {

            while(list($k, $v) = each($m)) {
                $this->urlmap[$v[url]] = $p;
                if ($v[sub]) {
            $pp = $p; // p may still be used in loop, don't change
            $pp[] = $k;
            $this->build_urlmap($v[sub], $pp);
                }
        }

  }

  # get path
  function get_path() {

            global $PHP_SELF;
            $this->p = $this->urlmap[$PHP_SELF];

  }

  # build menu
  function build_menu($m, $p, $d=0) {

            global $PHP_SELF;
            reset($m);

            switch ($this->type) {

              case "tree": {
          while(list($k, $v) = each($m)) {

          if ($v[url] == $PHP_SELF) { // menu item found
            $found = 1;
          } elseif ($p[$d+1] == $k) { // menu subtree found
            $found = 2;
          } else {
            $found = false; // keep going
          }

          $this->str .= $this->get_cell($k,$v,$d,$found);

          # recurse only if matched menu subtree
          if ($found && ($v[sub])) {
            $this->build_menu($v[sub], $p, $d+1);
          }

          }
          break;
        }

        case "urhere": {
          while(list($k, $v) = each($m)) {

          if ($v[url] == $PHP_SELF) { // menu item found
            $found = 1;
          } elseif ($p[$d+1] == $k) { // menu subtree found
            $found = 2;
          } else {
            $found = false; // keep going
          }

          if ($found) {
            $this->str .= $this->get_cell($k,$v,$d,$found);
            if ($v[sub]) {
              $this->build_menu($v[sub], $p, $d+1);
              continue;
            }
          }
          }
          break;
        }

        case "rows": {
          $this->start_menu();

          while(list($k, $v) = each($m)) {

          if ($v[url] == $PHP_SELF) { // menu item found
            $found = 1;
          } elseif ($p[$d+1] == $k) { // menu subtree found
            $found = 2;
          } else {
            $found = false; // keep going
          }

          $this->str .= $this->get_cell($k,$v,$d,$found);

          if ($found && ($v[sub])) { // recurse if found and has subtree
            $sub = $v[sub];
          }

          }

          $this->end_menu();
          $sub ? $this->build_menu($sub, $p, $d+1) : "" ;
        break;
      }

    } // end switch

  } // end function build_menu

  function concat($n, $s) {

            $r = "";
            for($i = $n; $i > 0; $i--) {
                $r .= $s;
            }
            return $r;

  }

  #
  # functions that can be subclassed
  #

  function get_cell ($id, $pr, $d, $found) {

            $r = "";
            $class = "";
            $this->type == "tree" ? $ind = $this->concat($d,'&nbsp;') : $ind = "";
            $pr["class"] ? $class = $pr["class"] : $class = $this->class;

            # if type is tree, prefix with <tr> tag
            $this->type == "tree" ? $r .= "<tr>\n": "";

          switch ($found) {
              case 1: {
          $r .= "<td class=$class>";
          $r .= $ind . "$pr[title] </td>";
          break;
        }
        case 2: {
          $r .= "<td>" . $ind;
          $r .= "<a href=\"$pr[url]\" class=$class>";
          $r .= "<font color=blue><b>$pr[title]</b></font></a></td> \n";
            
              # if type is urhere, postfix with a separator
          if ($this->type == "urhere") {
            $r .= "<td class=$class><font color=red>>></font></td>\n";
          }
          break;
        }
        default: {
          $r .= "<td>" . $ind;
          $r .= "<a href=\"$pr[url]\" class=$class>";
          $r .= "<font color=blue>$pr[title]</font></a> </td>\n";
        }
        } // end switch

            # if type tree, postfix with </tr> tag
            $this->type == "tree" ? $r .= "</tr>\n": "";

            return $r;

  } // end function get_cell

  function start_menu() {

          switch($this->type) {
          case "rows": {
            $this->str .= "<table align=center cellpadding=0 border=0>\n
            <tr>\n";
            break;;
          }
          case "urhere": {
            print("<!-- start menu type $this->type --> \n");
            print("<table cellpadding=0 cellspacing=0 border=0 valing=top>
            \n");
            print("<td class=$this->class>You are here: </td>\n");
            break;;
          }
          default: {
            print("<!-- start menu type $this->type --> \n");
            print("<table cellpadding=0 cellspacing=0 border=0 valing=top>
            \n");
          }
        }

  } // end function start_menu

  function end_menu() {

          switch($this->type) {
          case "rows": {
            $this->str .= "</tr>\n </table>\n";
            break;;
          }
          default: {
              print("</table> \n");
            print("<!-- end menu type $this->type --> \n");
          }
        }

  } // end function end_menu

} // end class
?>
-
PHP3 Base Library Mailing List. Send messages to <phplib <email protected>>.
To unsubscribe, send "unsubscribe" to <phplib-request <email protected>> in
the body, not the subject, of your message.