defaults = array( 'title' => __( 'Popular Posts', 'advance-widget-pack' ), 'post_count' => '5', 'sort_radio' => 'views', 'featured-image' => '0', 'post-date' => '0', 'post-author' => '0', 'post-category' => '0', 'comments' => '0', 'views' => '0', 'post-excerpt' => '0', ); $widget_ops = array( 'classname' => 'awp_popular_post awp_widget', 'description' => __( 'Widget to display popular posts', 'advance-widget-pack' ), ); $control_ops = array( 'id_base' => 'awp_popular_post', 'width' => 200, 'height' => 250, ); parent::__construct( 'awp_popular_post', __( 'AWP Popular Posts', 'advance-widget-pack' ), $widget_ops, $control_ops ); } public function widget( $awp_args, $instance ) { $instance = wp_parse_args( (array) $instance, $this->defaults ); $title = apply_filters( 'widget_title', $instance['title'] ); $post_count = absint( $instance['post_count'] ); $sort_by = 'comments' === $instance['sort_radio'] ? 'comments' : 'views'; echo $awp_args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- sidebar-provided wrapper markup, trusted per WP core convention. if ( ! empty( $title ) ) { echo $awp_args['before_title'] . esc_html( $title ) . $awp_args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- title text is esc_html()'d; before/after_title are sidebar-provided wrapper markup. } $post_ids = self::get_post_ids( $post_count, $sort_by ); if ( $post_ids ) { awp_is_rendering( true ); echo ''; awp_is_rendering( false ); } echo $awp_args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- sidebar-provided wrapper markup, trusted per WP core convention. } /** * Fetches the popular-post ID list for the given count/sort, using the * shared transient cache. Used by both the widget and the Popular Posts block. * * @param int $post_count Number of posts to fetch. * @param string $sort_by 'views' or 'comments'. * @return int[] Post IDs. */ public static function get_post_ids( $post_count, $sort_by = 'views' ) { $post_count = absint( $post_count ); $sort_by = 'comments' === $sort_by ? 'comments' : 'views'; $cache_key = 'awp_popular_posts_' . $sort_by . '_' . awp_cache_generation() . '_' . $post_count; $post_ids = get_transient( $cache_key ); if ( false === $post_ids ) { if ( 'comments' === $sort_by ) { $args = array( 'posts_per_page' => $post_count, 'post_type' => 'post', 'post_status' => 'publish', 'orderby' => 'comment_count', 'order' => 'DESC', 'no_found_rows' => true, 'update_post_term_cache' => false, ); } else { $args = array( 'posts_per_page' => $post_count, 'post_type' => 'post', 'post_status' => 'publish', 'meta_key' => 'wp_views', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- cached via transient below to absorb the cost of sorting by postmeta. 'orderby' => 'meta_value_num', 'order' => 'DESC', 'no_found_rows' => true, 'update_post_term_cache' => false, ); } $query = new WP_Query( $args ); $post_ids = wp_list_pluck( $query->posts, 'ID' ); // Cache longer than the other widgets: this query is the most // expensive one in the plugin (unindexed postmeta sort). set_transient( $cache_key, $post_ids, 15 * MINUTE_IN_SECONDS ); } return $post_ids; } /** * Renders a single post row inside a