<?php
!defined('M_P') && exit('Forbidden');
require_once (M_P . 'lib/base/module.class.php');

/**
 * 文章相關的會話bean
 * @author xiejin
 *
 */
class PW_ArticleModule extends PW_Module {
	var $PAGECUT = '[###page###]'; //分頁符

	var $articleId;
	var $subject;
	var $descrip;
	var $author;
	var $user;
	var $userId;
	var $jumpUrl;
	var $fromInfo;
	var $fromUrl;
	var $columnId;
	var $ifcheck;
	var $postDate;
	var $modifyDate;
	var $ifAttach;
	var $sourceType;
	var $sourceId;
	var $hits;
	var $relate = array();

	var $pageCount;
	var $content;
	var $attach = array();
	var $_filterUitil;

	function __construct() {
		parent::__construct();
		$this->_filterUitil = L::loadClass('FilterUtil', 'filter');
	}

	function PW_ArticleModule() {
		$this->__construct();
	}

	/**
	 * 設置文章 主題
	 * @param string $subject
	 */
	function setSubject($subject) {
		if (empty($subject)) {
			$this->addError('文章<span class=\'s1\'>標題</span>不能為空');
		}
		if (strlen($subject) > 80) {
			$this->addError('文章<span class=\'s1\'>標題</span>長度不能大于<span class=\'s1\'>80</span>字節');
		}
		if( ($bword = $this->_filterUitil->comprise($subject)) &&  $GLOBALS['iscontinue'] != 1 ){ 
			$this->addError("文章<span class='s1'>標題</span>中含有敏感詞︰<span class='s1'>" . $bword . "</span>，禁止發表，請返回修改");
		}
		$this->subject = $this->_filterUitil->convert($subject);
		/*$this->subject = pwHtmlspecialchars_decode($subject);  bug fix 入庫前替換？2011-9-30*/
	}

	/**
	 * 設置文章內容
	 * @param string $content
	 * @param int $page
	 */
	function setContent($content, $page = 0) {
		if (empty($content)) {
			$this->addError('文章<span class=\'s1\'>內容</span>不能為空');
		}
		if (strlen($content) > 50000) {
			$this->addError('文章<span class=\'s1\'>內容</span>過大');
		}
		if( ($bword = $this->_filterUitil->comprise($content)) &&  $GLOBALS['iscontinue'] != 1) {
			$this->addError("文章內容中含有敏感詞︰<span class='s1'>" . $bword . "</span>，禁止發表，請返回修改");
		}
		$content = $this->_filterUitil->convert($content);
		$content = htmlspecialchars($content);
		//$content = html_check($content);
		foreach (array('wmv', 'rm', 'flash') as $key => $value) {
			if (strpos(",{$GLOBALS['_G']['media']},", ",$value,") === false) {
				$content = preg_replace("/(\[$value=([0-9]{1,3}\,[0-9]{1,3}\,)?)1(\].+?\[\/$value\])/is", "\${1}0\\3", $content);
			}
		}
		$content = preg_replace(array("/<script.*>.*<\/script>/is", "/<(([^\"']|\"[^\"]*\"|'[^']*')*?)>/eis",
			"/javascript/i"), array("", "\$this->_jscv('\\1')", "java script"), str_replace('.', '&#46;', $content));
		$this->content = $this->_cookContentByPage($content, $page);
	}

	/**
	 * 過濾javascript代碼
	 * @param string $code
	 */
	function _jscv($code) {
		$code = str_replace('\\"','"',$code);
		$code = preg_replace('/[\s]on[\w]+\s*=\s*(\\\"|\\\\\').+?\\1/is',"",$code);
		$code = preg_replace("/[\s]on[\w]+\s*=[^\s]*/is","",$code);
		return '<'.$code.'>';
	}

	/**
	 * 設置文章摘要
	 * @param string $descrip
	 */
	function setDescrip($descrip) {
		if( ($bword = $this->_filterUitil->comprise( $descrip ))  &&  $GLOBALS['iscontinue'] != 1) {
			$this->addError("文章<span class='s1'>摘要</span>中包含禁用敏感詞︰<span class='s1'>" . $bword. "</span>，禁止發表，請返回修改");
		 } 
		$descrip = $this->_filterUitil->convert( $descrip );
		if (empty($descrip)) {
			$descrip = substrs($this->_filterWindCode(), 200);
		}
		if (strlen($descrip) > 255) {
			$this->addError('<span class=\'s1\'>描述</span>內容不能大于<span class=\'s1\'>255</span>字節');
		}
		$this->descrip = $descrip;
	}

	function _filterWindCode(){
		return trim(str_replace(array($this->PAGECUT,'\[s:[0-9]*\]'),'',stripWindCode(strip_tags($this->content))),' ');
	}

	/**
	 * 設置文章所屬欄目ID
	 * @param int $channelId
	 */
	function setColumnId($columnId) {
		$columnId = (int) $columnId;
		if (!$columnId) {
			$this->addError('沒有選擇<span class=\'s1\'>欄目<span>');
		}
		$this->columnId = $columnId;
	}

	/**
	 * 設置相關文章
	 * @param array $relate
	 * @return string
	 */
	function setRelate($relate) {
		if (!$relate['subject'] && !$relate['url']) {return false;}
		$temp = array();
		foreach ($relate['subject'] as $key => $value) {
			if ($value && $relate['url'][$key] && $this->_checkUrl($relate['url'][$key])) {
				$temp[] = array('subject' => $value, 'url' => $relate['url'][$key]);
			}
		}
		$this->relate = $temp;
	}

	/**
	 * 設置附件
	 * @param array $oldatt_desc
	 * @param array $keep
	 */
	function setAttach($flashatt, $oldatt_desc = array()) {
		global $db_allowupload, $_G;
		$attachs = $this->attach ? $this->attach : array();
		$attachs = $this->_cookOldAttachs($attachs, $oldatt_desc);
		C::loadClass('articleupload', 'upload', false);
		$uploaddb = array();
		if ($db_allowupload && $_G['allowupload'] && (PwUpload::getUploadNum() || $flashatt)) {
			$articleUpload = new ArticleUpload();
			$articleUpload->setFlashAtt($flashatt, intval($_POST['savetoalbum']), intval($_POST['albumid']));
			PwUpload::upload($articleUpload);
			$uploaddb = $articleUpload->getAttachs();
		}
		$this->attach = (array)$attachs + (array)$uploaddb;
	}

	/**
	 * 獲取某分頁文章內容
	 * @param $page
	 */
	function getPageContent($page = 1) {
		if ($page === 'add') return '';
		if ($page === 'all') return $this->content;
		$page = (int) $page;
		$contents = $this->_explodeContent();
		$key = $page - 1;
		if (isset($contents[$key])) {
			return count($contents) > 1 ? $this->autoCloseTags($contents[$key]) : $contents[$key];
		}
		$this->addError('分頁數有誤');
	}

	/**
	 * 自動補全ubb
	 * @param $content
	 */
	function autoCloseTags($content) {
		$openTags = array('paragraph', 'hr', 'attachment', 's');
		//$closeTags = array('code', 'payto', 'list', 'u', 'b', 'i', 'li', 'sub', 'sup', 'strike', 'blockquote', 'backcolor', 'color', 'font', 'size', 'align', 'email', 'glow', 'img', 'music', 'url', 'fly', 'move', 'post', 'hide', 'sell', 'quote', 'flash', 'table', 'wmv', 'mp3', 'rm', 'iframe');
		preg_match_all('/\[([a-z]+)[^\]]*\]/i', $content, $result);
		$startTags = $result[1];
		preg_match_all('/\[\/([^\]]+)\]/i', $content, $result);
		$endTags = $result[1];
		list($startTagsLength, $startCountNum, $endCountNum) = array(count($startTags), array_count_values($startTags), array_count_values($endTags));
		if (count($endTags) == $startTagsLength) return $content;

		$startTags = array_reverse($startTags);
		for ($i = 0; $i < $startTagsLength; $i++) {
			if (in_array($startTags[$i], $openTags) || $startCountNum[$startTags[$i]] == $endCountNum[$startTags[$i]]) continue;
			$nextTag = $startTags[$i+1];
			$content = $nextTag ? preg_replace('/\[\/' . $nextTag . '\]/iU', '[/' . $startTags[$i] . '][/' . $nextTag . ']', $content) : $content . '[/' . $startTags[$i] . ']';
		}
		return $content;
	}
	
	/**
	 * 刪除本bean的某個分頁
	 * @param int $page
	 */
	function deletePage($page) {
		$page = (int) $page;
		$pageCount = $this->getPageCount();
		if ($pageCount < 2) {
			$this->addError('本文章沒有分頁，無法刪除');
		}
		if ($page > $pageCount || !$page) {
			$this->addError('需要刪除的分頁數據有誤');
		}
		$key = $page - 1;
		$contents = $this->_explodeContent();

		unset($contents[$key]);
		$this->content = implode($this->PAGECUT, $contents);
	}

	/**
	 * 設置文章跳轉鏈接
	 * @param string $jumpUrl
	 */
	function setJumpUrl($jumpUrl) {
		if ($jumpUrl && !$this->_checkUrl($jumpUrl)) {
			$this->addError('跳轉鏈接地址格式有誤');
		}
		$this->jumpUrl = $jumpUrl;
	}

	function setSourceType($sourceType) {
		$sourceTypeConfig = $this->getSourceTypeConfig();
		if ($sourceType && !isset($sourceTypeConfig[$sourceType])) {
			$this->addError('<span class=\'s1\'>文章獲取來源</span>有誤');
		}
		$this->sourceType = $sourceType;
	}

	function setSourceId($soureId) {
		$soureId = (int) $soureId;
		if (!$soureId) $this->sourceType = '';
		$this->sourceId = $soureId;
	}

	/**
	 * 獲取文章的分頁數
	 * return int
	 */
	function getPageCount() {
		$contents = $this->_explodeContent();
		return count($contents);
	}

	/**
	 * 獲取文章的分頁模塊
	 * @param $page
	 * @param $url
	 * return string
	 */
	function getPages($page, $url) {
		return $this->_markPages($page, $this->getPageCount(), $url);
	}

	/**
	 * 獲取數據來源配置
	 */
	function getSourceTypeConfig() {
		return array('thread' => '帖子ID', 'diary' => '日志ID');
	}

	/**
	 * @param string $sourceType
	 * @return Object
	 */
	function sourceFactory($sourceType) {
		$sourceTypeConfig = $this->getSourceTypeConfig();
		if (isset($sourceTypeConfig[$sourceType])) {
			$className = $sourceType . 'sourcetype';
			return C::loadClass($className, 'sourcetype');
		}
		return C::loadClass('nonesourcetype', 'sourcetype');
	}

	function _cookContentByPage($content, $page) {
		if ($page === 'add') return $this->content . "\r\n" . $this->PAGECUT . "\r\n" . $content;
		if ($page === 'all') return $content;
		$page = (int) $page;
		if (!$page || !$this->content) return $content;
		$contents = $this->_explodeContent();

		$key = $page - 1;
		$contents[$key] = $content;
		return implode($this->PAGECUT, $contents);
	}

	function _cookOldAttachs($attachs, $oldatt_desc) {
		foreach ($attachs as $key => $value) {
			$value['descrip'] = $oldatt_desc[$value['attach_id']];
			$value['attname'] = 'update';
			$attachs[$key] = $value;
		}
		return $attachs;
	}

	function _checkUrl($jumpUrl) {
		if (strpos($jumpUrl, 'http') === 0) {return true;}
		return false;
	}

	function _markPages($page, $count, $url) {
		if ($count < 2) return '';
		$page = (int) $page;
		list($url, $mao) = explode('#', $url);
		$mao && $mao = '#' . $mao;
		$pages = "<div class=\"pages\">";
		if ($page > 1) {
			$pages .= "<a href=\"{$url}page=" . ($page - 1) . "$mao\">上一頁</a>";
		}

		for ($i = $page - 3; $i <= $page - 1; $i++) {
			if ($i < 1) continue;
			$pages .= "<a href=\"{$url}page=$i$mao\">$i</a>";
		}
		if ($page) {
			$pages .= "<b>$page</b>";
		}
		if ($page < $count) {
			$this->_numPages($pages, $page, $count, $url, $mao);
		}
		$pages .= "</div>";
		return $pages;
	}

	function _numPages(&$pages, $page, $count, $url, $mao) {
		$flag = 0;
		for ($i = $page + 1; $i <= $count; $i++) {
			$pages .= "<a href=\"{$url}page=$i$mao\">$i</a>";
			$flag++;
			if ($flag == 4) break;
		}
		$pages .= "<a href=\"{$url}page=" . ($page + 1) . "$mao\">下一頁</a>";
	}

	function _explodeContent() {
		return explode($this->PAGECUT, $this->content);
	}

	function getSourceUrl() {
		$source = $this->sourceFactory($this->sourceType);
		return $source->getSourceUrl($this->sourceId);
	}

	function setAuthor($author) {
		$author = $this->_filterUitil->convert($author);
		$this->author = $author;
	}

	function setFromInfo($fromInfo) {
		$fromInfo = $this->_filterUitil->convert($fromInfo);
		$this->fromInfo = $fromInfo;
	}

	function setFromUrl($fromUrl) {
		if ($fromUrl && !$this->_checkUrl($fromUrl)) {
			$this->addError('來源網址格式有誤');
		}
		$this->fromUrl = $fromUrl;
	}

	function setPostDate($postDate) {
		$this->postDate = (int) $postDate;
	}

	function setModifyDate($modifyDate) {
		$this->modifyDate = (int) $modifyDate;
	}

	function setUser($user) {
		$this->user = $user;
	}

	function setUserId($userId) {
		$this->userId = $userId;
	}

	function setIfCheck($ifcheck) {
		$this->ifcheck = (int) $ifcheck;
	}

	function setIfAttach($ifAttach) {
		$this->ifAttach = (int) $ifAttach;
	}

	function setPageCount($count) {
		$this->pageCount = (int) $count;
	}

	function setArticleId($articleId) {
		$this->articleId = (int) $articleId;
	}

}
