<?php
// $Revision: 1.1.2.11 $
// ------------------------------------------------------------------------- //
//  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 //
// ------------------------------------------------------------------------- //

if ( ! defined( 'XOOPS_ROOT_PATH' ) ) exit();

/**
 * XooNIps Group Handler class
 */
class XooNIpsGroupHandler {
  var $_xg_handler;
  var $_xgl_handler;

  function XooNIpsGroupHandler() {
    $this->_xg_handler =& xoonips_getormhandler( 'xoonips', 'groups' );
    $this->_xgl_handler =& xoonips_getormhandler( 'xoonips', 'groups_users_link' );
  }

  /**
   * check group existance
   *
   * @access public
   * @param string $name group name
   * @return bool true if group exists
   */
  function existsGroup( $name ) {
    $criteria = new Criteria( 'name', $name );
    $cnt = $this->_xg_handler->getCount( $criteria );
    return ( $cnt != 0 );
  }

  /**
   * check user is group member
   *
   * @access public
   * @param int $uid user id
   * @param int $gid group id
   * @return bool true if user is group member
   */
  function isGroupMember( $uid, $gid ) {
    $criteria = new CriteriaCompo();
    $criteria->add( new Criteria( 'uid', $uid ) );
    $criteria->add( new Criteria( 'gid', $gid ) );
    $cnt = $this->_xgl_handler->getCount( $criteria );
    return ( $cnt == 0 ) ? false : true;
  }

  /**
   * check user is group admin
   *
   * @access public
   * @param int $uid user id
   * @param int $gid group id
   * @return bool true if user is group admin
   */
  function isGroupAdmin( $uid, $gid = null ) {
    $criteria = new CriteriaCompo();
    $criteria->add( new Criteria( 'uid', $uid ) );
    $criteria->add( new Criteria( 'is_admin', 1 ) );
    if ( is_null( $gid ) ) {
      $criteria->add( new Criteria( 'gid', GID_DEFAULT, '!=' ) );
    } else {
      $criteria->add( new Criteria( 'gid', $gid ) );
    }
    $cnt = $this->_xgl_handler->getCount( $criteria );
    return ( $cnt == 0 ) ? false : true;
  }

  /**
   * get group ids
   *
   * @access public
   * @param int $uid user id if null to get all group ids
   * @param bool $is_admin_only true if limit to user is administrator only
   * @return array subscribed group ids
   */
  function getGroupIds( $uid = null, $is_admin_only = false ) {
    $criteria = new CriteriaCompo( new Criteria( 'gid', GID_DEFAULT, '!=' ) );
    if ( ! is_null( $uid ) ) {
      $criteria->add( new Criteria( 'uid', $uid ) );
      if ( $is_admin_only ) {
        $criteria->add( new Criteria( 'is_admin', 1 ) );
      }
    }
    $xgl_objs =& $this->_xgl_handler->getObjects( $criteria, false, 'gid' );
    $gids = array();
    foreach ( $xgl_objs as $xgl_obj ) {
      $gids[] = $xgl_obj->get( 'gid' );
    }
    return $gids;
  }

  /**
   * get group joined user ids
   *
   * @access public
   * @param int $gid group id
   * @param bool $is_admin_only true if limit to user is administrator only
   * @retrun array user ids
   */
  function getUserIds( $gid, $is_admin_only = false ) {
    $criteria = new CriteriaCompo( new Criteria( 'gid', GID_DEFAULT, '!=' ) );
    $criteria->add( new Criteria( 'gid', $gid ) );
    if ( $is_admin_only ) {
      $criteria->add( new Criteria( 'is_admin', 1 ) );
    }
    $xgl_objs =& $this->_xgl_handler->getObjects( $criteria, false, 'uid' );
    $uids = array();
    foreach ( $xgl_objs as $xgl_obj ) {
      $uids[] = $xgl_obj->get( 'uid' );
    }
    return $uids;
  }

  /**
   * get group index ids
   *
   * @access public
   * @param int $uid user id
   * @param bool $is_admin_only true if limit to user is administrator only
   * @retrun array index ids
   */
  function getGroupIndexIds( $uid = null, $is_admin_only = false ) {
    $criteria = new CriteriaCompo();
    $criteria->add( new Criteria( 'gid', GID_DEFAULT, '!=', 'xg' ) );
    if ( ! is_null( $uid ) ) {
      $criteria->add( new Criteria( 'uid', $uid ) );
      if ( $is_admin_only ) {
        $criteria->add( new Criteria( 'is_admin', 1 ) );
      }
    }
    $join = new XooNIpsJoinCriteria( 'xoonips_groups', 'gid', 'gid', 'INNER', 'xg' );
    $xgl_objs =& $this->_xgl_handler->getObjects( $criteria, false, 'xg.group_index_id AS gxid', false, $join );
    $gxids = array();
    foreach ( $xgl_objs as $xgl_obj ) {
      $gxids[] = $xgl_obj->getExtraVar( 'gxid' );
    }
    return $gxids;
  }

  /**
   * get group object
   *
   * @access public
   * @param int $gid group id
   * @return object instance of XooNIpsOrmGroups 
   */
  function &getGroupObject( $gid ) {
    return $this->_xg_handler->get( $gid );
  }

  /**
   * get group objects
   *
   * @access public
   * @param array $gids array of group ids
   * @return array object instance array of XooNIpsOrmGroups
   */
  function &getGroupObjects( $gids = null ) {
    $criteria = new CriteriaCompo( new Criteria( 'gid', GID_DEFAULT, '!=' ) );
    if ( ! is_null( $gids ) ) {
      $criteria->add( new Criteria( 'gid', '('.implode( ',', $gids ).')', 'IN' ) );
    }
    return $this->_xg_handler->getObjects( $criteria );
  }

  /**
   * add user to XooNIps group
   *
   * @access public
   * @param int $gid group id
   * @param int $uid user id
   * @param bool $is_admin true if user will be group admin
   * @return bool false if failure
   */
  function addUserToXooNIpsGroup( $gid, $uid, $is_admin ) {
    $xu_handler =& xoonips_getormhandler( 'xoonips', 'users' );
    $is_admin_new = ( $is_admin ) ? 1 : 0;
    // check user and group exists
    $criteria = new Criteria( 'uid', $uid );
    if ( $xu_handler->getCount( $criteria ) != 1 ) {
        return false; // user not found
    }
    $criteria = new Criteria( 'gid', $gid );
    if ( $this->_xg_handler->getCount( $criteria ) != 1 ) {
      return false; // group not found
    }
    // check current groups
    $criteria = new CriteriaCompo( new Criteria( 'gid', $gid ) );
    $criteria->add( new Criteria( 'uid', $uid ) );
    $xgl_objs =& $this->_xgl_handler->getObjects( $criteria );
    $xgl_count = count( $xgl_objs );
    if ( $xgl_count == 0 ) {
      // insert user to group
      $xgl_obj =& $this->_xgl_handler->create();
      $xgl_obj->setVar( 'gid', $gid, true ); // not gpc
      $xgl_obj->setVar( 'uid', $uid, true ); // not gpc
      $xgl_obj->setVar( 'is_admin', $is_admin_new, true ); // not gpc
      if ( ! $this->_xgl_handler->insert( $xgl_obj ) ) {
        return false;
      }
    } else if ( $xgl_count == 1 ) {
      // already exists
      $xgl_obj =& $xgl_objs[0];
      $is_admin_old = $xgl_obj->get( 'is_admin' );
      if ( $is_admin_old != $is_admin_new ) {
        // update is_admin field
        $xgl_obj->setVar( 'is_admin', $is_admin_new, true ); // not gpc
        if ( ! $xgl_handler->insert( $xgl_obj ) ) {
          return false;
        }
      } else {
        // status not changed
        return true;
      }
    } else {
      // unexcepted error - the user joined duplicated same group
      die( 'Fatal error occurred in '. __FILE__.' line '.__LINE__ );
    }
    // record event log
    $event_handler =& xoonips_getormhandler( 'xoonips', 'event_log' );
    $event_handler->recordInsertGroupMemberEvent( $uid, $gid );
    return true;
  }

  /**
   * add user to default xoonips group
   *
   * @access public
   * @param int $uid user id
   * @return bool false if failure
   */
  function addUserToDefaultXooNIpsGroup( $uid ) {
    $default_group_id = GID_DEFAULT;
    $is_admin = false;
    return $this->addUserToXooNIpsGroup( $default_group_id, $uid, $is_admin );
  }

  /**
   * delete user from xoonips group
   *
   * @access public
   * @param int $uid user id
   * @param int $gid group id
   * @param bool $force force deletion
   * @return bool false if failure
   */
  function deleteUserFromXooNIpsGroup( $gid, $uid, $force = false ) {
    $xu_handler =& xoonips_getormhandler( 'xoonips', 'users' );
    // check user and group exists
    $criteria = new Criteria( 'uid', $uid );
    if ( $xu_handler->getCount( $criteria ) != 1 ) {
        return false; // user not found
    }
    $criteria = new Criteria( 'gid', $gid );
    if ( $this->_xg_handler->getCount( $criteria ) != 1 ) {
      return false; // group not found
    }
    // check current groups
    $criteria = new CriteriaCompo( new Criteria( 'gid', $gid ) );
    $criteria->add( new Criteria( 'uid', $uid ) );
    $xgl_objs =& $this->_xgl_handler->getObjects( $criteria );
    $xgl_count = count( $xgl_objs );
    if ( $xgl_count == 0 ) {
      return true;
    } else if ( $xgl_count == 1 ) {
      $xgl_obj =& $xgl_objs[0];
      if ( ! $force && $xgl_obj->get( 'is_admin' ) == 1 ) {
        // administrator can not leave from group member
        return false;
      }
      if ( ! $this->_xgl_handler->deleteAll( $criteria ) ) {
        return false;
      }
    } else {
      // unexcepted error - the user joined duplicated same group
      die( 'Fatal error occurred in '. __FILE__.' line '.__LINE__ );
    }
    // record event log
    $event_handler =& xoonips_getormhandler( 'xoonips', 'event_log' );
    $event_handler->recordDeleteGroupMemberEvent( $uid, $gid );
    return true;
  }

  /**
   * create new group
   *
   * @access public
   * @param string $name group name
   * @param string $desc group description
   * @param array $admin_uids administrator's uids
   * @param int $max_item maximum number of items
   * @param int $max_index maximum number of indexes
   * @param float $max_size maximum storage size [MB]
   * @return bool false if failure
   */
  function createGroup( $name, $desc, $admin_uids, $max_item, $max_index, $max_size ) {
    // create group
    $xg_obj =& $this->_xg_handler->create();
    $xg_obj->setVar( 'gname', $name, true ); // not gpc
    $xg_obj->setVar( 'gdesc', $desc, true ); // not gpc
    $xg_obj->setVar( 'group_item_number_limit', $max_item, true ); // not gpc
    $xg_obj->setVar( 'group_index_number_limit', $max_index, true ); // not gpc
    $xg_obj->setVar( 'group_item_storage_limit', $max_size, true ); // not gpc
    if ( $this->_xg_handler->insert( $xg_obj ) ) {
      return false;
    }
    $gid = $xg_obj->get( 'gid' );
    // create group root index
    $index_handler =& xoonips_getormhandler( 'xoonips', 'index' );
    $gxid = $index_handler->createGroupRootIndex( $gid );
    if ( $gxid === false ) {
      $this->_xg_handler->delete( $xg_obj );
      return false;
    }
    // update group index id
    $xg_obj->setVar( 'group_index_id', $gxid, true ); // not gpc
    if ( ! $this->_xg_handler->insert( $xg_obj ) ) {
      // TODO: remove index
      return false;
    }
    // record event log
    $event_handler =& xoonips_getormhandler( 'xoonips', 'event_log' );
    $event_handler->recordInsertGroupEvent( $gid );
    // add admin user to group
    foreach ( $admin_uids as $uid ) {
      $this->addUserToXooNIpsGroup( $gid, $uid, true );
    }
    return true;
  }

  /**
   * update group
   *
   * @access public
   * @param int $gid group id
   * @param string $name group name
   * @param string $desc group description
   * @param array $admin_uids administrator's uids
   * @param int $max_item maximum number of items
   * @param int $max_index maximum number of indexes
   * @param float $max_size maximum storage size [MB]
   * @return bool false if failure
   */
  function updateGroup( $gid, $name, $desc, $admin_uids, $max_item, $max_index, $max_size ) {
    $xg_obj =& $this->_xg_handler->get( $gid );
    if ( is_object( $xg_obj ) ) {
      return false;
    }
    $old_name = $xg_obj->get( 'gname' );
    $xg_obj->setVar( 'gname', $name, true ); // not gpc
    $xg_obj->setVar( 'gdesc', $desc, true ); // not gpc
    $xg_obj->setVar( 'group_item_number_limit', $max_item, true ); // not gpc
    $xg_obj->setVar( 'group_index_number_limit', $max_index, true ); // not gpc
    $xg_obj->setVar( 'group_item_storage_limit', $max_size, true ); // not gpc
    if ( ! $this->_xg_handler->insert( $xg_obj ) ) {
      return false;
    }
    if ( $old_name != $name ) {
      // rename index title
      $xid = $xg_obj->get( 'group_index_id' );
      $index_handler =& xoonips_getormhandler( 'xoonips', 'index' );
      if ( ! $index_handler->renameIndexTitle( $xid, $name ) ) {
        return false;
      }
    }
    // record event log
    $event_handler =& xoonips_getormhandler( 'xoonips', 'event_log' );
    $event_handler->recordUpdateGroupEvent( $gid );
    return true;
  }

  /**
   * delete xoonips group
   *
   * @param int $gid group id
   * @return bool false if failure
   */
  function deleteGroup( $gid ) {
    $xg_obj =& $this->_xg_handler->get( $gid );
    if ( is_object( $xg_obj ) ) {
      return false;
    }
    // delete rankings
    $admin_ranking_handler =& xoonips_gethandler( 'xoonips', 'admin_ranking' );
    if ( ! $admin_ranking_handler->deleteGroupRankings( $gid ) ) {
       return false;
    }
    // delete group members
    $uids = $this->getUserIds( $gid );
    foreach ( $uids as $uid ) {
      if ( $this->deleteUserFromXooNIpsGroup( $uid, $gid, true ) ) {
        return false;
      }
    }
    // delete group indexes
    $index_handler =& xoonips_gethandler( 'xoonips', 'index' );
    if ( ! $index_handler->deleteGroupIndex( $gid ) ) {
       return false;
    }
    // delete group
    if ( ! $this->_xg_handler->delete( $xg_obj ) ) {
      return false;
    }
    // record event log
    $event_handler =& xoonips_getormhandler( 'xoonips', 'event_log' );
    $event_handler->recordUpdateGroupEvent( $gid );
  }
}

?>
