Created
October 14, 2015 22:52
-
-
Save hasangilak/828f17c7dc2ecfd6302c to your computer and use it in GitHub Desktop.
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 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' => '<ul class="wpp-list">', | |
'wpp-end' => '</ul>', | |
'post-html' => '<li>{thumb} {title} {stats}</li>', | |
'post-start' => '<li>', | |
'post-end' => '</li>', | |
'title-start' => '<h2>', | |
'title-end' => '</h2>' | |
) | |
); | |
/** | |
* 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