Last active
March 28, 2022 18:54
-
-
Save tw2113/d91939af0da36fc88ecf to your computer and use it in GitHub Desktop.
JetPack Popular Posts class.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Plugin Name: WDS JetPack Popular Posts | |
Plugin URI: http://www.webdevstudios.com | |
Description: Query for popular posts by views using JetPack by Automattic. | |
Version: 1.0 | |
Author: WebDevStudios | |
Author URI: http://www.webdevstudios.com | |
License: GPLv2 | |
Text Domain: wds-popular-posts | |
*/ | |
class WDS_JetPack_Popular_Posts { | |
public $post_count = 5; | |
public $days = 2; | |
public $transient = ''; | |
public function __construct( $args ) { | |
if ( isset( $args['count'] ) ) { | |
$this->post_count = $args['count']; | |
} | |
if ( isset( $args['days'] ) ) { | |
$this->days = $args['days']; | |
} | |
if ( empty( $args['transient_affix'] ) ) { | |
$this->transient = '_popular'; | |
$queried = get_queried_object_id(); | |
if ( !empty( $queried ) ) { | |
$this->transient .= '_' . $queried; | |
} | |
} else { | |
$this->transient = $args['transient_affix']; | |
} | |
} | |
/** | |
* Kick everything off. This should be the only method needing called. | |
* | |
* @since 1.0.0 | |
* | |
* @return array Array of popular posts based on specified parameters. | |
*/ | |
public function get_posts() { | |
if ( !function_exists( 'stats_get_csv' ) ) { | |
return '<p>' . __( 'Please install and activate Jetpack by Automattic.', 'wds-popular-posts' ) . '</p>'; | |
} | |
$rawposts = $this->maybe_query_jetpack_api(); | |
$filtered = $this->filter_posts( $rawposts ); | |
return $filtered; | |
} | |
/** | |
* Get all of the posts we will deal with and filter down to the top X amount. | |
* | |
* @since 1.0.0 | |
* | |
* @param array $posts Array of post data from JetPack | |
* | |
* @return array Array of our popular posts. | |
*/ | |
private function filter_posts( $posts ) { | |
$count = $this->post_count; | |
$popular = array(); | |
if ( !is_array( $posts ) ) { | |
return $popular; | |
} | |
$post_ids = array_filter( wp_list_pluck( $posts, 'post_id' ) ); | |
if ( !$post_ids || empty( $post_ids ) ) { | |
return $popular; | |
} | |
//If we have posts of any terms, whether page or specific genre | |
$popular = $this->get_popular_posts( $post_ids, $count ); | |
return $popular; | |
} | |
/** | |
* Check if we have an existing transient value to use and query JetPack if we do not. | |
* | |
* @since 1.0.0 | |
* | |
* @return array|string array if we have data, error message if querying failed. | |
*/ | |
private function maybe_query_jetpack_api() { | |
if ( false === ( $popular_posts = get_transient( 'wds_jppp_' . $this->transient ) ) ) { | |
$popular_posts = $this->query_jetpack_api(); | |
//conditionally set | |
if ( !empty( $popular_posts ) ) { | |
set_transient( 'wds_jppp_' . $this->transient, $popular_posts, 60 * 30 ); | |
} else { | |
return __( 'There was an error retrieving popular posts. Please try again.', 'wds-popular-posts' ); | |
} | |
} | |
return $popular_posts; | |
} | |
/** | |
* Query JetPack API using stats_get_csv | |
* | |
* @since 1.0.0 | |
* | |
* @return array|bool array if we have posts to work with, false if no results. | |
*/ | |
private function query_jetpack_api() { | |
$days = $this->days; | |
$post_view_posts = stats_get_csv( 'postviews', array( 'days' => $days, 'limit' => 300 ) ); | |
return $post_view_posts; | |
} | |
/** | |
* Construct an array of posts limited to the specified count total. | |
* | |
* @since 1.0.0 | |
* | |
* @param array $post_ids All of the returned IDs | |
* @param integer $count How many posts we want to return | |
* | |
* @return array Array of top posts. | |
*/ | |
private function get_popular_posts( $post_ids = array(), $count = 5 ) { | |
$counter = 0; $posts = array(); | |
foreach ( (array) $post_ids as $post_id ) { | |
$post = get_post( $post_id ); | |
if ( !$post || 'post' != $post->post_type ) { | |
continue; | |
} | |
// hide private and password protected posts | |
if ( 'publish' != $post->post_status || !empty( $post->post_password ) || empty( $post->ID ) ) { | |
continue; | |
} | |
$title = $this->set_title( $post ); | |
$permalink = get_permalink( $post->ID ); | |
$posts[] = compact( 'title', 'permalink', 'post_id' ); | |
if ( $counter == $count ) | |
break; // only need to load and show x number of likes | |
$counter++; | |
} | |
return $posts; | |
} | |
/** | |
* Set the title to use with end result. Grabs first part of post content if no title set. | |
* | |
* @since 1.0.0 | |
* | |
* @param object $post Post object. | |
* | |
* @return string Title text to use | |
*/ | |
private function set_title( $post ) { | |
// Both get HTML stripped etc on display | |
if ( empty( $post->post_title ) ) { | |
$title_source = $post->post_content; | |
$title = wp_html_excerpt( $title_source, 50 ); | |
$title .= '…'; | |
} else { | |
$title = $post->post_title; | |
} | |
return $title; | |
} | |
} |
Pure Genius!
A little code we added to line 151 in order to skip certain categories.
$terms = wp_list_pluck(wp_get_object_terms($post->ID, 'category'), 'slug');
if (array_intersect(['obituaries', 'lifestyle', 'police-reports'], $terms)) continue;
Hope this can help someone else.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I don't understand how this isn't more popular, I was planning to do exactly this today.