Most Discussed Posts Widget
Adds a "Most Discussed Posts" widget that lists the posts with the most comments, all-time or from the last few weeks, with optional comment counts.
Opens WPIDE on
Code
if ( ! class_exists( 'WPIDE_Most_Discussed_Widget' ) ) {
class WPIDE_Most_Discussed_Widget extends WP_Widget {
public function __construct() {
parent::__construct( 'wpide_most_discussed', 'Most Discussed Posts', array(
'description' => 'Posts with the most comments, optionally from recent weeks only.',
'customize_selective_refresh' => true,
) );
}
public function widget( $args, $instance ) {
$number = ! empty( $instance['number'] ) ? absint( $instance['number'] ) : 5;
$days = isset( $instance['days'] ) ? absint( $instance['days'] ) : 0;
$key = 'wpide_discussed_' . $number . '_' . $days;
$ids = get_transient( $key );
if ( ! is_array( $ids ) ) {
$query = array(
'post_type' => 'post',
'posts_per_page' => $number,
'orderby' => array( 'comment_count' => 'DESC', 'date' => 'DESC' ),
'has_password' => false,
'ignore_sticky_posts' => true,
'no_found_rows' => true,
'fields' => 'ids',
);
if ( $days ) {
$query['date_query'] = array( array( 'after' => $days . ' days ago' ) );
}
$ids = get_posts( $query );
set_transient( $key, $ids, HOUR_IN_SECONDS );
}
if ( ! $ids ) {
return;
}
_prime_post_caches( $ids, false, false );
$title = isset( $instance['title'] ) && '' !== $instance['title'] ? $instance['title'] : 'Most Discussed';
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput -- theme markup.
if ( '' !== (string) $title ) {
echo $args['before_title'] . esc_html( $title ) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput
}
echo '<ol class="wpide-most-discussed">';
foreach ( $ids as $id ) {
$count = (int) get_comments_number( $id );
echo '<li><a href="' . esc_url( get_permalink( $id ) ) . '">' . esc_html( get_the_title( $id ) ) . '</a>';
if ( ! empty( $instance['show_count'] ) ) {
echo ' <small>(' . esc_html( sprintf( _n( '%s comment', '%s comments', $count ), number_format_i18n( $count ) ) ) . ')</small>';
}
echo '</li>';
}
echo '</ol>';
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput
}
public function form( $instance ) {
$title = isset( $instance['title'] ) ? $instance['title'] : '';
$number = ! empty( $instance['number'] ) ? absint( $instance['number'] ) : 5;
$days = isset( $instance['days'] ) ? absint( $instance['days'] ) : 0;
echo '<p><label for="' . esc_attr( $this->get_field_id( 'title' ) ) . '">Title:</label><input class="widefat" type="text" id="' . esc_attr( $this->get_field_id( 'title' ) ) . '" name="' . esc_attr( $this->get_field_name( 'title' ) ) . '" value="' . esc_attr( $title ) . '" /></p>';
echo '<p><label for="' . esc_attr( $this->get_field_id( 'number' ) ) . '">Number of posts:</label> <input class="tiny-text" type="number" min="1" max="20" id="' . esc_attr( $this->get_field_id( 'number' ) ) . '" name="' . esc_attr( $this->get_field_name( 'number' ) ) . '" value="' . esc_attr( $number ) . '" /></p>';
echo '<p><label for="' . esc_attr( $this->get_field_id( 'days' ) ) . '">Only posts from the last (days, 0 = all time):</label> <input class="tiny-text" type="number" min="0" max="3650" id="' . esc_attr( $this->get_field_id( 'days' ) ) . '" name="' . esc_attr( $this->get_field_name( 'days' ) ) . '" value="' . esc_attr( $days ) . '" /></p>';
echo '<p><input type="checkbox" class="checkbox" id="' . esc_attr( $this->get_field_id( 'show_count' ) ) . '" name="' . esc_attr( $this->get_field_name( 'show_count' ) ) . '"' . checked( ! empty( $instance['show_count'] ), true, false ) . ' /> <label for="' . esc_attr( $this->get_field_id( 'show_count' ) ) . '">Show comment counts</label></p>';
return '';
}
public function update( $new_instance, $old_instance ) {
return array(
'title' => isset( $new_instance['title'] ) ? sanitize_text_field( $new_instance['title'] ) : '',
'number' => isset( $new_instance['number'] ) ? max( 1, min( 20, absint( $new_instance['number'] ) ) ) : 5,
'days' => isset( $new_instance['days'] ) ? min( 3650, absint( $new_instance['days'] ) ) : 0,
'show_count' => ! empty( $new_instance['show_count'] ),
);
}
}
}
add_action( 'widgets_init', function () {
register_widget( 'WPIDE_Most_Discussed_Widget' );
} );
Notes
Add it under Appearance > Widgets (as a Legacy Widget in the block editor); results are cached for an hour.
How to add this snippet
- Install WPIDE on your WordPress site (it is free) and open Code Snippets.
- Use snippet above adds it from the library in one click. Or copy the code into a new snippet with the same code type.
- It is added inactive: review the code and settings, then switch it on.