wp/wp-content/plugins/akismet/class.akismet-admin.php
changeset 5 5e2f62d02dcd
child 7 cf61fcea0001
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
       
     1 <?php
       
     2 
       
     3 class Akismet_Admin {
       
     4 	const NONCE = 'akismet-update-key';
       
     5 
       
     6 	private static $initiated = false;
       
     7 	private static $notices = array();
       
     8 
       
     9 	public static function init() {
       
    10 		if ( ! self::$initiated ) {
       
    11 			self::init_hooks();
       
    12 		}
       
    13 
       
    14 		if ( isset( $_POST['action'] ) && $_POST['action'] == 'enter-key' ) {
       
    15 			self::enter_api_key();
       
    16 		}
       
    17 	}
       
    18 
       
    19 	public static function init_hooks() {
       
    20 		// The standalone stats page was removed in 3.0 for an all-in-one config and stats page.
       
    21 		// Redirect any links that might have been bookmarked or in browser history.
       
    22 		if ( isset( $_GET['page'] ) && 'akismet-stats-display' == $_GET['page'] ) {
       
    23 			wp_safe_redirect( esc_url_raw( self::get_page_url( 'stats' ) ), 301 );
       
    24 			die;
       
    25 		}
       
    26 
       
    27 		self::$initiated = true;
       
    28 
       
    29 		add_action( 'admin_init', array( 'Akismet_Admin', 'admin_init' ) );
       
    30 		add_action( 'admin_menu', array( 'Akismet_Admin', 'admin_menu' ), 5 ); # Priority 5, so it's called before Jetpack's admin_menu.
       
    31 		add_action( 'admin_notices', array( 'Akismet_Admin', 'display_notice' ) );
       
    32 		add_action( 'admin_enqueue_scripts', array( 'Akismet_Admin', 'load_resources' ) );
       
    33 		add_action( 'activity_box_end', array( 'Akismet_Admin', 'dashboard_stats' ) );
       
    34 		add_action( 'rightnow_end', array( 'Akismet_Admin', 'rightnow_stats' ) );
       
    35 		add_action( 'manage_comments_nav', array( 'Akismet_Admin', 'check_for_spam_button' ) );
       
    36 		add_action( 'admin_action_akismet_recheck_queue', array( 'Akismet_Admin', 'recheck_queue' ) );
       
    37 		add_action( 'wp_ajax_akismet_recheck_queue', array( 'Akismet_Admin', 'recheck_queue' ) );
       
    38 		add_action( 'wp_ajax_comment_author_deurl', array( 'Akismet_Admin', 'remove_comment_author_url' ) );
       
    39 		add_action( 'wp_ajax_comment_author_reurl', array( 'Akismet_Admin', 'add_comment_author_url' ) );
       
    40 		add_action( 'jetpack_auto_activate_akismet', array( 'Akismet_Admin', 'connect_jetpack_user' ) );
       
    41 
       
    42 		add_filter( 'plugin_action_links', array( 'Akismet_Admin', 'plugin_action_links' ), 10, 2 );
       
    43 		add_filter( 'comment_row_actions', array( 'Akismet_Admin', 'comment_row_action' ), 10, 2 );
       
    44 		add_filter( 'comment_text', array( 'Akismet_Admin', 'text_add_link_class' ) );
       
    45 		
       
    46 		add_filter( 'plugin_action_links_'.plugin_basename( plugin_dir_path( __FILE__ ) . 'akismet.php'), array( 'Akismet_Admin', 'admin_plugin_settings_link' ) );
       
    47 		
       
    48 		add_filter( 'wxr_export_skip_commentmeta', array( 'Akismet_Admin', 'exclude_commentmeta_from_export' ), 10, 3 );
       
    49 	}
       
    50 
       
    51 	public static function admin_init() {
       
    52 		load_plugin_textdomain( 'akismet' );
       
    53 		add_meta_box( 'akismet-status', __('Comment History', 'akismet'), array( 'Akismet_Admin', 'comment_status_meta_box' ), 'comment', 'normal' );
       
    54 	}
       
    55 
       
    56 	public static function admin_menu() {
       
    57 		if ( class_exists( 'Jetpack' ) )
       
    58 			add_action( 'jetpack_admin_menu', array( 'Akismet_Admin', 'load_menu' ) );
       
    59 		else
       
    60 			self::load_menu();
       
    61 	}
       
    62 
       
    63 	public static function admin_head() {
       
    64 		if ( !current_user_can( 'manage_options' ) )
       
    65 			return;
       
    66 	}
       
    67 	
       
    68 	public static function admin_plugin_settings_link( $links ) { 
       
    69   		$settings_link = '<a href="'.esc_url( self::get_page_url() ).'">'.__('Settings', 'akismet').'</a>';
       
    70   		array_unshift( $links, $settings_link ); 
       
    71   		return $links; 
       
    72 	}
       
    73 
       
    74 	public static function load_menu() {
       
    75 		if ( class_exists( 'Jetpack' ) )
       
    76 			$hook = add_submenu_page( 'jetpack', __( 'Akismet' , 'akismet'), __( 'Akismet' , 'akismet'), 'manage_options', 'akismet-key-config', array( 'Akismet_Admin', 'display_page' ) );
       
    77 		else
       
    78 			$hook = add_options_page( __('Akismet', 'akismet'), __('Akismet', 'akismet'), 'manage_options', 'akismet-key-config', array( 'Akismet_Admin', 'display_page' ) );
       
    79 
       
    80 		if ( version_compare( $GLOBALS['wp_version'], '3.3', '>=' ) ) {
       
    81 			add_action( "load-$hook", array( 'Akismet_Admin', 'admin_help' ) );
       
    82 		}
       
    83 	}
       
    84 
       
    85 	public static function load_resources() {
       
    86 		global $hook_suffix;
       
    87 
       
    88 		if ( in_array( $hook_suffix, array(
       
    89 			'index.php', # dashboard
       
    90 			'edit-comments.php',
       
    91 			'comment.php',
       
    92 			'post.php',
       
    93 			'settings_page_akismet-key-config',
       
    94 			'jetpack_page_akismet-key-config',
       
    95 		) ) ) {
       
    96 			wp_register_style( 'akismet.css', AKISMET__PLUGIN_URL . '_inc/akismet.css', array(), AKISMET_VERSION );
       
    97 			wp_enqueue_style( 'akismet.css');
       
    98 
       
    99 			wp_register_script( 'akismet.js', AKISMET__PLUGIN_URL . '_inc/akismet.js', array('jquery','postbox'), AKISMET_VERSION );
       
   100 			wp_enqueue_script( 'akismet.js' );
       
   101 			wp_localize_script( 'akismet.js', 'WPAkismet', array(
       
   102 				'comment_author_url_nonce' => wp_create_nonce( 'comment_author_url_nonce' ),
       
   103 				'strings' => array(
       
   104 					'Remove this URL' => __( 'Remove this URL' , 'akismet'),
       
   105 					'Removing...'     => __( 'Removing...' , 'akismet'),
       
   106 					'URL removed'     => __( 'URL removed' , 'akismet'),
       
   107 					'(undo)'          => __( '(undo)' , 'akismet'),
       
   108 					'Re-adding...'    => __( 'Re-adding...' , 'akismet'),
       
   109 				)
       
   110 			) );
       
   111 		}
       
   112 	}
       
   113 
       
   114 	/**
       
   115 	 * Add help to the Akismet page
       
   116 	 *
       
   117 	 * @return false if not the Akismet page
       
   118 	 */
       
   119 	public static function admin_help() {
       
   120 		$current_screen = get_current_screen();
       
   121 
       
   122 		// Screen Content
       
   123 		if ( current_user_can( 'manage_options' ) ) {
       
   124 			if ( !Akismet::get_api_key() || ( isset( $_GET['view'] ) && $_GET['view'] == 'start' ) ) {
       
   125 				//setup page
       
   126 				$current_screen->add_help_tab(
       
   127 					array(
       
   128 						'id'		=> 'overview',
       
   129 						'title'		=> __( 'Overview' , 'akismet'),
       
   130 						'content'	=>
       
   131 							'<p><strong>' . esc_html__( 'Akismet Setup' , 'akismet') . '</strong></p>' .
       
   132 							'<p>' . esc_html__( 'Akismet filters out your comment and trackback spam for you, so you can focus on more important things.' , 'akismet') . '</p>' .
       
   133 							'<p>' . esc_html__( 'On this page, you are able to setup the Akismet plugin.' , 'akismet') . '</p>',
       
   134 					)
       
   135 				);
       
   136 
       
   137 				$current_screen->add_help_tab(
       
   138 					array(
       
   139 						'id'		=> 'setup-signup',
       
   140 						'title'		=> __( 'New to Akismet' , 'akismet'),
       
   141 						'content'	=>
       
   142 							'<p><strong>' . esc_html__( 'Akismet Setup' , 'akismet') . '</strong></p>' .
       
   143 							'<p>' . esc_html__( 'You need to enter an API key to activate the Akismet service on your site.' , 'akismet') . '</p>' .
       
   144 							'<p>' . sprintf( __( 'Signup for an account on %s to get an API Key.' , 'akismet'), '<a href="https://akismet.com/plugin-signup/" target="_blank">Akismet.com</a>' ) . '</p>',
       
   145 					)
       
   146 				);
       
   147 
       
   148 				$current_screen->add_help_tab(
       
   149 					array(
       
   150 						'id'		=> 'setup-manual',
       
   151 						'title'		=> __( 'Enter an API Key' , 'akismet'),
       
   152 						'content'	=>
       
   153 							'<p><strong>' . esc_html__( 'Akismet Setup' , 'akismet') . '</strong></p>' .
       
   154 							'<p>' . esc_html__( 'If you already have an API key' , 'akismet') . '</p>' .
       
   155 							'<ol>' .
       
   156 								'<li>' . esc_html__( 'Copy and paste the API key into the text field.' , 'akismet') . '</li>' .
       
   157 								'<li>' . esc_html__( 'Click the Use this Key button.' , 'akismet') . '</li>' .
       
   158 							'</ol>',
       
   159 					)
       
   160 				);
       
   161 			}
       
   162 			elseif ( isset( $_GET['view'] ) && $_GET['view'] == 'stats' ) {
       
   163 				//stats page
       
   164 				$current_screen->add_help_tab(
       
   165 					array(
       
   166 						'id'		=> 'overview',
       
   167 						'title'		=> __( 'Overview' , 'akismet'),
       
   168 						'content'	=>
       
   169 							'<p><strong>' . esc_html__( 'Akismet Stats' , 'akismet') . '</strong></p>' .
       
   170 							'<p>' . esc_html__( 'Akismet filters out your comment and trackback spam for you, so you can focus on more important things.' , 'akismet') . '</p>' .
       
   171 							'<p>' . esc_html__( 'On this page, you are able to view stats on spam filtered on your site.' , 'akismet') . '</p>',
       
   172 					)
       
   173 				);
       
   174 			}
       
   175 			else {
       
   176 				//configuration page
       
   177 				$current_screen->add_help_tab(
       
   178 					array(
       
   179 						'id'		=> 'overview',
       
   180 						'title'		=> __( 'Overview' , 'akismet'),
       
   181 						'content'	=>
       
   182 							'<p><strong>' . esc_html__( 'Akismet Configuration' , 'akismet') . '</strong></p>' .
       
   183 							'<p>' . esc_html__( 'Akismet filters out your comment and trackback spam for you, so you can focus on more important things.' , 'akismet') . '</p>' .
       
   184 							'<p>' . esc_html__( 'On this page, you are able to enter/remove an API key, view account information and view spam stats.' , 'akismet') . '</p>',
       
   185 					)
       
   186 				);
       
   187 
       
   188 				$current_screen->add_help_tab(
       
   189 					array(
       
   190 						'id'		=> 'settings',
       
   191 						'title'		=> __( 'Settings' , 'akismet'),
       
   192 						'content'	=>
       
   193 							'<p><strong>' . esc_html__( 'Akismet Configuration' , 'akismet') . '</strong></p>' .
       
   194 							'<p><strong>' . esc_html__( 'API Key' , 'akismet') . '</strong> - ' . esc_html__( 'Enter/remove an API key.' , 'akismet') . '</p>' .
       
   195 							'<p><strong>' . esc_html__( 'Comments' , 'akismet') . '</strong> - ' . esc_html__( 'Show the number of approved comments beside each comment author in the comments list page.' , 'akismet') . '</p>' .
       
   196 							'<p><strong>' . esc_html__( 'Strictness' , 'akismet') . '</strong> - ' . esc_html__( 'Choose to either discard the worst spam automatically or to always put all spam in spam folder.' , 'akismet') . '</p>',
       
   197 					)
       
   198 				);
       
   199 
       
   200 				$current_screen->add_help_tab(
       
   201 					array(
       
   202 						'id'		=> 'account',
       
   203 						'title'		=> __( 'Account' , 'akismet'),
       
   204 						'content'	=>
       
   205 							'<p><strong>' . esc_html__( 'Akismet Configuration' , 'akismet') . '</strong></p>' .
       
   206 							'<p><strong>' . esc_html__( 'Subscription Type' , 'akismet') . '</strong> - ' . esc_html__( 'The Akismet subscription plan' , 'akismet') . '</p>' .
       
   207 							'<p><strong>' . esc_html__( 'Status' , 'akismet') . '</strong> - ' . esc_html__( 'The subscription status - active, cancelled or suspended' , 'akismet') . '</p>',
       
   208 					)
       
   209 				);
       
   210 			}
       
   211 		}
       
   212 
       
   213 		// Help Sidebar
       
   214 		$current_screen->set_help_sidebar(
       
   215 			'<p><strong>' . esc_html__( 'For more information:' , 'akismet') . '</strong></p>' .
       
   216 			'<p><a href="https://akismet.com/faq/" target="_blank">'     . esc_html__( 'Akismet FAQ' , 'akismet') . '</a></p>' .
       
   217 			'<p><a href="https://akismet.com/support/" target="_blank">' . esc_html__( 'Akismet Support' , 'akismet') . '</a></p>'
       
   218 		);
       
   219 	}
       
   220 
       
   221 	public static function enter_api_key() {
       
   222 		if ( function_exists('current_user_can') && !current_user_can('manage_options') )
       
   223 			die(__('Cheatin&#8217; uh?', 'akismet'));
       
   224 
       
   225 		if ( !wp_verify_nonce( $_POST['_wpnonce'], self::NONCE ) )
       
   226 			return false;
       
   227 
       
   228 		foreach( array( 'akismet_strictness', 'akismet_show_user_comments_approved' ) as $option ) {
       
   229 			update_option( $option, isset( $_POST[$option] ) && (int) $_POST[$option] == 1 ? '1' : '0' );
       
   230 		}
       
   231 
       
   232 		if ( defined( 'WPCOM_API_KEY' ) )
       
   233 			return false; //shouldn't have option to save key if already defined
       
   234 
       
   235 		$new_key = preg_replace( '/[^a-f0-9]/i', '', $_POST['key'] );
       
   236 		$old_key = Akismet::get_api_key();
       
   237 
       
   238 		if ( empty( $new_key ) ) {
       
   239 			if ( !empty( $old_key ) ) {
       
   240 				delete_option( 'wordpress_api_key' );
       
   241 				self::$notices[] = 'new-key-empty';
       
   242 			}
       
   243 		}
       
   244 		elseif ( $new_key != $old_key ) {
       
   245 			self::save_key( $new_key );
       
   246 		}
       
   247 
       
   248 		return true;
       
   249 	}
       
   250 
       
   251 	public static function save_key( $api_key ) {
       
   252 		$key_status = Akismet::verify_key( $api_key );
       
   253 
       
   254 		if ( $key_status == 'valid' ) {
       
   255 			$akismet_user = self::get_akismet_user( $api_key );
       
   256 			
       
   257 			if ( $akismet_user ) {				
       
   258 				if ( in_array( $akismet_user->status, array( 'active', 'active-dunning', 'no-sub' ) ) )
       
   259 					update_option( 'wordpress_api_key', $api_key );
       
   260 				
       
   261 				if (  $akismet_user->status == 'active' )
       
   262 					self::$notices['status'] = 'new-key-valid';
       
   263 				else
       
   264 					self::$notices['status'] = $akismet_user->status;
       
   265 			}
       
   266 			else
       
   267 				self::$notices['status'] = 'new-key-invalid';
       
   268 		}
       
   269 		elseif ( in_array( $key_status, array( 'invalid', 'failed' ) ) )
       
   270 			self::$notices['status'] = 'new-key-'.$key_status;
       
   271 	}
       
   272 
       
   273 	public static function dashboard_stats() {
       
   274 		if ( !function_exists('did_action') || did_action( 'rightnow_end' ) )
       
   275 			return; // We already displayed this info in the "Right Now" section
       
   276 
       
   277 		if ( !$count = get_option('akismet_spam_count') )
       
   278 			return;
       
   279 
       
   280 		global $submenu;
       
   281 
       
   282 		echo '<h3>' . esc_html( _x( 'Spam', 'comments' , 'akismet') ) . '</h3>';
       
   283 
       
   284 		echo '<p>'.sprintf( _n(
       
   285 				'<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comment</a>.',
       
   286 				'<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comments</a>.',
       
   287 				$count
       
   288 			, 'akismet'), 'https://akismet.com/wordpress/', esc_url( add_query_arg( array( 'page' => 'akismet-admin' ), admin_url( isset( $submenu['edit-comments.php'] ) ? 'edit-comments.php' : 'edit.php' ) ) ), number_format_i18n($count) ).'</p>';
       
   289 	}
       
   290 
       
   291 	// WP 2.5+
       
   292 	public static function rightnow_stats() {
       
   293 		if ( $count = get_option('akismet_spam_count') ) {
       
   294 			$intro = sprintf( _n(
       
   295 				'<a href="%1$s">Akismet</a> has protected your site from %2$s spam comment already. ',
       
   296 				'<a href="%1$s">Akismet</a> has protected your site from %2$s spam comments already. ',
       
   297 				$count
       
   298 			, 'akismet'), 'https://akismet.com/wordpress/', number_format_i18n( $count ) );
       
   299 		} else {
       
   300 			$intro = sprintf( __('<a href="%s">Akismet</a> blocks spam from getting to your blog. ', 'akismet'), 'https://akismet.com/wordpress/' );
       
   301 		}
       
   302 
       
   303 		$link = add_query_arg( array( 'comment_status' => 'spam' ), admin_url( 'edit-comments.php' ) );
       
   304 
       
   305 		if ( $queue_count = self::get_spam_count() ) {
       
   306 			$queue_text = sprintf( _n(
       
   307 				'There&#8217;s <a href="%2$s">%1$s comment</a> in your spam queue right now.',
       
   308 				'There are <a href="%2$s">%1$s comments</a> in your spam queue right now.',
       
   309 				$queue_count
       
   310 			, 'akismet'), number_format_i18n( $queue_count ), esc_url( $link ) );
       
   311 		} else {
       
   312 			$queue_text = sprintf( __( "There&#8217;s nothing in your <a href='%s'>spam queue</a> at the moment." , 'akismet'), esc_url( $link ) );
       
   313 		}
       
   314 
       
   315 		$text = $intro . '<br />' . $queue_text;
       
   316 		echo "<p class='akismet-right-now'>$text</p>\n";
       
   317 	}
       
   318 
       
   319 	public static function check_for_spam_button( $comment_status ) {
       
   320 		// The "Check for Spam" button should only appear when the page might be showing
       
   321 		// a comment with comment_approved=0, which means an un-trashed, un-spammed,
       
   322 		// not-yet-moderated comment.
       
   323 		if ( 'all' != $comment_status && 'moderated' != $comment_status ) {
       
   324 			return;
       
   325 		}
       
   326 
       
   327 		if ( function_exists('plugins_url') )
       
   328 			$link = add_query_arg( array( 'action' => 'akismet_recheck_queue' ), admin_url( 'admin.php' ) );
       
   329 		else
       
   330 			$link = add_query_arg( array( 'page' => 'akismet-admin', 'recheckqueue' => 'true', 'noheader' => 'true' ), admin_url( 'edit-comments.php' ) );
       
   331 
       
   332 		echo '</div><div class="alignleft"><a class="button-secondary checkforspam" href="' . esc_url( $link ) . '">' . esc_html__('Check for Spam', 'akismet') . '</a><span class="checkforspam-spinner"></span>';
       
   333 	}
       
   334 
       
   335 	public static function recheck_queue() {
       
   336 		global $wpdb;
       
   337 
       
   338 		Akismet::fix_scheduled_recheck();
       
   339 
       
   340 		if ( ! ( isset( $_GET['recheckqueue'] ) || ( isset( $_REQUEST['action'] ) && 'akismet_recheck_queue' == $_REQUEST['action'] ) ) )
       
   341 			return;
       
   342 
       
   343 		$paginate = '';
       
   344 		if ( isset( $_POST['limit'] ) && isset( $_POST['offset'] ) ) {
       
   345 			$paginate = $wpdb->prepare( " LIMIT %d OFFSET %d", array( $_POST['limit'], $_POST['offset'] ) );
       
   346 		}
       
   347 		$moderation = $wpdb->get_results( "SELECT * FROM {$wpdb->comments} WHERE comment_approved = '0'{$paginate}", ARRAY_A );
       
   348 
       
   349 		foreach ( (array) $moderation as $c ) {
       
   350 			$c['user_ip']      = $c['comment_author_IP'];
       
   351 			$c['user_agent']   = $c['comment_agent'];
       
   352 			$c['referrer']     = '';
       
   353 			$c['blog']         = get_bloginfo('url');
       
   354 			$c['blog_lang']    = get_locale();
       
   355 			$c['blog_charset'] = get_option('blog_charset');
       
   356 			$c['permalink']    = get_permalink($c['comment_post_ID']);
       
   357 
       
   358 			$c['user_role'] = '';
       
   359 			if ( isset( $c['user_ID'] ) )
       
   360 				$c['user_role'] = Akismet::get_user_roles($c['user_ID']);
       
   361 
       
   362 			if ( Akismet::is_test_mode() )
       
   363 				$c['is_test'] = 'true';
       
   364 
       
   365 			add_comment_meta( $c['comment_ID'], 'akismet_rechecking', true );
       
   366 
       
   367 			$response = Akismet::http_post( Akismet::build_query( $c ), 'comment-check' );
       
   368 			
       
   369 			if ( 'true' == $response[1] ) {
       
   370 				wp_set_comment_status( $c['comment_ID'], 'spam' );
       
   371 				update_comment_meta( $c['comment_ID'], 'akismet_result', 'true' );
       
   372 				delete_comment_meta( $c['comment_ID'], 'akismet_error' );
       
   373 				delete_comment_meta( $c['comment_ID'], 'akismet_delayed_moderation_email' );
       
   374 				Akismet::update_comment_history( $c['comment_ID'], '', 'recheck-spam' );
       
   375 
       
   376 			} elseif ( 'false' == $response[1] ) {
       
   377 				update_comment_meta( $c['comment_ID'], 'akismet_result', 'false' );
       
   378 				delete_comment_meta( $c['comment_ID'], 'akismet_error' );
       
   379 				delete_comment_meta( $c['comment_ID'], 'akismet_delayed_moderation_email' );
       
   380 				Akismet::update_comment_history( $c['comment_ID'], '', 'recheck-ham' );
       
   381 			// abnormal result: error
       
   382 			} else {
       
   383 				update_comment_meta( $c['comment_ID'], 'akismet_result', 'error' );
       
   384 				Akismet::update_comment_history(
       
   385 					$c['comment_ID'],
       
   386 					'',
       
   387 					'recheck-error',
       
   388 					array( 'response' => substr( $response[1], 0, 50 ) )
       
   389 				);
       
   390 			}
       
   391 
       
   392 			delete_comment_meta( $c['comment_ID'], 'akismet_rechecking' );
       
   393 		}
       
   394 		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
       
   395 			wp_send_json( array(
       
   396 				'processed' => count((array) $moderation),
       
   397 			));
       
   398 		}
       
   399 		else {
       
   400 			$redirect_to = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : admin_url( 'edit-comments.php' );
       
   401 			wp_safe_redirect( $redirect_to );
       
   402 			exit;
       
   403 		}
       
   404 	}
       
   405 
       
   406 	// Adds an 'x' link next to author URLs, clicking will remove the author URL and show an undo link
       
   407 	public static function remove_comment_author_url() {
       
   408 		if ( !empty( $_POST['id'] ) && check_admin_referer( 'comment_author_url_nonce' ) ) {
       
   409 			$comment = get_comment( intval( $_POST['id'] ), ARRAY_A );
       
   410 			if ( $comment && current_user_can( 'edit_comment', $comment['comment_ID'] ) ) {
       
   411 				$comment['comment_author_url'] = '';
       
   412 				do_action( 'comment_remove_author_url' );
       
   413 				print( wp_update_comment( $comment ) );
       
   414 				die();
       
   415 			}
       
   416 		}
       
   417 	}
       
   418 
       
   419 	public static function add_comment_author_url() {
       
   420 		if ( !empty( $_POST['id'] ) && !empty( $_POST['url'] ) && check_admin_referer( 'comment_author_url_nonce' ) ) {
       
   421 			$comment = get_comment( intval( $_POST['id'] ), ARRAY_A );
       
   422 			if ( $comment && current_user_can( 'edit_comment', $comment['comment_ID'] ) ) {
       
   423 				$comment['comment_author_url'] = esc_url( $_POST['url'] );
       
   424 				do_action( 'comment_add_author_url' );
       
   425 				print( wp_update_comment( $comment ) );
       
   426 				die();
       
   427 			}
       
   428 		}
       
   429 	}
       
   430 
       
   431 	public static function comment_row_action( $a, $comment ) {
       
   432 
       
   433 		// failsafe for old WP versions
       
   434 		if ( !function_exists('add_comment_meta') )
       
   435 			return $a;
       
   436 
       
   437 		$akismet_result = get_comment_meta( $comment->comment_ID, 'akismet_result', true );
       
   438 		$akismet_error  = get_comment_meta( $comment->comment_ID, 'akismet_error', true );
       
   439 		$user_result    = get_comment_meta( $comment->comment_ID, 'akismet_user_result', true);
       
   440 		$comment_status = wp_get_comment_status( $comment->comment_ID );
       
   441 		$desc = null;
       
   442 		if ( $akismet_error ) {
       
   443 			$desc = __( 'Awaiting spam check' , 'akismet');
       
   444 		} elseif ( !$user_result || $user_result == $akismet_result ) {
       
   445 			// Show the original Akismet result if the user hasn't overridden it, or if their decision was the same
       
   446 			if ( $akismet_result == 'true' && $comment_status != 'spam' && $comment_status != 'trash' )
       
   447 				$desc = __( 'Flagged as spam by Akismet' , 'akismet');
       
   448 			elseif ( $akismet_result == 'false' && $comment_status == 'spam' )
       
   449 				$desc = __( 'Cleared by Akismet' , 'akismet');
       
   450 		} else {
       
   451 			$who = get_comment_meta( $comment->comment_ID, 'akismet_user', true );
       
   452 			if ( $user_result == 'true' )
       
   453 				$desc = sprintf( __('Flagged as spam by %s', 'akismet'), $who );
       
   454 			else
       
   455 				$desc = sprintf( __('Un-spammed by %s', 'akismet'), $who );
       
   456 		}
       
   457 
       
   458 		// add a History item to the hover links, just after Edit
       
   459 		if ( $akismet_result ) {
       
   460 			$b = array();
       
   461 			foreach ( $a as $k => $item ) {
       
   462 				$b[ $k ] = $item;
       
   463 				if (
       
   464 					$k == 'edit'
       
   465 					|| ( $k == 'unspam' && $GLOBALS['wp_version'] >= 3.4 )
       
   466 				) {
       
   467 					$b['history'] = '<a href="comment.php?action=editcomment&amp;c='.$comment->comment_ID.'#akismet-status" title="'. esc_attr__( 'View comment history' , 'akismet') . '"> '. esc_html__('History', 'akismet') . '</a>';
       
   468 				}
       
   469 			}
       
   470 
       
   471 			$a = $b;
       
   472 		}
       
   473 
       
   474 		if ( $desc )
       
   475 			echo '<span class="akismet-status" commentid="'.$comment->comment_ID.'"><a href="comment.php?action=editcomment&amp;c='.$comment->comment_ID.'#akismet-status" title="' . esc_attr__( 'View comment history' , 'akismet') . '">'.esc_html( $desc ).'</a></span>';
       
   476 
       
   477 		$show_user_comments = apply_filters( 'akismet_show_user_comments_approved', get_option('akismet_show_user_comments_approved') );
       
   478 		$show_user_comments = $show_user_comments === 'false' ? false : $show_user_comments; //option used to be saved as 'false' / 'true'
       
   479 		
       
   480 		if ( $show_user_comments ) {
       
   481 			$comment_count = Akismet::get_user_comments_approved( $comment->user_id, $comment->comment_author_email, $comment->comment_author, $comment->comment_author_url );
       
   482 			$comment_count = intval( $comment_count );
       
   483 			echo '<span class="akismet-user-comment-count" commentid="'.$comment->comment_ID.'" style="display:none;"><br><span class="akismet-user-comment-counts">'. sprintf( esc_html( _n( '%s approved', '%s approved', $comment_count , 'akismet') ), number_format_i18n( $comment_count ) ) . '</span></span>';
       
   484 		}
       
   485 
       
   486 		return $a;
       
   487 	}
       
   488 
       
   489 	public static function comment_status_meta_box( $comment ) {
       
   490 		$history = Akismet::get_comment_history( $comment->comment_ID );
       
   491 
       
   492 		if ( $history ) {
       
   493 			echo '<div class="akismet-history" style="margin: 13px;">';
       
   494 
       
   495 			foreach ( $history as $row ) {
       
   496 				$time = date( 'D d M Y @ h:i:m a', $row['time'] ) . ' GMT';
       
   497 				
       
   498 				$message = '';
       
   499 				
       
   500 				if ( ! empty( $row['message'] ) ) {
       
   501 					// Old versions of Akismet stored the message as a literal string in the commentmeta.
       
   502 					// New versions don't do that for two reasons:
       
   503 					// 1) Save space.
       
   504 					// 2) The message can be translated into the current language of the blog, not stuck 
       
   505 					//    in the language of the blog when the comment was made.
       
   506 					$message = $row['message'];
       
   507 				}
       
   508 				
       
   509 				// If possible, use a current translation.
       
   510 				switch ( $row['event'] ) {
       
   511 					case 'recheck-spam';
       
   512 						$message = __( 'Akismet re-checked and caught this comment as spam.', 'akismet' );
       
   513 					break;
       
   514 					case 'check-spam':
       
   515 						$message = __( 'Akismet caught this comment as spam.', 'akismet' );
       
   516 					break;
       
   517 					case 'recheck-ham':
       
   518 						$message = __( 'Akismet re-checked and cleared this comment.', 'akismet' );
       
   519 					break;
       
   520 					case 'check-ham':
       
   521 						$message = __( 'Akismet cleared this comment.', 'akismet' );
       
   522 					break;
       
   523 					case 'wp-blacklisted':
       
   524 						$message = __( 'Comment was caught by wp_blacklist_check.', 'akismet' );
       
   525 					break;
       
   526 					case 'report-spam':
       
   527 						if ( isset( $row['user'] ) ) {
       
   528 							$message = sprintf( __( '%s reported this comment as spam.', 'akismet' ), $row['user'] );
       
   529 						}
       
   530 						else if ( ! $message ) {
       
   531 							$message = __( 'This comment was reported as spam.', 'akismet' );
       
   532 						}
       
   533 					break;
       
   534 					case 'report-ham':
       
   535 						if ( isset( $row['user'] ) ) {
       
   536 							$message = sprintf( __( '%s reported this comment as not spam.', 'akismet' ), $row['user'] );
       
   537 						}
       
   538 						else if ( ! $message ) {
       
   539 							$message = __( 'This comment was reported as not spam.', 'akismet' );
       
   540 						}
       
   541 					break;
       
   542 					case 'cron-retry-spam':
       
   543 						$message = __( 'Akismet caught this comment as spam during an automatic retry.' , 'akismet');
       
   544 					break;
       
   545 					case 'cron-retry-ham':
       
   546 						$message = __( 'Akismet cleared this comment during an automatic retry.', 'akismet');
       
   547 					break;
       
   548 					case 'check-error':
       
   549 						if ( isset( $row['meta'], $row['meta']['response'] ) ) {
       
   550 							$message = sprintf( __( 'Akismet was unable to check this comment (response: %s) but will automatically retry later.', 'akismet'), $row['meta']['response'] );
       
   551 						}
       
   552 					break;
       
   553 					case 'recheck-error':
       
   554 						if ( isset( $row['meta'], $row['meta']['response'] ) ) {
       
   555 							$message = sprintf( __( 'Akismet was unable to recheck this comment (response: %s).', 'akismet'), $row['meta']['response'] );
       
   556 						}
       
   557 					break;
       
   558 					default:
       
   559 						if ( preg_match( '/^status-changed/', $row['event'] ) ) {
       
   560 							// Half of these used to be saved without the dash after 'status-changed'.
       
   561 							// See https://plugins.trac.wordpress.org/changeset/1150658/akismet/trunk
       
   562 							$new_status = preg_replace( '/^status-changed-?/', '', $row['event'] );
       
   563 							$message = sprintf( __( 'Comment status was changed to %s', 'akismet' ), $new_status );
       
   564 						}
       
   565 						else if ( preg_match( '/^status-/', $row['event'] ) ) {
       
   566 							$new_status = preg_replace( '/^status-/', '', $row['event'] );
       
   567 
       
   568 							if ( isset( $row['user'] ) ) {
       
   569 								$message = sprintf( __( '%1$s changed the comment status to %2$s.', 'akismet' ), $row['user'], $new_status );
       
   570 							}
       
   571 						}
       
   572 					break;
       
   573 					
       
   574 				}
       
   575 
       
   576 				echo '<div style="margin-bottom: 13px;">';
       
   577 					echo '<span style="color: #999;" alt="' . $time . '" title="' . $time . '">' . sprintf( esc_html__('%s ago', 'akismet'), human_time_diff( $row['time'] ) ) . '</span>';
       
   578 					echo ' - ';
       
   579 					echo esc_html( $message );
       
   580 				echo '</div>';
       
   581 			}
       
   582 
       
   583 			echo '</div>';
       
   584 		}
       
   585 	}
       
   586 
       
   587 	public static function plugin_action_links( $links, $file ) {
       
   588 		if ( $file == plugin_basename( AKISMET__PLUGIN_URL . '/akismet.php' ) ) {
       
   589 			$links[] = '<a href="' . esc_url( self::get_page_url() ) . '">'.esc_html__( 'Settings' , 'akismet').'</a>';
       
   590 		}
       
   591 
       
   592 		return $links;
       
   593 	}
       
   594 
       
   595 	public static function text_add_link_callback( $m ) {
       
   596 		// bare link?
       
   597 		if ( $m[4] == $m[2] )
       
   598 			return '<a '.$m[1].' href="'.$m[2].'" '.$m[3].' class="comment-link">'.$m[4].'</a>';
       
   599 		else
       
   600 			return '<span title="'.$m[2].'" class="comment-link"><a '.$m[1].' href="'.$m[2].'" '.$m[3].' class="comment-link">'.$m[4].'</a></span>';
       
   601 	}
       
   602 
       
   603 	public static function text_add_link_class( $comment_text ) {
       
   604 		return preg_replace_callback( '#<a ([^>]*)href="([^"]+)"([^>]*)>(.*?)</a>#i', array( 'Akismet_Admin', 'text_add_link_callback' ), $comment_text );
       
   605 	}
       
   606 
       
   607 	// Total spam in queue
       
   608 	// get_option( 'akismet_spam_count' ) is the total caught ever
       
   609 	public static function get_spam_count( $type = false ) {
       
   610 		global $wpdb;
       
   611 
       
   612 		if ( !$type ) { // total
       
   613 			$count = wp_cache_get( 'akismet_spam_count', 'widget' );
       
   614 			if ( false === $count ) {
       
   615 				if ( function_exists('wp_count_comments') ) {
       
   616 					$count = wp_count_comments();
       
   617 					$count = $count->spam;
       
   618 				} else {
       
   619 					$count = (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM {$wpdb->comments} WHERE comment_approved = 'spam'");
       
   620 				}
       
   621 				wp_cache_set( 'akismet_spam_count', $count, 'widget', 3600 );
       
   622 			}
       
   623 			return $count;
       
   624 		} elseif ( 'comments' == $type || 'comment' == $type ) { // comments
       
   625 			$type = '';
       
   626 		}
       
   627 
       
   628 		return (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(comment_ID) FROM {$wpdb->comments} WHERE comment_approved = 'spam' AND comment_type = %s", $type ) );
       
   629 	}
       
   630 
       
   631 	// Check connectivity between the WordPress blog and Akismet's servers.
       
   632 	// 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).
       
   633 	public static function check_server_ip_connectivity() {
       
   634 		
       
   635 		$servers = $ips = array();
       
   636 
       
   637 		// Some web hosts may disable this function
       
   638 		if ( function_exists('gethostbynamel') ) {	
       
   639 			
       
   640 			$ips = gethostbynamel( 'rest.akismet.com' );
       
   641 			if ( $ips && is_array($ips) && count($ips) ) {
       
   642 				$api_key = Akismet::get_api_key();
       
   643 				
       
   644 				foreach ( $ips as $ip ) {
       
   645 					$response = Akismet::verify_key( $api_key, $ip );
       
   646 					// even if the key is invalid, at least we know we have connectivity
       
   647 					if ( $response == 'valid' || $response == 'invalid' )
       
   648 						$servers[$ip] = 'connected';
       
   649 					else
       
   650 						$servers[$ip] = $response ? $response : 'unable to connect';
       
   651 				}
       
   652 			}
       
   653 		}
       
   654 		
       
   655 		return $servers;
       
   656 	}
       
   657 	
       
   658 	// Simpler connectivity check
       
   659 	public static function check_server_connectivity($cache_timeout = 86400) {
       
   660 		
       
   661 		$debug = array();
       
   662 		$debug[ 'PHP_VERSION' ]         = PHP_VERSION;
       
   663 		$debug[ 'WORDPRESS_VERSION' ]   = $GLOBALS['wp_version'];
       
   664 		$debug[ 'AKISMET_VERSION' ]     = AKISMET_VERSION;
       
   665 		$debug[ 'AKISMET__PLUGIN_DIR' ] = AKISMET__PLUGIN_DIR;
       
   666 		$debug[ 'SITE_URL' ]            = site_url();
       
   667 		$debug[ 'HOME_URL' ]            = home_url();
       
   668 		
       
   669 		$servers = get_option('akismet_available_servers');
       
   670 		if ( (time() - get_option('akismet_connectivity_time') < $cache_timeout) && $servers !== false ) {
       
   671 			$servers = self::check_server_ip_connectivity();
       
   672 			update_option('akismet_available_servers', $servers);
       
   673 			update_option('akismet_connectivity_time', time());
       
   674 		}
       
   675 			
       
   676 		$response = wp_remote_get( 'http://rest.akismet.com/1.1/test' );
       
   677 		
       
   678 		$debug[ 'gethostbynamel' ]  = function_exists('gethostbynamel') ? 'exists' : 'not here';
       
   679 		$debug[ 'Servers' ]         = $servers;
       
   680 		$debug[ 'Test Connection' ] = $response;
       
   681 		
       
   682 		Akismet::log( $debug );
       
   683 		
       
   684 		if ( $response && 'connected' == wp_remote_retrieve_body( $response ) )
       
   685 			return true;
       
   686 		
       
   687 		return false;
       
   688 	}
       
   689 
       
   690 	// Check the server connectivity and store the available servers in an option. 
       
   691 	public static function get_server_connectivity($cache_timeout = 86400) {
       
   692 		return self::check_server_connectivity( $cache_timeout );
       
   693 	}
       
   694 
       
   695 	public static function get_number_spam_waiting() {
       
   696 		global $wpdb;
       
   697 		return (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->commentmeta} WHERE meta_key = 'akismet_error'" );
       
   698 	}
       
   699 
       
   700 	public static function get_page_url( $page = 'config' ) {
       
   701 
       
   702 		$args = array( 'page' => 'akismet-key-config' );
       
   703 
       
   704 		if ( $page == 'stats' )
       
   705 			$args = array( 'page' => 'akismet-key-config', 'view' => 'stats' );
       
   706 		elseif ( $page == 'delete_key' )
       
   707 			$args = array( 'page' => 'akismet-key-config', 'view' => 'start', 'action' => 'delete-key', '_wpnonce' => wp_create_nonce( self::NONCE ) );
       
   708 
       
   709 		$url = add_query_arg( $args, class_exists( 'Jetpack' ) ? admin_url( 'admin.php' ) : admin_url( 'options-general.php' ) );
       
   710 
       
   711 		return $url;
       
   712 	}
       
   713 	
       
   714 	public static function get_akismet_user( $api_key ) {
       
   715 		$akismet_user = Akismet::http_post( Akismet::build_query( array( 'key' => $api_key, 'blog' => get_bloginfo( 'url' ) ) ), 'get-subscription' );
       
   716 
       
   717 		if ( ! empty( $akismet_user[1] ) )
       
   718 			$akismet_user = json_decode( $akismet_user[1] );
       
   719 		else
       
   720 			$akismet_user = false;
       
   721 			
       
   722 		return $akismet_user;
       
   723 	}
       
   724 	
       
   725 	public static function get_stats( $api_key ) {
       
   726 		$stat_totals = array();
       
   727 
       
   728 		foreach( array( '6-months', 'all' ) as $interval ) {
       
   729 			$response = Akismet::http_post( Akismet::build_query( array( 'blog' => get_bloginfo( 'url' ), 'key' => $api_key, 'from' => $interval ) ), 'get-stats' );
       
   730 
       
   731 			if ( ! empty( $response[1] ) ) {
       
   732 				$stat_totals[$interval] = json_decode( $response[1] );
       
   733 			}
       
   734 		}
       
   735 
       
   736 		return $stat_totals;
       
   737 	}
       
   738 	
       
   739 	public static function verify_wpcom_key( $api_key, $user_id, $extra = array() ) {
       
   740 		$akismet_account = Akismet::http_post( Akismet::build_query( array_merge( array(
       
   741 			'user_id'          => $user_id,
       
   742 			'api_key'          => $api_key,
       
   743 			'get_account_type' => 'true'
       
   744 		), $extra ) ), 'verify-wpcom-key' );
       
   745 
       
   746 		if ( ! empty( $akismet_account[1] ) )
       
   747 			$akismet_account = json_decode( $akismet_account[1] );
       
   748 
       
   749 		Akismet::log( compact( 'akismet_account' ) );
       
   750 		
       
   751 		return $akismet_account;
       
   752 	}
       
   753 	
       
   754 	public static function connect_jetpack_user() {
       
   755 	
       
   756 		if ( $jetpack_user = self::get_jetpack_user() ) {
       
   757 			if ( isset( $jetpack_user['user_id'] ) && isset(  $jetpack_user['api_key'] ) ) {
       
   758 				$akismet_user = self::verify_wpcom_key( $jetpack_user['api_key'], $jetpack_user['user_id'], array( 'action' => 'connect_jetpack_user' ) );
       
   759 							
       
   760 				if ( is_object( $akismet_user ) ) {
       
   761 					self::save_key( $akismet_user->api_key );
       
   762 					return in_array( $akismet_user->status, array( 'active', 'active-dunning', 'no-sub' ) );
       
   763 				}
       
   764 			}
       
   765 		}
       
   766 		
       
   767 		return false;
       
   768 	}
       
   769 
       
   770 	public static function display_alert() {
       
   771 		Akismet::view( 'notice', array(
       
   772 			'type' => 'alert',
       
   773 			'code' => (int) get_option( 'akismet_alert_code' ),
       
   774 			'msg'  => get_option( 'akismet_alert_msg' )
       
   775 		) );
       
   776 	}
       
   777 
       
   778 	public static function display_spam_check_warning() {
       
   779 		Akismet::fix_scheduled_recheck();
       
   780 
       
   781 		if ( wp_next_scheduled('akismet_schedule_cron_recheck') > time() && self::get_number_spam_waiting() > 0 ) {
       
   782 			$link_text = apply_filters( 'akismet_spam_check_warning_link_text', sprintf( __( 'Please check your <a href="%s">Akismet configuration</a> and contact your web host if problems persist.', 'akismet'), esc_url( self::get_page_url() ) ) );
       
   783 			Akismet::view( 'notice', array( 'type' => 'spam-check', 'link_text' => $link_text ) );
       
   784 		}
       
   785 	}
       
   786 
       
   787 	public static function display_invalid_version() {
       
   788 		Akismet::view( 'notice', array( 'type' => 'version' ) );
       
   789 	}
       
   790 
       
   791 	public static function display_api_key_warning() {
       
   792 		Akismet::view( 'notice', array( 'type' => 'plugin' ) );
       
   793 	}
       
   794 
       
   795 	public static function display_page() {
       
   796 		if ( !Akismet::get_api_key() || ( isset( $_GET['view'] ) && $_GET['view'] == 'start' ) )
       
   797 			self::display_start_page();
       
   798 		elseif ( isset( $_GET['view'] ) && $_GET['view'] == 'stats' )
       
   799 			self::display_stats_page();
       
   800 		else
       
   801 			self::display_configuration_page();
       
   802 	}
       
   803 
       
   804 	public static function display_start_page() {
       
   805 		if ( isset( $_GET['action'] ) ) {
       
   806 			if ( $_GET['action'] == 'delete-key' ) {
       
   807 				if ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], self::NONCE ) )
       
   808 					delete_option( 'wordpress_api_key' );
       
   809 			}
       
   810 		}
       
   811 
       
   812 		if ( $api_key = Akismet::get_api_key() ) {
       
   813 			self::display_configuration_page();
       
   814 			return;
       
   815 		}
       
   816 		
       
   817 		//the user can choose to auto connect their API key by clicking a button on the akismet done page
       
   818 		//if jetpack, get verified api key by using connected wpcom user id
       
   819 		//if no jetpack, get verified api key by using an akismet token	
       
   820 		
       
   821 		$akismet_user = false;
       
   822 		
       
   823 		if ( isset( $_GET['token'] ) && preg_match('/^(\d+)-[0-9a-f]{20}$/', $_GET['token'] ) )
       
   824 			$akismet_user = self::verify_wpcom_key( '', '', array( 'token' => $_GET['token'] ) );
       
   825 		elseif ( $jetpack_user = self::get_jetpack_user() )
       
   826 			$akismet_user = self::verify_wpcom_key( $jetpack_user['api_key'], $jetpack_user['user_id'] );
       
   827 			
       
   828 		if ( isset( $_GET['action'] ) ) {
       
   829 			if ( $_GET['action'] == 'save-key' ) {
       
   830 				if ( is_object( $akismet_user ) ) {
       
   831 					self::save_key( $akismet_user->api_key );
       
   832 					self::display_notice();
       
   833 					self::display_configuration_page();
       
   834 					return;				
       
   835 				}
       
   836 			}
       
   837 		}
       
   838 
       
   839 		echo '<h2 class="ak-header">'.esc_html__('Akismet', 'akismet').'</h2>';
       
   840 
       
   841 		self::display_status();
       
   842 
       
   843 		Akismet::view( 'start', compact( 'akismet_user' ) );
       
   844 	}
       
   845 
       
   846 	public static function display_stats_page() {
       
   847 		Akismet::view( 'stats' );
       
   848 	}
       
   849 
       
   850 	public static function display_configuration_page() {
       
   851 		$api_key      = Akismet::get_api_key();
       
   852 		$akismet_user = self::get_akismet_user( $api_key );
       
   853 		$stat_totals  = self::get_stats( $api_key );
       
   854 		
       
   855 		// If unset, create the new strictness option using the old discard option to determine its default
       
   856        	if ( get_option( 'akismet_strictness' ) === false )
       
   857         	add_option( 'akismet_strictness', (get_option('akismet_discard_month') === 'true' ? '1' : '0') );
       
   858 
       
   859 		if ( empty( self::$notices ) ) {
       
   860 			//show status
       
   861 			if ( ! empty( $stat_totals['all'] ) && isset( $stat_totals['all']->time_saved ) && $akismet_user->status == 'active' && $akismet_user->account_type == 'free-api-key' ) {
       
   862 
       
   863 				$time_saved = false;
       
   864 
       
   865 				if ( $stat_totals['all']->time_saved > 1800 ) {
       
   866 					$total_in_minutes = round( $stat_totals['all']->time_saved / 60 );
       
   867 					$total_in_hours   = round( $total_in_minutes / 60 );
       
   868 					$total_in_days    = round( $total_in_hours / 8 );
       
   869 					$cleaning_up      = __( 'Cleaning up spam takes time.' , 'akismet');
       
   870 
       
   871 					if ( $total_in_days > 1 )
       
   872 						$time_saved = $cleaning_up . ' ' . sprintf( __( 'Since you joined us, Akismet has saved you %s days!' , 'akismet'), number_format_i18n( $total_in_days ) );
       
   873 					elseif ( $total_in_hours > 1 )
       
   874 						$time_saved = $cleaning_up . ' ' . sprintf( __( 'Since you joined us, Akismet has saved you %d hours!' , 'akismet'), $total_in_hours );
       
   875 					elseif ( $total_in_minutes >= 30 )
       
   876 						$time_saved = $cleaning_up . ' ' . sprintf( __( 'Since you joined us, Akismet has saved you %d minutes!' , 'akismet'), $total_in_minutes );
       
   877 				}
       
   878 
       
   879 				Akismet::view( 'notice', array( 'type' => 'active-notice', 'time_saved' => $time_saved ) );
       
   880 			}
       
   881 			
       
   882 			if ( !empty( $akismet_user->limit_reached ) && in_array( $akismet_user->limit_reached, array( 'yellow', 'red' ) ) ) {
       
   883 				Akismet::view( 'notice', array( 'type' => 'limit-reached', 'level' => $akismet_user->limit_reached ) );
       
   884 			}
       
   885 		}
       
   886 		
       
   887 		if ( !isset( self::$notices['status'] ) && in_array( $akismet_user->status, array( 'cancelled', 'suspended', 'missing', 'no-sub' ) ) )	
       
   888 			Akismet::view( 'notice', array( 'type' => $akismet_user->status ) );
       
   889 
       
   890 		Akismet::log( compact( 'stat_totals', 'akismet_user' ) );
       
   891 		Akismet::view( 'config', compact( 'api_key', 'akismet_user', 'stat_totals' ) );
       
   892 	}
       
   893 
       
   894 	public static function display_notice() {
       
   895 		global $hook_suffix;
       
   896 
       
   897 		if ( in_array( $hook_suffix, array( 'jetpack_page_akismet-key-config', 'settings_page_akismet-key-config', 'edit-comments.php' ) ) && (int) get_option( 'akismet_alert_code' ) > 0 ) {
       
   898 			Akismet::verify_key( Akismet::get_api_key() ); //verify that the key is still in alert state
       
   899 			
       
   900 			if ( get_option( 'akismet_alert_code' ) > 0 )
       
   901 				self::display_alert();
       
   902 		}
       
   903 		elseif ( $hook_suffix == 'plugins.php' && !Akismet::get_api_key() ) {
       
   904 			self::display_api_key_warning();
       
   905 		}
       
   906 		elseif ( $hook_suffix == 'edit-comments.php' && wp_next_scheduled( 'akismet_schedule_cron_recheck' ) ) {
       
   907 			self::display_spam_check_warning();
       
   908 		}
       
   909 		elseif ( in_array( $hook_suffix, array( 'jetpack_page_akismet-key-config', 'settings_page_akismet-key-config' ) ) && Akismet::get_api_key() ) {
       
   910 			self::display_status();
       
   911 		}
       
   912 	}
       
   913 
       
   914 	public static function display_status() {
       
   915 		$type = '';
       
   916 
       
   917 		if ( !self::get_server_connectivity() )
       
   918 			$type = 'servers-be-down';
       
   919 
       
   920 		if ( !empty( $type ) )
       
   921 			Akismet::view( 'notice', compact( 'type' ) );
       
   922 		elseif ( !empty( self::$notices ) ) {
       
   923 			foreach ( self::$notices as $type )
       
   924 				Akismet::view( 'notice', compact( 'type' ) );
       
   925 		}
       
   926 	}
       
   927 
       
   928 	private static function get_jetpack_user() {
       
   929 		if ( !class_exists('Jetpack') )
       
   930 			return false;
       
   931 
       
   932 		Jetpack::load_xml_rpc_client();
       
   933 		$xml = new Jetpack_IXR_ClientMulticall( array( 'user_id' => get_current_user_id() ) );
       
   934 
       
   935 		$xml->addCall( 'wpcom.getUserID' );
       
   936 		$xml->addCall( 'akismet.getAPIKey' );
       
   937 		$xml->query();
       
   938 
       
   939 		Akismet::log( compact( 'xml' ) );
       
   940 
       
   941 		if ( !$xml->isError() ) {
       
   942 			$responses = $xml->getResponse();
       
   943 			if ( count( $responses ) > 1 ) {
       
   944 				$api_key = array_shift( $responses[0] );
       
   945 				$user_id = (int) array_shift( $responses[1] );
       
   946 				return compact( 'api_key', 'user_id' );
       
   947 			}
       
   948 		}
       
   949 		return false;
       
   950 	}
       
   951 	
       
   952 	/**
       
   953 	 * Some commentmeta isn't useful in an export file. Suppress it (when supported).
       
   954 	 *
       
   955 	 * @param bool $exclude
       
   956 	 * @param string $key The meta key
       
   957 	 * @param object $meta The meta object
       
   958 	 * @return bool Whether to exclude this meta entry from the export.
       
   959 	 */
       
   960 	public static function exclude_commentmeta_from_export( $exclude, $key, $meta ) {
       
   961 		if ( in_array( $key, array( 'akismet_as_submitted', 'akismet_rechecking', 'akismet_delayed_moderation_email' ) ) ) {
       
   962 			return true;
       
   963 		}
       
   964 		
       
   965 		return $exclude;
       
   966 	}
       
   967 }