[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-content/plugins/akismet/ -> class.akismet-admin.php (source)

   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      private static $allowed   = array(
   9          'a' => array(
  10              'href' => true,
  11              'title' => true,
  12          ),
  13          'b' => array(),
  14          'code' => array(),
  15          'del' => array(
  16              'datetime' => true,
  17          ),
  18          'em' => array(),
  19          'i' => array(),
  20          'q' => array(
  21              'cite' => true,
  22          ),
  23          'strike' => array(),
  24          'strong' => array(),
  25      );
  26  
  27  	public static function init() {
  28          if ( ! self::$initiated ) {
  29              self::init_hooks();
  30          }
  31  
  32          if ( isset( $_POST['action'] ) && $_POST['action'] == 'enter-key' ) {
  33              self::enter_api_key();
  34          }
  35      }
  36  
  37  	public static function init_hooks() {
  38          // The standalone stats page was removed in 3.0 for an all-in-one config and stats page.
  39          // Redirect any links that might have been bookmarked or in browser history.
  40          if ( isset( $_GET['page'] ) && 'akismet-stats-display' == $_GET['page'] ) {
  41              wp_safe_redirect( esc_url_raw( self::get_page_url( 'stats' ) ), 301 );
  42              die;
  43          }
  44  
  45          self::$initiated = true;
  46  
  47          add_action( 'admin_init', array( 'Akismet_Admin', 'admin_init' ) );
  48          add_action( 'admin_menu', array( 'Akismet_Admin', 'admin_menu' ), 5 ); # Priority 5, so it's called before Jetpack's admin_menu.
  49          add_action( 'admin_notices', array( 'Akismet_Admin', 'display_notice' ) );
  50          add_action( 'admin_enqueue_scripts', array( 'Akismet_Admin', 'load_resources' ) );
  51          add_action( 'activity_box_end', array( 'Akismet_Admin', 'dashboard_stats' ) );
  52          add_action( 'rightnow_end', array( 'Akismet_Admin', 'rightnow_stats' ) );
  53          add_action( 'manage_comments_nav', array( 'Akismet_Admin', 'check_for_spam_button' ) );
  54          add_action( 'admin_action_akismet_recheck_queue', array( 'Akismet_Admin', 'recheck_queue' ) );
  55          add_action( 'wp_ajax_akismet_recheck_queue', array( 'Akismet_Admin', 'recheck_queue' ) );
  56          add_action( 'wp_ajax_comment_author_deurl', array( 'Akismet_Admin', 'remove_comment_author_url' ) );
  57          add_action( 'wp_ajax_comment_author_reurl', array( 'Akismet_Admin', 'add_comment_author_url' ) );
  58          add_action( 'jetpack_auto_activate_akismet', array( 'Akismet_Admin', 'connect_jetpack_user' ) );
  59  
  60          add_filter( 'plugin_action_links', array( 'Akismet_Admin', 'plugin_action_links' ), 10, 2 );
  61          add_filter( 'comment_row_actions', array( 'Akismet_Admin', 'comment_row_action' ), 10, 2 );
  62          
  63          add_filter( 'plugin_action_links_'.plugin_basename( plugin_dir_path( __FILE__ ) . 'akismet.php'), array( 'Akismet_Admin', 'admin_plugin_settings_link' ) );
  64          
  65          add_filter( 'wxr_export_skip_commentmeta', array( 'Akismet_Admin', 'exclude_commentmeta_from_export' ), 10, 3 );
  66          
  67          add_filter( 'all_plugins', array( 'Akismet_Admin', 'modify_plugin_description' ) );
  68  
  69          // priority=1 because we need ours to run before core's comment anonymizer runs, and that's registered at priority=10
  70          add_filter( 'wp_privacy_personal_data_erasers', array( 'Akismet_Admin', 'register_personal_data_eraser' ), 1 );
  71      }
  72  
  73  	public static function admin_init() {
  74          if ( get_option( 'Activated_Akismet' ) ) {
  75              delete_option( 'Activated_Akismet' );
  76              if ( ! headers_sent() ) {
  77                  wp_redirect( add_query_arg( array( 'page' => 'akismet-key-config', 'view' => 'start' ), class_exists( 'Jetpack' ) ? admin_url( 'admin.php' ) : admin_url( 'options-general.php' ) ) );
  78              }
  79          }
  80  
  81          load_plugin_textdomain( 'akismet' );
  82          add_meta_box( 'akismet-status', __('Comment History', 'akismet'), array( 'Akismet_Admin', 'comment_status_meta_box' ), 'comment', 'normal' );
  83  
  84          if ( function_exists( 'wp_add_privacy_policy_content' ) ) {
  85              wp_add_privacy_policy_content(
  86                  __( 'Akismet', 'akismet' ),
  87                  __( 'We collect information about visitors who comment on Sites that use our Akismet anti-spam service. The information we collect depends on how the User sets up Akismet for the Site, but typically includes the commenter\'s IP address, user agent, referrer, and Site URL (along with other information directly provided by the commenter such as their name, username, email address, and the comment itself).', 'akismet' )
  88              );
  89          }
  90      }
  91  
  92  	public static function admin_menu() {
  93          if ( class_exists( 'Jetpack' ) )
  94              add_action( 'jetpack_admin_menu', array( 'Akismet_Admin', 'load_menu' ) );
  95          else
  96              self::load_menu();
  97      }
  98  
  99  	public static function admin_head() {
 100          if ( !current_user_can( 'manage_options' ) )
 101              return;
 102      }
 103      
 104  	public static function admin_plugin_settings_link( $links ) { 
 105            $settings_link = '<a href="'.esc_url( self::get_page_url() ).'">'.__('Settings', 'akismet').'</a>';
 106            array_unshift( $links, $settings_link ); 
 107            return $links; 
 108      }
 109  
 110  	public static function load_menu() {
 111          if ( class_exists( 'Jetpack' ) ) {
 112              $hook = add_submenu_page( 'jetpack', __( 'Akismet Anti-Spam' , 'akismet'), __( 'Akismet Anti-Spam' , 'akismet'), 'manage_options', 'akismet-key-config', array( 'Akismet_Admin', 'display_page' ) );
 113          }
 114          else {
 115              $hook = add_options_page( __('Akismet Anti-Spam', 'akismet'), __('Akismet Anti-Spam', 'akismet'), 'manage_options', 'akismet-key-config', array( 'Akismet_Admin', 'display_page' ) );
 116          }
 117          
 118          if ( $hook ) {
 119              add_action( "load-$hook", array( 'Akismet_Admin', 'admin_help' ) );
 120          }
 121      }
 122  
 123  	public static function load_resources() {
 124          global $hook_suffix;
 125  
 126          if ( in_array( $hook_suffix, apply_filters( 'akismet_admin_page_hook_suffixes', array(
 127              'index.php', # dashboard
 128              'edit-comments.php',
 129              'comment.php',
 130              'post.php',
 131              'settings_page_akismet-key-config',
 132              'jetpack_page_akismet-key-config',
 133              'plugins.php',
 134          ) ) ) ) {
 135              wp_register_style( 'akismet.css', plugin_dir_url( __FILE__ ) . '_inc/akismet.css', array(), AKISMET_VERSION );
 136              wp_enqueue_style( 'akismet.css');
 137  
 138              wp_register_script( 'akismet.js', plugin_dir_url( __FILE__ ) . '_inc/akismet.js', array('jquery'), AKISMET_VERSION );
 139              wp_enqueue_script( 'akismet.js' );
 140          
 141              $inline_js = array(
 142                  'comment_author_url_nonce' => wp_create_nonce( 'comment_author_url_nonce' ),
 143                  'strings' => array(
 144                      'Remove this URL' => __( 'Remove this URL' , 'akismet'),
 145                      'Removing...'     => __( 'Removing...' , 'akismet'),
 146                      'URL removed'     => __( 'URL removed' , 'akismet'),
 147                      '(undo)'          => __( '(undo)' , 'akismet'),
 148                      'Re-adding...'    => __( 'Re-adding...' , 'akismet'),
 149                  )
 150              );
 151  
 152              if ( isset( $_GET['akismet_recheck'] ) && wp_verify_nonce( $_GET['akismet_recheck'], 'akismet_recheck' ) ) {
 153                  $inline_js['start_recheck'] = true;
 154              }
 155  
 156              if ( apply_filters( 'akismet_enable_mshots', true ) ) {
 157                  $inline_js['enable_mshots'] = true;
 158              }
 159  
 160              wp_localize_script( 'akismet.js', 'WPAkismet', $inline_js );
 161          }
 162      }
 163  
 164      /**
 165       * Add help to the Akismet page
 166       *
 167       * @return false if not the Akismet page
 168       */
 169  	public static function admin_help() {
 170          $current_screen = get_current_screen();
 171  
 172          // Screen Content
 173          if ( current_user_can( 'manage_options' ) ) {
 174              if ( !Akismet::get_api_key() || ( isset( $_GET['view'] ) && $_GET['view'] == 'start' ) ) {
 175                  //setup page
 176                  $current_screen->add_help_tab(
 177                      array(
 178                          'id'        => 'overview',
 179                          'title'        => __( 'Overview' , 'akismet'),
 180                          'content'    =>
 181                              '<p><strong>' . esc_html__( 'Akismet Setup' , 'akismet') . '</strong></p>' .
 182                              '<p>' . esc_html__( 'Akismet filters out spam, so you can focus on more important things.' , 'akismet') . '</p>' .
 183                              '<p>' . esc_html__( 'On this page, you are able to set up the Akismet plugin.' , 'akismet') . '</p>',
 184                      )
 185                  );
 186  
 187                  $current_screen->add_help_tab(
 188                      array(
 189                          'id'        => 'setup-signup',
 190                          'title'        => __( 'New to Akismet' , 'akismet'),
 191                          'content'    =>
 192                              '<p><strong>' . esc_html__( 'Akismet Setup' , 'akismet') . '</strong></p>' .
 193                              '<p>' . esc_html__( 'You need to enter an API key to activate the Akismet service on your site.' , 'akismet') . '</p>' .
 194                              '<p>' . sprintf( __( 'Sign up for an account on %s to get an API Key.' , 'akismet'), '<a href="https://akismet.com/plugin-signup/" target="_blank">Akismet.com</a>' ) . '</p>',
 195                      )
 196                  );
 197  
 198                  $current_screen->add_help_tab(
 199                      array(
 200                          'id'        => 'setup-manual',
 201                          'title'        => __( 'Enter an API Key' , 'akismet'),
 202                          'content'    =>
 203                              '<p><strong>' . esc_html__( 'Akismet Setup' , 'akismet') . '</strong></p>' .
 204                              '<p>' . esc_html__( 'If you already have an API key' , 'akismet') . '</p>' .
 205                              '<ol>' .
 206                                  '<li>' . esc_html__( 'Copy and paste the API key into the text field.' , 'akismet') . '</li>' .
 207                                  '<li>' . esc_html__( 'Click the Use this Key button.' , 'akismet') . '</li>' .
 208                              '</ol>',
 209                      )
 210                  );
 211              }
 212              elseif ( isset( $_GET['view'] ) && $_GET['view'] == 'stats' ) {
 213                  //stats page
 214                  $current_screen->add_help_tab(
 215                      array(
 216                          'id'        => 'overview',
 217                          'title'        => __( 'Overview' , 'akismet'),
 218                          'content'    =>
 219                              '<p><strong>' . esc_html__( 'Akismet Stats' , 'akismet') . '</strong></p>' .
 220                              '<p>' . esc_html__( 'Akismet filters out spam, so you can focus on more important things.' , 'akismet') . '</p>' .
 221                              '<p>' . esc_html__( 'On this page, you are able to view stats on spam filtered on your site.' , 'akismet') . '</p>',
 222                      )
 223                  );
 224              }
 225              else {
 226                  //configuration page
 227                  $current_screen->add_help_tab(
 228                      array(
 229                          'id'        => 'overview',
 230                          'title'        => __( 'Overview' , 'akismet'),
 231                          'content'    =>
 232                              '<p><strong>' . esc_html__( 'Akismet Configuration' , 'akismet') . '</strong></p>' .
 233                              '<p>' . esc_html__( 'Akismet filters out spam, so you can focus on more important things.' , 'akismet') . '</p>' .
 234                              '<p>' . esc_html__( 'On this page, you are able to update your Akismet settings and view spam stats.' , 'akismet') . '</p>',
 235                      )
 236                  );
 237  
 238                  $current_screen->add_help_tab(
 239                      array(
 240                          'id'        => 'settings',
 241                          'title'        => __( 'Settings' , 'akismet'),
 242                          'content'    =>
 243                              '<p><strong>' . esc_html__( 'Akismet Configuration' , 'akismet') . '</strong></p>' .
 244                              ( Akismet::predefined_api_key() ? '' : '<p><strong>' . esc_html__( 'API Key' , 'akismet') . '</strong> - ' . esc_html__( 'Enter/remove an API key.' , 'akismet') . '</p>' ) .
 245                              '<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>' .
 246                              '<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>',
 247                      )
 248                  );
 249  
 250                  if ( ! Akismet::predefined_api_key() ) {
 251                      $current_screen->add_help_tab(
 252                          array(
 253                              'id'        => 'account',
 254                              'title'        => __( 'Account' , 'akismet'),
 255                              'content'    =>
 256                                  '<p><strong>' . esc_html__( 'Akismet Configuration' , 'akismet') . '</strong></p>' .
 257                                  '<p><strong>' . esc_html__( 'Subscription Type' , 'akismet') . '</strong> - ' . esc_html__( 'The Akismet subscription plan' , 'akismet') . '</p>' .
 258                                  '<p><strong>' . esc_html__( 'Status' , 'akismet') . '</strong> - ' . esc_html__( 'The subscription status - active, cancelled or suspended' , 'akismet') . '</p>',
 259                          )
 260                      );
 261                  }
 262              }
 263          }
 264  
 265          // Help Sidebar
 266          $current_screen->set_help_sidebar(
 267              '<p><strong>' . esc_html__( 'For more information:' , 'akismet') . '</strong></p>' .
 268              '<p><a href="https://akismet.com/faq/" target="_blank">'     . esc_html__( 'Akismet FAQ' , 'akismet') . '</a></p>' .
 269              '<p><a href="https://akismet.com/support/" target="_blank">' . esc_html__( 'Akismet Support' , 'akismet') . '</a></p>'
 270          );
 271      }
 272  
 273  	public static function enter_api_key() {
 274          if ( ! current_user_can( 'manage_options' ) ) {
 275              die( __( 'Cheatin&#8217; uh?', 'akismet' ) );
 276          }
 277  
 278          if ( !wp_verify_nonce( $_POST['_wpnonce'], self::NONCE ) )
 279              return false;
 280  
 281          foreach( array( 'akismet_strictness', 'akismet_show_user_comments_approved' ) as $option ) {
 282              update_option( $option, isset( $_POST[$option] ) && (int) $_POST[$option] == 1 ? '1' : '0' );
 283          }
 284  
 285          if ( ! empty( $_POST['akismet_comment_form_privacy_notice'] ) ) {
 286              self::set_form_privacy_notice_option( $_POST['akismet_comment_form_privacy_notice'] );
 287          } else {
 288              self::set_form_privacy_notice_option( 'hide' );
 289          }
 290  
 291          if ( Akismet::predefined_api_key() ) {
 292              return false; //shouldn't have option to save key if already defined
 293          }
 294          
 295          $new_key = preg_replace( '/[^a-f0-9]/i', '', $_POST['key'] );
 296          $old_key = Akismet::get_api_key();
 297  
 298          if ( empty( $new_key ) ) {
 299              if ( !empty( $old_key ) ) {
 300                  delete_option( 'wordpress_api_key' );
 301                  self::$notices[] = 'new-key-empty';
 302              }
 303          }
 304          elseif ( $new_key != $old_key ) {
 305              self::save_key( $new_key );
 306          }
 307  
 308          return true;
 309      }
 310  
 311  	public static function save_key( $api_key ) {
 312          $key_status = Akismet::verify_key( $api_key );
 313  
 314          if ( $key_status == 'valid' ) {
 315              $akismet_user = self::get_akismet_user( $api_key );
 316              
 317              if ( $akismet_user ) {                
 318                  if ( in_array( $akismet_user->status, array( 'active', 'active-dunning', 'no-sub' ) ) )
 319                      update_option( 'wordpress_api_key', $api_key );
 320                  
 321                  if ( $akismet_user->status == 'active' )
 322                      self::$notices['status'] = 'new-key-valid';
 323                  elseif ( $akismet_user->status == 'notice' )
 324                      self::$notices['status'] = $akismet_user;
 325                  else
 326                      self::$notices['status'] = $akismet_user->status;
 327              }
 328              else
 329                  self::$notices['status'] = 'new-key-invalid';
 330          }
 331          elseif ( in_array( $key_status, array( 'invalid', 'failed' ) ) )
 332              self::$notices['status'] = 'new-key-'.$key_status;
 333      }
 334  
 335  	public static function dashboard_stats() {
 336          if ( did_action( 'rightnow_end' ) ) {
 337              return; // We already displayed this info in the "Right Now" section
 338          }
 339  
 340          if ( !$count = get_option('akismet_spam_count') )
 341              return;
 342  
 343          global $submenu;
 344  
 345          echo '<h3>' . esc_html( _x( 'Spam', 'comments' , 'akismet') ) . '</h3>';
 346  
 347          echo '<p>'.sprintf( _n(
 348                  '<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comment</a>.',
 349                  '<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comments</a>.',
 350                  $count
 351              , '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>';
 352      }
 353  
 354      // WP 2.5+
 355  	public static function rightnow_stats() {
 356          if ( $count = get_option('akismet_spam_count') ) {
 357              $intro = sprintf( _n(
 358                  '<a href="%1$s">Akismet</a> has protected your site from %2$s spam comment already. ',
 359                  '<a href="%1$s">Akismet</a> has protected your site from %2$s spam comments already. ',
 360                  $count
 361              , 'akismet'), 'https://akismet.com/wordpress/', number_format_i18n( $count ) );
 362          } else {
 363              $intro = sprintf( __('<a href="%s">Akismet</a> blocks spam from getting to your blog. ', 'akismet'), 'https://akismet.com/wordpress/' );
 364          }
 365  
 366          $link = add_query_arg( array( 'comment_status' => 'spam' ), admin_url( 'edit-comments.php' ) );
 367  
 368          if ( $queue_count = self::get_spam_count() ) {
 369              $queue_text = sprintf( _n(
 370                  'There&#8217;s <a href="%2$s">%1$s comment</a> in your spam queue right now.',
 371                  'There are <a href="%2$s">%1$s comments</a> in your spam queue right now.',
 372                  $queue_count
 373              , 'akismet'), number_format_i18n( $queue_count ), esc_url( $link ) );
 374          } else {
 375              $queue_text = sprintf( __( "There&#8217;s nothing in your <a href='%s'>spam queue</a> at the moment." , 'akismet'), esc_url( $link ) );
 376          }
 377  
 378          $text = $intro . '<br />' . $queue_text;
 379          echo "<p class='akismet-right-now'>$text</p>\n";
 380      }
 381  
 382  	public static function check_for_spam_button( $comment_status ) {
 383          // The "Check for Spam" button should only appear when the page might be showing
 384          // a comment with comment_approved=0, which means an un-trashed, un-spammed,
 385          // not-yet-moderated comment.
 386          if ( 'all' != $comment_status && 'moderated' != $comment_status ) {
 387              return;
 388          }
 389  
 390          $link = '';
 391  
 392          $comments_count = wp_count_comments();
 393          
 394          echo '</div>';
 395          echo '<div class="alignleft actions">';
 396  
 397          $classes = array(
 398              'button-secondary',
 399              'checkforspam',
 400              'button-disabled'    // Disable button until the page is loaded
 401          );
 402  
 403          if ( $comments_count->moderated > 0 ) {
 404              $classes[] = 'enable-on-load';
 405  
 406              if ( ! Akismet::get_api_key() ) {
 407                  $link = add_query_arg( array( 'page' => 'akismet-key-config' ), class_exists( 'Jetpack' ) ? admin_url( 'admin.php' ) : admin_url( 'options-general.php' ) );
 408                  $classes[] = 'ajax-disabled';
 409              }
 410          }
 411  
 412          echo '<a
 413                  class="' . esc_attr( implode( ' ', $classes ) ) . '"' .
 414                  ( ! empty( $link ) ? ' href="' . esc_url( $link ) . '"' : '' ) .
 415                  /* translators: The placeholder is for showing how much of the process has completed, as a percent. e.g., "Checking for Spam (40%)" */
 416                  ' data-progress-label="' . esc_attr( __( 'Checking for Spam (%1$s%)', 'akismet' ) ) . '"
 417                  data-success-url="' . esc_attr( remove_query_arg( array( 'akismet_recheck', 'akismet_recheck_error' ), add_query_arg( array( 'akismet_recheck_complete' => 1, 'recheck_count' => urlencode( '__recheck_count__' ), 'spam_count' => urlencode( '__spam_count__' ) ) ) ) ) . '"
 418                  data-failure-url="' . esc_attr( remove_query_arg( array( 'akismet_recheck', 'akismet_recheck_complete' ), add_query_arg( array( 'akismet_recheck_error' => 1 ) ) ) ) . '"
 419                  data-pending-comment-count="' . esc_attr( $comments_count->moderated ) . '"
 420                  data-nonce="' . esc_attr( wp_create_nonce( 'akismet_check_for_spam' ) ) . '"
 421                  ' . ( ! in_array( 'ajax-disabled', $classes ) ? 'onclick="return false;"' : '' ) . '
 422                  >' . esc_html__('Check for Spam', 'akismet') . '</a>';
 423          echo '<span class="checkforspam-spinner"></span>';
 424      }
 425  
 426  	public static function recheck_queue() {
 427          global $wpdb;
 428  
 429          Akismet::fix_scheduled_recheck();
 430  
 431          if ( ! ( isset( $_GET['recheckqueue'] ) || ( isset( $_REQUEST['action'] ) && 'akismet_recheck_queue' == $_REQUEST['action'] ) ) ) {
 432              return;
 433          }
 434          
 435          if ( ! wp_verify_nonce( $_POST['nonce'], 'akismet_check_for_spam' ) ) {
 436              wp_send_json( array(
 437                  'error' => __( "You don't have permission to do that."),
 438              ));
 439              return;
 440          }
 441  
 442          $result_counts = self::recheck_queue_portion( empty( $_POST['offset'] ) ? 0 : $_POST['offset'], empty( $_POST['limit'] ) ? 100 : $_POST['limit'] );
 443  
 444          if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
 445              wp_send_json( array(
 446                  'counts' => $result_counts,
 447              ));
 448          }
 449          else {
 450              $redirect_to = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : admin_url( 'edit-comments.php' );
 451              wp_safe_redirect( $redirect_to );
 452              exit;
 453          }
 454      }
 455      
 456  	public static function recheck_queue_portion( $start = 0, $limit = 100 ) {
 457          global $wpdb;
 458          
 459          $paginate = '';
 460  
 461          if ( $limit <= 0 ) {
 462              $limit = 100;
 463          }
 464  
 465          if ( $start < 0 ) {
 466              $start = 0;
 467          }
 468  
 469          $moderation = $wpdb->get_col( $wpdb->prepare( "SELECT * FROM {$wpdb->comments} WHERE comment_approved = '0' LIMIT %d OFFSET %d", $limit, $start ) );
 470  
 471          $result_counts = array(
 472              'processed' => count( $moderation ),
 473              'spam' => 0,
 474              'ham' => 0,
 475              'error' => 0,
 476          );
 477  
 478          foreach ( $moderation as $comment_id ) {
 479              $api_response = Akismet::recheck_comment( $comment_id, 'recheck_queue' );
 480  
 481              if ( 'true' === $api_response ) {
 482                  ++$result_counts['spam'];
 483              }
 484              elseif ( 'false' === $api_response ) {
 485                  ++$result_counts['ham'];
 486              }
 487              else {
 488                  ++$result_counts['error'];
 489              }
 490          }
 491  
 492          return $result_counts;
 493      }
 494  
 495      // Adds an 'x' link next to author URLs, clicking will remove the author URL and show an undo link
 496  	public static function remove_comment_author_url() {
 497          if ( !empty( $_POST['id'] ) && check_admin_referer( 'comment_author_url_nonce' ) ) {
 498              $comment_id = intval( $_POST['id'] );
 499              $comment = get_comment( $comment_id, ARRAY_A );
 500              if ( $comment && current_user_can( 'edit_comment', $comment['comment_ID'] ) ) {
 501                  $comment['comment_author_url'] = '';
 502                  do_action( 'comment_remove_author_url' );
 503                  print( wp_update_comment( $comment ) );
 504                  die();
 505              }
 506          }
 507      }
 508  
 509  	public static function add_comment_author_url() {
 510          if ( !empty( $_POST['id'] ) && !empty( $_POST['url'] ) && check_admin_referer( 'comment_author_url_nonce' ) ) {
 511              $comment_id = intval( $_POST['id'] );
 512              $comment = get_comment( $comment_id, ARRAY_A );
 513              if ( $comment && current_user_can( 'edit_comment', $comment['comment_ID'] ) ) {
 514                  $comment['comment_author_url'] = esc_url( $_POST['url'] );
 515                  do_action( 'comment_add_author_url' );
 516                  print( wp_update_comment( $comment ) );
 517                  die();
 518              }
 519          }
 520      }
 521  
 522  	public static function comment_row_action( $a, $comment ) {
 523          $akismet_result = get_comment_meta( $comment->comment_ID, 'akismet_result', true );
 524          $akismet_error  = get_comment_meta( $comment->comment_ID, 'akismet_error', true );
 525          $user_result    = get_comment_meta( $comment->comment_ID, 'akismet_user_result', true);
 526          $comment_status = wp_get_comment_status( $comment->comment_ID );
 527          $desc = null;
 528          if ( $akismet_error ) {
 529              $desc = __( 'Awaiting spam check' , 'akismet');
 530          } elseif ( !$user_result || $user_result == $akismet_result ) {
 531              // Show the original Akismet result if the user hasn't overridden it, or if their decision was the same
 532              if ( $akismet_result == 'true' && $comment_status != 'spam' && $comment_status != 'trash' )
 533                  $desc = __( 'Flagged as spam by Akismet' , 'akismet');
 534              elseif ( $akismet_result == 'false' && $comment_status == 'spam' )
 535                  $desc = __( 'Cleared by Akismet' , 'akismet');
 536          } else {
 537              $who = get_comment_meta( $comment->comment_ID, 'akismet_user', true );
 538              if ( $user_result == 'true' )
 539                  $desc = sprintf( __('Flagged as spam by %s', 'akismet'), $who );
 540              else
 541                  $desc = sprintf( __('Un-spammed by %s', 'akismet'), $who );
 542          }
 543  
 544          // add a History item to the hover links, just after Edit
 545          if ( $akismet_result ) {
 546              $b = array();
 547              foreach ( $a as $k => $item ) {
 548                  $b[ $k ] = $item;
 549                  if (
 550                      $k == 'edit'
 551                      || $k == 'unspam'
 552                  ) {
 553                      $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>';
 554                  }
 555              }
 556  
 557              $a = $b;
 558          }
 559  
 560          if ( $desc )
 561              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>';
 562  
 563          $show_user_comments_option = get_option( 'akismet_show_user_comments_approved' );
 564          
 565          if ( $show_user_comments_option === false ) {
 566              // Default to active if the user hasn't made a decision.
 567              $show_user_comments_option = '1';
 568          }
 569          
 570          $show_user_comments = apply_filters( 'akismet_show_user_comments_approved', $show_user_comments_option );
 571          $show_user_comments = $show_user_comments === 'false' ? false : $show_user_comments; //option used to be saved as 'false' / 'true'
 572          
 573          if ( $show_user_comments ) {
 574              $comment_count = Akismet::get_user_comments_approved( $comment->user_id, $comment->comment_author_email, $comment->comment_author, $comment->comment_author_url );
 575              $comment_count = intval( $comment_count );
 576              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>';
 577          }
 578  
 579          return $a;
 580      }
 581  
 582  	public static function comment_status_meta_box( $comment ) {
 583          $history = Akismet::get_comment_history( $comment->comment_ID );
 584  
 585          if ( $history ) {
 586              foreach ( $history as $row ) {
 587                  $time = date( 'D d M Y @ h:i:s a', $row['time'] ) . ' GMT';
 588                  
 589                  $message = '';
 590                  
 591                  if ( ! empty( $row['message'] ) ) {
 592                      // Old versions of Akismet stored the message as a literal string in the commentmeta.
 593                      // New versions don't do that for two reasons:
 594                      // 1) Save space.
 595                      // 2) The message can be translated into the current language of the blog, not stuck 
 596                      //    in the language of the blog when the comment was made.
 597                      $message = esc_html( $row['message'] );
 598                  }
 599                  
 600                  // If possible, use a current translation.
 601                  switch ( $row['event'] ) {
 602                      case 'recheck-spam';
 603                          $message = esc_html( __( 'Akismet re-checked and caught this comment as spam.', 'akismet' ) );
 604                      break;
 605                      case 'check-spam':
 606                          $message = esc_html( __( 'Akismet caught this comment as spam.', 'akismet' ) );
 607                      break;
 608                      case 'recheck-ham':
 609                          $message = esc_html( __( 'Akismet re-checked and cleared this comment.', 'akismet' ) );
 610                      break;
 611                      case 'check-ham':
 612                          $message = esc_html( __( 'Akismet cleared this comment.', 'akismet' ) );
 613                      break;
 614                      case 'wp-blacklisted':
 615                      case 'wp-disallowed':
 616                          $message = sprintf(
 617                              /* translators: The placeholder is a WordPress PHP function name. */
 618                              esc_html( __( 'Comment was caught by %s.', 'akismet' ) ),
 619                              function_exists( 'wp_check_comment_disallowed_list' ) ? '<code>wp_check_comment_disallowed_list</code>' : '<code>wp_blacklist_check</code>'
 620                          );
 621                      break;
 622                      case 'report-spam':
 623                          if ( isset( $row['user'] ) ) {
 624                              $message = esc_html( sprintf( __( '%s reported this comment as spam.', 'akismet' ), $row['user'] ) );
 625                          }
 626                          else if ( ! $message ) {
 627                              $message = esc_html( __( 'This comment was reported as spam.', 'akismet' ) );
 628                          }
 629                      break;
 630                      case 'report-ham':
 631                          if ( isset( $row['user'] ) ) {
 632                              $message = esc_html( sprintf( __( '%s reported this comment as not spam.', 'akismet' ), $row['user'] ) );
 633                          }
 634                          else if ( ! $message ) {
 635                              $message = esc_html( __( 'This comment was reported as not spam.', 'akismet' ) );
 636                          }
 637                      break;
 638                      case 'cron-retry-spam':
 639                          $message = esc_html( __( 'Akismet caught this comment as spam during an automatic retry.' , 'akismet') );
 640                      break;
 641                      case 'cron-retry-ham':
 642                          $message = esc_html( __( 'Akismet cleared this comment during an automatic retry.', 'akismet') );
 643                      break;
 644                      case 'check-error':
 645                          if ( isset( $row['meta'], $row['meta']['response'] ) ) {
 646                              $message = sprintf( esc_html( __( 'Akismet was unable to check this comment (response: %s) but will automatically retry later.', 'akismet') ), '<code>' . esc_html( $row['meta']['response'] ) . '</code>' );
 647                          }
 648                          else {
 649                              $message = esc_html( __( 'Akismet was unable to check this comment but will automatically retry later.', 'akismet' ) );
 650                          }
 651                      break;
 652                      case 'recheck-error':
 653                          if ( isset( $row['meta'], $row['meta']['response'] ) ) {
 654                              $message = sprintf( esc_html( __( 'Akismet was unable to recheck this comment (response: %s).', 'akismet') ), '<code>' . esc_html( $row['meta']['response'] ) . '</code>' );
 655                          }
 656                          else {
 657                              $message = esc_html( __( 'Akismet was unable to recheck this comment.', 'akismet' ) );
 658                          }
 659                      break;
 660                      default:
 661                          if ( preg_match( '/^status-changed/', $row['event'] ) ) {
 662                              // Half of these used to be saved without the dash after 'status-changed'.
 663                              // See https://plugins.trac.wordpress.org/changeset/1150658/akismet/trunk
 664                              $new_status = preg_replace( '/^status-changed-?/', '', $row['event'] );
 665                              $message = sprintf( esc_html( __( 'Comment status was changed to %s', 'akismet' ) ), '<code>' . esc_html( $new_status ) . '</code>' );
 666                          }
 667                          else if ( preg_match( '/^status-/', $row['event'] ) ) {
 668                              $new_status = preg_replace( '/^status-/', '', $row['event'] );
 669  
 670                              if ( isset( $row['user'] ) ) {
 671                                  $message = sprintf( esc_html( __( '%1$s changed the comment status to %2$s.', 'akismet' ) ), $row['user'], '<code>' . esc_html( $new_status ) . '</code>' );
 672                              }
 673                          }
 674                      break;
 675                      
 676                  }
 677  
 678                  if ( ! empty( $message ) ) {
 679                      echo '<p>';
 680                      echo '<span style="color: #999;" alt="' . $time . '" title="' . $time . '">' . sprintf( esc_html__('%s ago', 'akismet'), human_time_diff( $row['time'] ) ) . '</span>';
 681                      echo ' - ';
 682                      echo $message; // esc_html() is done above so that we can use HTML in some messages.
 683                      echo '</p>';
 684                  }
 685              }
 686          }
 687          else {
 688              echo '<p>';
 689              echo esc_html( __( 'No comment history.', 'akismet' ) );
 690              echo '</p>';
 691          }
 692      }
 693  
 694  	public static function plugin_action_links( $links, $file ) {
 695          if ( $file == plugin_basename( plugin_dir_url( __FILE__ ) . '/akismet.php' ) ) {
 696              $links[] = '<a href="' . esc_url( self::get_page_url() ) . '">'.esc_html__( 'Settings' , 'akismet').'</a>';
 697          }
 698  
 699          return $links;
 700      }
 701  
 702      // Total spam in queue
 703      // get_option( 'akismet_spam_count' ) is the total caught ever
 704  	public static function get_spam_count( $type = false ) {
 705          global $wpdb;
 706  
 707          if ( !$type ) { // total
 708              $count = wp_cache_get( 'akismet_spam_count', 'widget' );
 709              if ( false === $count ) {
 710                  $count = wp_count_comments();
 711                  $count = $count->spam;
 712                  wp_cache_set( 'akismet_spam_count', $count, 'widget', 3600 );
 713              }
 714              return $count;
 715          } elseif ( 'comments' == $type || 'comment' == $type ) { // comments
 716              $type = '';
 717          }
 718  
 719          return (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(comment_ID) FROM {$wpdb->comments} WHERE comment_approved = 'spam' AND comment_type = %s", $type ) );
 720      }
 721  
 722      // Check connectivity between the WordPress blog and Akismet's servers.
 723      // 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).
 724  	public static function check_server_ip_connectivity() {
 725          
 726          $servers = $ips = array();
 727  
 728          // Some web hosts may disable this function
 729          if ( function_exists('gethostbynamel') ) {    
 730              
 731              $ips = gethostbynamel( 'rest.akismet.com' );
 732              if ( $ips && is_array($ips) && count($ips) ) {
 733                  $api_key = Akismet::get_api_key();
 734                  
 735                  foreach ( $ips as $ip ) {
 736                      $response = Akismet::verify_key( $api_key, $ip );
 737                      // even if the key is invalid, at least we know we have connectivity
 738                      if ( $response == 'valid' || $response == 'invalid' )
 739                          $servers[$ip] = 'connected';
 740                      else
 741                          $servers[$ip] = $response ? $response : 'unable to connect';
 742                  }
 743              }
 744          }
 745          
 746          return $servers;
 747      }
 748      
 749      // Simpler connectivity check
 750  	public static function check_server_connectivity($cache_timeout = 86400) {
 751          
 752          $debug = array();
 753          $debug[ 'PHP_VERSION' ]         = PHP_VERSION;
 754          $debug[ 'WORDPRESS_VERSION' ]   = $GLOBALS['wp_version'];
 755          $debug[ 'AKISMET_VERSION' ]     = AKISMET_VERSION;
 756          $debug[ 'AKISMET__PLUGIN_DIR' ] = AKISMET__PLUGIN_DIR;
 757          $debug[ 'SITE_URL' ]            = site_url();
 758          $debug[ 'HOME_URL' ]            = home_url();
 759          
 760          $servers = get_option('akismet_available_servers');
 761          if ( (time() - get_option('akismet_connectivity_time') < $cache_timeout) && $servers !== false ) {
 762              $servers = self::check_server_ip_connectivity();
 763              update_option('akismet_available_servers', $servers);
 764              update_option('akismet_connectivity_time', time());
 765          }
 766  
 767          if ( wp_http_supports( array( 'ssl' ) ) ) {
 768              $response = wp_remote_get( 'https://rest.akismet.com/1.1/test' );
 769          }
 770          else {
 771              $response = wp_remote_get( 'http://rest.akismet.com/1.1/test' );
 772          }
 773  
 774          $debug[ 'gethostbynamel' ]  = function_exists('gethostbynamel') ? 'exists' : 'not here';
 775          $debug[ 'Servers' ]         = $servers;
 776          $debug[ 'Test Connection' ] = $response;
 777          
 778          Akismet::log( $debug );
 779          
 780          if ( $response && 'connected' == wp_remote_retrieve_body( $response ) )
 781              return true;
 782          
 783          return false;
 784      }
 785  
 786      // Check the server connectivity and store the available servers in an option. 
 787  	public static function get_server_connectivity($cache_timeout = 86400) {
 788          return self::check_server_connectivity( $cache_timeout );
 789      }
 790  
 791      /**
 792       * Find out whether any comments in the Pending queue have not yet been checked by Akismet.
 793       *
 794       * @return bool
 795       */
 796  	public static function are_any_comments_waiting_to_be_checked() {
 797          return !! get_comments( array(
 798              // Exclude comments that are not pending. This would happen if someone manually approved or spammed a comment
 799              // that was waiting to be checked. The akismet_error meta entry will eventually be removed by the cron recheck job.
 800              'status' => 'hold',
 801              
 802              // This is the commentmeta that is saved when a comment couldn't be checked.
 803              'meta_key' => 'akismet_error',
 804              
 805              // We only need to know whether at least one comment is waiting for a check.
 806              'number' => 1,
 807          ) );
 808      }
 809  
 810  	public static function get_page_url( $page = 'config' ) {
 811  
 812          $args = array( 'page' => 'akismet-key-config' );
 813  
 814          if ( $page == 'stats' )
 815              $args = array( 'page' => 'akismet-key-config', 'view' => 'stats' );
 816          elseif ( $page == 'delete_key' )
 817              $args = array( 'page' => 'akismet-key-config', 'view' => 'start', 'action' => 'delete-key', '_wpnonce' => wp_create_nonce( self::NONCE ) );
 818  
 819          $url = add_query_arg( $args, class_exists( 'Jetpack' ) ? admin_url( 'admin.php' ) : admin_url( 'options-general.php' ) );
 820  
 821          return $url;
 822      }
 823      
 824  	public static function get_akismet_user( $api_key ) {
 825          $akismet_user = false;
 826  
 827          $subscription_verification = Akismet::http_post( Akismet::build_query( array( 'key' => $api_key, 'blog' => get_option( 'home' ) ) ), 'get-subscription' );
 828  
 829          if ( ! empty( $subscription_verification[1] ) ) {
 830              if ( 'invalid' !== $subscription_verification[1] ) {
 831                  $akismet_user = json_decode( $subscription_verification[1] );
 832              }
 833          }
 834  
 835          return $akismet_user;
 836      }
 837      
 838  	public static function get_stats( $api_key ) {
 839          $stat_totals = array();
 840  
 841          foreach( array( '6-months', 'all' ) as $interval ) {
 842              $response = Akismet::http_post( Akismet::build_query( array( 'blog' => get_option( 'home' ), 'key' => $api_key, 'from' => $interval ) ), 'get-stats' );
 843  
 844              if ( ! empty( $response[1] ) ) {
 845                  $stat_totals[$interval] = json_decode( $response[1] );
 846              }
 847          }
 848  
 849          return $stat_totals;
 850      }
 851      
 852  	public static function verify_wpcom_key( $api_key, $user_id, $extra = array() ) {
 853          $akismet_account = Akismet::http_post( Akismet::build_query( array_merge( array(
 854              'user_id'          => $user_id,
 855              'api_key'          => $api_key,
 856              'get_account_type' => 'true'
 857          ), $extra ) ), 'verify-wpcom-key' );
 858  
 859          if ( ! empty( $akismet_account[1] ) )
 860              $akismet_account = json_decode( $akismet_account[1] );
 861  
 862          Akismet::log( compact( 'akismet_account' ) );
 863          
 864          return $akismet_account;
 865      }
 866      
 867  	public static function connect_jetpack_user() {
 868      
 869          if ( $jetpack_user = self::get_jetpack_user() ) {
 870              if ( isset( $jetpack_user['user_id'] ) && isset(  $jetpack_user['api_key'] ) ) {
 871                  $akismet_user = self::verify_wpcom_key( $jetpack_user['api_key'], $jetpack_user['user_id'], array( 'action' => 'connect_jetpack_user' ) );
 872                              
 873                  if ( is_object( $akismet_user ) ) {
 874                      self::save_key( $akismet_user->api_key );
 875                      return in_array( $akismet_user->status, array( 'active', 'active-dunning', 'no-sub' ) );
 876                  }
 877              }
 878          }
 879          
 880          return false;
 881      }
 882  
 883  	public static function display_alert() {
 884          Akismet::view( 'notice', array(
 885              'type' => 'alert',
 886              'code' => (int) get_option( 'akismet_alert_code' ),
 887              'msg'  => get_option( 'akismet_alert_msg' )
 888          ) );
 889      }
 890  
 891  	public static function display_spam_check_warning() {
 892          Akismet::fix_scheduled_recheck();
 893  
 894          if ( wp_next_scheduled('akismet_schedule_cron_recheck') > time() && self::are_any_comments_waiting_to_be_checked() ) {
 895              $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() ) ) );
 896              Akismet::view( 'notice', array( 'type' => 'spam-check', 'link_text' => $link_text ) );
 897          }
 898      }
 899  
 900  	public static function display_api_key_warning() {
 901          Akismet::view( 'notice', array( 'type' => 'plugin' ) );
 902      }
 903  
 904  	public static function display_page() {
 905          if ( !Akismet::get_api_key() || ( isset( $_GET['view'] ) && $_GET['view'] == 'start' ) )
 906              self::display_start_page();
 907          elseif ( isset( $_GET['view'] ) && $_GET['view'] == 'stats' )
 908              self::display_stats_page();
 909          else
 910              self::display_configuration_page();
 911      }
 912  
 913  	public static function display_start_page() {
 914          if ( isset( $_GET['action'] ) ) {
 915              if ( $_GET['action'] == 'delete-key' ) {
 916                  if ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], self::NONCE ) )
 917                      delete_option( 'wordpress_api_key' );
 918              }
 919          }
 920  
 921          if ( $api_key = Akismet::get_api_key() && ( empty( self::$notices['status'] ) || 'existing-key-invalid' != self::$notices['status'] ) ) {
 922              self::display_configuration_page();
 923              return;
 924          }
 925          
 926          //the user can choose to auto connect their API key by clicking a button on the akismet done page
 927          //if jetpack, get verified api key by using connected wpcom user id
 928          //if no jetpack, get verified api key by using an akismet token    
 929          
 930          $akismet_user = false;
 931          
 932          if ( isset( $_GET['token'] ) && preg_match('/^(\d+)-[0-9a-f]{20}$/', $_GET['token'] ) )
 933              $akismet_user = self::verify_wpcom_key( '', '', array( 'token' => $_GET['token'] ) );
 934          elseif ( $jetpack_user = self::get_jetpack_user() )
 935              $akismet_user = self::verify_wpcom_key( $jetpack_user['api_key'], $jetpack_user['user_id'] );
 936              
 937          if ( isset( $_GET['action'] ) ) {
 938              if ( $_GET['action'] == 'save-key' ) {
 939                  if ( is_object( $akismet_user ) ) {
 940                      self::save_key( $akismet_user->api_key );
 941                      self::display_configuration_page();
 942                      return;
 943                  }
 944              }
 945          }
 946  
 947          Akismet::view( 'start', compact( 'akismet_user' ) );
 948  
 949          /*
 950          // To see all variants when testing.
 951          $akismet_user->status = 'no-sub';
 952          Akismet::view( 'start', compact( 'akismet_user' ) );
 953          $akismet_user->status = 'cancelled';
 954          Akismet::view( 'start', compact( 'akismet_user' ) );
 955          $akismet_user->status = 'suspended';
 956          Akismet::view( 'start', compact( 'akismet_user' ) );
 957          $akismet_user->status = 'other';
 958          Akismet::view( 'start', compact( 'akismet_user' ) );
 959          $akismet_user = false;
 960          */
 961      }
 962  
 963  	public static function display_stats_page() {
 964          Akismet::view( 'stats' );
 965      }
 966  
 967  	public static function display_configuration_page() {
 968          $api_key      = Akismet::get_api_key();
 969          $akismet_user = self::get_akismet_user( $api_key );
 970          
 971          if ( ! $akismet_user ) {
 972              // This could happen if the user's key became invalid after it was previously valid and successfully set up.
 973              self::$notices['status'] = 'existing-key-invalid';
 974              self::display_start_page();
 975              return;
 976          }
 977  
 978          $stat_totals  = self::get_stats( $api_key );
 979  
 980          // If unset, create the new strictness option using the old discard option to determine its default.
 981          // If the old option wasn't set, default to discarding the blatant spam.
 982          if ( get_option( 'akismet_strictness' ) === false ) {
 983              add_option( 'akismet_strictness', ( get_option( 'akismet_discard_month' ) === 'false' ? '0' : '1' ) );
 984          }
 985          
 986          // Sync the local "Total spam blocked" count with the authoritative count from the server.
 987          if ( isset( $stat_totals['all'], $stat_totals['all']->spam ) ) {
 988              update_option( 'akismet_spam_count', $stat_totals['all']->spam );
 989          }
 990  
 991          $notices = array();
 992  
 993          if ( empty( self::$notices ) ) {
 994              if ( ! empty( $stat_totals['all'] ) && isset( $stat_totals['all']->time_saved ) && $akismet_user->status == 'active' && $akismet_user->account_type == 'free-api-key' ) {
 995  
 996                  $time_saved = false;
 997  
 998                  if ( $stat_totals['all']->time_saved > 1800 ) {
 999                      $total_in_minutes = round( $stat_totals['all']->time_saved / 60 );
1000                      $total_in_hours   = round( $total_in_minutes / 60 );
1001                      $total_in_days    = round( $total_in_hours / 8 );
1002                      $cleaning_up      = __( 'Cleaning up spam takes time.' , 'akismet');
1003  
1004                      if ( $total_in_days > 1 )
1005                          $time_saved = $cleaning_up . ' ' . sprintf( _n( 'Akismet has saved you %s day!', 'Akismet has saved you %s days!', $total_in_days, 'akismet' ), number_format_i18n( $total_in_days ) );
1006                      elseif ( $total_in_hours > 1 )
1007                          $time_saved = $cleaning_up . ' ' . sprintf( _n( 'Akismet has saved you %d hour!', 'Akismet has saved you %d hours!', $total_in_hours, 'akismet' ), $total_in_hours );
1008                      elseif ( $total_in_minutes >= 30 )
1009                          $time_saved = $cleaning_up . ' ' . sprintf( _n( 'Akismet has saved you %d minute!', 'Akismet has saved you %d minutes!', $total_in_minutes, 'akismet' ), $total_in_minutes );
1010                  }
1011                  
1012                  $notices[] =  array( 'type' => 'active-notice', 'time_saved' => $time_saved );
1013              }
1014              
1015              if ( !empty( $akismet_user->limit_reached ) && in_array( $akismet_user->limit_reached, array( 'yellow', 'red' ) ) ) {
1016                  $notices[] = array( 'type' => 'limit-reached', 'level' => $akismet_user->limit_reached );
1017              }
1018          }
1019          
1020          if ( !isset( self::$notices['status'] ) && in_array( $akismet_user->status, array( 'cancelled', 'suspended', 'missing', 'no-sub' ) ) ) {
1021              $notices[] = array( 'type' => $akismet_user->status );
1022          }
1023  
1024          /*
1025          // To see all variants when testing.
1026          $notices[] = array( 'type' => 'active-notice', 'time_saved' => 'Cleaning up spam takes time. Akismet has saved you 1 minute!' );
1027          $notices[] = array( 'type' => 'plugin' );
1028          $notices[] = array( 'type' => 'spam-check', 'link_text' => 'Link text.' );
1029          $notices[] = array( 'type' => 'notice', 'notice_header' => 'This is the notice header.', 'notice_text' => 'This is the notice text.' );
1030          $notices[] = array( 'type' => 'missing-functions' );
1031          $notices[] = array( 'type' => 'servers-be-down' );
1032          $notices[] = array( 'type' => 'active-dunning' );
1033          $notices[] = array( 'type' => 'cancelled' );
1034          $notices[] = array( 'type' => 'suspended' );
1035          $notices[] = array( 'type' => 'missing' );
1036          $notices[] = array( 'type' => 'no-sub' );
1037          $notices[] = array( 'type' => 'new-key-valid' );
1038          $notices[] = array( 'type' => 'new-key-invalid' );
1039          $notices[] = array( 'type' => 'existing-key-invalid' );
1040          $notices[] = array( 'type' => 'new-key-failed' );
1041          $notices[] = array( 'type' => 'limit-reached', 'level' => 'yellow' );
1042          $notices[] = array( 'type' => 'limit-reached', 'level' => 'red' );
1043          */
1044          
1045          Akismet::log( compact( 'stat_totals', 'akismet_user' ) );
1046          Akismet::view( 'config', compact( 'api_key', 'akismet_user', 'stat_totals', 'notices' ) );
1047      }
1048  
1049  	public static function display_notice() {
1050          global $hook_suffix;
1051  
1052          if ( in_array( $hook_suffix, array( 'jetpack_page_akismet-key-config', 'settings_page_akismet-key-config' ) ) ) {
1053              // This page manages the notices and puts them inline where they make sense.
1054              return;
1055          }
1056  
1057          if ( in_array( $hook_suffix, array( 'edit-comments.php' ) ) && (int) get_option( 'akismet_alert_code' ) > 0 ) {
1058              Akismet::verify_key( Akismet::get_api_key() ); //verify that the key is still in alert state
1059              
1060              if ( get_option( 'akismet_alert_code' ) > 0 )
1061                  self::display_alert();
1062          }
1063          elseif ( ( 'plugins.php' === $hook_suffix || 'edit-comments.php' === $hook_suffix ) && ! Akismet::get_api_key() ) {
1064              // Show the "Set Up Akismet" banner on the comments and plugin pages if no API key has been set.
1065              self::display_api_key_warning();
1066          }
1067          elseif ( $hook_suffix == 'edit-comments.php' && wp_next_scheduled( 'akismet_schedule_cron_recheck' ) ) {
1068              self::display_spam_check_warning();
1069          }
1070          
1071          if ( isset( $_GET['akismet_recheck_complete'] ) ) {
1072              $recheck_count = (int) $_GET['recheck_count'];
1073              $spam_count = (int) $_GET['spam_count'];
1074              
1075              if ( $recheck_count === 0 ) {
1076                  $message = __( 'There were no comments to check. Akismet will only check comments awaiting moderation.', 'akismet' );
1077              }
1078              else {
1079                  $message = sprintf( _n( 'Akismet checked %s comment.', 'Akismet checked %s comments.', $recheck_count, 'akismet' ), number_format( $recheck_count ) );
1080                  $message .= ' ';
1081              
1082                  if ( $spam_count === 0 ) {
1083                      $message .= __( 'No comments were caught as spam.', 'akismet' );
1084                  }
1085                  else {
1086                      $message .= sprintf( _n( '%s comment was caught as spam.', '%s comments were caught as spam.', $spam_count, 'akismet' ), number_format( $spam_count ) );
1087                  }
1088              }
1089              
1090              echo '<div class="notice notice-success"><p>' . esc_html( $message ) . '</p></div>';
1091          }
1092          else if ( isset( $_GET['akismet_recheck_error'] ) ) {
1093              echo '<div class="notice notice-error"><p>' . esc_html( __( 'Akismet could not recheck your comments for spam.', 'akismet' ) ) . '</p></div>';
1094          }
1095      }
1096  
1097  	public static function display_status() {
1098          if ( ! self::get_server_connectivity() ) {
1099              Akismet::view( 'notice', array( 'type' => 'servers-be-down' ) );
1100          }
1101          else if ( ! empty( self::$notices ) ) {
1102              foreach ( self::$notices as $index => $type ) {
1103                  if ( is_object( $type ) ) {
1104                      $notice_header = $notice_text = '';
1105                      
1106                      if ( property_exists( $type, 'notice_header' ) ) {
1107                          $notice_header = wp_kses( $type->notice_header, self::$allowed );
1108                      }
1109                  
1110                      if ( property_exists( $type, 'notice_text' ) ) {
1111                          $notice_text = wp_kses( $type->notice_text, self::$allowed );
1112                      }
1113                      
1114                      if ( property_exists( $type, 'status' ) ) {
1115                          $type = wp_kses( $type->status, self::$allowed );
1116                          Akismet::view( 'notice', compact( 'type', 'notice_header', 'notice_text' ) );
1117                          
1118                          unset( self::$notices[ $index ] );
1119                      }
1120                  }
1121                  else {
1122                      Akismet::view( 'notice', compact( 'type' ) );
1123                      
1124                      unset( self::$notices[ $index ] );
1125                  }
1126              }
1127          }
1128      }
1129  
1130  	private static function get_jetpack_user() {
1131          if ( !class_exists('Jetpack') )
1132              return false;
1133  
1134          if ( defined( 'JETPACK__VERSION' ) && version_compare( JETPACK__VERSION, '7.7', '<' )  ) {
1135              // For version of Jetpack prior to 7.7.
1136              Jetpack::load_xml_rpc_client();
1137          }
1138  
1139          $xml = new Jetpack_IXR_ClientMulticall( array( 'user_id' => get_current_user_id() ) );
1140  
1141          $xml->addCall( 'wpcom.getUserID' );
1142          $xml->addCall( 'akismet.getAPIKey' );
1143          $xml->query();
1144  
1145          Akismet::log( compact( 'xml' ) );
1146  
1147          if ( !$xml->isError() ) {
1148              $responses = $xml->getResponse();
1149              if ( count( $responses ) > 1 ) {
1150                  // Due to a quirk in how Jetpack does multi-calls, the response order
1151                  // can't be trusted to match the call order. It's a good thing our
1152                  // return values can be mostly differentiated from each other.
1153                  $first_response_value = array_shift( $responses[0] );
1154                  $second_response_value = array_shift( $responses[1] );
1155                  
1156                  // If WPCOM ever reaches 100 billion users, this will fail. :-)
1157                  if ( preg_match( '/^[a-f0-9]{12}$/i', $first_response_value ) ) {
1158                      $api_key = $first_response_value;
1159                      $user_id = (int) $second_response_value;
1160                  }
1161                  else {
1162                      $api_key = $second_response_value;
1163                      $user_id = (int) $first_response_value;
1164                  }
1165                  
1166                  return compact( 'api_key', 'user_id' );
1167              }
1168          }
1169          return false;
1170      }
1171      
1172      /**
1173       * Some commentmeta isn't useful in an export file. Suppress it (when supported).
1174       *
1175       * @param bool $exclude
1176       * @param string $key The meta key
1177       * @param object $meta The meta object
1178       * @return bool Whether to exclude this meta entry from the export.
1179       */
1180  	public static function exclude_commentmeta_from_export( $exclude, $key, $meta ) {
1181          if ( in_array( $key, array( 'akismet_as_submitted', 'akismet_rechecking', 'akismet_delayed_moderation_email' ) ) ) {
1182              return true;
1183          }
1184          
1185          return $exclude;
1186      }
1187      
1188      /**
1189       * When Akismet is active, remove the "Activate Akismet" step from the plugin description.
1190       */
1191  	public static function modify_plugin_description( $all_plugins ) {
1192          if ( isset( $all_plugins['akismet/akismet.php'] ) ) {
1193              if ( Akismet::get_api_key() ) {
1194                  $all_plugins['akismet/akismet.php']['Description'] = __( 'Used by millions, Akismet is quite possibly the best way in the world to <strong>protect your blog from spam</strong>. Your site is fully configured and being protected, even while you sleep.', 'akismet' );
1195              }
1196              else {
1197                  $all_plugins['akismet/akismet.php']['Description'] = __( 'Used by millions, Akismet is quite possibly the best way in the world to <strong>protect your blog from spam</strong>. It keeps your site protected even while you sleep. To get started, just go to <a href="admin.php?page=akismet-key-config">your Akismet Settings page</a> to set up your API key.', 'akismet' );
1198              }
1199          }
1200          
1201          return $all_plugins;
1202      }
1203  
1204  	private static function set_form_privacy_notice_option( $state ) {
1205          if ( in_array( $state, array( 'display', 'hide' ) ) ) {
1206              update_option( 'akismet_comment_form_privacy_notice', $state );
1207          }
1208      }
1209      
1210  	public static function register_personal_data_eraser( $erasers ) {
1211          $erasers['akismet'] = array(
1212              'eraser_friendly_name' => __( 'Akismet', 'akismet' ),
1213              'callback' => array( 'Akismet_Admin', 'erase_personal_data' ),
1214          );
1215  
1216          return $erasers;
1217      }
1218      
1219      /**
1220       * When a user requests that their personal data be removed, Akismet has a duty to discard
1221       * any personal data we store outside of the comment itself. Right now, that is limited
1222       * to the copy of the comment we store in the akismet_as_submitted commentmeta.
1223       *
1224       * FWIW, this information would be automatically deleted after 15 days.
1225       * 
1226       * @param $email_address string The email address of the user who has requested erasure.
1227       * @param $page int This function can (and will) be called multiple times to prevent timeouts,
1228       *                  so this argument is used for pagination.
1229       * @return array
1230       * @see https://developer.wordpress.org/plugins/privacy/adding-the-personal-data-eraser-to-your-plugin/
1231       */
1232  	public static function erase_personal_data( $email_address, $page = 1 ) {
1233          $items_removed = false;
1234          
1235          $number = 50;
1236          $page = (int) $page;
1237  
1238          $comments = get_comments(
1239              array(
1240                  'author_email' => $email_address,
1241                  'number'       => $number,
1242                  'paged'        => $page,
1243                  'order_by'     => 'comment_ID',
1244                  'order'        => 'ASC',
1245              )
1246          );
1247  
1248          foreach ( (array) $comments as $comment ) {
1249              $comment_as_submitted = get_comment_meta( $comment->comment_ID, 'akismet_as_submitted', true );
1250              
1251              if ( $comment_as_submitted ) {
1252                  delete_comment_meta( $comment->comment_ID, 'akismet_as_submitted' );
1253                  $items_removed = true;
1254              }
1255          }
1256  
1257          // Tell core if we have more comments to work on still
1258          $done = count( $comments ) < $number;
1259          
1260          return array(
1261              'items_removed' => $items_removed,
1262              'items_retained' => false, // always false in this example
1263              'messages' => array(), // no messages in this example
1264              'done' => $done,
1265          );
1266      }
1267  }


Generated : Fri Oct 30 08:20:01 2020 Cross-referenced by PHPXref