Andrew's Web Libraries (AWL)
MenuSet.php
1<?php
15require_once("AWLUtilities.php");
16
29 var $label;
30
35 var $target;
36
41 var $title;
42
47 var $active;
48
53 var $sortkey;
54
59 var $style;
60
65 var $submenu_set;
72 var $self;
73
81 var $rendered;
92 function __construct( $label, $target, $title="", $style="menu", $sortkey=1000 ) {
93 $this->label = $label;
94 $this->target = $target;
95 $this->title = $title;
96 $this->style = $style;
97 $this->attributes = array();
98 $this->active = false;
99 $this->sortkey = $sortkey;
100
101 $this->rendered = "";
102 $this->self =& $this;
103 }
104
109 function Render( ) {
110 $r = sprintf('<a href="%s" class="%s" title="%s"%s>%s</a>',
111 $this->target, $this->style, htmlspecialchars($this->title), "%%attributes%%",
112 htmlspecialchars($this->label), $this->style );
113
114 // Now process the generic attributes
115 $attribute_values = "";
116 foreach( $this->attributes AS $k => $v ) {
117 if ( substr($k, 0, 1) == '_' ) continue;
118 $attribute_values .= ' '.$k.'="'.htmlspecialchars($v).'"';
119 }
120 $r = str_replace( '%%attributes%%', $attribute_values, $r );
121
122 $this->rendered = $r;
123 return "$r";
124 }
125
131 function Set( $attribute, $value ) {
132 $this->attributes[$attribute] = $value;
133 }
134
139 function Active( $style=false ) {
140 $this->active = true;
141 if ( $style ) $this->style = $style;
142 }
143
147 function AddSubmenu( &$submenu_set ) {
148 $this->submenu_set = &$submenu_set;
149 }
150
155 function IsActive( ) {
156 return ( $this->active );
157 }
158
163 function MaybeActive( $test_pattern, $active_style ) {
164 if ( is_string($test_pattern) && preg_match($test_pattern,$_SERVER['REQUEST_URI']) ) {
165 $this->Active($active_style);
166 }
167 return ( $this->active );
168 }
169}
170
171
179function _CompareMenuSequence( $a, $b ) {
180 dbg_error_log("MenuSet", ":_CompareMenuSequence: Comparing %d with %d", $a->sortkey, $b->sortkey);
181 return ($a->sortkey - $b->sortkey);
182}
183
184
185
222class MenuSet {
230 var $div_id;
231
236 var $main_class;
237
242 var $active_class;
243
248 var $options;
249
254 var $parent;
255
260 var $last_sortkey;
261
267 var $has_active_options;
276 function __construct( $div_id, $main_class = '', $active_class = 'active' ) {
277 $this->options = array();
278 $this->main_class = $main_class;
279 $this->active_class = $active_class;
280 $this->div_id = $div_id;
281 }
282
295 function &AddOption( $label, $target, $title="", $active=false, $sortkey=null, $external=false ) {
296 if ( !isset($sortkey) ) {
297 $sortkey = (isset($this->last_sortkey) ? $this->last_sortkey + 100 : 1000);
298 }
299 $this->last_sortkey = $sortkey;
300 if ( version_compare(phpversion(), '5.0') < 0) {
301 $new_option = new MenuOption( $label, $target, $title, $this->main_class, $sortkey );
302 }
303 else {
304 $new_option = new MenuOption( $label, $target, $title, $this->main_class, $sortkey );
305 }
306 if ( ($old_option = $this->_OptionExists( $label )) === false ) {
307 $this->options[] = &$new_option ;
308 }
309 else {
310 dbg_error_log("MenuSet",":AddOption: Replacing existing option # $old_option ($label)");
311 $this->options[$old_option] = &$new_option; // Overwrite the existing option
312 }
313 if ( is_bool($active) && $active == false && $_SERVER['REQUEST_URI'] == $target ) {
314 // If $active is not set, then we look for an exact match to the current URL
315 $new_option->Active( $this->active_class );
316 }
317 else if ( is_bool($active) && $active ) {
318 // When active is specified as a boolean, the recognition has been done externally
319 $new_option->Active( $this->active_class );
320 }
321 else if ( is_string($active) && preg_match($active,$_SERVER['REQUEST_URI']) ) {
322 // If $active is a string, then we match the current URL to that as a Perl regex
323 $new_option->Active( $this->active_class );
324 }
325
326 if ( $external == true ) $new_option->Set('target', '_blank');
327
328 return $new_option ;
329 }
330
341 function &AddSubMenu( &$submenu_set, $label, $target, $title="", $active=false, $sortkey=2000 ) {
342 $new_option =& $this->AddOption( $label, $target, $title, $active, $sortkey );
343 $submenu_set->parent = &$new_option ;
344 $new_option->AddSubmenu( $submenu_set );
345 return $new_option ;
346 }
347
354 function _HasActive( ) {
355 if ( isset($this->has_active_options) ) {
356 return $this->has_active_options;
357 }
358 foreach( $this->options AS $k => $v ) {
359 if ( $v->IsActive() ) {
360 $rc = true;
361 return $rc;
362 }
363 }
364 $rc = false;
365 return $rc;
366 }
367
372 function Size( ) {
373 return count($this->options);
374 }
375
380 function _OptionExists( $newlabel ) {
381 $rc = false;
382 foreach( $this->options AS $k => $v ) {
383 if ( $newlabel == $v->label ) return $k;
384 }
385 return $rc;
386 }
387
395 function LinkActiveSubMenus( ) {
396 $this->has_active_options = false;
397 foreach( $this->options AS $k => $v ) {
398 if ( isset($v->submenu_set) && $v->submenu_set->_HasActive() ) {
399 // Note that we need to do it this way, since $v is a copy, not a reference
400 $this->options[$k]->Active( $this->active_class );
401 $this->has_active_options = true;
402 }
403 }
404 }
405
413 function MakeSomethingActive( $test_pattern ) {
414 if ( $this->has_active_options ) return; // Already true.
415 foreach( $this->options AS $k => $v ) {
416 if ( isset($v->submenu_set) && $v->submenu_set->_HasActive() ) {
417 // Note that we need to do it this way, since $v is a copy, not a reference
418 $this->options[$k]->Active( $this->active_class );
419 $this->has_active_options = true;
420 return $this->has_active_options;
421 }
422 }
423
424 foreach( $this->options AS $k => $v ) {
425 if ( isset($v->submenu_set) && $v->submenu_set->MakeSomethingActive($test_pattern) ) {
426 // Note that we need to do it this way, since $v is a copy, not a reference
427 $this->options[$k]->Active( $this->active_class );
428 $this->has_active_options = true;
429 return $this->has_active_options;
430 }
431 else {
432 if ( $this->options[$k]->MaybeActive( $test_pattern, $this->active_class ) ) {
433 $this->has_active_options = true;
434 return $this->has_active_options;
435 }
436 }
437 }
438 return false;
439 }
440
448 function _CompareSequence( $a, $b ) {
449 dbg_error_log("MenuSet",":_CompareSequence: Comparing %d with %d", $a->sortkey, $b->sortkey);
450 return ($a->sortkey - $b->sortkey);
451 }
452
453
462 function Render( $submenus_inline = false ) {
463 if ( !isset($this->has_active_options) ) {
464 $this->LinkActiveSubMenus();
465 }
466 $options = $this->options;
467 usort($options,"_CompareMenuSequence");
468 $render_sub_menus = false;
469 $r = "<div id=\"$this->div_id\">\n";
470 foreach( $options AS $k => $v ) {
471 $r .= $v->Render();
472 if ( $v->IsActive() && isset($v->submenu_set) && $v->submenu_set->Size() > 0 ) {
473 $render_sub_menus = $v->submenu_set;
474 if ( $submenus_inline )
475 $r .= $render_sub_menus->Render();
476 }
477 }
478 $r .="</div>\n";
479 if ( !$submenus_inline && $render_sub_menus != false ) {
480 $r .= $render_sub_menus->Render();
481 }
482 return $r;
483 }
484
485
494 function RenderAsCSS( $depth = 0, $skip_empty = true ) {
495 $this->LinkActiveSubMenus();
496
497 if ( $depth > 0 )
498 $class = "submenu" . $depth;
499 else
500 $class = "menu";
501
502 $options = $this->options;
503 usort($options,"_CompareMenuSequence");
504
505 $r = "<div id=\"$this->div_id\" class=\"$class\">\n<ul>\n";
506 foreach( $options AS $k => $v ) {
507 if ( $skip_empty && isset($v->submenu_set) && $v->submenu_set->Size() < 1 ) continue;
508 $r .= "<li>".$v->Render();
509 if ( isset($v->submenu_set) && $v->submenu_set->Size() > 0 ) {
510 $r .= $v->submenu_set->RenderAsCSS($depth+1);
511 }
512 $r .= "</li>\n";
513 }
514 $r .="</ul></div>\n";
515 return $r;
516 }
517}
__construct( $label, $target, $title="", $style="menu", $sortkey=1000)
Definition: MenuSet.php:92
MaybeActive( $test_pattern, $active_style)
Definition: MenuSet.php:163
AddSubmenu(&$submenu_set)
Definition: MenuSet.php:147
Active( $style=false)
Definition: MenuSet.php:139
Set( $attribute, $value)
Definition: MenuSet.php:131
_OptionExists( $newlabel)
Definition: MenuSet.php:380
& AddOption( $label, $target, $title="", $active=false, $sortkey=null, $external=false)
Definition: MenuSet.php:295
_CompareSequence( $a, $b)
Definition: MenuSet.php:448
& AddSubMenu(&$submenu_set, $label, $target, $title="", $active=false, $sortkey=2000)
Definition: MenuSet.php:341
RenderAsCSS( $depth=0, $skip_empty=true)
Definition: MenuSet.php:494
LinkActiveSubMenus()
Definition: MenuSet.php:395
__construct( $div_id, $main_class='', $active_class='active')
Definition: MenuSet.php:276
Size()
Definition: MenuSet.php:372
_HasActive()
Definition: MenuSet.php:354
Render( $submenus_inline=false)
Definition: MenuSet.php:462
MakeSomethingActive( $test_pattern)
Definition: MenuSet.php:413