Server IP : 103.119.228.120 / Your IP : 18.226.104.30 Web Server : Apache System : Linux v8.techscape8.com 3.10.0-1160.119.1.el7.tuxcare.els2.x86_64 #1 SMP Mon Jul 15 12:09:18 UTC 2024 x86_64 User : nobody ( 99) PHP Version : 5.6.40 Disable Function : shell_exec,symlink,system,exec,proc_get_status,proc_nice,proc_terminate,define_syslog_variables,syslog,openlog,closelog,escapeshellcmd,passthru,ocinum cols,ini_alter,leak,listen,chgrp,apache_note,apache_setenv,debugger_on,debugger_off,ftp_exec,dl,dll,myshellexec,proc_open,socket_bind,proc_close,escapeshellarg,parse_ini_filepopen,fpassthru,exec,passthru,escapeshellarg,escapeshellcmd,proc_close,proc_open,ini_alter,popen,show_source,proc_nice,proc_terminate,proc_get_status,proc_close,pfsockopen,leak,apache_child_terminate,posix_kill,posix_mkfifo,posix_setpgid,posix_setsid,posix_setuid,dl,symlink,shell_exec,system,dl,passthru,escapeshellarg,escapeshellcmd,myshellexec,c99_buff_prepare,c99_sess_put,fpassthru,getdisfunc,fx29exec,fx29exec2,is_windows,disp_freespace,fx29sh_getupdate,fx29_buff_prepare,fx29_sess_put,fx29shexit,fx29fsearch,fx29ftpbrutecheck,fx29sh_tools,fx29sh_about,milw0rm,imagez,sh_name,myshellexec,checkproxyhost,dosyayicek,c99_buff_prepare,c99_sess_put,c99getsource,c99sh_getupdate,c99fsearch,c99shexit,view_perms,posix_getpwuid,posix_getgrgid,posix_kill,parse_perms,parsesort,view_perms_color,set_encoder_input,ls_setcheckboxall,ls_reverse_all,rsg_read,rsg_glob,selfURL,dispsecinfo,unix2DosTime,addFile,system,get_users,view_size,DirFiles,DirFilesWide,DirPrintHTMLHeaders,GetFilesTotal,GetTitles,GetTimeTotal,GetMatchesCount,GetFileMatchesCount,GetResultFiles,fs_copy_dir,fs_copy_obj,fs_move_dir,fs_move_obj,fs_rmdir,SearchText,getmicrotime MySQL : ON | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /usr/share/awl/inc/ |
Upload File : |
<?php /** * Some intelligence and standardisation around presenting a menu hierarchy. * * See the MenuSet class for examples as that is the primary interface. * @see MenuSet * * @package awl * @subpackage MenuSet * @author Andrew McMillan <andrew@mcmillan.net.nz> * @copyright Catalyst IT Ltd, Morphoss Ltd <http://www.morphoss.com/> * @license http://gnu.org/copyleft/gpl.html GNU GPL v2 or later */ require_once("AWLUtilities.php"); /** * Each menu option is an object. * @package awl */ class MenuOption { /**#@+ * @access private */ /** * The label for the menu item * @var string */ var $label; /** * The target URL for the menu * @var string */ var $target; /** * The title for the item when moused over, which should be displayed as a tooltip. * @var string */ var $title; /** * Whether the menu option is active * @var string */ var $active; /** * For sorting menu options * @var string */ var $sortkey; /** * Style to render the menu option with. * @var string */ var $style; /** * The MenuSet that this menu is a parent of * @var string */ var $submenu_set; /**#@-*/ /** * A reference to this menu option itself * @var reference */ var $self; /**#@+ * @access public */ /** * The rendered HTML fragment (once it has been). * @var string */ var $rendered; /**#@-*/ /** * The thing we click * @param string $label The label to display for this option. * @param string $target The URL to target for this option. * @param string $title Some tooltip help for the title tag. * @param string $style A base class name for this option. * @param int $sortkey An (optional) value to allow option ordering. */ function __construct( $label, $target, $title="", $style="menu", $sortkey=1000 ) { $this->label = $label; $this->target = $target; $this->title = $title; $this->style = $style; $this->attributes = array(); $this->active = false; $this->sortkey = $sortkey; $this->rendered = ""; $this->self =& $this; } /** * Convert the menu option into an HTML string * @return string The HTML fragment for the menu option. */ function Render( ) { $r = sprintf('<a href="%s" class="%s" title="%s"%s>%s</a>', $this->target, $this->style, htmlspecialchars($this->title), "%%attributes%%", htmlspecialchars($this->label), $this->style ); // Now process the generic attributes $attribute_values = ""; foreach( $this->attributes AS $k => $v ) { if ( substr($k, 0, 1) == '_' ) continue; $attribute_values .= ' '.$k.'="'.htmlspecialchars($v).'"'; } $r = str_replace( '%%attributes%%', $attribute_values, $r ); $this->rendered = $r; return "$r"; } /** * Set arbitrary attributes of the menu option * @param string $attribute An arbitrary attribute to be set in the hyperlink. * @param string $value A value for this attribute. */ function Set( $attribute, $value ) { $this->attributes[$attribute] = $value; } /** * Mark it as active, with a fancy style to distinguish that * @param string $style A style used to highlight that the option is active. */ function Active( $style=false ) { $this->active = true; if ( $style ) $this->style = $style; } /** * This menu option is now promoted to the head of a tree */ function AddSubmenu( &$submenu_set ) { $this->submenu_set = &$submenu_set; } /** * Whether this option is currently active. * @return boolean The value of the active flag. */ function IsActive( ) { return ( $this->active ); } /** * Whether this option is currently active. * @return boolean The value of the active flag. */ function MaybeActive( $test_pattern, $active_style ) { if ( is_string($test_pattern) && preg_match($test_pattern,$_SERVER['REQUEST_URI']) ) { $this->Active($active_style); } return ( $this->active ); } } /** * _CompareMenuSequence is used in sorting the menu options into the sequence order * * @param objectref $a The first menu option * @param objectref $b The second menu option * @return int ( $a == b ? 0 ( $a > b ? 1 : -1 )) */ function _CompareMenuSequence( $a, $b ) { dbg_error_log("MenuSet", ":_CompareMenuSequence: Comparing %d with %d", $a->sortkey, $b->sortkey); return ($a->sortkey - $b->sortkey); } /** * A MenuSet is a hierarchy of MenuOptions, some of which might be * MenuSet objects themselves. * * The menu options are presented in HTML span tags, and the menus * themselves are presented inside HTML div tags. All layout and * styling is expected to be provide by CSS. * * A non-trivial example would look something like this: *<code> *require("MenuSet.php"); *$main_menu = new MenuSet('menu', 'menu', 'menu_active'); * ... *$other_menu = new MenuSet('submenu', 'submenu', 'submenu_active'); *$other_menu->AddOption("Extra Other","/extraother.php","Submenu option to do extra things."); *$other_menu->AddOption("Super Other","/superother.php","Submenu option to do super things."); *$other_menu->AddOption("Meta Other","/metaother.php","Submenu option to do meta things."); * ... *$main_menu->AddOption("Do This","/dothis.php","Option to do this thing."); *$main_menu->AddOption("Do That","/dothat.php","Option to do all of that."); *$main_menu->AddSubMenu( $other_menu, "Do The Other","/dotheother.php","Submenu to do all of the other things.", true); * ... *if ( isset($main_menu) && is_object($main_menu) ) { * $main_menu->AddOption("Home","/","Go back to the home page"); * echo $main_menu->Render(); *} *</code> * In a hierarchical menu tree, like the example above, only one sub-menu will be * shown, which will be the first one that is found to have active menu options. * * The menu display will generally recognise the current URL and mark as active the * menu option that matches it, but in some cases it might be desirable to force one * or another option to be marked as active using the appropriate parameter to the * AddOption or AddSubMenu call. * @package awl */ class MenuSet { /**#@+ * @access private */ /** * CSS style to use for the div around the options * @var string */ var $div_id; /** * CSS style to use for normal menu option * @var string */ var $main_class; /** * CSS style to use for active menu option * @var string */ var $active_class; /** * An array of MenuOption objects * @var array */ var $options; /** * Any menu option that happens to parent this set * @var reference */ var $parent; /** * The sortkey used by any previous option * @var last_sortkey */ var $last_sortkey; /** * Will be set to true or false when we link active sub-menus, but will be * unset until we do that. * @var reference */ var $has_active_options; /**#@-*/ /** * Start a new MenuSet with no options. * @param string $div_id An ID for the HTML div that the menu will be presented in. * @param string $main_class A CSS class for most menu options. * @param string $active_class A CSS class for active menu options. */ function __construct( $div_id, $main_class = '', $active_class = 'active' ) { $this->options = array(); $this->main_class = $main_class; $this->active_class = $active_class; $this->div_id = $div_id; } /** * Add an option, which is a link. * The call will attempt to work out whether the option should be marked as * active, and will sometimes get it wrong. * @param string $label A Label for the new menu option * @param string $target The URL to target for this option. * @param string $title Some tooltip help for the title tag. * @param string $active Whether this option should be marked as Active. * @param int $sortkey An (optional) value to allow option ordering. * @param external open this link in a new window/tab. * @return mixed A reference to the MenuOption that was added, or false if none were added. */ function &AddOption( $label, $target, $title="", $active=false, $sortkey=null, $external=false ) { if ( !isset($sortkey) ) { $sortkey = (isset($this->last_sortkey) ? $this->last_sortkey + 100 : 1000); } $this->last_sortkey = $sortkey; if ( version_compare(phpversion(), '5.0') < 0) { $new_option = new MenuOption( $label, $target, $title, $this->main_class, $sortkey ); } else { $new_option = new MenuOption( $label, $target, $title, $this->main_class, $sortkey ); } if ( ($old_option = $this->_OptionExists( $label )) === false ) { $this->options[] = &$new_option ; } else { dbg_error_log("MenuSet",":AddOption: Replacing existing option # $old_option ($label)"); $this->options[$old_option] = &$new_option; // Overwrite the existing option } if ( is_bool($active) && $active == false && $_SERVER['REQUEST_URI'] == $target ) { // If $active is not set, then we look for an exact match to the current URL $new_option->Active( $this->active_class ); } else if ( is_bool($active) && $active ) { // When active is specified as a boolean, the recognition has been done externally $new_option->Active( $this->active_class ); } else if ( is_string($active) && preg_match($active,$_SERVER['REQUEST_URI']) ) { // If $active is a string, then we match the current URL to that as a Perl regex $new_option->Active( $this->active_class ); } if ( $external == true ) $new_option->Set('target', '_blank'); return $new_option ; } /** * Add an option, which is a submenu * @param object &$submenu_set A reference to a menu tree * @param string $label A Label for the new menu option * @param string $target The URL to target for this option. * @param string $title Some tooltip help for the title tag. * @param string $active Whether this option should be marked as Active. * @param int $sortkey An (optional) value to allow option ordering. * @return mixed A reference to the MenuOption that was added, or false if none were added. */ function &AddSubMenu( &$submenu_set, $label, $target, $title="", $active=false, $sortkey=2000 ) { $new_option =& $this->AddOption( $label, $target, $title, $active, $sortkey ); $submenu_set->parent = &$new_option ; $new_option->AddSubmenu( $submenu_set ); return $new_option ; } /** * Does the menu have any options that are active. * Most likely used so that we can then set the parent menu as active. * @param string $label A Label for the new menu option * @return boolean Whether the menu has options that are active. */ function _HasActive( ) { if ( isset($this->has_active_options) ) { return $this->has_active_options; } foreach( $this->options AS $k => $v ) { if ( $v->IsActive() ) { $rc = true; return $rc; } } $rc = false; return $rc; } /** * Find out how many options the menu has. * @return int The number of options in the menu. */ function Size( ) { return count($this->options); } /** * See if a menu already has this option * @return boolean Whether the option already exists in the menu. */ function _OptionExists( $newlabel ) { $rc = false; foreach( $this->options AS $k => $v ) { if ( $newlabel == $v->label ) return $k; } return $rc; } /** * Mark each MenuOption as active that has an active sub-menu entry. * * Currently needs to be called manually before rendering but * really should probably be called as part of the render now, * and then this could be a private routine. */ function LinkActiveSubMenus( ) { $this->has_active_options = false; foreach( $this->options AS $k => $v ) { if ( isset($v->submenu_set) && $v->submenu_set->_HasActive() ) { // Note that we need to do it this way, since $v is a copy, not a reference $this->options[$k]->Active( $this->active_class ); $this->has_active_options = true; } } } /** * Mark each MenuOption as active that has an active sub-menu entry. * * Currently needs to be called manually before rendering but * really should probably be called as part of the render now, * and then this could be a private routine. */ function MakeSomethingActive( $test_pattern ) { if ( $this->has_active_options ) return; // Already true. foreach( $this->options AS $k => $v ) { if ( isset($v->submenu_set) && $v->submenu_set->_HasActive() ) { // Note that we need to do it this way, since $v is a copy, not a reference $this->options[$k]->Active( $this->active_class ); $this->has_active_options = true; return $this->has_active_options; } } foreach( $this->options AS $k => $v ) { if ( isset($v->submenu_set) && $v->submenu_set->MakeSomethingActive($test_pattern) ) { // Note that we need to do it this way, since $v is a copy, not a reference $this->options[$k]->Active( $this->active_class ); $this->has_active_options = true; return $this->has_active_options; } else { if ( $this->options[$k]->MaybeActive( $test_pattern, $this->active_class ) ) { $this->has_active_options = true; return $this->has_active_options; } } } return false; } /** * _CompareSequence is used in sorting the menu options into the sequence order * * @param objectref $a The first menu option * @param objectref $b The second menu option * @return int ( $a == b ? 0 ( $a > b ? 1 : -1 )) */ function _CompareSequence( $a, $b ) { dbg_error_log("MenuSet",":_CompareSequence: Comparing %d with %d", $a->sortkey, $b->sortkey); return ($a->sortkey - $b->sortkey); } /** * Render the menu tree to an HTML fragment. * * @param boolean $submenus_inline Indicate whether to render the sub-menus within * the menus, or render them entirely separately after we finish rendering the * top level ones. * @return string The HTML fragment. */ function Render( $submenus_inline = false ) { if ( !isset($this->has_active_options) ) { $this->LinkActiveSubMenus(); } $options = $this->options; usort($options,"_CompareMenuSequence"); $render_sub_menus = false; $r = "<div id=\"$this->div_id\">\n"; foreach( $options AS $k => $v ) { $r .= $v->Render(); if ( $v->IsActive() && isset($v->submenu_set) && $v->submenu_set->Size() > 0 ) { $render_sub_menus = $v->submenu_set; if ( $submenus_inline ) $r .= $render_sub_menus->Render(); } } $r .="</div>\n"; if ( !$submenus_inline && $render_sub_menus != false ) { $r .= $render_sub_menus->Render(); } return $r; } /** * Render the menu tree to an HTML fragment. * * @param boolean $submenus_inline Indicate whether to render the sub-menus within * the menus, or render them entirely separately after we finish rendering the * top level ones. * @return string The HTML fragment. */ function RenderAsCSS( $depth = 0, $skip_empty = true ) { $this->LinkActiveSubMenus(); if ( $depth > 0 ) $class = "submenu" . $depth; else $class = "menu"; $options = $this->options; usort($options,"_CompareMenuSequence"); $r = "<div id=\"$this->div_id\" class=\"$class\">\n<ul>\n"; foreach( $options AS $k => $v ) { if ( $skip_empty && isset($v->submenu_set) && $v->submenu_set->Size() < 1 ) continue; $r .= "<li>".$v->Render(); if ( isset($v->submenu_set) && $v->submenu_set->Size() > 0 ) { $r .= $v->submenu_set->RenderAsCSS($depth+1); } $r .= "</li>\n"; } $r .="</ul></div>\n"; return $r; } }