折腾WordPress內置嵌套评论专用Ajax comments
前阵子折腾这个没有成功,今天搞定了。
文章有点长,边听下歌边看吧:
电台情歌 – <莫文蔚>
再去掉几个WP插件:
0×01
中文 WordPress 工具箱 (mulberrykit) 这个插件用了好久了,自从我建WP那天起就一直在用,今天突然打开它的源文件,看见它的代码 ,发现其实很久以来我只用到它的一个功能,就是截取UTF-8字符。
去掉这个插件,然后把以下代码加入functions.php即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // A trim function to remove the last character of a utf-8 string // by following instructions on http://en.wikipedia.org/wiki/UTF-8 // dotann function utf8_trim($str) { $len = strlen($str); for ($i=strlen($str)-1; $i>=0; $i-=1){ $hex .= ' '.ord($str[$i]); $ch = ord($str[$i]); if (($ch & 128)==0) return(substr($str,0,$i)); if (($ch & 192)==192) return(substr($str,0,$i)); } return($str.$hex); } function mul_excerpt ($excerpt) { $myexcerpt = substr($excerpt,0,255); return utf8_trim($myexcerpt) . '... '; } add_filter('the_excerpt', 'mul_excerpt'); add_filter('the_excerpt_rss', 'mul_excerpt'); |
0×02
wordpress-thread-comment 这个专门用来实现嵌套评论功能的插件也被我残忍地去掉了。感谢willin童鞋的折腾,呵呵,现在我的任务是继续他的折腾。 ![]()
用了willin大师的 《WordPress 內置嵌套評論專用 Ajax comments》 和 《Comment Mail Notify》
对于willin的 WordPress 內置嵌套評論專用 Ajax comments 中的 comments-ajax.php文件,我也做了些修改:
willin是把原版的wp-comments-post.php文件中的wp_die修改为err函数,然后再自定义一个名为err的函数,个人觉得无论从哪方面说这都是没必要的。
首先405 Method Not Allowed表示 提交方式不允许,并不是所有的错误都是由非法提交方式引起的,所以,我们不需要自定义函数了。只要简单了把wp_die修改为die就可以了。
另外,还发现willin的comments-ajax.php与wp原版的wp-comments-post.php文件不同的地方是添加了两个东东:
增加: 檢查評論太快功能
和
增加: 檢查重覆評論功能
其实这两个也是没有必要添加的。看下WP的代码就知道了:
在wp的default-filters.php文件中你可以看到以下代码:
//default-filters.php
1 2 | add_action( 'check_comment_flood', 'check_comment_flood_db', 10, 3 ); add_filter( 'comment_flood_filter', 'wp_throttle_comment_flood', 10, 3 ); |
再在wp的comments.php等文件可以看到如下相关代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | // wp_throttle_comment_flood函数用来检查评论者提交留言的时间是否满足是恶意灌水的条件 function wp_throttle_comment_flood($block, $time_lastcomment, $time_newcomment) { if ( $block ) // a plugin has already blocked... we'll let that decision stand return $block; if ( ($time_newcomment - $time_lastcomment) < 15 ) return true; return false; } //用来检测灌水的函数,对于管理员它是不检测的。 function check_comment_flood_db( $ip, $email, $date ) { global $wpdb; if ( current_user_can( 'manage_options' ) ) return; // don't throttle admins $hour_ago = gmdate( 'Y-m-d H:i:s', time() - 3600 ); if ( $lasttime = $wpdb->get_var( $wpdb->prepare( "SELECT `comment_date_gmt` FROM `$wpdb->comments` WHERE `comment_date_gmt` >= %s AND ( `comment_author_IP` = %s OR `comment_author_email` = %s ) ORDER BY `comment_date_gmt` DESC LIMIT 1", $hour_ago, $ip, $email ) ) ) { $time_lastcomment = mysql2date('U', $lasttime, false); $time_newcomment = mysql2date('U', $date, false); //这里调用了 wp_throttle_comment_flood 函数 $flood_die = apply_filters('comment_flood_filter', false, $time_lastcomment, $time_newcomment); if ( $flood_die ) { do_action('comment_flood_trigger', $time_lastcomment, $time_newcomment); if ( defined('DOING_AJAX') ) die( __('You are posting comments too quickly. Slow down.') ); wp_die( __('You are posting comments too quickly. Slow down.'), '', array('response' => 403) ); } } } //检测重复评论 和 恶意灌水 function wp_allow_comment($commentdata) { global $wpdb; extract($commentdata, EXTR_SKIP); /检测重复评论 // Simple duplicate check // expected_slashed ($comment_post_ID, $comment_author, $comment_author_email, $comment_content) $dupe = "SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = '$comment_post_ID' AND comment_approved != 'trash' AND ( comment_author = '$comment_author' "; if ( $comment_author_email ) $dupe .= "OR comment_author_email = '$comment_author_email' "; $dupe .= ") AND comment_content = '$comment_content' LIMIT 1"; if ( $wpdb->get_var($dupe) ) { if ( defined('DOING_AJAX') ) die( __('Duplicate comment detected; it looks as though you’ve already said that!') ); wp_die( __('Duplicate comment detected; it looks as though you’ve already said that!') ); } //恶意灌水检测,在这里会调用 check_comment_flood_db (此函数属于check_comment_flood action)等函数 do_action( 'check_comment_flood', $comment_author_IP, $comment_author_email, $comment_date_gmt ); if ( isset($user_id) && $user_id) { $userdata = get_userdata($user_id); $user = new WP_User($user_id); $post_author = $wpdb->get_var($wpdb->prepare("SELECT post_author FROM $wpdb->posts WHERE ID = %d LIMIT 1", $comment_post_ID)); } if ( isset($userdata) && ( $user_id == $post_author || $user->has_cap('moderate_comments') ) ) { // The author and the admins get respect. $approved = 1; } else { // Everyone else's comments will be checked. if ( check_comment($comment_author, $comment_author_email, $comment_author_url, $comment_content, $comment_author_IP, $comment_agent, $comment_type) ) $approved = 1; else $approved = 0; if ( wp_blacklist_check($comment_author, $comment_author_email, $comment_author_url, $comment_content, $comment_author_IP, $comment_agent) ) $approved = 'spam'; } $approved = apply_filters('pre_comment_approved', $approved); return $approved; } //新建评论的函数 function wp_new_comment( $commentdata ) { $commentdata = apply_filters('preprocess_comment', $commentdata); $commentdata['comment_post_ID'] = (int) $commentdata['comment_post_ID']; if ( isset($commentdata['user_ID']) ) $commentdata['user_id'] = $commentdata['user_ID'] = (int) $commentdata['user_ID']; elseif ( isset($commentdata['user_id']) ) $commentdata['user_id'] = (int) $commentdata['user_id']; $commentdata['comment_parent'] = isset($commentdata['comment_parent']) ? absint($commentdata['comment_parent']) : 0; $parent_status = ( 0 < $commentdata['comment_parent'] ) ? wp_get_comment_status($commentdata['comment_parent']) : ''; $commentdata['comment_parent'] = ( 'approved' == $parent_status || 'unapproved' == $parent_status ) ? $commentdata['comment_parent'] : 0; $commentdata['comment_author_IP'] = preg_replace( '/[^0-9a-fA-F:., ]/', '',$_SERVER['REMOTE_ADDR'] ); $commentdata['comment_agent'] = substr($_SERVER['HTTP_USER_AGENT'], 0, 254); $commentdata['comment_date'] = current_time('mysql'); $commentdata['comment_date_gmt'] = current_time('mysql', 1); $commentdata = wp_filter_comment($commentdata); $commentdata['comment_approved'] = wp_allow_comment($commentdata); $comment_ID = wp_insert_comment($commentdata); do_action('comment_post', $comment_ID, $commentdata['comment_approved']); if ( 'spam' !== $commentdata['comment_approved'] ) { // If it's spam save it silently for later crunching if ( '0' == $commentdata['comment_approved'] ) wp_notify_moderator($comment_ID); $post = &get_post($commentdata['comment_post_ID']); // Don't notify if it's your own comment if ( get_option('comments_notify') && $commentdata['comment_approved'] && $post->post_author != $commentdata['user_id'] ) wp_notify_postauthor($comment_ID, $commentdata['comment_type']); } return $comment_ID; } |
由此可见WP本身就有检测重复评论和恶意灌水的功能,没有必要重复添加代码了。
呵呵。
注意我添加了这个:
1 |
这是为什么?呵呵,肯定是有用的。由于我们是ajax获取返回数据,因此要让wordpress做die这个动作而不是wp_die,看下wp_allow_comment和check_comment_flood_db函数就知道了。
经我修改后的comments-ajax.php文件内容全部如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | <?php /** * Handles Comment Post to WordPress and prevents duplicate comment posting. * * @package WordPress */ if ( 'POST' != $_SERVER['REQUEST_METHOD'] ) { header('Allow: POST'); header('HTTP/1.1 405 Method Not Allowed'); header('Content-Type: text/plain'); exit; } //定义AJAX提交 define('DOING_AJAX', true); /** Sets up the WordPress Environment. */ //这个文件是放在主题目录下面的 require( dirname(__FILE__) . '/../../../wp-load.php' ); nocache_headers(); $comment_post_ID = isset($_POST['comment_post_ID']) ? (int) $_POST['comment_post_ID'] : 0; $status = $wpdb->get_row( $wpdb->prepare("SELECT post_status, comment_status FROM $wpdb->posts WHERE ID = %d", $comment_post_ID) ); if ( empty($status->comment_status) ) { do_action('comment_id_not_found', $comment_post_ID); die( __('Invalid comment status.') ); } elseif ( !comments_open($comment_post_ID) ) { do_action('comment_closed', $comment_post_ID); die( __('Sorry, comments are closed for this item.') ); } elseif ( in_array($status->post_status, array('draft', 'future', 'pending') ) ) { do_action('comment_on_draft', $comment_post_ID); die( __('The post you are trying to comment is not published currently.') ); } elseif ( 'trash' == $status->post_status ) { do_action('comment_on_trash', $comment_post_ID); die( __('Sorry, this post has been moved to trash.') ); } elseif ( post_password_required($comment_post_ID) ) { do_action('comment_on_password_protected', $comment_post_ID); die( __('Sorry, this post is password protected.') ); } else { do_action('pre_comment_on_post', $comment_post_ID); } $comment_author = ( isset($_POST['author']) ) ? trim(strip_tags($_POST['author'])) : null; $comment_author_email = ( isset($_POST['email']) ) ? trim($_POST['email']) : null; $comment_author_url = ( isset($_POST['url']) ) ? trim($_POST['url']) : null; $comment_content = ( isset($_POST['comment']) ) ? trim($_POST['comment']) : null; $edit_id = ( isset($_POST['edit_id']) ) ? $_POST['edit_id'] : null; // 提取 edit_id // If the user is logged in $user = wp_get_current_user(); if ( $user->ID ) { if ( empty( $user->display_name ) ) $user->display_name=$user->user_login; $comment_author = $wpdb->escape($user->display_name); $comment_author_email = $wpdb->escape($user->user_email); $comment_author_url = $wpdb->escape($user->user_url); if ( current_user_can('unfiltered_html') ) { if ( wp_create_nonce('unfiltered-html-comment_' . $comment_post_ID) != $_POST['_wp_unfiltered_html_comment'] ) { kses_remove_filters(); // start with a clean slate kses_init_filters(); // set up the filters } } } else { if ( get_option('comment_registration') || 'private' == $status->post_status ) die( __('Sorry, you must be logged in to post a comment.') ); } $comment_type = ''; if ( get_option('require_name_email') && !$user->ID ) { if ( 6 > strlen($comment_author_email) || '' == $comment_author ) die( __('Error: please fill the required fields (name, email).') ); elseif ( !is_email($comment_author_email)) die( __('Error: please enter a valid email address.') ); } if ( '' == $comment_content ) die( __('Error: please type a comment.') ); $comment_parent = isset($_POST['comment_parent']) ? absint($_POST['comment_parent']) : 0; $commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type', 'comment_parent', 'user_ID'); // 增加: 檢查評論是否正被編輯, 更新或新建評論 if ( $edit_id ) { $comment_id = $commentdata['comment_ID'] = $edit_id; wp_update_comment( $commentdata ); } else { $comment_id = wp_new_comment( $commentdata ); } $comment = get_comment($comment_id); if ( !$user->ID ) { $comment_cookie_lifetime = apply_filters('comment_cookie_lifetime', 30000000); setcookie('comment_author_' . COOKIEHASH, $comment->comment_author, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN); setcookie('comment_author_email_' . COOKIEHASH, $comment->comment_author_email, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN); setcookie('comment_author_url_' . COOKIEHASH, esc_url($comment->comment_author_url), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN); } /* $location = empty($_POST['redirect_to']) ? get_comment_link($comment_id) : $_POST['redirect_to'] . '#comment-' . $comment_id; $location = apply_filters('comment_post_redirect', $location, $comment); wp_redirect($location); */ $comment_depth = 1; //为评论的 class 属性准备的 $tmp_c = $comment; while($tmp_c->comment_parent != 0){ $comment_depth++; $tmp_c = get_comment($tmp_c->comment_parent); } //以下是評論式樣, 不含 "回覆". 要用你模板的式樣 copy 覆蓋. ?> <div class="<?php echo $oddcomment; ?><?php if ($first) { echo ' first'; $first = false; } ?>" id="comment-<?php comment_ID() ?>"> <div class="commentdetails"> <p class="commentauthor"><?php comment_author_link() ?></p> <?php if ($comment->comment_approved == '0') : ?> <em>Your comment is awaiting moderation.</em> <?php endif; ?> <p class="commentdate"><?php comment_date('F jS, Y') ?> at <?php comment_time() ?> <?php edit_comment_link('Edit Comment','',''); ?> </p> </div> <?php echo get_avatar($comment, 32); ?> <br class="break" /> <?php comment_text() ?> </div> |








再次受教~
(我错了,没能在相应的页面留下评论。希望博主不要鄙视我把评论复制过来的行为……)
果然还是建立在willin博客制作的ajax评论的基础之上。
我直接将willin的comments-ajax.php文件替换成博主的,其余一切按照willin的说明进行操作,却出现了错误:我以访客身份在自己的博客上留言(下同),刷新页面之前无法再编辑(没有提示与按钮)评论,而且评论显示起来没有任何样式,是彻头彻尾的纯文本;刷新之后,依旧无法再编辑评论,不过评论能正常显示了。
后来我将comments-ajax.php文件替换回willin的,没有再遇到评论显示方面的问题,但是很遗憾,刷新之后是不可再编辑评论的,这与我在博主博客上体验到的“刷新前后都能‘编辑’”情况相去甚远。不用说,这肯定是代码上的问题了,博主能再提示一下吗?
@3qsami
呵呵,这也不能算错误了。可能是很多人会觉得置顶的文章里的评论会容易看到一些吧~~不过我一般是在后台看评论的。再者,“知错能改 善莫大焉”啦。
不显示编辑按钮这个问题我也遇到过,以前我用的greenthewebnews主题就一直没办法显示。可能是js方面的一些冲突吧(不确定)。
“评论显示起来没有任何样式”的问题,其实只要你仔细看下 comments-ajax.php文件源码就会发现,willin特别在那里加上了注释“要用你模板的式樣 copy 覆蓋” ,也就是说,要用你的模板的comments.php 文件中调用显示评论时代码样式来重新覆盖掉这段代码。因为每个主题可能用的不同的CSS评论样式,没有css样式的评论,当然是非常有可能是看上去像“纯文本”。
@荒野无灯
非常感谢荒野无灯这么细致的回答。
不过如果非要把一些细节讲清楚,估计你一言我一语地永远不会有个头,所以,我觉得我的问题还是留待我学成相应背景知识后再来讨教,那样才皆大欢喜~
还是不明白那句define(‘DOING_AJAX’, true);是什么意思?
不知道博主能否简单讲解一下 .看到好多主题都用这个,但是我不是很明白
过来学习,搞这个回复再编辑头大了。。。
为什么截图上有两排一样重复发表评论的提示:
学习啦,呵呵。
又可以了。
其实我想说的是
返回的 http code 并不能触发jquery ajax的error,而是触发了success,错误结果只能当做一条新评论插入到评论列表中,并不是willin原来的错误处理机制。你的图,你的真相也是这样的结果。我现在想到的处理方法在是在success中加个判断,不知道你有没有更换的方法。
嗯,有返回肯定是触发success的啦。不过重复评论是不会入库的,WP给挡住了。
为什么刚才用这个昵称无法评论,封杀了?
字体好酷啊.我想知道这是什么字体..有什么办法改不- -
救命稻草啊,我之前用的 我一直被提示您的评论太快,不知道什么造成的,根据你的思路我重新整了我的代码,现在算是解决问题了
我的账户在我自己的blog一真提示你的评论太快 我快崩溃了
博主你好,我有一个问题想请问您。我用的是仿BlogBus主题,win主机,我的博客只能用IE浏览器发表评论,换默认主题就好了,本地测试也没事,我觉得是win主机不支持的comments-ajax?我也不知道!想请您帮忙解决
那我来试试
诚祝来年快乐、家庭幸福!
平安,如意!
谢谢!也预祝你2011幸福快乐!
那个输入用户信息的字体.
尝试一下博主的comments系统吧!!!
感觉jquery效果还可以!
学习了
字体好酷啊.我想知道这是什么字体..有什么办法改不- -
哪个字体?
真的很佩服,看到这么乱的代码头晕。。。
测试结果是无论是否需要审核都显示审核。。。。比较郁闷
我来看看学习下~~
噢, 那我来试试呢,我正好想用到
那我也来测试
测试下~
荒野大哥,这个应该大部分主题都通用的吧?
果然檢查出錯
晚上11点多了willin童鞋还在呃,
增加檢查評論太快和重覆評論功能, 修改 err 函数, 才能從 Ajax 回傳錯誤訊息啊~
當然不要也可以, 錯誤直接 die…
没有,我这里并不是直接die,和你的效果是一样的,可以返回信息的。wordpress本身已经考虑到AJAX提交信息的返回问题了。