DarkFlower
Ist gelegentlich hier
- Registriert
- 27. November 2013
- Beiträge
- 42
- Reaktionspunkte
- 27
- Punkte
- 18
Als ich heute Morgen aufgestanden bin und meine Seite besucht habe, war ich ohne ein Schluck Kaffee hellwach, denn mein co Admin hat alle Ratings zurückgesetzt. :emoticon-0124-worri
Nun bin ich nicht ungedingt der PHP/MySQL Fachmann und ein Blick in die DB hat mich nun nicht wirklich weiter geholfen. Denn die direkte Spalte für die Ratings haben ich erstmal nicht gefunden. Klar, sind ja auch alle weg.
Nun hoffe ich, dass hier vielleicht einer von euch das Wissen hat, welche Tabelle & Spalte das ist, und mir ein DB Updatebefehl schreiben kann, so das ich zwar erstmal die Ratings Fake aber dann wenigstens wieder welche da sind.
Hier mal die PHP Datei, wo ich GLAUBE ab Zeile 979 etwas gefunden zu haben.
Nun bin ich nicht ungedingt der PHP/MySQL Fachmann und ein Blick in die DB hat mich nun nicht wirklich weiter geholfen. Denn die direkte Spalte für die Ratings haben ich erstmal nicht gefunden. Klar, sind ja auch alle weg.
Nun hoffe ich, dass hier vielleicht einer von euch das Wissen hat, welche Tabelle & Spalte das ist, und mir ein DB Updatebefehl schreiben kann, so das ich zwar erstmal die Ratings Fake aber dann wenigstens wieder welche da sind.
Hier mal die PHP Datei, wo ich GLAUBE ab Zeile 979 etwas gefunden zu haben.
Code:
<?php
/*
Plugin Name: own Post Ratings
Version: 1.0.1
Plugin URI: http://www.psd2wp.net/
Description: Simple rating / vote count via custom post meta.
Author: SG
Author URI: psd2wp.net@gmail.com
Text Domain: post-ratings
Domain Path: /lang
*/
/*
* Public methods you can call from outside:
*
* PostRatings()->getControl() - gets the rate links
* PostRatings()->currentUserCanRate($post_id) - checks if the current user can rate that post
* PostRatings()->getTopRated($options) - gets a list of top rated posts...
*
*
*
*/
/*
* PostRatings Class
*
* @since 1.0
*/
class PostRatings{
const
VERSION = '2.4', // plugin version
PROJECT_URI = 'http://digitalnature.eu/forum/plugins/post-ratings/', // url to support forums
ID = 'post-ratings', // internally used for text domain, theme option group name etc.
MIN_VOTES = 1, // minimum vote count (MV)
BR1 = '(v / (v + MV)) * r + (MV / (v + MV)) * R', // bayesian rating formula: the IMDB version
BR2 = '((AV * R) + (v * r)) / (AV + v)'; // bayesian rating formula: thebroth.com version
protected static $instance;
protected
$options = null,
// stores rated post IDs for the current session;
// we're using this for to get the rated state in our ajax calls
$rated_posts = array(),
// default option values
$defaults = array(
'version' => self::VERSION,
'anonymous_vote' => true,
'max_rating' => 5,
'bayesian_formula' => self::BR1,
'user_formula' => '',
'custom_filter' => '',
'before_post' => false,
'after_post' => true,
'post_types' => array('post'),
'visibility' => array('home', 'singular'), // same as WP conditional "tags", but with "is_" omitted
// internal, global stats
'avg_rating' => 0,
'num_votes' => 0,
'num_rated_posts' => 0,
);
/*
* This will instantiate the class if needed, and return the only class instance if not...
*
* @since 1.0
*/
public static function app(){
// first run?
if(!(self::$instance instanceof self)){
self::$instance = new self();
// localize
load_plugin_textdomain(self::ID, false, dirname(plugin_basename(__FILE__)).'/lang');
if(is_admin()){
add_action('admin_menu', array(self::$instance, 'CreateMenu'));
add_action('admin_init', array(self::$instance, 'RegisterSettings'));
}else{
add_action('wp', array(self::$instance, 'Run'));
}
// register shortcode
add_shortcode('rate', array(self::$instance, 'Shortcode'));
// register widget
add_action('widgets_init', array(self::$instance, 'Widget'));
// empty our cache when a new post is written or when a post gets deleted
add_action('save_post', array(self::$instance, 'clearQueryCache'));
add_action('deleted_post', array(self::$instance, 'clearQueryCache'));
// run on plugin uninstall; not sure when does this run?!
register_uninstall_hook(__FILE__, array(__CLASS__, 'Uninstall'));
}
return self::$instance;
}
/*
* A single instance only
*
* @since 1.0
*/
final protected function __construct(){
// initialize early, to avoid endless loop within update_option() + settings validation callback.
// stupid settings API...
$this->getOptions();
}
/*
* No cloning
*
* @since 1.0
*/
final protected function __clone(){}
/*
* Returns one or all plugin options.
*
* @since 1.0
* @param string $key Option to get; if not given all options are returned
* @return mixed Option(s)
*/
public function getOptions($key = false){
// first call, initialize the options
if(!isset($this->options)){
$options = get_option(self::ID);
// options exist
if($options !== false){
if(!isset($options['version']))
$options['version'] = '1.0';
$new_version = version_compare($options['version'], self::VERSION, '!=');
$desync = array_diff_key($this->defaults, $options) !== array_diff_key($options, $this->defaults);
// update options if version changed, or we have missing/extra (out of sync) option entries
if($new_version || $desync){
$new_options = array();
// check for new options and set defaults if necessary
foreach($this->defaults as $option => $value)
$new_options[$option] = isset($options[$option]) ? $options[$option] : $value;
// update version info
$new_options['version'] = self::VERSION;
update_option(self::ID, $new_options);
$this->options = $new_options;
// no update was required
}else{
$this->options = $options;
}
// new install (plugin was just activated)
}else{
update_option(self::ID, $this->defaults);
$this->options = $this->defaults;
}
}
return $key ? $this->options[$key] : $this->options;
}
/*
* Loads a template file from the theme or child theme directory.
*
* @since 1.0
* @param string $_name Template name, without the '.php' suffix
* @param array $_vars Variables to expose in the template. Note that unlike WP, we're not exposing all the global variable mess inside it...
*/
final public function loadTemplate($_name, $_vars = array()){
// you cannot let locate_template to load your template
// because WP devs made sure you can't pass
// variables to your template :(
$_located = locate_template("{$_name}.php", false, false);
// use the default one if the (child) theme doesn't have it
if(!$_located)
$_located = dirname(__FILE__).'/templates/'.$_name.'.php';
unset($_name);
// create variables
if($_vars)
extract($_vars);
ob_start();
// load it
require $_located;
return ob_get_clean();
}
/*
* Hook our plugin options menu / page
*
* @since 1.0
*/
public function CreateMenu(){
add_options_page(__('Post Ratings', self::ID), __('Post Ratings', self::ID), 'manage_options', self::ID, array($this, 'SettingsPage'));
}
/*
* Register our setting with the new useless Settings API bloat...
*
* @since 1.0
*/
public function RegisterSettings(){
register_setting(self::ID, self::ID, array($this, 'ValidateSettings'));
add_filter('plugin_action_links', array($this, 'PluginSettingsLink'), 10, 2);
}
/*
* Settings link in the plugin list
*
* @since 1.0
* @param string $file
* @param array $links
* @return array
*/
public function PluginSettingsLink($links, $file){
if(plugin_basename(__FILE__) === $file){
$settings_link = '<a href="'.add_query_arg(array('page' => self::ID), admin_url('options-general.php')).'">'.__('Settings', self::ID).'</a>';
array_unshift($links, $settings_link);
}
return $links;
}
/*
* Validate user input for our settings
*
* @since 1.0
* @param array $input
* @return array
*/
public function ValidateSettings($input){
extract($input);
$options = array(
'anonymous_vote' => isset($anonymous_vote) ? true : false,
'max_rating' => min(max((int)$max_rating, 1), 10),
'bayesian_formula' => wp_filter_nohtml_kses($bayesian_formula),
// only allow super admins to change this, because it's a little sensitive (part of this string is used inside the top rated db query)
'user_formula' => current_user_can('edit_plugins') ? wp_filter_nohtml_kses($user_formula) : $this->getOptions('user_formula'),
'before_post' => isset($before_post) ? true : false,
'after_post' => isset($after_post) ? true : false,
'custom_filter' => wp_filter_nohtml_kses($custom_filter),
'post_types' => isset($post_types) ? array_filter($post_types, 'post_type_exists') : array(),
'visibility' => isset($visibility) ? array_map('wp_filter_nohtml_kses', $visibility) : array(),
// internal, global stats
'avg_rating' => $this->getOptions('avg_rating'),
'num_votes' => $this->getOptions('num_votes'),
'num_rated_posts' => $this->getOptions('num_rated_posts'),
'version' => self::VERSION,
);
if(isset($remove_ratings) || ($options['max_rating'] !== $this->getOptions('max_rating'))){
$options['avg_rating'] = $options['num_votes'] = $options['num_rated_posts'] = 0;
$this->DeleteRatingRecords();
}
return $options;
}
/*
* The options page (form)
*
* @since 1.0
*/
public function SettingsPage(){
$options = $this->getOptions();
extract($options);
$generic_pages = array(
'home' => __('Home', self::ID),
'archive' => __('Archives', self::ID),
'singular' => __('Single pages', self::ID),
'search' => __('Search results', self::ID),
);
?>
<div class="wrap metabox-holder">
<h2><?php _e('Post Ratings', self::ID); ?></h2>
<form method="post" action="options.php" style="position:relative;">
<div class="postbox" style="position:absolute;right:0;top:0;">
<h3><span><?php _e('Global stats', self::ID); ?></span></h3>
<div class="inside">
<p><?php printf(__('%1$s votes (on %2$s posts)', self::ID), sprintf('<strong>%d</strong>', $num_votes), sprintf('<strong>%d</strong>', $num_rated_posts)); ?></p>
<p><?php printf(__('Average vote count per post: %s', self::ID), sprintf('<strong>%.2F</strong>', @($options['num_votes'] / $options['num_rated_posts']))); ?></p>
<p><?php printf(__('Average rating per post: %s', self::ID), sprintf('<strong>%.2F</strong>', $avg_rating)); ?></p>
</div>
</div>
<?php settings_fields(self::ID); ?>
<table class="form-table">
<tr valign="top">
<th scope="row"><?php _e('Access level', self::ID); ?></th>
<td>
<label for="anonymous_vote">
<input type="checkbox" id="anonymous_vote" name="<?php echo self::ID; ?>[anonymous_vote]" value="cookie" <?php checked($anonymous_vote); ?> />
<?php _e('Allow unregistered users to vote', self::ID); ?>
</label>
</td>
</tr>
<tr valign="top">
<th scope="row"><?php _e('Maximum rating', self::ID); ?></th>
<td>
<input type="text" size="3" name="<?php echo self::ID; ?>[max_rating]" value="<?php echo $max_rating;?>" /> <strong>[ By Default: 5 ]</strong>
<p><span class="description"><?php _e('Changing this option will reset existing post rating records', self::ID); ?></span></p>
</td>
</tr>
<tr valign="top">
<th scope="row">
<?php _e('Bayesian rating (score) formula', self::ID); ?>
</th>
<td>
<fieldset>
<p>
<label for="user_formula">
<input id="user_formula" name="<?php echo self::ID; ?>[bayesian_formula]" type="radio" value="0" checked />
<?php _e('I have my own formula:', self::ID); ?>
<input type="text" name="<?php echo self::ID; ?>[user_formula]" size="46" class="code" value="<?php if($user_formula == ''){ echo "r";} else{esc_attr_e($user_formula);} ?>" />
</label> <a href="#" onclick="jQuery('#legend').toggle();">(<?php _e('Legend', self::ID); ?>)</a>
</p>
<div id="legend" style="display:none;">
<p>
<code style="font-size: 14px;"><strong>AV</strong></code> = <?php _e('Global average number of votes per post', self::ID); ?>
<br />
<code style="font-size: 14px;"><strong> V</strong></code> = <?php _e('Global number of votes (from all posts)', self::ID); ?>
<br />
<code style="font-size: 14px;"><em> v</em></code> = <?php _e('Number of votes from the current post', self::ID); ?>
<br />
<code style="font-size: 14px;"><strong> R</strong></code> = <?php printf(__('Global average rating per post (from 1 to %d)', self::ID), $max_rating); ?>
<br />
<code style="font-size: 14px;"><em> r</em></code> = <?php printf(__('Average rating of the current post (from 1 to %d)', self::ID), $max_rating); ?>
<br />
<code style="font-size: 14px;"><strong>MV</strong></code> = <?php printf(__('Minimum vote count per post to consider (%d by default)', self::ID), self::MIN_VOTES); ?>
<br />
<code style="font-size: 14px;"><strong>MR</strong></code> = <?php printf(__('Maximum rating, see option above (currently %d)', self::ID), $max_rating); ?>
</p>
</div>
</fieldset>
</td>
</tr>
<tr valign="top">
<th scope="row"><?php _e('Allow ratings on', self::ID); ?></th>
<td>
<fieldset>
<?php foreach(get_post_types(array('public' => true)) as $type): ?>
<?php $object = get_post_type_object($type); ?>
<?php if($type=="post"){ ?> <label for="post_type_<?php echo $type; ?>">
<input type="checkbox" value="<?php echo $type; ?>" id="post_type_<?php echo $type; ?>" name="<?php echo self::ID; ?>[post_types][]" <?php checked(in_array($type, $post_types)); ?> /> <?php echo $object->labels->name; ?> </label> <?php } ?>
<?php endforeach; ?>
</fieldset>
</td>
</tr>
<tr valign="top">
<th scope="row"><?php _e('Locations of the rate links', self::ID); ?></th>
<td>
<fieldset>
<label for="location_before_post">
<input id="location_before_post" name="<?php echo self::ID; ?>[before_post]" type="checkbox" <?php checked($before_post); ?> />
<?php _e('Before post content', self::ID); ?>
</label>
</td>
</tr>
<tr valign="top">
<th scope="row"><?php _e('Page visibility', self::ID); ?></th>
<td>
<fieldset>
<?php foreach($generic_pages as $page => $label): ?> <?php if($page == "singular") { ?> <label for="visibility_<?php echo $page; ?>">
<input type="checkbox" value="<?php echo $page; ?>" id="visibility_<?php echo $page; ?>" name="<?php echo self::ID; ?>[visibility][]" <?php checked(in_array($page, $visibility)); ?> />
<?php echo $label; ?> </label> <?php } ?>
<?php endforeach; ?>
</fieldset>
</td>
</tr>
<tr><td colspan="2"> </td></tr>
<tr valign="top">
<th scope="row" colspan="2">
<input type="submit" class="button-primary" value="<?php _e('Save Changes', self::ID); ?>" />
<label for="remove_all">
<input id="remove_all" type="checkbox" value="1" name="<?php echo self::ID; ?>[remove_ratings]" />
<?php _e('Delete rating records from all posts', self::ID); ?>
</label>
</th>
</tr>
</table>
</form>
</div>
<?php
}
/*
* Javascript and CSS used by the plugin
*
* @since 1.0
*/
public function assets(){
// js
wp_enqueue_script('jquery');
wp_enqueue_script(self::ID, plugins_url('post-ratings.js', __FILE__), array('jquery'), self::VERSION, true);
// note that Atom-based themes alread have this variable "localized"
if(!class_exists('Atom') || (class_exists('Atom') && (!defined('Atom::VERSION'))))
wp_localize_script(self::ID, 'post_ratings', array('blog_url' => home_url('/')));
// allow themes to override css
$style = is_readable(get_stylesheet_directory().'/post-ratings.css') ? get_stylesheet_directory_uri().'/post-ratings.css' : plugins_url('post-ratings.css', __FILE__);
wp_enqueue_style(self::ID, $style);
}
/*
* Remove plugin options and rating stats on uninstall
*
* @since 1.0
*/
public static function Uninstall(){
PostRatings()->DeleteRatingRecords();
delete_option(self::ID);
}
/*
* Get user rating for a post
*
* @since 1.0
* @param int $post_id Post ID
* @return array Rating, vote count and bayesian rating
*/
public function getRating($post_id){
$options = $this->getOptions();
extract($options);
$rating = (float)get_post_meta($post_id, 'rating', true);
$votes = (int)get_post_meta($post_id, 'votes', true);
$bayesian_rating = 0;
if($votes != 0){
$avg_num_votes = ($num_rated_posts != 0) ? ($num_votes / $num_rated_posts) : 0;
$identifiers = array(
'AV' => $avg_num_votes,
'MV' => self::MIN_VOTES,
'MR' => $max_rating,
'V' => $num_votes,
'v' => $votes,
'R' => $avg_rating,
'r' => $rating,
);
if(!$bayesian_formula)
$bayesian_formula = $user_formula;
if(!$bayesian_formula)
$bayesian_formula = 'r';
$bayesian_formula = strtr($bayesian_formula, $identifiers);
// safe eval - only super admins can set their own formula
$bayesian_rating = (float)@eval("return ({$bayesian_formula});");
$bayesian_rating = 100 * ($bayesian_rating / $max_rating);
}
return compact('rating', 'votes', 'bayesian_rating');
}
/*
* Adjust user meta key name, or cookie key name for multisite blogs (except primary blog)
*
* @since 2.0
* @param string
* @return string
*/
private function getRecordsKey($key){
if(is_multisite() && !is_main_site())
$key .= '_'.get_current_blog_id();
return $key;
}
/*
* Attempt to get the visitor's IP address
*
* @since 2.3
* @return string
*/
private function getIP(){
if(isset($_SERVER['HTTP_CLIENT_IP']))
return $_SERVER['HTTP_CLIENT_IP'];
if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
return $_SERVER['HTTP_X_FORWARDED_FOR'];
if(isset($_SERVER['HTTP_X_FORWARDED']))
return $_SERVER['HTTP_X_FORWARDED'];
if(isset($_SERVER['HTTP_FORWARDED_FOR']))
return $_SERVER['HTTP_FORWARDED_FOR'];
if(isset($_SERVER['HTTP_FORWARDED']))
return $_SERVER['HTTP_FORWARDED'];
return $_SERVER['REMOTE_ADDR'];
}
/*
* Process rating, or set up plugin hooks if this is not a rate request
*
* @since 1.0
*/
public function Run(){
$options = $this->getOptions();
extract($options);
if(!isset($_GET['rate'])){
if($custom_filter)
add_filter($custom_filter, array($this, 'ControlBlockHook'));
if($before_post || $after_post){
// post content
add_filter('the_content', array($this, 'ControlBlockHook'), 20);
// bbpress
add_filter('bbp_get_topic_content', array($this, 'ControlBlockHook'));
add_filter('bbp_get_reply_content', array($this, 'ControlBlockHook'));
}
add_action('wp_enqueue_scripts', array($this, 'assets'));
// this is our $.ajax request
}else{
defined('DOING_AJAX') or define('DOING_AJAX', true);
$post_id = (int)$_GET['post_id'];
$voted = min(max((int)$_GET['rate'], 1), $max_rating);
$error = '';
$post = &get_post($post_id);
$rating = 0;
$votes = 0;
if(!$post){
$error = __("Invalid vote! Cheatin' uh?", self::ID);
}else{
// get current post rating and vote count
extract($this->getRating($post->ID));
// vote seems valid, register it
if($this->currentUserCanRate($post_id)){
// increase global post rate count if this is the first vote
if($votes < 1)
$options['num_rated_posts']++;
// global vote count
$options['num_votes']++;
// update post rating and vote count
$votes++;
$rating = (($rating * ($votes - 1)) + $voted) / $votes;
update_post_meta($post->ID, 'rating', $rating);
update_post_meta($post->ID, 'votes', $votes);
// update global stats
$options['avg_rating'] = ($options['num_votes'] > 0) ? ((($options['avg_rating'] * ($options['num_votes'] - 1)) + $voted) / $options['num_votes']) : 0;
update_option(self::ID, $options);
$ip_cache = get_transient('post_ratings_ip_cache');
if(!$ip_cache)
$ip_cache = array();
$posts_rated = isset($_COOKIE[$this->getRecordsKey('posts_rated')]) ? explode('-', $_COOKIE[$this->getRecordsKey('posts_rated')]) : array();
$posts_rated = array_map('intval', array_filter($posts_rated));
// add user's IP to the cache
$ip_cache[$post_id][] = $this->getIP();
// keep it light, only 10 records per post and maximum 10 post records (=> max. 100 ip entries)
// also, the data gets deleted after 2 weeks if there's no activity during this time...
if(count($ip_cache[$post_id]) > 10)
array_shift($ip_cache[$post_id]);
if(count($ip_cache) > 10)
array_shift($ip_cache);
set_transient('post_ratings_ip_cache', $ip_cache, 60 * 60 * 24 * 14);
// update user meta
if(is_user_logged_in()){
$user = wp_get_current_user();
$current_user_ratings = get_user_meta($user->ID, $this->getRecordsKey('posts_rated'), true);
if(!$current_user_ratings)
$current_user_ratings = array();
$posts_rated = array_unique(array_merge($posts_rated, array_filter($current_user_ratings)));
update_user_meta($user->ID, $this->getRecordsKey('posts_rated'), $posts_rated);
}
// update cookie
$posts_rated = array_slice($posts_rated, -20); // keep it under 20 entries
$posts_rated[] = $post_id;
setcookie($this->getRecordsKey('posts_rated'), implode('-', $posts_rated), time() + 60 * 60 * 24 * 90, '/'); // expires in 90 days
$this->rated_posts[] = $post_id;
do_action('rated_post', $post_id);
$this->clearQueryCache();
}else{
$error = __('You cannot rate this post!', self::ID);
}
}
// send updated info
echo json_encode(array(
'error' => $error,
'rating' => sprintf('%.2F', $rating),
'max_rating' => $max_rating,
'votes' => $votes,
'html' => $this->getControl($post_id, true),
));
exit;
}
}
/*
* Delete all ratings-related meta data from the database
*
* @since 1.0
*/
public function DeleteRatingRecords(){
// clear cache, just in case we have a persistent cache plugin active
wp_cache_flush();
delete_transient('post_ratings_ip_cache');
// remove all our meta entries
delete_metadata('post', 0, 'rating', '', $delete_all = true);
delete_metadata('post', 0, 'votes', '', $delete_all = true);
delete_metadata('user', 0, $this->getRecordsKey('posts_rated'), '', $delete_all = true);
// delete the current user's cookie too; this is probably useless because it only handles the current user;
// we should store a unique ID on both the server and client computer
// and if this ID doesn't match with the one on the user's computer then expire his cookie
if(isset($_COOKIE[$this->getRecordsKey('posts_rated')]))
setcookie($this->getRecordsKey('posts_rated'), null, -1, '/');
}
/*
* Hook for the content
*
* @since 1.8
* @param string $content
* @return string
*/
public function ControlBlockHook($content = ''){
global $post, $wp_current_filter;
$control = $this->getControl();
if($control){
$options = $this->getOptions();
extract($options);
// no post ID?
// this is most likely the user's action tag, fired in the wrong place...
if(empty($post->ID)){
printf(__("Your '%s' action is must run in a post's context!", self::ID), $custom_filter);
return $content;
}
// check if this is the right post type
if(!in_array(get_post_type($post->ID), $post_types))
return $content;
// we don't want to insert our html in excerpts...
// see here why: http://digitalnature.eu/blog/2011/09/12/how-to-correctly-hook-your-filter-to-the-post-content
if(array_intersect(array('get_the_excerpt', 'the_excerpt'), $wp_current_filter))
return $content;
$continue = false;
// this is the user's custom action, so directly output the HTML
if(in_array($custom_filter, $wp_current_filter)){
echo $control;
// the_content
}elseif(array_intersect(array('the_content', 'bbp_get_reply_content'), $wp_current_filter)){
// we don't want to mess with custom loops
if(in_the_loop()){
if($before_post)
$content = $control.$content;
if($after_post)
$content = $content.$control;
}
}
}
return $content;
}
/*
* The rate links
*
* @since 1.0
* @param int $post_id
* @param bool $ignore_visibility_setting
* @return string
*/
public function getControl($post_id = '', $ignore_visibility_setting = false){
global $post;
$control = array();
$options = $this->getOptions();
$post_id = $post_id ? $post_id : $post->ID;
extract($options);
// check if this is the right post type
if(!in_array(get_post_type($post_id), $post_types))
return false;
if(empty($post_id))
throw new Exception('Need a post ID...');
$continue = false;
if(!$ignore_visibility_setting){
// page visibility check
foreach($visibility as $page)
if(call_user_func("is_{$page}"))
$continue = true;
// cpt archive check
if(in_array('archive', $visibility) && is_post_type_archive($post_types))
$continue = true;
$continue = apply_filters('post_ratings_visibility', $continue);
}
if($continue || $ignore_visibility_setting){
// get current post rating
extract($this->getRating($post_id));
$post = get_post($post_id);
setup_postdata($post);
$loaded = $this->loadTemplate('post-ratings-control', compact('rating', 'votes', 'bayesian_rating', 'max_rating'));
wp_reset_postdata();
return $loaded;
}
return false;
}
/*
* Checks if the current user can rate a post.
*
* @since 1.0
* @param int $post_id Optional, post ID to check (if not given, the global $post is used)
* @return bool
*/
public function currentUserCanRate($post_id = false){
global $post;
$post_id = $post_id ? $post_id : $post->ID;
$can_rate = false;
if(in_array($post_id, $this->rated_posts))
return false;
// check if ratings are enabled for this post type
if(in_array(get_post_type($post_id), $this->getOptions('post_types')))
// check if the user is logged in; if not, only continue if anonymouse voting is allowed
if($this->getOptions('anonymous_vote') || is_user_logged_in()){
// last 100 IPs
$ip_cache = get_transient('post_ratings_ip_cache');
// client cookie
$posts_rated = isset($_COOKIE[$this->getRecordsKey('posts_rated')]) ? explode('-', $_COOKIE[$this->getRecordsKey('posts_rated')]) : array();
// also get user meta rating records if user is logged in
if(is_user_logged_in()){
$user = wp_get_current_user();
$posts_rated = array_merge($posts_rated, (array)get_user_meta($user->ID, $this->getRecordsKey('posts_rated'), true));
}
$can_rate = !((isset($ip_cache[$post_id]) && in_array($this->getIP(), $ip_cache[$post_id])) || in_array($post_id, $posts_rated));
}
return apply_filters('post_ratings_access_check', $can_rate, $post_id);
}
/*
* Get a list of most rated posts.
* The results are returned as an array of objects
*
* @since 1.0
* @param array $args Arguments, see below
* @return array
*/
public function getTopRated($args){
global $wpdb;
$args = wp_parse_args($args, array(
'post_type' => 'post',
'number' => 10,
'offset' => 0,
'sortby' => 'bayesian_rating', // bayesian_rating, rating or votes
'order' => 'DESC', // ASC or DESC (no reason to use ASC...)
'date_limit' => 0, // date limit in days
'where' => '',
'bayesian_formula' => $this->getOptions('bayesian_formula'),
));
$options = $this->getOptions();
extract($options);
extract($args);
// averge votes per post
$avg_num_votes = ($num_rated_posts != 0) ? ($num_votes / $num_rated_posts) : 0;
$where = $date_limit ? "AND post_date > '".date('Y-m-d', strtotime(sprintf('-%d days', $date_limit)))."'" : $where;
if(empty($bayesian_formula))
$bayesian_formula = $user_formula;
if(!$bayesian_formula)
$bayesian_formula = 'r';
$identifiers = array(
'AV' => $avg_num_votes,
'MV' => self::MIN_VOTES,
'MR' => $max_rating,
'V' => $num_votes,
'v' => 'votes',
'R' => $avg_rating,
'r' => 'rating',
);
$bayesian_formula = strtr($bayesian_formula, $identifiers);
// many thanks for this SQL query to Utku Yıldırım :)
// http://stackoverflow.com/questions/8214902/order-database-results-by-bayesian-rating/8215068#8215068
$query = "
SELECT *, {$bayesian_formula} AS bayesian_rating
FROM {$wpdb->posts}
LEFT JOIN(
SELECT DISTINCT post_id,
(SELECT CAST(meta_value AS DECIMAL(10)) FROM {$wpdb->postmeta} WHERE {$wpdb->postmeta}.post_id = meta.post_id AND meta_key ='votes') AS votes,
(SELECT CAST(meta_value AS DECIMAL(10,2)) FROM {$wpdb->postmeta} WHERE {$wpdb->postmeta}.post_id = meta.post_id AND meta_key ='rating') AS rating
FROM {$wpdb->postmeta} meta )
AS newmeta ON {$wpdb->posts}.ID = newmeta.post_id
WHERE post_status = 'publish' AND post_type = '{$post_type}' {$where}
GROUP BY ID
ORDER BY {$sortby} {$order}
LIMIT {$offset}, {$number}
";
// check cache first
$key = md5($query);
$cache = wp_cache_get('get_top_rated', self::ID);
if(isset($cache[$key])){
$results = $cache[$key];
// no cache, do the db query...
}else{
$results = $wpdb->get_results($query);
$cache[$key] = $results;
wp_cache_set('get_top_rated', $cache, self::ID);
}
return $results;
}
/*
* Flushes cached queries.
*
* @since 1.9
*/
public function clearQueryCache(){
wp_cache_delete('get_top_rated');
}
/*
* The [rate] shortcode
*
* @since 1.0
* @params array $atts Can accept the post ID as argument; if not given, control() will use the $post global
* @return string
*/
public function Shortcode($atts){
$post_id = '';
// check if a post ID was given as first argument
if(isset($atts[0]) && is_numeric($atts[0]))
$post_id = (int)$atts[0];
// no, maybe it's the 2nd argument
elseif(isset($atts[1]) && is_numeric($atts[1]))
$post_id = (int)$atts[1];
// check if a "force" attribute is present
$force = array_search('force', (array)$atts) !== false;
return $this->getControl($post_id, $force);
}
/*
* Register the "Top Rated" widget
*
* @since 1.0
*/
public function Widget(){
require dirname(__FILE__).'/widget.php';
register_widget('PostRatingsWidget');
}
}
// a shortcut to our application
function PostRatings(){
static $app;
// first call to app() initializes the plugin
if(!($app instanceof PostRatings))
$app = PostRatings::app();
return $app;
}
PostRatings();
// @todo
add_filter('user_has_cap', 'post_ratings_has_cap', 10, 3);
add_filter('map_meta_cap', 'post_ratings_map_cap_for_sa', 10, 4);
function post_ratings_map_cap_for_sa($caps, $req_cap, $user_id, $args){
// $args[0] is the post ID
if(($req_cap === 'rate') && is_multisite() && is_super_admin($user_id) && isset($args[0]) && !PostRatings()->currentUserCanRate($args[0]))
$caps[] = 'do_not_allow';
return $caps;
}
function post_ratings_has_cap($allcaps, $caps, $args){
// $args[2] is the post ID
if($args[0] !== 'rate' && !isset($args[2]) || !PostRatings()->currentUserCanRate($args[2]))
return $allcaps;
$allcaps['rate'] = 1;
return $allcaps;
}