<?php
// $Revision: 1.8.4.1.2.4 $
// ------------------------------------------------------------------------- //
//  XooNIps - Neuroinformatics Base Platform System                          //
//  Copyright (C) 2005-2008 RIKEN, Japan All rights reserved.                //
//  http://xoonips.sourceforge.jp/                                           //
// ------------------------------------------------------------------------- //
//  This program is free software; you can redistribute it and/or modify     //
//  it under the terms of the GNU General Public License as published by     //
//  the Free Software Foundation; either version 2 of the License, or        //
//  (at your option) any later version.                                      //
//                                                                           //
//  You may not change or alter any portion of this comment or credits       //
//  of supporting developers from this source code or any supporting         //
//  source code which is considered copyrighted (c) material of the          //
//  original comment or credit authors.                                      //
//                                                                           //
//  This program is distributed in the hope that it will be useful,          //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of           //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            //
//  GNU General Public License for more details.                             //
//                                                                           //
//  You should have received a copy of the GNU General Public License        //
//  along with this program; if not, write to the Free Software              //
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA //
// ------------------------------------------------------------------------- //

	/*
		attributes add to index:
			bool is_last; // not null
			int depth; // not null
			int child_count; // not null
	 */
	
	
	
	/** A child is added recursively. (Caution) not add parentXID.
	 * @param $parentXID parentXID
	 * @param $in  XID->index Conversion table
	 * @param $childFinder  XID->array(childXID) Conversion table
	 * @param $out Output place. Priority is given to the depth when searching.
	 *             Brothers output in result sorted by sort_number.  $out[] = index
	 *             ROOT's depth = 0 ($out don't contain ROOT.)
	 * @return nothing
	 */
	
	function genIndexTreeAdd( $parentXID, &$indexFinder, &$childFinder, &$out, $depth ){
		$depth++;
		$len = count($childFinder[$parentXID]);
		for ( $i = 0; $i < $len; $i++ ){
			$xid = $childFinder[$parentXID][$i];
			
			$indexFinder[$xid]['is_last'] = ( $i == $len-1 );
			$indexFinder[$xid]['depth'] = $depth;
			
			if ( isset( $childFinder[$xid] ) ){
				$indexFinder[$xid]['child_count'] = count($childFinder[$xid]);
				$indexFinder[$xid]['child'] = $childFinder[$xid];
			}
			else
				$indexFinder[$xid]['child_count'] = 0;
			
			// first, add children.
			$out[] = $indexFinder[$xid];
			
			// next, children's posterity is added recursively.
			if ( isset( $childFinder[$xid] ) )
				genIndexTreeAdd( $xid, $indexFinder, $childFinder, $out, $depth );
		}
	}

	/* todo: to collect genIndexTree, genPublicIndexTree, genMyIndexTree, genSameAreaIndexTree, genPublicPrivateIndexTree, 
	 *       exractWritableIndexTree, and extractEditableIndexTree.
	 * genIndexTree( xnpsid, uid, public_flag, gids, private_flag );
	 */
	
	function genIndexTree0( $xnpsid ){
		$criteria = array( 'orders'=>array(
		  array('name'=>'parent_index_id','order'=>'ASC'),
		  array('name'=>'sort_number', 'order'=>'ASC' ) ) );
		$indexes = array();
		xnp_get_all_indexes( $xnpsid, $criteria, $indexes );
		if ( empty( $indexes ) ) return array();
		return $indexes;
	}
	
	function genIndexTree1( &$indexes ){
		// divide into every parents
		$indexFinder = array(); // index_id -> index
		$childFinder = array(); // index_id -> child_index_id
		while ( list ( $dummy, $index ) = each( $indexes ) ){
			if ( $index === false )
				continue;
			$parent_xid = $index['parent_index_id'];
			if ( !isset( $childFinder[$parent_xid] ) )
				$childFinder[$parent_xid] = array();
			$childFinder[$parent_xid][] = $index['item_id'];
			
			$indexFinder[ $index['item_id'] ] = $index;
		}
		
		// add recursively from ROOT
		$out = array();
		genIndexTreeAdd( IID_ROOT, $indexFinder, $childFinder, $out, 0 );
		return $out;
	}

	/** get Index tree
	 * @param $xnpsid XNPSID
	 * @return tree Empty array in error.
	 */
	function genIndexTree( $xnpsid ){
		$indexes = genIndexTree0( $xnpsid );
		return genIndexTree1( $indexes );
	}


	/** get Public index tree. 
	 * @param $xnpsid XNPSID
	 * @return tree Empty array in error.
	 */
	function genPublicIndexTree( $xnpsid ){
		$indexes = genIndexTree0( $xnpsid );
		filterPublicIndex( $indexes );
		return genIndexTree1( $indexes );
	}
	
	function filterPublicIndex( &$indexes ){
		$len = count($indexes);
		for ( $i = 0; $i < $len; $i++ ){
			if ( $indexes[$i] === false ) continue;
			if ( $indexes[$i]['open_level'] != OL_PUBLIC )
				$indexes[$i] = false;
		}
	}

	/** get Index tree for moderator
	 *  not contain other's private index, and not contain group-index of group which he does not belong.
	 * @param $xnpsid XNPSID
	 * @return tree Empty array in error.
	 */
	function genMyIndexTree( $xnpsid, $uid ){
		$indexes = genIndexTree0( $xnpsid );
		filterMyIndex( $indexes, $xnpsid, $uid );
		return genIndexTree1( $indexes );
	}
	
	function filterMyIndex( &$indexes, $xnpsid, $uid ){
		$gids = array();
		$result = xnp_get_groups_by_uid( $xnpsid, $uid, array(), $gids );
		$gids = array_flip( $gids );
		
		$len = count($indexes);
		for ( $i = 0; $i < $len; $i++ ){
			$index = &$indexes[$i];
			if ( $index === false ) continue;
			if ( $index['open_level'] == OL_GROUP_ONLY ){
				if ( !isset( $gids[ $index['owner_gid'] ] ) ) // group which he does not belong.
				$indexes[$i] = false;
			}
			else if ( $index['open_level'] == OL_PRIVATE ){
				if ( $index['owner_uid'] != $uid ) // index is not this user's one.
				$indexes[$i] = false;
			}
		}
	}
	
	
	/** get Index tree.
	 *  get same index as $refIndex ($refIndex have same open_level and same owner_gid, and  same owner_uid)
	 * @param $xnpsid XNPSID
	 * @return tree Empty array in error.
	 */
	function genSameAreaIndexTree( $xnpsid, $uid, $refIndex ){
		$indexes = genIndexTree0( $xnpsid );
		filterSameAreaIndex( $indexes, $refIndex );
		return genIndexTree1( $indexes );
	}
	function filterSameAreaIndex( &$indexes, &$refIndex ){
		$len = count($indexes);
		for ( $i = 0; $i < $len; $i++ ){
			$index = &$indexes[$i];
			if ( $index === false ) continue;
			if (  !( $index['open_level'] == OL_PUBLIC     && $refIndex['open_level'] == OL_PUBLIC 
				  || $index['open_level'] == OL_GROUP_ONLY && $refIndex['open_level'] == OL_GROUP_ONLY && $index['owner_gid'] == $refIndex['owner_gid']
				  || $index['open_level'] == OL_PRIVATE    && $refIndex['open_level'] == OL_PRIVATE    && $index['owner_uid'] == $refIndex['owner_uid'] ) )
				$indexes[$i] = false;
		}
	}
	
	
	/** get Index tree contains Public and Private Index.
	 * @param $xnpsid XNPSID
	 * @return tree Empty array in error.
	 */
	function genPublicPrivateIndexTree( $xnpsid, $uid ){
		$indexes = genIndexTree0( $xnpsid );
		filterPublicPrivateIndex( $indexes, $uid );
		return genIndexTree1( $indexes );
	}
	
	function filterPublicPrivateIndex( &$indexes, $uid ){
		$len = count($indexes);
		for ( $i = 0; $i < $len; $i++ ){
			$index = &$indexes[$i];
			if ( $index === false ) continue;
			if ( $index['open_level'] != OL_PUBLIC && !($index['open_level'] == OL_PRIVATE && $index['owner_uid'] == $uid ))
				$indexes[$i] = false;
		}
	}
	

	function filterWritableIndex( &$indexes, $xnpsid, $uid ){
		if ( xnp_is_moderator($xnpsid,$uid) )
			return;
		
		$isGroupAdmin = array();
		$criteria = array();
		$gids = array();
		$result = xnp_get_groups_by_uid( $xnpsid, $uid, $criteria, $gids );
		if ( $result == RES_OK ){
			foreach ( $gids as $key => $gid ){
				if ( xnp_is_group_admin( $xnpsid, (int)$gid, $uid ) )
					$isGroupAdmin[(int)$gid] = true;
			}
		}
		
		$len = count($indexes);
		for ( $i = 0; $i < $len; $i++ ){
			$index = &$indexes[$i];
			if ( $index === false ) continue;
			if ( !( $index['open_level'] == OL_PRIVATE && $index['owner_uid'] == $uid
			  || $index['open_level'] == OL_GROUP_ONLY && isset($isGroupAdmin[$index['owner_gid']]) ) )
				$indexes[$i] = false;
		}
	}
	
	// get editable Index in editindex.php.
	function filterEditableIndex( &$indexes, $xnpsid, $uid, $puid, $isPublicEditable ){
		$isPublicEditable |= xnp_is_moderator($xnpsid,$uid);
		$isGroupAdmin = array();
		$criteria = array();
		$gids = array();
		$result = xnp_get_groups_by_uid( $xnpsid, $puid, $criteria, $gids );
		if ( $result == RES_OK ){
			foreach ( $gids as $key => $gid ){
				if ( xnp_is_group_admin( $xnpsid, (int)$gid, $puid ) )
					$isGroupAdmin[(int)$gid] = true;
			}
		}
		
		$len = count($indexes);
		for ( $i = 0; $i < $len; $i++ ){
			$index = &$indexes[$i];
			if ( $index === false ) continue;
			if (!( $index['open_level'] == OL_PRIVATE && $index['owner_uid'] == $puid
                   || $index['open_level'] == OL_GROUP_ONLY && isset($isGroupAdmin[$index['owner_gid']])
                   || $index['open_level'] == OL_PUBLIC && $isPublicEditable ))
				$indexes[$i] = false;
		}
	}
?>
