diff --git a/includes/comments.php b/includes/comments.php index 1c94c69..96e63d1 100644 --- a/includes/comments.php +++ b/includes/comments.php @@ -20,9 +20,9 @@ require_once __DIR__ . "/../libs/comments.php"; $parameter = array( 'parentId' => $this->hidden ? 0 : $this->cid, - 'parentContent' => $this->row, + 'parentContent' => (Cuckoo_Comments_Archive::isTypechoVersion()) ? $this : $this->row, 'respondId' => $this->respondId, - 'commentPage' => $this->request->filter('int')->commentPage, + 'commentPage' => (Cuckoo_Comments_Archive::isTypechoVersion()) ? $this->parameter->commentPage : $this->request->filter('int')->commentPage, 'allowComment' => $this->allow('comment') ); $this->widget('Cuckoo_Comments_Archive', $parameter)->to($comments); diff --git a/libs/comments.php b/libs/comments.php index f3833b0..292cb46 100644 --- a/libs/comments.php +++ b/libs/comments.php @@ -14,37 +14,39 @@ * @date 2023-12-09 */ +use Typecho\Config; +use Typecho\Cookie; +use Typecho\Db; +use Typecho\Router; +use Typecho\Widget\Exception; +use Typecho\Widget\Helper\PageNavigator\Box; +use Utils\Helper; +use Widget\Comments\Archive; + if (!defined('__TYPECHO_ROOT_DIR__')) exit; // 基本按照 Typecho 评论组件而来 -/** - * 评论归档 - * - * @category typecho - * @package Widget - * @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org) - * @license GNU General Public License 2.0 - * @version $Id$ - */ - /** * 评论归档组件 * + * 由于不继承 \Widget\Base\Comments 会导致 1.3.0 和 1.2.0 版本的 ___parentContent 方法返回类型不一致 (1.3.0 返回 \Widget\Base\Contents,1.3.0 以下返回数组) + * 继承又会因为基本都要覆写 (因为有大量 protected 方法,若需调用子类 private 变量则需要进行覆写) + * 没办法了,为了兼容新老版本只能继承 + 覆写了口牙! (这样就能不管 ___parentContent 方法到底给我了啥) + * * @category typecho * @package Widget * @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org) * @license GNU General Public License 2.0 */ -class Cuckoo_Comments_Archive extends Widget_Abstract_Comments -{ +class Cuckoo_Comments_Archive extends Archive { /** * 当前页 * * @access private * @var integer */ - private $_currentPage; + private int $currentPage; /** * 所有文章个数 @@ -52,7 +54,7 @@ class Cuckoo_Comments_Archive extends Widget_Abstract_Comments * @access private * @var integer */ - private $_total = false; + private int $total = 0; /** * 子父级评论关系 @@ -60,29 +62,44 @@ class Cuckoo_Comments_Archive extends Widget_Abstract_Comments * @access private * @var array */ - private $_threadedComments = array(); + private array $threadedComments = []; /** * _singleCommentOptions * - * @var mixed + * @var Config|null * @access private */ - private $_singleCommentOptions = NULL; + private ?Config $singleCommentOptions = NULL; /** - * 构造函数,初始化组件 + * @param Config $parameter + */ + protected function initParameter(Config $parameter) { + $parameter->setDefault([ + 'parentId' => 0, + 'respondId' => '', + 'commentPage' => 0, + 'commentsNum' => 0, + 'allowComment' => 1, + 'parentContent' => null, + ]); + } + + /** + * 判断 Typecho 版本号 * * @access public - * @param mixed $request request对象 - * @param mixed $response response对象 - * @param mixed $params 参数列表 - * @return void + * @return bool 提取到的版本号是否大于或等于 1.3.0 */ - public function __construct($request, $response, $params = NULL) - { - parent::__construct($request, $response, $params); - $this->parameter->setDefault('parentId=0&commentPage=0&commentsNum=0&allowComment=1'); + public static function isTypechoVersion(): bool { + $version = "1.0.0"; + + if (preg_match('/Typecho\s+([\d.]+)/i', Helper::options()->generator, $matches)) { + $version = $matches[1]; + } + + return (bool)version_compare($version, '1.3.0', '>='); } /** @@ -90,12 +107,13 @@ public function __construct($request, $response, $params = NULL) * * @access private * @return void + * @throws Db\Exception */ - private function threadedCommentsCallback() - { - $singleCommentOptions = $this->_singleCommentOptions; + private function threadedCommentsCallback(): void { + $singleCommentOptions = $this->singleCommentOptions; if (function_exists('threadedComments')) { - return threadedComments($this, $singleCommentOptions); + threadedComments($this, $singleCommentOptions); + return; } $commentClass = ''; @@ -105,23 +123,21 @@ private function threadedCommentsCallback() } else { $commentClass .= ' comment-by-user'; } - } -?> -
+ } ?> +
- + commenter-avatar mail); if ($this->authorId == $this->ownerId) { ?> - + author-prefix
@@ -144,7 +160,7 @@ private function threadedCommentsCallback()
commentsReply(); - echo preg_replace('#]*>#', '', parseBiaoQing($this->content));; ?> + echo preg_replace('#]*>#', '', parseBiaoQing($this->content)); ?>
children) { ?>
@@ -155,14 +171,19 @@ private function threadedCommentsCallback() fetchRow($db->select('parent')->from('table.comments')->where('coid = ?', $this->coid)); $parentID = $parentID['parent']; if ($parentID == '0') { - return ''; + return; } else { $author = $db->fetchRow($db->select()->from('table.comments')->where('coid = ?', $parentID)); $link = 'href="#comment-' . $author['coid'] . '"'; @@ -182,23 +203,36 @@ private function commentsReply() /** * 获取当前评论链接 + * (Typecho 1.3.0 已移除该方法) * * @access protected * @return string */ - protected function ___permalink() : string - { + protected function ___permalink() : string { + if (self::isTypechoVersion()) { + // Typecho 1.3.0 \Widget\Base\Comment ___permalink 方法 + if ($this->options->commentsPageBreak) { + return Router::url( + 'comment_page', + $this, + $this->options->index + ) . '#' . $this->theId; + } - 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; + } else { + // Typecho 1.3.0- \Widget\Comments\Archive ___permalink 方法 + if ($this->options->commentsPageBreak) { + $pageRow = array('permalink' => $this->parentContent['pathinfo'], 'commentPage' => $this->currentPage); + return Router::url( + 'comment_page', + $pageRow, + $this->options->index + ) . '#' . $this->theId; + } - return $this->parentContent['permalink'] . '#' . $this->theId; + return $this->parentContent['permalink'] . '#' . $this->theId; + } } /** @@ -207,10 +241,9 @@ protected function ___permalink() : string * @access protected * @return array */ - protected function ___children() - { - return $this->options->commentsThreaded && !$this->isTopLevel && isset($this->_threadedComments[$this->coid]) - ? $this->_threadedComments[$this->coid] : array(); + protected function ___children(): array { + return $this->options->commentsThreaded && !$this->isTopLevel && isset($this->threadedComments[$this->coid]) + ? $this->threadedComments[$this->coid] : []; } /** @@ -219,39 +252,35 @@ protected function ___children() * @access protected * @return boolean */ - protected function ___isTopLevel() - { + protected function ___isTopLevel(): bool { return $this->levels > $this->options->commentsMaxNestingLevels - 2; } /** - * 重载内容获取 + * 重载评论页码获取 + * Typecho v1.2.1 无该方法 * - * @access protected - * @return void + * @return int */ - protected function ___parentContent() : ?array - { - return $this->parameter->parentContent; + protected function ___commentPage(): int { + return $this->currentPage; } /** * 输出文章评论数 * * @access public - * @param string $string 评论数格式化数据 + * @param mixed ...$args * @return void */ - public function num() - { - $args = func_get_args(); - if (!$args) { + public function num(...$args) { + if (empty($args)) { $args[] = '%d'; } - $num = intval($this->_total); + $num = $this->total; - echo sprintf(isset($args[$num]) ? $args[$num] : array_pop($args), $num); + echo sprintf($args[$num] ?? array_pop($args), $num); } /** @@ -259,18 +288,36 @@ public function num() * * @access public * @return void + * @throws Db\Exception */ - public function execute() - { + 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; + // Typecho 版本判断 + if (self::isTypechoVersion()) { + $unapprovedCommentId = intval(Cookie::get('__typecho_unapproved_comment', 0)); + $select = $this->select()->where('cid = ?', $this->parameter->parentId) + ->where( + 'status = ? OR (coid = ? AND status <> ?)', + 'approved', + $unapprovedCommentId, + 'approved' + ); + } else { + $commentsAuthor = Cookie::get('__typecho_remember_author'); + $commentsMail = 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' + ); + } if ($this->options->commentsShowCommentOnly) { $select->where('table.comments.type = ?', 'comment'); @@ -280,7 +327,7 @@ public function execute() $this->db->fetchAll($select, array($this, 'push')); /** 需要输出的评论列表 */ - $outputComments = array(); + $outputComments = []; /** 如果开启评论回复 */ if ($this->options->commentsThreaded) { @@ -305,7 +352,7 @@ public function execute() ? count($this->_threadedComments[$parent]) + 1 : 1; /** 如果是子节点 */ - $this->_threadedComments[$parent][$coid] = $comment; + $this->threadedComments[$parent][$coid] = $comment; } else { $outputComments[$coid] = $comment; } @@ -317,32 +364,31 @@ public function execute() /** 评论排序 */ if ('DESC' == $this->options->commentsOrder) { $this->stack = array_reverse($this->stack, true); - $this->_threadedComments = array_map('array_reverse', $this->_threadedComments); + $this->threadedComments = array_map('array_reverse', $this->threadedComments); } /** 评论总数 */ - $this->_total = count($this->stack); + $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); + $this->currentPage = ceil($this->total / $this->options->commentsPageSize); } else { - $this->_currentPage = $this->parameter->commentPage ? $this->parameter->commentPage : 1; + $this->currentPage = $this->parameter->commentPage ? $this->parameter->commentPage : 1; } /** 截取评论 */ $this->stack = array_slice( $this->stack, - ($this->_currentPage - 1) * $this->options->commentsPageSize, + ($this->currentPage - 1) * $this->options->commentsPageSize, $this->options->commentsPageSize ); - - /** 评论置位 */ - $this->length = count($this->stack); - $this->row = $this->length > 0 ? current($this->stack) : array(); } + /** 评论置位 */ + $this->length = count($this->stack); + $this->row = $this->length > 0 ? current($this->stack) : []; reset($this->stack); } @@ -353,8 +399,7 @@ public function execute() * @param array $value 每行的值 * @return array */ - public function push(array $value) : array - { + public function push(array $value) : array { $value = $this->filter($value); /** 计算深度 */ @@ -375,59 +420,76 @@ public function push(array $value) : array * 输出分页 * * @access public - * @param string $prev 上一页文字 - * @param string $next 下一页文字 - * @param int $splitPage 分割范围 - * @param string $splitWord 分割字符 - * @param string $template 展现配置信息 + * @param string $prev 上一页文字 + * @param string $next 下一页文字 + * @param int $splitPage 分割范围 + * @param string $splitWord 分割字符 + * @param string|array $template 展现配置信息 * @return void + * @throws Exception */ - public function pageNav($prev = '«', $next = '»', $splitPage = 3, $splitWord = '...', $template = '') - { - if ($this->options->commentsPageBreak && $this->_total > $this->options->commentsPageSize) { - $default = array( - 'wrapTag' => 'ol', - 'wrapClass' => 'page-navigator' - ); + public function pageNav(string $prev = '«', string $next = '»', int $splitPage = 3, string $splitWord = '...', $template = '') { + if ($this->options->commentsPageBreak) { + $default = [ + 'wrapTag' => 'ol', + 'wrapClass' => 'page-navigator' + ]; if (is_string($template)) { parse_str($template, $config); } else { - $config = $template; + $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); + // 进行 Typecho 版本判断 + if (self::isTypechoVersion()) { + $pageRow = [ + 'permalink' => $this->parameter->parentContent->path, + 'commentPage' => '{commentPage}' + ]; + } else { + $pageRow = $this->parameter->parentContent; + $pageRow['permalink'] = $pageRow['pathinfo']; + } + $query = Router::url('comment_page', $pageRow, $this->options->index); - /** 使用盒状分页 */ - $nav = new Typecho_Widget_Helper_PageNavigator_Box( - $this->_total, - $this->_currentPage, + self::pluginHandle()->trigger($hasNav)->call( + 'pageNav', + $this->currentPage, + $this->total, $this->options->commentsPageSize, + $prev, + $next, + $splitPage, + $splitWord, + $template, $query ); - $nav->setPageHolder('commentPage'); - $nav->setAnchor('comments'); - echo '<' . $template['wrapTag'] . (empty($template['wrapClass']) - ? '' : ' class="' . $template['wrapClass'] . '"') . '>'; - $nav->render($prev, $next, $splitPage, $splitWord, $template); - echo ''; + if (!$hasNav && $this->total > $this->options->commentsPageSize) { + /** 使用盒状分页 */ + $nav = new 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 ''; + } } } /** * 递归输出评论 * - * @access protected + * @access public * @return void + * @throws Db\Exception */ - public function threadedComments() - { + public function threadedComments() { $children = $this->children; if ($children) { //缓存变量便于还原 @@ -435,7 +497,7 @@ public function threadedComments() $this->sequence++; //在子评论之前输出 - echo $this->_singleCommentOptions->before; + echo $this->singleCommentOptions->before; foreach ($children as $child) { $this->row = $child; @@ -444,7 +506,7 @@ public function threadedComments() } //在子评论之后输出 - echo $this->_singleCommentOptions->after; + echo $this->singleCommentOptions->after; $this->sequence--; } @@ -453,15 +515,16 @@ public function threadedComments() /** * 列出评论 * - * @access private + * @access public * @param mixed $singleCommentOptions 单个评论自定义选项 * @return void + * @throws Db\Exception */ public function listComments($singleCommentOptions = NULL) { //初始化一些变量 - $this->_singleCommentOptions = Typecho_Config::factory($singleCommentOptions); - $this->_singleCommentOptions->setDefault(array( + $this->singleCommentOptions = Config::factory($singleCommentOptions); + $this->singleCommentOptions->setDefault([ 'before' => '', 'after' => '', 'beforeAuthor' => '', @@ -472,55 +535,24 @@ public function listComments($singleCommentOptions = NULL) 'replyWord' => _t('回复'), 'commentStatus' => _t('您的评论正等待审核!'), 'avatarSize' => 32, - 'defaultAvatar' => NULL - )); - $this->pluginHandle()->trigger($plugged)->listComments($this->_singleCommentOptions, $this); + 'defaultAvatar' => NULL, + 'avatarHighRes' => false + ]); + self::pluginHandle()->trigger($plugged)->call('listComments', $this->singleCommentOptions, $this); if (!$plugged) { if ($this->have()) { - echo $this->_singleCommentOptions->before; + echo $this->singleCommentOptions->before; while ($this->next()) { $this->threadedCommentsCallback(); } - echo $this->_singleCommentOptions->after; + echo $this->singleCommentOptions->after; } } } - /** - * 重载alt函数,以适应多级评论 - * - * @access public - * @return void - */ - public function alt(...$args) - { - $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]; - } - /** * 评论回复链接 * @@ -528,13 +560,13 @@ public function levelsAlt() * @param string $word 回复链接文字 * @return void */ - public function reply($word = '') - { + public function reply(string $word = '') { if ($this->options->commentsThreaded && !$this->isTopLevel && $this->parameter->allowComment) { $word = empty($word) ? _t('回复') : $word; - $this->pluginHandle()->trigger($plugged)->reply($word, $this); + self::pluginHandle()->trigger($plugged)->call('reply', $word, $this); if (!$plugged) { + // TypechoComment 位于 comments.min.js echo '' . $word . ''; @@ -549,16 +581,16 @@ public function reply($word = '') * @param string $word 取消回复链接文字 * @return void */ - public function cancelReply($word = '') - { + public function cancelReply(string $word = '') { if ($this->options->commentsThreaded) { $word = empty($word) ? _t('取消回复') : $word; - $this->pluginHandle()->trigger($plugged)->cancelReply($word, $this); + self::pluginHandle()->trigger($plugged)->call('cancelReply', $word, $this); if (!$plugged) { - $replyId = $this->request->filter('int')->replyTo; - echo ''; + $replyId = $this->request->filter('int')->get('replyTo'); + // TypechoComment 位于 comments.min.jst + echo ''; } } } @@ -568,8 +600,7 @@ public function cancelReply($word = '') * * @access public */ - public static function AntiSpam($comment) - { + public static function AntiSpam($comment) { echo ''; echo ''; echo '';