I’ve been coding on experts exchange, testing myself. Here’s some relevant code for one of the answers.
They’re classes that have been used to generate hierarchical menus.
<?php
/**
* @package menu
* @author John Kawakami <johnk---.net>
* @link http://www.slaptech.net Developed by The Slaptech Collective
* @copyright 2006 Public Domain
* @version $Id: Menu.class.php 97 2006-07-27 10:43:40Z johnk $
*
* Library to help create hierarchical menus.
* Use MenuRenderer to display the menus.
*
*
* $menuBar = new Menu('MenuBar');
* $fileMenu = $menuBar->addMenu( 'File' );
* $fileMenu->addUrl( 'Open', '/admin/foo.php' );
* $fileMenu->addUrl( 'Save', '/admin/bar.php' );
* $fileMenu->addDivider();
* $fileMenu->addUrl( 'Close', '/admin/baz.php' );
*
*/
include_once('ACL.class.php');
class Menu
{
var $acl;
var $menu;
var $menuHash; //fixme - combine these two structures into one
var $name;
var $description;
var $icon;
var $url;
var $highlight;
function Menu( &$acl, $name, $description='', $icon='', $url='' )
{
$this->acl =& $acl;
$this->menu = array();
$this->name =& $name;
$this->description =& $description;
$this->icon =& $icon;
$this->url =& $url;
$this->highlight = false;
}
function addObject( &$obj )
{
array_push( $this->menu, &$obj );
}
function addNamedObject( $name, &$obj )
{
$this->menuHash[$name] =& $obj;
$this->addObject( &$obj );
}
/**
* Utility function.
*/
function &addMenu( &$acl, $name, $description='', $icon='', $url='' )
{
$new = new Menu( &$acl, $name, $description, $icon, $url );
$this->addObject( $new );
return $new;
}
function &getNamedObject( $name )
{
return $this->menuHash[$name];
}
function &addUrl( &$acl, $name, $url, $description='', $popup='' )
{
$new = new UrlMenuItem( &$acl, $name, $url, $description, $popup );
$this->addObject( $new );
return $new;
}
function &addDivider()
{
$new = new DividerMenuItem();
$this->addObject( $new );
return $new;
}
function select( $name )
{
for( $i=0; $i < count($this->menu); $i++ )
{
if ($this->menu[$i]->name==$name)
{
return $this->menu[$i];
}
}
}
function rewind()
{
reset($this->menu);
}
function &next()
{
// check the acl to see if this user can see the next item - fixme
list( $index, $obj ) = each( $this->menu );
return $obj;
}
function disable()
{
$this->enabled = false;
}
function enable()
{
$this->enabled = true;
}
function highlight()
{
$this->highlight = true;
}
}
class UrlMenuItem extends Menu
{
var $name;
var $url;
var $description;
var $popup;
function &UrlMenuItem( &$acl, $name, $url, $description='', $popup='' )
{
$this->acl =& $acl;
$this->name =& $name;
$this->url =& $url;
$this->description =& $description;
$this->popup =& $popup;
return $this;
}
}
class DividerMenuItem extends Menu
{
function DividerMenuItem()
{
$this->name = 'divider';
}
}
?>
The menus are rendered via another class:
<?php
/**
* @package menu
* @author John Kawakami <johnk----.net>
* @link http://www.slaptech.net Developed by The Slaptech Collective
* @copyright 2006 Public Domain
* @version $Id: MenuRenderer.class.php 92 2006-07-27 09:13:10Z johnk $
*
* Rendering classes for menus. These are kind of like "templates"
* for menus, except they can render hierarchies, portions of menus,
* etc. There's HTML code in here. Yuk.
*/
/**
* Rendering interface. Each renderer must implement the
* url, divider, and menu methods. The menu() method is the heart
* of the renderer.
*/
class MenuRenderer
{
function MenuRenderer() {}
function divider() {}
function url() {}
function menu() {}
function item( $obj )
{
return $obj->name;
}
}
/**
* Renders a menu as an html unordered list (UL).
*/
class HtmlMenuRenderer extends MenuRenderer
{
function HtmlMenuRenderer() {}
function menu( &$menu, $indent=0 )
{
$t = str_repeat( ' ', $indent );
$m =& $menu;
$m->rewind();
if ($m->name != '@')
$output .= "$t<li>";
if ($m->name != '@')
{
if ($m->url)
$output .= "<a href='$m->url'>";
if ($m->icon)
{
$output .= "<img src='$m->icon' border='0' />";
$output .= "<br>";
}
$output .= $m->name."n";
if ($m->url)
$output .= '</a>';
}
$output .= "$t<ul>n";
while( $obj =& $m->next() )
{
$class = strtolower(get_class($obj));
// echo "$class<br>";
switch( $class )
{
case 'apmenu':
case 'menu':
$output .= $this->menu( $obj, $indent+4 );
break;
case 'urlmenuitem':
$output .= $this->url( $obj, $indent+4 );
break;
case 'dividermenuitem':
$output .= $this->divider( $obj, $indent+4 );
break;
default:
$output .= $this->item( $obj, $indent+4 );
break;
}
}
$output .= "$t</ul>n";
if ($m->name != '@')
$output .= "$t</li>n";
return $output;
}
function divider( &$obj, $indent=0 )
{
$t = str_repeat( ' ', $indent );
return "$t<li>-----------</li>n";
}
function url( &$obj, $indent=0 )
{
$t = str_repeat( ' ', $indent );
return "$t<li><a href='$obj->url'>$obj->name</a></li>n";
}
}