[ Index ]

PHP Cross Reference of WordPress

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


Generated: Mon Jul 22 01:00:03 2019 Cross-referenced by PHPXref 0.7.1