> Read the accompanying readme.txt file for instructions and documentation.
* =>> Also, visit the plugin's homepage for additional information and updates.
* =>> Or visit: https://wordpress.org/plugins/admin-commenters-comments-count/
*
* @package Admin_Commenters_Comments_Count
* @author Scott Reilly
* @version 1.9
*/
/*
* TODO:
* - When a comment gets approved/unapproved via comment action links, update commenter's count accordingly
* - Allow admin to manually group commenters with different email addresses (allows grouping a person who
* may be using multiple email addresses, or maybe admin prefers to group people per organization). The reported
* counts would be for the group and not the individual. The link to see the emails would search for all of the
* email addresses in the group. Via filter maybe?
* - Add sortability to 'Comments' column in user table
* - Consider inserting commenter bomment bubble via 'comment_row_actions' hook like Akismet does, though that
* requires introducing a JS dependency.
*
*/
/*
Copyright (c) 2009-2018 by Scott Reilly (aka coffee2code)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
defined( 'ABSPATH' ) or die();
if ( ! class_exists( 'c2c_AdminCommentersCommentsCount' ) ) :
class c2c_AdminCommentersCommentsCount {
/**
* The field name.
*
* Changing this requires changing .css and .js files.
*
* @var string
* @access private
*/
private static $field = 'commenters_count';
/**
* The field title.
*
* @var string
* @access private
*/
private static $field_title = '';
/**
* Memoized array of commenter counts.
*
* @var string
* @access private
*
* @since 1.7
*/
private static $memoized = array();
/**
* Prevent instantiation.
*
* @since 1.8
*/
private function __construct() {}
/**
* Prevent unserializing an instance.
*
* @since 1.8
*/
private function __wakeup() {}
/**
* Returns version of the plugin.
*
* @since 1.1.4
*/
public static function version() {
return '1.9';
}
/**
* Initializer
*/
public static function init() {
add_action( 'plugins_loaded', array( __CLASS__, 'do_init' ) );
}
/**
* Performs initialization
*/
public static function do_init() {
// Set translatable and filterable strings
self::$field_title = __( 'Comments', 'admin-commenters-comments-count' );
// Load textdomain.
load_plugin_textdomain( 'admin-commenters-comments-count' );
// Register hooks
add_filter( 'comment_author', array( __CLASS__, 'comment_author' ) );
add_filter( 'get_comment_author_link', array( __CLASS__, 'get_comment_author_link' ) );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_admin_css' ) );
add_filter( 'manage_users_columns', array( __CLASS__, 'add_user_column' ) );
add_filter( 'manage_users_custom_column', array( __CLASS__, 'handle_column_data' ), 10, 3 );
// Disable Akismet's version of this functionality.
add_filter( 'akismet_show_user_comments_approved', '__return_false' );
}
/**
* Resets cached data.
*
* @since 1.7
*/
public static function reset_cache() {
self::$memoized = array();
}
/**
* Enqueues stylesheets if the user has admin expert mode activated.
*
* @since 1.3
*/
public static function enqueue_admin_css() {
wp_enqueue_style( __CLASS__ . '_admin', plugins_url( 'assets/admin.css', __FILE__ ), array(), self::version() );
}
/**
* Adds a column for the count of user comments.
*
* @since 1.4
*
* @param array $users_columns Array of user column titles.
*
* @return array The $posts_columns array with the user comments count column's title added.
*/
public static function add_user_column( $users_columns ) {
$users_columns[ self::$field ] = self::$field_title;
return $users_columns;
}
/**
* Outputs a linked count of the user's comments.
*
* @since 1.4
*
* @param string $output Custom column output. Default empty.
* @param string $column_name Column name.
* @param int $user_id ID of the currently-listed user.
*/
public static function handle_column_data( $output, $column_name, $user_id ) {
if ( self::$field != $column_name ) {
return $output;
}
$user = get_user_by( 'id', $user_id );
list( $comment_count, $pending_count ) = self::get_comments_count( 'comment_author_email', $user->user_email, 'comment', $user->ID );
$msg = sprintf( _n( '%d comment', '%d comments', $comment_count, 'admin-commenters-comments-count' ), $comment_count );
return self::get_comments_bubble( $user->user_email, $comment_count, $pending_count, $msg, false );
}
/**
* Gets the count of comments and pending comments for the given user.
*
* @since 1.4
*
* @param string $field The comment field value to search. One of: comment_author, comment_author_email, comment_author_IP, comment_author_url, user_id
* @param string $value The value of the field to check for.
* @param string $type Optional. comment_type value. Default 'comment'.
* @param int $user_id Optional. The user ID. This is searched for as an OR to the $field search. If set, forces $type to be 'comment'. Default 0.
*
* @return array Array of comment count and pending count.
*/
public static function get_comments_count( $field, $value, $type = 'comment', $user_id = 0 ) {
global $wpdb;
if ( ! in_array( $field, array( 'comment_author', 'comment_author_email', 'comment_author_IP', 'comment_author_url', 'user_id' ) ) ) {
$field = 'comment_author_email';
}
// Check if count has already been memoized.
$memoize_key = "{$field}_{$value}_{$type}_" . (int) $user_id;
if ( isset( self::$memoized[ $memoize_key ] ) && self::$memoized[ $memoize_key ] ) {
return self::$memoized[ $memoize_key ];
}
// Query for counts.
if ( $user_id && 'user_id' != $field ) {
$query = "SELECT COUNT(*) FROM {$wpdb->comments} WHERE ( {$field} = %s OR user_id = %d ) AND comment_approved = %d";
$comment_count = $wpdb->get_var( $wpdb->prepare( $query, $value, $user_id, 1 ) );
$pending_count = $wpdb->get_var( $wpdb->prepare( $query, $value, $user_id, 0 ) );
} elseif ( 'comment' == $type ) {
$query = "SELECT COUNT(*) FROM {$wpdb->comments} WHERE {$field} = %s AND comment_approved = %d";
$comment_count = $wpdb->get_var( $wpdb->prepare( $query, $value, 1 ) );
$pending_count = $wpdb->get_var( $wpdb->prepare( $query, $value, 0 ) );
} elseif ( 'pingback' == $type || 'trackback' == $type ) {
$query = "SELECT COUNT(*) FROM {$wpdb->comments} WHERE comment_author_url LIKE %s AND comment_type = %s AND comment_approved = %d";
$comment_count = $wpdb->get_var( $wpdb->prepare( $query, $wpdb->esc_like( $value ) . '%', $type, 1 ) );
$pending_count = $wpdb->get_var( $wpdb->prepare( $query, $wpdb->esc_like( $value ) . '%', $type, 0 ) );
} else {
$comment_count = $pending_count = 0;
}
// Return value is array of comment count and pending count.
$return = array( (int) $comment_count, (int) $pending_count );
// Memoize the counts being returned.
self::$memoized[ $memoize_key ] = $return;
return $return;
}
/**
* Returns the URL for the admin listing of comments for the given email
* address.
*
* @since 1.4
*
* @param string $email Email address.
*
* @return string
*/
public static function get_comments_url( $email ) {
return add_query_arg( 's', urlencode( $email ), admin_url( 'edit-comments.php' ) );
}
/**
* Returns the comment author link for the specified author along with the
* markup indicating the number of times the comment author has commented
* on the site. The comment count links to a listing of all of that
* person's comments.
*
* Commenters are identified by the email address they provided when
* commenting.
*
* @param string $author_name Name of the comment author.
*
* @return string Comment author link plus linked comment count markup.
*/
public static function comment_author( $author_name ) {
if ( ! is_admin() ) {
return $author_name;
}
global $comment;
$type = get_comment_type();
if ( 'comment' == $type ) {
$author_email = $comment->comment_author_email;
$author_name = $comment->comment_author;
if ( ! $author_email ) {
$field = 'comment_author';
$value = $author_name;
} else {
$field = 'comment_author_email';
$value = $author_email;
}
list( $comment_count, $pending_count ) = self::get_comments_count( $field, $value, $type );
$msg = sprintf( _n( '%d comment', '%d comments', $comment_count, 'admin-commenters-comments-count' ), $comment_count );
} elseif ( 'pingback' == $type || 'trackback' == $type ) {
$author_url = $comment->comment_author_url;
// Want to get the root domain and not use the exact pingback/trackback source link
$parsed_url = parse_url( $author_url );
$author_url = $parsed_url['scheme'] . '://' . $parsed_url['host'];
list( $comment_count, $pending_count ) = self::get_comments_count( 'comment_author_url', $author_url, $type );
$author_email = $author_url;
/* Translators: sorry, but I'm not supplying explicit translation strings for all possible other comment types.
You can at least expect '%d trackback', '%d trackbacks', '%d pingback' and '%d pingbacks' */
$msg = sprintf( _n( '%d %s', '%d %ss', $comment_count, 'admin-commenters-comments-count' ), $comment_count, $type );
} else {
return $author_name;
}
// If appearing on the dashboard, then don't need to break out of
// pre-existing tags.
$screen = get_current_screen();
$is_dashboard = $screen && 'dashboard' == $screen->id;
$html = $is_dashboard ? '' : '';
$html .= self::get_comments_bubble( $author_email, $comment_count, $pending_count, $msg );
$html .= $is_dashboard ? '' : '';
$html .= $author_name;
return $html;
}
/**
* Returns the markup for the comments bubble for the given email address with
* with the provided counts.
*
* @since 1.8
*
* @param string $author_email Comment author email address.
* @param int $comment_count The number of comments for the email
* address.
* @param int $pending_count The number of pending comments for the
* email address.
* @param string $msg. String to use as title attribute for
* comment bubble.
* @param bool. $no_comments_bubble Should the comment bubble be shown if the
* email address has no comments?
*
* @return string
*/
public static function get_comments_bubble( $author_email, $comment_count, $pending_count, $msg = '', $no_comments_bubble = true ) {
$html = '';
$url = ( $comment_count + $pending_count ) > 0 ? self::get_comments_url( $author_email ) : '#';
$comment_str = sprintf(
_n( '%s comment', '%s comments', $comment_count, 'admin-commenters-comments-count' ),
number_format_i18n( $comment_count )
);
$pending_class = $pending_count ? '' : ' author-com-count-no-pending';
if ( ! $no_comments_bubble && ! $comment_count && ! $pending_count ) {
return sprintf( '—%s',
__( 'No comments', 'admin-commenters-comments-count' )
);
}
$html .= '\n";
$comments_number = number_format_i18n( $comment_count );
if ( $comment_count ) {
$html .= sprintf(
'
%s
',
esc_url( add_query_arg( 'comment_status', 'approved', $url ) ),
esc_attr( $msg ),
$comments_number,
$comment_str
);
} else {
$html .= sprintf(
'',
esc_attr( $msg ),
$comments_number,
$pending_count ? __( 'No approved comments', 'admin-commenters-comments-count' ) : __( 'No comments', 'admin-commenters-comments-count' )
);
}
$pending_comments_number = number_format_i18n( $pending_count );
$pending_phrase = sprintf( _n( '%s pending comment', '%s pending comments', $pending_count, 'admin-commenters-comments-count' ), $pending_comments_number );
if ( $pending_count ) {
$html .= sprintf(
'%s',
esc_url( add_query_arg( 'comment_status', 'moderated', $url ) ),
$pending_comments_number,
$pending_phrase
);
} else {
$html .= sprintf(
'%s',
$pending_comments_number,
$comment_count ? __( 'No pending comments', 'admin-commenters-comments-count' ) : __( 'No comments', 'admin-commenters-comments-count' )
);
}
$html .= "";
return $html;
}
/**
* Filter for WP's get_comment_author_link() that returns the value of
* comment_author() when in the admin.
*
* @param string $author_link Author link
*
* @return string Modified author link
*/
public static function get_comment_author_link( $author_link ) {
if ( ! is_admin() ) {
return $author_link;
}
return self::comment_author( get_comment_author() );
}
} // end c2c_AdminCommentersCommentsCount
c2c_AdminCommentersCommentsCount::init();
endif; // end if !class_exists()