<?php
/**
 * 部门模型 - 数据对象模型
 * @author jason <yangjs17@yeah.net>
 * @version TS3.0
 */
class DepartmentModel extends Model {

	const FIELD_ID = 34;					// 部门的字段ID
	const FIELD_KEY = 'department';			// 部门的字段KEY

	protected $tableName = 'department';
	protected $fields = array(0=>'department_id',1=>'title',2=>'parent_dept_id',3=>'display_order',4=>'ctime');

	protected $treeDo;  					// 分类树模型
	
	/**
	 * 初始化方法，生成部门的树形对象模型
	 * @return void
	 */
	public function _initialize() {
		$field = array('id'=>'department_id','name'=>'title','pid'=>'parent_dept_id','sort'=>'display_order');
		tsload(ADDON_PATH.'/model/CateTreeModel');
		$this->treeDo = new CateTreeModel('department');
		$this->treeDo->setField($field);
	}

	/**
	 * 获取部门信息的树形结构
	 * @param integer $pid 父级ID，默认为0
	 * @return array 部门信息的树形结构
	 */
	public function getDepartment($pid = 0) {
		$data = $this->treeDo->getTree($pid);
		return $data;
	}

	/**
	 * 获取部门全部分类的Hash数组
	 * @return array 部门分类的Hash数组
	 */
	public function getAllHash() {
		return $this->treeDo->getAllHash();
	}

	/**
	 * 获取指定子树的部门Hash数组
	 * @param integer $pid 父级ID
	 * @param integer $sid 资源节点ID
	 * @param integer $nosid 是否包含资源节点ID，默认为0
	 * @return array 指定子树的部门Hash数组
	 */
	public function getHashDepartment($pid = 0, $sid = '', $nosid = 0) {
		$treeHash 	=$this->treeDo->getAllHash();
		$pid ==0 && $optHash[0] = L('PUBLIC_TOP_DEPARTMENT') ;			// 顶级部门
		foreach($treeHash as $k => $v) {
			if($nosid == 1 && !empty($sid) && $k == $sid) {
				continue;
			}
			$v['parent_dept_id'] == $pid && $optHash[$k] = $v['title'];
		}
		return $optHash;
	}

	/**
	 * 清除部门缓存
	 * @return void
	 */
	public function cleanCache() {
		return $this->treeDo->cleanCache();
	}

	/**
	 * 添加一个部门信息
	 * @param array $data 新部门相关信息
	 * @return boolean 是否添加成功
	 */
	public function addDepart($data) {
		if(empty($data)) {
			return false;
		}
		if(empty($data['title'])) {
			return false;
		}
		// 添加部门操作
		$add['title'] = t($data['title']);
		$add['parent_dept_id'] = $this->_getParent_dept($data);
		$add['display_order'] = isset($data['display_order'])  && !empty($data['display_order'])? $data['display_order'] : 255;
		$add['ctime'] = time();

		if($this->add($add)) {
			$this->cleanCache();
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 获取指定分类的上级ID
	 * @param array $data 指定分类的相关数据
	 * @return integer 指定分类的上级ID
	 */
	public function _getParent_dept($data) {
		$pid = $data['parent_dept_id'];
		if(!empty($data['_parent_dept_id'])) {
			$level = count($data['_parent_dept_id']);
			$_P = $data['_parent_dept_id'][$level-2] ?  $data['_parent_dept_id'][$level - 2] : $pid;
			$pid = $data['_parent_dept_id'][$level-1] > 0 ? $data['_parent_dept_id'][$level - 1] : $_P;
		}

		return intval($pid);
	}

	/**
	 * 删除指定部门操作
	 * @param integer $id 指定分类ID
	 * @param integer $pid 父级分类ID
	 * @return boolean 是否删除成功
	 */
	public function delDepart($id, $pid = 0) {
		if(empty($id)) {
			return false;
		}
		// 如果子部门不是移动到顶级下面，则判断是否移动到自己子集下面
		if($pid != 0) {	
			$data = $this->treeDo->getChildHash($id);
			if(in_array($pid, $data)) {
				return false;
			}
		}
		$map = array();
		$map['department_id'] = $id;
		// 获取子节点
		$tree = $this->treeDo->getTree($id);
		// 移动子节点 
		if(!empty($tree['_child'])) {
			foreach ($tree['_child'] as $c) {
				$this->moveDepart($c['department_id'],$pid);
			}
		}
		// 移动当前部门用户到新的部门
		$oldTreeName = $this->getTreeName($id);
		$newTreeName = $this->getTreeName($pid);
		$this->editUserProfile($oldTreeName,$newTreeName);
		// 修改当前部门下用户的部门关联表信息
		$ids = $this->getTreeId($pid);
		$this->updateUserDepart(implode('|', $newTreeName)."|",$ids);

		if($this->where($map)->delete()){
			$this->editUserProfile();
			// 移动子集
			$upmap = array();
			$upmap['parent_dept_id'] = $id;
			$save['parent_dept_id']  = $pid;
			$this->where($upmap)->save($save);
			
			$fieldids = D('user_profile_setting')->where("form_type='selectDepart'")->field('field_id')->findAll();
			$fids = getSubByKey( $fieldids , 'field_id' );
			$profilemap['field_data'] = $id;
			$profilemap['field_id'] = array( 'in' , $fids );
			D('user_profile')->setField('field_data',$pid,$profilemap);
			
			$this->cleanCache();
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 移动部门，将某个部门移动到新部门下面
	 * @param integer $id 预移动部门ID
	 * @param integer $pid 移动到的父级ID
	 * @return boolean 是否移动成功
	 */
	public function moveDepart($id, $pid = 0) {
		if(empty($id)) {
			$this->error = L('PUBLIC_DEPARTMENT_ID_REQUIRED');			// 部门ID不能为空
			return false;
		}
		// 如果子部门不是移动到顶级下面，则判断是否移动到自己子集下面
		if($pid != 0) {	
			$data = $this->treeDo->getChildHash($id);
			if(in_array($pid, $data)) {
				return false;
			}
		}
		$map = array();
		$map['department_id'] = $id;
		$save['parent_dept_id']  = $pid;
		$oldTreeName = $this->getTreeName($id);
		
		if($this->where($map)->save($save)) {
			$curName = $oldTreeName[count($oldTreeName) - 1];
			$newtreeName = array();
			if($pid != 0) {
				$newTreeName = $this->getTreeName($pid);	
			}
			$newTreeName[] = $curName; 
			$this->cleanCache();
			// 替换用户字段表的冗余数据
			$this->editUserProfile($oldTreeName, $newTreeName);
			// 更新部门关联表数据
			$ids = $this->getTreeIdBySql($id);
			$this->updateUserDepart(implode('|', $newTreeName)."|",$ids);
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 获取多个用户的部门信息
	 * @param array $uids 用户ID数组
	 * @return array 多个用户的部门信息
	 */
	public function getUserDepart($uids) {
		!is_array($uids) && $uids = explode(',', $uids);
		if(empty($uids)) {
			return array();
		}
		$map['uid'] = array('IN', $uids);
		$map['field_id'] = self::FIELD_ID;
		return D('user_profile')->where($map)->getHashList('uid', 'field_data');
	}

	/**
	 * 获取指定用户的部门ID
	 * @param integer $uid 用户ID
	 * @return integer 指定用户的部门ID
	 */
	public function getUserDepartId($uid) {
		$department = $this->getUserDepart($uid);
		$d = explode('|', trim($department[$uid], '|'));
		$map['a.title'] = end($d);
		$map['b.uid'] = $uid; 
		
		$departmentInfo = $this->table($this->tablePrefix.'department AS a LEFT JOIN '.$this->tablePrefix.'user_department AS b ON a.department_id = b.department_id')
						  	   ->where($map)
						  	   ->find();
						
		return $departmentInfo['department_id'];						  
	}

	/**
	 * 更新部门为departMentTree的用户的关联表信息 
	 * @param string $treeName 树结构的名称
	 * @param array $departmentIds 部门ID数组
	 * @return void
	 */
	public function updateUserDepart($treeName, $departmentIds) {
		if(empty($treeName) && empty($departmentIds)) {
			return false;	
		}
		$sql = "DELETE FROM {$this->tablePrefix}user_department 
				WHERE uid IN (
						SELECT uid FROM {$this->tablePrefix}user_profile WHERE field_id ='".self::FIELD_ID."' AND field_data = '{$treeName}')";	

		$this->query($sql);

		foreach($departmentIds as $id) {
			$sql = "INSERT INTO {$this->tablePrefix}user_department 
				SELECT uid,{$id} AS department_id FROM {$this->tablePrefix}user_profile WHERE field_id ='".self::FIELD_ID."' AND field_data = '{$treeName}' ";
			
			$this->query($sql);
		}
	}

	/**
	 * 更新指定用户的部门信息
	 * @param integer $uid 用户ID
	 * @param integer $newDepartmentId 新的部门ID
	 * @return void
	 */
	public function updateUserDepartById($uid, $newDepartmentId) {
		if(empty($uid) || empty($newDepartmentId)) {
			return false;
		}
		$departmentTree = $this->getTreeName($newDepartmentId);
		$departmentIds = $this->getTreeId($newDepartmentId);
		if(empty($departmentIds)) {
			return false;
		}
		// TODO:后期事务处理
		$up['uid'] = $uid;
		$up['field_id'] = self::FIELD_ID;
		if(D('user_profile')->where($up)->count() > 0) {
			$sp['field_data'] = implode("|", $departmentTree)."|";
			D('user_profile')->where($up)->save($sp);
		} else {
			$up['field_data'] = implode("|", $departmentTree)."|";
			D('user_profile')->add($up);
		}
		
		// 修改用户部门关联表数据
		$ud['uid'] = $uid;
		D('user_department')->where($ud)->delete();
		$sql = "INSERT INTO {$this->tablePrefix}user_department (uid,department_id) VALUES ";

		foreach($departmentIds as $department_id) {
			$sql .= "({$uid},{$department_id}),";
		}

		return $this->query(trim($sql,','));
	}

	/**
	 * 根据部门ID获取该部门的路径
	 * @param integer $id 部门ID
	 * @param array $names 部门名称
	 * @return array 返回部门路径名称数组
	 */
	public function getTreeName($id, $names = array()) {
		return array_reverse($this->_getTreeName($id, $names));
	}

	/**
	 * 递归方法获取父级部门名称
	 * @param integer $id 部门ID
	 * @param array $names 部门名称
	 * @return array 返回部门路径名称数组
	 */
	private function _getTreeName($id,$names){
		$data = $this->treeDo->getTree($id);
		$names[] = $data['title'];
		if($data['parent_dept_id'] !=0){
			return $this->_getTreeName($data['parent_dept_id'],$names);
		}
		return $names;
	}

	/**
	 * 获取从顶级到该级的父亲节点数组
	 * @param integer $id 当前节点的ID
	 * @param array $ids 附加的节点ID
	 * @return array 从顶级到该级的父亲节点数组
	 */
	public function getTreeId($id, $ids = array()) {
		$ids[] = $id;
		$data = $this->treeDo->getTree($id);
		if($data['parent_dept_id'] == 0) {
			return $ids;
		}

		return $this->getTreeId($data['parent_dept_id'],$ids);
	}

	/**
	 * 获取从顶级到该级的父亲节点数组，查询数据库
	 * @param integer $id 当前节点的ID
	 * @param array $ids 附加的节点ID
	 * @return array 从顶级到该级的父亲节点数组
	 */
	public function getTreeIdBySql($id,$ids=array()){
		$ids[] = $id;
		$map['department_id'] = $id;
		$data = $this->where($map)->find();
		if($data['parent_dept_id'] == 0){
			return $ids;
		}

		return $this->getTreeIdBySql($data['parent_dept_id'], $ids);
	}

	/**
	 * 批量修改部门名字，需要传入旧部门名称Tree和新名称Tree数组
	 * @param array $oldTreeName 旧部门名称Tree
	 * @param array $newTreeName 新部门名称Tree
	 * @return mix 修改失败返回false，修改成功返回1
	 */
	public function  editUserProfile($oldTreeName, $newTreeName) {
		$old = implode('|', $oldTreeName)."|";
		$new = implode('|',$newTreeName)."|";
		$sql = "UPDATE `{$this->tablePrefix}user_profile` SET field_data = REPLACE(field_data,'{$old}','{$new}') WHERE field_id = ".self::FIELD_ID;

		return $this->query($sql);
	}

	/**
	 * 测试使用
	 * @return string 插入数据的SQL语句
	 */
	public function initDepartMent() {
		// 将用户放到第一个部门下
		$data = $this->treeDo->getTree(0);
		$departName = $data['_child'][0]['title'].'|';
		$departId =$data['_child'][0]['department_id'];
		$sql = "INSERT INTO {$this->tablePrefix}user_profile SELECT uid,".self::FIELD_ID." AS field_id,'{$departName}' AS field_data,0 AS privacy FROM {$this->tablePrefix}user";
		echo $sql;
		$this->query($sql);
		$sql = "INSERT INTO {$this->tablePrefix}user_department SELECT uid,{$departId} AS department_id FROM {$this->tablePrefix}user";
		$this->query($sql);	
		echo $sql;
	}
}
