<?php
defined('WEKIT_VERSION') || exit('Forbidden');

Wind::import('SRV:forum.dm.PwForumDm');
Wind::import('SRV:forum.bo.PwForumBo');
Wind::import('SRV:forum.PwForum');

/**
 * 版块公共服务
 *
 * @author Jianmin Chen <sky_hold@163.com>
 * @license http://www.phpwind.com
 * @version $Id: PwForumService.php 24758 2013-02-20 06:55:42Z jieyin $
 * @package forum
 */

class PwForumService {
	
	protected static $_forums = null;
	protected static $_map = null;
	
	/**
	 * 获取版块列表
	 *
	 * @return array
	 */
	public function getForumList() {
		isset(self::$_forums) || self::$_forums = $this->_getForum()->getForumList();
		return self::$_forums;
	}
	
	/**
	 * 获取用户所有可以访问的版块列表
	 *
	 * @param PwUserBo $user
	 * @return array
	 */
	public function getAllowVisitForum(PwUserBo $user, $forums = null) {
		$forums === null && $forums = $this->getForumList();
		$fids = array();
		foreach ($forums as $key => $value) {
			if (!$value['allow_visit'] || $user->inGroup(explode(',', $value['allow_visit']))) {
				$fids[] = $value['fid'];
			}
		}
		return $fids;
	}
	
	/**
	 * 获取用户所有禁止访问的版块列表
	 *
	 * @param PwUserBo $user
	 * @param array $forums 版块列表
	 * @param bool $includeHide 是否包含隐藏版块
	 * @return array
	 */
	public function getForbidVisitForum(PwUserBo $user, $forums = null, $includeHide = false) {
		$forums === null && $forums = $this->getForumList();
		$fids = array();
		foreach ($forums as $key => $value) {
			if ($value['allow_visit'] && !$user->inGroup(explode(',', $value['allow_visit']))) {
				$fids[] = $value['fid'];
			} elseif ($includeHide && $value['isshow'] == 0) {
				$fids[] = $value['fid'];
			}
		}
		return $fids;
	}
	
	/**
	 * 获取指定版块的信息（使用全部版块缓存，如果没有这个前提，直接使用 forum.PwForum->fetchForum 接口比较合算）
	 *
	 * @param array $fids;
	 * @return array
	 */
	public function fetchForum($fids) {
		return Pw::subArray($this->getForumList(), $fids);
	}

	/**
	 * 获取版块层级列表
	 *
	 * @return array
	 */
	public function getForumMap() {
		if (!isset(self::$_map)) {
			$forums = $this->getForumList();
			foreach ($forums as $key => $value) {
				self::$_map[$value['parentid']][] = $value;
			}
		}
		return self::$_map;
	}
	
	/**
	 * 获取分类和版块列表（子版除外）
	 *
	 * @return array
	 */
	public function getCommonForumList($fetchmode = PwForum::FETCH_MAIN) {
		$forumdb = array(0 => array());
		$forumList = $this->_getForum()->getCommonForumList($fetchmode);
		foreach ($forumList as $forums) {
			if (!$forums['isshow']) continue;
			if ($forums['type'] === 'forum') {
				$forumdb[$forums['parentid']][$forums['fid']] = $forums;
			} elseif ($forums['type'] === 'category') {
				$forumdb[0][$forums['fid']] = $forums;
			}
		}
		return $forumdb;
	}
	
	/**
	 * 根据层级列表，递归获取链级列表
	 *
	 * @param int $parentid 获取该版的所属
	 * @param array $map 版块层级列表
	 * @return array
	 */
	public function getForumsByLevel($parentid, $map) {
		if (!isset($map[$parentid])) return array();
		$length = count($map[$parentid]);
		$array = array();
		foreach ($map[$parentid] as $key => $value) {
			if ($key == $length-1) $value['isEnd'] = 1;
			$array[] = $value;
			$array = array_merge($array, $this->getForumsByLevel($value['fid'], $map));
		}
		return $array;
	}
	
	/**
	 * 根据层级列表，递归获取链级列表
	 *
	 * @param int $parentid 获取该版的所属
	 * @param array $map 版块层级列表
	 * @return array
	 */
	public function findOptionInMap($parentid, $map, $lang = array()) {
		if (!isset($map[$parentid])) return array();
		$result = array();
		foreach ($map[$parentid] as $key => $value) {
			$result[$value['fid']] = $lang[$value['type']] . $value['name'];
			$result += $this->findOptionInMap($value['fid'], $map, $lang);
		}
		return $result;
	}
	
	/**
	 * 获取版块的select/option
	 *
	 * @param mixed $selected 选中的fid序列
	 * @return string option的html
	 */
	public function getForumOption($selected = array()) {
		is_array($selected) || $selected = array($selected);
		$map = $this->getForumMap();
		$option_html = '';
		$option_arr = $this->findOptionInMap(0, $map, array(
			'category' => '&gt;&gt; ',
			'forum' => ' &nbsp;|- ',
			'sub' => ' &nbsp; &nbsp;|-  ',
			'sub2' => '&nbsp;&nbsp; &nbsp; &nbsp;|-  '
		));
		foreach ($option_arr as $key => $value) {
			$option_html .= '<option value="' . $key . '"' . (in_array($key, $selected) ? ' selected' : '') . '>' . strip_tags($value) . '</option>';
		}
		return $option_html;
	}
	
	/**
	 * 获取上级版块id序列
	 *
	 * @param int $fid 版块id
	 * @return array
	 */
	public function getParentFids($fid) {
		$forums = $this->getForumList();
		$upfids = array();
		$fid = $forums[$fid]['parentid'];
		while (in_array($forums[$fid]['type'], array('sub2','sub','forum'))) {
			$upfids[] = $fid;
			$fid = $forums[$fid]['parentid'];
		}
		return $upfids;
	}
	
	/** 
	 * 获取分类id
	 *
	 * @param int $fid
	 * @return int
	 */
	public function getCateId($fid) {
		$forum = $this->_getForum()->getForum($fid);
		if ($forum['type'] == 'category') return $fid;
		$array = explode(',', $forum['fup']);
		return array_pop($array);
	}
	
	/**
	 * 获取用户加入的版块列表
	 *
	 * @param int $uid
	 * @return array
	 */
	public function getJoinForum($uid) {
		if ($result = Wekit::load('forum.PwForumUser')->getFroumByUid($uid)) {
			$array = array();
			$tmp = Wekit::load('forum.PwForum')->fetchForum(array_keys($result));
			foreach ($tmp as $key => $value) {
				$array[$value['fid']] = $value['name'];
			}
			return $array;
		}
		return array();
	}

	/**
	 * 重新统计本版及上级版块的帖子统计数
	 *
	 * @param mixed $forum (int fid | object PwForumBo)
	 * @return void
	 */
	public function updateForumStatistics($forum) {
		if (!$forum instanceof PwForumBo) {
			$forum = new PwForumBo($forum);
		}
		if (!$forum->isForum()) return false;
		$service = $this->_getForum();
		$service->updateForumStatistics($forum->fid);
		if ($fids = $forum->getParentFids()) {
			foreach ($fids as $fid) {
				$service->updateForumStatistics($fid);
			}
		}
	}

	/**
	 * 更新版块帖子统计数
	 *
	 * @param mixed $forum int 版块fid | object PwForumBo
	 * @param int $topic 主题更新数
	 * @param int $replies 回复更新数
	 * @param int $tpost 今日发帖更新数
	 * @param int $lastinfo 
	 * @return void
	 */
	public function updateStatistics($forum, $topic, $replies, $tpost = 0, $lastinfo = array()) {
		if (!$forum instanceof PwForumBo) {
			$forum = new PwForumBo($forum);
		}
		if (!$forum->isForum()) return false;
		$article = $topic + $replies;
		$dm = new PwForumDm($forum->fid);
		$dm->addThreads($topic)->addPosts($replies)->addArticle($article)->addTodayPosts($tpost);
		if ($lastinfo) {
			!isset($lastinfo['time']) && $lastinfo['time'] = Pw::getTime();
			$dm->setLastpostInfo($lastinfo['tid'], Pw::substrs($lastinfo['subject'], 26, 0, true), $lastinfo['username'], $lastinfo['time']);
		}
		$service = $this->_getForum();
		$service->updateForum($dm, PwForum::FETCH_STATISTICS);

		if ($fids = $forum->getParentFids()) {
			$dm = new PwForumDm(true);
			$dm->addArticle($article)->addSubThreads($topic)->addTodayPosts($tpost);
			if ($lastinfo && $forum->isOpen()) {
				$dm->setLastpostInfo($lastinfo['tid'], Pw::substrs($lastinfo['subject'], 26, 0, true), $lastinfo['username'], $lastinfo['time']);
			}
			$service->batchUpdateForum($fids, $dm, PwForum::FETCH_STATISTICS);
		}
		return true;
	}

	protected function _getForum() {
		return Wekit::load('forum.PwForum');
	}
}