Location: PHPKode > projects > Saurus CMS > classes/menu.class.php
<?php
/**
 * This source file is is part of Saurus CMS content management software.
 * It is licensed under MPL 1.1 (http://www.opensource.org/licenses/mozilla1.1.php).
 * Copyright (C) 2000-2010 Saurused Ltd (http://www.saurus.info/).
 * Redistribution of this file must retain the above copyright notice.
 * 
 * Please note that the original authors never thought this would turn out
 * such a great piece of software when the work started using Perl in year 2000.
 * Due to organic growth, you may find parts of the software being
 * a bit (well maybe more than a bit) old fashioned and here's where you can help.
 * Good luck and keep your open source minds open!
 * 
 * @package		SaurusCMS
 * @copyright	2000-2010 Saurused Ltd (http://www.saurus.info/)
 * @license		Mozilla Public License 1.1 (http://www.opensource.org/licenses/mozilla1.1.php)
 * 
 */


/**
 * Menu tree functions
 * 
 */


/**
 * Class for creating and printing menu tree 
 * 
 * 
 * 
 * @package CMS
 * 
 * @param array tree 
 * @param string datatype   optional, for custom operations, shows which data we are handling: group/profile
 * @param string param_name   parameter name passed to href
 * @param string params   all additional parameters, will be passed to href
 * @param string tree_title - optional, first row headline
 * @param string tree_icon - optional, will be placed before first row headline
 * @param bool selectform - 1/0, if selectform submit or usual href
 *
 * constructor new Menu(array(
 *   tree => $data_array,
 *	[datatype => "group"] # 
 *   [param_name => "group_id"] # .. err.. should deprecate it soon... 
 *	[tree_title => $site->sys_sona(array(sona => "groups", tyyp=>"admin"))]
 *	[expand_all  => 0/1] default : 0 // expand all branches in the tree
 *	[show_checkboxes  => 0/1]  default: 0 // shows checkboxes near sections
 *
 * ));
 * 
 */
class Menu extends BaasObjekt {

var $parents;
var $max_tase;
var $tree;
var $parent_object;
var $object_parent;
var $path_arr; // array of parent headlines
	####################
	# MENU
	function Menu () {
		$args = func_get_arg(0);
		$this->BaasObjekt($args);
		$this->args = &$args;

		$this->maximum_allowed = 20; // protect from infinite cycles
		$this->group_id = $this->site->fdat['group_id']+1-1; // to numeric format
		if (!is_array($args['tree']))$args['tree'] = array();

		$this->with_checkboxes = $args['with_checkboxes'];

		###########
		# PERMISSIONS CHECK - get group permissions for current user
		if($args['datatype']=='group'){
			if ($this->site->user->user_id && !isset($this->site->user->aclpermissions)) { 
				$this->site->user->aclpermissions = $this->site->user->load_aclpermissions();
			} 
			elseif($this->site->guest && !isset($this->site->guest->aclpermissions)) { 
				$this->site->guest->aclpermissions = $this->site->guest->load_aclpermissions();
			}
			$aclpermissions = ($this->site->user->user_id ? $this->site->user->aclpermissions : $this->site->guest->aclpermissions);
			#echo printr($aclpermissions);

			# save read-allowed groups ID-s
			$read_allowed_groups = array();
			foreach($aclpermissions as $perm_group_id => $perm){
				if($perm['R']){ $read_allowed_groups[] = $perm_group_id; }
			}
			#echo printr($read_allowed_groups);
		}

		######## pass_href
		if (is_array($this->site->fdat)){
			foreach ($this->site->fdat as $key => $val){
				$this->pass_href .= "&".$key."=".$val;
			}
		}
		# array of all leafs in open tree
		$this->parents_arr = array();
		# array of all IDs under the ID
		$this->subtree_arr = array();

		$i=0;
		$this->tree[0]['id'] = 0;
		$this->tree[0]['parent'] = '';
		$this->tree[0]['name'] = $args['tree_title'];

		##############
		# TREE
			foreach ($args['tree'] as $key => $val){
				$this->parent_object[$val['parent']] = $val['id'];
				$this->object_parent[$val['id']] = $val['parent'];
				#	echo "TEST:".$val['id'].":p ".$val['parent']."<br>";

				$this->subtree_arr[$val['parent']][] = $val['id'];

				if (!$first[$val['parent']]) {
					$this->subtrees[$val['parent']] = $val['id'];
					$first[$val['parent']] = 1;
				}
				# permissions check: don't add group data to tree if leaf(group) is not readable
				if($args['datatype']=='group' && !$this->site->user->is_superuser && !in_array($val['id'],$read_allowed_groups)){ continue; }

				$this->tree[$val['id']]['id'] = &$args['tree'][$key]['id'];
				$this->tree[$val['id']]['parent'] = &$args['tree'][$key]['parent'];
				$this->tree[$val['id']]['name'] = &$args['tree'][$key]['name'];
			}
		# / TREE
		##############

			########## CHILDREN

			# if group menu then get group children (sql in function is different)
			if($args['datatype']=='group'){
				$this->find_group_childrens();
			}
			# if profile menu then get source table children (sql in function is different)
			if($args['datatype']=='profile'){
				$this->find_profile_childrens();
			}

			########## PARENTS
			$this->find_parents($this->group_id, 0);

			########## MAXTASE: on vaja teada, kui sügav on Menu
			$this->max_tase = count($this->parents_arr);

#				$this->add('
#				<table width="100%" height="100%"  border="0" cellpadding="0" cellspacing="0">');

				########### FAVOURITES row
#				$this->print_favourites();

			$obj = $this->tree[0];

			#####################
			# print 1. row for profile tree, it's type name
			if($args['datatype']=='profile'){
				$this->title = '
						<tr>
							<td '.($args['no_separator']?'':'class="scms_groupheader"').'>';
				if($args['table']) $this->title .='<a href="?source_table='.$args['table'].'">'.($this->site->fdat['source_table']==$args['table']?'<span class="scms_selected">':'');

				$this->title .= '<IMG SRC="'.$this->args['tree_icon'].'" WIDTH="16" HEIGHT="16" BORDER="0" ALT="" align=absmiddle>&nbsp;&nbsp;';
				$this->title .= ($this->args['tree_title'] ? $this->args['tree_title'] : $obj['name']);

				if($args['table']) $this->title .= ($this->site->fdat['source_table']==$args['table']?'</span>':'').'</a>';
				$this->title .= '
							</td>
						</tr>';

			} # profile tree title

			############# SET TITLE ROW 
			else {
				$this->title = '
						<tr>
							<td '.($args['no_separator']?'':'class="scms_groupheader"').'>
									<a href="'.$href.'" '.$js_event.'><IMG SRC="'.$this->args['tree_icon'].'" WIDTH="16" HEIGHT="16" BORDER="0" ALT="" align=absmiddle></a>&nbsp;&nbsp;<a href="'.$href.'">'.$this->args['tree_title'].'</a>
							</td>
						</tr>
				';
			}

			$tase = 0;
		
			######## PARAMS: set parameter name: will be in "href" link
			if($args['datatype']=='group') { $param_name = "group_id"; }
			if($args['datatype']=='profile') { $param_name = "profile_id"; }			
			if($args['datatype']=='extension') { $param_name = "extension_id"; }			
			if(!$param_name) { $param_name = $args['param_name']; }

			########################
			# start making menu
				$this->make_tase(array(
					parent => $obj,
					tase => ++$tase,
					param_name => $param_name,
				));
#			$this->add('</td>
#					</tr>			
#				</table>');

	} # constructor
	# / MENU
	####################

	####################
	# FUNCTION make_tase - recursive func

	function make_tase() {
		global $site;

		$args = func_get_arg(0);
		if ($args['tase']>10){ # prevent infinite loop
			return 0;
		}
		# kui tase on suurem kui lubatud max-väärtus
		# siis väljuda
		if ($args['tase']>=$this->maximum_allowed) {
			#$this->debug->msg("Jõuti max lubatud tasemeni (".$args['tase']."). Lõpetan menüü tegemise.");
			return 0;
		}
		if(!($this->args['datatype'] == 'group' && $args['tase'] == 1)){ # special case, first is everybody
			$this->add('<ul  class="scms_tree_menu">');
		}
		########### TREE DATA
		reset($this->tree);
		$list = array();
		foreach ($this->tree as $key => $val){
			if ($val['parent']==$args['parent']['id']){
				$list[] = &$this->tree[$key];
			}				
		}
			$list_on_viimane = $list[count($list)-1]['id'];
	####################
	# loopover folders
	foreach ($list as $obj) {

			$is_selected = in_array($obj['id'], $this->parents_arr);

			if ($this->args['expand_all']){
				$is_selected = 1;
			}

			if (in_array($obj['id'], $this->parents_arr)){
				$is_in_current = 1;
				# teeme kus-ma-olen riba:
				if ($obj['id']) {$this->path_arr[] = $obj['name'];}
			}
		####################
		# print folder row 
		# ara prindi obj_id=0 :
		if ($obj['id']){
			########## GET HREF value
			if($this->args['selectform']) {
				$href = "javascript:select_group('".$obj['id']."')";
			}
			# default case:
			else {
				$href = '?'.$args['param_name'].'='.$obj['id'].$this->args['params'];
			}

			########## STYLE:
			$span_class = ""; 
			$span_end = ""; 
			# selected group or profile 
			if($obj['id'] == $this->site->fdat[$args['param_name']]) { 
				# class with subtree and without it:	
				$class = $this->subtrees[$obj['id']] ?  "scms_minus" : "scms_plain";
				$span_class = '<span class="scms_selected">'; 
				$span_end = '</span>';
				# for public usage  - to get group name without loading all group info
				$this->sel_group_name = $obj['name'];
			}
			# if subtree exist & leaf IS selected in tree
			elseif($this->subtrees[$obj['id']] && $is_selected) { $class = "scms_minus"; }
			# if subtree exist & leaf IS NOT selected in tree
			elseif($this->subtrees[$obj['id']] && !$is_selected) { $class = "scms_plus"; }
			# default: open subtree or last leaf
			else { 	$class = "scms_plain"; }

			######### JS EVENT
			if($this->args['datatype'] == 'group'){
				$js_event = "ondblclick=\"javascript:void(openpopup('".$this->site->CONF['wwwroot'].$this->site->CONF['adm_path']."/edit_group.php?group_id=".$obj['id']."&tab=group&op=edit','group','366','450'))\"";
			}
			############# PRINT EVERYBODY
			# special case: if first row of groups (everybody group)
			if($this->args['datatype'] == 'group' && $args['tase'] == 1){
				$this->title = '
						<tr>
							<td '.($args['no_separator']?'':'class="scms_groupheader"').'>
									<a href="'.$href.'" '.$js_event.'><IMG SRC="'.$this->args['tree_icon'].'" WIDTH="16" HEIGHT="16" BORDER="0" ALT="" align=absmiddle></a>&nbsp;&nbsp;<a href="'.$href.'">'.$site->sys_sona(array(sona => "Groups", tyyp=>"kasutaja")).'</a>
							</td>
						</tr>
				';
			}
			############# PRINT FOLDER
			else {

#				$this->add($args['tase']);
			$this->add('<li class="'.$class.'">');
		

			# Show cheboxes, if need:
			if ($this->args['show_checkboxes']){
				$checkbox = '<input type=checkbox onClick="sel_box_group('.$obj['id'].', this)" name="selgroup_'.$obj['id'].'" id="selgroup_'.$obj['id'].'">';
			} else {
				$checkbox = '';
			}			

			########## PRINT link & name:

			$this->add('<a href="'.$href.'" '.$js_event.'>'.$span_class.$checkbox.$obj['name'].$span_end.'</a>');

			$this->add('</li>');

			########## print checkboxes if required (for selecting groups):
			if($this->with_checkboxes) {
#				$this->add('<td width="16"><input type="checkbox" name="select_group" value="'.$obj['id'].'"></td>');
			}

			} # usual case

		}
		# / print row
		###################

			$viimane_tasemel = &$args['viimane_tasemel'];
			$viimane_tasemel[$args['tase']] = ($obj['id']==$list_on_viimane ? 1:0);

			######## Recursive step
			if ($is_selected && $obj['id']) {
				$this->make_tase(array(
					parent => $obj,
					viimane_tasemel => &$viimane_tasemel,					
					tase => $args['tase']+1,
					param_name => $args['param_name']				
				));
			}
			$y++;
	} # while alamlist
	# / loopover folders
	####################

		if(!($this->args['datatype'] == 'group' && $args['tase'] == 1)){ # special case, first is everybody
			$this->add('</ul>');
		}

	}
	# / FUNCTION make_tase
	####################


	####################
	# FUNCTION find_group_childrens

		# NB! is datatype specific function; 
		# returns group_id after jumping:
		function find_group_childrens($z=0){ # private function

			$z++;
			if (!( $z>50)){
				if (!$this->subtrees[$this->group_id]){
					return $this->group_id;
				}
				
				$sql = $this->site->db->prepare("SELECT count(*) FROM groups  WHERE parent_group_id=? ", $this->group_id);
				$sth = new SQL($sql);
				$has_childrens = $sth->fetchsingle();

				if ($has_childrens){
					return $this->group_id;
				} else {
					$this->group_id = $this->subtrees[$this->group_id];
					$this->find_group_childrens($z);
				}
			}
		} # function

	####################
	# FUNCTION find_profile_childrens

		# NB! is datatype specific function; 
		# returns profile_id after jumping:
		function find_profile_childrens($z=0){ # private function

			$z++;
			if (!( $z>50)){

				if (!$this->subtrees[$this->profile_id]){
					return $this->profile_id;
				}
				
				$sql = $this->site->db->prepare("SELECT count(*) FROM object_profiles  WHERE source_table=? ", $this->profile_id);
				$sth = new SQL($sql);
				$has_childrens = $sth->fetchsingle();

				if ($has_childrens){
					return $this->profile_id;
				} else {
					$this->profile_id = $this->subtrees[$this->profile_id];
					$this->find_profile_childrens($z);
				}
			}
		} # function


	####################
	# FUNCTION find_parents

		# retuns array of parents:
		function find_parents($id, $i){
			if (!$i){
				$this->parents_arr[]=$id;
			}
			$i++;
			if ($i>50) {
				#echo "cycle!"; 
				return 0;
			}
			
			if ($this->object_parent[$id]){				
				$this->parents_arr[] = $this->object_parent[$id];
				$this->find_parents($this->object_parent[$id], $i);
			} else {
				$this->parents_arr[] = 0;
				return 0;
			}		
		}


	####################
	# FUNCTION add - adding html to source variable
	function add($html) {

		$this->source .= $html;
	}

	####################
	# FUNCTION get_full_subtree

	# public to get ALL ID-s recursively under given ID
	function get_full_subtree() {
		$args = func_get_arg(0);
		
		$id = $args[parent_id];
		if($id){
			$this->full_subtree[] = $id;
			# if children exist:
			if(sizeof($this->subtree_arr[$id]) > 0) {
				foreach($this->subtree_arr[$id] as $key=>$value) {
					# recursive step:
					$subtree = $this->get_full_subtree(array("parent_id" => $value));
				}
			}
		} # parameter not null

		return $full_subtree;
	}

	####################
	# FUNCTION print_favourites

	function print_favorites() {

		$this->add('
					<tr>
						<td class="scms_groupheader">
								<a href="#"><IMG SRC="'.$this->site->CONF['wwwroot'].$this->site->CONF[styles_path].'/gfx/icons/16x16/actions/bookmark.png" WIDTH="16" HEIGHT="16" BORDER="0" ALT="" align=absmiddle></a>&nbsp;&nbsp;<a href="#">Lemmikud</a>
						</td>
					</tr>
					<tr>
						<td valign=top>
								<!-- Favorites -->
								<TABLE width="100%" border="0" cellpadding="0" cellspacing="0">
									<tr>
										<td>									
											
										<ul class="scms_tree_menu">
											<li class="scms_plain"><a href="#">Teine Tase</a></li>
											<li class="scms_plain"><a href="#">Teine Tase</a></li>
										</ul>

										
										</td>
									</tr>
								</TABLE>
								<!-- //Favorites -->
						</td>
					</tr>
			');	
	}
	# / FUNCTION print_favourites
	####################

}
Return current item: Saurus CMS