Skip to content

Instantly share code, notes, and snippets.

@hasangilak
Created October 14, 2015 22:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hasangilak/828f17c7dc2ecfd6302c to your computer and use it in GitHub Desktop.
Save hasangilak/828f17c7dc2ecfd6302c to your computer and use it in GitHub Desktop.
<?php namespace PopularPost;
class WordpressPopularPostsExtracted
{
/**
* Instance of this class.
*
* @since 3.0.0
* @var object
*/
protected static $instance = NULL;
/**
* Slug of the plugin screen.
*
* @since 3.0.0
* @var string
*/
protected $plugin_screen_hook_suffix = NULL;
/**
* Plugin defaults.
*
* @since 2.3.3
* @var array
*/
protected $defaults = array(
'title' => '',
'limit' => 10,
'range' => 'daily',
'freshness' => false,
'order_by' => 'views',
'post_type' => 'post,page',
'pid' => '',
'author' => '',
'cat' => '',
'shorten_title' => array(
'active' => false,
'length' => 25,
'words' => false
),
'post-excerpt' => array(
'active' => false,
'length' => 55,
'keep_format' => false,
'words' => false
),
'thumbnail' => array(
'active' => false,
'build' => 'manual',
'width' => 15,
'height' => 15,
'crop' => true
),
'rating' => false,
'stats_tag' => array(
'comment_count' => false,
'views' => true,
'author' => false,
'date' => array(
'active' => false,
'format' => 'F j, Y'
),
'category' => false
),
'markup' => array(
'custom_html' => false,
'wpp-start' => '&lt;ul class="wpp-list"&gt;',
'wpp-end' => '&lt;/ul&gt;',
'post-html' => '&lt;li&gt;{thumb} {title} {stats}&lt;/li&gt;',
'post-start' => '&lt;li&gt;',
'post-end' => '&lt;/li&gt;',
'title-start' => '&lt;h2&gt;',
'title-end' => '&lt;/h2&gt;'
)
);
/**
* Admin page user settings defaults.
*
* @since 2.3.3
* @var array
*/
protected $default_user_settings = array(
'stats' => array(
'order_by' => 'views',
'limit' => 10,
'post_type' => 'post,page',
'freshness' => false
),
'tools' => array(
'ajax' => false,
'css' => true,
'link' => array(
'target' => '_self'
),
'thumbnail' => array(
'source' => 'featured',
'field' => '',
'resize' => false,
'default' => '',
'responsive' => false
),
'log' => array(
'level' => 1,
'limit' => 0,
'expires_after' => 180
),
'cache' => array(
'active' => false,
'interval' => array(
'time' => 'hour',
'value' => 1
)
),
'sampling' => array(
'active' => false,
'rate' => 100
)
)
);
/**
* Merges two associative arrays recursively
*
* @since 2.3.4
* @link http://www.php.net/manual/en/function.array-merge-recursive.php#92195
* @param array array1
* @param array array2
* @return array
*/
private function __merge_array_r(array &$array1, array &$array2)
{
$merged = $array1;
foreach ($array2 as $key => &$value) {
if (is_array($value) && isset ($merged[$key]) && is_array($merged[$key])) {
$merged[$key] = $this->__merge_array_r($merged[$key], $value);
} else {
$merged[$key] = $value;
}
}
return $merged;
} // end __merge_array_r
/**
* Returns mysql datetime
*
* @since 2.1.6
* @return string
*/
private function __now()
{
return current_time('mysql');
} // end __now
/**
* Queries the database and returns the posts (if any met the criteria set by the user).
*
* @since 1.4.0
* @global object $wpdb
* @param array Widget instance
* @return null|array Array of posts, or null if nothing was found
*/
protected function _query_posts($instance)
{
global $wpdb;
// parse instance values
$instance = $this->__merge_array_r(
$this->defaults,
$instance
);
$prefix = $wpdb->prefix . "popularposts";
$fields = "p.ID AS 'id', p.post_title AS 'title', p.post_date AS 'date', p.post_author AS 'uid'";
$from = "";
$where = "WHERE 1 = 1";
$orderby = "";
$groupby = "";
$limit = "LIMIT {$instance['limit']}";
$post_types = "";
$pids = "";
$cats = "";
$authors = "";
$content = "";
$now = $this->__now();
// post filters
// * freshness - get posts published within the selected time range only
if ($instance['freshness']) {
switch ($instance['range']) {
case "daily":
$where .= " AND p.post_date > DATE_SUB('{$now}', INTERVAL 1 DAY) ";
break;
case "weekly":
$where .= " AND p.post_date > DATE_SUB('{$now}', INTERVAL 1 WEEK) ";
break;
case "monthly":
$where .= " AND p.post_date > DATE_SUB('{$now}', INTERVAL 1 MONTH) ";
break;
default:
$where .= "";
break;
}
}
// * post types - based on code seen at https://github.com/williamsba/WordPress-Popular-Posts-with-Custom-Post-Type-Support
$types = explode(",", $instance['post_type']);
$sql_post_types = "";
$join_cats = true;
// if we're getting just pages, why join the categories table?
if ('page' == strtolower($instance['post_type'])) {
$join_cats = false;
$where .= " AND p.post_type = '{$instance['post_type']}'";
} // we're listing other custom type(s)
else {
if (count($types) > 1) {
foreach ($types as $post_type) {
$post_type = trim($post_type); // required in case user places whitespace between commas
$sql_post_types .= "'{$post_type}',";
}
$sql_post_types = rtrim($sql_post_types, ",");
$where .= " AND p.post_type IN({$sql_post_types})";
} else {
$where .= " AND p.post_type = '{$instance['post_type']}'";
}
}
// * posts exclusion
if (!empty($instance['pid'])) {
$ath = explode(",", $instance['pid']);
$where .= (count($ath) > 1)
? " AND p.ID NOT IN({$instance['pid']})"
: " AND p.ID <> '{$instance['pid']}'";
}
// * categories
if (!empty($instance['cat']) && $join_cats) {
$cat_ids = explode(",", $instance['cat']);
$in = array();
$out = array();
for ($i = 0; $i < count($cat_ids); $i++) {
if ($cat_ids[$i] >= 0)
$in[] = $cat_ids[$i];
else
$out[] = $cat_ids[$i];
}
$in_cats = implode(",", $in);
$out_cats = implode(",", $out);
$out_cats = preg_replace('|[^0-9,]|', '', $out_cats);
if ($in_cats != "" && $out_cats == "") { // get posts from from given cats only
$where .= " AND p.ID IN (
SELECT object_id
FROM {$wpdb->term_relationships} AS r
JOIN {$wpdb->term_taxonomy} AS x ON x.term_taxonomy_id = r.term_taxonomy_id
WHERE x.taxonomy = 'category' AND x.term_id IN({$in_cats})
)";
} else if ($in_cats == "" && $out_cats != "") { // exclude posts from given cats only
$where .= " AND p.ID NOT IN (
SELECT object_id
FROM {$wpdb->term_relationships} AS r
JOIN {$wpdb->term_taxonomy} AS x ON x.term_taxonomy_id = r.term_taxonomy_id
WHERE x.taxonomy = 'category' AND x.term_id IN({$out_cats})
)";
} else { // mixed
$where .= " AND p.ID IN (
SELECT object_id
FROM {$wpdb->term_relationships} AS r
JOIN {$wpdb->term_taxonomy} AS x ON x.term_taxonomy_id = r.term_taxonomy_id
WHERE x.taxonomy = 'category' AND x.term_id IN({$in_cats}) AND x.term_id NOT IN({$out_cats})
) ";
}
}
// * authors
if (!empty($instance['author'])) {
$ath = explode(",", $instance['author']);
$where .= (count($ath) > 1)
? " AND p.post_author IN({$instance['author']})"
: " AND p.post_author = '{$instance['author']}'";
}
// All-time range
if ("all" == $instance['range']) {
$fields .= ", p.comment_count AS 'comment_count'";
// order by comments
if ("comments" == $instance['order_by']) {
$from = "{$wpdb->posts} p";
$where .= " AND p.comment_count > 0 ";
$orderby = " ORDER BY p.comment_count DESC";
// get views, too
if ($instance['stats_tag']['views']) {
$fields .= ", IFNULL(v.pageviews, 0) AS 'pageviews'";
$from .= " LEFT JOIN {$prefix}data v ON p.ID = v.postid";
}
} // order by (avg) views
else {
$from = "{$prefix}data v LEFT JOIN {$wpdb->posts} p ON v.postid = p.ID";
// order by views
if ("views" == $instance['order_by']) {
$fields .= ", v.pageviews AS 'pageviews'";
$orderby = "ORDER BY pageviews DESC";
} // order by avg views
elseif ("avg" == $instance['order_by']) {
$fields .= ", ( v.pageviews/(IF ( DATEDIFF('{$now}', MIN(v.day)) > 0, DATEDIFF('{$now}', MIN(v.day)), 1) ) ) AS 'avg_views'";
$groupby = "GROUP BY v.postid";
$orderby = "ORDER BY avg_views DESC";
}
}
} else { // CUSTOM RANGE
$interval = "";
switch ($instance['range']) {
case "daily":
$interval = "1 DAY";
break;
case "weekly":
$interval = "1 WEEK";
break;
case "monthly":
$interval = "1 MONTH";
break;
default:
$interval = "1 DAY";
break;
}
// order by comments
if ("comments" == $instance['order_by']) {
$fields .= ", COUNT(c.comment_post_ID) AS 'comment_count'";
$from = "{$wpdb->comments} c LEFT JOIN {$wpdb->posts} p ON c.comment_post_ID = p.ID";
$where .= " AND c.comment_date_gmt > DATE_SUB('{$now}', INTERVAL {$interval}) AND c.comment_approved = 1 ";
$groupby = "GROUP BY c.comment_post_ID";
$orderby = "ORDER BY comment_count DESC";
if ($instance['stats_tag']['views']) { // get views, too
$fields .= ", IFNULL(v.pageviews, 0) AS 'pageviews'";
$from .= " LEFT JOIN (SELECT postid, SUM(pageviews) AS pageviews FROM {$prefix}summary WHERE last_viewed > DATE_SUB('{$now}', INTERVAL {$interval}) GROUP BY postid) v ON p.ID = v.postid";
}
} // ordered by views / avg
else {
$from = "{$prefix}summary v LEFT JOIN {$wpdb->posts} p ON v.postid = p.ID";
$where .= " AND v.last_viewed > DATE_SUB('{$now}', INTERVAL {$interval}) ";
$groupby = "GROUP BY v.postid";
// ordered by views
if ("views" == $instance['order_by']) {
$fields .= ", SUM(v.pageviews) AS 'pageviews'";
$orderby = "ORDER BY pageviews DESC";
} // ordered by avg views
elseif ("avg" == $instance['order_by']) {
$fields .= ", ( SUM(v.pageviews)/(IF ( DATEDIFF('{$now}', DATE_SUB('{$now}', INTERVAL {$interval})) > 0, DATEDIFF('{$now}', DATE_SUB('{$now}', INTERVAL {$interval})), 1) ) ) AS 'avg_views' ";
$orderby = "ORDER BY avg_views DESC";
}
// get comments, too
if ($instance['stats_tag']['comment_count']) {
$fields .= ", IFNULL(c.comment_count, 0) AS 'comment_count'";
$from .= " LEFT JOIN (SELECT comment_post_ID, COUNT(comment_post_ID) AS 'comment_count' FROM {$wpdb->comments} WHERE comment_date_gmt > DATE_SUB('{$now}', INTERVAL {$interval}) AND comment_approved = 1 GROUP BY comment_post_ID) c ON p.ID = c.comment_post_ID";
}
}
}
// List only published, non password-protected posts
$where .= " AND p.post_password = '' AND p.post_status = 'publish'";
// Build query
$query = "SELECT {$fields} FROM {$from} {$where} {$groupby} {$orderby} {$limit};";
$result = $wpdb->get_results($query);
return apply_filters('wpp_query_posts', $result, $instance);
} // end query_posts
/**
* Returns the formatted list of posts.
*
* @since 3.0.0
* @param array instance The current instance of the widget / shortcode parameters
* @return string HTML list of popular posts
*/
private function __get_popular_posts($instance)
{
// Parse instance values
$instance = $this->__merge_array_r(
$this->defaults,
$instance
);
$mostpopular = $this->_query_posts($instance);
return $mostpopular;
}
/**
* Template tag - gets popular posts.
*
* @since 2.0.3
* @param mixed args
* @return string
*/
public function get_most_popular($args = [])
{
return $this->__get_popular_posts($args);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment