2 add_action( 'admin_menu', 'akismet_admin_menu' );
4 akismet_admin_warnings();
6 function akismet_admin_init() {
9 // all admin functions are disabled in old versions
10 if ( !function_exists('is_multisite') && version_compare( $wp_version, '3.0', '<' ) ) {
12 function akismet_version_warning() {
14 <div id='akismet-warning' class='updated fade'><p><strong>".sprintf(__('Akismet %s requires WordPress 3.0 or higher.'), AKISMET_VERSION) ."</strong> ".sprintf(__('Please <a href="%s">upgrade WordPress</a> to a current version, or <a href="%s">downgrade to version 2.4 of the Akismet plugin</a>.'), 'http://codex.wordpress.org/Upgrading_WordPress', 'http://wordpress.org/extend/plugins/akismet/download/'). "</p></div>
17 add_action('admin_notices', 'akismet_version_warning');
22 if ( function_exists( 'get_plugin_page_hook' ) )
23 $hook = get_plugin_page_hook( 'akismet-stats-display', 'index.php' );
25 $hook = 'dashboard_page_akismet-stats-display';
26 add_meta_box('akismet-status', __('Comment History'), 'akismet_comment_status_meta_box', 'comment', 'normal');
28 add_action('admin_init', 'akismet_admin_init');
30 add_action( 'admin_enqueue_scripts', 'akismet_load_js_and_css' );
31 function akismet_load_js_and_css() {
35 $hook_suffix == 'index.php' # dashboard
36 || $hook_suffix == 'edit-comments.php'
37 || $hook_suffix == 'comment.php'
38 || $hook_suffix == 'post.php'
39 || $hook_suffix == 'plugins_page_akismet-key-config'
41 wp_register_style( 'akismet.css', AKISMET_PLUGIN_URL . 'akismet.css', array(), '2.5.4.4' );
42 wp_enqueue_style( 'akismet.css');
44 wp_register_script( 'akismet.js', AKISMET_PLUGIN_URL . 'akismet.js', array('jquery'), '2.5.4.6' );
45 wp_enqueue_script( 'akismet.js' );
46 wp_localize_script( 'akismet.js', 'WPAkismet', array(
47 'comment_author_url_nonce' => wp_create_nonce( 'comment_author_url_nonce' )
53 function akismet_nonce_field($action = -1) { return wp_nonce_field($action); }
54 $akismet_nonce = 'akismet-update-key';
56 function akismet_plugin_action_links( $links, $file ) {
57 if ( $file == plugin_basename( dirname(__FILE__).'/akismet.php' ) ) {
58 $links[] = '<a href="' . admin_url( 'admin.php?page=akismet-key-config' ) . '">'.__( 'Settings' ).'</a>';
64 add_filter( 'plugin_action_links', 'akismet_plugin_action_links', 10, 2 );
66 function akismet_conf() {
67 global $akismet_nonce, $wpcom_api_key;
69 if ( isset($_POST['submit']) ) {
70 if ( function_exists('current_user_can') && !current_user_can('manage_options') )
71 die(__('Cheatin’ uh?'));
73 check_admin_referer( $akismet_nonce );
74 $key = preg_replace( '/[^a-h0-9]/i', '', $_POST['key'] );
75 $home_url = parse_url( get_bloginfo('url') );
78 $key_status = 'empty';
79 $ms[] = 'new_key_empty';
80 delete_option('wordpress_api_key');
81 } elseif ( empty($home_url['host']) ) {
82 $key_status = 'empty';
83 $ms[] = 'bad_home_url';
85 $key_status = akismet_verify_key( $key );
88 if ( $key_status == 'valid' ) {
89 update_option('wordpress_api_key', $key);
90 $ms[] = 'new_key_valid';
91 } else if ( $key_status == 'invalid' ) {
92 $ms[] = 'new_key_invalid';
93 } else if ( $key_status == 'failed' ) {
94 $ms[] = 'new_key_failed';
97 if ( isset( $_POST['akismet_discard_month'] ) )
98 update_option( 'akismet_discard_month', 'true' );
100 update_option( 'akismet_discard_month', 'false' );
102 if ( isset( $_POST['akismet_show_user_comments_approved'] ) )
103 update_option( 'akismet_show_user_comments_approved', 'true' );
105 update_option( 'akismet_show_user_comments_approved', 'false' );
107 } elseif ( isset($_POST['check']) ) {
108 akismet_get_server_connectivity(0);
111 if ( empty( $key_status) || $key_status != 'valid' ) {
112 $key = get_option('wordpress_api_key');
113 if ( empty( $key ) ) {
114 if ( empty( $key_status ) || $key_status != 'failed' ) {
115 if ( akismet_verify_key( '1234567890ab' ) == 'failed' )
116 $ms[] = 'no_connection';
120 $key_status = 'empty';
122 $key_status = akismet_verify_key( $key );
124 if ( $key_status == 'valid' ) {
126 } else if ( $key_status == 'invalid' ) {
127 $ms[] = 'key_invalid';
128 } else if ( !empty($key) && $key_status == 'failed' ) {
129 $ms[] = 'key_failed';
134 'new_key_empty' => array('color' => 'aa0', 'text' => __('Your key has been cleared.')),
135 'new_key_valid' => array('color' => '4AB915', 'text' => __('Your key has been verified. Happy blogging!')),
136 'new_key_invalid' => array('color' => '888', 'text' => __('The key you entered is invalid. Please double-check it.')),
137 'new_key_failed' => array('color' => '888', 'text' => __('The key you entered could not be verified because a connection to akismet.com could not be established. Please check your server configuration.')),
138 'no_connection' => array('color' => '888', 'text' => __('There was a problem connecting to the Akismet server. Please check your server configuration.')),
139 'key_empty' => array('color' => 'aa0', 'text' => sprintf(__('Please enter an API key. (<a href="%s" style="color:#fff">Get your key.</a>)'), 'http://akismet.com/get/?return=true')),
140 'key_valid' => array('color' => '4AB915', 'text' => __('This key is valid.')),
141 'key_invalid' => array('color' => '888', 'text' => __('This key is invalid.')),
142 'key_failed' => array('color' => 'aa0', 'text' => __('The key below was previously validated but a connection to akismet.com can not be established at this time. Please check your server configuration.')),
143 'bad_home_url' => array('color' => '888', 'text' => sprintf( __('Your WordPress home URL %s is invalid. Please fix the <a href="%s">home option</a>.'), esc_html( get_bloginfo('url') ), admin_url('options.php#home') ) ),
146 <?php if ( !empty($_POST['submit'] ) ) : ?>
147 <div id="message" class="updated fade"><p><strong><?php _e('Options saved.') ?></strong></p></div>
150 <h2><?php _e('Akismet Configuration'); ?></h2>
151 <?php if (isset($_GET['message']) && $_GET['message'] == 'success') { ?>
152 <div class="updated below-h2" id="message"><p><?php _e( '<strong>Sign up success!</strong> Please check your email for your Akismet API Key and enter it below.' ); ?></p></div>
155 <form action="" method="post" id="akismet-conf" style="margin: auto; width: 400px; ">
156 <?php if ( !$wpcom_api_key ) { ?>
157 <p><?php printf(__('For many people, <a href="%1$s">Akismet</a> will greatly reduce or even completely eliminate the comment and trackback spam you get on your site. If one does happen to get through, simply mark it as "spam" on the moderation screen and Akismet will learn from the mistakes. If you don\'t have an API key yet, you can get one at <a href="%2$s">Akismet.com</a>.'), 'http://akismet.com/?return=true', 'http://akismet.com/get/?return=true'); ?></p>
159 <h3><label for="key"><?php _e('Akismet API Key'); ?></label></h3>
160 <?php foreach ( $ms as $m ) : ?>
161 <p style="padding: .5em; background-color: #<?php echo $messages[$m]['color']; ?>; color: #fff; font-weight: bold;"><?php echo $messages[$m]['text']; ?></p>
163 <p><input id="key" name="key" type="text" size="15" maxlength="12" value="<?php echo get_option('wordpress_api_key'); ?>" style="font-family: 'Courier New', Courier, mono; font-size: 1.5em;" /> (<?php _e('<a href="http://akismet.com/get/?return=true">What is this?</a>'); ?>)</p>
164 <?php if ( isset( $invalid_key) && $invalid_key ) { ?>
165 <h3><?php _e('Why might my key be invalid?'); ?></h3>
166 <p><?php _e('This can mean one of two things, either you copied the key wrong or that the plugin is unable to reach the Akismet servers, which is most often caused by an issue with your web host around firewalls or similar.'); ?></p>
169 <?php akismet_nonce_field($akismet_nonce) ?>
170 <p><label><input name="akismet_discard_month" id="akismet_discard_month" value="true" type="checkbox" <?php if ( get_option('akismet_discard_month') == 'true' ) echo ' checked="checked" '; ?> /> <?php _e('Auto-delete spam submitted on posts more than a month old.'); ?></label></p>
171 <p><label><input name="akismet_show_user_comments_approved" id="akismet_show_user_comments_approved" value="true" type="checkbox" <?php if ( get_option('akismet_show_user_comments_approved') == 'true' ) echo ' checked="checked" '; ?> /> <?php _e('Show the number of comments you\'ve approved beside each comment author.'); ?></label></p>
172 <p class="submit"><input type="submit" name="submit" value="<?php _e('Update options »'); ?>" /></p>
175 <form action="" method="post" id="akismet-connectivity" style="margin: auto; width: 400px; ">
177 <h3><?php _e('Server Connectivity'); ?></h3>
179 if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') ) {
181 <p style="padding: .5em; background-color: #888; color: #fff; font-weight:bold;"><?php _e('Network functions are disabled.'); ?></p>
182 <p><?php echo sprintf( __('Your web host or server administrator has disabled PHP\'s <code>fsockopen</code> or <code>gethostbynamel</code> functions. <strong>Akismet cannot work correctly until this is fixed.</strong> Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet\'s system requirements</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
185 $servers = akismet_get_server_connectivity();
186 $fail_count = count($servers) - count( array_filter($servers) );
187 if ( is_array($servers) && count($servers) > 0 ) {
188 // some connections work, some fail
189 if ( $fail_count > 0 && $fail_count < count($servers) ) { ?>
190 <p style="padding: .5em; background-color: #aa0; color: #fff; font-weight:bold;"><?php _e('Unable to reach some Akismet servers.'); ?></p>
191 <p><?php echo sprintf( __('A network problem or firewall is blocking some connections from your web server to Akismet.com. Akismet is working but this may cause problems during times of network congestion. Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet and firewalls</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
193 // all connections fail
194 } elseif ( $fail_count > 0 ) { ?>
195 <p style="padding: .5em; background-color: #888; color: #fff; font-weight:bold;"><?php _e('Unable to reach any Akismet servers.'); ?></p>
196 <p><?php echo sprintf( __('A network problem or firewall is blocking all connections from your web server to Akismet.com. <strong>Akismet cannot work correctly until this is fixed.</strong> Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet and firewalls</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
198 // all connections work
200 <p style="padding: .5em; background-color: #4AB915; color: #fff; font-weight:bold;"><?php _e('All Akismet servers are available.'); ?></p>
201 <p><?php _e('Akismet is working correctly. All servers are accessible.'); ?></p>
206 <p style="padding: .5em; background-color: #888; color: #fff; font-weight:bold;"><?php _e('Unable to find Akismet servers.'); ?></p>
207 <p><?php echo sprintf( __('A DNS problem or firewall is preventing all access from your web server to Akismet.com. <strong>Akismet cannot work correctly until this is fixed.</strong> Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet and firewalls</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
212 if ( !empty($servers) ) {
214 <table style="width: 100%;">
215 <thead><th><?php _e('Akismet server'); ?></th><th><?php _e('Network Status'); ?></th></thead>
219 foreach ( $servers as $ip => $status ) {
220 $color = ( $status ? '#4AB915' : '#888');
223 <td><?php echo htmlspecialchars($ip); ?></td>
224 <td style="padding: 0 .5em; font-weight:bold; color: #fff; background-color: <?php echo $color; ?>"><?php echo ($status ? __('Accessible') : __('Re-trying') ); ?></td>
232 <p><?php if ( get_option('akismet_connectivity_time') ) echo sprintf( __('Last checked %s ago.'), human_time_diff( get_option('akismet_connectivity_time') ) ); ?></p>
233 <p class="submit"><input type="submit" name="check" value="<?php _e('Check network status »'); ?>" /></p>
234 <p><?php printf( __('<a href="%s" target="_blank">Click here</a> to confirm that <a href="%s" target="_blank">Akismet.com is up</a>.'), 'http://status.automattic.com/9931/136079/Akismet-API', 'http://status.automattic.com/9931/136079/Akismet-API' ); ?></p>
242 function akismet_stats_display() {
243 global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
244 $blog = urlencode( get_bloginfo('url') );
250 $url .= 'akismet.com/web/1.0/user-stats.php';
251 $url .= "?blog={$blog}&api_key=" . akismet_get_key();
254 <iframe src="<?php echo $url; ?>" width="100%" height="2500px" frameborder="0" id="akismet-stats-frame"></iframe>
259 function akismet_stats() {
260 if ( !function_exists('did_action') || did_action( 'rightnow_end' ) ) // We already displayed this info in the "Right Now" section
262 if ( !$count = get_option('akismet_spam_count') )
264 $path = plugin_basename(__FILE__);
265 echo '<h3>' . _x( 'Spam', 'comments' ) . '</h3>';
267 if ( isset( $submenu['edit-comments.php'] ) )
268 $link = 'edit-comments.php';
271 echo '<p>'.sprintf( _n( '<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comments</a>.', '<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comments</a>.', $count ), 'http://akismet.com/?return=true', clean_url("$link?page=akismet-admin"), number_format_i18n($count) ).'</p>';
273 add_action('activity_box_end', 'akismet_stats');
275 function akismet_admin_warnings() {
276 global $wpcom_api_key, $pagenow;
279 $pagenow == 'edit-comments.php'
280 || ( !empty( $_GET['page'] ) && $_GET['page'] == 'akismet-key-config' )
281 || ( !empty( $_GET['page'] ) && $_GET['page'] == 'akismet-stats-display' )
283 if ( get_option( 'akismet_alert_code' ) ) {
284 function akismet_alert() {
286 'code' => (int) get_option( 'akismet_alert_code' ),
287 'msg' => get_option( 'akismet_alert_msg' )
291 <p><strong>Akismet Error Code: <?php echo $alert['code']; ?></strong></p>
292 <p><?php esc_html_e( $alert['msg'] ); ?></p>
293 <p>More information is available at <a href="https://akismet.com/errors/<?php echo $alert['code']; ?>">https://akismet.com/errors/<?php echo $alert['code']; ?></a></p>
298 add_action( 'admin_notices', 'akismet_alert' );
302 if ( !get_option('wordpress_api_key') && !$wpcom_api_key && !isset($_POST['submit']) ) {
303 function akismet_warning() {
305 <div id='akismet-warning' class='updated fade'><p><strong>".__('Akismet is almost ready.')."</strong> ".sprintf(__('You must <a href="%1$s">enter your Akismet API key</a> for it to work.'), "admin.php?page=akismet-key-config")."</p></div>
308 add_action('admin_notices', 'akismet_warning');
310 } elseif ( ( empty($_SERVER['SCRIPT_FILENAME']) || basename($_SERVER['SCRIPT_FILENAME']) == 'edit-comments.php' ) && wp_next_scheduled('akismet_schedule_cron_recheck') ) {
311 function akismet_warning() {
313 akismet_fix_scheduled_recheck();
314 $waiting = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->commentmeta WHERE meta_key = 'akismet_error'" );
315 $next_check = wp_next_scheduled('akismet_schedule_cron_recheck');
316 if ( $waiting > 0 && $next_check > time() )
318 <div id='akismet-warning' class='updated fade'><p><strong>".__('Akismet has detected a problem.')."</strong> ".sprintf(__('Some comments have not yet been checked for spam by Akismet. They have been temporarily held for moderation. Please check your <a href="%s">Akismet configuration</a> and contact your web host if problems persist.'), 'admin.php?page=akismet-key-config')."</p></div>
321 add_action('admin_notices', 'akismet_warning');
328 function akismet_comment_row_action( $a, $comment ) {
330 // failsafe for old WP versions
331 if ( !function_exists('add_comment_meta') )
334 $akismet_result = get_comment_meta( $comment->comment_ID, 'akismet_result', true );
335 $akismet_error = get_comment_meta( $comment->comment_ID, 'akismet_error', true );
336 $user_result = get_comment_meta( $comment->comment_ID, 'akismet_user_result', true);
337 $comment_status = wp_get_comment_status( $comment->comment_ID );
339 if ( $akismet_error ) {
340 $desc = __( 'Awaiting spam check' );
341 } elseif ( !$user_result || $user_result == $akismet_result ) {
342 // Show the original Akismet result if the user hasn't overridden it, or if their decision was the same
343 if ( $akismet_result == 'true' && $comment_status != 'spam' && $comment_status != 'trash' )
344 $desc = __( 'Flagged as spam by Akismet' );
345 elseif ( $akismet_result == 'false' && $comment_status == 'spam' )
346 $desc = __( 'Cleared by Akismet' );
348 $who = get_comment_meta( $comment->comment_ID, 'akismet_user', true );
349 if ( $user_result == 'true' )
350 $desc = sprintf( __('Flagged as spam by %s'), $who );
352 $desc = sprintf( __('Un-spammed by %s'), $who );
355 // add a History item to the hover links, just after Edit
356 if ( $akismet_result ) {
358 foreach ( $a as $k => $item ) {
362 || ( $k == 'unspam' && $GLOBALS['wp_version'] >= 3.4 )
364 $b['history'] = '<a href="comment.php?action=editcomment&c='.$comment->comment_ID.'#akismet-status" title="'. esc_attr__( 'View comment history' ) . '"> '. __('History') . '</a>';
372 echo '<span class="akismet-status" commentid="'.$comment->comment_ID.'"><a href="comment.php?action=editcomment&c='.$comment->comment_ID.'#akismet-status" title="' . esc_attr__( 'View comment history' ) . '">'.htmlspecialchars($desc).'</a></span>';
374 if ( apply_filters( 'akismet_show_user_comments_approved', get_option('akismet_show_user_comments_approved') ) == 'true' ) {
375 $comment_count = akismet_get_user_comments_approved( $comment->user_id, $comment->comment_author_email, $comment->comment_author, $comment->comment_author_url );
376 $comment_count = intval( $comment_count );
377 echo '<span class="akismet-user-comment-count" commentid="'.$comment->comment_ID.'" style="display:none;"><br><span class="akismet-user-comment-counts">'.sprintf( _n( '%s approved', '%s approved', $comment_count ), number_format_i18n( $comment_count ) ) . '</span></span>';
383 add_filter( 'comment_row_actions', 'akismet_comment_row_action', 10, 2 );
385 function akismet_comment_status_meta_box($comment) {
386 $history = akismet_get_comment_history( $comment->comment_ID );
389 echo '<div class="akismet-history" style="margin: 13px;">';
390 foreach ( $history as $row ) {
391 $time = date( 'D d M Y @ h:i:m a', $row['time'] ) . ' GMT';
392 echo '<div style="margin-bottom: 13px;"><span style="color: #999;" alt="' . $time . '" title="' . $time . '">' . sprintf( __('%s ago'), human_time_diff( $row['time'] ) ) . '</span> - ';
393 echo htmlspecialchars( $row['message'] ) . '</div>';
402 // add an extra column header to the comments screen
403 function akismet_comments_columns( $columns ) {
404 $columns[ 'akismet' ] = __( 'Akismet' );
408 #add_filter( 'manage_edit-comments_columns', 'akismet_comments_columns' );
410 // Show stuff in the extra column
411 function akismet_comment_column_row( $column, $comment_id ) {
412 if ( $column != 'akismet' )
415 $history = akismet_get_comment_history( $comment_id );
418 echo '<dl class="akismet-history">';
419 foreach ( $history as $row ) {
420 echo '<dt>' . sprintf( __('%s ago'), human_time_diff( $row['time'] ) ) . '</dt>';
421 echo '<dd>' . htmlspecialchars( $row['message'] ) . '</dd>';
428 #add_action( 'manage_comments_custom_column', 'akismet_comment_column_row', 10, 2 );
432 // call out URLS in comments
433 function akismet_text_add_link_callback( $m ) {
436 if ( $m[4] == $m[2] )
437 return '<a '.$m[1].' href="'.$m[2].'" '.$m[3].' class="comment-link">'.$m[4].'</a>';
439 return '<span title="'.$m[2].'" class="comment-link"><a '.$m[1].' href="'.$m[2].'" '.$m[3].' class="comment-link">'.$m[4].'</a></span>';
442 function akismet_text_add_link_class( $comment_text ) {
444 return preg_replace_callback( '#<a ([^>]*)href="([^"]+)"([^>]*)>(.*?)</a>#i', 'akismet_text_add_link_callback', $comment_text );
447 add_filter('comment_text', 'akismet_text_add_link_class');
451 function akismet_rightnow() {
452 global $submenu, $wp_db_version;
454 if ( 8645 < $wp_db_version ) // 2.7
455 $link = 'edit-comments.php?comment_status=spam';
456 elseif ( isset( $submenu['edit-comments.php'] ) )
457 $link = 'edit-comments.php?page=akismet-admin';
459 $link = 'edit.php?page=akismet-admin';
461 if ( $count = get_option('akismet_spam_count') ) {
462 $intro = sprintf( _n(
463 '<a href="%1$s">Akismet</a> has protected your site from %2$s spam comment already. ',
464 '<a href="%1$s">Akismet</a> has protected your site from %2$s spam comments already. ',
466 ), 'http://akismet.com/?return=true', number_format_i18n( $count ) );
468 $intro = sprintf( __('<a href="%1$s">Akismet</a> blocks spam from getting to your blog. '), 'http://akismet.com/?return=true' );
471 $link = function_exists( 'esc_url' ) ? esc_url( $link ) : clean_url( $link );
472 if ( $queue_count = akismet_spam_count() ) {
473 $queue_text = sprintf( _n(
474 'There\'s <a href="%2$s">%1$s comment</a> in your spam queue right now.',
475 'There are <a href="%2$s">%1$s comments</a> in your spam queue right now.',
477 ), number_format_i18n( $queue_count ), $link );
479 $queue_text = sprintf( __( "There's nothing in your <a href='%1\$s'>spam queue</a> at the moment." ), $link );
482 $text = $intro . '<br />' . $queue_text;
483 echo "<p class='akismet-right-now'>$text</p>\n";
486 add_action('rightnow_end', 'akismet_rightnow');
490 function akismet_check_for_spam_button($comment_status) {
491 if ( 'approved' == $comment_status )
493 if ( function_exists('plugins_url') )
494 $link = 'admin.php?action=akismet_recheck_queue';
496 $link = 'edit-comments.php?page=akismet-admin&recheckqueue=true&noheader=true';
497 echo "</div><div class='alignleft'><a class='button-secondary checkforspam' href='$link'>" . __('Check for Spam') . "</a>";
499 add_action('manage_comments_nav', 'akismet_check_for_spam_button');
501 function akismet_submit_nonspam_comment ( $comment_id ) {
502 global $wpdb, $akismet_api_host, $akismet_api_port, $current_user, $current_site;
503 $comment_id = (int) $comment_id;
505 $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment_id'");
506 if ( !$comment ) // it was deleted
509 // use the original version stored in comment_meta if available
510 $as_submitted = get_comment_meta( $comment_id, 'akismet_as_submitted', true);
511 if ( $as_submitted && is_array($as_submitted) && isset($as_submitted['comment_content']) ) {
512 $comment = (object) array_merge( (array)$comment, $as_submitted );
515 $comment->blog = get_bloginfo('url');
516 $comment->blog_lang = get_locale();
517 $comment->blog_charset = get_option('blog_charset');
518 $comment->permalink = get_permalink($comment->comment_post_ID);
519 $comment->reporter_ip = $_SERVER['REMOTE_ADDR'];
520 if ( is_object($current_user) ) {
521 $comment->reporter = $current_user->user_login;
523 if ( is_object($current_site) ) {
524 $comment->site_domain = $current_site->domain;
527 $comment->user_role = '';
528 if ( isset( $comment->user_ID ) )
529 $comment->user_role = akismet_get_user_roles($comment->user_ID);
531 if ( akismet_test_mode() )
532 $comment->is_test = 'true';
534 $post = get_post( $comment->comment_post_ID );
535 $comment->comment_post_modified_gmt = $post->post_modified_gmt;
538 foreach ( $comment as $key => $data )
539 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
541 $response = akismet_http_post($query_string, $akismet_api_host, "/1.1/submit-ham", $akismet_api_port);
542 if ( $comment->reporter ) {
543 akismet_update_comment_history( $comment_id, sprintf( __('%s reported this comment as not spam'), $comment->reporter ), 'report-ham' );
544 update_comment_meta( $comment_id, 'akismet_user_result', 'false' );
545 update_comment_meta( $comment_id, 'akismet_user', $comment->reporter );
548 do_action('akismet_submit_nonspam_comment', $comment_id, $response[1]);
551 function akismet_submit_spam_comment ( $comment_id ) {
552 global $wpdb, $akismet_api_host, $akismet_api_port, $current_user, $current_site;
553 $comment_id = (int) $comment_id;
555 $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment_id'");
556 if ( !$comment ) // it was deleted
558 if ( 'spam' != $comment->comment_approved )
561 // use the original version stored in comment_meta if available
562 $as_submitted = get_comment_meta( $comment_id, 'akismet_as_submitted', true);
563 if ( $as_submitted && is_array($as_submitted) && isset($as_submitted['comment_content']) ) {
564 $comment = (object) array_merge( (array)$comment, $as_submitted );
567 $comment->blog = get_bloginfo('url');
568 $comment->blog_lang = get_locale();
569 $comment->blog_charset = get_option('blog_charset');
570 $comment->permalink = get_permalink($comment->comment_post_ID);
571 $comment->reporter_ip = $_SERVER['REMOTE_ADDR'];
572 if ( is_object($current_user) ) {
573 $comment->reporter = $current_user->user_login;
575 if ( is_object($current_site) ) {
576 $comment->site_domain = $current_site->domain;
579 $comment->user_role = '';
580 if ( isset( $comment->user_ID ) )
581 $comment->user_role = akismet_get_user_roles($comment->user_ID);
583 if ( akismet_test_mode() )
584 $comment->is_test = 'true';
586 $post = get_post( $comment->comment_post_ID );
587 $comment->comment_post_modified_gmt = $post->post_modified_gmt;
590 foreach ( $comment as $key => $data )
591 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
593 $response = akismet_http_post($query_string, $akismet_api_host, "/1.1/submit-spam", $akismet_api_port);
594 if ( $comment->reporter ) {
595 akismet_update_comment_history( $comment_id, sprintf( __('%s reported this comment as spam'), $comment->reporter ), 'report-spam' );
596 update_comment_meta( $comment_id, 'akismet_user_result', 'true' );
597 update_comment_meta( $comment_id, 'akismet_user', $comment->reporter );
599 do_action('akismet_submit_spam_comment', $comment_id, $response[1]);
603 function akismet_transition_comment_status( $new_status, $old_status, $comment ) {
604 if ( $new_status == $old_status )
607 # we don't need to record a history item for deleted comments
608 if ( $new_status == 'delete' )
614 if ( !current_user_can( 'edit_post', $comment->comment_post_ID ) && !current_user_can( 'moderate_comments' ) )
617 if ( defined('WP_IMPORTING') && WP_IMPORTING == true )
620 // if this is present, it means the status has been changed by a re-check, not an explicit user action
621 if ( get_comment_meta( $comment->comment_ID, 'akismet_rechecking' ) )
624 global $current_user;
626 if ( is_object( $current_user ) )
627 $reporter = $current_user->user_login;
630 // We want to submit comments to Akismet only when a moderator explicitly spams or approves it - not if the status
631 // is changed automatically by another plugin. Unfortunately WordPress doesn't provide an unambiguous way to
632 // determine why the transition_comment_status action was triggered. And there are several different ways by which
633 // to spam and unspam comments: bulk actions, ajax, links in moderation emails, the dashboard, and perhaps others.
634 // We'll assume that this is an explicit user action if POST or GET has an 'action' key.
635 if ( isset($_POST['action']) || isset($_GET['action']) ) {
636 if ( $new_status == 'spam' && ( $old_status == 'approved' || $old_status == 'unapproved' || !$old_status ) ) {
637 return akismet_submit_spam_comment( $comment->comment_ID );
638 } elseif ( $old_status == 'spam' && ( $new_status == 'approved' || $new_status == 'unapproved' ) ) {
639 return akismet_submit_nonspam_comment( $comment->comment_ID );
643 akismet_update_comment_history( $comment->comment_ID, sprintf( __('%s changed the comment status to %s'), $reporter, $new_status ), 'status-' . $new_status );
646 add_action( 'transition_comment_status', 'akismet_transition_comment_status', 10, 3 );
648 // Total spam in queue
649 // get_option( 'akismet_spam_count' ) is the total caught ever
650 function akismet_spam_count( $type = false ) {
653 if ( !$type ) { // total
654 $count = wp_cache_get( 'akismet_spam_count', 'widget' );
655 if ( false === $count ) {
656 if ( function_exists('wp_count_comments') ) {
657 $count = wp_count_comments();
658 $count = $count->spam;
660 $count = (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam'");
662 wp_cache_set( 'akismet_spam_count', $count, 'widget', 3600 );
665 } elseif ( 'comments' == $type || 'comment' == $type ) { // comments
667 } else { // pingback, trackback, ...
668 $type = $wpdb->escape( $type );
671 return (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam' AND comment_type='$type'");
675 function akismet_recheck_queue() {
676 global $wpdb, $akismet_api_host, $akismet_api_port;
678 akismet_fix_scheduled_recheck();
680 if ( ! ( isset( $_GET['recheckqueue'] ) || ( isset( $_REQUEST['action'] ) && 'akismet_recheck_queue' == $_REQUEST['action'] ) ) )
683 $moderation = $wpdb->get_results( "SELECT * FROM $wpdb->comments WHERE comment_approved = '0'", ARRAY_A );
684 foreach ( (array) $moderation as $c ) {
685 $c['user_ip'] = $c['comment_author_IP'];
686 $c['user_agent'] = $c['comment_agent'];
688 $c['blog'] = get_bloginfo('url');
689 $c['blog_lang'] = get_locale();
690 $c['blog_charset'] = get_option('blog_charset');
691 $c['permalink'] = get_permalink($c['comment_post_ID']);
693 $c['user_role'] = '';
694 if ( isset( $c['user_ID'] ) )
695 $c['user_role'] = akismet_get_user_roles($c['user_ID']);
697 if ( akismet_test_mode() )
698 $c['is_test'] = 'true';
700 $id = (int) $c['comment_ID'];
703 foreach ( $c as $key => $data )
704 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
706 add_comment_meta( $c['comment_ID'], 'akismet_rechecking', true );
707 $response = akismet_http_post($query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port);
708 if ( 'true' == $response[1] ) {
709 wp_set_comment_status($c['comment_ID'], 'spam');
710 update_comment_meta( $c['comment_ID'], 'akismet_result', 'true' );
711 delete_comment_meta( $c['comment_ID'], 'akismet_error' );
712 akismet_update_comment_history( $c['comment_ID'], __('Akismet re-checked and caught this comment as spam'), 'check-spam' );
714 } elseif ( 'false' == $response[1] ) {
715 update_comment_meta( $c['comment_ID'], 'akismet_result', 'false' );
716 delete_comment_meta( $c['comment_ID'], 'akismet_error' );
717 akismet_update_comment_history( $c['comment_ID'], __('Akismet re-checked and cleared this comment'), 'check-ham' );
718 // abnormal result: error
720 update_comment_meta( $c['comment_ID'], 'akismet_result', 'error' );
721 akismet_update_comment_history( $c['comment_ID'], sprintf( __('Akismet was unable to re-check this comment (response: %s)'), substr($response[1], 0, 50)), 'check-error' );
724 delete_comment_meta( $c['comment_ID'], 'akismet_rechecking' );
726 $redirect_to = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : admin_url( 'edit-comments.php' );
727 wp_safe_redirect( $redirect_to );
731 add_action('admin_action_akismet_recheck_queue', 'akismet_recheck_queue');
733 // Adds an 'x' link next to author URLs, clicking will remove the author URL and show an undo link
734 function akismet_remove_comment_author_url() {
735 if ( !empty($_POST['id'] ) && check_admin_referer( 'comment_author_url_nonce' ) ) {
737 $comment = get_comment( intval($_POST['id']), ARRAY_A );
738 if (current_user_can('edit_comment', $comment['comment_ID'])) {
739 $comment['comment_author_url'] = '';
740 do_action( 'comment_remove_author_url' );
741 print(wp_update_comment( $comment ));
747 add_action('wp_ajax_comment_author_deurl', 'akismet_remove_comment_author_url');
749 function akismet_add_comment_author_url() {
750 if ( !empty( $_POST['id'] ) && !empty( $_POST['url'] ) && check_admin_referer( 'comment_author_url_nonce' ) ) {
752 $comment = get_comment( intval($_POST['id']), ARRAY_A );
753 if (current_user_can('edit_comment', $comment['comment_ID'])) {
754 $comment['comment_author_url'] = esc_url($_POST['url']);
755 do_action( 'comment_add_author_url' );
756 print(wp_update_comment( $comment ));
762 add_action('wp_ajax_comment_author_reurl', 'akismet_add_comment_author_url');
764 // Check connectivity between the WordPress blog and Akismet's servers.
765 // Returns an associative array of server IP addresses, where the key is the IP address, and value is true (available) or false (unable to connect).
766 function akismet_check_server_connectivity() {
767 global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
769 $test_host = 'rest.akismet.com';
771 // Some web hosts may disable one or both functions
772 if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') )
775 $ips = gethostbynamel($test_host);
776 if ( !$ips || !is_array($ips) || !count($ips) )
780 foreach ( $ips as $ip ) {
781 $response = akismet_verify_key( akismet_get_key(), $ip );
782 // even if the key is invalid, at least we know we have connectivity
783 if ( $response == 'valid' || $response == 'invalid' )
784 $servers[$ip] = true;
786 $servers[$ip] = false;
792 // Check the server connectivity and store the results in an option.
793 // Cached results will be used if not older than the specified timeout in seconds; use $cache_timeout = 0 to force an update.
794 // Returns the same associative array as akismet_check_server_connectivity()
795 function akismet_get_server_connectivity( $cache_timeout = 86400 ) {
796 $servers = get_option('akismet_available_servers');
797 if ( (time() - get_option('akismet_connectivity_time') < $cache_timeout) && $servers !== false )
800 // There's a race condition here but the effect is harmless.
801 $servers = akismet_check_server_connectivity();
802 update_option('akismet_available_servers', $servers);
803 update_option('akismet_connectivity_time', time());
807 // Returns true if server connectivity was OK at the last check, false if there was a problem that needs to be fixed.
808 function akismet_server_connectivity_ok() {
809 // skip the check on WPMU because the status page is hidden
810 global $wpcom_api_key;
811 if ( $wpcom_api_key )
813 $servers = akismet_get_server_connectivity();
814 return !( empty($servers) || !count($servers) || count( array_filter($servers) ) < count($servers) );
817 function akismet_admin_menu() {
818 if ( class_exists( 'Jetpack' ) ) {
819 add_action( 'jetpack_admin_menu', 'akismet_load_menu' );
825 function akismet_load_menu() {
826 if ( class_exists( 'Jetpack' ) ) {
827 add_submenu_page( 'jetpack', __( 'Akismet Configuration' ), __( 'Akismet Configuration' ), 'manage_options', 'akismet-key-config', 'akismet_conf' );
828 add_submenu_page( 'jetpack', __( 'Akismet Stats' ), __( 'Akismet Stats' ), 'manage_options', 'akismet-stats-display', 'akismet_stats_display' );
830 add_submenu_page('plugins.php', __('Akismet Configuration'), __('Akismet Configuration'), 'manage_options', 'akismet-key-config', 'akismet_conf');
831 add_submenu_page('index.php', __('Akismet Stats'), __('Akismet Stats'), 'manage_options', 'akismet-stats-display', 'akismet_stats_display');