<?php

require_once XOOPS_TRUST_PATH . '/libs/xoonips/class/core/BeanBase.class.php';
require_once XOOPS_TRUST_PATH . '/libs/xoonips/class/core/DataTypeFactory.class.php';
require_once dirname(dirname(__FILE__)) . '/core/ItemFieldManagerFactory.class.php';
require_once dirname(dirname(__FILE__)) . '/core/ItemFieldManager.class.php';
require_once dirname(dirname(__FILE__)) . '/core/Notification.class.php';
require_once dirname(dirname(__FILE__)) . '/entity/ItemEntity.class.php';

if (Xoonips_BeanFactory::chkUserBean()) {
  require_once XOOPS_TRUST_PATH . '/modules/user/class/core/UserFieldManager.class.php';
}

/**
 * @brief operate xoonips_item_virtual_table
 *
 */
class Xoonips_ItemVirtualBean extends Xoonips_BeanBase {
	/**
	 * Constructor
	 **/
	public function Xoonips_ItemVirtualBean($dirname, $trustDirname) {
		$this->Xoonips_BeanBase($dirname, $trustDirname);
		$this->setTableName('index_item_link', true);
	}

	/**
	 * get item by id
	 * @param item type id
	 * @return item
	 */
	public function getItem($itemId) {
		$ret = array();
		$itemUsersBean = false;
		$itemRelationBean = false;
		$itemTitleBean = false;
		$itemKeywordBean = false;
		$fileBean = false;
		$indexItemLinkBean = false;
		$changeLogBean = false;
		$itemExtendBean = false;

		// item table
		$itemBean = Xoonips_BeanFactory::getBean('ItemBean', $this->dirname, $this->trustDirname);
		$info = $itemBean->getItemBasicInfo($itemId);
		$ret[$this->dirname . '_item'] = $info;
		$itemTypeId = $info['item_type_id'];

		// item type table
		$itemTypeBean = Xoonips_BeanFactory::getBean('ItemTypeBean', $this->dirname, $this->trustDirname);
		$info = $itemTypeBean->getItemTypeInfo($itemTypeId);
		$ret[$this->dirname . '_item_type'] = $info;

		$itemFieldManager = Xoonips_ItemFieldManagerFactory::getInstance($this->dirname, $this->trustDirname)->getItemFieldManager($itemTypeId);
		$itemFields = $itemFieldManager->getFields();
		foreach ($itemFields as $itemField) {
			$tableName = $itemField->getTableName();
			// if item table
			if ($tableName == $this->modulePrefix('item')) {
				continue;
			// if item users link table
			} elseif ($tableName == $this->modulePrefix('item_users_link')) {
				if (!$itemUsersBean) {
					$itemUsersBean = Xoonips_BeanFactory::getBean('ItemUsersLinkBean', $this->dirname, $this->trustDirname);
					$info = $itemUsersBean->getItemUsersInfo($itemId);
				}
			// if item relation table
			} elseif ($tableName == $this->modulePrefix('item_related_to')) {
				if (!$itemRelationBean) {
					$itemRelationBean = Xoonips_BeanFactory::getBean('ItemRelatedToBean', $this->dirname, $this->trustDirname);
					$info = $itemRelationBean->getRelatedToInfo($itemId);
				}
			// if item title table
			} elseif ($tableName == $this->modulePrefix('item_title')) {
				if (!$itemTitleBean) {
					$itemTitleBean = Xoonips_BeanFactory::getBean('ItemTitleBean', $this->dirname, $this->trustDirname);
					$info = $itemTitleBean->getItemTitleInfo($itemId);
				}
			// if item keyword table
			} elseif ($tableName == $this->modulePrefix('item_keyword')) {
				if (!$itemKeywordBean) {
					$itemKeywordBean = Xoonips_BeanFactory::getBean('ItemKeywordBean', $this->dirname, $this->trustDirname);
					$info = $itemKeywordBean->getKeywords($itemId);
				}
			// if file table
			} elseif ($tableName == $this->modulePrefix('item_file')) {
				if (!$fileBean) {
					$fileBean = Xoonips_BeanFactory::getBean('ItemFileBean', $this->dirname, $this->trustDirname);
				}
				#$info = $fileBean->getFilesByItemId($itemId);
				$group_id = $itemField->getFieldGroupId() ? $itemField->getFieldGroupId() : 0;
				$info = $fileBean->getFilesByItemId($itemId, $group_id);

			// if index item link table
			} elseif ($tableName == $this->modulePrefix('index_item_link')) {
				if (!$indexItemLinkBean) {
					$indexItemLinkBean = Xoonips_BeanFactory::getBean('IndexItemLinkBean', $this->dirname, $this->trustDirname);
					$info = $indexItemLinkBean->getIndexItemLinkInfo($itemId);
				}
			// if change log table
			} elseif ($tableName == $this->modulePrefix('item_changelog')) {
				if (!$changeLogBean) {
					$changeLogBean = Xoonips_BeanFactory::getBean('ItemChangeLogBean', $this->dirname, $this->trustDirname);
					$info = $changeLogBean->getChangeLogs($itemId);
				}
			// if item extend
			} elseif (strncmp($tableName, $this->modulePrefix('item_extend'), strlen($this->dirname) + 12) == 0) {
				if (!$itemExtendBean) {
					$itemExtendBean = Xoonips_BeanFactory::getBean('ItemExtendBean', $this->dirname, $this->trustDirname);
				}
				$group_id = $itemField->getFieldGroupId() ? $itemField->getFieldGroupId() : 0;
				$info = $itemExtendBean->getItemExtendInfo($itemId, $tableName, $group_id);

			} else {
				$info = false;
			}
			if (!isset($ret[$tableName])) {
				$ret[$tableName] = $info;
			} else {
				foreach ($info as $val) {
					array_push($ret[$tableName], $val);
				}
			}
		}
		return $ret;
	}

	public function getItem2($itemId) {
		$ret = array();
		// item table
		$itemBean = Xoonips_BeanFactory::getBean('ItemBean', $this->dirname, $this->trustDirname);
		$info = $itemBean->getItemBasicInfo($itemId);
		$ret['xoonips_item'] = $info;
		$itemTypeId = $info['item_type_id'];

		// item type table
		$itemTypeBean = Xoonips_BeanFactory::getBean('ItemTypeBean', $this->dirname, $this->trustDirname);
		$info = $itemTypeBean->getItemTypeInfo($itemTypeId);
		$ret['xoonips_item_type'] = $info;
		return $ret;
	}

	/**
	 * get item list html by id
	 * @param item type id
	 * @return item list html
	 */
	public function getItemListHtml($item) {
		global $xoopsTpl;
		$itemTypeId = $item['xoonips_item_type']['item_type_id'];
		$itemEntity = new Xoonips_ItemEntity($this->dirname, $this->trustDirname);
		$itemEntity->setData($item);
		$xoopsTpl->assign('item', $itemEntity);
		ob_start();
		$xoopsTpl->display($this->dirname . "_itemtype:$itemTypeId," . $this->dirname);
		$xoopsTpl->force_compile = true;
		$ret = ob_get_contents();
		ob_clean();
		return $ret;
	}

	/**
	 * can view item
	 * @param int $item_id
	 *         int $uid
	 * @return bool:true-can,false-can not
	 */
	public function canView($item_id, $uid) {
		$linkBean = Xoonips_BeanFactory::getBean('IndexItemLinkBean', $this->dirname, $this->trustDirname);
		$indexBean = Xoonips_BeanFactory::getBean('IndexBean', $this->dirname, $this->trustDirname);
		$linkInfos = $linkBean->getIndexItemLinkInfo($item_id);
		if ($linkInfos) {
			foreach ($linkInfos as $linkInfo) {
				$canViewItemIds = $indexBean->getCanViewItemIds($linkInfo['index_id'], $uid);
				if ($canViewItemIds && in_array($item_id, $canViewItemIds)) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * filter can view item
	 * @param array $item_ids
	 *         int $uid
	 * @return array
	 */
	public function filterCanViewItem(&$item_ids, $uid) {
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', XCUBE_CORE_USER_MODULE_NAME);
		if ($userBean->isModerator($uid)) {
			return;
		}
		if ($item_ids && count($item_ids) > 0) {
			foreach ($item_ids as $key => $item_id) {
				if (!$this->canView($item_id, $uid)) {
					unset($item_ids[$key]);
				}
			}
		}
	}

	/**
	 * get items list
	 * @param $iids, $criteria
	 * @return array
	 */
	public function getItemsList($item_ids, $criteria) {
		$items = array();
		if (count($item_ids) == 0) return $items;
		$itemTable = $this->prefix($this->modulePrefix('item'));
		$itemBean = Xoonips_BeanFactory::getBean('ItemBean', $this->dirname, $this->trustDirname);
		$sql = '';
		if ($criteria['orderby'] == '0') {
			$sql = "SELECT DISTINCT item_id FROM $itemTable WHERE item_id IN ( " . $this->getCsvStr($item_ids) . ' )';
			$criteria['order'] = ' item_id ';
		} else {
			$sortBean = Xoonips_BeanFactory::getBean('ItemTypeSortDetailBean', $this->dirname, $this->trustDirname);
			$sortInfos = $sortBean->select($criteria['orderby']);
			$itemtypeDetailBean = Xoonips_BeanFactory::getBean('ItemFieldDetailBean', $this->dirname, $this->trustDirname);
			$unionSql = array();
			$tableUsers = $this->prefix('users');
			$groupby_item_ids = $itemBean->groupby($item_ids);
			foreach ($sortInfos as $sortInfo) {
				$item_type_id = $sortInfo['item_type_id'];
				if (isset($groupby_item_ids[$item_type_id])) {
					$target_item_ids = $groupby_item_ids[$item_type_id];
					unset($groupby_item_ids[$item_type_id]);
				} else {
					continue;
				}
				$detailId = $sortInfo['item_field_detail_id'];
				$sql = '';
				if (empty($detailId)) {
					$sql = "SELECT item_id , NULL as orderColumn FROM $itemTable a WHERE";
				} else {
					$itemtypeDetail = $itemtypeDetailBean->getItemTypeDetailById($detailId);
					if (!$itemtypeDetail) continue;
					$tableNm = $itemtypeDetail['table_name'];
					$columnNm = $itemtypeDetail['column_name'];
					$tableName = $this->prefix($tableNm);
					if ($tableNm == $this->modulePrefix('item_users_link')) {
						$sql = "SELECT a.item_id, b.name as orderColumn FROM $tableName a, $tableUsers b WHERE a.uid=b.uid AND";
					} elseif ($tableNm == $this->modulePrefix('item_file')) {
						$sql = "SELECT a.item_id, b.original_file_name as orderColumn FROM $itemTable a LEFT JOIN $tableName b ON(a.item_id=b.item_id AND b.item_field_detail_id=$detailId) WHERE";
					} elseif ($tableNm == $this->modulePrefix('item')) {
						$sql = "SELECT item_id , $columnNm as orderColumn FROM $itemTable a WHERE";
					} elseif ($tableNm == $this->modulePrefix('item_related_to')) {
						$sql = "SELECT a.item_id , b.$columnNm as orderColumn FROM $itemTable a LEFT JOIN $tableName b ON(a.item_id=b.item_id) WHERE";
					} else {
						$sql = "SELECT a.item_id , b.$columnNm as orderColumn FROM $itemTable a LEFT JOIN $tableName b ON(a.item_id=b.item_id) WHERE";
					}
				}
				$unionSql[] = $sql . ' a.item_id IN(' . implode(',', $target_item_ids) . ')';
			}
			foreach ($groupby_item_ids as $item_ids) {
				$sql = "SELECT item_id , NULL as orderColumn FROM $itemTable a WHERE a.item_id IN(" . implode(',', $item_ids) . ')';
				$unionSql[] = $sql;
			}
			$unionSqlStr = implode(' UNION ALL ', $unionSql);
			$sql = "SELECT DISTINCT temp.item_id FROM ( $unionSqlStr ) AS temp";
			$criteria['order'] = ' temp.orderColumn ';
		}
		$sql .= $this->getCriteriaStr($criteria);
		$result = $this->execute($sql);
		if (!$result) return false;
		while ($row = $this->fetchArray($result)) {
			$items[] = $row['item_id'];
		}
		return $items;
	}

	/**
	 * get criteria string
	 * @param $cri
	 * @return array
	 */
	private function getCriteriaStr($cri) {
		$sql = '';
		if (isset($cri['order']) && isset($cri['orderdir'])) {
			if (isset($cri['order']) && $cri['orderdir'] == 0) {
				$orders = $cri['order'] . ' ASC';
			} elseif (isset($cri['order']) && $cri['orderdir'] == 1) {
				$orders = $cri['order'] . ' DESC';
			}
			$sql .= " ORDER BY $orders ";
		}
		if (isset($cri['rows']) && $cri['rows'] > 0) {
			$sql .= ' LIMIT ';
			if (isset($cri['start']) && $cri['start'] > 0) {
				$sql .= $cri['start'] . ', ';
			}
			$sql .= $cri['rows'];
		}
		return $sql;
	}

	/**
	 * get csv string
	 * @param $descXID
	 * @return array
	 */
	private function getCsvStr($descXID) {
		if (count($descXID)) {
			$ar = array();
			foreach ($descXID as $val)
			$ar[] = (int) $val;
			return implode(',', $ar);
		}
		return '';
	}

	/**
	 * check item group
	 * @param group id,uid
	 * @return boolean
	 */
	public function isItemGroup($groupId, $uid) {
		$ret = false;
		$tblItemUser = $this->prefix($this->modulePrefix('item_users_link'));
		$tblIndex = $this->prefix($this->modulePrefix('index'));
		$sql = "SELECT COUNT($tblItemUser.item_id) AS count"
			. " FROM ($tblItemUser inner join $this->table on $tblItemUser.item_id=$this->table.item_id)"
			. " inner join $tblIndex on $tblIndex.index_id=$this->table.index_id"
			. " WHERE $tblItemUser.uid=$uid AND $tblIndex.open_level=" . XOONIPS_OL_GROUP_ONLY
			. " AND $tblIndex.groupid=$groupId";

		$result = $this->execute($sql);
		if (!$result) {
			return false;
		}
		if ($row = $this->fetchArray($result)) {
			if ($row['count'] != 0) {
				$ret = true;
			}
		}
		$this->freeRecordSet($result);
		return $ret;
	}

	/**
	 * get item extend table
	 * @param
	 * @return table name
	 */
	public function getItemExtendTableByItemtypeId($itemtypeId) {
		$ret = array();
		$table = $this->prefix($this->modulePrefix('item_field_detail'));
		$sql = "SELECT DISTINCT table_name FROM $table WHERE released=1 AND item_type_id=$itemtypeId";
		$result = $this->execute($sql);
		if (!$result) {
			return false;
		}
		while ($row = $this->fetchArray($result)) {
			if (strPos($row['table_name'], 'item_extend') !== false) {
				$ret[] = $row['table_name'];
			}
		}
		$this->freeRecordSet($result);
		return $ret;
	}

	/**
	 *delete item extend by id
	 * @param table name,item id
	 * @return boolean true:success,false:failed
	 */
	public function deleteItemExtend($tableName, $itemId) {
		$table = $this->prefix($tableName);
		$sql = "DELETE FROM $table WHERE item_id=$itemId";
		$result = $this->execute($sql);
		if (!$result) {
			return false;
		}
		return true;
	}

	/**
	 *get the count of items
	 * @param group id
	 * @return int
	 */
	public function countGroupItems($groupId) {
		$ret = 0;
		$tblIndex = $this->prefix($this->modulePrefix('index'));
		$sql = "select count(distinct b.item_id) AS count from $tblIndex a,$this->table b"
			. " where a.groupid=$groupId and a.open_level=" . XOONIPS_OL_GROUP_ONLY
			. " and a.index_id=b.index_id and b.certify_state>=" . XOONIPS_CERTIFIED
			. " and b.item_id not in (select item_id from $tblIndex c,$this->table d"
			. " where c.open_level=" . XOONIPS_OL_PUBLIC . " and c.index_id=d.index_id"
			. " and d.certify_state>=" . XOONIPS_CERTIFIED . ")";
		$result = $this->execute($sql);
		if (!$result) {
			return 0;
		}
		if ($row = $this->fetchArray($result)) {
			if ($row['count'] != 0) {
				$ret = $row['count'];
			}
		}
		$this->freeRecordSet($result);
		return $ret;
	}

	/**
	 *get download notify
	 * @param item id,item type id
	 * @return array
	 */
	public function getDownloadNotify($itemId, $itemtypeId) {
		$ret = array();
		$table = $this->prefix($this->modulePrefix('item_field_detail'));
		$viewTypeBean = Xoonips_BeanFactory::getBean('ViewTypeBean', $this->dirname, $this->trustDirname);
		$sql = "SELECT DISTINCT table_name FROM $table where view_type_id=";
		$sql .= $viewTypeBean->selectByName('download notify') . " and item_type_id=$itemtypeId";
		$result = $this->execute($sql);
		if (!$result) {
			return false;
		}
		while ($row = $this->fetchArray($result)) {
			if (strPos($row['table_name'], 'item_extend') !== false) {
				$extendTable = $this->prefix($row['table_name']);
				$extendSql = "SELECT DISTINCT value FROM $extendTable WHERE item_id=$itemId";
				$extendRet = $this->execute($extendSql);
				if (!$extendRet) {
					return false;
				}
				while ($extendRow = $this->fetchArray($extendRet)) {
					return $extendRow['value'];
				}
				$this->freeRecordSet($extendRet);
			}
		}
		$this->freeRecordSet($result);
		return false;
	}

	/**
	 *get rights
	 * @param item id,item type id
	 * @return array
	 */
	public function getRights($itemId, $itemtypeId) {
		$ret = array();
		$table = $this->prefix($this->modulePrefix('item_field_detail'));
		$viewTypeBean = Xoonips_BeanFactory::getBean('ViewTypeBean', $this->dirname, $this->trustDirname);
		$sql = "SELECT DISTINCT table_name FROM $table where view_type_id=";
		$sql .= $viewTypeBean->selectByName('rights') . " and item_type_id=$itemtypeId";
		$result = $this->execute($sql);
		if (!$result) {
			return false;
		}
		while ($row = $this->fetchArray($result)) {
			if (strPos($row['table_name'], 'item_extend') !== false) {
				$extendTable = $this->prefix($row['table_name']);
				$extendSql = "SELECT DISTINCT value FROM $extendTable WHERE item_id=$itemId";
				$entendRet = $this->execute($extendSql);
				if (!$entendRet) {
					return false;
				}
				while ($entendRow = $this->fetchArray($entendRet)) {
					return $entendRow['value'];
				}
				$this->freeRecordSet($entendRet);
			}
		}
		$this->freeRecordSet($result);
		return false;
	}

	/**
	 *get download limit
	 * @param item id,item type id
	 * @return array
	 */
	public function getDownloadLimit($itemId, $itemtypeId) {
		$ret = array();
		$table = $this->prefix($this->modulePrefix('item_field_detail'));
		$viewTypeBean = Xoonips_BeanFactory::getBean('ViewTypeBean', $this->dirname, $this->trustDirname);
		$sql = "SELECT DISTINCT table_name FROM $table where view_type_id=";
		$sql .= $viewTypeBean->selectByName('download limit') . " and item_type_id=$itemtypeId";
		$result = $this->execute($sql);
		if (!$result) {
			return false;
		}
		while ($row = $this->fetchArray($result)) {
			if (strPos($row['table_name'], 'item_extend') !== false) {
				$extendTable = $this->prefix($row['table_name']);
				$extendSql = "SELECT DISTINCT value FROM $extendTable WHERE item_id=$itemId";
				$entendRet = $this->execute($extendSql);
				if (!$entendRet) {
					return false;
				}
				while ($entendRow = $this->fetchArray($entendRet)) {
					return ($entendRow['value'] == 0);
				}
				$this->freeRecordSet($entendRet);
			}
		}
		$this->freeRecordSet($result);
		return true;
	}

	/**
	 *get private item id
	 * @param uid,$iids
	 * @return boolean
	 */
	public function getPosts($uid, &$posts) {
		$userTable = $this->prefix($this->modulePrefix('item_users_link'));
		$sql = 'SELECT count(item_id) as items FROM ' . $userTable . ' WHERE uid='. $uid;
		$result = $this->execute($sql);
		if (!$result) return false;
		$row = $this->fetchArray($result);
		$posts += (is_null($row['items'])) ? 0 : $row['items'];
		return true;
	}

	/**
	 * get private item limit
	 * @param uid
	 * @return array
	 */
	public function getPrivateItemLimit($uid) {
		$privateItemLimit = array('itemNumber'=>0, 'itemStorage'=>0);

		if (Xoonips_BeanFactory::chkUserBean()) {
			$usersBean = Xoonips_BeanFactory::getBean('UsersBean', XCUBE_CORE_USER_MODULE_NAME);
			$userFieldManager = User_UserFieldManager::getInstance();
   	 	foreach ($userFieldManager->getFields() as $field) {
    			if ($field->getXmlTag() == 'item_number_limit') {
					$extend = $usersBean->getUserExtend($field->getTableName(), $uid);
    				if (!empty($extend)) {
						$privateItemLimit['itemNumber'] = $extend[0]['value'];
					}
    			} elseif ($field->getXmlTag() == 'item_storage_limit') {
					$extend = $usersBean->getUserExtend($field->getTableName(), $uid);
    				if (!empty($extend)) {
						$privateItemLimit['itemStorage'] = $extend[0]['value'];
					}
    			}
    		}
		}

		return $privateItemLimit;
	}

	/**
	 * count user's items
	 * @param uid
	 * @return boolean
	 */
	public function countUserItems($uid) {
		$userTable = $this->prefix($this->modulePrefix('item_users_link'));
		$sql = 'SELECT count(item_id) as items FROM ' . $userTable . ' WHERE uid=' . $uid
			. ' AND item_id NOT IN (SELECT item_id FROM ' . $this->table
			. ' WHERE certify_state>=' . XOONIPS_CERTIFIED . ')';
		$result = $this->execute($sql);
		if (!$result) return 0;
		$row = $this->fetchArray($result);
		return (is_null($row['items'])) ? 0 : $row['items'];
	}

	/**
	 *get filesize private
	 * @param uid
	 * @return array
	 */
	public function getFilesizePrivate($uid) {
		$fileTable = $this->prefix($this->modulePrefix('item_file'));
		$userTable = $this->prefix($this->modulePrefix('item_users_link'));
		$sql = 'SELECT sum(a.file_size) as sizes FROM ' . $fileTable . ' a, ' . $userTable . ' b'
			. ' WHERE a.item_id=b.item_id AND b.uid=' . $uid
			. ' AND b.item_id NOT IN (SELECT item_id FROM ' . $this->table
			. ' WHERE certify_state>=' . XOONIPS_CERTIFIED . ')';
		$result = $this->execute($sql);
		if (!$result) return 0;
		$row = $this->fetchArray($result);
		return $row['sizes'];
	}

	/**
	 * get itemtype search
	 * @param $itemtype_id
	 * @return array
	 */
	public function getItemtypeSearch($itemtype_id) {
		$items = array();
		$itemTable = $this->prefix($this->modulePrefix('item'));
		$sql = "SELECT item_id FROM $itemTable WHERE item_type_id=$itemtype_id";
		$result = $this->execute($sql);
		if (!$result) return $items;
		while ($row = $this->fetchArray($result)) {
			$items[] = $row['item_id'];
		}
		return $items;
	}

	/**
	 * get itemsubtype search
	 * @param $itemtype_id, $itemsubtype
	 * @return array
	 */
	public function getItemsubtypeSearch($itemtype_id, $itemsubtype) {
		$items = array();
		$itemFieldManager = Xoonips_ItemFieldManagerFactory::getInstance($this->dirname, $this->trustDirname)->getItemFieldManager($itemtype_id);
		$itemFields = $itemFieldManager->getFields();
		$tableName = '';
		$columnName = '';
		foreach ($itemFields as $itemField) {
			if ($itemField->getViewTypeId() == 40) {
				$tableName = $itemField->getTableName();
				$columnName = $itemField->getColumnName();
			}
		}
		if ($tableName == '' || $columnName == '') return $items;

		$table = $this->prefix($tableName);
		$sql = "SELECT DISTINCT item_id FROM $table WHERE $columnName='$itemsubtype'";
		$result = $this->execute($sql);
		if (!$result) return $items;
		while ($row = $this->fetchArray($result)) {
			$items[] = $row['item_id'];
		}
		return $items;
	}

	/**
	 * get index change info
	 * @param int $itemId
	 *         array $checkedIndexes
	 * @return array
	 *              [0]:add index
	 *              [1]:delete index
	 *              [2]:can not edit index
	 *              [][index_id]=message
	 */
	public function getIndexChangeInfo($itemId, $checkedIndexes) {
		$ret = array();
		global $xoopsUser;
		$xoopsUid = $xoopsUser->getVar('uid');
		$indexBean = Xoonips_BeanFactory::getBean('IndexBean', $this->dirname, $this->trustDirname);
		$canViewIndexes = $indexBean->getCanVeiwIndexes($itemId, $xoopsUid);
		$existIndexes = $indexBean->getIndexWithState($itemId, $canViewIndexes);
		$checkIndexes = $indexBean->getIndexesByCheckedIndex($checkedIndexes);
		// check off to on
		foreach ($checkIndexes as $key => $index) {
			// add index
			if (!isset($existIndexes[$key])) {
				$indexId = $index['index_id'];
				$level = $index['open_level'];
				$title = $index['title'];
				if ($level == XOONIPS_OL_PUBLIC) {
					$ret[0][$indexId] = sprintf(_MD_XOONIPS_ITEM_PUBLIC_REQUEST_MESSAGE, $title);
				} elseif ($level == XOONIPS_OL_GROUP_ONLY) {
					$ret[0][$indexId] = sprintf(_MD_XOONIPS_ITEM_GROUP_REQUEST_MESSAGE, $title);
				} elseif ($level == XOONIPS_OL_PRIVATE) {
					if ($index['uid'] == $xoopsUid && $index['parent_index_id'] ==1) {
						$title = 'Private';
					}
					$ret[0][$indexId] = sprintf(_MD_XOONIPS_ITEM_PRIVATE_REGIST_MESSAGE, $title);
				}
			}
		}

		// check on to off
		foreach ($existIndexes as $key => $index) {
			$indexId = $index['index_id'];
			$level = $index['open_level'];
			$title = $index['title'];
			$state = $index['certify_state'];
			// delete index
			if (!isset($checkIndexes[$key])) {
				if ($level == XOONIPS_OL_PUBLIC) {
					if($state == XOONIPS_CERTIFIED) {
						$ret[1][$indexId] = sprintf(_MD_XOONIPS_ITEM_PUBLIC_CANCEL_REQUEST_MESSAGE, $title);
					} elseif ($state == XOONIPS_CERTIFY_REQUIRED) {
						$ret[2][$indexId] = sprintf(_MD_XOONIPS_ITEM_PUBLIC_REQUEST_STOP_MESSAGE, $title);
					}
				} elseif ($level == XOONIPS_OL_GROUP_ONLY) {
					if ($state == XOONIPS_CERTIFIED) {
						$ret[1][$indexId] = sprintf(_MD_XOONIPS_ITEM_GROUP_CANCEL_REQUEST_MESSAGE, $title);
					} elseif ($state == XOONIPS_CERTIFY_REQUIRED) {
						$ret[2][$indexId] = sprintf(_MD_XOONIPS_ITEM_GROUP_REQUEST_STOP_MESSAGE, $title);
					}
				} elseif ($level == XOONIPS_OL_PRIVATE && $state == XOONIPS_NOT_CERTIFIED) {
					if ($index['uid'] == $xoopsUid && $index['parent_index_id'] ==1) {
						$title = 'Private';
					}
					$ret[1][$indexId] = sprintf(_MD_XOONIPS_ITEM_PRIVATE_DELETE_MESSAGE, $title);
				}
			} else {
				if ($level == XOONIPS_OL_PUBLIC && $state == XOONIPS_WITHDRAW_REQUIRED) {
					$ret[2][$indexId] = sprintf(_MD_XOONIPS_ITEM_PUBLIC_CANCEL_REQUEST_STOP_MESSAGE, $title);
				} elseif ($level == XOONIPS_OL_GROUP_ONLY && $state == XOONIPS_WITHDRAW_REQUIRED) {
					$ret[2][$indexId] = sprintf(_MD_XOONIPS_ITEM_GROUP_CANCEL_REQUEST_STOP_MESSAGE, $title);
				}
			}
		}
		return $ret;
	}

    /**
	 *
	 * count activated users
	 *
	 * @param  $isActivate
	 * @return int count
	 */
    public function getCountUsedFieldValue($table, $column, $value) {
		$sql = 'select count(item_id) as cnt from ' . $this->prefix($table) . ' WHERE value=' . Xoonips_Utils::convertSQLStr($value);

   		$result = $this->execute($sql);
		if (!$result) {
			return false;
		}
		$ret = $this->fetchArray($result);

		$this->freeRecordSet($result);
		return $ret['cnt'];
    }

    /**
	 * update index change info
	 * @param int $itemId
	 *         array $checkedIndexes
	 *         int $certify_msg
	 * @return boolean : true/false
	 */
	public function updateIndexChangeInfo($itemId, $checkedIndexes, &$certify_msg) {
		$changeInfo = $this->getIndexChangeInfo($itemId, $checkedIndexes);
		$typeInfo = array();
		$certify = null;
		if (!$this->checkApproval($changeInfo, $typeInfo, $certify, $certify_msg)) {
			return false;
		}
		$linkBean = Xoonips_BeanFactory::getBean('IndexItemLinkBean', $this->dirname, $this->trustDirname);
		$fileBean = Xoonips_BeanFactory::getBean('ItemFileBean', $this->dirname, $this->trustDirname);
		$itemTitleBean = Xoonips_BeanFactory::getBean('ItemTitleBean', $this->dirname, $this->trustDirname);
		$eventLogBean = Xoonips_BeanFactory::getBean('EventLogBean', $this->dirname, $this->trustDirname);
		$notification = new Xoonips_Notification($this->db, $this->dirname, $this->trustDirname);
		Xoonips_Utils::loadMessage($this->dirname);

		// add index
		foreach ($typeInfo as $type) {
			$indexId = $type['indexId'];
			if ($type['type'] == 'add') {
				if ($type['open_level'] == XOONIPS_OL_PUBLIC) {
					if ($certify == 'auto') {
						if (!$linkBean->insert($indexId, $itemId, XOONIPS_CERTIFIED)) return false;
						//event log
						$sendToUsers = array();
						XCube_DelegateUtils::call('Legacy_Workflow.GetAllCertifyUsers', Xoonips_Enum::certifyPublicItems($this->dirname), new XCube_Ref($sendToUsers));
						$notification->itemCertifiedAuto($itemId, $indexId, $sendToUsers);
						$eventLogBean->recordCertifyItemEvent($itemId, $indexId);
					} else {
						if (!$linkBean->insert($indexId, $itemId, XOONIPS_CERTIFY_REQUIRED)) return false;
						$certify_msg = _MD_XOONIPS_ITEM_NEED_TO_BE_CERTIFIED;
						$indexItemLinkInfo = $linkBean->getInfo($itemId, $indexId);
						$indexItemLinkId = $indexItemLinkInfo['index_item_link_id'];
						$certifyName = $itemTitleBean->getItemTitle($itemId);
						$result = array();
						XCube_DelegateUtils::call('Legacy_Workflow.AddItem', new XCube_Ref($result), $certifyName, Xoonips_Enum::certifyPublicItems($this->dirname), $indexItemLinkId);
						if ($result[0] == false) {
							$certify_msg = $result[1];
							return false;
						}
						//event log
						$sendToUsers = array();
						XCube_DelegateUtils::call('Legacy_Workflow.GetCurrentCertifyUsers', Xoonips_Enum::certifyPublicItems($this->dirname), $indexItemLinkId, new XCube_Ref($sendToUsers));
						$notification->itemCertifyRequest($itemId, $indexId, $sendToUsers);
						$eventLogBean->recordRequestCertifyItemEvent($itemId, $indexId);
					}
				} elseif ($type['open_level'] == XOONIPS_OL_GROUP_ONLY) {
					$groupId = $type['groupid'];
					$accept = $type['item_accept'];
					if ($accept == '1') {
						if (!$linkBean->insert($indexId, $itemId, XOONIPS_CERTIFIED)) return false;
						//event log
						$sendToUsers = array();
						XCube_DelegateUtils::call('Legacy_Workflow.GetAllCertifyUsers', Xoonips_Enum::certifyPublicItems($this->dirname), new XCube_Ref($sendToUsers), $groupId);
						$notification->groupItemCertifiedAuto($itemId, $indexId, $groupId, $sendToUsers);
						$eventLogBean->recordCertifyGroupItemEvent($indexId, $itemId);
					} else {
						if (!$linkBean->insert($indexId, $itemId, XOONIPS_CERTIFY_REQUIRED)) return false;
						$certify_msg = _MD_XOONIPS_ITEM_NEED_TO_BE_CERTIFIED;

						$groupName = $type['name'];
						$certifyName = $groupName . ':' . $itemTitleBean->getItemTitle($itemId);
						$indexItemLinkInfo = $linkBean->getInfo($itemId, $indexId);
						$indexItemLinkId = $indexItemLinkInfo['index_item_link_id'];
						$result = array();
						XCube_DelegateUtils::call('Legacy_Workflow.AddItem', new XCube_Ref($result), $certifyName, Xoonips_Enum::certifyGroupItems($this->dirname), $indexItemLinkId);
						if ($result[0] == false) {
							$certify_msg = $result[1];
							return false;
						}
						//event log
						$sendToUsers = array();
						XCube_DelegateUtils::call('Legacy_Workflow.GetCurrentCertifyUsers', Xoonips_Enum::certifyGroupItems($this->dirname), $indexItemLinkId, new XCube_Ref($sendToUsers));
						$notification->groupItemCertifyRequest($itemId, $indexId, $groupId, $sendToUsers);
						$eventLogBean->recordRequestGroupItemEvent($itemId, $indexId);
					}
				} elseif ($type['open_level'] == XOONIPS_OL_PRIVATE) {
					if (!$linkBean->insert($indexId, $itemId, XOONIPS_NOT_CERTIFIED)) return false;
				}
		// delete index
		} elseif ($type['type'] == 'delete') {
			if ($type['open_level'] == XOONIPS_OL_PUBLIC) {
					if ($certify == 'auto') {
						if (!$linkBean->deleteByid($indexId, $itemId)) return false;
						//event log
						$sendToUsers = array();
						XCube_DelegateUtils::call('Legacy_Workflow.GetAllCertifyUsers', Xoonips_Enum::certifyPublicItemsWithdrawal($this->dirname), new XCube_Ref($sendToUsers));
						$notification->itemPublicWithdrawalAuto($itemId, $indexId, $sendToUsers);
						$eventLogBean->recordCertifyItemWithdrawalEvent($itemId, $indexId);
					} else {
						if (!$linkBean->update($indexId, $itemId, XOONIPS_WITHDRAW_REQUIRED)) return false;
						$certify_msg = _MD_XOONIPS_ITEM_NEED_TO_BE_CERTIFIED;
						$certifyName = $itemTitleBean->getItemTitle($itemId);
						$indexItemLinkInfo = $linkBean->getInfo($itemId, $indexId);
						$indexItemLinkId = $indexItemLinkInfo['index_item_link_id'];
						$result = array();
						XCube_DelegateUtils::call('Legacy_Workflow.AddItem', new XCube_Ref($result), $certifyName, Xoonips_Enum::certifyPublicItemsWithdrawal($this->dirname), $indexItemLinkId);
						if ($result[0] == false) {
							$certify_msg = $result[1];
							return false;
						}
						//event log
						$sendToUsers = array();
						XCube_DelegateUtils::call('Legacy_Workflow.GetCurrentCertifyUsers', Xoonips_Enum::certifyPublicItemsWithdrawal($this->dirname), $indexItemLinkId, new XCube_Ref($sendToUsers));
						$notification->itemPublicWithdrawalRequest($itemId, $indexId, $sendToUsers);
						$eventLogBean->recordRequestItemWithdrawalEvent($itemId, $indexId);
					}
				} elseif ($type['open_level'] == XOONIPS_OL_GROUP_ONLY) {
					$groupId = $type['groupid'];
					$accept = $type['item_accept'];
					if ($accept == '1') {
						if (!$linkBean->deleteByid($indexId, $itemId)) return false;
						//event log
						$sendToUsers = array();
						XCube_DelegateUtils::call('Legacy_Workflow.GetAllCertifyUsers', Xoonips_Enum::certifyGroupItemsWithdrawal($this->dirname), new XCube_Ref($sendToUsers), $groupId);
						$notification->groupItemWithdrawalAuto($itemId, $indexId, $groupId, $sendToUsers);
						$eventLogBean->recordCertifyGroupItemWithdrawalEvent($itemId, $indexId);
					} else {
						if (!$linkBean->update($indexId, $itemId, XOONIPS_WITHDRAW_REQUIRED)) return false;
						$certify_msg = _MD_XOONIPS_ITEM_NEED_TO_BE_CERTIFIED;

						$groupName = $type['name'];
						$certifyName = $groupName . ':' . $itemTitleBean->getItemTitle($itemId);
						$indexItemLinkInfo = $linkBean->getInfo($itemId, $indexId);
						$indexItemLinkId = $indexItemLinkInfo['index_item_link_id'];
						$result = array();
						XCube_DelegateUtils::call('Legacy_Workflow.AddItem', new XCube_Ref($result), $certifyName, Xoonips_Enum::certifyGroupItemsWithdrawal($this->dirname), $indexItemLinkId);
						if($result[0]==false){
							$certify_msg = $result[1];
							return false;
						}
						//event log
						$sendToUsers = array();
						XCube_DelegateUtils::call('Legacy_Workflow.GetCurrentCertifyUsers', Xoonips_Enum::certifyGroupItemsWithdrawal($this->dirname), $indexItemLinkId, new XCube_Ref($sendToUsers));
						$notification->groupItemWithdrawalRequest($itemId, $indexId, $groupId, $sendToUsers);
						$eventLogBean->recordRequestGroupItemWithdrawalEvent($itemId, $indexId);
					}
				} elseif ($type['open_level'] == XOONIPS_OL_PRIVATE) {
					if (!$linkBean->deleteByid($indexId, $itemId)) return false;
				}
			}
		}

		// if private index is none, add root private index
		if (!$this->insertRootPrivateIndex($itemId)) return false;

		return true;
	}

	private function checkApproval($changeInfo, &$typeInfo, &$certify, &$certify_msg) {
		$indexBean = Xoonips_BeanFactory::getBean('IndexBean', $this->dirname, $this->trustDirname);
		$groupBean = Xoonips_BeanFactory::getBean('GroupsBean', XCUBE_CORE_USER_MODULE_NAME);
		$configBean = Xoonips_BeanFactory::getBean('ConfigBean', $this->dirname, $this->trustDirname);
		$certify = $configBean->getConfig('certify_item');

		$typeList = array();
		// add index
		if (isset($changeInfo[0])) {
			foreach ($changeInfo[0] as $indexId => $msg) {
				$index = $indexBean->getIndex($indexId);
				if ($index['open_level'] == XOONIPS_OL_PUBLIC) {
					$typeInfo[] = array(
						'type' => 'add',
						'indexId' => $indexId,
						'open_level' => $index['open_level']
					);
					if ($certify != 'auto') {
						$typeId = Xoonips_Enum::certifyPublicItems($this->dirname);
						$typeList[$typeId] = $typeId;
					}
				} elseif ($index['open_level'] == XOONIPS_OL_GROUP_ONLY) {
					$groupId = $index['groupid'];
					$groupInfo = $groupBean->getGroup($groupId);
					if ($groupInfo['item_number_limit'] > 0 && $this->countGroupItems($groupId) >= $groupInfo['item_number_limit']) {
						$certify_msg = _MD_XOONIPS_ITEM_WARNING_ITEM_NUMBER_LIMIT;
						return false;
					}
					if ($groupInfo['item_storage_limit'] > 0 && $fileBean->countGroupFileSizes($groupId) >= $groupInfo['item_storage_limit']) {
						$certify_msg = _MD_XOONIPS_ITEM_WARNING_ITEM_NUMBER_LIMIT;
						return false;
					}
					$accept = $groupInfo['item_accept'];
					$typeInfo[] = array(
						'type' => 'add',
						'indexId' => $indexId,
						'open_level' => $index['open_level'],
						'item_accept' => $accept,
						'groupid' => $groupId,
						'name' => $groupInfo['name']
					);
					if ($accept != '1') {
						$typeId = Xoonips_Enum::certifyGroupItems($this->dirname);
						$typeList[$typeId] = $typeId;
					}
				} else {
					$typeInfo[] = array(
						'type' => 'add',
						'indexId' => $indexId,
						'open_level' => $index['open_level'],
					);
				}
			}
		}

		// delete index
		if (isset($changeInfo[1])) {
			foreach ($changeInfo[1] as $indexId => $msg) {
				$index = $indexBean->getIndex($indexId);
				if ($index['open_level'] == XOONIPS_OL_PUBLIC) {
					$typeInfo[] = array(
						'type' => 'delete',
						'indexId' => $indexId,
						'open_level' => $index['open_level'],
					);
					if ($certify != 'auto') {
						$typeId = Xoonips_Enum::certifyPublicItemsWithdrawal($this->dirname);
						$typeList[$typeId] = $typeId;
					}
				} elseif ($index['open_level'] == XOONIPS_OL_GROUP_ONLY) {
					$groupId = $index['groupid'];
					$groupInfo = $groupBean->getGroup($groupId);
					$accept = $groupInfo['item_accept'];
					$typeInfo[] = array(
						'type' => 'delete',
						'indexId' => $indexId,
						'open_level' => $index['open_level'],
						'item_accept' => $accept,
						'groupid' => $groupId,
						'name' => $groupInfo['name']
					);
					if ($accept != '1') {
						$typeId = Xoonips_Enum::certifyGroupItemsWithdrawal($this->dirname);
						$typeList[$typeId] = $typeId;
					}
				} else {
					$typeInfo[] = array(
						'type' => 'delete',
						'indexId' => $indexId,
						'open_level' => $index['open_level'],
					);
				}
			}
		}

		foreach ($typeList as $type) {
			$result = array();
			XCube_DelegateUtils::call('Legacy_Workflow.CheckApproval', new XCube_Ref($result), $type);
			if ($result[0] == false) {
				$certify_msg = $result[1];
				return false;
			}
		}
		return true;
	}

	// insert root private index
	private function insertRootPrivateIndex($itemId) {
		$itemUsersBean = Xoonips_BeanFactory::getBean('ItemUsersLinkBean', $this->dirname, $this->trustDirname);
		$linkBean = Xoonips_BeanFactory::getBean('IndexItemLinkBean', $this->dirname, $this->trustDirname);
		$usersObj = $itemUsersBean->getItemUsersInfo($itemId);
		foreach ($usersObj as $user) {
			if (!$linkBean->Link2UserRootIndex($itemId, $user['uid'])) return false;
		}
		return true;
	}

	/**
	 * can item edit
	 * @param int $itemId, int $uid
	 * @return boolean : true/false
	 */
	public function canItemEdit($itemId, $uid) {
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', XCUBE_CORE_USER_MODULE_NAME);
		$isModerator = $userBean->isModerator($uid);
		$itemUsersBean = Xoonips_BeanFactory::getBean('ItemUsersLinkBean', $this->dirname, $this->trustDirname);
		$isItemUser = $itemUsersBean->isLink($itemId, $uid);
		if (!$isItemUser && !$isModerator) return false;

		$bean = Xoonips_BeanFactory::getBean('IndexItemLinkBean', $this->dirname, $this->trustDirname);
		$result = $bean->getIndexItemLinkInfo($itemId);
		if ($result) {
			foreach ($result as $link) {
				if ($link['certify_state'] == XOONIPS_CERTIFY_REQUIRED || $link['certify_state'] == XOONIPS_WITHDRAW_REQUIRED) {
					return false;
				}
				if ($link['certify_state'] == XOONIPS_CERTIFIED && !$isModerator) {
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * can item users edit
	 * @param int $itemId, int $uid
	 * @return boolean : true/false
	 */
	public function canItemUsersEdit($itemId, $uid) {
		if (!Xoonips_BeanFactory::chkUserBean()) return false;

		$userBean = Xoonips_BeanFactory::getBean('UsersBean', XCUBE_CORE_USER_MODULE_NAME);
		$isModerator = $userBean->isModerator($uid);
		$itemUsersBean = Xoonips_BeanFactory::getBean('ItemUsersLinkBean', $this->dirname, $this->trustDirname);
		$isItemUser = $itemUsersBean->isLink($itemId, $uid);
		if (!$isItemUser && !$isModerator) return false;

		$bean = Xoonips_BeanFactory::getBean('IndexItemLinkBean', $this->dirname, $this->trustDirname);
		$result = $bean->getIndexItemLinkInfo($itemId);
		if ($result) {
			foreach ($result as $link) {
				if ($link['certify_state'] == XOONIPS_CERTIFY_REQUIRED || $link['certify_state'] == XOONIPS_WITHDRAW_REQUIRED) {
					return false;
				}
				if ($link['certify_state'] == XOONIPS_CERTIFIED && !$isModerator && !$isItemUser) {
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * can item index edit
	 * @param int $itemId, int $uid
	 * @return boolean : true/false
	 */
	public function canItemIndexEdit($itemId, $uid) {
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', XCUBE_CORE_USER_MODULE_NAME);
		$isModerator = $userBean->isModerator($uid);
		$itemUsersBean = Xoonips_BeanFactory::getBean('ItemUsersLinkBean', $this->dirname, $this->trustDirname);
		$isItemUser = $itemUsersBean->isLink($itemId, $uid);

		$linkBean = Xoonips_BeanFactory::getBean('IndexItemLinkBean', $this->dirname, $this->trustDirname);
		$links = $linkBean->getIndexItemLinkInfo( $itemId );
		$indexBean = Xoonips_BeanFactory::getBean('IndexBean', $this->dirname, $this->trustDirname);
		$visible = false;
		if ($links) {
			foreach ($links as $link) {
				$indexInfo = $indexBean->getIndex($link['index_id']);
				if ($link['certify_state'] == XOONIPS_NOT_CERTIFIED) {
					if ($isModerator || $isItemUser) {
						$visible = true;
					}
				} elseif ($link['certify_state'] == XOONIPS_CERTIFY_REQUIRED || $link['certify_state'] == XOONIPS_CERTIFIED || $link['certify_state'] == XOONIPS_WITHDRAW_REQUIRED) {
					if ($indexInfo['open_level'] == XOONIPS_OL_PUBLIC){
						if ($isModerator || $isItemUser) {
							$visible = true;
						}
					} elseif ($indexInfo['open_level'] == XOONIPS_OL_GROUP_ONLY) {
						$isGroupManager = $userBean->isGroupManager($indexInfo['groupid'], $uid);
						if ($isModerator || $isItemUser || $isGroupManager) {
							$visible = true;
						}
					}
				}
			}
		}
		return $visible;
	}

	/**
	 * can item delete
	 * @param int $itemId, int $uid
	 * @return boolean : true/false
	 */
	public function canItemDelete($itemId, $uid) {
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', XCUBE_CORE_USER_MODULE_NAME);
		$isModerator = $userBean->isModerator($uid);
		$itemUsersBean = Xoonips_BeanFactory::getBean('ItemUsersLinkBean', $this->dirname, $this->trustDirname);
		$isItemUser = $itemUsersBean->isLink($itemId, $uid);
		if (!$isItemUser && !$isModerator) return false;

		$linkTable = $this->prefix($this->modulePrefix('index_item_link'));
		$sql = "SELECT index_id FROM $linkTable WHERE item_id=$itemId AND certify_state>" . XOONIPS_NOT_CERTIFIED;
		$result = $this->execute($sql);
		if ($result && $this->getRowsNum($result) > 0) {
			return false;
		}
		return true;
	}

	/**
	 * can item export
	 *
	 * @param int $itemId, int $uid
	 * @return boolean : true/false
	 */
	public function canItemExport($itemId, $uid) {
		$userBean = Xoonips_BeanFactory::getBean('UsersBean', XCUBE_CORE_USER_MODULE_NAME);
		$isModerator = $userBean->isModerator($uid);
		$itemUsersBean = Xoonips_BeanFactory::getBean('ItemUsersLinkBean', $this->dirname, $this->trustDirname);
		$isItemUser = $itemUsersBean->isLink($itemId, $uid);
		if (!$isItemUser && !$isModerator) return false;

		$indexBean = Xoonips_BeanFactory::getBean('IndexBean', $this->dirname, $this->trustDirname);

		// Check Public Index
		if(!$isModerator && $indexBean->isLinked2PublicItem($itemId)){
			return false;
		}

		return true;
	}

}
?>
