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


Generated : Thu Apr 9 08:20:01 2020 Cross-referenced by PHPXref