<?php

require_once XOOPS_TRUST_PATH .'/libs/xoonips/class/core/FieldGroup.class.php';
require_once 'UserFieldManager.class.php';
require_once XOOPS_TRUST_PATH .'/libs/xoonips/class/core/ComplementFactory.class.php';
require_once XOOPS_TRUST_PATH .'/libs/xoonips/class/core/Errors.class.php';
require_once XOOPS_TRUST_PATH .'/libs/xoonips/class/core/ViewTypeFactory.class.php';
require_once 'UserField.class.php';
require_once XOOPS_TRUST_PATH .'/libs/xoonips/class/core/Utils.class.php';
require_once XOOPS_TRUST_PATH .'/libs/xoonips/class/core/BeanFactory.class.php';
require_once XOOPS_TRUST_PATH .'/libs/xoonips/class/core/Transaction.class.php';
require_once 'Notification.class.php';
require_once XOOPS_TRUST_PATH . '/libs/xoonips/class/Enum.class.php';

class User_User {
	private $id;
	private $fields = array();
	private $fieldGroups = array();
    private $data = array();
    private $notification = null;
    private static $instance;
   	private $dirname;
	private $trustDirname;
 	private $xoopsTpl;

 	public function User_User() {
 		$root = XCube_Root::getSingleton();
		$root->getLanguageManager()->loadModuleAdminMessageCatalog(XCUBE_CORE_USER_MODULE_NAME);
		//get Items information
		$userFieldManager = User_UserFieldManager::getInstance();
		$this->dirname = $userFieldManager->getDirname();
		$this->trustDirname = $userFieldManager->getTrustDirname();
		$this->xoopsTpl = $userFieldManager->getXoopsTpl();
 		global $xoopsDB;
		$this->notification = new User_Notification($xoopsDB, $this->dirname, $this->trustDirname);
    	$this->setFieldGroups($userFieldManager->getFieldGroups());
    	$this->setFields($userFieldManager->getFields());
		$this->template = $this->dirname . '_user.html';
 	}
    
    public static function getInstance() {
    	if (!isset(self::$instance)) {
            self::$instance = new User_User();
        }
        return self::$instance;
    }
    
  	public function setId($id) {
		$this->id = $id;
   	}
   	
   	public function getId() {
   		return $this->id;
   	}
   	
   	public function setFields($fields) {
   		$this->fields = $fields;
   	}
   	
	public function setFieldGroups($fieldGroups) {
   		$this->fieldGroups = $fieldGroups;
   	}

   	public function setDataFromPost($data) {
   		$this->data = Xoonips_Utils::convertPost($data);
   	}
   	
	public function setData($data) {
   		$this->data = $data;
   	}
   	  	
	private function loadData() {
		loadBasicData();
		loadExtendData();
	}
	
	private function loadBasicData() {
		
	}
	
	private function loadExtendData() {
		
	}

	/**
	 *
	 * get id for html name attribute
	 *
	 * @param object $field
	 *        int $groupLoopId
	 * @return string
	 */
	protected function getFieldName($field, $groupLoopId, $id = null, $gid=0) {
		if ($gid == 0) $gid = $field->getFieldGroupId();
		if ($id == null) {
			return $gid . Xoonips_Enum::ITEM_ID_SEPARATOR . $groupLoopId . Xoonips_Enum::ITEM_ID_SEPARATOR . $field->getId();
		} else {
			return $gid . Xoonips_Enum::ITEM_ID_SEPARATOR . $groupLoopId . Xoonips_Enum::ITEM_ID_SEPARATOR . $id;
		}
	}

	/**
	 *
	 * get field xml
	 *
	 * @param string $html_name : name of html
	 * @return string $ret : name of xml
	 */
	public function getFieldXml($html_name) {
		$ret = '';
		$ids = explode(Xoonips_Enum::ITEM_ID_SEPARATOR, $html_name);
		$ids2 = explode('_', $ids[2]);
		$fieldBean = Xoonips_BeanFactory::getBean('FieldDetailBean', $this->dirname, $this->trustDirname);
		if (!($ret = $fieldBean->getFieldXml($ids2[0]))) {
			$ret = $html_name;
		}
		return $ret;
	}

	/**
	 * 
	 * registry input check
	 * 
	 * @param  object $errors:error
	 * @return 
	 */
	public function inputCheck(&$errors) {
		foreach ($this->fieldGroups as $fieldGroup) {
			$fieldGroup->inputCheck($this->data, $errors);
		}
	}
	
	/**
	 * 
	 * edit input check
	 * 
	 * @param  object $errors:error
	 * @return 
	 */
	public function editCheck(&$errors, $uid) {
		foreach ($this->fieldGroups as $fieldGroup) {
			$fieldGroup->editCheck($this->data, $errors, $uid);
		}
	}
	
	/**
	 * 
	 * search input check
	 * 
	 * @param  object $errors:error
	 * @return 
	 */
	public function searchCheck(&$errors) {
		foreach ($this->fieldGroups as $fieldGroup) {
			$fieldGroup->searchCheck($this->data, $errors);
		}
	}
	
	/**
	 * 
	 * get registry view
	 * 
	 * @param  int $uid:0
	 * @return array
	 */
	public function getRegistryView($uid) {
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$userType = $userBean->getUserType($uid);
		$fieldGroup = array();
		foreach ($this->fieldGroups as $group) {
			//$op:registry
			//$userType:guest
			$cnt = $group->countDisplayField(Xoonips_Enum::OP_TYPE_REGISTRY, $userType);
			if ($cnt > 0) {
				$groupName = $group->getName();
				$fieldGroup[] = array('name' => $groupName,
					 'isMust' => $group->isMust(Xoonips_Enum::OP_TYPE_REGISTRY, $userType),
					 'view' => $group->getRegistryView($cnt, $userType));
			}
		}
		$this->xoopsTpl->assign('viewType', 'input');
		$this->xoopsTpl->assign('fieldGroup', $fieldGroup);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}
	
	/**
	 * 
	 * get registry view with data
	 * 
	 * @param  int $uid:0
	 * @return array
	 */
	public function getRegistryViewWithData($uid) {
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		//$userType:guest
		$userType = $userBean->getUserType($uid);
		$fieldGroup = array();
		foreach ($this->fieldGroups as $group) {
			$cnt = $group->countDisplayField(Xoonips_Enum::OP_TYPE_REGISTRY, $userType);
			if ($cnt > 0) {
				$groupName = $group->getName();
				$fieldGroup[] = array('name' => $groupName,
					 'isMust' => $group->isMust(Xoonips_Enum::OP_TYPE_REGISTRY, $userType),
					 'view' => $group->getRegistryViewWithData($this->data, $cnt, $userType));
			}
		}
		$this->xoopsTpl->assign('viewType', 'input');
		$this->xoopsTpl->assign('fieldGroup', $fieldGroup);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}
	
	/**
	 * 
	 * get registry view for moderator
	 * 
	 * @param  
	 * @return array
	 */
	public function getRegistryViewForModerator() {
		$fieldGroup = array();
		foreach ($this->fieldGroups as $group) {
			$cnt = $group->countDisplayField(Xoonips_Enum::OP_TYPE_MANAGER_REGISTRY, Xoonips_Enum::USER_TYPE_MODERATOR);
			if ($cnt > 0) {
				$groupName = $group->getName();
				$fieldGroup[] = array('name' => $groupName,
					 'isMust' => $group->isMust(Xoonips_Enum::OP_TYPE_MANAGER_REGISTRY, Xoonips_Enum::USER_TYPE_MODERATOR),
					 'view' => $group->getRegistryView($cnt, Xoonips_Enum::USER_TYPE_MODERATOR, Xoonips_Enum::OP_TYPE_MANAGER_REGISTRY));
			}
		}
		$this->xoopsTpl->assign('viewType', 'input');
		$this->xoopsTpl->assign('fieldGroup', $fieldGroup);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}
	
	/**
	 * 
	 * get registry view with data for moderator
	 * 
	 * @param  
	 * @return array
	 */
	public function getRegistryViewWithDataForModerator() {
		$fieldGroup = array();
		foreach ($this->fieldGroups as $group) {
			$cnt = $group->countDisplayField(Xoonips_Enum::OP_TYPE_MANAGER_REGISTRY, Xoonips_Enum::USER_TYPE_MODERATOR);
			if ($cnt > 0) {
				$groupName = $group->getName();
				$fieldGroup[] = array('name' => $groupName,
					 'isMust' => $group->isMust(Xoonips_Enum::OP_TYPE_MANAGER_REGISTRY, Xoonips_Enum::USER_TYPE_MODERATOR),
					 'view' => $group->getRegistryViewWithData($this->data, $cnt, Xoonips_Enum::USER_TYPE_MODERATOR, Xoonips_Enum::OP_TYPE_MANAGER_REGISTRY));
			}
		}
		$this->xoopsTpl->assign('viewType', 'input');
		$this->xoopsTpl->assign('fieldGroup', $fieldGroup);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}
	
	/**
	 * 
	 * do registry
	 * 
	 * @param  int $uid:0
	 * @return array
	 */
	public function doRegistry($uid) {
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$ret = array();
		$userBasicInfo = array();
		$ret['insertError'] = true;
		$newId = '';
		$actkey = '';
		$row = 1;
		$sqlStrings = array();
		//set actkey 
		$actkey = substr(md5(uniqid(mt_rand(), 1)), 0, 8);
		//$userType:guest
		$userType = $userBean->getUserType($uid);
		foreach ($this->fieldGroups as $fieldGroup) {
			//$op:registry
			$cnt = $fieldGroup->countDisplayField(Xoonips_Enum::OP_TYPE_REGISTRY, $userType);
			if ($cnt > 0) {
				$fieldGroup->doRegistry($this->data, $sqlStrings, $userType);
				$row++;
			}
		}
		
		//if insert success, set insertError false.
		if ($this->saveUsersTable($sqlStrings, $newId, $actkey) && 
			$this->saveUserExtendTable($sqlStrings, $newId) && 
			$this->saveUserExtendTable2($newId) &&
			$this->saveUserActivateTable($newId, 0) &&
			$this->saveGroupsUsersLinkTable($newId)) {
			$ret['insertError'] = false;
			XCube_DelegateUtils::call('Module.User.Event.User.CertifyRequest', new XoopsUser($newId));
		}
		$ret['newId'] = $newId;
		$ret['actkey'] = $actkey;
		//get userInfo by id
		$userBasicInfo = $userBean->getUserBasicInfo($newId);
		$ret['uname'] = $userBasicInfo['uname'];
		$ret['email'] = $userBasicInfo['email'];
		$ret['name'] = $userBasicInfo['name'];
		return $ret;
	}
	
	/**
	 * 
	 * do registry for moderator
	 * 
	 * @param  
	 * @return boolean
	 */
	public function doRegistryForModerator(&$msg) {
		$row = 1;
		$newId = '';
		$msg = '';
		$sqlStrings = array();
		foreach ($this->fieldGroups as $fieldGroup) {
			//$op:registry
			//$userType:moderator
			$cnt = $fieldGroup->countDisplayField(Xoonips_Enum::OP_TYPE_MANAGER_REGISTRY, Xoonips_Enum::USER_TYPE_MODERATOR);
			if ($cnt > 0) {
				$fieldGroup->doRegistry($this->data, $sqlStrings, Xoonips_Enum::USER_TYPE_MODERATOR, Xoonips_Enum::OP_TYPE_MANAGER_REGISTRY);
				$row++;
			}
		}
		//start transaction
		$transaction = null;
		$transaction = Xoonips_Transaction::getInstance();
		$transaction->start();
		if (!$this->saveUsersTableForModerator($sqlStrings, $newId) || 
				!$this->saveUserExtendTable($sqlStrings, $newId) ||
				!$this->saveUserActivateTable($newId, 1) || 
				!$this->saveGroupsUsersLinkTableForModerator($sqlStrings, $newId)) {
			//rollback
			$transaction->rollback();
			return false;		
		}
		$myxoopsConfigUser = Xoonips_Utils::getXoopsConfigs(XOOPS_CONF_USER);
		$certify_user = $myxoopsConfigUser['certify_user'];
		$xleprogressCertifyUser = Xoonips_Enum::certifyUsers();
		$is_certify_auto = ($certify_user == 'auto') || $xleprogressCertifyUser == 0;
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$userBasicInfo = $userBean->getUserBasicInfo($newId);
		if (!$is_certify_auto) {
			$uname = $userBasicInfo['uname'];
			$name = $userBasicInfo['name'];
			$certifyName = ($name == '') ? $uname : $uname . "($name)";
			
			$result = array();
			XCube_DelegateUtils::call('Legacy_Workflow.AddItem', new XCube_Ref($result), $certifyName, $xleprogressCertifyUser, $newId);
			if ($result[0] == false) {
				$msg = $result[1];
				$transaction->rollback();
				$userBean->deleteUsers($newId);
				$userLinkBean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);	
				$userLinkBean->deleteByUid($newId);
				return true;
			}
			$sendToUsers = array();
			XCube_DelegateUtils::call('Legacy_Workflow.GetCurrentCertifyUsers', $xleprogressCertifyUser, $newId, new XCube_Ref($sendToUsers));
			$this->notification->accountCertifyRequest($newId, $sendToUsers);
			//log			
			XCube_DelegateUtils::call('Module.User.Event.User.CertifyRequest', new XoopsUser($newId));
		} else {
			// XOOPS : auto, XooNIps : auto
			if (!$userBean->certifiyUser($userBasicInfo)) {
				//rollback
				$transaction->rollback();
				return false;
			}
			$sendToUsers = array();
			XCube_DelegateUtils::call('Legacy_Workflow.GetAllCertifyUsers', $xleprogressCertifyUser, new XCube_Ref($sendToUsers));
			$this->notification->accountCertifiedAuto($newId, $sendToUsers);
			//certified event log			
			XCube_DelegateUtils::call('Module.User.Event.User.Certify', new XoopsUser($newId));			
		}
		//commit
		$transaction->commit();
		return true;
	}
	
	/**
	 * 
	 * insert into user table
	 * 
	 * @param  array $sqlString:data array
	 * 		   int	 $newId:uid 
	 * 		   int   $actkey:actkey	
	 * @return boolean
	 */
	private function saveUsersTable($sqlStrings, &$newId, $actkey) {
		$strings = $sqlStrings['users'];
		$columns = '';
		$values = '';
		foreach ($strings as $column => $v) {
			$columns .= $column . ',';
			$values .= $v[0] . ',';
		}
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		return $userBean->insert($columns, $values, $newId, $actkey, Xoonips_Enum::USER_TYPE_GUEST);
	}
	
	/**
	 * 
	 * insert into users table for moderator
	 * 
	 * @param  array $sqlString:data array
	 * 		   int	 $newId:uid 
	 * @return boolean
	 */
	private function saveUsersTableForModerator($sqlStrings, &$newId) {
		$strings = $sqlStrings['users'];
		$columns = '';
		$values = '';
		foreach ($strings as $column => $v) {
			$columns .= $column . ',';
			$values .= $v[0] . ',';
		}
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		return $userBean->insert($columns, $values, $newId, null, Xoonips_Enum::USER_TYPE_MODERATOR);
	}
	
	/**
	 * 
	 * insert into user_extend table
	 * 
	 * @param  array $sqlString:data array
	 * 		   int	 $newId:uid 
	 * @return boolean
	 */
	private function saveUserExtendTable($sqlStrings, $newId) {
		$ret = true;
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$column = '';
		foreach ($sqlStrings as $tableName => $strings) {
			//get user_extend information from 'sqlStrings'
			if (strPos($tableName, $this->dirname . '_extend') !== false) {
				foreach ($strings as $gid => $column_arr) {
					foreach ($column_arr as $column => $values) {
						$loop = 1;
						foreach ($values as $v) {
							if (trim($v) != '' && trim($v) != "''") {
								if (!$userBean->insertExtend($tableName, $newId, $v, $loop, $gid)) {						
									$ret = false;
								}
								$loop++;
							}
						}
					}
				}
			}
		}
		return $ret;
	}
	
	private function saveUserExtendTable2($newId) {		
		//global $xoopsDB;
		$resources = array();
		XCube_DelegateUtils::call('Module.User.GetUserMaximumResources', new XCube_Ref($resources), new XoopsUser($newId));
		if (count($resources) > 0) {
			foreach ($resources as $limit) {
				$private_item_number_limit = $limit['itemNumberLimit'];
				$private_index_number_limit = $limit['indexNumberLimit'];
				$private_item_storage_limit = $limit['itemStorageLimit'];
			}
		} else {
			$private_item_number_limit = 0;
			$private_index_number_limit = 0;
			$private_item_storage_limit = 0;
		}
		// private_item_number_limit
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
	    $userFieldManager = User_UserFieldManager::getInstance();
    	foreach ($userFieldManager->getFields() as $field) {
    		if ($field->getXmlTag() == 'item_number_limit') {
				// $private_item_number_limit
    			if (!$userBean->insertExtend($field->getTableName(), $newId, $private_item_number_limit, 1)) {
					return false;
				}
    		} elseif ($field->getXmlTag() == 'index_number_limit') {
    			// $private_item_number_limit
    			if (!$userBean->insertExtend($field->getTableName(), $newId, $private_index_number_limit, 1)) {
					return false;
				}
    		} elseif ($field->getXmlTag() == 'item_storage_limit') {
    			// $private_item_number_limit
    			if (!$userBean->insertExtend($field->getTableName(), $newId, $private_item_storage_limit, 1)) {
					return false;
				}
    		}
    	}
		return true;
	}

    private static function getActivateTableName() {
    	$userFieldManager = User_UserFieldManager::getInstance(true);
    	foreach ($userFieldManager->getFields() as $field) {
    		if ($field->getXmlTag() == 'activate') {
				return $field->getTableName();    		
    		}
    	}
    	return 'user_extend34';
    }

    private function saveUserActivateTable($newId, $activate) {
		//activate xoops account automatically
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$myxoopsConfigUser = Xoonips_Utils::getXoopsConfigs(XOOPS_CONF_USER);
		$tableName = self::getActivateTableName();
		if ($myxoopsConfigUser['activation_type'] == 1) {
			$certify_user = $myxoopsConfigUser['certify_user'];
			$is_certify_auto = ($certify_user == 'auto');
			if ($is_certify_auto) {				
				$activate =  Xoonips_Enum::USER_CERTIFIED;
			} else {
				$activate =  Xoonips_Enum::USER_NOT_CERTIFIED;
			}
		}
		if (!$userBean->insertExtend($tableName, $newId, $activate, 1)) {			
			return false;
		}		
		return true;
	}

	/**
	 * 
	 * insert into groups_users_link table
	 * 
	 * @param  int $newId:uid 
	 * @return boolean
	 */
	private function saveGroupsUsersLinkTable($newId) {
		$userLinkBean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		$groupUserLink = array(
			'activate' => Xoonips_Enum::GRP_US_CERTIFIED,
			'groupid' => Xoonips_Enum::GRP_ID_USER,
			'uid' => $newId,
			'is_admin' => Xoonips_Enum::GRP_USER);
		if (!$userLinkBean->insert($groupUserLink)) {
			return false;
		}
		return true;
	}
	
	/**
	 * 
	 * insert into groups_users_link table for moderator
	 * 
	 * @param  array $sqlString:data array
	 * 		   int	 $newId:uid 
	 * @return boolean
	 */
	private function saveGroupsUsersLinkTableForModerator($sqlStrings, $newId) {
		$userLinkBean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);	
		$strings = $sqlStrings['groups_users_link'];
		$valueArr = explode(',', $strings);
		//remove null elements
		$newGroups = array_filter($valueArr);
		$message = '';
		if (!$this->doGroupsUsersLink($newGroups, array(), $newId, $message)) {
			return false;
		}
		return true;
	}
	
	/**
	 * 
	 * get edit view 
	 * 
	 * @param  int $uid:user id
	 * @return array
	 */
	public function getEditView($uid) {
		//get data from db
		$data = $this->getUserDetailInfo($uid);
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$userType = $userBean->getUserType($uid);
		$fieldGroup = array();
		foreach ($this->fieldGroups as $group) {
			$cnt = $group->countDisplayField(Xoonips_Enum::OP_TYPE_EDIT, $userType);
			if ($cnt > 0) {
				$groupName = $group->getName();
				$fieldGroup[] = array('name' => $groupName,
					 'isMust' => $group->isMust(Xoonips_Enum::OP_TYPE_EDIT, $userType),
					 'view' => $group->getEditView($data, $cnt, $userType));
			}
		}
		$this->xoopsTpl->assign('viewType', 'input');
		$this->xoopsTpl->assign('fieldGroup', $fieldGroup);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}
	
	/**
	 * 
	 * get edit view with data
	 * 
	 * @param  int $uid:user id
	 * @return array
	 */
	public function getEditViewWithData($uid) {
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$userType = $userBean->getUserType($uid);
		$fieldGroup = array();
		foreach ($this->fieldGroups as $group) {
			$cnt = $group->countDisplayField(Xoonips_Enum::OP_TYPE_EDIT, $userType);
			if ($cnt > 0) {
				$groupName = $group->getName();
				$fieldGroup[] = array('name' => $groupName,
					 'isMust' => $group->isMust(Xoonips_Enum::OP_TYPE_EDIT, $userType),
					 'view' => $group->getEditViewWithData($this->data, $cnt, $userType));
			}
		}
		$this->xoopsTpl->assign('viewType', 'input');
		$this->xoopsTpl->assign('fieldGroup', $fieldGroup);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}
	
	/**
	 * 
	 * get edit view for moderator
	 * 
	 * @param  int $uid:user id
	 * @return array
	 */
	public function getEditViewForModerator($uid) {
		$data = $this->getUserDetailInfo($uid);
		$fieldGroup = array();
		foreach ($this->fieldGroups as $group) {
			$cnt = $group->countDisplayField(Xoonips_Enum::OP_TYPE_MANAGER_EDIT, Xoonips_Enum::USER_TYPE_MODERATOR);
			if ($cnt > 0) {
				$groupName = $group->getName();
				$fieldGroup[] = array('name' => $groupName,
					 'isMust' => $group->isMust(Xoonips_Enum::OP_TYPE_MANAGER_EDIT, Xoonips_Enum::USER_TYPE_MODERATOR),
					 'view' => $group->getEditViewForModerator($data, $cnt));
			}
		}
		$this->xoopsTpl->assign('viewType', 'input');
		$this->xoopsTpl->assign('fieldGroup', $fieldGroup);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}
	
	/**
	 * 
	 * get edit view with data for moderator
	 * 
	 * @param  
	 * @return array
	 */
	public function getEditViewWithDataForModerator() {
		$fieldGroup = array();
		foreach ($this->fieldGroups as $group) {
			$cnt = $group->countDisplayField(Xoonips_Enum::OP_TYPE_MANAGER_EDIT, Xoonips_Enum::USER_TYPE_MODERATOR);
			if ($cnt > 0) {
				$groupName = $group->getName();
				$fieldGroup[] = array('name' => $groupName,
					 'isMust' => $group->isMust(Xoonips_Enum::OP_TYPE_MANAGER_EDIT, Xoonips_Enum::USER_TYPE_MODERATOR),
					 'view' => $group->getEditViewWithDataForModerator($this->data, $cnt));
			}
		}
		$this->xoopsTpl->assign('viewType', 'input');
		$this->xoopsTpl->assign('fieldGroup', $fieldGroup);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}
	
	/**
	 * 
	 * do edit
	 * 
	 * @param  int $uid:user id
	 * @return boolean
	 */
	public function doEdit($uid) {
		$ret = false;
		$sqlStrings = array();		
		foreach ($this->fieldGroups as $fieldGroup) {
			//$op:edit 
			//$userType:user
			$cnt = $fieldGroup->countDisplayField(Xoonips_Enum::OP_TYPE_EDIT, Xoonips_Enum::USER_TYPE_USER);
			if ($cnt > 0) {
				$fieldGroup->doEdit($this->data, $sqlStrings);
			}
		}
		if ($this->editUsersTable($sqlStrings, $uid) && $this->editUserExtendTable($sqlStrings, $uid)) {
			$ret = true;
		}
		return $ret;		
	}
	
	/**
	 * 
	 * do edit for moderator
	 * 
	 * @param  int $uid:user id
	 * @return boolean
	 */
	public function doEditForModerator(&$errors, $uid) {
		$sqlStrings = array();		
		foreach ($this->fieldGroups as $fieldGroup) {
			//$op:edit
			//$userType:moderator
			$cnt = $fieldGroup->countDisplayField(Xoonips_Enum::OP_TYPE_MANAGER_EDIT, Xoonips_Enum::USER_TYPE_MODERATOR);
			if ($cnt > 0) {
				$fieldGroup->doEditForModerator($this->data, $sqlStrings);
			}
		}
		//start transaction
		$transaction = null;
		$transaction = Xoonips_Transaction::getInstance();
		$transaction->start();
		if (!$this->editUsersTable($sqlStrings, $uid) || 
			!$this->editUserExtendTable($sqlStrings, $uid) || 
			!$this->editGroupsUsersLink($sqlStrings, $uid, $errors)) {
				$transaction->rollback();
				return false;
		} else {
			$transaction->commit();
		}
		return true;
	}
	
	/**
	 * 
	 * update users table
	 * 
	 * @param  array $sqlStrings:data array
	 * 		   int $uid:user id
	 * @return boolean
	 */
	private function editUsersTable($sqlStrings, $uid) {
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		return $userBean->update($uid, $sqlStrings['users']);
	}
	
	/**
	 * 
	 * update user_extend[999] table
	 * 
	 * @param  array $sqlStrings:data array
	 * 		   int $uid:user id
	 * @return boolean
	 */
	private function editUserExtendTable($sqlStrings, $uid) {
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$gid = 0;
		$column = '';
		$del_table = array();
		foreach ($sqlStrings as $tableName => $strings) {
			//get user_extend[999] table name
			if (strPos($tableName, $this->dirname . '_extend') !== false) {
				//delete data
				if (!in_array($tableName, $del_table)) {
					$del_table[] = $tableName;
					if (!$userBean->deleteUserExtend($tableName, $uid)) {
						return false;
					}
				}
				foreach ($strings as $gid => $column_arr) {
					foreach ($column_arr as $column => $values) {
						$loop = 1;
						foreach ($values as $v) {
							if (trim($v) != '' && trim($v) != "''") {
								if (!$userBean->insertExtend($tableName, $uid, $v, $loop, $gid)) {
									$ret = false;
								}
								$loop++;
							}
						}
					}
				}
			}
		}
		return true;
	}
	
	/**
	 * 
	 * update groups_users_link table
	 * 
	 * @param  array $sqlStrings:data array
	 * 		   int $uid:user id
	 * @return boolean
	 */
	private function editGroupsUsersLink($sqlStrings, $uid, &$errors) {
		$userLinkBean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		$strings = $sqlStrings['groups_users_link'];
		$valueArr = explode(',', $strings);
		//remove null elements
		$newGroups = array_filter($valueArr);
		$oldGroups = $userLinkBean->getGroupUserLinkInfoByUserId($uid);

		if (!$this->doGroupsUsersLink($newGroups, $oldGroups, $uid, $errors)) {
			return false;
		}
		return true;
	}
	
	private function doGroupsUsersLink($newGroups, $oldGroups, $uid, &$errors) {
		$groupUserLinkBean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		$group_handler =& xoops_gethandler('group');
		$memberHandler =& xoops_gethandler('member');
		$oldGroupIds = array();
		foreach ($oldGroups as $key => $oldGroup) {
			$oldGroupIds[] = $key;
		}
		foreach ($newGroups as $newGroup) {
			if (!in_array($newGroup, $oldGroupIds)) {
				$xoopsGroup = $group_handler->get($newGroup);
				if ($xoopsGroup->get('group_type') == Xoonips_Enum::GROUP_TYPE) {
					$message = '';
					if (!$this->doGroupMemberJoined($newGroup, $uid, $xoopsGroup, $message)) {
						$errors->addError($message, null, null, false);
						return false;
					}
				} else {
					$memberHandler->addUserToGroup($newGroup, $uid);
				}
			}
		}
		foreach ($oldGroupIds as $oldGroup) {
			if (!in_array($oldGroup, $newGroups)) {
				$groupUserLink = $groupUserLinkBean->getGroupUserLinkInfo($oldGroup, $uid);
				$xoopsGroup = $group_handler->get($oldGroup);
				if ($groupUserLink['activate'] == Xoonips_Enum::GRP_US_JOIN_REQUIRED
					|| $groupUserLink['activate'] == Xoonips_Enum::GRP_US_LEAVE_REQUIRED) {
					$errors->addError('_MD_USER_ERROR_GROUP_LEAVE_FAILED', 'group', array($xoopsGroup->get('name')));	
					continue;		
				}
				if ($xoopsGroup->get('group_type') == Xoonips_Enum::GROUP_TYPE) {
					$message = '';
					if (!$this->doGroupMemberLeaved($oldGroup, $uid, $xoopsGroup, $message)) {
						$errors->addError($message, null, null, false);
						return false;
					}
				} else {
					$memberHandler->removeUserFromGroup($oldGroup, $uid);
				}
			}
		}
		return true;
	}
	
	/**
	 * 
	 * get search view
	 * 
	 * @param  
	 * @return array
	 */
	public function getSearchView() {
		$fieldGroup = array();
		foreach ($this->fieldGroups as $group) {
			$cnt = $group->countDisplayField(Xoonips_Enum::OP_TYPE_SEARCH, Xoonips_Enum::USER_TYPE_USER);
			if ($cnt > 0) {
				$groupName = $group->getName();
				$fieldGroup[] = array('name' => $groupName,
					 'view' => $group->getSearchView($cnt));
			}
		}
		$this->xoopsTpl->assign('viewType', 'detail');
		$this->xoopsTpl->assign('fieldGroup', $fieldGroup);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}
	
	/**
	 * 
	 * get search view with data
	 * 
	 * @param  
	 * @return array
	 */
	public function getSearchViewWithData() {
		$fieldGroup = array();
		foreach ($this->fieldGroups as $group) {
			$cnt = $group->countDisplayField(Xoonips_Enum::OP_TYPE_SEARCH, Xoonips_Enum::USER_TYPE_USER);
			if ($cnt > 0) {
				$groupName = $group->getName();
				$fieldGroup[] = array('name' => $groupName,
					 'view' => $group->getSearchViewWithData($this->data, $cnt));
			}
		}
		$this->xoopsTpl->assign('viewType', 'detail');
		$this->xoopsTpl->assign('fieldGroup', $fieldGroup);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}
	
	/**
	 * 
	 * get search view for moderator
	 * 
	 * @param  
	 * @return array
	 */
	public function getSearchViewForModerator() {
		$fieldGroup = array();
		foreach ($this->fieldGroups as $group) {
			$cnt = $group->countDisplayField(Xoonips_Enum::OP_TYPE_SEARCH, Xoonips_Enum::USER_TYPE_MODERATOR);
			if ($cnt > 0) {
				$groupName = $group->getName();
				$fieldGroup[] = array('name' => $groupName,
					 'view' => $group->getSearchView($cnt, Xoonips_Enum::USER_TYPE_MODERATOR));
			}
		}
		$this->xoopsTpl->assign('viewType', 'detail');
		$this->xoopsTpl->assign('fieldGroup', $fieldGroup);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}
	
	/**
	 * 
	 * get search view with data for moderator
	 * 
	 * @param  
	 * @return array
	 */
	public function getSearchViewWithDataForModerator() {
		$fieldGroup = array();
		foreach ($this->fieldGroups as $group) {
			$cnt = $group->countDisplayField(Xoonips_Enum::OP_TYPE_SEARCH, Xoonips_Enum::USER_TYPE_MODERATOR);
			if ($cnt > 0) {
				$groupName = $group->getName();
				$fieldGroup[] = array('name' => $groupName,
					 'view' => $group->getSearchViewWithData($this->data, $cnt, 1, Xoonips_Enum::USER_TYPE_MODERATOR));
			}
		}
		$this->xoopsTpl->assign('viewType', 'detail');
		$this->xoopsTpl->assign('fieldGroup', $fieldGroup);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}
	
	/**
	 * 
	 * do search
	 * 
	 * @param  
	 * @return array
	 */
	public function doSearch() {
		$row = 1;
		$sqlStrings = array();
		$ret = array();
		$rowList = array();
		//
		foreach ($this->fieldGroups as $fieldGroup) {
			//$op:search
			//$userType:user
			$cnt = $fieldGroup->countDisplayField(Xoonips_Enum::OP_TYPE_SEARCH, Xoonips_Enum::USER_TYPE_USER);
			if ($cnt > 0) {
				$fieldGroup->doSearch($this->data, $sqlStrings);
				$row++;
			}
		}
		
		//get sql
		$sql = $this->searchUsersTable($sqlStrings);
		global $xoopsDB;
		$result = $xoopsDB->query($sql);
		if (!$result) {
			return false;
		}
		//get searched uid
		while ($row = $xoopsDB->fetchArray($result)) {
			$rowList[] = $row['uid'];
		}
		$ret = $this->getSearchInfo($rowList);	
		return $ret;
	}
	
	/**
	 * 
	 * get searched user information's list
	 * 
	 * @param $uidList:user id
	 * @return array
	 */
	private function getSearchInfo($uidList) {
		$ret = array();

		//get table name array
		$tableList = $this->getItemTableName();
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$xoopsUserId = 0;
		if (isset($_SESSION['xoopsUserId'])) {
			$xoopsUserId = $_SESSION['xoopsUserId'];
		}
		foreach ($uidList as $uid) {
			$rowList = array();
			foreach ($tableList as $tblIndex) {
				$extendRow = array();
				if ($tblIndex == 'users') {
					$row = $userBean->getUserBasicInfo($uid, false);
					if (!$row) {
						return false;
					}
					if ($row['user_viewemail'] != 1 && $uid != $xoopsUserId && !$userBean->isModerator($xoopsUserId)) {
						$row['email'] = '';
					}
					$headList = $this->getDetailHead();
					foreach ($row as $key => $v) {
						foreach ($headList as $fieldTag) {
							$flag = false;
							if ($key == $fieldTag['column_name']) {
								$field = new User_UserField();
								$user = self::getInstance();
								$user->setId($uid);
								$viewType = Xoonips_ViewTypeFactory::getInstance($this->dirname, $this->trustDirname)->getViewType($fieldTag['view_type_id']);
								$dataType = Xoonips_DataTypeFactory::getInstance($this->dirname, $this->trustDirname)->getDataType($fieldTag['data_type_id']);
								$id = $fieldTag['user_detail_id'];
								$name = $fieldTag['name'];			
								$groupId = $fieldTag['group_id'];
								$field->setId($id);
								$field->setName($name);
								$field->setFieldGroupId($groupId);
								$field->setViewType($viewType);
								$field->setDataType($dataType);
								$field->setListId($fieldTag['list']);
								$v = $viewType->getDetailView($field, $v, 1, true);
								$rowList[$key] = $v;
								$flag = true;
								break;
							}
						}
						if (!$flag) {
							$rowList[$key] = Xoonips_Utils::htmlSpecialChars($v);
						}
					}
				}
				//if user_extend[999] table
				if (strPos($tblIndex, $this->dirname . '_extend') !== false) {
					$result = $userBean->getUserExtend($tblIndex, $uid);
					if (!$result) {
						$extendRow[] = null;
						$rowList[$tblIndex] = $extendRow; 
					} else {
						foreach ($result as $row) {
							//convert special chars
							$extendRow[] = Xoonips_Utils::htmlSpecialChars($row['value']);
							$rowList[$tblIndex] = $extendRow;
						}
					}
				}
			}
			$ret[] = $rowList;
		}
		return $ret;
	}
	
	/**
	 * 
	 * do search for moderator
	 * 
	 * @param  
	 * @return array
	 */
	public function doSearchForModerator() {
		$sqlStrings = array();
		$rowList = array();
		$ret = array();
		foreach ($this->fieldGroups as $fieldGroup) {
			//$op:search
			//$userType:moderator
			$cnt = $fieldGroup->countDisplayField(Xoonips_Enum::OP_TYPE_SEARCH, Xoonips_Enum::USER_TYPE_MODERATOR);
			if ($cnt > 0) {
				$fieldGroup->doSearch($this->data, $sqlStrings, Xoonips_Enum::USER_TYPE_MODERATOR);
			}
		}
		//$userType:moderator
		$userType = Xoonips_Enum::USER_TYPE_MODERATOR;
		$sql = $this->searchUsersTable($sqlStrings, $userType);
		global $xoopsDB;
		$result = $xoopsDB->query($sql);
		if (!$result) {
			return false;
		}
		$tableName = self::getActivateTableName();
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		while ($row = $xoopsDB->fetchArray($result)) {
			//set activate
			$values = $userBean->getUserExtend($tableName, $row['uid']);
			if (isset($values[0]['value'])) {	
				$row['activate'] = 	$values[0]['value'];
			}
			$ret[] = $row;
		}
		return $ret;
	}
	
	/**
	 * 
	 * select data from users table
	 * 
	 * @param  array $sqlString:data array
	 * 		   $userType:user type
	 * @return string
	 */
	private function searchUsersTable(&$sqlStrings, $userType = Xoonips_Enum::USER_TYPE_USER) {
		global $xoopsDB;
		$values = '';
		$extendSql = '';
		$groupSql = '';
		$groupData = '';
		if (count($sqlStrings) != 0) {
			//if users table
			$strings = $sqlStrings['users'];
			foreach ($strings as $v) {
				$values = $values . mb_ereg_replace('\\x22t1\\x22', 'users', $v)  . ' and ';
			}
			if ($values != '') {
				//remove last "and"
				$values = ' where ' . substr($values, 0, strlen($values) - 4);
			}
			
			foreach ($sqlStrings as $tableName => $strings) {
				//if user_extend[999] table
				if (strPos($tableName, $this->dirname . '_extend') !== false) {
					$num = 1;
					foreach ($strings as $extendValues) {
						$tableName2 = $xoopsDB->prefix($tableName);
						$tableOtherName = $tableName . $num;
						$extendSql = $extendSql . "inner join $tableName2 $tableOtherName on users.uid=$tableOtherName.uid and " . mb_ereg_replace('\\x22t1\\x22', $tableOtherName, $extendValues);
						$num++;
					}
				}
				//if groups_users_link table
				if ($tableName == 'groups_users_link') {
					foreach ($strings as $groupValues) {
						$groupData = $groupData . $groupValues;
					}
					if (count($strings) != 0) {
						$tableName = $xoopsDB->prefix('groups_users_link');
						$groupData = substr($groupData, 0, strlen($groupData) - 1);
						$groupSql = "inner join $tableName on users.uid=$tableName.uid and $tableName.groupid in ($groupData) ";
					}
				}
			}
		}
		$tableName = $xoopsDB->prefix('users');
		$userType == Xoonips_Enum::USER_TYPE_USER ? $selectContent = 'users.uid' : $selectContent = "users.*";
		$sql = "select distinct $selectContent from $tableName users $extendSql" . "$groupSql" . "$values order by users.uid";
		return $sql;
	}
	
	/**
	 * 
	 * get confirm view
	 * 
	 * @param  int $uid:user id
	 *         int $op
	 * @return array
	 */
	public function getConfirmView($uid, $op = Xoonips_Enum::OP_TYPE_REGISTRY) {

		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$userType = $userBean->getUserType($uid);
		$fieldGroup = array();
		foreach ($this->fieldGroups as $group) {
			$cnt = $group->countDisplayField($op, $userType);
			if ($cnt > 0) {
				$groupName = $group->getName();
				$fieldGroup[] = array('name' => $groupName,
					 'view' => $group->getConfirmView($this->data, $cnt, $op, $userType));
			}
		}
		$this->xoopsTpl->assign('viewType', 'detail');
		$this->xoopsTpl->assign('fieldGroup', $fieldGroup);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}
	
	/**
	 * 
	 * get detail view
	 * 
	 * @param  int $uid:user id
	 * @return array
	 */
	public function getDetailView($uid, $xoopsUserId) {
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$userType = $userBean->getUserType($xoopsUserId);
		$data = $this->getUserDetailInfo($uid);
		$fieldGroup = array();
		foreach ($this->fieldGroups as $group) {
			$cnt = $group->countDisplayField(Xoonips_Enum::OP_TYPE_DETAIL, $userType);
			if ($cnt > 0) {
				$groupName = $group->getName();
				$fieldGroup[] = array('name' => $groupName,
					 'view' => $group->getDetailView($data, $cnt, $userType));
			}
		}
		$this->xoopsTpl->assign('viewType', 'detail');
		$this->xoopsTpl->assign('fieldGroup', $fieldGroup);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}
	
	public function getDetailViewForCertify($uid, $xoopsUserId) {
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$userType = $userBean->getUserType($xoopsUserId);
		$data = $this->getUserDetailInfo($uid);
		$fieldGroup = array();
		foreach ($this->fieldGroups as $group) {
			$cnt = $group->countDisplayField(Xoonips_Enum::OP_TYPE_DETAIL, $userType);
			if ($cnt > 0) {
				$groupName = $group->getName();
				$fieldGroup[] = array('name' => $groupName,
					 'view' => $group->getDetailViewForCertify($data, $cnt));
			}
		}
		$this->xoopsTpl->assign('viewType', 'detail');
		$this->xoopsTpl->assign('fieldGroup', $fieldGroup);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}
	
	/**
	 * 
	 * get detail view for moderator
	 * 
	 * @param  int $uid:user id
	 * @return array
	 */
	public function getDetailViewForModerator($uid) {
		$data = $this->getUserDetailInfo($uid);
		$fieldGroup = array();
		foreach ($this->fieldGroups as $group) {
			$cnt = $group->countDisplayField(Xoonips_Enum::OP_TYPE_DETAIL, Xoonips_Enum::USER_TYPE_MODERATOR);
			if ($cnt > 0) {
				$groupName = $group->getName();
				$fieldGroup[] = array('name' => $groupName,
					 'view' => $group->getDetailViewForModerator($data, $cnt, Xoonips_Enum::USER_TYPE_MODERATOR));
			}
		}
		$this->xoopsTpl->assign('viewType', 'detail');
		$this->xoopsTpl->assign('fieldGroup', $fieldGroup);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}
	
	/**
	 * 
	 * get list head
	 * 
	 * @param
	 * @return array
	 */
	public function getDetailHead() {
		$ret = array();
		global $xoopsDB;
		$tbl = $xoopsDB->prefix($this->dirname . '_field_detail');
		$sql = "select * from $tbl where list_display=1 and released=1 and nondisplay=0 order by group_id,weight";
		$result = $xoopsDB->queryF($sql);
		if (!$result) {
			return false;
		}
		while ($row = $xoopsDB->fetchArray($result)) {
			$viewType = Xoonips_ViewTypeFactory::getInstance($this->dirname, $this->trustDirname)->getViewType($row['view_type_id']);
			if ($viewType->isDisplay(Xoonips_Enum::OP_TYPE_SEARCHLIST)) {
				$ret[] = $row;
			}
		}
		return $ret;
	}
	 
	/**
	 * 
	 * get search result for moderator
	 * 
	 * @param array $uidList:user id array
	 * @return array
	 */
	public function getSearchInfoForModerator($uidList) {
		$ret = array();

		//get table name array
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$tableList = $this->getItemTableName();
		
		foreach ($uidList as $uid) {
			$rowList = array();
			foreach ($tableList as $tblIndex) {
				//if users table
				if ($tblIndex == 'users') {
					$row = $userBean->getUserBasicInfo($uid, false);
					if (!$row) {
						return false;
					}
					if ($row) {
						foreach ($row as $key => $v) {
							// convert special chars
							$rowList[$key] = Xoonips_Utils::htmlSpecialChars($v);
						}
					}
				}
			}
			$ret[] = $rowList;
		}
		return $ret;
	}
	
	/**
	 * 
	 * get user detail information
	 * 
	 * @param int $uid:user id
	 * @return array
	 */
	private function getUserDetailInfo($uid) {
		$ret = array();

		//get table name array
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$tableList = $this->getItemTableName();
		foreach ($tableList as $tblIndex) {
			//if users table
			if ($tblIndex == 'users') {
				$row = $userBean->getUserBasicInfo($uid, false);
				if (!$row) {
					return false;
				}
				foreach ($row as $key => $v) {
					$retKey = '';
					foreach ($this->fields as $field) {
						//set data
						if ($key == $field->getColumnName()) {
							$retKey = $this->getFieldName($field, 1);
							break;
						}
					}
					//if NULL  
					if ($v === NULL) {
						$v = '';
					}
					$ret[$retKey] = $v;
				}
			}
			//if user_extend[999] table
			if (strPos($tblIndex, $this->dirname . '_extend') !== false) {
				//get detail id
				$len = strlen($this->dirname) + 7;
				$detailId = substr($tblIndex, $len, strlen($tblIndex) - $len);

				$result = $userBean->getUserExtend($tblIndex, $uid);
				if ($result) {
					foreach ($result as $row) {
						$retKey = '';
						foreach ($this->fields as $field) {
							//set data
							if ($detailId == $field->getId()) {
								$retKey = $this->getFieldName($field, $row['occurrence_number'], $detailId, $row['group_id']);
								break;
							}
						}
						$ret[$retKey] = $row['value'];
					}
				}
			}
			//if groups_users_link table
			if ($tblIndex == 'groups_users_link') {
				$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
				$viewTypeBean = Xoonips_BeanFactory::getBean('ViewTypeBean', $this->dirname, $this->trustDirname);

				//get groups info by uid
				$groupsInfo = $userBean->getGroupsUsersLinkByUid($uid);
				$groupsIds = '';
				foreach ($groupsInfo as $groupsValue) {
					$groupsIds .= $groupsValue['groupid'] . ',';
				}
				//remove last ','
				$groupsIds = substr($groupsIds, 0, strlen($groupsIds) - 1);
				foreach ($this->fields as $field) {
					//if view type is groupName, set data
					if ($field->getViewType()->getId() == $viewTypeBean->selectByName('group name')) {
						$retKey = $this->getFieldName($field, 1);
						break;
					}
				}
				$ret[$retKey] = $groupsIds;
			}
		}
		return $ret;
	}
	
	/**
	 * 
	 * get table name
	 * 
	 * @param 
	 * @return array
	 */
	private function getItemTableName() {
		$tableList = array();
		foreach ($this->fields as $field) {
			$tableName = $field->getTableName();
			$tableList[] = $tableName;
		}
		$tableList = array_unique($tableList);
		return $tableList;
	}

	public function deleteUserCheck($uid, &$message) {
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		if ($userBean->isGroupMember(1, $uid)) {
			$message = _MD_USER_ERROR_ADMIN_FAILED;
			return false;
		}	
		if ($userBean->isGroupAdmin($uid)) {
			$message = _MD_USER_ERROR_GROUP_ADMIN_FAILED;
			return false;
		}

		$result = array();
		XCube_DelegateUtils::call('Module.User.Event.User.DeleteCondition', new XCube_Ref($result), new XoopsUser($uid));
		foreach ($result as $condition) {
			if ($condition[0]) {
				$message = _MD_USER_ERROR_ITEM_FAILED;
				return false;
			}
		}
		return true;
	}

	/**
	 * 
	 * delete user
	 * 
	 * @param  int $uid:user id
	 * @return boolean
	 */
	public function deleteUser($uid) {
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$groupUserLinkBean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		
		$userInfo = $userBean->getUserBasicInfo($uid);
		$xoopsConfig = Xoonips_Utils::getXoopsConfigs(XOOPS_CONF);
		/*$result = array();
		XCube_DelegateUtils::call('Module.User.GetMessageSign', new XCube_Ref($result));
		foreach ($result as $messageSign) {
			$myxoopsConfig = $messageSign;
		}*/
		Xoonips_Utils::loadMessage($this->dirname);
		
		$transaction = null;
		$transaction = Xoonips_Transaction::getInstance();
		$transaction->start();		
		$groupIds = array();
		$groupIds = $userBean->getGroupsUsers($uid, Xoonips_Enum::GRP_US_CERTIFIED);
		$group_handler =& xoops_gethandler('group');
		$xoopsUser = new XoopsUser($uid);		
		if ($groupIds != false && count($groupIds) != 0) {
			if (!$userBean->deleteGroupsUsers($uid, Xoonips_Enum::GRP_US_CERTIFIED)) {
				$transaction->rollback();	
				return false;
			} else {
				foreach ($groupIds as $groupId) {
					$xoopsGroup = $group_handler->get($groupId);
					if ($xoopsGroup->getVar('group_type') == Xoonips_Enum::GROUP_TYPE) {
						//log
						XCube_DelegateUtils::call('Module.User.Event.Group.Member.Leave', $xoopsUser, $xoopsGroup);
						//mail
						//$sendToUsers = array();
						//XCube_DelegateUtils::call('Legacy_Workflow.GetAllCertifyUsers', Xoonips_Enum::certifyGroupLeave(), new XCube_Ref($sendToUsers), $groupId);
						//$this->notification->groupLeaveAuto($groupId, $uid, $sendToUsers);
					}
				}
			}
		}
		
		$groupIds = array();
		$groupIds = $userBean->getGroupsUsers($uid, Xoonips_Enum::GRP_US_JOIN_REQUIRED);
		if ($groupIds != false && count($groupIds) != 0) {
			foreach ($groupIds as $groupId) {
				//xleprogress
				$linkId = $groupUserLinkBean->getGroupUserLinkInfo($groupId, $uid);
				$ret = '';
				XCube_DelegateUtils::call('Legacy_Workflow.AutoReject', new XCube_Ref($ret), Xoonips_Enum::certifyGroupJoin(), $linkId['linkid']);				
				//log:46
				$xoopsGroup = $group_handler->get($groupId);
				XCube_DelegateUtils::call('Module.User.Event.Group.Member.JoinReject', $xoopsUser, $xoopsGroup);
				//event
				$sendToUsers = array();
				foreach ($groupUserLinkBean->getAdminUserIds($groupId) as $id) {
					$sendToUsers[$id] = $id; 
				}
			    XCube_DelegateUtils::call('Legacy_Workflow.GetAllCertifyUsers', Xoonips_Enum::certifyGroupJoin(), new XCube_Ref($sendToUsers), $groupId);
				$this->notification->groupJoinRejected($groupId, $uid, $sendToUsers, '');
			}
			if (!$userBean->deleteGroupsUsers($uid, Xoonips_Enum::GRP_US_JOIN_REQUIRED)) {
				$transaction->rollback();
				return false;
			}
		}
		
		$groupIds = array();
		$groupIds = $userBean->getGroupsUsers($uid, Xoonips_Enum::GRP_US_LEAVE_REQUIRED);
		if ($groupIds != false && count($groupIds) != 0) {
			foreach ($groupIds as $groupId) {
				//xleprogress
				$linkId = $groupUserLinkBean->getGroupUserLinkInfo($groupId, $uid);
				$ret = '';
				XCube_DelegateUtils::call('Legacy_Workflow.AutoCertify', new XCube_Ref($ret), Xoonips_Enum::certifyGroupLeave(), $linkId['linkid']);
				//log
				$xoopsGroup = $group_handler->get($groupId);
				XCube_DelegateUtils::call('Module.User.Event.Group.Member.LeaveCertify', $xoopsUser, $xoopsGroup);	
				//mail
				$sendToUsers = array();
				foreach ($groupUserLinkBean->getAdminUserIds($groupId) as $id) {
					$sendToUsers[$id] = $id; 
				}
				XCube_DelegateUtils::call('Legacy_Workflow.GetAllCertifyUsers', Xoonips_Enum::certifyGroupLeave(), new XCube_Ref($sendToUsers), $groupId);
				$this->notification->groupLeave($groupId, $uid, $sendToUsers, '');
			}
			if (!$userBean->deleteGroupsUsers($uid, Xoonips_Enum::GRP_US_LEAVE_REQUIRED)) {
				$transaction->rollback();
				return false;
			}
		}		
		
		//delete users
		$deleteUserInfo = new XoopsUser($uid);
		if (!$userBean->deleteUsers($uid)) {
			$transaction->rollback(); 	
			return false;
		} else {			
			//send to user
			$xoopsMailer =& getMailer();
		 	$xoopsMailer->useMail();
		 	$xoopsMailer->setTemplateDir(Xoonips_Utils::mailTemplateDir($this->dirname, $this->trustDirname));
		 	$xoopsMailer->setTemplate('user_account_deleted_notify.tpl');
		 	$xoopsMailer->assign('SITENAME', $xoopsConfig['sitename']);
		 	$xoopsMailer->assign('ADMINMAIL', $xoopsConfig['adminmail']);
		 	$xoopsMailer->assign('SITEURL', XOOPS_URL . '/');
		 	$xoopsMailer->assign('USER_UNAME', $userInfo['uname']);
	   	 	$xoopsMailer->assign('USER_DIVISION', $userInfo['division']);
		    $xoopsMailer->assign('USER_NAME', $userInfo['name']);
		    $xoopsMailer->assign('USER_EMAIL', $userInfo['email']);
		    $xoopsMailer->assign('USER_COMPANY_NAME', $userInfo['company']);
		    $xoopsMailer->assign('USER_ADDRESS', $userInfo['user_from']);
		    $xoopsMailer->assign('USER_COUNTRY', $userInfo['country']);
		 	$xoopsMailer->setToUsers($deleteUserInfo);
		 	$xoopsMailer->setFromEmail($xoopsConfig['adminmail']);
		 	$xoopsMailer->setFromName($xoopsConfig['sitename']);
			$xoopsMailer->setSubject(_MD_USER_MESSAGE_ACCOUNT_DELETED_NOTIFYSBJ);
			$xoopsMailer->send();
			
			//send to moderators
			$sendToUsers = array();		
			XCube_DelegateUtils::call('Legacy_Workflow.GetAllCertifyUsers', Xoonips_Enum::certifyUsers(), new XCube_Ref($sendToUsers));
			$this->notification->accountDeleted($userInfo, $sendToUsers);
		}
		
		$extendUserTable = array();
		$extendUserTable = $userBean->getUserExtendTable();
		//delelte user_extend
		if ($extendUserTable != false && count($extendUserTable) != 0) {
			foreach ($extendUserTable as $tableName) {
				if (!$userBean->deleteUserExtend($tableName, $uid)) {
					$transaction->rollback(); 	
					return false;
				}
			}
		}
		XCube_DelegateUtils::call('Module.User.Event.User.Delete', $xoopsUser);
		$transaction->commit();
		return true;
	}
	
	/**
	 * 
	 * complete relation
	 * 
	 * @param  int $id:html's item name
	 * @return 
	 */
	public function completeRelation($id) {
		$ids = explode(Xoonips_Enum::ITEM_ID_SEPARATOR, $id);
		$fieldId = $ids[2];
		$field = UserFieldManager::getInstance()->getField($fieldId);
		$viewTypeId = $field->getViewType()->getId();
		$relation = ComplementFactory::getInstance($this->dirname, $this->trustDirname)->getComplement($viewTypeId);
		$relation->complete($field, $id, $this->data);
	}
	
	/**
	 * 
	 * add itemGroup
	 * 
	 * @param  int $id:html's item name
	 * @return 
	 */
	public function addItemGroup($id) {
		$ids = explode(Xoonips_Enum::ITEM_ID_SEPARATOR, $id);
		$groupId = $ids[0];
		$groupLoopId = $ids[1];
		$fieldGroup = UserFieldManager::getInstance()->getFieldGroup($groupId);
		foreach ($fieldGroup->getFields() as $field) {
			$key = $id . Xoonips_Enum::ITEM_ID_SEPARATOR . $field->getId(); 
			$this->data[$key] = '';
		}
	}
	
	/**
	 * 
	 * delete itemGroup
	 * 
	 * @param  int $id:html's item name
	 * @return 
	 */
	public function delItemGroup($id) {
		$ids = explode(Xoonips_Enum::ITEM_ID_SEPARATOR, $id);
		$groupId = $ids[0];
		$groupLoopId = $ids[1];
		$fieldGroup = UserFieldManager::getInstance()->getFieldGroup($groupId);
		foreach ($fieldGroup->getFields() as $field) {
			$key = $groupId . Xoonips_Enum::ITEM_ID_SEPARATOR . $groupLoopId . Xoonips_Enum::ITEM_ID_SEPARATOR . $field->getId();
			unset($this->data[$key]);
		}
	}
	
	/**
	 * 
	 * move itemGroup down
	 * 
	 * @param  int $id:html's item name
	 * @return 
	 */
	public function moveItemGroupDown($id) {
		$ids = explode(Xoonips_Enum::ITEM_ID_SEPARATOR, $id);
		$groupId = $ids[0];
		$groupLoopId = $ids[1];
		$fieldGroup = UserFieldManager::getInstance()->getFieldGroup($groupId);
		foreach ($fieldGroup->getFields() as $field) {
			$key = $id . Xoonips_Enum::ITEM_ID_SEPARATOR . $field->getId() ; 
			$nextKey = $groupId . Xoonips_Enum::ITEM_ID_SEPARATOR . (1 + $groupLoopId) . Xoonips_Enum::ITEM_ID_SEPARATOR . $field->getId() ;
			$temp = $this->data[$nextKey];
			$this->data[$nextKey] = $this->data[$key];
			$this->data[$key] = $temp;
		}
	}
	
	public function getDisclaimer($value = null) {
		$myxoopsConfigUser = Xoonips_Utils::getXoopsConfigs(XOOPS_CONF_USER);
		$this->xoopsTpl->assign('viewType', 'disclaimer');
		$this->xoopsTpl->assign('reg_disclaimer', $myxoopsConfigUser['reg_disclaimer']);
		$this->xoopsTpl->assign('value', $value);
		return $this->xoopsTpl->fetch('db:'. $this->template);
	}

	public function checkLoginImpl($uid, $logging) {
	   	$userBean = Xoonips_BeanFactory::getBean('UsersBean', XCUBE_CORE_USER_MODULE_NAME);
    	$userInfo = $userBean->getUserBasicInfo($uid);
		if (!$userInfo || $userInfo['level'] == 0) {
			if ($logging) {
	    		XCube_DelegateUtils::call("Module.User.Evnet.User.Login.Fail", xoops_getrequest('uname'));
			}
			redirect_header(XOOPS_URL.'/', 5, _MD_USER_LANG_NOACTTPADM);
			// TODO We should use message "_MD_USER_LANG_NOACTTPADM"
		}

    	if ($userInfo['level'] != 5 && (empty($userInfo['activate']) || $userInfo['activate']!=2)) {
    		if ($logging) {
	    		XCube_DelegateUtils::call("Module.User.Evnet.User.Login.Fail", xoops_getrequest('uname'));
    		}
       		redirect_header( XOOPS_URL.'/', 3, _MD_USER_ACCOUNT_NOT_ACTIVATED );  
    	}
		
		$handler =& xoops_gethandler('user');
		$user =& $handler->get($uid);
		
		if (is_callable(array($user, "getNumGroups"))) { // Compatible for replaced handler.
			if ($user->getNumGroups() == 0) {
				return false;
			}
		}
		else {
			$groups = $user->getGroups();
			if (count($groups) == 0) {
				return false;
			}
		}
		
		return $user;
	}

	public function doGroupRegistry($group, $uids, &$message) {
		$myxoopsConfigUser = Xoonips_Utils::getXoopsConfigs(XOOPS_CONF_USER);
		$configVal = $myxoopsConfigUser['group_making_certify'];

		//insert group
		if ($group['is_hidden'] == '') {
			$group['is_hidden'] = 0;
		}
		if ($group['is_hidden'] == 1) {
			$group['can_join'] = 0;
		}		
		if ($configVal == 'off') {
			$group['activate'] = 1;
		} else {
			$group['activate'] = 0;
		}
		$group['group_type'] = '';
		$group['name'] = trim($group['name']);
		$group['description'] = trim($group['description']);
		$group['item_number_limit'] = $this->limitCheck($group['item_number_limit'], true);
		$group['index_number_limit'] = $this->limitCheck($group['index_number_limit'], true);
		$group['item_storage_limit'] = $this->limitCheck($group['item_storage_limit'] * 1024 * 1024, false);

		$groupbean = Xoonips_BeanFactory::getBean('GroupsBean', $this->dirname, $this->trustDirname);	
		$group_id = $groupbean->insert($group);
		$group['item_storage_limit'] = $group['item_storage_limit'] / 1024 / 1024;
		if (!$group_id) {
			$message = _MD_USER_ERROR_DBUPDATE_FAILED;
			return false;
		}
		$group_handler =& xoops_gethandler('group');
		$xoopsGroup = $group_handler->get($group_id);
		$groupUserLinkBean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		//insert group user link
		foreach ($uids as $uid) {
			$groupUserLink = array();
			$groupUserLink['activate'] = 0;
			$groupUserLink['groupid'] = $group_id;
			$groupUserLink['uid'] = $uid;
			$groupUserLink['is_admin'] = Xoonips_Enum::GRP_US_JOIN_REQUIRED;
			$group_user_id = $groupUserLinkBean->insert($groupUserLink);			
			XCube_DelegateUtils::call('Module.User.Event.Group.Member.Join', new XoopsUser($uid), $xoopsGroup);
			if (!$group_user_id) {
				$groupbean->delete($group_id);
				$groupUserLinkBean->deleteGroupUsers($group_id);
				$message = _MD_USER_ERROR_DBUPDATE_FAILED;
				return false;
			}
		}

		Xoonips_Utils::loadMessage($this->dirname);
		$certifyGroups = Xoonips_Enum::certifyGroups();
		if ($configVal == 'off') {
			$this->doGroupCertified($group_id, $xoopsGroup, true);
			$message = _MD_USER_MESSAGE_GROUP_NEW_SUCCESS;
		} else {
			$groupInfo = $groupbean->getGroup($group_id);
			$certifyTitle = $groupInfo['name'];

			$result = array();
			XCube_DelegateUtils::call('Legacy_Workflow.AddItem', new XCube_Ref($result), $certifyTitle, Xoonips_Enum::certifyGroups(), $group_id);
			if ($result[0] == false) {
				$groupbean->delete($group_id);
				$groupUserLinkBean->deleteGroupUsers($group_id);
				$message = $result;
				return false;
			}
			XCube_DelegateUtils::call('Module.User.Event.Group.CertifyRequest', $xoopsGroup);
			$sendToUsers = array();
			XCube_DelegateUtils::call('Legacy_Workflow.GetCurrentCertifyUsers', Xoonips_Enum::certifyGroups(), $group_id, new XCube_Ref($sendToUsers));
			$this->notification->groupCertifyRequest($group_id, $sendToUsers);
			$message = _MD_USER_MESSAGE_GROUP_NEW_NOTIFY;
		}
		return $group_id;
	}

	public function doGroupCertified($groupId, $xoopsGroup, $isAuto, $comment = '') {
		XCube_DelegateUtils::call('Module.User.Event.Group.Certify', $xoopsGroup);
		//send to certify users
		$groupUserLinkBean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		foreach ($groupUserLinkBean->getAdminUserIds($groupId) as $id) {
			$sendToUsers[$id] = $id; 
		}
		XCube_DelegateUtils::call('Legacy_Workflow.GetAllCertifyUsers', Xoonips_Enum::certifyGroups(), new XCube_Ref($sendToUsers));

		if ($isAuto) {
			$this->notification->groupCertifiedAuto($groupId, $sendToUsers);
		} else {
			$this->notification->groupCertified($groupId, $sendToUsers, $comment);
		}
	} 

	public function doGroupEdit($groupPublic, $group, $uids, &$message) {
		$myxoopsConfigUser = Xoonips_Utils::getXoopsConfigs(XOOPS_CONF_USER);
		$configVal = $myxoopsConfigUser['group_publish_certify'];
		Xoonips_Utils::loadMessage($this->dirname);

		$groupId = $group['groupid'];

		//get activate		
		$group_handler =& xoops_gethandler('group');
		$xoopsGroup = $group_handler->get($groupId);
		$certifyGroupOpen = Xoonips_Enum::certifyGroupOpen();		
		if ($group['is_public'] == 1 &&  $groupPublic == 0) {
			if ($configVal == 'off') {
				$group['activate'] = Xoonips_Enum::GRP_PUBLIC;
				$this->doGroupOpened($groupId, $xoopsGroup, true);
				$message = _MD_USER_MESSAGE_GROUP_OPEN_SUCCESS;							
			} else {
				$group['activate'] = Xoonips_Enum::GRP_OPEN_REQUIRED;
				$group['is_public'] = 0;
				$certifyTitle =$xoopsGroup->get('name');
				$result = array();
				XCube_DelegateUtils::call('Legacy_Workflow.AddItem', new XCube_Ref($result), $certifyTitle, $certifyGroupOpen, $groupId);
				if ($result[0] == false) {
					$message = $result;
					return false;
				}		
				
				$sendToUsers = array();
				XCube_DelegateUtils::call('Legacy_Workflow.GetCurrentCertifyUsers', $certifyGroupOpen, $groupId, new XCube_Ref($sendToUsers));
				$this->notification->groupOpenRequest($groupId, $sendToUsers);
				XCube_DelegateUtils::call('Module.User.Event.Group.OpenRequest', $xoopsGroup);
				$message = _MD_USER_MESSAGE_GROUP_OPEN_NOTIFY;				
			}		
		}
		$certifyGroupClose = Xoonips_Enum::certifyGroupClose();
		if ($group['is_public'] == 0 && $groupPublic == 1) {
			if ($configVal == 'off') {
				$group['activate'] = Xoonips_Enum::GRP_CERTIFIED;
				$this->doGroupClosed($groupId, $xoopsGroup, true);
				$message = _MD_USER_MESSAGE_GROUP_CLOSE_SUCCESS;					
			} else {
				$group['activate'] = Xoonips_Enum::GRP_CLOSE_REQUIRED;
				$group['is_public'] = 1;
				$certifyTitle = $xoopsGroup->get('name');
				$result = array();
				XCube_DelegateUtils::call('Legacy_Workflow.AddItem', new XCube_Ref($result), $certifyTitle, $certifyGroupClose, $groupId);
				if ($result[0] == false) {
					$message = $result;
					return false;
				}			
				$sendToUsers = array();
				XCube_DelegateUtils::call('Legacy_Workflow.GetCurrentCertifyUsers', $certifyGroupClose, $groupId, new XCube_Ref($sendToUsers));
				$this->notification->groupCloseRequest($groupId, $sendToUsers);
				XCube_DelegateUtils::call('Module.User.Event.Group.CloseRequest', $xoopsGroup);	
				$message = _MD_USER_MESSAGE_GROUP_CLOSE_NOTIFY;				
			}	
		}
			
		//update group
		$group['name'] = trim($group['name']);
		$group['description'] = trim($group['description']);
		$group['item_number_limit'] = $this->limitCheck($group['item_number_limit'], true);
		$group['index_number_limit'] = $this->limitCheck($group['index_number_limit'], true);
		$group['item_storage_limit'] = $this->limitCheck($group['item_storage_limit'] * 1024 * 1024, false);

		$groupBean = Xoonips_BeanFactory::getBean('GroupsBean', $this->dirname, $this->trustDirname);	    
		if (!$groupBean->update($group)) {
			$message = _MD_USER_ERROR_DBUPDATE_FAILED;
			return false;
		}
		$group['item_storage_limit'] = $group['item_storage_limit'] / 1024 / 1024;		
		XCube_DelegateUtils::call('Module.User.Event.Group.Edit', $xoopsGroup);	

		//update manager
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$groupUserLinkBean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		foreach ($uids as $uid) {
			$groupUserLink = $groupUserLinkBean->getGroupUserLinkInfo($groupId, $uid);
			if (!empty($groupUserLink)) {
				$isGroupManager = $userBean->isGroupManager($groupId, $uid);
				if (!$isGroupManager) {
					$groupManager = $groupUserLinkBean->updateManager($groupId, $uid);
					if (!$groupManager) {
						$message = _MD_USER_ERROR_DBUPDATE_FAILED;
						return false;
					}
				}
			} else {
				$groupUser = array();
				$groupUser['activate'] = Xoonips_Enum::GRP_US_CERTIFIED;
				$groupUser['groupid'] = $groupId;
				$groupUser['uid'] = $uid;
				$groupUser['is_admin'] = Xoonips_Enum::GRP_ADMINISTRATOR;
				$groupUserId = $groupUserLinkBean->insert($groupUser);				
				XCube_DelegateUtils::call('Module.User.Event.Group.Member.Join', new XoopsUser($uid), $xoopsGroup);	
				if (!$groupUserId) {
					$message = _MD_USER_ERROR_DBUPDATE_FAILED;
					return false;
				}
			}
		}

		$managers = $userBean->getUsersGroups($groupId, true);
		foreach ($managers as $manager) {
			if (!in_array($manager['uid'], $uids)) {
				$groupMember = $groupUserLinkBean->updateMemeber($groupId, $manager['uid']);
				if(!$groupMember){
					$message = _MD_USER_ERROR_DBUPDATE_FAILED;
					return false;
				}
			}
		}
		return true;
	}
	
	public function doGroupOpened($groupId, $xoopsGroup, $isAuto, $comment = '') {
		XCube_DelegateUtils::call('Module.User.Event.Group.OpenCertify', $xoopsGroup);
		//send to certify users
		$groupUserLinkBean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		foreach ($groupUserLinkBean->getAdminUserIds($groupId) as $id) {
			$sendToUsers[$id] = $id; 
		}
		XCube_DelegateUtils::call('Legacy_Workflow.GetAllCertifyUsers', Xoonips_Enum::certifyGroupOpen(), new XCube_Ref($sendToUsers));

		if ($isAuto) {
			$this->notification->groupOpenedAuto($groupId, $sendToUsers);
		} else {
			$this->notification->groupOpened($groupId, $sendToUsers, $comment);
		}
	}

	public function doGroupClosed($groupId, $xoopsGroup, $isAuto, $comment = '') {
		XCube_DelegateUtils::call('Module.User.Event.Group.CloseCertify', $xoopsGroup);
		//send to certify users
		$groupUserLinkBean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		foreach ($groupUserLinkBean->getAdminUserIds($groupId) as $id) {
			$sendToUsers[$id] = $id; 
		}
		XCube_DelegateUtils::call('Legacy_Workflow.GetAllCertifyUsers', Xoonips_Enum::certifyGroupClose(), new XCube_Ref($sendToUsers));

		if ($isAuto) {
			$this->notification->groupClosedAuto($groupId, $sendToUsers);
		} else {
			$this->notification->groupClosed($groupId, $sendToUsers, $comment);
		}
	}

	public function doGroupMember($groupId, $members, $memberIds, &$message) {
		$groupUserLinkBean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		$group_handler =& xoops_gethandler('group');
		$xoopsGroup = $group_handler->get($groupId);

		//update group member
		if (!empty($memberIds)) {
			foreach ($memberIds as $memberId) {
				$groupUserLink = $groupUserLinkBean->getGroupUserLinkInfo($groupId, $memberId);
				if (empty($groupUserLink)) {
					if (!$this->doGroupMemberJoined($groupId, $memberId, $xoopsGroup, $message)) {
						return false;
					}
				}
			}	
			foreach ($members as $member) {
				if (!in_array($member['uid'], $memberIds)) {
					if (!$this->doGroupMemberLeaved($groupId, $member['uid'], $xoopsGroup, $message)) {
						return false;
					}
				}
			}	
		} else {
			foreach ($members as $member) {
				if (!$this->doGroupMemberLeaved($groupId, $member['uid'], $xoopsGroup, $message)) {
					return false;
				}
			}	
		}
		return true;
	}

	private function doGroupMemberJoined($groupId, $uid, $xoopsGroup, &$message) {
		$groupUser = array();
		$groupUser['activate'] = Xoonips_Enum::GRP_US_CERTIFIED;
		$groupUser['groupid'] = $groupId;
		$groupUser['uid'] = $uid;
		$groupUser['is_admin'] = Xoonips_Enum::GRP_USER;
		$groupUserLinkBean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		$groupUserId = $groupUserLinkBean->insert($groupUser);						
		XCube_DelegateUtils::call('Module.User.Event.Group.Member.Join', new XoopsUser($uid), $xoopsGroup);
		if (!$groupUserId) {
			$message = _MD_USER_ERROR_DBUPDATE_FAILED;
			return false;
		}
		return true;
	}
	
	private function doGroupMemberLeaved($groupId, $uid, $xoopsGroup, &$message) {
		$groupUserLinkBean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		$groupMember = $groupUserLinkBean->delete($groupId, $uid);
		XCube_DelegateUtils::call('Module.User.Event.Group.Member.Leave', new XoopsUser($uid), $xoopsGroup);
		if (!$groupMember) {
			$message = _MD_USER_ERROR_DBUPDATE_FAILED;
			return false;
		}
		return true;	
	}

	public function doGroupJoin($group, $uid, &$message) {
		if (empty($group)) {
			$message = _MD_USER_ERROR_GROUP_ENTRY;
			return false;
		}

		//join check
		if (!$this->rightCheck($group, $uid, 'join')) {
			$message = _MD_USER_ERROR_GROUP_ENTRY;
			return false;
		}

		//join group
		$groupuserlinkbean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		if ($group['member_accept'] == 1) {
			$groupUserLink['activate'] = Xoonips_Enum::GRP_US_CERTIFIED;
		} else {
			$groupUserLink['activate'] = Xoonips_Enum::GRP_US_JOIN_REQUIRED;
		}
		$groupId = $group['groupid'];
		$groupUserLink['groupid'] = $groupId;
		$groupUserLink['uid'] = $uid;
		$groupUserLink['is_admin'] = 0;
		$insert = $groupuserlinkbean->insert($groupUserLink);
		if (!$insert) {
			$message = _MD_USER_ERROR_GROUP_ENTRY;
			return false;
		}

		Xoonips_Utils::loadMessage($this->dirname);
		$certifyGroupJoin = Xoonips_Enum::certifyGroupJoin();
		$group_handler =& xoops_gethandler('group');
		$xoopsGroup = $group_handler->get($groupId);
		if ($group['member_accept'] == 0) {
			//group member certify 
			$groupbean = Xoonips_BeanFactory::getBean('GroupsBean', $this->dirname, $this->trustDirname);
			$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
			$groupsUsersLinkInfo = $groupuserlinkbean->getGroupUserLinkInfo($groupId, $uid);
			$linkId = $groupsUsersLinkInfo['linkid'];
			$groupInfo = $groupbean->getGroup($groupId);
			$groupName = $groupInfo['name'];
			$userInfo = $userBean->getUserBasicInfo($uid);
			$uname = $userInfo['uname'];
			$name = $userInfo['name'];
			$certifyTitle = ($name == '') ? $uname : $uname . "($name)";
			$certifyTitle = $groupName . ':' . $certifyTitle;
				
			$result = array();
			XCube_DelegateUtils::call('Legacy_Workflow.AddItem', new XCube_Ref($result), $certifyTitle, $certifyGroupJoin, $linkId);
			if ($result[0] == false) {
				$groupuserlinkbean->delete($groupId, $uid);
				$message = $result;
				return false;
			}
			//event log									
			XCube_DelegateUtils::call('Module.User.Event.Group.Member.JoinRequest', new XoopsUser($uid), $xoopsGroup);
			$sendToUsers = array();
			XCube_DelegateUtils::call('Legacy_Workflow.GetCurrentCertifyUsers', $certifyGroupJoin, $linkId, new XCube_Ref($sendToUsers));
			$this->notification->groupJoinRequest($groupId, $uid, $sendToUsers);
			$message = _MD_USER_MESSAGE_GROUP_JOIN_NOTIFY;
		} else {
			$this->doGroupJoined($groupId, $uid, $xoopsGroup, true);
			$message = _MD_USER_MESSAGE_GROUP_JOIN_SUCCESS;
		}
		return true;
	}

	public function doGroupJoined($groupId, $uid, $xoopsGroup, $isAuto, $comment = '') {
		XCube_DelegateUtils::call('Module.User.Event.Group.Member.JoinCertify', new XoopsUser($uid), $xoopsGroup);
		//send to certify users
		$sendToUsers[$uid] = $uid;
		$groupUserLinkBean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		foreach ($groupUserLinkBean->getAdminUserIds($groupId) as $id) {
			$sendToUsers[$id] = $id; 
		}
		XCube_DelegateUtils::call('Legacy_Workflow.GetAllCertifyUsers', Xoonips_Enum::certifyGroupJoin(), new XCube_Ref($sendToUsers));

		if ($isAuto) {
			$this->notification->groupJoinAuto($groupId, $uid, $sendToUsers);
		} else {
			$this->notification->groupJoin($groupId, $uid, $sendToUsers, $comment);
		}
	} 

	public function doGroupLeave($group, $uid, &$message) {
		if (empty($group)) {
			$message = _MD_USER_ERROR_GROUP_LEAVE;
			return false;
		}

		//leave check
		if (!$this->rightCheck($group, $uid, 'leave')) {
			$message = _MD_USER_ERROR_GROUP_LEAVE;
			return false;
		}
			
		//group item check
		$groupId = $group['groupid'];
		$group_handler =& xoops_gethandler('group');
		$xoopsGroup = $group_handler->get($groupId);
		$itemChecks = array();
		XCube_DelegateUtils::call('Module.User.Event.Group.Member.LeaveCondition', new XCube_Ref($itemChecks), $xoopsGroup, new XoopsUser($uid));
		if (count($itemChecks) > 0) {
			foreach ($itemChecks as $itemCheck) {
				if($itemCheck){
					$message = _MD_USER_ERROR_GROUP_REFUSE_LEAVE;
					return false;
				}
			}
		}

		Xoonips_Utils::loadMessage($this->dirname);
		$groupuserlinkbean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);		
		$certifyGroupLeave = Xoonips_Enum::certifyGroupLeave();
		//leave group
		if ($group['member_accept'] == 1) {
			$delete = $groupuserlinkbean->delete($groupId, $uid);
			if (!$delete) {
				$message = _MD_USER_ERROR_GROUP_LEAVE;
				return false;
			}
			//send to activate user
			$this->doGroupLeaved($groupId, $uid, $xoopsGroup, true);
		} else {
			$update = $groupuserlinkbean->update($groupId, $uid);
			if (!$update) {
				$message = _MD_USER_ERROR_GROUP_LEAVE;
				return false;
			}
			//group member certify 
			$userBean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
			$groupsUsersLinkInfo = $groupuserlinkbean->getGroupUserLinkInfo($groupId, $uid);
			$linkId = $groupsUsersLinkInfo['linkid'];
			$groupName = $group['name'];
			$userInfo = $userBean->getUserBasicInfo($uid);
			$uname = $userInfo['uname'];
			$name = $userInfo['name'];
			$certifyTitle = ($name == '') ? $uname : $uname . "($name)";
			$certifyTitle = $groupName . ':' . $certifyTitle;
			
			$result = array();
			XCube_DelegateUtils::call('Legacy_Workflow.AddItem', new XCube_Ref($result), $certifyTitle, $certifyGroupLeave, $linkId);
			if ($result[0] == false) {
				$groupuserlinkbean->certify($groupId, $uid);
				$message = $result;
				return false;
			}
				
			$sendToUsers = array();
			XCube_DelegateUtils::call('Legacy_Workflow.GetCurrentCertifyUsers', $certifyGroupLeave, $linkId, new XCube_Ref($sendToUsers));
			$this->notification->groupLeaveRequest($groupId, $uid, $sendToUsers);
		}
			
		if ($group['member_accept'] == 0) {
			XCube_DelegateUtils::call('Module.User.Event.Group.Member.LeaveRequest', new XoopsUser($uid), $xoopsGroup);
			$message = _MD_USER_MESSAGE_GROUP_LEAVE_NOTIFY;		   		
		} else {				
			XCube_DelegateUtils::call('Module.User.Event.Group.Member.LeaveCertify', new XoopsUser($uid), $xoopsGroup);
			$message = _MD_USER_MESSAGE_GROUP_LEAVE_SUCCESS;
		}
	}

	public function doGroupLeaved($groupId, $uid, $xoopsGroup, $isAuto, $comment = '') {
		XCube_DelegateUtils::call('Module.User.Event.Group.Member.LeaveCertify', new XoopsUser($uid), $xoopsGroup);
		//send to certify users
		$sendToUsers[$uid] = $uid;
		$groupUserLinkBean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		foreach ($groupUserLinkBean->getAdminUserIds($groupId) as $id) {
			$sendToUsers[$id] = $id; 
		}
		XCube_DelegateUtils::call('Legacy_Workflow.GetAllCertifyUsers', Xoonips_Enum::certifyGroupLeave(), new XCube_Ref($sendToUsers));

		if ($isAuto) {
			$this->notification->groupLeaveAuto($groupId, $uid, $sendToUsers);
		} else {
			$this->notification->groupLeave($groupId, $uid, $sendToUsers, $comment);
		}
	} 

	public function addGroupOperationFlag($groups, $uid, &$newflag) {

		//new button flag
		$newflag = false;
		$myxoopsConfigUser = Xoonips_Utils::getXoopsConfigs(XOOPS_CONF_USER);
		$configVal = $myxoopsConfigUser['group_making'];
		$userbean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$isModerator = $userbean->isModerator($uid);
		if ($isModerator || $configVal == 'on') {
			$newflag = true;
		}
		
		//display group list
		$groupuserlinkbean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		$groupLists = array();
		foreach ($groups as $group) {
			$groupUserList = $groupuserlinkbean->getGroupUserLinkInfo($group['groupid'], $uid);
			$isGroupManager = $userbean->isGroupManager($group['groupid'], $uid);

			//group name edit
			if ($group['is_hidden'] == 1) {
				if ($isModerator) {
					$group['secret'] = 1;
				} elseif (!empty($groupUserList)) {
					if ($groupUserList['activate'] == Xoonips_Enum::GRP_US_CERTIFIED || $groupUserList['activate'] == Xoonips_Enum::GRP_US_LEAVE_REQUIRED) {
						$group['secret'] = 1;
					} else {
						continue;
					}
				} else {
					continue;
				}
			}
				
			//edit button,member button flag
			$group['editflag'] = false;
			$group['memberflag'] = false;
			if ($group['activate'] == Xoonips_Enum::GRP_CERTIFIED
					|| $group['activate'] == Xoonips_Enum::GRP_OPEN_REQUIRED
					|| $group['activate'] == Xoonips_Enum::GRP_PUBLIC
					|| $group['activate'] == Xoonips_Enum::GRP_CLOSE_REQUIRED) {
				if ($isModerator || $isGroupManager) {
					$group['editflag'] = true;
					$group['memberflag'] = true;
				}
			}	
	
			//join button flag
			$group['joinflag'] = $this->rightCheck($group, $uid, 'join');	
		
			//leave button flag
			$group['leaveflag'] = $this->rightCheck($group, $uid, 'leave');

			//delete button flag
			$group['deleteflag'] = false;
			if ($group['activate'] == Xoonips_Enum::GRP_CERTIFIED || $group['activate'] == Xoonips_Enum::GRP_PUBLIC) {
				if ($isModerator || $isGroupManager) {
					$group['deleteflag'] = true;
				}
			}

			//group user pending	
			if ($groupUserList) {
				$group['userActivate'] = $groupUserList['activate'];
			}		
			$groupLists[] = $group;	
		}
		return $groupLists;
	}

	public function doGroupDelete($group, &$message) {
		global $xoopsUser;
		$uid = $xoopsUser->getVar('uid');

		if (empty($group)) {
			$message = _MD_USER_ERROR_GROUP_DELETE;
			return false;
		}

		$groupId = $group['groupid'];
		$userbean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$isModerator = $userbean->isModerator($uid);
		$isGroupManager = $userbean->isGroupManager($groupId, $uid);

		//delete check
		$check = false;
		if ($group['activate'] == Xoonips_Enum::GRP_CERTIFIED || $group['activate'] == Xoonips_Enum::GRP_PUBLIC) {
			if ($isModerator || $isGroupManager) {
				$check = true;
			}
		}
		if (!$check) {
			$message = _MD_USER_ERROR_GROUP_DELETE;
			return false;
		}
			
		//delete group,index
		$groupbean = Xoonips_BeanFactory::getBean('GroupsBean', $this->dirname, $this->trustDirname);
		$myxoopsConfigUser = Xoonips_Utils::getXoopsConfigs(XOOPS_CONF_USER);
		$configVal = $myxoopsConfigUser['group_making_certify'];
		
		$group_handler =& xoops_gethandler('group');
		$xoopsGroup = $group_handler->get($groupId);
		Xoonips_Utils::loadMessage($this->dirname);
		if ($configVal == 'off') {
			if (!$this->doGroupDeleted($group, $xoopsGroup, true, $message)) {
				return false;
			}
			$message = _MD_USER_MESSAGE_GROUP_DELETE_SUCCESS;
		} else {
			$update = $groupbean->updateActivate($groupId);
			if (!$update) {
				$message = _MD_USER_ERROR_GROUP_DELETE;
				return false;
			}
			$certifyTitle = $group['name'];
				
			$result = array();
			XCube_DelegateUtils::call('Legacy_Workflow.AddItem', new XCube_Ref($result), $certifyTitle, Xoonips_Enum::certifyGroupDelete(), $groupId);
			if ($result[0] == false) {
				if ($group['activate'] == Xoonips_Enum::GRP_CERTIFIED) {
					$groupbean->groupsCertify($groupId);
				} elseif ($group['activate'] == Xoonips_Enum::GRP_PUBLIC) {
					$groupbean->groupsOpen($groupId);
				}
				$message = $result;
				return false;
			}
			
			XCube_DelegateUtils::call('Module.User.Event.Group.DeleteRequest', $xoopsGroup);
			$sendToUsers = array();
			XCube_DelegateUtils::call('Legacy_Workflow.GetCurrentCertifyUsers', Xoonips_Enum::certifyGroupDelete(), $groupId, new XCube_Ref($sendToUsers));
			$this->notification->groupDeleteRequest($groupId, $sendToUsers);
			$message = _MD_USER_MESSAGE_GROUP_DELETE_NOTIFY;
		}
		return true;
	}

	public function doGroupDeleted($group, $xoopsGroup, $isAuto, &$message, $comment = '') {
		$userbean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$groupuserlinkbean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);

		$groupId = $group['groupid'];
		$managers = $userbean->getUsersGroups($groupId, true);
		$members = $userbean->getUsersGroups($groupId, false);
		foreach ($groupuserlinkbean->getAdminUserIds($groupId) as $id) {
			$sendToUsers[$id] = $id;
		}
		XCube_DelegateUtils::call('Legacy_Workflow.GetAllCertifyUsers', Xoonips_Enum::certifyGroupDelete(), new XCube_Ref($sendToUsers));
		foreach ($members as $member) {
			$groupMembersDelete = $groupuserlinkbean->delete($groupId, $member['uid']);
			if (!$groupMembersDelete) {
				$message = _MD_USER_ERROR_GROUP_DELETE;
				return false;
			}
			XCube_DelegateUtils::call('Module.User.Event.Group.Member.Leave', new XoopsUser($member['uid']), $xoopsGroup);
		}
		foreach ($managers as $manager) {
			$groupManagerDelete = $groupuserlinkbean->delete($groupId, $manager['uid']);
			if (!$groupManagerDelete) {
				$message = _MD_USER_ERROR_GROUP_DELETE;
				return false;
			}
			XCube_DelegateUtils::call('Module.User.Event.Group.Member.Leave', new XoopsUser($manager['uid']), $xoopsGroup);
		}

		$groupbean = Xoonips_BeanFactory::getBean('GroupsBean', $this->dirname, $this->trustDirname);
		$groupDelete = $groupbean->delete($groupId);
		if (!$groupDelete) {
			$message = _MD_USER_ERROR_GROUP_DELETE;
			return false;
		}
			
		$handler =& xoops_gethandler('groupperm');
		if (!$handler->deleteByGroup($groupId)) {
			$message = _MD_USER_ERROR_GROUP_DELETE;
			return false;
		}
								
		XCube_DelegateUtils::call('Module.User.Event.Group.DeleteCertify', $xoopsGroup);
				
		//send to certify users
		if ($isAuto) {
			$this->notification->groupDeletedAuto($group, $sendToUsers);
		} else {
			$this->notification->groupDeleted($group, $sendToUsers, $comment);
		}

		return true;
	}

	private function limitCheck($limit, $isInteger) {
		$limit = trim($limit);
		if ($limit == '' || !is_numeric($limit)) {
			$limit = 0;
		}
		if ($isInteger && strpos($limit, '.')) {
			$limit = floor($limit);
		}
		return $limit;
	}

	/**
	 * group can join,leave check
	 * 
	 * @return bool
	 */
	private function rightCheck($group, $uid, $type) {
		$userbean = Xoonips_BeanFactory::getBean('UsersBean', $this->dirname, $this->trustDirname);
		$groupuserlinkbean = Xoonips_BeanFactory::getBean('GroupsUsersLinkBean', $this->dirname, $this->trustDirname);
		$groupUserList = $groupuserlinkbean->getGroupUserLinkInfo($group['groupid'], $uid);
		$isGroupManager = $userbean->isGroupManager($group['groupid'], $uid);
		if ($group['activate'] == Xoonips_Enum::GRP_CERTIFIED
				|| $group['activate'] == Xoonips_Enum::GRP_OPEN_REQUIRED
				|| $group['activate'] == Xoonips_Enum::GRP_PUBLIC
				|| $group['activate'] == Xoonips_Enum::GRP_CLOSE_REQUIRED) {
			if ($group['can_join'] == 1) {
				if ($type == 'join') {
					if (empty($groupUserList)) {
						return true;
					}
				}
				if ($type == 'leave') {
					if (!$isGroupManager && !empty($groupUserList)) {
						if ($groupUserList['activate'] == Xoonips_Enum::GRP_US_CERTIFIED) {
							return true;
						}
					}
				}
			}	
		}
		return false;
	}
}

