PageRenderTime 47ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/wp-recentcomments/core.php

https://github.com/kikaendeavor/wordpress
PHP | 479 lines | 274 code | 80 blank | 125 comment | 90 complexity | 163d2f6bd49c792db880dee287c30cdc MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0, AGPL-1.0, LGPL-2.1
  1. <?php
  2. /**
  3. * Ajax 方法
  4. */
  5. function rc_ajax(){
  6. // 翻页
  7. if($_GET['action'] == 'rc_ajax') {
  8. $argsf = $_GET["args"];
  9. $start = $_GET["start"];
  10. $args = str_replace('|', '&', $argsf);
  11. $args = str_replace('--', '=', $args);
  12. echo create_recentcomments($args, $start);
  13. die();
  14. // 查看详细信息
  15. } else if($_GET['action'] == 'rc_detail_ajax') {
  16. $argsf = $_GET["args"];
  17. $start = $_GET["start"];
  18. $id = $_GET["id"];
  19. echo create_rc_detail($id, $argsf, $start);
  20. die();
  21. }
  22. }
  23. add_action('init', 'rc_ajax');
  24. /**
  25. * 获取最新评论列表
  26. * @param args 参数字符串
  27. * @param start 评论的开始位置
  28. * @return 生成的 HTML 字符串
  29. */
  30. function create_recentcomments($args = '', $start = 0) {
  31. // AJAX 翻页时用的参数
  32. $argsf = str_replace('=', '--', $args);
  33. $argsf = str_replace('&', '|', $argsf);
  34. // 加载过程显示的文本
  35. $loading_text = __('Loading', 'wp-recentcomments');
  36. // 分列参数
  37. $args = rc_parse_args($args);
  38. if ($start < 0) {
  39. $start = 0;
  40. }
  41. // 在数据库中获取评论相关信息
  42. global $wpdb, $comments, $comment;
  43. // 是否 pingback 的 SQL 条件
  44. $sql_pingback = '';
  45. if ($args['pingback'] == 'false') {
  46. $sql_pingback = " AND comment_type != 'pingback'";
  47. }
  48. // 是否 trackback 的 SQL 条件
  49. $sql_trackback = '';
  50. if ($args['trackback'] == 'false') {
  51. $sql_trackback = " AND comment_type != 'trackback'";
  52. }
  53. // 是否显示管理员用户的 SQL 条件
  54. $sql_administrator = '';
  55. if ($args['administrator'] == 'false') {
  56. $sql_administrator = " AND comment_author_email NOT IN (SELECT A1.user_email FROM $wpdb->users A1, $wpdb->usermeta A2 WHERE A1.ID = A2.user_id AND A2.meta_key = 'wp_capabilities' AND A2.meta_value LIKE '%administrator%')";
  57. }
  58. // 显示密码保护文章的评论的 SQL 条件
  59. $post_protected = $_COOKIE['wp-postpass_' . COOKIEHASH];
  60. $sql_protected = " AND (comment_post_ID = ID AND (post_password = '' OR post_password = '" . $post_protected . "'))";
  61. // 显示私有文章的评论的 SQL 条件
  62. global $user_ID;
  63. $sql_private = " AND (comment_post_ID = ID AND (post_status != 'private' OR post_author = '" . $user_ID . "'))";
  64. // 准备多取一个, 以便获知是否有更多评论存在
  65. $size = $args['limit'] + 1;
  66. // SQL 查找数据集合
  67. $comments_query = "SELECT comment_author, comment_author_email, comment_author_url, comment_ID, comment_post_ID, comment_content, comment_type, comment_author_IP, comment_agent FROM $wpdb->comments, $wpdb->posts WHERE comment_approved = '1'" . $sql_protected . $sql_private . $sql_pingback . $sql_trackback . $sql_administrator . " ORDER BY comment_date_gmt DESC LIMIT " . $start . "," . $size;
  68. $comments = $wpdb->get_results($comments_query);
  69. // 如果能够获取多一个元组, 证明有更多评论存在, 需要显示 Older 按钮
  70. $has_older = (count($comments) - $args['limit'] > 0);
  71. // 有更多评论存在时, 删除最后那个多余的
  72. if ($has_older) {
  73. array_pop($comments);
  74. }
  75. // 获取最新评论列表
  76. $result = ''; $count = 0;
  77. if ($comments) {
  78. foreach ($comments as $comment) {
  79. // 如果访客昵称为空, 则将显示名字设为 "Anonymous"
  80. if ($comment->comment_author == '') {
  81. $comment->comment_author = __('Anonymous', 'wp-recentcomments');
  82. }
  83. // 用户头像
  84. $element_avatar = rc_get_avatar($args['avatar'], $args['avatar_position'], $args['avatar_size'], $args['avatar_default'], $comment->comment_author_email);
  85. // 获取摘要
  86. $comment_excerpt = preg_replace('/(\r\n)|(\n)/', '', $comment->comment_content); // 消灭换行符
  87. $comment_excerpt = rc_remove_blockquotes($comment_excerpt); // 消灭所有 blockquote 内容
  88. $comment_excerpt = preg_replace('/\<(.+?)\>/', '', $comment_excerpt); // 消灭所有标签
  89. $comment_excerpt = rc_substring($comment_excerpt, 0, $args['length'], $comment->comment_ID, $argsf, $start, $loading_text);
  90. // 处理摘要里的表情
  91. if ((strlen($comment_excerpt) > 0) && $args['smilies'] == 'true') {
  92. $comment_excerpt = convert_smilies($comment_excerpt);
  93. }
  94. // 获取信息
  95. if ($comment->comment_type == 'pingback') {
  96. $result .= '<li id="rc_item_' . ++$count . '" class="rc_item rc_pingback">' . sprintf('<div class="rc_info"><span class="rc_label">' . __('Pingback:') . '</span> %1$s</div>', get_comment_author_link()) . '</li>';
  97. } else if ($comment->comment_type == 'trackback') {
  98. $result .= '<li id="rc_item_' . ++$count . '" class="rc_item rc_trackback">' . sprintf('<div class="rc_info"><span class="rc_label">' . __('Trackback:') . '</span> %1$s</div>', get_comment_author_link()) . '</li>';
  99. } else if ($args['post'] == 'true') {
  100. $result .= '<li id="rc_item_' . ++$count . '" class="rc_item">' . $element_avatar . sprintf('<div class="rc_info"><span class="author_name">%1$s</span> </div>', get_comment_author_link()) . '<div class="rc_excerpt">
  101. <a target="_blank" href="'. get_permalink($comment->comment_post_ID) . '#comment-' . $comment->comment_ID . '">' . $comment_excerpt . '</a>
  102. </div></li>';
  103. } else {
  104. $result .= '<li id="rc_item_' . ++$count . '" class="rc_item">' . $element_avatar . sprintf('<div class="rc_info"><span class="author_name">%1$s</span>' . rc_get_author_info() . '</div>', '<a href="'. get_permalink($comment->comment_post_ID) . '#comment-' . $comment->comment_ID . '">' . $comment->comment_author . '</a>') . '<div class="rc_excerpt">' . $comment_excerpt . '</div></li>';
  105. }
  106. } // foreach ($comments as $comment)
  107. // 新评论和老评论的开始位置
  108. $newer_start = $start - $args['limit'];
  109. $older_start = $start + $args['limit'];
  110. // Newest 按钮
  111. $newest = '';
  112. // 判断是否还有最新评论
  113. // 第一页不需要显示最新评论的链接
  114. // 第二页功能与 Newer 链接功能相同, 也不需显示
  115. // 第三页开始才有必要显示出来
  116. $has_newest = ($start >= $args['limit'] * 2);
  117. if ($has_newest) {
  118. $newest = '<div id="rc_newest"><a href="javascript:void(0);" onclick="RCJS.page(\'' . get_bloginfo('siteurl') . '\',\'' . $argsf . '\',0,\'' . $loading_text . '\');">' . __('&laquo; Newest', 'wp-recentcomments') . '</a></div>';
  119. }
  120. // Newer 按钮
  121. $newer = '';
  122. // 判断是否还有新评论
  123. // 只要前面还有新的评论, 就要显示.
  124. $has_newer = ($start > 0);
  125. if ($has_newer) {
  126. // 如果开始位置为负数, 将它修改为 0
  127. if ($newer_start < 0) {
  128. $newer_start = 0;
  129. }
  130. $newer = '<div id="rc_newer"><a href="javascript:void(0);" onclick="RCJS.page(\'' . get_bloginfo('siteurl') . '\',\'' . $argsf . '\',' . $newer_start . ',\'' . $loading_text . '\');">' . __('&laquo; Newer', 'wp-recentcomments') . '</a></div>';
  131. }
  132. // Older 按钮
  133. $older = '';
  134. if ($has_older) {
  135. $older = '<div id="rc_older"><a href="javascript:void(0);" onclick="RCJS.page(\'' . get_bloginfo('siteurl') . '\',\'' . $argsf . '\',' . $older_start . ',\'' . $loading_text . '\');">' . __('Older &raquo;', 'wp-recentcomments') . '</a></div>';
  136. }
  137. // 当需要显示 Newer 或 Older 按钮时才显示这一栏
  138. if (($has_newer || $has_older) && $args['navigator'] == 'true') {
  139. $result .= '<li id="rc_nav"><div>' . $newest . $newer . $older . '<div class="rc_fixed"></div></div></li>';
  140. }
  141. // 返回 HTML 格式的字符串
  142. return $result;
  143. } // if ($comments)
  144. }
  145. /**
  146. * 获取某个评论的详细信息
  147. * @param id 评论 ID
  148. * @param argsf 格式化的参数字符串
  149. * @param start 评论的开始位置
  150. * @param loading_text 加载文本
  151. */
  152. function create_rc_detail($id, $argsf, $start) {
  153. // AJAX 翻页时用的参数
  154. $args = str_replace('|', '&', $argsf);
  155. $args = str_replace('--', '=', $args);
  156. // 加载过程显示的文本
  157. $loading_text = __('Loading', 'wp-recentcomments');
  158. // 分列参数
  159. $args = rc_parse_args($args);
  160. // 在数据库中获取评论相关信息
  161. global $wpdb, $comment;
  162. $comments = $wpdb->get_results("SELECT comment_author, comment_author_email, comment_author_url, comment_ID, comment_post_ID, comment_content, comment_date, comment_author_IP, comment_agent FROM $wpdb->comments WHERE comment_ID = " . $id);
  163. $comment = $comments[0];
  164. // 用户头像
  165. $element_avatar = rc_get_avatar($args['avatar'], $args['avatar_position'], $args['avatar_size'], $args['avatar_default'], $comment->comment_author_email);
  166. // 处理 blockquote
  167. $content = rc_remove_blockquotes_but_outermost($comment->comment_content);
  168. // 处理摘要里的表情
  169. if ((strlen($content) > 0) && $args['smilies'] == 'true') {
  170. $content = convert_smilies($content);
  171. }
  172. // 处理抛锚链接
  173. $content = preg_replace(array('/href="#/', '/href=\'#/'), array('href="'. get_permalink($comment->comment_post_ID) . '#', 'href=\''. get_permalink($comment->comment_post_ID) . '#'), $content);
  174. // 日期时间
  175. $date_format = __('Y/m/d', 'wp-recentcomments');
  176. $time_format = __('H:i', 'wp-recentcomments');
  177. $datetime = sprintf(__('%1$s - %2$s', 'wp-recentcomments'), mysql2date($date_format, $comment->comment_date), mysql2date($time_format, $comment->comment_date));
  178. // 组合 HTML 格式的字符串
  179. $result = '<li id="rc_item_1" class="rc_item">' . $element_avatar . '<div class="rc_info">';
  180. $result .= '<div class="author_name">' . get_comment_author_link() . '</div>';
  181. $result .= '<div class="post_title"><a href="'. get_permalink($comment->comment_post_ID) . '#comment-' . $comment->comment_ID . '">' . get_the_title($comment->comment_post_ID) . '</a></div>';
  182. $result .= '</div></li>';
  183. $result .= '<li id="rc_item_2" class="rc_item">' . $content . '</li>';
  184. $result .= '<li id="rc_nav">';
  185. $result .= '<a class="rc_back" href="javascript:void(0);" onclick="RCJS.page(\'' . get_bloginfo('siteurl') . '\',\'' . $argsf . '\',' . $start . ',\'' . $loading_text . '\');">' . __('&laquo; Back', 'wp-recentcomments') . '</a>';
  186. $result .= '<span class="rc_datetime">' . $datetime . '</span>';
  187. $result .= '<div class="rc_fixed"></div></li>';
  188. // 返回 HTML 格式的字符串
  189. return wpautop($result);
  190. }
  191. /**
  192. * 初始化参数
  193. * @param args 参数字符串
  194. */
  195. function rc_parse_args($args) {
  196. // 默认参数
  197. $defaults = array(
  198. 'limit' => 5, // 最新评论的条目数量
  199. 'length' => 45, // 每条评论的字符长度
  200. 'pingback' => 'true', // 是否显示 pingback, true: 显示; false: 不显示
  201. 'trackback' => 'true', // 是否显示 trackback, true: 显示; false: 不显示
  202. 'post' => 'true', // 是否显示评论所在帖, true: 显示; false: 不显示
  203. 'avatar' => 'true', // 是否显示评论者头像, true: 显示; false: 不显示
  204. 'avatar_size' => 48, // 评论者头像纵横尺寸
  205. 'avatar_position' => 'left', // 评论者头像放置位置
  206. 'avatar_default' => '', // 评论者默认头像文件
  207. 'navigator' => 'true', // 是否显示翻页的导航, true: 显示; false: 不显示
  208. 'administrator' => 'true', // 是否显示管理员评论, true: 显示; false: 不显示
  209. 'smilies' => 'fales' // 是否要使用表情图标, true: 使用; false: 不使用
  210. );
  211. // 替换参数
  212. $args = wp_parse_args($args, $defaults);
  213. // 限定参数
  214. if ($args['limit'] < 1) {
  215. $args['limit'] = 1;
  216. } else if ($args['limit'] > 20) {
  217. $args['limit'] = 20;
  218. }
  219. if ($args['length'] > 15) {
  220. $args['length'] = 15;
  221. }
  222. if ($args['avatar_size'] < 8) {
  223. $args['avatar_size'] = 8;
  224. }
  225. if ($args['avatar_size'] > 96) {
  226. $args['avatar_size'] = 96;
  227. }
  228. if ($args['avatar_position'] != 'right') {
  229. $args['avatar_position'] = 'left';
  230. }
  231. if ($args['pingback'] != 'false') {
  232. $args['pingback'] = 'true';
  233. }
  234. if ($args['trackback'] != 'false') {
  235. $args['trackback'] = 'true';
  236. }
  237. if ($args['post'] != 'false') {
  238. $args['post'] = 'true';
  239. }
  240. if ($args['avatar'] != 'false') {
  241. $args['avatar'] = 'true';
  242. }
  243. if ($args['navigator'] != 'false') {
  244. $args['navigator'] = 'true';
  245. }
  246. if ($args['administrator'] != 'false') {
  247. $args['administrator'] = 'true';
  248. }
  249. if ($args['smilies'] != 'true') {
  250. $args['smilies'] = 'false';
  251. }
  252. return $args;
  253. }
  254. /**
  255. * 以字符为单位获得字符串子串
  256. * @param str 原字符串
  257. * @param start 起始位置
  258. * @param len 截取长度
  259. * @param comment_id 评论 ID
  260. * @param argsf 格式化的参数字符串
  261. * @param comment_start 评论的开始位置
  262. * @param loading_text 加载文本
  263. * @param code 接受编码
  264. */
  265. function rc_substring($str, $start=0, $len=50, $comment_id, $argsf, $comment_start, $loading_text, $code='UTF-8') {
  266. if($code == 'UTF-8') {
  267. $pa = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/";
  268. preg_match_all($pa, $str, $t_str);
  269. if(count($t_str[0]) - $start > $len) {
  270. $ellipsis = '...';
  271. $str = join('', array_slice($t_str[0], $start, $len)) . $ellipsis;
  272. }
  273. $expand = ' <span class="rc_expand"><a href="javascript:void(0);" onclick="RCJS.detail(' . $comment_id . ',\'' . get_bloginfo('siteurl') . '\',\'' . $argsf . '\',' . $comment_start . ',\'' . $loading_text . '\');">' . __('&raquo;', 'wp-recentcomments') . '</a></span>';
  274. return $str . $expand;
  275. }
  276. }
  277. /**
  278. * 获取头像. 如果用户要求显示头像, 并且 WordPress 中包含获取头像的函数, 则生成头像的 HTML
  279. * @param show 是否显示头像
  280. * @param position 头像位置
  281. * @param size 头像尺寸
  282. * @param default 默认头像路径
  283. * @param email 评论者邮箱
  284. */
  285. function rc_get_avatar($show, $position, $size, $default, $email) {
  286. $avatar = '';
  287. if ($show == 'true' && function_exists('get_avatar') && get_option('show_avatars')) {
  288. // 当默认头像来自 Internet 时
  289. if (substr(strtolower($default), 0, 7) == 'http://') {
  290. $file = attribute_escape($default);
  291. $avatar = '<div class="rc_avatar rc_' . $position . '">' . get_avatar($email, $size, $file) . '</div>';
  292. // 当默认头像来自 "/wp-recentcomments/avatars/" 目录时
  293. } else if ($default != '') {
  294. $file = 'wp-content/plugins/wp-recentcomments/avatars/' . $default;
  295. if (file_exists($file)) {
  296. $file = get_bloginfo('siteurl') . '/' . $file;
  297. $avatar = '<div class="rc_avatar rc_' . $position . '">' . get_avatar($email, $size, $file) . '</div>';
  298. }
  299. // 当不包含默认头像时
  300. } else {
  301. $avatar = '<div class="rc_avatar rc_' . $position . '">' . get_avatar($email, $size) . '</div>';
  302. }
  303. }
  304. return $avatar;
  305. }
  306. /**
  307. * 移除 HTML 字符串中所有 blockquote
  308. * @param str HTML 字符串
  309. */
  310. function rc_remove_blockquotes($str) {
  311. // 开头和结尾的标记
  312. $start_pattern = '<blockquote';
  313. $end_pattern = '</blockquote>';
  314. // 出现的次数
  315. $quote_count = substr_count(strtolower($str), $start_pattern);
  316. // 如果出现次数为 0, 不进行任何处理, 直接返回
  317. if ($quote_count <= 0) {
  318. return $str;
  319. // 如果出现次数为 1, 将这个 blockquote 内的全部内容移除
  320. } else if ($quote_count == 1) {
  321. $all_pattern = '/(\<blockquote(.*?)\>)(.*)(\<\/blockquote\>)/i';
  322. return preg_replace($all_pattern, '', $str);
  323. }
  324. // 如果出现次数大于 1
  325. // 找到第一个结尾出现的位置
  326. $end = strpos(strtolower($str), $end_pattern);
  327. // 处理所有 blockquote
  328. while ($end) {
  329. // 获得尾部之前的子串, 并在子串中找到相应的开头位置
  330. $str_before_end = substr($str, 0, $end);
  331. $start = strrpos(strtolower($str_before_end), $start_pattern);
  332. // 将 blockquote 部分除去, 并用分隔符隔开
  333. $sep = ' ';
  334. $str = substr_replace($str, $sep, $start, $end + strlen($end_pattern) - $start);
  335. // 找到下一个结尾的位置
  336. $end = strpos(strtolower($str), $end_pattern);
  337. }
  338. return $str;
  339. }
  340. /**
  341. * 移除 HTML 字符串中, 除最外层的所有 blockquote
  342. * @param str HTML 字符串
  343. */
  344. function rc_remove_blockquotes_but_outermost($str) {
  345. // 开头和结尾的标记
  346. $start_pattern = '<blockquote';
  347. $end_pattern = '</blockquote>';
  348. // 出现的次数
  349. $quote_count = substr_count(strtolower($str), $start_pattern);
  350. // 如果出现次数为 0 或 1, 不进行任何处理, 直接返回
  351. if ($quote_count <= 1) {
  352. return $str;
  353. }
  354. // 如果出现次数大于 1, 创建数组以存放字符串段落
  355. $paragraphs = array();
  356. // 找到第一个结尾出现的位置
  357. $end = strpos(strtolower($str), $end_pattern);
  358. // 处理所有 blockquote
  359. while ($end) {
  360. // 获得尾部之前的子串
  361. $str_before_end = substr($str, 0, $end);
  362. // 结尾之前, 开始部分的出现次数
  363. $quote_count = substr_count(strtolower($str_before_end), $start_pattern);
  364. // 如果只有一个开头, 证明这是最外层引用, 放到段落数组里面
  365. if ($quote_count == 1) {
  366. $paragraph = substr($str, 0, $end + strlen($end_pattern));
  367. array_push($paragraphs, $paragraph);
  368. $sep = '';
  369. $str = substr_replace($str, $sep, 0, $end + strlen($end_pattern));
  370. // 如果出现多次开头部分
  371. } else {
  372. // 在子串中找到相应的开头位置
  373. $start = strrpos(strtolower($str_before_end), $start_pattern);
  374. // 将 blockquote 部分除去, 并用分隔符隔开
  375. $sep = ' ';
  376. $str = substr_replace($str, $sep, $start, $end + strlen($end_pattern) - $start);
  377. }
  378. // 找到下一个结尾的位置
  379. $end = strpos(strtolower($str), $end_pattern);
  380. }
  381. // 循环所有段落, 并组合成新的 HTML 字符串
  382. if ($paragraphs) {
  383. $str_before = '';
  384. foreach ($paragraphs as $paragraph) {
  385. $str_before .= $paragraph;
  386. }
  387. return $str_before . $str;
  388. }
  389. return $str;
  390. }
  391. /**
  392. * 获取评论者信息
  393. */
  394. function rc_get_author_info() {
  395. if (function_exists(display_commenter_info)) {
  396. return display_commenter_info('');
  397. }
  398. }
  399. ?>