You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

504 lines
16 KiB

<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* 评论归档
*
* @category typecho
* @package Widget
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id$
*/
/**
* 评论归档组件
*
* @category typecho
* @package Widget
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
*/
class Widget_Comments_Archive extends Widget_Abstract_Comments
{
/**
* 当前页
*
* @access private
* @var integer
*/
private $_currentPage;
/**
* 所有文章个数
*
* @access private
* @var integer
*/
private $_total = false;
/**
* 子父级评论关系
*
* @access private
* @var array
*/
private $_threadedComments = array();
/**
* _singleCommentOptions
*
* @var mixed
* @access private
*/
private $_singleCommentOptions = NULL;
/**
* 构造函数,初始化组件
*
* @access public
* @param mixed $request request对象
* @param mixed $response response对象
* @param mixed $params 参数列表
* @return void
*/
public function __construct($request, $response, $params = NULL)
{
parent::__construct($request, $response, $params);
$this->parameter->setDefault('parentId=0&commentPage=0&commentsNum=0&allowComment=1');
}
/**
* 评论回调函数
*
* @access private
* @return void
*/
private function threadedCommentsCallback()
{
$singleCommentOptions = $this->_singleCommentOptions;
if (function_exists('threadedComments')) {
return threadedComments($this, $singleCommentOptions);
}
$commentClass = '';
if ($this->authorId) {
if ($this->authorId == $this->ownerId) {
$commentClass .= ' comment-by-author';
} else {
$commentClass .= ' comment-by-user';
}
}
?>
<li itemscope itemtype="http://schema.org/UserComments" id="<?php $this->theId(); ?>" class="comment-body<?php
if ($this->levels > 0) {
echo ' comment-child';
$this->levelsAlt(' comment-level-odd', ' comment-level-even');
} else {
echo ' comment-parent';
}
$this->alt(' comment-odd', ' comment-even');
echo $commentClass;
?>">
<div class="comment-author" itemprop="creator" itemscope itemtype="http://schema.org/Person">
<span itemprop="image"><?php $this->gravatar($singleCommentOptions->avatarSize, $singleCommentOptions->defaultAvatar); ?></span>
<cite class="fn" itemprop="name"><?php $singleCommentOptions->beforeAuthor();
$this->author();
$singleCommentOptions->afterAuthor(); ?></cite>
</div>
<div class="comment-meta">
<a href="<?php $this->permalink(); ?>"><time itemprop="commentTime" datetime="<?php $this->date('c'); ?>"><?php $singleCommentOptions->beforeDate();
$this->date($singleCommentOptions->dateFormat);
$singleCommentOptions->afterDate(); ?></time></a>
<?php if ('waiting' == $this->status) { ?>
<em class="comment-awaiting-moderation"><?php $singleCommentOptions->commentStatus(); ?></em>
<?php } ?>
</div>
<div class="comment-content" itemprop="commentText">
<?php $this->content(); ?>
</div>
<div class="comment-reply">
<?php $this->reply($singleCommentOptions->replyWord); ?>
</div>
<?php if ($this->children) { ?>
<div class="comment-children" itemprop="discusses">
<?php $this->threadedComments(); ?>
</div>
<?php } ?>
</li>
<?php
}
/**
* 获取当前评论链接
*
* @access protected
* @return string
*/
protected function ___permalink()
{
if ($this->options->commentsPageBreak) {
$pageRow = array('permalink' => $this->parentContent['pathinfo'], 'commentPage' => $this->_currentPage);
return Typecho_Router::url('comment_page',
$pageRow, $this->options->index) . '#' . $this->theId;
}
return $this->parentContent['permalink'] . '#' . $this->theId;
}
/**
* 子评论
*
* @access protected
* @return array
*/
protected function ___children()
{
return $this->options->commentsThreaded && !$this->isTopLevel && isset($this->_threadedComments[$this->coid])
? $this->_threadedComments[$this->coid] : array();
}
/**
* 是否到达顶层
*
* @access protected
* @return boolean
*/
protected function ___isTopLevel()
{
return $this->levels > $this->options->commentsMaxNestingLevels - 2;
}
/**
* 重载内容获取
*
* @access protected
* @return void
*/
protected function ___parentContent()
{
return $this->parameter->parentContent;
}
/**
* 输出文章评论数
*
* @access public
* @param string $string 评论数格式化数据
* @return void
*/
public function num()
{
$args = func_get_args();
if (!$args) {
$args[] = '%d';
}
$num = intval($this->_total);
echo sprintf(isset($args[$num]) ? $args[$num] : array_pop($args), $num);
}
/**
* 执行函数
*
* @access public
* @return void
*/
public function execute()
{
if (!$this->parameter->parentId) {
return;
}
$commentsAuthor = Typecho_Cookie::get('__typecho_remember_author');
$commentsMail = Typecho_Cookie::get('__typecho_remember_mail');
$select = $this->select()->where('table.comments.cid = ?', $this->parameter->parentId)
->where('table.comments.status = ? OR (table.comments.author = ? AND table.comments.mail = ? AND table.comments.status = ?)', 'approved', $commentsAuthor, $commentsMail, 'waiting');
$threadedSelect = NULL;
if ($this->options->commentsShowCommentOnly) {
$select->where('table.comments.type = ?', 'comment');
}
$select->order('table.comments.coid', 'ASC');
$this->db->fetchAll($select, array($this, 'push'));
/** 需要输出的评论列表 */
$outputComments = array();
/** 如果开启评论回复 */
if ($this->options->commentsThreaded) {
foreach ($this->stack as $coid => &$comment) {
/** 取出父节点 */
$parent = $comment['parent'];
/** 如果存在父节点 */
if (0 != $parent && isset($this->stack[$parent])) {
/** 如果当前节点深度大于最大深度, 则将其挂接在父节点上 */
if ($comment['levels'] >= $this->options->commentsMaxNestingLevels) {
$comment['levels'] = $this->stack[$parent]['levels'];
$parent = $this->stack[$parent]['parent']; // 上上层节点
$comment['parent'] = $parent;
}
/** 计算子节点顺序 */
$comment['order'] = isset($this->_threadedComments[$parent])
? count($this->_threadedComments[$parent]) + 1 : 1;
/** 如果是子节点 */
$this->_threadedComments[$parent][$coid] = $comment;
} else {
$outputComments[$coid] = $comment;
}
}
$this->stack = $outputComments;
}
/** 评论排序 */
if ('DESC' == $this->options->commentsOrder) {
$this->stack = array_reverse($this->stack, true);
$this->_threadedComments = array_map('array_reverse', $this->_threadedComments);
}
/** 评论总数 */
$this->_total = count($this->stack);
/** 对评论进行分页 */
if ($this->options->commentsPageBreak) {
if ('last' == $this->options->commentsPageDisplay && !$this->parameter->commentPage) {
$this->_currentPage = ceil($this->_total / $this->options->commentsPageSize);
} else {
$this->_currentPage = $this->parameter->commentPage ? $this->parameter->commentPage : 1;
}
/** 截取评论 */
$this->stack = array_slice($this->stack,
($this->_currentPage - 1) * $this->options->commentsPageSize, $this->options->commentsPageSize);
/** 评论置位 */
$this->row = current($this->stack);
$this->length = count($this->stack);
}
reset($this->stack);
}
/**
* 将每行的值压入堆栈
*
* @access public
* @param array $value 每行的值
* @return array
*/
public function push(array $value)
{
$value = $this->filter($value);
/** 计算深度 */
if (0 != $value['parent'] && isset($this->stack[$value['parent']]['levels'])) {
$value['levels'] = $this->stack[$value['parent']]['levels'] + 1;
} else {
$value['levels'] = 0;
}
/** 重载push函数,使用coid作为数组键值,便于索引 */
$this->stack[$value['coid']] = $value;
$this->length ++;
return $value;
}
/**
* 输出分页
*
* @access public
* @param string $prev 上一页文字
* @param string $next 下一页文字
* @param int $splitPage 分割范围
* @param string $splitWord 分割字符
* @param string $template 展现配置信息
* @return void
*/
public function pageNav($prev = '&laquo;', $next = '&raquo;', $splitPage = 3, $splitWord = '...', $template = '')
{
if ($this->options->commentsPageBreak && $this->_total > $this->options->commentsPageSize) {
$default = array(
'wrapTag' => 'ol',
'wrapClass' => 'page-navigator'
);
if (is_string($template)) {
parse_str($template, $config);
} else {
$config = $template;
}
$template = array_merge($default, $config);
$pageRow = $this->parameter->parentContent;
$pageRow['permalink'] = $pageRow['pathinfo'];
$query = Typecho_Router::url('comment_page', $pageRow, $this->options->index);
/** 使用盒状分页 */
$nav = new Typecho_Widget_Helper_PageNavigator_Box($this->_total,
$this->_currentPage, $this->options->commentsPageSize, $query);
$nav->setPageHolder('commentPage');
$nav->setAnchor('comments');
echo '<' . $template['wrapTag'] . (empty($template['wrapClass'])
? '' : ' class="' . $template['wrapClass'] . '"') . '>';
$nav->render($prev, $next, $splitPage, $splitWord, $template);
echo '</' . $template['wrapTag'] . '>';
}
}
/**
* 递归输出评论
*
* @access protected
* @return void
*/
public function threadedComments()
{
$children = $this->children;
if ($children) {
//缓存变量便于还原
$tmp = $this->row;
$this->sequence ++;
//在子评论之前输出
echo $this->_singleCommentOptions->before;
foreach ($children as $child) {
$this->row = $child;
$this->threadedCommentsCallback();
$this->row = $tmp;
}
//在子评论之后输出
echo $this->_singleCommentOptions->after;
$this->sequence --;
}
}
/**
* 列出评论
*
* @access private
* @param mixed $singleCommentOptions 单个评论自定义选项
* @return void
*/
public function listComments($singleCommentOptions = NULL)
{
//初始化一些变量
$this->_singleCommentOptions = Typecho_Config::factory($singleCommentOptions);
$this->_singleCommentOptions->setDefault(array(
'before' => '<ol class="comment-list">',
'after' => '</ol>',
'beforeAuthor' => '',
'afterAuthor' => '',
'beforeDate' => '',
'afterDate' => '',
'dateFormat' => $this->options->commentDateFormat,
'replyWord' => _t('回复'),
'commentStatus' => _t('您的评论正等待审核!'),
'avatarSize' => 32,
'defaultAvatar' => NULL
));
$this->pluginHandle()->trigger($plugged)->listComments($this->_singleCommentOptions, $this);
if (!$plugged) {
if ($this->have()) {
echo $this->_singleCommentOptions->before;
while ($this->next()) {
$this->threadedCommentsCallback();
}
echo $this->_singleCommentOptions->after;
}
}
}
/**
* 重载alt函数,以适应多级评论
*
* @access public
* @return void
*/
public function alt()
{
$args = func_get_args();
$num = func_num_args();
$sequence = $this->levels <= 0 ? $this->sequence : $this->order;
$split = $sequence % $num;
echo $args[(0 == $split ? $num : $split) -1];
}
/**
* 根据深度余数输出
*
* @access public
* @param string $param 需要输出的值
* @return void
*/
public function levelsAlt()
{
$args = func_get_args();
$num = func_num_args();
$split = $this->levels % $num;
echo $args[(0 == $split ? $num : $split) -1];
}
/**
* 评论回复链接
*
* @access public
* @param string $word 回复链接文字
* @return void
*/
public function reply($word = '')
{
if ($this->options->commentsThreaded && !$this->isTopLevel && $this->parameter->allowComment) {
$word = empty($word) ? _t('回复') : $word;
$this->pluginHandle()->trigger($plugged)->reply($word, $this);
if (!$plugged) {
echo '<a href="' . substr($this->permalink, 0, - strlen($this->theId) - 1) . '?replyTo=' . $this->coid .
'#' . $this->parameter->respondId . '" rel="nofollow" onclick="return TypechoComment.reply(\'' .
$this->theId . '\', ' . $this->coid . ');">' . $word . '</a>';
}
}
}
/**
* 取消评论回复链接
*
* @access public
* @param string $word 取消回复链接文字
* @return void
*/
public function cancelReply($word = '')
{
if ($this->options->commentsThreaded) {
$word = empty($word) ? _t('取消回复') : $word;
$this->pluginHandle()->trigger($plugged)->cancelReply($word, $this);
if (!$plugged) {
$replyId = $this->request->filter('int')->replyTo;
echo '<a id="cancel-comment-reply-link" href="' . $this->parameter->parentContent['permalink'] . '#' . $this->parameter->respondId .
'" rel="nofollow"' . ($replyId ? '' : ' style="display:none"') . ' onclick="return TypechoComment.cancelReply();">' . $word . '</a>';
}
}
}
}